Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ export function createV2StreamingCoordinator(config: V2StreamingConfig): V2Strea
});
},

onSessionStatusChanged: status => {
onSessionStatusChanged: (status, _sessionId) => {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WARNING: Idle status from child sessions can prematurely end root streaming

This callback now receives sessionId but ignores it. If a subagent/child session emits status.type === 'idle', this will set isStreaming to false and call onStreamComplete for the parent flow too early. Consider gating completion to the active/root session ID, similar to the safeguard added in run-session.ts.

if (status.type === 'idle') {
store.setState({ isStreaming: false });
onStreamComplete?.();
Expand Down
2 changes: 1 addition & 1 deletion src/components/cloud-agent-next/useCloudAgentStream.ts
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ export function useCloudAgentStream({
}
},

onSessionStatusChanged: status => {
onSessionStatusChanged: (status, _sessionId) => {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WARNING: Stream completion can be triggered by non-root session idle events

onSessionStatusChanged now provides sessionId, but this handler still marks streaming complete on any idle. In multi-session/subagent execution, an idle child session can incorrectly flip root UI state and fire onComplete early. Consider checking the event sessionId against the active/root session before completing.

setSessionStatus(status);

// Handle streaming state based on status
Expand Down
4 changes: 2 additions & 2 deletions src/lib/cloud-agent-next/processor/event-processor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -309,9 +309,9 @@ export function createEventProcessor(config: EventProcessorConfig = {}): EventPr
* Handle session.status events.
*/
function handleSessionStatus(data: EventSessionStatus['properties']): void {
const { status } = data;
const { status, sessionID } = data;

callbacks.onSessionStatusChanged?.(status);
callbacks.onSessionStatusChanged?.(status, sessionID);

// Update streaming state based on status
if (status.type === 'idle') {
Expand Down
2 changes: 1 addition & 1 deletion src/lib/cloud-agent-next/processor/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ export type EventProcessorCallbacks = {
) => void;

/** Called when session status changes (idle/busy/retry) */
onSessionStatusChanged?: (status: SessionStatus) => void;
onSessionStatusChanged?: (status: SessionStatus, sessionId: string) => void;

/** Called when a new session is created (session.created event) */
onSessionCreated?: (sessionInfo: Session) => void;
Expand Down
5 changes: 3 additions & 2 deletions src/lib/cloud-agent-next/run-session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -242,8 +242,9 @@ export async function runSessionToCompletion(input: RunSessionInput): Promise<Ru
errorMessage = errData?.data?.message ?? 'Assistant message failed.';
}
},
onSessionStatusChanged: status => {
if (status.type === 'idle') resolveOnce();
onSessionStatusChanged: (status, eventSessionId) => {
// Only resolve when the root session goes idle, not subagent/child sessions.
if (status.type === 'idle' && eventSessionId === sessionId) resolveOnce();
},
onError: error => {
hasError = true;
Expand Down
Loading