@cargo-ai/cli 1.0.18 → 1.0.20
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/README.md +46 -16
- package/build/commands/ai/index.d.ts.map +1 -1
- package/build/commands/ai/index.js +1 -3
- package/build/commands/content/file.d.ts.map +1 -0
- package/build/commands/{ai → content}/file.js +7 -7
- package/build/commands/content/index.d.ts +4 -0
- package/build/commands/content/index.d.ts.map +1 -0
- package/build/commands/content/index.js +9 -0
- package/build/commands/content/library.d.ts +4 -0
- package/build/commands/content/library.d.ts.map +1 -0
- package/build/commands/content/library.js +78 -0
- package/build/commands/orchestration/index.d.ts.map +1 -1
- package/build/commands/orchestration/index.js +0 -2
- package/build/commands/orchestration/release.d.ts.map +1 -1
- package/build/commands/orchestration/release.js +256 -2
- package/build/commands/storage/model.js +3 -3
- package/build/commands/workflow/index.d.ts +4 -0
- package/build/commands/workflow/index.d.ts.map +1 -0
- package/build/commands/workflow/index.js +10 -0
- package/build/commands/workflow/inputTypes.d.ts +18 -0
- package/build/commands/workflow/inputTypes.d.ts.map +1 -0
- package/build/commands/workflow/inputTypes.js +175 -0
- package/build/commands/workflow/sync.d.ts +4 -0
- package/build/commands/workflow/sync.d.ts.map +1 -0
- package/build/commands/workflow/sync.js +454 -0
- package/build/index.js +2 -0
- package/package.json +5 -5
- package/build/commands/ai/file.d.ts.map +0 -1
- package/build/commands/orchestration/draftRelease.d.ts +0 -4
- package/build/commands/orchestration/draftRelease.d.ts.map +0 -1
- package/build/commands/orchestration/draftRelease.js +0 -73
- /package/build/commands/{ai → content}/file.d.ts +0 -0
package/README.md
CHANGED
|
@@ -98,25 +98,55 @@ cargo-ai orchestration workflow --help
|
|
|
98
98
|
|
|
99
99
|
### Domains and example commands
|
|
100
100
|
|
|
101
|
-
| Domain | Description
|
|
102
|
-
| ------------------------ |
|
|
103
|
-
| **init** | Workspace initialisation (user, workspace, datasets, etc.)
|
|
104
|
-
| **orchestration** | Workflows, plays, runs, batches, tools, templates
|
|
105
|
-
| **workspaceManagement** | Workspaces, users, tokens, roles, folders
|
|
106
|
-
| **storage** | Datasets, models, relationships, runs, records
|
|
107
|
-
| **connection** | Connectors and integrations
|
|
108
|
-
| **billing** | Usage and subscription
|
|
109
|
-
| **segmentation** | Segments and changes
|
|
110
|
-
| **revenue-organization** | Allocations, capacities, members, territories
|
|
111
|
-
| **expression** | Recipes and expression evaluation
|
|
112
|
-
| **system-of-record** | System of record, client, logs
|
|
113
|
-
| **user-management** | Current user (no workspace context)
|
|
114
|
-
| **ai** | AI templates, agents, releases, chats, MCP, files
|
|
115
|
-
| **context** | Context repository, runtime sandbox, and knowledge graph
|
|
116
|
-
| **hosting** | Cargo Hosting apps (Vite SPAs), workers, and deployments
|
|
101
|
+
| Domain | Description | Example commands |
|
|
102
|
+
| ------------------------ | ------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
|
|
103
|
+
| **init** | Workspace initialisation (user, workspace, datasets, etc.) | `cargo-ai init` |
|
|
104
|
+
| **orchestration** | Workflows, plays, runs, batches, tools, templates | `cargo-ai orchestration workflow list`, `cargo-ai orchestration run list --workflow-uuid <uuid>` |
|
|
105
|
+
| **workspaceManagement** | Workspaces, users, tokens, roles, folders | `cargo-ai workspaceManagement workspaces list`, `cargo-ai workspaceManagement token list` |
|
|
106
|
+
| **storage** | Datasets, models, relationships, runs, records | `cargo-ai storage dataset list`, `cargo-ai storage model list` |
|
|
107
|
+
| **connection** | Connectors and integrations | `cargo-ai connection connector list`, `cargo-ai connection integration list` |
|
|
108
|
+
| **billing** | Usage and subscription | `cargo-ai billing subscription get`, `cargo-ai billing usage get-metrics --payload '{"from":"2025-01-01","to":"2025-01-31"}'` |
|
|
109
|
+
| **segmentation** | Segments and changes | `cargo-ai segmentation segment list`, `cargo-ai segmentation change list --payload '{}'` |
|
|
110
|
+
| **revenue-organization** | Allocations, capacities, members, territories | `cargo-ai revenue-organization member list`, `cargo-ai revenue-organization territory list` |
|
|
111
|
+
| **expression** | Recipes and expression evaluation | `cargo-ai expression recipe list`, `cargo-ai expression eval evaluate --payload '{}'` |
|
|
112
|
+
| **system-of-record** | System of record, client, logs | `cargo-ai system-of-record sor list`, `cargo-ai system-of-record log list --payload '{}'` |
|
|
113
|
+
| **user-management** | Current user (no workspace context) | `cargo-ai user-management user get-current` |
|
|
114
|
+
| **ai** | AI templates, agents, releases, chats, MCP, files | `cargo-ai ai template list`, `cargo-ai ai agent list`, `cargo-ai ai file list` |
|
|
115
|
+
| **context** | Context repository, runtime sandbox, and knowledge graph | `cargo-ai context repository get`, `cargo-ai context runtime browse --path <path>`, `cargo-ai context graph get` |
|
|
116
|
+
| **hosting** | Cargo Hosting apps (Vite SPAs), workers, and deployments | `cargo-ai hosting app list`, `cargo-ai hosting worker list`, `cargo-ai hosting deployment list --payload '{}'` |
|
|
117
|
+
| **workflow** | Workflow SDK developer tools: per-workspace type sync/codegen | `cargo-ai workflow sync` (SDK deploy lives at `cargo-ai orchestration release deploy-draft --file <path>`) |
|
|
117
118
|
|
|
118
119
|
Commands that accept complex payloads use a `--payload <json>` option (e.g. `cargo-ai orchestration play create --payload '{"name":"My Play",...}'`). Use `--help` on any subcommand for options.
|
|
119
120
|
|
|
121
|
+
### `orchestration release deploy-draft`
|
|
122
|
+
|
|
123
|
+
Deploy a draft release of an **existing** workflow. Two input modes share the same command:
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
# Compile a Workflow SDK module and deploy it
|
|
127
|
+
cargo-ai orchestration release deploy-draft --file ./my-workflow.ts
|
|
128
|
+
|
|
129
|
+
# Preview the compiled nodes + form fields without deploying
|
|
130
|
+
cargo-ai orchestration release deploy-draft --file ./my-workflow.ts --dry-run
|
|
131
|
+
|
|
132
|
+
# Pin an explicit version + description
|
|
133
|
+
cargo-ai orchestration release deploy-draft --file ./my-workflow.ts --workflow-uuid <uuid> --version 2.0.0 --description "New enrichment path"
|
|
134
|
+
|
|
135
|
+
# Power-user path: deploy raw wire-format JSON
|
|
136
|
+
cargo-ai orchestration release deploy-draft --workflow-uuid <uuid> --nodes '[…]' --form-fields '[…]'
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
`--file <path>` loads a [`@cargo-ai/workflow-sdk`](../workflow-sdk/README.md) module (its `export default defineWorkflow(...)`) and sources `nodes` / `formFields` / `description` from the compiled output. With `--file`:
|
|
140
|
+
|
|
141
|
+
- `--workflow-uuid` is optional — when omitted, the command best-effort matches the compiled `slug` against existing workflows' `template.slug` and errors if the match is missing or ambiguous.
|
|
142
|
+
- `--version` defaults to the next minor bump over the latest existing release (or `1.0.0` for the first).
|
|
143
|
+
- `--description` defaults to the compiled workflow's description.
|
|
144
|
+
- `--nodes` / `--form-fields` are rejected (they're sourced from the module).
|
|
145
|
+
|
|
146
|
+
Without `--file`, `--workflow-uuid`, `--nodes`, and `--form-fields` are all required (raw JSON path). Constraint either way: there is **no** workflow-create endpoint, so the target workflow must already exist.
|
|
147
|
+
|
|
148
|
+
Other release verbs (`list`, `get <uuid>`, `get-deployed`, `get-draft`, `update-draft`) live under the same group — see `cargo-ai orchestration release --help`.
|
|
149
|
+
|
|
120
150
|
## Agent Skills
|
|
121
151
|
|
|
122
152
|
[Cargo Skills](https://github.com/getcargohq/cargo-skills) teaches AI coding agents (Claude Code, Cursor, Windsurf, GitHub Copilot, etc.) how to use the Cargo CLI. Install the skill to let your agent build, run, and manage revenue automation workflows programmatically:
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/ai/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/ai/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAcxC,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,GAAG,IAAI,CAiB3E"}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { registerAgentCommands } from "./agent.js";
|
|
2
2
|
import { registerChatCommands } from "./chat.js";
|
|
3
3
|
import { registerDocumentCommands } from "./document.js";
|
|
4
|
-
import { registerFileCommands } from "./file.js";
|
|
5
4
|
import { registerMcpClientCommands } from "./mcpClient.js";
|
|
6
5
|
import { registerMcpServerCommands } from "./mcpServer.js";
|
|
7
6
|
import { registerMemoryCommands } from "./memory.js";
|
|
@@ -14,13 +13,12 @@ import { registerVoteCommands } from "./vote.js";
|
|
|
14
13
|
export function registerAiCommands(parent, getApi) {
|
|
15
14
|
const ai = parent
|
|
16
15
|
.command("ai")
|
|
17
|
-
.description("AI templates, agents, releases, chats, MCP
|
|
16
|
+
.description("AI templates, agents, releases, chats, MCP");
|
|
18
17
|
registerTemplateCommands(ai, getApi);
|
|
19
18
|
registerAgentCommands(ai, getApi);
|
|
20
19
|
registerReleaseCommands(ai, getApi);
|
|
21
20
|
registerChatCommands(ai, getApi);
|
|
22
21
|
registerMcpServerCommands(ai, getApi);
|
|
23
|
-
registerFileCommands(ai, getApi);
|
|
24
22
|
registerMessageCommands(ai, getApi);
|
|
25
23
|
registerVoteCommands(ai, getApi);
|
|
26
24
|
registerDocumentCommands(ai, getApi);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file.d.ts","sourceRoot":"","sources":["../../../src/commands/content/file.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAGxC,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,GAAG,IAAI,CAkF7E"}
|
|
@@ -2,13 +2,13 @@ import { readFile } from "node:fs/promises";
|
|
|
2
2
|
import { basename } from "node:path";
|
|
3
3
|
import { handleApiCall, outputJson } from "../runHandler.js";
|
|
4
4
|
export function registerFileCommands(parent, getApi) {
|
|
5
|
-
const file = parent.command("file").description("
|
|
5
|
+
const file = parent.command("file").description("Storage file operations");
|
|
6
6
|
file
|
|
7
7
|
.command("list")
|
|
8
|
-
.description("List all
|
|
8
|
+
.description("List all workspace files")
|
|
9
9
|
.action(async () => {
|
|
10
10
|
const api = getApi();
|
|
11
|
-
const result = await handleApiCall(() => api.
|
|
11
|
+
const result = await handleApiCall(() => api.content.file.all());
|
|
12
12
|
outputJson(result);
|
|
13
13
|
});
|
|
14
14
|
file
|
|
@@ -16,7 +16,7 @@ export function registerFileCommands(parent, getApi) {
|
|
|
16
16
|
.description("Get file by UUID")
|
|
17
17
|
.action(async (uuid) => {
|
|
18
18
|
const api = getApi();
|
|
19
|
-
const result = await handleApiCall(() => api.
|
|
19
|
+
const result = await handleApiCall(() => api.content.file.get(uuid));
|
|
20
20
|
outputJson(result);
|
|
21
21
|
});
|
|
22
22
|
file
|
|
@@ -27,7 +27,7 @@ export function registerFileCommands(parent, getApi) {
|
|
|
27
27
|
.option("--folder-uuid <uuid>", "Folder UUID")
|
|
28
28
|
.action(async (opts) => {
|
|
29
29
|
const api = getApi();
|
|
30
|
-
const result = await handleApiCall(() => api.
|
|
30
|
+
const result = await handleApiCall(() => api.content.file.update({
|
|
31
31
|
uuid: opts.uuid,
|
|
32
32
|
name: opts.name,
|
|
33
33
|
folderUuid: opts.folderUuid,
|
|
@@ -39,7 +39,7 @@ export function registerFileCommands(parent, getApi) {
|
|
|
39
39
|
.description("Remove a file")
|
|
40
40
|
.action(async (uuid) => {
|
|
41
41
|
const api = getApi();
|
|
42
|
-
await handleApiCall(() => api.
|
|
42
|
+
await handleApiCall(() => api.content.file.remove(uuid));
|
|
43
43
|
outputJson({ ok: true });
|
|
44
44
|
});
|
|
45
45
|
file
|
|
@@ -53,7 +53,7 @@ export function registerFileCommands(parent, getApi) {
|
|
|
53
53
|
const fileObj = new File([buffer], name);
|
|
54
54
|
const api = getApi();
|
|
55
55
|
await handleApiCall(() => new Promise((resolve, reject) => {
|
|
56
|
-
api.
|
|
56
|
+
api.content.file.upload({
|
|
57
57
|
file: fileObj,
|
|
58
58
|
folderUuid: opts.folderUuid,
|
|
59
59
|
onProgress: (pct) => {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/content/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAIxC,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,OAAO,EACf,MAAM,EAAE,MAAM,GAAG,GAChB,IAAI,CAON"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { registerFileCommands } from "./file.js";
|
|
2
|
+
import { registerLibraryCommands } from "./library.js";
|
|
3
|
+
export function registerContentCommands(parent, getApi) {
|
|
4
|
+
const content = parent
|
|
5
|
+
.command("content")
|
|
6
|
+
.description("Workspace files and libraries");
|
|
7
|
+
registerFileCommands(content, getApi);
|
|
8
|
+
registerLibraryCommands(content, getApi);
|
|
9
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"library.d.ts","sourceRoot":"","sources":["../../../src/commands/content/library.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAGxC,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,OAAO,EACf,MAAM,EAAE,MAAM,GAAG,GAChB,IAAI,CAwGN"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { handleApiCall, outputJson } from "../runHandler.js";
|
|
2
|
+
export function registerLibraryCommands(parent, getApi) {
|
|
3
|
+
const library = parent
|
|
4
|
+
.command("library")
|
|
5
|
+
.description("Storage library operations");
|
|
6
|
+
library
|
|
7
|
+
.command("list")
|
|
8
|
+
.description("List workspace libraries")
|
|
9
|
+
.option("--connector-uuid <uuid>", "Filter by connector UUID")
|
|
10
|
+
.option("--kind <kind>", "Filter by kind (native or connector)")
|
|
11
|
+
.action(async (opts) => {
|
|
12
|
+
const api = getApi();
|
|
13
|
+
const kind = opts.kind === "connector" || opts.kind === "native"
|
|
14
|
+
? opts.kind
|
|
15
|
+
: undefined;
|
|
16
|
+
const result = await handleApiCall(() => api.content.library.list({
|
|
17
|
+
connectorUuid: opts.connectorUuid,
|
|
18
|
+
kind,
|
|
19
|
+
}));
|
|
20
|
+
outputJson(result);
|
|
21
|
+
});
|
|
22
|
+
library
|
|
23
|
+
.command("get <uuid>")
|
|
24
|
+
.description("Get library by UUID")
|
|
25
|
+
.action(async (uuid) => {
|
|
26
|
+
const api = getApi();
|
|
27
|
+
const result = await handleApiCall(() => api.content.library.get(uuid));
|
|
28
|
+
outputJson(result);
|
|
29
|
+
});
|
|
30
|
+
library
|
|
31
|
+
.command("create")
|
|
32
|
+
.description("Create a connector library")
|
|
33
|
+
.requiredOption("--name <name>", "Library name")
|
|
34
|
+
.requiredOption("--extractor-slug <slug>", "Unstructured extractor slug")
|
|
35
|
+
.requiredOption("--connector-uuid <uuid>", "Connector UUID")
|
|
36
|
+
.option("--folder-uuid <uuid>", "Default folder UUID")
|
|
37
|
+
.option("--config <json>", "Library config JSON", "{}")
|
|
38
|
+
.action(async (opts) => {
|
|
39
|
+
const api = getApi();
|
|
40
|
+
const config = JSON.parse(opts.config);
|
|
41
|
+
const result = await handleApiCall(() => api.content.library.create({
|
|
42
|
+
name: opts.name,
|
|
43
|
+
extractorSlug: opts.extractorSlug,
|
|
44
|
+
connectorUuid: opts.connectorUuid,
|
|
45
|
+
folderUuid: opts.folderUuid,
|
|
46
|
+
config,
|
|
47
|
+
}));
|
|
48
|
+
outputJson(result);
|
|
49
|
+
});
|
|
50
|
+
library
|
|
51
|
+
.command("update")
|
|
52
|
+
.description("Update a library")
|
|
53
|
+
.requiredOption("--uuid <uuid>", "Library UUID")
|
|
54
|
+
.option("--name <name>", "Library name")
|
|
55
|
+
.option("--folder-uuid <uuid>", "Default folder UUID")
|
|
56
|
+
.option("--config <json>", "Library config JSON")
|
|
57
|
+
.action(async (opts) => {
|
|
58
|
+
const api = getApi();
|
|
59
|
+
const config = opts.config !== undefined
|
|
60
|
+
? JSON.parse(opts.config)
|
|
61
|
+
: undefined;
|
|
62
|
+
const result = await handleApiCall(() => api.content.library.update({
|
|
63
|
+
uuid: opts.uuid,
|
|
64
|
+
name: opts.name,
|
|
65
|
+
folderUuid: opts.folderUuid,
|
|
66
|
+
config,
|
|
67
|
+
}));
|
|
68
|
+
outputJson(result);
|
|
69
|
+
});
|
|
70
|
+
library
|
|
71
|
+
.command("remove <uuid>")
|
|
72
|
+
.description("Remove a library")
|
|
73
|
+
.action(async (uuid) => {
|
|
74
|
+
const api = getApi();
|
|
75
|
+
await handleApiCall(() => api.content.library.remove(uuid));
|
|
76
|
+
outputJson({ ok: true });
|
|
77
|
+
});
|
|
78
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/orchestration/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/orchestration/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAexC,wBAAgB,6BAA6B,CAC3C,MAAM,EAAE,OAAO,EACf,MAAM,EAAE,MAAM,GAAG,GAChB,IAAI,CAkBN"}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { registerActionCommands } from "./action.js";
|
|
2
2
|
import { registerBatchCommands } from "./batch.js";
|
|
3
|
-
import { registerDraftReleaseCommands } from "./draftRelease.js";
|
|
4
3
|
import { registerNodeCommands } from "./node.js";
|
|
5
4
|
import { registerPlayCommands } from "./play.js";
|
|
6
5
|
import { registerQueryCommands } from "./query.js";
|
|
@@ -24,7 +23,6 @@ export function registerOrchestrationCommands(parent, getApi) {
|
|
|
24
23
|
registerSpanCommands(orchestration, getApi);
|
|
25
24
|
registerTraceCommands(orchestration, getApi);
|
|
26
25
|
registerReleaseCommands(orchestration, getApi);
|
|
27
|
-
registerDraftReleaseCommands(orchestration, getApi);
|
|
28
26
|
registerToolCommands(orchestration, getApi);
|
|
29
27
|
registerRecordCommands(orchestration, getApi);
|
|
30
28
|
registerTemplateCommands(orchestration, getApi);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"release.d.ts","sourceRoot":"","sources":["../../../src/commands/orchestration/release.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"release.d.ts","sourceRoot":"","sources":["../../../src/commands/orchestration/release.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAyCxC,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,OAAO,EACf,MAAM,EAAE,MAAM,GAAG,GAChB,IAAI,CAkLN"}
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { isAbsolute, resolve } from "node:path";
|
|
3
|
+
import { pathToFileURL } from "node:url";
|
|
4
|
+
import { ExitCodes, failWith, handleApiCall, info, outputJson, parseJson, success, } from "../runHandler.js";
|
|
2
5
|
export function registerReleaseCommands(parent, getApi) {
|
|
3
6
|
const release = parent
|
|
4
7
|
.command("release")
|
|
5
|
-
.description("Manage workflow releases (list, get, get-deployed)");
|
|
8
|
+
.description("Manage workflow releases (list, get, get-deployed, get-draft, update-draft, deploy-draft)");
|
|
6
9
|
release
|
|
7
10
|
.command("list")
|
|
8
11
|
.description("List releases")
|
|
@@ -37,4 +40,255 @@ export function registerReleaseCommands(parent, getApi) {
|
|
|
37
40
|
}));
|
|
38
41
|
outputJson(result);
|
|
39
42
|
});
|
|
43
|
+
release
|
|
44
|
+
.command("get-draft")
|
|
45
|
+
.description("Get the draft release for a workflow")
|
|
46
|
+
.requiredOption("--workflow-uuid <uuid>", "Workflow UUID")
|
|
47
|
+
.action(async (opts) => {
|
|
48
|
+
const api = getApi();
|
|
49
|
+
const result = await handleApiCall(() => api.orchestration.draftRelease.get({
|
|
50
|
+
workflowUuid: opts.workflowUuid,
|
|
51
|
+
}));
|
|
52
|
+
outputJson(result);
|
|
53
|
+
});
|
|
54
|
+
release
|
|
55
|
+
.command("update-draft")
|
|
56
|
+
.description("Update the draft release of a workflow")
|
|
57
|
+
.requiredOption("--workflow-uuid <uuid>", "Workflow UUID")
|
|
58
|
+
.option("--parent-uuid <uuid>", "Parent release UUID")
|
|
59
|
+
.option("--nodes <json>", "Nodes (JSON array of node definitions)")
|
|
60
|
+
.option("--test-records <json>", "Test records (JSON array)")
|
|
61
|
+
.option("--form-fields <json>", "Form fields (JSON array, or 'null')")
|
|
62
|
+
.option("--options <json>", "Options (JSON object)")
|
|
63
|
+
.action(async (opts) => {
|
|
64
|
+
const api = getApi();
|
|
65
|
+
const result = await handleApiCall(() => api.orchestration.draftRelease.update({
|
|
66
|
+
workflowUuid: opts.workflowUuid,
|
|
67
|
+
parentUuid: opts.parentUuid,
|
|
68
|
+
nodes: opts.nodes !== undefined
|
|
69
|
+
? parseJson(opts.nodes, "--nodes")
|
|
70
|
+
: undefined,
|
|
71
|
+
testRecords: opts.testRecords !== undefined
|
|
72
|
+
? parseJson(opts.testRecords, "--test-records")
|
|
73
|
+
: undefined,
|
|
74
|
+
formFields: opts.formFields === "null"
|
|
75
|
+
? null
|
|
76
|
+
: opts.formFields !== undefined
|
|
77
|
+
? parseJson(opts.formFields, "--form-fields")
|
|
78
|
+
: undefined,
|
|
79
|
+
options: opts.options !== undefined
|
|
80
|
+
? parseJson(opts.options, "--options")
|
|
81
|
+
: undefined,
|
|
82
|
+
}));
|
|
83
|
+
outputJson(result);
|
|
84
|
+
});
|
|
85
|
+
release
|
|
86
|
+
.command("deploy-draft")
|
|
87
|
+
.description("Deploy a draft release. Pass --file to compile a Workflow SDK module, or --nodes + --form-fields to deploy raw wire-format JSON.")
|
|
88
|
+
.option("--file <path>", "Path to a Workflow SDK module (its default export must be the compiled workflow returned by defineWorkflow()). When set, --nodes / --form-fields are sourced from the compiled output.")
|
|
89
|
+
.option("--workflow-uuid <uuid>", "Target workflow UUID. Required without --file; with --file, defaults to the existing workflow whose template.slug matches the compiled slug.")
|
|
90
|
+
.option("--version <version>", "Release version (e.g. '1.2.0'). With --file, defaults to the next minor bump over the latest existing release; otherwise required by the engine.")
|
|
91
|
+
.option("--nodes <json>", "Nodes (JSON array of node definitions). Required without --file; rejected with --file.")
|
|
92
|
+
.option("--form-fields <json>", "Form fields (JSON array, or 'null'). Required without --file; rejected with --file.")
|
|
93
|
+
.option("--description <text>", "Release description (with --file, defaults to the compiled workflow's description).")
|
|
94
|
+
.option("--options <json>", "Options (JSON object)")
|
|
95
|
+
.option("--dry-run", "With --file: compile and print the nodes + form fields without deploying. Ignored without --file.")
|
|
96
|
+
.action(async (opts) => {
|
|
97
|
+
if (opts.file !== undefined) {
|
|
98
|
+
await runFileDeploy(getApi, opts);
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
await runJsonDeploy(getApi, opts);
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
// ---------- raw-JSON path (legacy `draft-release deploy`) ----------
|
|
105
|
+
async function runJsonDeploy(getApi, opts) {
|
|
106
|
+
if (opts.workflowUuid === undefined) {
|
|
107
|
+
failWith("--workflow-uuid is required when --file is not set", {
|
|
108
|
+
code: ExitCodes.InvalidUsage,
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
if (opts.nodes === undefined) {
|
|
112
|
+
failWith("--nodes is required when --file is not set", {
|
|
113
|
+
code: ExitCodes.InvalidUsage,
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
if (opts.formFields === undefined) {
|
|
117
|
+
failWith("--form-fields is required when --file is not set", {
|
|
118
|
+
code: ExitCodes.InvalidUsage,
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
// Pull required values into locals so the narrowing survives the closure
|
|
122
|
+
// we hand to `handleApiCall` below.
|
|
123
|
+
const workflowUuid = opts.workflowUuid;
|
|
124
|
+
const nodesJson = opts.nodes;
|
|
125
|
+
const formFieldsJson = opts.formFields;
|
|
126
|
+
const api = getApi();
|
|
127
|
+
const result = await handleApiCall(() => api.orchestration.draftRelease.deploy({
|
|
128
|
+
workflowUuid,
|
|
129
|
+
version: opts.version,
|
|
130
|
+
nodes: parseJson(nodesJson, "--nodes"),
|
|
131
|
+
formFields: formFieldsJson === "null"
|
|
132
|
+
? null
|
|
133
|
+
: parseJson(formFieldsJson, "--form-fields"),
|
|
134
|
+
description: opts.description,
|
|
135
|
+
options: opts.options !== undefined
|
|
136
|
+
? parseJson(opts.options, "--options")
|
|
137
|
+
: undefined,
|
|
138
|
+
}));
|
|
139
|
+
outputJson(result);
|
|
140
|
+
}
|
|
141
|
+
// ---------- SDK-file path (replaces `workflow deploy <file>`) ----------
|
|
142
|
+
async function runFileDeploy(getApi, opts) {
|
|
143
|
+
if (opts.file === undefined) {
|
|
144
|
+
failWith("--file is required for SDK deploy", {
|
|
145
|
+
code: ExitCodes.InvalidUsage,
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
if (opts.nodes !== undefined) {
|
|
149
|
+
failWith("--nodes is not allowed with --file (sourced from the module)", {
|
|
150
|
+
code: ExitCodes.InvalidUsage,
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
if (opts.formFields !== undefined) {
|
|
154
|
+
failWith("--form-fields is not allowed with --file (sourced from the module)", { code: ExitCodes.InvalidUsage });
|
|
155
|
+
}
|
|
156
|
+
const compiled = await loadCompiledWorkflow(opts.file);
|
|
157
|
+
if (opts.dryRun === true) {
|
|
158
|
+
outputJson({
|
|
159
|
+
slug: compiled.slug,
|
|
160
|
+
description: compiled.description,
|
|
161
|
+
nodes: compiled.nodes,
|
|
162
|
+
formFields: compiled.formFields,
|
|
163
|
+
});
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
const api = getApi();
|
|
167
|
+
const workflowUuid = await resolveWorkflowUuid(api, compiled, opts.workflowUuid);
|
|
168
|
+
const version = opts.version !== undefined
|
|
169
|
+
? opts.version
|
|
170
|
+
: await computeNextVersion(api, workflowUuid);
|
|
171
|
+
const description = opts.description !== undefined ? opts.description : compiled.description;
|
|
172
|
+
info(`Deploying "${compiled.slug}" → workflow ${workflowUuid} as v${version} (${String(compiled.nodes.length)} node(s))…`);
|
|
173
|
+
const payload = {
|
|
174
|
+
workflowUuid,
|
|
175
|
+
version,
|
|
176
|
+
nodes: compiled.nodes,
|
|
177
|
+
formFields: compiled.formFields,
|
|
178
|
+
description,
|
|
179
|
+
options: opts.options !== undefined
|
|
180
|
+
? parseJson(opts.options, "--options")
|
|
181
|
+
: undefined,
|
|
182
|
+
};
|
|
183
|
+
const result = await handleApiCall(() => api.orchestration.draftRelease.deploy(payload));
|
|
184
|
+
success(`Deployed v${version}.`);
|
|
185
|
+
outputJson(result);
|
|
186
|
+
}
|
|
187
|
+
// Load a workflow module via the tsx ESM loader so `.ts` sources (and their
|
|
188
|
+
// imports of `@cargo-ai/workflow-sdk` / `zod`) are transpiled on the fly,
|
|
189
|
+
// returning its default export validated as a compiled workflow.
|
|
190
|
+
async function loadCompiledWorkflow(file) {
|
|
191
|
+
const absPath = isAbsolute(file) ? file : resolve(process.cwd(), file);
|
|
192
|
+
if (!existsSync(absPath)) {
|
|
193
|
+
failWith(`Workflow file not found: ${absPath}`, {
|
|
194
|
+
code: ExitCodes.InvalidUsage,
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
let mod;
|
|
198
|
+
try {
|
|
199
|
+
const { tsImport } = await import("tsx/esm/api");
|
|
200
|
+
mod = (await tsImport(pathToFileURL(absPath).href, import.meta.url));
|
|
201
|
+
}
|
|
202
|
+
catch (error) {
|
|
203
|
+
failWith(`Failed to load workflow module: ${error instanceof Error ? error.message : String(error)}`, { code: ExitCodes.GenericError });
|
|
204
|
+
}
|
|
205
|
+
const candidate = resolveDefaultExport(mod);
|
|
206
|
+
if (!isCompiledWorkflow(candidate)) {
|
|
207
|
+
failWith("Workflow module must `export default` a compiled workflow (the value returned by defineWorkflow()).", { code: ExitCodes.InvalidUsage });
|
|
208
|
+
}
|
|
209
|
+
return candidate;
|
|
210
|
+
}
|
|
211
|
+
// Peel the extra interop layer tsx adds when a TS source is transpiled to
|
|
212
|
+
// CJS: the ESM namespace's `default` is then the CJS `module.exports`
|
|
213
|
+
// (`{ __esModule: true, default: … }`), so the real value lives one level
|
|
214
|
+
// deeper. True-ESM modules expose it directly.
|
|
215
|
+
function resolveDefaultExport(mod) {
|
|
216
|
+
const top = mod.default;
|
|
217
|
+
if (top !== null && typeof top === "object") {
|
|
218
|
+
const inner = top;
|
|
219
|
+
if (inner["__esModule"] === true && "default" in inner) {
|
|
220
|
+
return inner["default"];
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
return top;
|
|
224
|
+
}
|
|
225
|
+
function isCompiledWorkflow(value) {
|
|
226
|
+
if (value === null || typeof value !== "object")
|
|
227
|
+
return false;
|
|
228
|
+
const v = value;
|
|
229
|
+
return (typeof v["slug"] === "string" &&
|
|
230
|
+
Array.isArray(v["nodes"]) &&
|
|
231
|
+
Array.isArray(v["formFields"]));
|
|
232
|
+
}
|
|
233
|
+
// Resolve the target workflow UUID. The platform `Workflow` has no free-form
|
|
234
|
+
// slug field — the closest stable identifier is `template.slug` — and there
|
|
235
|
+
// is no `workflow.create` endpoint, so an explicit `--workflow-uuid` always
|
|
236
|
+
// wins and slug matching is a best-effort convenience over existing
|
|
237
|
+
// workflows only.
|
|
238
|
+
async function resolveWorkflowUuid(api, compiled, explicitUuid) {
|
|
239
|
+
if (explicitUuid !== undefined)
|
|
240
|
+
return explicitUuid;
|
|
241
|
+
const { workflows } = await handleApiCall(() => api.orchestration.workflow.all());
|
|
242
|
+
const matches = workflows.filter((w) => {
|
|
243
|
+
const template = w.template;
|
|
244
|
+
return (template !== null &&
|
|
245
|
+
template !== undefined &&
|
|
246
|
+
template.slug === compiled.slug);
|
|
247
|
+
});
|
|
248
|
+
if (matches.length === 1) {
|
|
249
|
+
const match = matches[0];
|
|
250
|
+
if (match !== undefined) {
|
|
251
|
+
info(`Matched workflow ${match.uuid} by slug "${compiled.slug}".`);
|
|
252
|
+
return match.uuid;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
if (matches.length > 1) {
|
|
256
|
+
failWith(`Multiple workflows match slug "${compiled.slug}". Pass --workflow-uuid to disambiguate.`, {
|
|
257
|
+
code: ExitCodes.InvalidUsage,
|
|
258
|
+
extra: { candidates: matches.map((w) => w.uuid) },
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
failWith(`No workflow matched slug "${compiled.slug}". Create the workflow in the app first (there is no create endpoint), then deploy with --workflow-uuid <uuid>.`, { code: ExitCodes.NotFound });
|
|
262
|
+
}
|
|
263
|
+
// Derive the next release version by bumping the minor of the highest
|
|
264
|
+
// existing semver, or `1.0.0` when there are no prior releases.
|
|
265
|
+
async function computeNextVersion(api, workflowUuid) {
|
|
266
|
+
const { releases } = await handleApiCall(() => api.orchestration.release.list({ workflowUuid }));
|
|
267
|
+
let best;
|
|
268
|
+
for (const release of releases) {
|
|
269
|
+
const parsed = parseSemver(release.version);
|
|
270
|
+
if (parsed === undefined)
|
|
271
|
+
continue;
|
|
272
|
+
if (best === undefined || compareSemver(parsed, best) > 0) {
|
|
273
|
+
best = parsed;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
if (best === undefined)
|
|
277
|
+
return "1.0.0";
|
|
278
|
+
return `${String(best[0])}.${String(best[1] + 1)}.0`;
|
|
279
|
+
}
|
|
280
|
+
function parseSemver(value) {
|
|
281
|
+
if (value === null || value === undefined)
|
|
282
|
+
return undefined;
|
|
283
|
+
const match = /^(\d+)\.(\d+)\.(\d+)$/.exec(value.trim());
|
|
284
|
+
if (match === null)
|
|
285
|
+
return undefined;
|
|
286
|
+
return [Number(match[1]), Number(match[2]), Number(match[3])];
|
|
287
|
+
}
|
|
288
|
+
function compareSemver(a, b) {
|
|
289
|
+
if (a[0] !== b[0])
|
|
290
|
+
return a[0] - b[0];
|
|
291
|
+
if (a[1] !== b[1])
|
|
292
|
+
return a[1] - b[1];
|
|
293
|
+
return a[2] - b[2];
|
|
40
294
|
}
|
|
@@ -92,11 +92,11 @@ export function registerModelCommands(parent, getApi) {
|
|
|
92
92
|
outputJson(result);
|
|
93
93
|
});
|
|
94
94
|
model
|
|
95
|
-
.command("
|
|
96
|
-
.description("
|
|
95
|
+
.command("refresh <uuid>")
|
|
96
|
+
.description("Refresh a model")
|
|
97
97
|
.action(async (uuid) => {
|
|
98
98
|
const api = getApi();
|
|
99
|
-
const result = await handleApiCall(() => api.storage.model.
|
|
99
|
+
const result = await handleApiCall(() => api.storage.model.refresh(uuid));
|
|
100
100
|
outputJson(result);
|
|
101
101
|
});
|
|
102
102
|
model
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/workflow/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAMxC,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,OAAO,EACf,MAAM,EAAE,MAAM,GAAG,GAChB,IAAI,CAMN"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { registerSyncCommand } from "./sync.js";
|
|
2
|
+
// SDK deploy lives under `cargo-ai orchestration release deploy-draft --file
|
|
3
|
+
// <path>` (alongside the raw-JSON deploy path), so this group only ships the
|
|
4
|
+
// `sync` developer tool today.
|
|
5
|
+
export function registerWorkflowCommands(parent, getApi) {
|
|
6
|
+
const workflow = parent
|
|
7
|
+
.command("workflow")
|
|
8
|
+
.description("Workflow SDK developer tools (type sync, codegen)");
|
|
9
|
+
registerSyncCommand(workflow, getApi);
|
|
10
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fixed input shape of every agent node. Matches the SDK's `AgentInput`
|
|
3
|
+
* type and the engine's `AiUtils.agentConfig` schema.
|
|
4
|
+
*/
|
|
5
|
+
export declare const AGENT_INPUT_TYPE_SRC: string;
|
|
6
|
+
/**
|
|
7
|
+
* Print an integration action's JSON Schema config as a TS input type.
|
|
8
|
+
* Returns `"Record<string, unknown>"` when the schema is missing or not an
|
|
9
|
+
* object schema we can render.
|
|
10
|
+
*/
|
|
11
|
+
export declare function printJsonSchemaInput(schema: unknown): string;
|
|
12
|
+
/**
|
|
13
|
+
* Print a tool release's `formFields` as a TS input type. Returns
|
|
14
|
+
* `undefined` when the fields can't be interpreted (caller falls back to
|
|
15
|
+
* `Record<string, unknown>`).
|
|
16
|
+
*/
|
|
17
|
+
export declare function printFormFieldsInput(formFields: unknown): string | undefined;
|
|
18
|
+
//# sourceMappingURL=inputTypes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inputTypes.d.ts","sourceRoot":"","sources":["../../../src/commands/workflow/inputTypes.ts"],"names":[],"mappings":"AAgCA;;;GAGG;AACH,eAAO,MAAM,oBAAoB,QAE+D,CAAC;AAEjG;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,CAM5D;AAgGD;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAU5E"}
|