Skip to content

Commit 21e14c7

Browse files
feat(cli): improve v2 command workflows
1 parent 2c0fd4f commit 21e14c7

13 files changed

Lines changed: 940 additions & 432 deletions

File tree

packages/sim-cli/README.md

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -122,11 +122,17 @@ sim workflows get <id>
122122
sim workflows update <id> [--name <name>] [--description <text>] [--folder <path>]
123123
sim workflows mv <id> <folder>
124124
sim workflows deploy|undeploy|rollback <id>
125-
sim workflows run <id> [--input <json|@file>] [--select-output <path>…]
125+
sim workflows run <id> [--input <json|@file>] [--select-output <path>…] [--async]
126+
sim workflows executions list --workflow <workflowId> [--status <status>]
127+
sim workflows executions get <executionId> --workflow <workflowId> [--include-output]
128+
sim workflows executions cancel <executionId> --workflow <workflowId>
129+
sim workflows executions resume <executionId> --workflow <workflowId> --context <contextId> [--input <json|@file>]
126130

127-
sim logs list [--level error] [--workflow <id>…] [--trigger <name>…] [--start <date>]
128-
sim logs get <logId>
129-
sim logs executions get <executionId>
131+
sim logs list [--level error] [--workflow <id>…] [--trigger <name>…] [--start-date <date>]
132+
sim logs get <executionId>
133+
134+
sim audit-logs list --organization <organizationId> [--all-workspaces]
135+
sim audit-logs get <id> --organization <organizationId>
130136

131137
sim tables ls [path] [--search <text>] [--limit <n>]
132138
sim tables list [--folder <path>]
@@ -164,17 +170,26 @@ sim documents get <documentId> --kb <knowledgeBaseId>
164170
sim documents upload <path> --kb <knowledgeBaseId> [--tag <value>...]
165171
sim documents delete <documentId> --kb <knowledgeBaseId> --yes
166172

167-
sim billing
168-
sim billing logs [--period 7d] [--source sim-chat] [--limit <n>]
173+
sim billing status [--all-workspaces]
174+
sim billing logs [--period 7d] [--source sim-chat] [--limit <n>] [--all-workspaces]
169175
```
170176

171177
The `sim-chat` billing source combines Copilot and workspace chat usage.
178+
Organization audit logs require a personal API key. Commands with
179+
`--all-workspaces` otherwise default to the workspace in the active profile.
172180

173-
`sim logs get` keeps the default human output concise. Use JSON or YAML to
174-
inspect its complete `executionData` and recursive `traceSpans` tree:
181+
`workflows executions get` is the lightweight status and polling resource.
182+
`--workflow` names the parent resource, while the execution ID remains positional.
183+
For a paused execution, its status includes the context ID needed by `resume`.
184+
`logs get` is the full diagnostic resource. It keeps the default human output
185+
concise; add `--trace` for the expanded recursive trace with span inputs,
186+
outputs, errors, timing, and cost. JSON and YAML retain the complete structured
187+
response:
175188

176189
```bash
177-
sim logs get <logId> --output json | jq '.traceSpans'
190+
sim logs get <executionId> --trace
191+
sim logs get <executionId> --output json | jq '.traceSpans'
192+
sim logs list --include-trace-spans --output json
178193
```
179194

180195
Workflow output selectors use `blockName.field` syntax, such as

packages/sim-cli/src/contract/commands.ts

Lines changed: 125 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,13 @@ const KNOWLEDGE_DOCUMENT_SCOPE = {
2525
describe: 'Knowledge base ID',
2626
},
2727
} as const
28+
const WORKFLOW_EXECUTION_SCOPE = {
29+
id: {
30+
name: 'workflow',
31+
placeholder: 'workflowId',
32+
describe: 'Workflow ID',
33+
},
34+
} as const
2835
const FOLDER_LIST_COLUMNS: ColumnSpec[] = [
2936
{ header: 'path' },
3037
{ header: 'name' },
@@ -54,21 +61,24 @@ function moveResource(command: string, resource: string): CommandVariantSpec {
5461
* upsertTableRow → sim tables upsert <tableId>
5562
*/
5663
export const CLI_CONTRACT: CliContract = {
57-
getUsageSummary: {
58-
command: 'billing',
59-
groupDefault: true,
60-
describe: 'Show current billing-period usage',
64+
getBillingStatus: {
65+
command: 'billing status',
66+
allWorkspaces: true,
67+
describe: 'Show billing status and current-period credit usage',
6168
fields: [
6269
{ header: 'plan' },
70+
{ header: 'status' },
71+
{ header: 'workspace', path: 'workspaceId' },
6372
{ header: 'period start', path: 'period.start', format: 'timestamp' },
6473
{ header: 'period end', path: 'period.end', format: 'timestamp' },
65-
{ header: 'used credits', path: 'totalCredits' },
66-
{ header: 'limit credits', path: 'limitCredits' },
67-
{ header: 'by source', path: 'bySourceCredits' },
74+
{ header: 'used credits', path: 'credits.used' },
75+
{ header: 'limit credits', path: 'credits.limit' },
76+
{ header: 'remaining credits', path: 'credits.remaining' },
6877
],
6978
},
70-
listUsageLogs: {
79+
listBillingLogs: {
7180
command: 'billing logs',
81+
allWorkspaces: true,
7282
describe: 'List credit usage events',
7383
flags: {
7484
source: { describe: 'Filter by usage source; sim-chat combines Copilot and workspace chat' },
@@ -78,9 +88,11 @@ export const CLI_CONTRACT: CliContract = {
7888
},
7989
columns: [
8090
{ header: 'at', path: 'createdAt', format: 'timestamp' },
91+
{ header: 'workspace', path: 'workspaceId' },
8192
{ header: 'source' },
82-
{ header: 'workflow', path: 'workflowName' },
93+
{ header: 'workflow', path: 'workflow.name' },
8394
{ header: 'credits', path: 'creditCost' },
95+
{ header: 'execution', path: 'executionId' },
8496
{ header: 'id' },
8597
],
8698
},
@@ -154,9 +166,19 @@ export const CLI_CONTRACT: CliContract = {
154166
workflowIds: { name: 'workflow', list: true },
155167
folderPaths: { ...FOLDER_PATH_FLAG, list: true },
156168
triggers: { name: 'trigger', list: true },
169+
details: { describe: 'Response detail level' },
170+
includeTraceSpans: {
171+
boolean: true,
172+
describe: 'Include trace spans in JSON or YAML output (implies full detail)',
173+
},
174+
includeFinalOutput: {
175+
boolean: true,
176+
describe: 'Include final output in JSON or YAML output (implies full detail)',
177+
},
157178
},
158179
columns: [
159180
{ header: 'started', path: 'startedAt', format: 'timestamp' },
181+
{ header: 'status' },
160182
{ header: 'level' },
161183
{ header: 'trigger' },
162184
{ header: 'workflow', path: 'workflow.name' },
@@ -166,19 +188,20 @@ export const CLI_CONTRACT: CliContract = {
166188
],
167189
},
168190
getLog: {
169-
describe:
170-
'Show a log summary (traceSpans and executionData are included in JSON or YAML output)',
191+
describe: 'Show execution diagnostics',
192+
expandedTrace: true,
171193
fields: [
172-
{ header: 'id' },
173194
{ header: 'execution', path: 'executionId' },
174195
{ header: 'workflow', path: 'workflow.name' },
196+
{ header: 'status' },
175197
{ header: 'level' },
176198
{ header: 'trigger' },
177199
{ header: 'started', path: 'startedAt', format: 'timestamp' },
178200
{ header: 'ended', path: 'endedAt', format: 'timestamp' },
179201
{ header: 'duration', path: 'totalDurationMs', format: 'duration' },
180202
{ header: 'cost', path: 'cost.total', format: 'cost' },
181203
{ header: 'files', format: 'count' },
204+
{ header: 'trace', path: 'traceSpans', format: 'trace-count' },
182205
],
183206
},
184207
searchKnowledge: {
@@ -372,13 +395,29 @@ export const CLI_CONTRACT: CliContract = {
372395
},
373396

374397
listAuditLogs: {
398+
allWorkspaces: true,
399+
flags: {
400+
organizationId: {
401+
name: 'organization',
402+
describe: 'Organization ID (personal API key required)',
403+
},
404+
},
375405
columns: [
376406
{ header: 'at', path: 'createdAt', format: 'timestamp' },
407+
{ header: 'workspace', path: 'workspaceId' },
377408
{ header: 'actor', path: 'actorEmail' },
378409
{ header: 'action' },
379410
{ header: 'resource', path: 'resourceName' },
380411
],
381412
},
413+
getAuditLog: {
414+
flags: {
415+
organizationId: {
416+
name: 'organization',
417+
describe: 'Organization ID (personal API key required)',
418+
},
419+
},
420+
},
382421

383422
// ─── The expanded files surface ───────────────────────────────────────────
384423
// Every one of these derives badly. `/files/move` and `/files/bulk-delete`
@@ -612,8 +651,9 @@ export const CLI_CONTRACT: CliContract = {
612651
// `workflows execute create` and `workflows cancel create`.
613652
executeWorkflow: {
614653
command: 'workflows run',
615-
describe: 'Run a deployed workflow and wait for the result',
654+
describe: 'Run a deployed workflow',
616655
flags: {
656+
async: { boolean: true, describe: 'Queue the execution and return immediately' },
617657
input: { json: true, describe: 'Trigger input as JSON' },
618658
selectedOutputs: {
619659
name: 'select-output',
@@ -626,18 +666,89 @@ export const CLI_CONTRACT: CliContract = {
626666
// command; advertising a flag that breaks the response is worse than
627667
// not offering it yet.
628668
stream: { omit: true },
669+
includeThinking: { omit: true },
670+
includeToolCalls: { omit: true },
629671
},
630672
},
631673
getWorkflowExecution: {
632674
command: 'workflows executions get',
633-
describe: 'Show the status of one execution',
675+
pathFlags: WORKFLOW_EXECUTION_SCOPE,
676+
describe: 'Show execution status (requested outputs are included in JSON or YAML output)',
677+
flags: {
678+
includeOutput: {
679+
boolean: true,
680+
describe: 'Include the final output in JSON or YAML output',
681+
},
682+
selectedOutputs: {
683+
name: 'select-output',
684+
list: true,
685+
describe: 'Include blockName.field values in JSON or YAML output (e.g. agent_1.content)',
686+
},
687+
},
688+
fields: [
689+
{ header: 'execution', path: 'executionId' },
690+
{ header: 'workflow', path: 'workflowId' },
691+
{ header: 'status' },
692+
{ header: 'trigger' },
693+
{ header: 'started', path: 'startedAt', format: 'timestamp' },
694+
{ header: 'ended', path: 'endedAt', format: 'timestamp' },
695+
{ header: 'duration', path: 'durationMs', format: 'duration' },
696+
{ header: 'cost', path: 'cost.total', format: 'cost' },
697+
{ header: 'context', path: 'paused.contextId' },
698+
{ header: 'pause kind', path: 'paused.pauseKind' },
699+
{ header: 'paused at', path: 'paused.pausedAt', format: 'timestamp' },
700+
{ header: 'resume at', path: 'paused.resumeAt', format: 'timestamp' },
701+
{ header: 'blocked on', path: 'paused.blockedOnBlockId' },
702+
{ header: 'pause points', path: 'paused.pausePointCount' },
703+
{ header: 'error', path: 'error.message' },
704+
],
705+
},
706+
listWorkflowExecutions: {
707+
command: 'workflows executions list',
708+
pathFlags: WORKFLOW_EXECUTION_SCOPE,
709+
describe: 'List executions for a workflow',
710+
columns: [
711+
{ header: 'started', path: 'startedAt', format: 'timestamp' },
712+
{ header: 'status' },
713+
{ header: 'trigger' },
714+
{ header: 'duration', path: 'durationMs', format: 'duration' },
715+
{ header: 'cost', path: 'cost.total', format: 'cost' },
716+
{ header: 'execution', path: 'executionId' },
717+
],
634718
},
635719
cancelWorkflowExecution: {
636720
command: 'workflows executions cancel',
721+
pathFlags: WORKFLOW_EXECUTION_SCOPE,
637722
describe: 'Cancel a running execution',
638723
// Not `confirm`-gated: cancelling is recoverable (re-run it), and the
639724
// whole point is to stop something that is already going wrong.
640725
},
726+
resumeWorkflow: {
727+
command: 'workflows executions resume',
728+
pathFlags: WORKFLOW_EXECUTION_SCOPE,
729+
describe: 'Resume a paused execution (output is included in JSON or YAML output)',
730+
flags: {
731+
contextId: {
732+
name: 'context',
733+
describe: 'Pause context ID returned by execution status',
734+
},
735+
input: {
736+
json: true,
737+
describe: 'Resume input as JSON',
738+
},
739+
},
740+
fields: [
741+
{ header: 'execution', path: 'executionId' },
742+
{ header: 'workflow', path: 'workflowId' },
743+
{ header: 'status' },
744+
{ header: 'status URL', path: 'statusUrl' },
745+
{ header: 'queue position', path: 'queuePosition' },
746+
{ header: 'started', path: 'startedAt', format: 'timestamp' },
747+
{ header: 'ended', path: 'endedAt', format: 'timestamp' },
748+
{ header: 'duration', path: 'durationMs', format: 'duration' },
749+
{ header: 'error', path: 'error.message' },
750+
],
751+
},
641752

642753
// ─── Not a terminal-shaped operation ──────────────────────────────────────
643754
// Multipart upload; `sim documents upload <path> --kb <id>` needs its

packages/sim-cli/src/contract/types.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ export interface ColumnSpec {
8282
/** Dot path into the row. Defaults to `header`. */
8383
path?: string
8484
/** Rendering hint; `auto` inspects the value. */
85-
format?: 'auto' | 'timestamp' | 'bytes' | 'duration' | 'bool' | 'cost' | 'count'
85+
format?: 'auto' | 'timestamp' | 'bytes' | 'duration' | 'bool' | 'cost' | 'count' | 'trace-count'
8686
}
8787

8888
export interface BodyVariantSpec {
@@ -135,8 +135,12 @@ export interface CommandSpec {
135135
columns?: ColumnSpec[]
136136
/** Fields shown for a single record in human formats. Machine output stays raw. */
137137
fields?: ColumnSpec[]
138+
/** Add `--trace` to expand recursive trace spans in human-readable output. */
139+
expandedTrace?: boolean
138140
/** Dot path to a nested result array rendered as the command's human list. */
139141
itemsPath?: string
142+
/** Allow an optional workspaceId field to omit the configured workspace filter. */
143+
allWorkspaces?: boolean
140144
/**
141145
* Require `--yes`. The message should say what is about to be destroyed —
142146
* the point is that the caller can tell whether they meant it.

0 commit comments

Comments
 (0)