@crewx/workflow 0.3.22-rc.1 → 0.3.22-rc.100
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/SKILL.md +255 -11
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +129 -6
- package/dist/cli.js.map +1 -1
- package/dist/src/engine.d.ts +4 -0
- package/dist/src/engine.d.ts.map +1 -1
- package/dist/src/engine.js +54 -1
- package/dist/src/engine.js.map +1 -1
- package/dist/src/mermaid.d.ts.map +1 -1
- package/dist/src/mermaid.js +23 -7
- package/dist/src/mermaid.js.map +1 -1
- package/dist/src/parent-task-sync.d.ts +49 -0
- package/dist/src/parent-task-sync.d.ts.map +1 -0
- package/dist/src/parent-task-sync.js +125 -0
- package/dist/src/parent-task-sync.js.map +1 -0
- package/dist/src/run-manager.d.ts +13 -2
- package/dist/src/run-manager.d.ts.map +1 -1
- package/dist/src/run-manager.js +630 -31
- package/dist/src/run-manager.js.map +1 -1
- package/dist/src/types.d.ts +32 -2
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/utils/output-format.d.ts +12 -0
- package/dist/src/utils/output-format.d.ts.map +1 -1
- package/dist/src/utils/output-format.js +103 -5
- package/dist/src/utils/output-format.js.map +1 -1
- package/dist/src/utils/shell-security.d.ts +18 -0
- package/dist/src/utils/shell-security.d.ts.map +1 -0
- package/dist/src/utils/shell-security.js +138 -0
- package/dist/src/utils/shell-security.js.map +1 -0
- package/dist/workflow-schema.json +46 -1
- package/package.json +26 -4
- package/workflow-schema.json +46 -1
package/SKILL.md
CHANGED
|
@@ -35,12 +35,20 @@ crewx workflow show standard-dev-core --mermaid
|
|
|
35
35
|
# Validate all workflow files
|
|
36
36
|
crewx workflow validate
|
|
37
37
|
|
|
38
|
-
# Start a workflow execution
|
|
39
|
-
crewx workflow run start standard-dev-core --set goal="implement feature X"
|
|
38
|
+
# Start a workflow execution and auto-run until completion/pause
|
|
39
|
+
crewx workflow run start standard-dev-core --set goal="implement feature X" --auto
|
|
40
|
+
|
|
41
|
+
# In the CrewX web chat, start a workflow as a signed ChatCard.
|
|
42
|
+
# Text after the workflow id becomes state.input.
|
|
43
|
+
/wf rc-publish prepare the next RC
|
|
44
|
+
/wf rc-publish --manual dry run only
|
|
40
45
|
|
|
41
46
|
# Move to a node
|
|
42
47
|
crewx workflow run node <exec-id> research
|
|
43
48
|
|
|
49
|
+
# Resume auto-run from the current node
|
|
50
|
+
crewx workflow run auto <exec-id>
|
|
51
|
+
|
|
44
52
|
# Check execution state
|
|
45
53
|
crewx workflow run state <exec-id>
|
|
46
54
|
```
|
|
@@ -78,10 +86,12 @@ crewx workflow validate workflows/standard-dev.yaml # Validate a specific file
|
|
|
78
86
|
### `workflow run start <id|file>`
|
|
79
87
|
|
|
80
88
|
Creates a new execution instance. State is stored as a JSON file in `.crewx/workflow-runs/`.
|
|
89
|
+
Add `--auto` to immediately execute deterministic nodes and agent nodes until the run reaches `end`, `approval`, `parallel`, or a failure.
|
|
81
90
|
|
|
82
91
|
```bash
|
|
83
92
|
crewx workflow run start standard-dev-core
|
|
84
93
|
crewx workflow run start standard-dev-core --set goal="build auth module"
|
|
94
|
+
crewx workflow run start standard-dev-core --set goal="build auth module" --auto
|
|
85
95
|
crewx workflow run start workflows/idea-validation.yaml
|
|
86
96
|
```
|
|
87
97
|
|
|
@@ -109,6 +119,36 @@ crewx workflow run node wfr_abc12345 research
|
|
|
109
119
|
crewx workflow run node wfr_abc12345 end
|
|
110
120
|
```
|
|
111
121
|
|
|
122
|
+
### `workflow run auto <exec-id>`
|
|
123
|
+
|
|
124
|
+
Auto-runs from the current node until the workflow reaches a natural pause or terminal state.
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
crewx workflow run auto wfr_abc12345
|
|
128
|
+
crewx workflow run auto wfr_abc12345 --json
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Auto mode executes these node types directly:
|
|
132
|
+
|
|
133
|
+
| Node type | Auto behavior |
|
|
134
|
+
|-----------|---------------|
|
|
135
|
+
| `agent_task` | Invokes the configured agent via `crewx q/x`, stores output if `output` is set, then follows `next` |
|
|
136
|
+
| `skill_task` | Runs `crewx skill <skill> ...args`, stores output if `output` is set, then follows `next` |
|
|
137
|
+
| `shell_task` | Runs a gated argv command with `shell: false`, stores output if `output` is set, then follows `next` |
|
|
138
|
+
| `expression` | Evaluates safe state expressions and follows `next` |
|
|
139
|
+
| `branch` | Evaluates the branch condition and moves to the selected node |
|
|
140
|
+
| `join` | Checks predecessor completion and follows `next` |
|
|
141
|
+
| `end` | Marks the run as completed |
|
|
142
|
+
|
|
143
|
+
Auto mode pauses instead of crossing these boundaries:
|
|
144
|
+
|
|
145
|
+
| Node type | Why it pauses |
|
|
146
|
+
|-----------|---------------|
|
|
147
|
+
| `approval` | Requires an explicit human approve/reject decision |
|
|
148
|
+
| `parallel` | Branch scheduling/convergence must be handled separately |
|
|
149
|
+
|
|
150
|
+
`max_iterations` limits auto-run steps and prevents infinite loops.
|
|
151
|
+
|
|
112
152
|
### `workflow run reset <exec-id>`
|
|
113
153
|
|
|
114
154
|
Restores execution state to `initial_state`.
|
|
@@ -181,6 +221,42 @@ analyze:
|
|
|
181
221
|
next: calculate
|
|
182
222
|
```
|
|
183
223
|
|
|
224
|
+
#### agent_task — execution context & failure signaling
|
|
225
|
+
|
|
226
|
+
Every `agent_task` prompt is automatically prefixed with a `<crewx.workflow>` preamble
|
|
227
|
+
telling the agent it runs headless inside a workflow node (workflow ID, node ID, run ID),
|
|
228
|
+
that clarifying questions are impossible, and how to signal failure. Disable with
|
|
229
|
+
`CREWX_WORKFLOW_PREAMBLE=off`.
|
|
230
|
+
|
|
231
|
+
Two semantic-failure channels stop the run at the node (in addition to non-zero exit codes):
|
|
232
|
+
|
|
233
|
+
1. **`workflow_signal` (agent-initiated)** — the agent outputs exactly one JSON object:
|
|
234
|
+
|
|
235
|
+
```json
|
|
236
|
+
{"workflow_signal": "fail", "reason": "build is red — tsc reports 14 errors"}
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
The engine detects it (pure JSON or embedded in prose), marks the node failed, and
|
|
240
|
+
records the reason in `run.error`. This is the agent's `exit 1`.
|
|
241
|
+
|
|
242
|
+
2. **`fail_when` (node-declared)** — a safe expression evaluated against state *after*
|
|
243
|
+
the node's output is stored. Truthy → node fails, run halts. The judged output is
|
|
244
|
+
still preserved in state for inspection. No separate `check_*` branch node needed.
|
|
245
|
+
|
|
246
|
+
```yaml
|
|
247
|
+
verify:
|
|
248
|
+
type: agent_task
|
|
249
|
+
agent: core_dev
|
|
250
|
+
output: verify_result
|
|
251
|
+
output_format: json
|
|
252
|
+
fail_when: 'state.verify_result.status !== "pass"'
|
|
253
|
+
next: smoke_test
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
`fail_when` works on `agent_task`, `skill_task`, and `shell_task`. It uses the same
|
|
257
|
+
safe expression subset as `branch` conditions (`includes()`, `===`, `&&`, `Number()`...).
|
|
258
|
+
Use `branch` when failure should route somewhere; use `fail_when` when failure should stop the run.
|
|
259
|
+
|
|
184
260
|
#### agent_task — JSON output mode
|
|
185
261
|
|
|
186
262
|
When `output_format: json`, the engine requires the agent to return a single JSON object.
|
|
@@ -232,6 +308,81 @@ The schema is validated against JSON Schema 2020-12 (`@hyperjump/json-schema`).
|
|
|
232
308
|
|
|
233
309
|
OpenAI Structured Outputs compatible — use `output_strict: true` to enforce the subset in the LLM prompt.
|
|
234
310
|
|
|
311
|
+
### `skill_task` -- Run a CrewX skill
|
|
312
|
+
|
|
313
|
+
Runs a built-in or registered CrewX skill without asking an agent to do the mechanical work. Use this for deterministic steps such as document extraction, search, indexing, validation, or other skill-backed commands.
|
|
314
|
+
|
|
315
|
+
```yaml
|
|
316
|
+
extract_attachments:
|
|
317
|
+
type: skill_task
|
|
318
|
+
skill: ocr-extractor
|
|
319
|
+
args: ["--input", "{{attachment_dir}}", "--json"]
|
|
320
|
+
output: extracted_text
|
|
321
|
+
output_format: json
|
|
322
|
+
output_retry: 2
|
|
323
|
+
timeout: 600
|
|
324
|
+
next: analyze
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
| Field | Type | Required | Description |
|
|
328
|
+
|-------|------|----------|-------------|
|
|
329
|
+
| `skill` | string | **Yes** | Skill name. Must match `^[a-z0-9][a-z0-9-]*$`; path traversal and special characters are rejected. |
|
|
330
|
+
| `args` | string[] | No | CLI arguments appended after the skill name. Supports `{{state}}` template interpolation. |
|
|
331
|
+
| `cwd` | string | No | Working directory. Normalized and constrained under the project root. |
|
|
332
|
+
| `output` | string | No | State key to store stdout. |
|
|
333
|
+
| `output_format` | `'json'` | No | Parse stdout as JSON and validate with `output_schema` if provided. |
|
|
334
|
+
| `output_schema` | object | No | Standard JSON Schema 2020-12 for parsed output. |
|
|
335
|
+
| `output_retry` | integer | No | Retry attempts if JSON parse or schema validation fails. |
|
|
336
|
+
|
|
337
|
+
`skill_task` uses `CREWX_CLI` (default: `npx crewx`) and executes the equivalent of:
|
|
338
|
+
|
|
339
|
+
```bash
|
|
340
|
+
crewx skill <skill> ...args
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
### `shell_task` -- Run a gated argv command
|
|
344
|
+
|
|
345
|
+
Runs a local command only when both safety gates are enabled:
|
|
346
|
+
|
|
347
|
+
1. Environment opt-in: `CREWX_WORKFLOW_SHELL=1`
|
|
348
|
+
2. Workflow opt-in: `metadata.shell_task_allowed: true`
|
|
349
|
+
|
|
350
|
+
```yaml
|
|
351
|
+
workflows:
|
|
352
|
+
build-check:
|
|
353
|
+
metadata:
|
|
354
|
+
name: "Build check"
|
|
355
|
+
shell_task_allowed: true
|
|
356
|
+
nodes:
|
|
357
|
+
build:
|
|
358
|
+
type: shell_task
|
|
359
|
+
command: ["pnpm", "run", "build"]
|
|
360
|
+
cwd: "."
|
|
361
|
+
output: build_log
|
|
362
|
+
timeout: 600
|
|
363
|
+
next: end
|
|
364
|
+
end:
|
|
365
|
+
type: end
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
| Field | Type | Required | Description |
|
|
369
|
+
|-------|------|----------|-------------|
|
|
370
|
+
| `command` | string[] | **Yes** | argv array. Plain string commands are rejected. `command[0]` is the program; remaining values are args. |
|
|
371
|
+
| `cwd` | string | No | Working directory. Normalized and constrained under the project root. |
|
|
372
|
+
| `env` | object | No | Explicit env pass-through. Dangerous keys such as `LD_PRELOAD` are rejected. |
|
|
373
|
+
| `output` | string | No | State key to store stdout. |
|
|
374
|
+
| `output_format` | `'json'` | No | Parse stdout as JSON and validate with `output_schema` if provided. |
|
|
375
|
+
| `output_schema` | object | No | Standard JSON Schema 2020-12 for parsed output. |
|
|
376
|
+
| `output_retry` | integer | No | Retry attempts if JSON parse or schema validation fails. |
|
|
377
|
+
|
|
378
|
+
Security rules:
|
|
379
|
+
|
|
380
|
+
- `shell_task.command` must be an argv array; it never runs through a shell.
|
|
381
|
+
- Shell interpreters such as `sh`, `bash`, `zsh`, `fish`, `cmd`, and `powershell` are blocked.
|
|
382
|
+
- Inline code flags such as `node -e`, `python -c`, and `ruby -e` are blocked.
|
|
383
|
+
- Parent environment is not inherited wholesale; only a minimal allowlist plus explicit safe `env` keys is passed.
|
|
384
|
+
- Commands run with timeout and process-group termination.
|
|
385
|
+
|
|
235
386
|
### `parallel` -- Fan-out to concurrent branches
|
|
236
387
|
|
|
237
388
|
```yaml
|
|
@@ -325,14 +476,15 @@ end:
|
|
|
325
476
|
| `on_failure` | string | `fail_fast` \| `continue` \| `ignore` |
|
|
326
477
|
| `on_error` | object | `{ handler?, fallback_node? }` |
|
|
327
478
|
| `comment` | string | Human-readable annotation |
|
|
328
|
-
| `
|
|
479
|
+
| `output` | string | State key to store stdout/result (`agent_task`, `skill_task`, `shell_task`) |
|
|
480
|
+
| `output_format` | `'json'` | Enable JSON output mode (`agent_task`, `skill_task`, `shell_task`) |
|
|
329
481
|
| `output_schema` | object | Standard JSON Schema 2020-12 for output validation |
|
|
330
482
|
| `output_strict` | boolean | Apply OpenAI Structured Outputs subset to LLM prompt (default: `false`) |
|
|
331
483
|
| `output_retry` | integer | Retry count if JSON parse/validation fails (default: `1`) |
|
|
332
484
|
|
|
333
485
|
## Template Syntax
|
|
334
486
|
|
|
335
|
-
Use `{{variable_name}}` in `input`
|
|
487
|
+
Use `{{variable_name}}` in fields such as `input`, `args`, `command`, `cwd`, and `env` values to reference `state` values.
|
|
336
488
|
|
|
337
489
|
```yaml
|
|
338
490
|
state:
|
|
@@ -383,6 +535,9 @@ const exec: RunExecution = manager.start('workflows/dev.yaml', 'dev-core', { goa
|
|
|
383
535
|
// Execute a node (triggers agent call for agent_task nodes)
|
|
384
536
|
const updated: RunExecution = await manager.executeNode(exec.id, 'research');
|
|
385
537
|
|
|
538
|
+
// Auto-run until end, approval, parallel, or failure
|
|
539
|
+
const autoResult = await manager.runAuto(exec.id);
|
|
540
|
+
|
|
386
541
|
// Move to node without executing
|
|
387
542
|
const moved: RunExecution = manager.moveNode(exec.id, 'implement');
|
|
388
543
|
```
|
|
@@ -390,7 +545,16 @@ const moved: RunExecution = manager.moveNode(exec.id, 'implement');
|
|
|
390
545
|
### Key Types
|
|
391
546
|
|
|
392
547
|
```typescript
|
|
393
|
-
type NodeType =
|
|
548
|
+
type NodeType =
|
|
549
|
+
| 'agent_task'
|
|
550
|
+
| 'skill_task'
|
|
551
|
+
| 'shell_task'
|
|
552
|
+
| 'parallel'
|
|
553
|
+
| 'join'
|
|
554
|
+
| 'branch'
|
|
555
|
+
| 'approval'
|
|
556
|
+
| 'expression'
|
|
557
|
+
| 'end';
|
|
394
558
|
|
|
395
559
|
interface RunExecution {
|
|
396
560
|
id: string; // 'wfr_{nanoid(8)}'
|
|
@@ -402,10 +566,82 @@ interface RunExecution {
|
|
|
402
566
|
completed_nodes: string[];
|
|
403
567
|
state: Record<string, unknown>;
|
|
404
568
|
initial_state: Record<string, unknown>;
|
|
569
|
+
audit?: Array<{
|
|
570
|
+
node_id: string;
|
|
571
|
+
type: NodeType;
|
|
572
|
+
status: 'success' | 'failed' | 'timeout';
|
|
573
|
+
started_at: string;
|
|
574
|
+
finished_at: string;
|
|
575
|
+
duration_ms: number;
|
|
576
|
+
exit_code?: number | null;
|
|
577
|
+
trigger?: 'manual' | 'auto';
|
|
578
|
+
}>;
|
|
405
579
|
status?: 'running' | 'completed' | 'failed';
|
|
406
580
|
}
|
|
407
581
|
```
|
|
408
582
|
|
|
583
|
+
## Web UI `/wf` ChatCard Integration
|
|
584
|
+
|
|
585
|
+
The CrewX web chat treats workflow runs as **conversation content**, not as a side panel. When a user sends a `/wf` command, the server creates a workflow run, stores the original user message in the thread transcript, and stores an assistant message containing a signed workflow ChatCard.
|
|
586
|
+
|
|
587
|
+
### Syntax
|
|
588
|
+
|
|
589
|
+
```text
|
|
590
|
+
/wf <workflow-id> [input...]
|
|
591
|
+
/wf <workflow-id> --manual [input...]
|
|
592
|
+
/wf <workflow-id> --auto [input...]
|
|
593
|
+
```
|
|
594
|
+
|
|
595
|
+
Examples:
|
|
596
|
+
|
|
597
|
+
| Input | Run behavior |
|
|
598
|
+
|-------|--------------|
|
|
599
|
+
| `/wf rc-publish` | Starts `rc-publish` in auto mode |
|
|
600
|
+
| `/wf rc-publish pre-approved` | Starts `rc-publish` with `state.input = "pre-approved"` |
|
|
601
|
+
| `/wf rc-publish --manual dry run` | Creates the run in manual mode with `state.input = "dry run"` |
|
|
602
|
+
| `/wf rc-publish --auto prepare RC notes` | Explicit auto mode; same as default |
|
|
603
|
+
|
|
604
|
+
`--manual` and `--auto` are parsed as options and are **not** included in `state.input`. All remaining text after the workflow id is copied to `state.input`.
|
|
605
|
+
|
|
606
|
+
### `state.input`
|
|
607
|
+
|
|
608
|
+
`state.input` is the standard entry point for user instructions passed into a workflow run.
|
|
609
|
+
|
|
610
|
+
```yaml
|
|
611
|
+
nodes:
|
|
612
|
+
- id: plan
|
|
613
|
+
type: agent_task
|
|
614
|
+
agent: "@core_dev"
|
|
615
|
+
prompt: |
|
|
616
|
+
User instruction:
|
|
617
|
+
{{input}}
|
|
618
|
+
|
|
619
|
+
Plan and execute the workflow step accordingly.
|
|
620
|
+
```
|
|
621
|
+
|
|
622
|
+
Branches and templates may also read `state.input`:
|
|
623
|
+
|
|
624
|
+
```yaml
|
|
625
|
+
condition: state.input.includes("dry run")
|
|
626
|
+
```
|
|
627
|
+
|
|
628
|
+
Important security rule: `state.input` is **not authority**. It may influence prompts, branches, and templates, but it must never bypass an `approval` node. For example, `/wf rc-publish pre-approved` stores the text in `state.input`; it does not approve publishing. Approval still requires the signed ChatCard action button.
|
|
629
|
+
|
|
630
|
+
### Stored ChatCard
|
|
631
|
+
|
|
632
|
+
The assistant message stores only a signed reference to the workflow run:
|
|
633
|
+
|
|
634
|
+
```xml
|
|
635
|
+
<crewx_card type="workflow" version="1" run_id="wfr_xxx" workflow_id="rc-publish" mode="auto" proof="jwt..." />
|
|
636
|
+
```
|
|
637
|
+
|
|
638
|
+
Rules:
|
|
639
|
+
|
|
640
|
+
- The `proof` is server-issued and expires after 7 days.
|
|
641
|
+
- Raw `<crewx_card>` text from users is rendered as plain text.
|
|
642
|
+
- Workflow actions such as resolve, auto resume, approve, reject, and cancel require a valid proof bound to the current workspace/thread/task.
|
|
643
|
+
- The mutable run state remains in `.crewx/workflow-runs/`; the ChatCard stores only a reference.
|
|
644
|
+
|
|
409
645
|
## Architecture
|
|
410
646
|
|
|
411
647
|
```
|
|
@@ -417,29 +653,37 @@ interface RunExecution {
|
|
|
417
653
|
v
|
|
418
654
|
workflows/*.yaml (source files)
|
|
419
655
|
|
|
420
|
-
[CLI] crewx workflow run start/node/state
|
|
656
|
+
[CLI] crewx workflow run start/node/state/auto
|
|
421
657
|
|
|
|
422
658
|
v
|
|
423
659
|
RunManager <-- execution state management
|
|
424
660
|
|
|
|
425
661
|
+---> .crewx/workflow-runs/wfr_*.json (state files)
|
|
426
|
-
+---> crewx q/x
|
|
662
|
+
+---> crewx q/x (agent_task)
|
|
663
|
+
+---> crewx skill <skill> (skill_task)
|
|
664
|
+
+---> argv command, shell:false (shell_task; gated)
|
|
427
665
|
|
|
428
666
|
[Server] GET /api/v1/workflows[/:id]
|
|
667
|
+
POST /api/v1/workflows/:id/runs
|
|
668
|
+
GET/POST /api/v1/workflows/runs/:execId/*
|
|
429
669
|
|
|
|
430
670
|
v
|
|
431
|
-
WorkflowService --> fs (YAML read) + WorkflowEngine
|
|
671
|
+
WorkflowService --> fs (YAML read) + WorkflowEngine + RunManager
|
|
672
|
+
|
|
|
673
|
+
+---> Thread transcript card:
|
|
674
|
+
<crewx_card type="workflow" run_id="..." workflow_id="..." mode="auto" proof="jwt..." />
|
|
432
675
|
```
|
|
433
676
|
|
|
434
|
-
> **Note:** The server
|
|
677
|
+
> **Note:** The server uses `RunManager` for workflow runs and stores workflow UI references as ChatCard tags in thread messages. The mutable run status/state remains in `.crewx/workflow-runs/` and is fetched by `run_id`.
|
|
435
678
|
|
|
436
679
|
## Environment Variables
|
|
437
680
|
|
|
438
681
|
| Variable | Description | Default |
|
|
439
682
|
|----------|-------------|---------|
|
|
440
683
|
| `CREWX_WORKSPACE` | Workspace directory (where `workflows/` lives) | `.` |
|
|
441
|
-
| `CREWX_CLI` | CrewX CLI path (for
|
|
442
|
-
| `CREWX_WORKFLOW_TIMEOUT` |
|
|
684
|
+
| `CREWX_CLI` | CrewX CLI path (for `agent_task` and `skill_task`) | `npx crewx` |
|
|
685
|
+
| `CREWX_WORKFLOW_TIMEOUT` | `agent_task` execution timeout (ms) | `1800000` (30 min) |
|
|
686
|
+
| `CREWX_WORKFLOW_SHELL` | First safety gate for `shell_task`; must be `1` | unset |
|
|
443
687
|
| `CREWX_CONFIG` | Custom config file path | `crewx.yaml` |
|
|
444
688
|
|
|
445
689
|
## WARNING: Check Agent List Before Designing
|
package/dist/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../cli.ts"],"names":[],"mappings":";AAgBA,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE9C,OAAO,KAAK,EAAE,cAAc,EAAgB,YAAY,
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../cli.ts"],"names":[],"mappings":";AAgBA,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE9C,OAAO,KAAK,EAAE,cAAc,EAAgB,YAAY,EAA+B,MAAM,aAAa,CAAC;AA6F3G,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAAC;CACrC;AAED,wBAAgB,eAAe,CAC7B,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,MAAM,EAAE,EACf,MAAM,EAAE,cAAc,EACtB,SAAS,CAAC,EAAE,cAAc,EAAE,GAC3B,gBAAgB,CAkDlB;AAs0BD,wBAAgB,kBAAkB,CAChC,WAAW,EAAE,MAAM,EACnB,cAAc,EAAE,MAAM,EACtB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,GAClC,MAAM,GAAG,IAAI,CAoBf;AAMD,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,GAAG,MAAM,EAAE,CAsB1E;AA4CD,wBAAsB,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAsD9D"}
|
package/dist/cli.js
CHANGED
|
@@ -63,7 +63,7 @@ async function loadTracer() {
|
|
|
63
63
|
return null;
|
|
64
64
|
}
|
|
65
65
|
}
|
|
66
|
-
const BOOLEAN_FLAGS = new Set(['help', 'json', 'mermaid', 'version', 'no-exec']);
|
|
66
|
+
const BOOLEAN_FLAGS = new Set(['help', 'json', 'mermaid', 'version', 'no-exec', 'auto', 'no-run']);
|
|
67
67
|
function parseArgs(args) {
|
|
68
68
|
const result = { positional: [], options: {} };
|
|
69
69
|
for (let i = 0; i < args.length; i++) {
|
|
@@ -193,11 +193,14 @@ Commands:
|
|
|
193
193
|
workflow list List all workflows
|
|
194
194
|
workflow show <id|file> Show workflow detail
|
|
195
195
|
workflow validate [id|file] Validate workflow YAML
|
|
196
|
-
workflow run start <id|file> Create new execution
|
|
196
|
+
workflow run start <id|file> Create new execution (add --auto to run to completion)
|
|
197
197
|
# Resolution: .yaml path → workflow ID → filename slug
|
|
198
198
|
workflow run state <id> Get/set execution state
|
|
199
199
|
workflow run node <id> <node> Execute node (auto-invoke agent)
|
|
200
|
+
workflow run auto <id> Auto-run from current node until end/pause
|
|
200
201
|
workflow run reset <id> Reset execution
|
|
202
|
+
workflow run retry <id> Retry a failed run from the failed node (--no-run: transition only)
|
|
203
|
+
⚠️ re-executes the failed node; safe only if it is idempotent
|
|
201
204
|
workflow run list List all executions
|
|
202
205
|
workflow usage Show detailed guide
|
|
203
206
|
|
|
@@ -298,8 +301,8 @@ function cmdList(engine, jsonMode) {
|
|
|
298
301
|
const firstId = workflows[0]?.id;
|
|
299
302
|
if (firstId) {
|
|
300
303
|
console.log(`\n${'━'.repeat(43)}`);
|
|
301
|
-
console.log(`🔍
|
|
302
|
-
console.log(`🔀
|
|
304
|
+
console.log(`🔍 Workflow details: npx workflow show ${firstId}`);
|
|
305
|
+
console.log(`🔀 Run workflow: npx workflow run start <id> --set key="value"`);
|
|
303
306
|
}
|
|
304
307
|
const listCtx = {
|
|
305
308
|
commandId: 'workflow.list',
|
|
@@ -533,7 +536,7 @@ function cmdValidate(engine, target, jsonMode) {
|
|
|
533
536
|
async function cmdRun(rest, rawArgs, jsonMode, engine) {
|
|
534
537
|
const runSub = rest[0];
|
|
535
538
|
const runArgs = rest.slice(1);
|
|
536
|
-
const mgr = new run_manager_1.RunManager();
|
|
539
|
+
const mgr = new run_manager_1.RunManager(undefined, getProjectRoot());
|
|
537
540
|
const { paths } = getWorkflowConfig();
|
|
538
541
|
switch (runSub) {
|
|
539
542
|
case 'start': {
|
|
@@ -564,8 +567,18 @@ async function cmdRun(rest, rawArgs, jsonMode, engine) {
|
|
|
564
567
|
process.exit(1);
|
|
565
568
|
}
|
|
566
569
|
const sets = (0, run_manager_1.parseSetArgs)(rawArgs);
|
|
570
|
+
const auto = rawArgs.includes('--auto');
|
|
567
571
|
try {
|
|
568
572
|
const run = mgr.start(resolved.filePath, resolved.workflowId ?? positional[1], Object.keys(sets).length > 0 ? sets : undefined);
|
|
573
|
+
if (auto) {
|
|
574
|
+
if (!jsonMode) {
|
|
575
|
+
console.log(`✅ Created execution: ${run.id}`);
|
|
576
|
+
console.log(` Workflow: ${run.workflow_id} (${resolved.filePath})`);
|
|
577
|
+
}
|
|
578
|
+
const result = await mgr.runAuto(run.id);
|
|
579
|
+
reportAutoResult(result, jsonMode);
|
|
580
|
+
break;
|
|
581
|
+
}
|
|
569
582
|
if (jsonMode) {
|
|
570
583
|
console.log(JSON.stringify({ success: true, exec_id: run.id, run }, null, 2));
|
|
571
584
|
}
|
|
@@ -798,6 +811,58 @@ async function cmdRun(rest, rawArgs, jsonMode, engine) {
|
|
|
798
811
|
}
|
|
799
812
|
break;
|
|
800
813
|
}
|
|
814
|
+
case 'retry': {
|
|
815
|
+
const positional = runArgs.filter(a => !a.startsWith('--'));
|
|
816
|
+
const execId = positional[0];
|
|
817
|
+
if (!execId) {
|
|
818
|
+
const msg = 'Usage: workflow run retry <exec-id> [--no-run]';
|
|
819
|
+
if (jsonMode) {
|
|
820
|
+
console.log(JSON.stringify({ success: false, error: msg }));
|
|
821
|
+
}
|
|
822
|
+
else {
|
|
823
|
+
console.error(`❌ ${msg}`);
|
|
824
|
+
}
|
|
825
|
+
process.exit(1);
|
|
826
|
+
}
|
|
827
|
+
const noRun = rawArgs.includes('--no-run');
|
|
828
|
+
try {
|
|
829
|
+
const run = mgr.retry(execId);
|
|
830
|
+
if (noRun) {
|
|
831
|
+
if (jsonMode) {
|
|
832
|
+
console.log(JSON.stringify({
|
|
833
|
+
success: true,
|
|
834
|
+
exec_id: run.id,
|
|
835
|
+
current_node: run.current_node,
|
|
836
|
+
retry_count: run.retry_count,
|
|
837
|
+
status: run.status,
|
|
838
|
+
}, null, 2));
|
|
839
|
+
}
|
|
840
|
+
else {
|
|
841
|
+
console.log(`✅ Retry transition: ${execId}`);
|
|
842
|
+
console.log(` Resume node: ${run.current_node}`);
|
|
843
|
+
console.log(` Retry count: ${run.retry_count}`);
|
|
844
|
+
console.log(` (state transition only; run "workflow run auto ${execId}" to execute — re-runs the node, safe only if idempotent)`);
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
else {
|
|
848
|
+
const result = await mgr.runAuto(run.id);
|
|
849
|
+
reportAutoResult(result, jsonMode);
|
|
850
|
+
if (result.outcome === 'failed')
|
|
851
|
+
process.exit(1);
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
catch (e) {
|
|
855
|
+
const msg = e.message;
|
|
856
|
+
if (jsonMode) {
|
|
857
|
+
console.log(JSON.stringify({ success: false, error: msg }));
|
|
858
|
+
}
|
|
859
|
+
else {
|
|
860
|
+
console.error(`❌ ${msg}`);
|
|
861
|
+
}
|
|
862
|
+
process.exit(1);
|
|
863
|
+
}
|
|
864
|
+
break;
|
|
865
|
+
}
|
|
801
866
|
case 'list': {
|
|
802
867
|
const runs = mgr.listRuns();
|
|
803
868
|
if (jsonMode) {
|
|
@@ -828,8 +893,39 @@ async function cmdRun(rest, rawArgs, jsonMode, engine) {
|
|
|
828
893
|
}
|
|
829
894
|
break;
|
|
830
895
|
}
|
|
896
|
+
case 'auto': {
|
|
897
|
+
const positional = runArgs.filter(a => !a.startsWith('--'));
|
|
898
|
+
const execId = positional[0];
|
|
899
|
+
if (!execId) {
|
|
900
|
+
const msg = 'Usage: workflow run auto <exec-id>';
|
|
901
|
+
if (jsonMode) {
|
|
902
|
+
console.log(JSON.stringify({ success: false, error: msg }));
|
|
903
|
+
}
|
|
904
|
+
else {
|
|
905
|
+
console.error(`❌ ${msg}`);
|
|
906
|
+
}
|
|
907
|
+
process.exit(1);
|
|
908
|
+
}
|
|
909
|
+
try {
|
|
910
|
+
const result = await mgr.runAuto(execId);
|
|
911
|
+
reportAutoResult(result, jsonMode);
|
|
912
|
+
if (result.outcome === 'failed')
|
|
913
|
+
process.exit(1);
|
|
914
|
+
}
|
|
915
|
+
catch (e) {
|
|
916
|
+
const msg = e.message;
|
|
917
|
+
if (jsonMode) {
|
|
918
|
+
console.log(JSON.stringify({ success: false, error: msg }));
|
|
919
|
+
}
|
|
920
|
+
else {
|
|
921
|
+
console.error(`❌ ${msg}`);
|
|
922
|
+
}
|
|
923
|
+
process.exit(1);
|
|
924
|
+
}
|
|
925
|
+
break;
|
|
926
|
+
}
|
|
831
927
|
default: {
|
|
832
|
-
const msg = `Unknown run subcommand: ${runSub || '(none)'}\nUsage: workflow run <start|state|node|reset|list> [args...]`;
|
|
928
|
+
const msg = `Unknown run subcommand: ${runSub || '(none)'}\nUsage: workflow run <start|state|node|auto|reset|retry|list> [args...]`;
|
|
833
929
|
if (jsonMode) {
|
|
834
930
|
console.log(JSON.stringify({ success: false, error: msg }));
|
|
835
931
|
}
|
|
@@ -840,12 +936,39 @@ async function cmdRun(rest, rawArgs, jsonMode, engine) {
|
|
|
840
936
|
}
|
|
841
937
|
}
|
|
842
938
|
}
|
|
939
|
+
function reportAutoResult(result, jsonMode) {
|
|
940
|
+
const { run, outcome, reason, executed } = result;
|
|
941
|
+
const status = run.status ?? (outcome === 'paused' ? 'paused' : 'running');
|
|
942
|
+
if (jsonMode) {
|
|
943
|
+
console.log(JSON.stringify({
|
|
944
|
+
success: outcome !== 'failed',
|
|
945
|
+
exec_id: run.id,
|
|
946
|
+
status,
|
|
947
|
+
outcome,
|
|
948
|
+
current_node: run.current_node,
|
|
949
|
+
completed_nodes: run.completed_nodes,
|
|
950
|
+
executed,
|
|
951
|
+
...(reason ? { reason } : {}),
|
|
952
|
+
}, null, 2));
|
|
953
|
+
return;
|
|
954
|
+
}
|
|
955
|
+
const icon = outcome === 'failed' ? '❌' : outcome === 'paused' ? '⏸️' : '✅';
|
|
956
|
+
console.log(`${icon} Auto run: ${run.id}`);
|
|
957
|
+
if (executed.length > 0) {
|
|
958
|
+
console.log(` Executed: ${executed.join(' → ')}`);
|
|
959
|
+
}
|
|
960
|
+
console.log(` Outcome: ${outcome}${reason ? ` (${reason})` : ''}`);
|
|
961
|
+
console.log(` Current: ${run.current_node || '(none)'}`);
|
|
962
|
+
console.log(` Status: ${status}`);
|
|
963
|
+
}
|
|
843
964
|
function findNextNodeForCAL(currentNode, executedNodeId, nodes) {
|
|
844
965
|
const executedNode = nodes[executedNodeId];
|
|
845
966
|
if (!executedNode)
|
|
846
967
|
return null;
|
|
847
968
|
switch (executedNode.type) {
|
|
848
969
|
case 'agent_task':
|
|
970
|
+
case 'skill_task':
|
|
971
|
+
case 'shell_task':
|
|
849
972
|
case 'expression':
|
|
850
973
|
return typeof executedNode.next === 'string' ? executedNode.next : null;
|
|
851
974
|
case 'branch':
|