Skip to content

Commit aa0a1fe

Browse files
committed
feat(cli): follow a run, wait for one, and tail the log
Three commands the surface was missing, each polling or streaming something the generated command layer cannot express. `workflows run --follow` renders the SSE the execute route already emits, so a multi-minute agent run stops printing nothing until it ends. It rides on the generated `run` leaf rather than a sibling command — same operation, one different response encoding — and delegates to the handler it replaced, so every non-follow invocation still runs the generated path. Answer text, thinking and tool calls go to stderr; only the final envelope reaches stdout, so redirecting still yields the result. Reasoning and tool frames need the `X-Sim-Stream-Protocol` header, which is sent only when asked for, because negotiating also switches answer text to live chunks the server may retract. `workflows runs wait` closes the loop `--async` opens. Terminal is completed, failed or cancelled; `redacting` is not, since a run whose output is still being scrubbed is not yet a run you can read. A time pause keeps polling because the server resumes it, and a human pause stops with the resume command rather than burning the bound and calling it a timeout. Distinct exit codes keep cancelled and paused from reading as failure. The bound is `--wait-timeout` and not `--timeout`, because SIM_TIMEOUT_SECONDS already bounds one request and two knobs of the same name hide each other. `logs follow` tails runs as they arrive. Dedup keys on run id, not on the timestamp: a schedule fan-out starts many runs in the same millisecond, so a timestamp watermark either drops the siblings or reprints them. JSON output is one object per line, because a follow never closes an array, and the table header is printed once so columns stay aligned across polls.
1 parent c86c084 commit aa0a1fe

11 files changed

Lines changed: 2278 additions & 5 deletions

File tree

apps/docs/content/docs/en/cli/logs.mdx

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,3 +66,25 @@ sim logs list [options]
6666
| `--folder <value...>` | No | Folder path as shown in the app; the leading / is optional (space-separated, or @path / @- with one value per line). |
6767

6868
</CommandTable>
69+
70+
## Watch runs as they arrive, printing each new run once
71+
72+
```bash
73+
sim logs follow [options]
74+
```
75+
76+
**Options**
77+
78+
<CommandTable>
79+
80+
| Option | Required | Description |
81+
| --- | --- | --- |
82+
| `--workflow <id>` | No | Only follow runs of this workflow (repeatable). Defaults to ``. |
83+
| `--folder <path>` | No | Only follow runs of workflows in this folder (repeatable). Defaults to ``. |
84+
| `--trigger <type>` | No | Only follow runs with this trigger type (repeatable). Defaults to ``. |
85+
| `--level <level>` | No | Only follow runs at this severity. Accepted values: `info`, `error`. |
86+
| `--details <level>` | No | Response detail level; full names each run’s workflow. Accepted values: `basic`, `full`. Defaults to `full`. |
87+
| `-n, --lines <count>` | No | Recent runs to print before watching. Defaults to `10`. |
88+
| `--interval <seconds>` | No | Seconds between polls. Defaults to `3`. |
89+
90+
</CommandTable>

apps/docs/content/docs/en/cli/reference.mdx

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1538,6 +1538,30 @@ sim logs list [options]
15381538

15391539
</CommandTable>
15401540

1541+
### sim logs follow
1542+
1543+
Watch runs as they arrive, printing each new run once
1544+
1545+
```bash
1546+
sim logs follow [options]
1547+
```
1548+
1549+
**Options**
1550+
1551+
<CommandTable>
1552+
1553+
| Option | Required | Description |
1554+
| --- | --- | --- |
1555+
| `--workflow <id>` | No | Only follow runs of this workflow (repeatable). Defaults to ``. |
1556+
| `--folder <path>` | No | Only follow runs of workflows in this folder (repeatable). Defaults to ``. |
1557+
| `--trigger <type>` | No | Only follow runs with this trigger type (repeatable). Defaults to ``. |
1558+
| `--level <level>` | No | Only follow runs at this severity. Accepted values: `info`, `error`. |
1559+
| `--details <level>` | No | Response detail level; full names each run’s workflow. Accepted values: `basic`, `full`. Defaults to `full`. |
1560+
| `-n, --lines <count>` | No | Recent runs to print before watching. Defaults to `10`. |
1561+
| `--interval <seconds>` | No | Seconds between polls. Defaults to `3`. |
1562+
1563+
</CommandTable>
1564+
15411565
## sim mcp-servers
15421566

15431567
Also spelled `sim mcp-server`.
@@ -3190,6 +3214,35 @@ sim workflows runs resume <runId> [options]
31903214

31913215
</CommandTable>
31923216

3217+
### sim workflows runs wait
3218+
3219+
Wait for a run to reach a terminal state, then show it
3220+
3221+
```bash
3222+
sim workflows runs wait <runId> [options]
3223+
```
3224+
3225+
**Arguments**
3226+
3227+
<CommandTable>
3228+
3229+
| Argument | Required | Description |
3230+
| --- | --- | --- |
3231+
| `runId` | Yes | Unique workflow run identifier. |
3232+
3233+
</CommandTable>
3234+
3235+
**Options**
3236+
3237+
<CommandTable>
3238+
3239+
| Option | Required | Description |
3240+
| --- | --- | --- |
3241+
| `--workflow <workflowId>` | Yes | Workflow ID. |
3242+
| `--wait-timeout <seconds>` | No | Give up after this many seconds, or 0 to wait indefinitely (default: 3600). Bounds the whole wait; SIM_TIMEOUT_SECONDS bounds one request. |
3243+
3244+
</CommandTable>
3245+
31933246
### sim workflows create
31943247

31953248
Create Workflow
@@ -3389,6 +3442,9 @@ sim workflows run <id> [options]
33893442
| `--include-file-base64` | No | Inline eligible output files as base64 content. Rejected when `async` is true. |
33903443
| `--no-include-file-base64` | No | Send --include-file-base64 as false. |
33913444
| `--base64-max-bytes <value>` | No | Maximum total bytes of file content to inline as base64. Rejected when `async` is true. |
3445+
| `--follow` | No | Stream the run as it happens; progress on stderr, result on stdout. The stream reports only success and output, so the result omits the run id and timings a non-streaming run returns. |
3446+
| `--include-thinking` | No | Show model reasoning while following (requires --follow). |
3447+
| `--include-tool-calls` | No | Show tool calls while following (requires --follow). |
33923448

33933449
</CommandTable>
33943450

apps/docs/content/docs/en/cli/workflows.mdx

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,33 @@ Resume a paused run (output is included in JSON or YAML output)
117117

118118
</CommandTable>
119119

120+
## Wait for a run to reach a terminal state, then show it
121+
122+
```bash
123+
sim workflows runs wait <runId> [options]
124+
```
125+
126+
**Arguments**
127+
128+
<CommandTable>
129+
130+
| Argument | Required | Description |
131+
| --- | --- | --- |
132+
| `runId` | Yes | Unique workflow run identifier. |
133+
134+
</CommandTable>
135+
136+
**Options**
137+
138+
<CommandTable>
139+
140+
| Option | Required | Description |
141+
| --- | --- | --- |
142+
| `--workflow <workflowId>` | Yes | Workflow ID. |
143+
| `--wait-timeout <seconds>` | No | Give up after this many seconds, or 0 to wait indefinitely (default: 3600). Bounds the whole wait; SIM_TIMEOUT_SECONDS bounds one request. |
144+
145+
</CommandTable>
146+
120147
## Create workflow
121148

122149
```bash
@@ -300,6 +327,9 @@ sim workflows run <id> [options]
300327
| `--include-file-base64` | No | Inline eligible output files as base64 content. Rejected when `async` is true. |
301328
| `--no-include-file-base64` | No | Send --include-file-base64 as false. |
302329
| `--base64-max-bytes <value>` | No | Maximum total bytes of file content to inline as base64. Rejected when `async` is true. |
330+
| `--follow` | No | Stream the run as it happens; progress on stderr, result on stdout. The stream reports only success and output, so the result omits the run id and timings a non-streaming run returns. |
331+
| `--include-thinking` | No | Show model reasoning while following (requires --follow). |
332+
| `--include-tool-calls` | No | Show tool calls while following (requires --follow). |
303333

304334
</CommandTable>
305335

packages/sim-cli/src/commands/protocol/index.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,11 @@ import { Command } from 'commander'
22
import { attachFileGet } from './files-get'
33
import { attachFileUpload } from './files-upload'
44
import { attachKnowledgeDocumentUpload } from './knowledge-document-upload'
5+
import { attachLogsFollow } from './logs-follow'
56
import { attachResourceDirectoryCommands } from './resource-directory'
67
import { attachTableImport } from './tables-import'
8+
import { attachWorkflowRunFollow } from './workflow-run-follow'
9+
import { attachWorkflowRunWait } from './workflow-run-wait'
710

811
function group(program: Command, name: string): Command {
912
const existing = program.commands.find((command) => command.name() === name)
@@ -43,10 +46,18 @@ export function attachProtocolCommands(program: Command): void {
4346
createFolder: 'createTableFolder',
4447
})
4548

46-
attachResourceDirectoryCommands(group(program, 'workflows'), {
49+
const workflows = group(program, 'workflows')
50+
attachResourceDirectoryCommands(workflows, {
4751
kind: 'workflow',
4852
resources: 'listWorkflows',
4953
folders: 'listWorkflowFolders',
5054
createFolder: 'createWorkflowFolder',
5155
})
56+
// Both augment commands the generated pass already built — `run` gains
57+
// `--follow`, and `runs` gains `wait` — so they must attach after it, which is
58+
// the order `buildProgram` calls them in.
59+
attachWorkflowRunFollow(workflows)
60+
attachWorkflowRunWait(group(workflows, 'runs'))
61+
62+
attachLogsFollow(group(program, 'logs'))
5263
}

0 commit comments

Comments
 (0)