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
@@ -0,0 +1,20 @@
{"type":"transcript_start","provider":"cursor","protocol":"cursor-agent-sdk.local","version":"1","scenario":"command_output_streaming","metadata":{"generatedBy":"hand-authored","nativeAgentId":"agent-command-output-streaming"}}
{"type":"expect_outbound","label":"agent.open","frame":{"type":"agent.open","operation":"create","options":{"model":{"id":"composer-2.5"},"hasName":true,"mode":"agent","local":{"hasCwd":true,"autoReview":false,"settingSources":["project","user","team","mdm","plugins"],"sandboxEnabled":false,"enableAgentRetries":true}}}}
{"type":"emit_inbound","label":"agent.opened","frame":{"type":"agent.opened","agentId":"agent-command-output-streaming"}}
{"type":"expect_outbound","label":"run.start:1","frame":{"type":"run.start","message":"Run this exact shell command in the foreground and wait for it to finish: `for i in 1 2 3 4; do printf '\\033[32mstream line %s\\033[0m\\n' $i; sleep 1; done; printf 'progress 50%%\\rprogress 100%%\\n'`. Then respond exactly: command output fixture complete","options":{"model":{"id":"composer-2.5"},"mode":"agent"}}}
{"type":"emit_inbound","label":"run.started:1","frame":{"type":"run.started","runId":"run-command-output-streaming","agentId":"agent-command-output-streaming"}}
{"type":"emit_inbound","label":"thinking-delta","frame":{"type":"interaction.update","runId":"run-command-output-streaming","update":{"type":"thinking-delta","text":"Running the exact command and streaming its output."}}}
{"type":"emit_inbound","label":"thinking-completed","frame":{"type":"interaction.update","runId":"run-command-output-streaming","update":{"type":"thinking-completed","thinkingDurationMs":4}}}
{"type":"emit_inbound","label":"tool-call-started","frame":{"type":"interaction.update","runId":"run-command-output-streaming","update":{"type":"tool-call-started","callId":"tool-command-output-streaming","toolCall":{"type":"shell","args":{"command":"for i in 1 2 3 4; do printf '\\033[32mstream line %s\\033[0m\\n' $i; sleep 1; done; printf 'progress 50%%\\rprogress 100%%\\n'","timeout":45000}},"modelCallId":"d91507e1-e342-4c22-bb83-9037901fed21-0-6vz9"}}}
{"type":"emit_inbound","label":"shell-stdout-1","frame":{"type":"interaction.update","runId":"run-command-output-streaming","update":{"type":"shell-output-delta","event":{"case":"stdout","value":{"data":"\u001b[32mstream line 1\u001b[0m\n"}}}}}
{"type":"emit_inbound","label":"shell-stdout-2","frame":{"type":"interaction.update","runId":"run-command-output-streaming","update":{"type":"shell-output-delta","event":{"case":"stdout","value":{"data":"\u001b[32mstream line 2\u001b[0m\n"}}}}}
{"type":"emit_inbound","label":"shell-stdout-3","frame":{"type":"interaction.update","runId":"run-command-output-streaming","update":{"type":"shell-output-delta","event":{"case":"stdout","value":{"data":"\u001b[32mstream line 3\u001b[0m\n"}}}}}
{"type":"emit_inbound","label":"shell-stdout-4","frame":{"type":"interaction.update","runId":"run-command-output-streaming","update":{"type":"shell-output-delta","event":{"case":"stdout","value":{"data":"\u001b[32mstream line 4\u001b[0m\n"}}}}}
{"type":"emit_inbound","label":"shell-stdout-progress","frame":{"type":"interaction.update","runId":"run-command-output-streaming","update":{"type":"shell-output-delta","event":{"case":"stdout","value":{"data":"progress 50%\rprogress 100%\n"}}}}}
{"type":"emit_inbound","label":"shell-exit","frame":{"type":"interaction.update","runId":"run-command-output-streaming","update":{"type":"shell-output-delta","event":{"case":"exit","value":{"code":0,"aborted":false}}}}}
{"type":"emit_inbound","label":"tool-call-completed","frame":{"type":"interaction.update","runId":"run-command-output-streaming","update":{"type":"tool-call-completed","callId":"tool-command-output-streaming","toolCall":{"type":"shell","args":{"command":"for i in 1 2 3 4; do printf '\\033[32mstream line %s\\033[0m\\n' $i; sleep 1; done; printf 'progress 50%%\\rprogress 100%%\\n'","timeout":45000},"result":{"status":"success","value":{"exitCode":0,"signal":"","stdout":"\u001b[32mstream line 1\u001b[0m\n\u001b[32mstream line 2\u001b[0m\n\u001b[32mstream line 3\u001b[0m\n\u001b[32mstream line 4\u001b[0m\nprogress 100%\n","stderr":"","executionTime":4100}}},"modelCallId":"d91507e1-e342-4c22-bb83-9037901fed21-0-6vz9"}}}
{"type":"emit_inbound","label":"text-delta","frame":{"type":"interaction.update","runId":"run-command-output-streaming","update":{"type":"text-delta","text":"command output fixture complete"}}}
{"type":"emit_inbound","label":"step-completed","frame":{"type":"interaction.update","runId":"run-command-output-streaming","update":{"type":"step-completed","stepId":2,"stepDurationMs":4100}}}
{"type":"emit_inbound","label":"turn-ended","frame":{"type":"interaction.update","runId":"run-command-output-streaming","update":{"type":"turn-ended","usage":{"inputTokens":11614,"outputTokens":43,"cacheReadTokens":6336,"cacheWriteTokens":0}}}}
{"type":"emit_inbound","label":"run.completed:1","frame":{"type":"run.completed","result":{"id":"run-command-output-streaming","requestId":"3040efb6-d2b3-4c8c-89b9-56ed144d32e6","status":"finished","result":"command output fixture complete","model":{"id":"composer-2.5"},"durationMs":4200,"usage":{"inputTokens":11614,"outputTokens":43,"cacheReadTokens":6336,"cacheWriteTokens":0,"totalTokens":17993}}}}
{"type":"expect_outbound","label":"agent.close","frame":{"type":"agent.close","agentId":"agent-command-output-streaming"}}
9 changes: 9 additions & 0 deletions apps/server/src/orchestration-v2/testkit/fixtures/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1920,6 +1920,15 @@ export const ORCHESTRATOR_REPLAY_FIXTURES: ReadonlyArray<OrchestratorReplayFixtu
modelSelection: CLAUDE_MODEL_SELECTION,
assertOutput: assertCommandOutputStreamingOutput,
},
{
driver: ProviderDriverKind.make("cursor"),
transcriptFile: new URL(
"./command_output_streaming/cursor_transcript.ndjson",
import.meta.url,
),
modelSelection: CURSOR_MODEL_SELECTION,
assertOutput: assertCommandOutputStreamingOutput,
},
],
},
{
Expand Down
19 changes: 10 additions & 9 deletions packages/provider-cursor/src/server/adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1990,16 +1990,17 @@ export const makeCursorAdapterV2 = Effect.fn("makeCursorAdapterV2")(function* (
}
});

// `shell-output-delta` wraps a protobuf oneof as `{ case, value }`. Only stdout and
// stderr carry text; `exit` carries the exit status.
const shellOutputText = (event: Record<string, unknown>): string => {
const candidates = [
event.text,
event.output,
event.data,
event.stdout,
event.stderr,
event.chunk,
];
return candidates.filter((value): value is string => typeof value === "string").join("");
const kind = event.case;
if (kind !== "stdout" && kind !== "stderr") {
return "";
}
const value = event.value;
const data =
typeof value === "object" && value !== null ? Reflect.get(value, "data") : undefined;
return typeof data === "string" ? data : "";
};

const handleInteractionUpdate = Effect.fnUntraced(function* (
Expand Down
Loading