Fix job continuation: setMessages never fires sendAutomaticallyWhen
Gate 1 found the teacher staying silent after a research brief landed. The SDK only evaluates sendAutomaticallyWhen inside addToolOutput — an external setMessages (our syncFromServer) updates the UI but never triggers the continuation. Fix: syncFromServer checks lastAssistantMessageIsCompleteWithToolCalls and calls sendMessage() (itself a valid continuation trigger); plus a mount-continuation effect for the reload case (job fulfilled while no client was open).
This commit is contained in:
+32
-2
@@ -81,6 +81,25 @@ export function Chat({
|
||||
}
|
||||
}, [initialPrompt, initialMessages.length, sendMessage]);
|
||||
|
||||
// Mount continuation: if the stored transcript ends with a fulfilled tool
|
||||
// (a job result landed while no client was open), resume the lesson — the
|
||||
// SDK's sendAutomaticallyWhen only fires inside addToolOutput, so reloads
|
||||
// need this nudge. Once per mount; the turn that follows ends in text (or
|
||||
// a pending question), so no loop.
|
||||
const mountContinuation = useRef(false);
|
||||
useEffect(() => {
|
||||
if (mountContinuation.current) return;
|
||||
mountContinuation.current = true;
|
||||
if (
|
||||
status === "ready" &&
|
||||
messages.length > 0 &&
|
||||
lastAssistantMessageIsCompleteWithToolCalls({ messages })
|
||||
) {
|
||||
void sendMessage();
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps -- mount-only by design
|
||||
}, []);
|
||||
|
||||
const pending = findPendingToolCall(messages);
|
||||
const busy = status === "submitted" || status === "streaming";
|
||||
|
||||
@@ -102,8 +121,19 @@ export function Chat({
|
||||
const res = await fetch(`/api/chats/${chatId}`);
|
||||
if (!res.ok) return;
|
||||
const record = (await res.json()) as { messages?: TeacherUIMessage[] };
|
||||
if (Array.isArray(record.messages)) setMessages(record.messages);
|
||||
}, [chatId, setMessages]);
|
||||
if (!Array.isArray(record.messages)) return;
|
||||
setMessages(record.messages);
|
||||
// setMessages does NOT fire sendAutomaticallyWhen (the SDK only checks
|
||||
// it inside addToolOutput) — without this the teacher would stay silent
|
||||
// after a job result lands. sendMessage() with no args re-requests with
|
||||
// the current list: the continuation. (contracts.ts protocol §4.)
|
||||
if (
|
||||
status === "ready" &&
|
||||
lastAssistantMessageIsCompleteWithToolCalls({ messages: record.messages })
|
||||
) {
|
||||
void sendMessage();
|
||||
}
|
||||
}, [chatId, setMessages, sendMessage, status]);
|
||||
|
||||
const onSend = () => {
|
||||
const t = text.trim();
|
||||
|
||||
Reference in New Issue
Block a user