@cargo-ai/cli 1.0.15 → 1.0.16
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 +2 -1
- package/build/commands/connection/customIntegration.d.ts +4 -0
- package/build/commands/connection/customIntegration.d.ts.map +1 -0
- package/build/commands/connection/customIntegration.js +98 -0
- package/build/commands/connection/index.d.ts.map +1 -1
- package/build/commands/connection/index.js +2 -0
- package/build/commands/context/{skill.d.ts → graph.d.ts} +2 -2
- package/build/commands/context/graph.d.ts.map +1 -0
- package/build/commands/context/graph.js +14 -0
- package/build/commands/context/index.js +5 -5
- package/build/commands/context/runtime.d.ts +4 -0
- package/build/commands/context/runtime.d.ts.map +1 -0
- package/build/commands/context/runtime.js +80 -0
- package/build/commands/{orchestration/log.d.ts → hosting/app.d.ts} +2 -2
- package/build/commands/hosting/app.d.ts.map +1 -0
- package/build/commands/hosting/app.js +190 -0
- package/build/commands/hosting/deployment.d.ts +4 -0
- package/build/commands/hosting/deployment.d.ts.map +1 -0
- package/build/commands/hosting/deployment.js +125 -0
- package/build/commands/hosting/index.d.ts +4 -0
- package/build/commands/hosting/index.d.ts.map +1 -0
- package/build/commands/hosting/index.js +11 -0
- package/build/commands/hosting/templateUtils.d.ts +6 -0
- package/build/commands/hosting/templateUtils.d.ts.map +1 -0
- package/build/commands/hosting/templateUtils.js +30 -0
- package/build/commands/hosting/worker.d.ts +4 -0
- package/build/commands/hosting/worker.d.ts.map +1 -0
- package/build/commands/hosting/worker.js +174 -0
- package/build/commands/orchestration/index.d.ts.map +1 -1
- package/build/commands/orchestration/index.js +4 -2
- package/build/commands/orchestration/query.js +2 -2
- package/build/commands/{context/file.d.ts → orchestration/span.d.ts} +2 -2
- package/build/commands/orchestration/span.d.ts.map +1 -0
- package/build/commands/orchestration/{log.js → span.js} +8 -8
- package/build/commands/orchestration/trace.d.ts +4 -0
- package/build/commands/orchestration/trace.d.ts.map +1 -0
- package/build/commands/orchestration/trace.js +56 -0
- package/build/commands/storage/record.d.ts.map +1 -1
- package/build/commands/storage/record.js +51 -0
- package/build/index.js +2 -0
- package/package.json +5 -3
- package/build/commands/context/file.d.ts.map +0 -1
- package/build/commands/context/file.js +0 -39
- package/build/commands/context/skill.d.ts.map +0 -1
- package/build/commands/context/skill.js +0 -21
- package/build/commands/orchestration/log.d.ts.map +0 -1
package/README.md
CHANGED
|
@@ -112,7 +112,8 @@ cargo-ai orchestration workflow --help
|
|
|
112
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
113
|
| **user-management** | Current user (no workspace context) | `cargo-ai user-management user get-current` |
|
|
114
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,
|
|
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 '{}'` |
|
|
116
117
|
|
|
117
118
|
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.
|
|
118
119
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"customIntegration.d.ts","sourceRoot":"","sources":["../../../src/commands/connection/customIntegration.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAGxC,wBAAgB,iCAAiC,CAC/C,MAAM,EAAE,OAAO,EACf,MAAM,EAAE,MAAM,GAAG,GAChB,IAAI,CAqJN"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { handleApiCall, outputJson } from "../runHandler.js";
|
|
2
|
+
export function registerCustomIntegrationCommands(parent, getApi) {
|
|
3
|
+
const customIntegration = parent
|
|
4
|
+
.command("custom-integration")
|
|
5
|
+
.description("Manage custom integrations (external HTTP servers or worker-backed integrations)");
|
|
6
|
+
customIntegration
|
|
7
|
+
.command("list")
|
|
8
|
+
.description("List custom integrations in the current workspace")
|
|
9
|
+
.action(async () => {
|
|
10
|
+
const api = getApi();
|
|
11
|
+
const result = await handleApiCall(() => api.connection.customIntegration.list());
|
|
12
|
+
outputJson(result);
|
|
13
|
+
});
|
|
14
|
+
customIntegration
|
|
15
|
+
.command("get <uuid>")
|
|
16
|
+
.description("Get a custom integration by UUID")
|
|
17
|
+
.action(async (uuid) => {
|
|
18
|
+
const api = getApi();
|
|
19
|
+
const result = await handleApiCall(() => api.connection.customIntegration.get({ uuid }));
|
|
20
|
+
outputJson(result);
|
|
21
|
+
});
|
|
22
|
+
customIntegration
|
|
23
|
+
.command("create")
|
|
24
|
+
.description("Register a custom integration (kind=external for an externally hosted server, kind=worker for a Cargo Hosting worker)")
|
|
25
|
+
.requiredOption("--kind <kind>", 'Integration kind: "external" or "worker"')
|
|
26
|
+
.option("--base-url <url>", "Base URL of the externally hosted integration server (required when --kind external)")
|
|
27
|
+
.option("--worker-uuid <uuid>", "UUID of the Cargo Hosting worker that backs the integration (required when --kind worker)")
|
|
28
|
+
.addHelpText("after", `
|
|
29
|
+
Examples:
|
|
30
|
+
$ cargo-ai connection custom-integration create --kind external --base-url https://abc123.ngrok.io
|
|
31
|
+
$ cargo-ai connection custom-integration create --kind worker --worker-uuid 11111111-2222-3333-4444-555555555555`)
|
|
32
|
+
.action(async (opts) => {
|
|
33
|
+
if (opts.kind !== "external" && opts.kind !== "worker") {
|
|
34
|
+
console.error(JSON.stringify({
|
|
35
|
+
error: `Invalid --kind "${opts.kind}". Expected "external" or "worker".`,
|
|
36
|
+
}));
|
|
37
|
+
process.exit(1);
|
|
38
|
+
}
|
|
39
|
+
if (opts.kind === "external" && opts.baseUrl === undefined) {
|
|
40
|
+
console.error(JSON.stringify({
|
|
41
|
+
error: "--base-url is required when --kind is external.",
|
|
42
|
+
}));
|
|
43
|
+
process.exit(1);
|
|
44
|
+
}
|
|
45
|
+
if (opts.kind === "worker" && opts.workerUuid === undefined) {
|
|
46
|
+
console.error(JSON.stringify({
|
|
47
|
+
error: "--worker-uuid is required when --kind is worker.",
|
|
48
|
+
}));
|
|
49
|
+
process.exit(1);
|
|
50
|
+
}
|
|
51
|
+
const api = getApi();
|
|
52
|
+
const result = await handleApiCall(() => opts.kind === "external"
|
|
53
|
+
? api.connection.customIntegration.create({
|
|
54
|
+
kind: "external",
|
|
55
|
+
baseUrl: opts.baseUrl,
|
|
56
|
+
})
|
|
57
|
+
: api.connection.customIntegration.create({
|
|
58
|
+
kind: "worker",
|
|
59
|
+
workerUuid: opts.workerUuid,
|
|
60
|
+
}));
|
|
61
|
+
outputJson(result);
|
|
62
|
+
});
|
|
63
|
+
customIntegration
|
|
64
|
+
.command("update")
|
|
65
|
+
.description("Update a custom integration's base URL or worker (kind cannot change)")
|
|
66
|
+
.requiredOption("--uuid <uuid>", "Custom integration UUID")
|
|
67
|
+
.option("--base-url <url>", "New base URL (only valid when the integration was created with kind=external)")
|
|
68
|
+
.option("--worker-uuid <uuid>", "New worker UUID (only valid when the integration was created with kind=worker)")
|
|
69
|
+
.action(async (opts) => {
|
|
70
|
+
if (opts.baseUrl === undefined && opts.workerUuid === undefined) {
|
|
71
|
+
console.error(JSON.stringify({
|
|
72
|
+
error: "Provide at least one of --base-url or --worker-uuid.",
|
|
73
|
+
}));
|
|
74
|
+
process.exit(1);
|
|
75
|
+
}
|
|
76
|
+
if (opts.baseUrl !== undefined && opts.workerUuid !== undefined) {
|
|
77
|
+
console.error(JSON.stringify({
|
|
78
|
+
error: "--base-url and --worker-uuid are mutually exclusive.",
|
|
79
|
+
}));
|
|
80
|
+
process.exit(1);
|
|
81
|
+
}
|
|
82
|
+
const api = getApi();
|
|
83
|
+
const result = await handleApiCall(() => api.connection.customIntegration.update({
|
|
84
|
+
uuid: opts.uuid,
|
|
85
|
+
baseUrl: opts.baseUrl,
|
|
86
|
+
workerUuid: opts.workerUuid,
|
|
87
|
+
}));
|
|
88
|
+
outputJson(result);
|
|
89
|
+
});
|
|
90
|
+
customIntegration
|
|
91
|
+
.command("remove <uuid>")
|
|
92
|
+
.description("Remove a custom integration")
|
|
93
|
+
.action(async (uuid) => {
|
|
94
|
+
const api = getApi();
|
|
95
|
+
await handleApiCall(() => api.connection.customIntegration.remove(uuid));
|
|
96
|
+
outputJson({ ok: true });
|
|
97
|
+
});
|
|
98
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/connection/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/connection/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAMxC,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,OAAO,EACf,MAAM,EAAE,MAAM,GAAG,GAChB,IAAI,CASN"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { registerConnectorCommands } from "./connector.js";
|
|
2
|
+
import { registerCustomIntegrationCommands } from "./customIntegration.js";
|
|
2
3
|
import { registerIntegrationCommands } from "./integration.js";
|
|
3
4
|
import { registerNativeIntegrationCommands } from "./nativeIntegration.js";
|
|
4
5
|
export function registerConnectionCommands(parent, getApi) {
|
|
@@ -8,4 +9,5 @@ export function registerConnectionCommands(parent, getApi) {
|
|
|
8
9
|
registerConnectorCommands(connection, getApi);
|
|
9
10
|
registerIntegrationCommands(connection, getApi);
|
|
10
11
|
registerNativeIntegrationCommands(connection, getApi);
|
|
12
|
+
registerCustomIntegrationCommands(connection, getApi);
|
|
11
13
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { Command } from "commander";
|
|
2
2
|
import type { Api } from "../../api.js";
|
|
3
|
-
export declare function
|
|
4
|
-
//# sourceMappingURL=
|
|
3
|
+
export declare function registerGraphCommands(parent: Command, getApi: () => Api): void;
|
|
4
|
+
//# sourceMappingURL=graph.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graph.d.ts","sourceRoot":"","sources":["../../../src/commands/context/graph.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAGxC,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,OAAO,EACf,MAAM,EAAE,MAAM,GAAG,GAChB,IAAI,CAeN"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { handleApiCall, outputJson } from "../runHandler.js";
|
|
2
|
+
export function registerGraphCommands(parent, getApi) {
|
|
3
|
+
const graph = parent
|
|
4
|
+
.command("graph")
|
|
5
|
+
.description("Inspect the context knowledge graph for the workspace");
|
|
6
|
+
graph
|
|
7
|
+
.command("get")
|
|
8
|
+
.description("Build (or load from cache) the knowledge graph of all markdown/MDX files in the context repo")
|
|
9
|
+
.action(async () => {
|
|
10
|
+
const api = getApi();
|
|
11
|
+
const result = await handleApiCall(() => api.context.graph.get());
|
|
12
|
+
outputJson(result);
|
|
13
|
+
});
|
|
14
|
+
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { registerGraphCommands } from "./graph.js";
|
|
2
2
|
import { registerRepositoryCommands } from "./repository.js";
|
|
3
|
-
import {
|
|
3
|
+
import { registerRuntimeCommands } from "./runtime.js";
|
|
4
4
|
export function registerContextCommands(parent, getApi) {
|
|
5
5
|
const context = parent
|
|
6
6
|
.command("context")
|
|
7
|
-
.description("Context repository
|
|
7
|
+
.description("Context repository and runtime sandbox operations");
|
|
8
8
|
registerRepositoryCommands(context, getApi);
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
registerRuntimeCommands(context, getApi);
|
|
10
|
+
registerGraphCommands(context, getApi);
|
|
11
11
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../../src/commands/context/runtime.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,CAmIN"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { handleApiCall, outputJson } from "../runHandler.js";
|
|
2
|
+
export function registerRuntimeCommands(parent, getApi) {
|
|
3
|
+
const runtime = parent
|
|
4
|
+
.command("runtime")
|
|
5
|
+
.description("Read, write, edit, browse, and execute against the workspace runtime sandbox");
|
|
6
|
+
runtime
|
|
7
|
+
.command("browse")
|
|
8
|
+
.description("List entries in the runtime sandbox")
|
|
9
|
+
.option("--path <path>", "Path to browse (omit to browse the root)")
|
|
10
|
+
.action(async (opts) => {
|
|
11
|
+
const api = getApi();
|
|
12
|
+
const result = await handleApiCall(() => api.context.runtime.browse({ path: opts.path }));
|
|
13
|
+
outputJson(result);
|
|
14
|
+
});
|
|
15
|
+
runtime
|
|
16
|
+
.command("read")
|
|
17
|
+
.description("Read a file from the runtime sandbox")
|
|
18
|
+
.requiredOption("--path <path>", "Path to the file")
|
|
19
|
+
.option("--start-line <line>", "1-indexed inclusive start line (defaults to first line)")
|
|
20
|
+
.option("--end-line <line>", "1-indexed inclusive end line (defaults to last line)")
|
|
21
|
+
.action(async (opts) => {
|
|
22
|
+
const api = getApi();
|
|
23
|
+
const startLine = opts.startLine !== undefined ? Number(opts.startLine) : undefined;
|
|
24
|
+
const endLine = opts.endLine !== undefined ? Number(opts.endLine) : undefined;
|
|
25
|
+
const result = await handleApiCall(() => api.context.runtime.read({
|
|
26
|
+
path: opts.path,
|
|
27
|
+
startLine,
|
|
28
|
+
endLine,
|
|
29
|
+
}));
|
|
30
|
+
outputJson(result);
|
|
31
|
+
});
|
|
32
|
+
runtime
|
|
33
|
+
.command("write")
|
|
34
|
+
.description("Write a file in the runtime sandbox and push to the default branch")
|
|
35
|
+
.requiredOption("--path <path>", "Path to the file")
|
|
36
|
+
.requiredOption("--content <content>", "File content")
|
|
37
|
+
.option("--commit-message <message>", "Commit message override")
|
|
38
|
+
.action(async (opts) => {
|
|
39
|
+
const api = getApi();
|
|
40
|
+
const result = await handleApiCall(() => api.context.runtime.write({
|
|
41
|
+
path: opts.path,
|
|
42
|
+
content: opts.content,
|
|
43
|
+
commitMessage: opts.commitMessage,
|
|
44
|
+
}));
|
|
45
|
+
outputJson(result);
|
|
46
|
+
});
|
|
47
|
+
runtime
|
|
48
|
+
.command("edit")
|
|
49
|
+
.description("Replace a single occurrence of oldString with newString and push to the default branch")
|
|
50
|
+
.requiredOption("--path <path>", "Path to the file")
|
|
51
|
+
.requiredOption("--old-string <old>", "Exact substring to replace (must occur once)")
|
|
52
|
+
.requiredOption("--new-string <new>", "Replacement string (may be empty to delete the match)")
|
|
53
|
+
.option("--commit-message <message>", "Commit message override")
|
|
54
|
+
.action(async (opts) => {
|
|
55
|
+
const api = getApi();
|
|
56
|
+
const result = await handleApiCall(() => api.context.runtime.edit({
|
|
57
|
+
path: opts.path,
|
|
58
|
+
oldString: opts.oldString,
|
|
59
|
+
newString: opts.newString,
|
|
60
|
+
commitMessage: opts.commitMessage,
|
|
61
|
+
}));
|
|
62
|
+
outputJson(result);
|
|
63
|
+
});
|
|
64
|
+
runtime
|
|
65
|
+
.command("execute")
|
|
66
|
+
.description("Run a shell command in the runtime sandbox (changes are NOT pushed to GitHub)")
|
|
67
|
+
.requiredOption("--command <command>", "Shell command to run")
|
|
68
|
+
.option("--args <json>", "JSON array of arguments")
|
|
69
|
+
.action(async (opts) => {
|
|
70
|
+
const api = getApi();
|
|
71
|
+
const args = opts.args !== undefined
|
|
72
|
+
? JSON.parse(opts.args)
|
|
73
|
+
: undefined;
|
|
74
|
+
const result = await handleApiCall(() => api.context.runtime.execute({
|
|
75
|
+
command: opts.command,
|
|
76
|
+
args,
|
|
77
|
+
}));
|
|
78
|
+
outputJson(result);
|
|
79
|
+
});
|
|
80
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { Command } from "commander";
|
|
2
2
|
import type { Api } from "../../api.js";
|
|
3
|
-
export declare function
|
|
4
|
-
//# sourceMappingURL=
|
|
3
|
+
export declare function registerAppCommands(parent: Command, getApi: () => Api): void;
|
|
4
|
+
//# sourceMappingURL=app.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../../../src/commands/hosting/app.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAMxC,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,GAAG,IAAI,CAsO5E"}
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import { promises as fs } from "node:fs";
|
|
2
|
+
import { createRequire } from "node:module";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { handleApiCall, outputJson } from "../runHandler.js";
|
|
6
|
+
import { copyDirectory, listTemplates } from "./templateUtils.js";
|
|
7
|
+
const require = createRequire(import.meta.url);
|
|
8
|
+
export function registerAppCommands(parent, getApi) {
|
|
9
|
+
const app = parent
|
|
10
|
+
.command("app")
|
|
11
|
+
.description("Manage Cargo Hosting apps (Vite SPAs served on *.cargo.app)");
|
|
12
|
+
app
|
|
13
|
+
.command("list")
|
|
14
|
+
.description("List apps in the current workspace")
|
|
15
|
+
.option("--folder-uuid <uuid>", "Filter by folder UUID")
|
|
16
|
+
.action(async (opts) => {
|
|
17
|
+
const api = getApi();
|
|
18
|
+
const result = await handleApiCall(() => api.hosting.app.list({
|
|
19
|
+
folderUuid: opts.folderUuid,
|
|
20
|
+
}));
|
|
21
|
+
outputJson(result);
|
|
22
|
+
});
|
|
23
|
+
app
|
|
24
|
+
.command("get <uuid>")
|
|
25
|
+
.description("Show details of a single app")
|
|
26
|
+
.action(async (uuid) => {
|
|
27
|
+
const api = getApi();
|
|
28
|
+
const result = await handleApiCall(() => api.hosting.app.get(uuid));
|
|
29
|
+
outputJson(result);
|
|
30
|
+
});
|
|
31
|
+
app
|
|
32
|
+
.command("create")
|
|
33
|
+
.description("Create a new app slot")
|
|
34
|
+
.requiredOption("--name <name>", "Display name for the app")
|
|
35
|
+
.requiredOption("--slug <slug>", "URL slug (must be globally unique within the hosting domain)")
|
|
36
|
+
.option("--folder-uuid <uuid>", "Optional folder UUID")
|
|
37
|
+
.action(async (opts) => {
|
|
38
|
+
const api = getApi();
|
|
39
|
+
const result = await handleApiCall(() => api.hosting.app.create({
|
|
40
|
+
name: opts.name,
|
|
41
|
+
slug: opts.slug,
|
|
42
|
+
folderUuid: opts.folderUuid,
|
|
43
|
+
}));
|
|
44
|
+
outputJson(result);
|
|
45
|
+
});
|
|
46
|
+
app
|
|
47
|
+
.command("update")
|
|
48
|
+
.description("Update an existing app (name, folder)")
|
|
49
|
+
.requiredOption("--uuid <uuid>", "App UUID")
|
|
50
|
+
.option("--name <name>", "New display name")
|
|
51
|
+
.option("--folder-uuid <uuid>", "New folder UUID (pass 'null' to move to the workspace root)")
|
|
52
|
+
.action(async (opts) => {
|
|
53
|
+
const api = getApi();
|
|
54
|
+
const result = await handleApiCall(() => api.hosting.app.update({
|
|
55
|
+
uuid: opts.uuid,
|
|
56
|
+
name: opts.name,
|
|
57
|
+
folderUuid: opts.folderUuid === "null" ? null : opts.folderUuid,
|
|
58
|
+
}));
|
|
59
|
+
outputJson(result);
|
|
60
|
+
});
|
|
61
|
+
app
|
|
62
|
+
.command("remove <uuid>")
|
|
63
|
+
.description("Remove an app (also removes its deployments)")
|
|
64
|
+
.action(async (uuid) => {
|
|
65
|
+
const api = getApi();
|
|
66
|
+
await handleApiCall(() => api.hosting.app.remove(uuid));
|
|
67
|
+
outputJson({ ok: true });
|
|
68
|
+
});
|
|
69
|
+
app
|
|
70
|
+
.command("env <appUuid>")
|
|
71
|
+
.description("Print the .env.local lines a local copy of the app needs (Cargo OAuth + workspace + app UUID + API URL).")
|
|
72
|
+
.option("--api-url <url>", "Override the API URL written to the .env (default: https://api.getcargo.io)")
|
|
73
|
+
.action(async (appUuid, opts) => {
|
|
74
|
+
const api = getApi();
|
|
75
|
+
const { app: resolvedApp } = await handleApiCall(() => api.hosting.app.get(appUuid));
|
|
76
|
+
const lines = [
|
|
77
|
+
"# Generated by `cargo-ai hosting app env`. Do not commit secrets.",
|
|
78
|
+
"VITE_CARGO_OAUTH_DOMAIN=<set-by-cargo-hosting-at-deploy-time>",
|
|
79
|
+
"VITE_CARGO_OAUTH_CLIENT_ID=<set-by-cargo-hosting-at-deploy-time>",
|
|
80
|
+
"VITE_CARGO_OAUTH_AUDIENCE=<set-by-cargo-hosting-at-deploy-time>",
|
|
81
|
+
`VITE_CARGO_API_URL=${opts.apiUrl !== undefined ? opts.apiUrl : "https://api.getcargo.io"}`,
|
|
82
|
+
`VITE_CARGO_WORKSPACE_UUID=${resolvedApp.workspaceUuid}`,
|
|
83
|
+
`VITE_CARGO_APP_UUID=${resolvedApp.uuid}`,
|
|
84
|
+
"VITE_CARGO_DEPLOYMENT_UUID=<set-by-cargo-hosting-at-deploy-time>",
|
|
85
|
+
"VITE_APP_BASE_PATH=/",
|
|
86
|
+
"",
|
|
87
|
+
];
|
|
88
|
+
process.stdout.write(lines.join("\n"));
|
|
89
|
+
});
|
|
90
|
+
app
|
|
91
|
+
.command("init <directory>")
|
|
92
|
+
.description("Scaffold a new Cargo Hosting app locally from a template (Vite + @cargo-ai/app-sdk).")
|
|
93
|
+
.option("--template <slug>", "Template slug (default: blank)", "blank")
|
|
94
|
+
.option("--name <name>", "App name written into package.json (default: directory name)")
|
|
95
|
+
.option("--list-templates", "Print available templates and exit")
|
|
96
|
+
.action(async (directory, opts) => {
|
|
97
|
+
const templatesRoot = findTemplatesRoot();
|
|
98
|
+
if (opts.listTemplates === true) {
|
|
99
|
+
const slugs = await listTemplates(templatesRoot);
|
|
100
|
+
if (slugs.length === 0) {
|
|
101
|
+
console.error(JSON.stringify({ error: "No templates found", templatesRoot }));
|
|
102
|
+
process.exit(1);
|
|
103
|
+
}
|
|
104
|
+
console.log(JSON.stringify(slugs.map((slug) => ({
|
|
105
|
+
slug,
|
|
106
|
+
description: TEMPLATE_DESCRIPTIONS[slug] !== undefined
|
|
107
|
+
? TEMPLATE_DESCRIPTIONS[slug]
|
|
108
|
+
: "",
|
|
109
|
+
})), null, 2));
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
const templateDir = path.join(templatesRoot, opts.template);
|
|
113
|
+
try {
|
|
114
|
+
const stat = await fs.stat(templateDir);
|
|
115
|
+
if (stat.isDirectory() === false) {
|
|
116
|
+
throw new Error("Template path is not a directory");
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
catch {
|
|
120
|
+
const slugs = await listTemplates(templatesRoot);
|
|
121
|
+
console.error(JSON.stringify({
|
|
122
|
+
error: `Unknown template "${opts.template}"`,
|
|
123
|
+
available: slugs,
|
|
124
|
+
}));
|
|
125
|
+
process.exit(1);
|
|
126
|
+
}
|
|
127
|
+
const targetDir = path.resolve(directory);
|
|
128
|
+
try {
|
|
129
|
+
const stat = await fs.stat(targetDir);
|
|
130
|
+
if (stat.isDirectory() === true) {
|
|
131
|
+
const entries = await fs.readdir(targetDir);
|
|
132
|
+
if (entries.length > 0) {
|
|
133
|
+
console.error(JSON.stringify({
|
|
134
|
+
error: `Target directory ${targetDir} is not empty.`,
|
|
135
|
+
}));
|
|
136
|
+
process.exit(1);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
// Target does not exist yet — that's fine.
|
|
142
|
+
}
|
|
143
|
+
const appName = opts.name !== undefined ? opts.name : path.basename(targetDir);
|
|
144
|
+
await copyDirectory(path.join(templatesRoot, opts.template), targetDir, [
|
|
145
|
+
{ from: "__APP_NAME__", to: appName },
|
|
146
|
+
{ from: "__TEMPLATE_SLUG__", to: opts.template },
|
|
147
|
+
]);
|
|
148
|
+
console.log(JSON.stringify({
|
|
149
|
+
ok: true,
|
|
150
|
+
directory: targetDir,
|
|
151
|
+
template: opts.template,
|
|
152
|
+
name: appName,
|
|
153
|
+
nextSteps: [
|
|
154
|
+
`cd ${path.relative(process.cwd(), targetDir)}`,
|
|
155
|
+
"npm install",
|
|
156
|
+
"cargo-ai hosting app create --name '<App name>' --slug '<your-slug>'",
|
|
157
|
+
"cargo-ai hosting app env <appUuid> > .env.local",
|
|
158
|
+
"npm run dev",
|
|
159
|
+
],
|
|
160
|
+
}, null, 2));
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
const TEMPLATE_DESCRIPTIONS = {
|
|
164
|
+
blank: "Minimal Vite + refine app with one route, getCargoEnv() + CargoWorkspaceBadge wired (use as a starting point).",
|
|
165
|
+
"territories-overview": "Read-only grid of revenue organization territories. Demonstrates useCargoApi() + react-query + the SDK shadcn primitives.",
|
|
166
|
+
};
|
|
167
|
+
const findTemplatesRoot = () => {
|
|
168
|
+
// The CLI is published as `@cargo-ai/cli`. Templates live in
|
|
169
|
+
// `@cargo-ai/app-sdk/templates`. Resolve via require so we work whether the
|
|
170
|
+
// user installed both packages globally or both came from the monorepo.
|
|
171
|
+
try {
|
|
172
|
+
const appSdkPackageJson = require.resolve("@cargo-ai/app-sdk/package.json");
|
|
173
|
+
return path.join(path.dirname(appSdkPackageJson), "templates");
|
|
174
|
+
}
|
|
175
|
+
catch {
|
|
176
|
+
const here = fileURLToPath(import.meta.url);
|
|
177
|
+
let cursor = path.dirname(here);
|
|
178
|
+
for (let i = 0; i < 6; i += 1) {
|
|
179
|
+
const candidate = path.join(cursor, "packages/app-sdk/templates");
|
|
180
|
+
try {
|
|
181
|
+
require("node:fs").accessSync(candidate);
|
|
182
|
+
return candidate;
|
|
183
|
+
}
|
|
184
|
+
catch {
|
|
185
|
+
cursor = path.dirname(cursor);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
throw new Error("Could not locate @cargo-ai/app-sdk templates. Make sure @cargo-ai/app-sdk is installed alongside @cargo-ai/cli.");
|
|
189
|
+
}
|
|
190
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deployment.d.ts","sourceRoot":"","sources":["../../../src/commands/hosting/deployment.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAGxC,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,OAAO,EACf,MAAM,EAAE,MAAM,GAAG,GAChB,IAAI,CA6JN"}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { promises as fs } from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { handleApiCall, outputJson } from "../runHandler.js";
|
|
4
|
+
export function registerDeploymentCommands(parent, getApi) {
|
|
5
|
+
const deployment = parent
|
|
6
|
+
.command("deployment")
|
|
7
|
+
.description("Inspect, create, and promote deployments");
|
|
8
|
+
deployment
|
|
9
|
+
.command("list")
|
|
10
|
+
.description("List deployments for a given app or worker")
|
|
11
|
+
.option("--app-uuid <uuid>", "App UUID")
|
|
12
|
+
.option("--worker-uuid <uuid>", "Worker UUID")
|
|
13
|
+
.action(async (opts) => {
|
|
14
|
+
if (opts.appUuid === undefined && opts.workerUuid === undefined) {
|
|
15
|
+
console.error(JSON.stringify({
|
|
16
|
+
error: "Either --app-uuid or --worker-uuid must be provided.",
|
|
17
|
+
}));
|
|
18
|
+
process.exit(1);
|
|
19
|
+
}
|
|
20
|
+
const api = getApi();
|
|
21
|
+
const result = await handleApiCall(() => api.hosting.deployment.list({
|
|
22
|
+
appUuid: opts.appUuid,
|
|
23
|
+
workerUuid: opts.workerUuid,
|
|
24
|
+
}));
|
|
25
|
+
outputJson(result);
|
|
26
|
+
});
|
|
27
|
+
deployment
|
|
28
|
+
.command("get <uuid>")
|
|
29
|
+
.description("Show a single deployment's status and metadata")
|
|
30
|
+
.action(async (uuid) => {
|
|
31
|
+
const api = getApi();
|
|
32
|
+
const result = await handleApiCall(() => api.hosting.deployment.get(uuid));
|
|
33
|
+
outputJson(result);
|
|
34
|
+
});
|
|
35
|
+
deployment
|
|
36
|
+
.command("get-promoted")
|
|
37
|
+
.description("Show the currently promoted deployment for an app or worker")
|
|
38
|
+
.option("--app-uuid <uuid>", "App UUID")
|
|
39
|
+
.option("--worker-uuid <uuid>", "Worker UUID")
|
|
40
|
+
.action(async (opts) => {
|
|
41
|
+
if (opts.appUuid === undefined && opts.workerUuid === undefined) {
|
|
42
|
+
console.error(JSON.stringify({
|
|
43
|
+
error: "Either --app-uuid or --worker-uuid must be provided.",
|
|
44
|
+
}));
|
|
45
|
+
process.exit(1);
|
|
46
|
+
}
|
|
47
|
+
const api = getApi();
|
|
48
|
+
const result = await handleApiCall(() => api.hosting.deployment.getPromoted({
|
|
49
|
+
appUuid: opts.appUuid,
|
|
50
|
+
workerUuid: opts.workerUuid,
|
|
51
|
+
}));
|
|
52
|
+
outputJson(result);
|
|
53
|
+
});
|
|
54
|
+
deployment
|
|
55
|
+
.command("create")
|
|
56
|
+
.description("Create a new deployment by uploading a local source directory. For apps the backend runs `npm ci && vite build` in a sandbox; for workers it bundles the entrypoint.")
|
|
57
|
+
.option("--app-uuid <uuid>", "App UUID (mutually exclusive with --worker-uuid)")
|
|
58
|
+
.option("--worker-uuid <uuid>", "Worker UUID (mutually exclusive with --app-uuid)")
|
|
59
|
+
.requiredOption("--source <dir>", "Path to the source directory (typically the package root, not dist/)")
|
|
60
|
+
.option("--ignore <list>", "Comma-separated names to ignore (default: node_modules,dist,build,.git,.next)", "node_modules,dist,build,.git,.next")
|
|
61
|
+
.action(async (opts) => {
|
|
62
|
+
if ((opts.appUuid === undefined && opts.workerUuid === undefined) ||
|
|
63
|
+
(opts.appUuid !== undefined && opts.workerUuid !== undefined)) {
|
|
64
|
+
console.error(JSON.stringify({
|
|
65
|
+
error: "Exactly one of --app-uuid or --worker-uuid must be provided.",
|
|
66
|
+
}));
|
|
67
|
+
process.exit(1);
|
|
68
|
+
}
|
|
69
|
+
const api = getApi();
|
|
70
|
+
const sourceDir = path.resolve(opts.source);
|
|
71
|
+
const ignore = new Set(opts.ignore.split(",").map((entry) => entry.trim()));
|
|
72
|
+
const files = await collectFiles(sourceDir, { ignore });
|
|
73
|
+
if (files.length === 0) {
|
|
74
|
+
console.error(JSON.stringify({
|
|
75
|
+
error: `No files to deploy under ${sourceDir}`,
|
|
76
|
+
}));
|
|
77
|
+
process.exit(1);
|
|
78
|
+
}
|
|
79
|
+
const payload = opts.appUuid !== undefined
|
|
80
|
+
? { kind: "app", appUuid: opts.appUuid, files }
|
|
81
|
+
: {
|
|
82
|
+
kind: "worker",
|
|
83
|
+
workerUuid: opts.workerUuid,
|
|
84
|
+
files,
|
|
85
|
+
};
|
|
86
|
+
const result = await handleApiCall(() => api.hosting.deployment.create(payload));
|
|
87
|
+
outputJson({
|
|
88
|
+
...result,
|
|
89
|
+
stats: { fileCount: files.length },
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
deployment
|
|
93
|
+
.command("promote")
|
|
94
|
+
.description("Promote a deployment to the live URL")
|
|
95
|
+
.requiredOption("--uuid <uuid>", "Deployment UUID to promote")
|
|
96
|
+
.action(async (opts) => {
|
|
97
|
+
const api = getApi();
|
|
98
|
+
const result = await handleApiCall(() => api.hosting.deployment.promote({
|
|
99
|
+
uuid: opts.uuid,
|
|
100
|
+
}));
|
|
101
|
+
outputJson(result);
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
const collectFiles = async (rootDir, options) => {
|
|
105
|
+
const results = [];
|
|
106
|
+
const walk = async (dir, relative) => {
|
|
107
|
+
const entries = await fs.readdir(dir, { withFileTypes: true });
|
|
108
|
+
for (const entry of entries) {
|
|
109
|
+
if (options.ignore.has(entry.name)) {
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
const absolute = path.join(dir, entry.name);
|
|
113
|
+
const rel = relative.length === 0 ? entry.name : `${relative}/${entry.name}`;
|
|
114
|
+
if (entry.isDirectory() === true) {
|
|
115
|
+
await walk(absolute, rel);
|
|
116
|
+
}
|
|
117
|
+
else if (entry.isFile() === true) {
|
|
118
|
+
const content = await fs.readFile(absolute, "utf-8");
|
|
119
|
+
results.push({ path: rel, content });
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
await walk(rootDir, "");
|
|
124
|
+
return results;
|
|
125
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/hosting/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAKxC,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,OAAO,EACf,MAAM,EAAE,MAAM,GAAG,GAChB,IAAI,CAUN"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { registerAppCommands } from "./app.js";
|
|
2
|
+
import { registerDeploymentCommands } from "./deployment.js";
|
|
3
|
+
import { registerWorkerCommands } from "./worker.js";
|
|
4
|
+
export function registerHostingCommands(parent, getApi) {
|
|
5
|
+
const hosting = parent
|
|
6
|
+
.command("hosting")
|
|
7
|
+
.description("Cargo Hosting: apps (Vite SPAs), workers (edge HTTP handlers), and deployments");
|
|
8
|
+
registerAppCommands(hosting, getApi);
|
|
9
|
+
registerWorkerCommands(hosting, getApi);
|
|
10
|
+
registerDeploymentCommands(hosting, getApi);
|
|
11
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"templateUtils.d.ts","sourceRoot":"","sources":["../../../src/commands/hosting/templateUtils.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,aAAa,SAAgB,MAAM,KAAG,QAAQ,MAAM,EAAE,CAUlE,CAAC;AAEF,eAAO,MAAM,aAAa,QACnB,MAAM,QACL,MAAM,UACJ;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,EAAE,KACrC,QAAQ,IAAI,CAmBd,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { promises as fs } from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
export const listTemplates = async (root) => {
|
|
4
|
+
try {
|
|
5
|
+
const entries = await fs.readdir(root, { withFileTypes: true });
|
|
6
|
+
return entries
|
|
7
|
+
.filter((entry) => entry.isDirectory() === true)
|
|
8
|
+
.map((entry) => entry.name)
|
|
9
|
+
.filter((name) => name.startsWith("_") === false);
|
|
10
|
+
}
|
|
11
|
+
catch {
|
|
12
|
+
return [];
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
export const copyDirectory = async (src, dest, rename) => {
|
|
16
|
+
const entries = await fs.readdir(src, { withFileTypes: true });
|
|
17
|
+
await fs.mkdir(dest, { recursive: true });
|
|
18
|
+
for (const entry of entries) {
|
|
19
|
+
const srcPath = path.join(src, entry.name);
|
|
20
|
+
const destPath = path.join(dest, entry.name);
|
|
21
|
+
if (entry.isDirectory() === true) {
|
|
22
|
+
await copyDirectory(srcPath, destPath, rename);
|
|
23
|
+
}
|
|
24
|
+
else if (entry.isFile() === true) {
|
|
25
|
+
const raw = await fs.readFile(srcPath, "utf-8");
|
|
26
|
+
const replaced = rename.reduce((current, { from, to }) => current.split(from).join(to), raw);
|
|
27
|
+
await fs.writeFile(destPath, replaced, "utf-8");
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["../../../src/commands/hosting/worker.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAMxC,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,OAAO,EACf,MAAM,EAAE,MAAM,GAAG,GAChB,IAAI,CA8MN"}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import { promises as fs } from "node:fs";
|
|
2
|
+
import { createRequire } from "node:module";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { handleApiCall, outputJson } from "../runHandler.js";
|
|
6
|
+
import { copyDirectory, listTemplates } from "./templateUtils.js";
|
|
7
|
+
const require = createRequire(import.meta.url);
|
|
8
|
+
export function registerWorkerCommands(parent, getApi) {
|
|
9
|
+
const worker = parent
|
|
10
|
+
.command("worker")
|
|
11
|
+
.description("Manage Cargo Hosting workers (serverless HTTP handlers running on the edge)");
|
|
12
|
+
worker
|
|
13
|
+
.command("list")
|
|
14
|
+
.description("List workers in the current workspace")
|
|
15
|
+
.option("--folder-uuid <uuid>", "Filter by folder UUID")
|
|
16
|
+
.action(async (opts) => {
|
|
17
|
+
const api = getApi();
|
|
18
|
+
const result = await handleApiCall(() => api.hosting.worker.list({
|
|
19
|
+
folderUuid: opts.folderUuid,
|
|
20
|
+
}));
|
|
21
|
+
outputJson(result);
|
|
22
|
+
});
|
|
23
|
+
worker
|
|
24
|
+
.command("get <uuid>")
|
|
25
|
+
.description("Show details of a single worker")
|
|
26
|
+
.action(async (uuid) => {
|
|
27
|
+
const api = getApi();
|
|
28
|
+
const result = await handleApiCall(() => api.hosting.worker.get(uuid));
|
|
29
|
+
outputJson(result);
|
|
30
|
+
});
|
|
31
|
+
worker
|
|
32
|
+
.command("create")
|
|
33
|
+
.description("Create a new worker slot")
|
|
34
|
+
.requiredOption("--name <name>", "Display name for the worker")
|
|
35
|
+
.requiredOption("--slug <slug>", "URL slug (must be globally unique within the hosting domain)")
|
|
36
|
+
.option("--folder-uuid <uuid>", "Optional folder UUID")
|
|
37
|
+
.action(async (opts) => {
|
|
38
|
+
const api = getApi();
|
|
39
|
+
const result = await handleApiCall(() => api.hosting.worker.create({
|
|
40
|
+
name: opts.name,
|
|
41
|
+
slug: opts.slug,
|
|
42
|
+
folderUuid: opts.folderUuid,
|
|
43
|
+
}));
|
|
44
|
+
outputJson(result);
|
|
45
|
+
});
|
|
46
|
+
worker
|
|
47
|
+
.command("update")
|
|
48
|
+
.description("Update an existing worker (name, folder)")
|
|
49
|
+
.requiredOption("--uuid <uuid>", "Worker UUID")
|
|
50
|
+
.option("--name <name>", "New display name")
|
|
51
|
+
.option("--folder-uuid <uuid>", "New folder UUID (pass 'null' to move to the workspace root)")
|
|
52
|
+
.action(async (opts) => {
|
|
53
|
+
const api = getApi();
|
|
54
|
+
const result = await handleApiCall(() => api.hosting.worker.update({
|
|
55
|
+
uuid: opts.uuid,
|
|
56
|
+
name: opts.name,
|
|
57
|
+
folderUuid: opts.folderUuid === "null" ? null : opts.folderUuid,
|
|
58
|
+
}));
|
|
59
|
+
outputJson(result);
|
|
60
|
+
});
|
|
61
|
+
worker
|
|
62
|
+
.command("remove <uuid>")
|
|
63
|
+
.description("Remove a worker (also removes its deployments)")
|
|
64
|
+
.action(async (uuid) => {
|
|
65
|
+
const api = getApi();
|
|
66
|
+
await handleApiCall(() => api.hosting.worker.remove(uuid));
|
|
67
|
+
outputJson({ ok: true });
|
|
68
|
+
});
|
|
69
|
+
worker
|
|
70
|
+
.command("init <directory>")
|
|
71
|
+
.description("Scaffold a new Cargo Hosting worker locally from a template (edge `fetch(request, env)` handler).")
|
|
72
|
+
.option("--template <slug>", "Template slug (default: blank)", "blank")
|
|
73
|
+
.option("--name <name>", "Worker name written into package.json (default: directory name)")
|
|
74
|
+
.option("--list-templates", "Print available templates and exit")
|
|
75
|
+
.action(async (directory, opts) => {
|
|
76
|
+
const templatesRoot = findWorkerTemplatesRoot();
|
|
77
|
+
if (opts.listTemplates === true) {
|
|
78
|
+
const slugs = await listTemplates(templatesRoot);
|
|
79
|
+
if (slugs.length === 0) {
|
|
80
|
+
console.error(JSON.stringify({ error: "No templates found", templatesRoot }));
|
|
81
|
+
process.exit(1);
|
|
82
|
+
}
|
|
83
|
+
console.log(JSON.stringify(slugs.map((slug) => ({
|
|
84
|
+
slug,
|
|
85
|
+
description: WORKER_TEMPLATE_DESCRIPTIONS[slug] !== undefined
|
|
86
|
+
? WORKER_TEMPLATE_DESCRIPTIONS[slug]
|
|
87
|
+
: "",
|
|
88
|
+
})), null, 2));
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
const templateDir = path.join(templatesRoot, opts.template);
|
|
92
|
+
try {
|
|
93
|
+
const stat = await fs.stat(templateDir);
|
|
94
|
+
if (stat.isDirectory() === false) {
|
|
95
|
+
throw new Error("Template path is not a directory");
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
const slugs = await listTemplates(templatesRoot);
|
|
100
|
+
console.error(JSON.stringify({
|
|
101
|
+
error: `Unknown template "${opts.template}"`,
|
|
102
|
+
available: slugs,
|
|
103
|
+
}));
|
|
104
|
+
process.exit(1);
|
|
105
|
+
}
|
|
106
|
+
const targetDir = path.resolve(directory);
|
|
107
|
+
try {
|
|
108
|
+
const stat = await fs.stat(targetDir);
|
|
109
|
+
if (stat.isDirectory() === true) {
|
|
110
|
+
const entries = await fs.readdir(targetDir);
|
|
111
|
+
if (entries.length > 0) {
|
|
112
|
+
console.error(JSON.stringify({
|
|
113
|
+
error: `Target directory ${targetDir} is not empty.`,
|
|
114
|
+
}));
|
|
115
|
+
process.exit(1);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
catch {
|
|
120
|
+
// Target does not exist yet — that's fine.
|
|
121
|
+
}
|
|
122
|
+
const workerName = opts.name !== undefined ? opts.name : path.basename(targetDir);
|
|
123
|
+
await copyDirectory(templateDir, targetDir, [
|
|
124
|
+
{ from: "__APP_NAME__", to: workerName },
|
|
125
|
+
{ from: "__TEMPLATE_SLUG__", to: opts.template },
|
|
126
|
+
]);
|
|
127
|
+
const nextSteps = [
|
|
128
|
+
`cd ${path.relative(process.cwd(), targetDir)}`,
|
|
129
|
+
"npm install",
|
|
130
|
+
`cargo-ai hosting worker create --name '${workerName}' --slug '<your-slug>'`,
|
|
131
|
+
"npm run build",
|
|
132
|
+
"cargo-ai hosting deployment create --worker-uuid <workerUuid> --source ./dist",
|
|
133
|
+
"cargo-ai hosting deployment promote --uuid <deploymentUuid>",
|
|
134
|
+
];
|
|
135
|
+
if (opts.template === "custom-integration") {
|
|
136
|
+
nextSteps.push("cargo-ai connection custom-integration create --kind worker --worker-uuid <workerUuid>");
|
|
137
|
+
}
|
|
138
|
+
console.log(JSON.stringify({
|
|
139
|
+
ok: true,
|
|
140
|
+
directory: targetDir,
|
|
141
|
+
template: opts.template,
|
|
142
|
+
name: workerName,
|
|
143
|
+
nextSteps,
|
|
144
|
+
}, null, 2));
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
const WORKER_TEMPLATE_DESCRIPTIONS = {
|
|
148
|
+
blank: "Edge worker built on @cargo-ai/worker-sdk with automatic OpenAPI 3.1 spec at /openapi.json and Swagger UI at /docs.",
|
|
149
|
+
"custom-integration": "Cargo Custom Integration worker built on @cargo-ai/worker-sdk — manifest / actions / extractors / autocompletes / dynamic schemas with automatic /openapi.json.",
|
|
150
|
+
};
|
|
151
|
+
const findWorkerTemplatesRoot = () => {
|
|
152
|
+
// Worker templates live in `@cargo-ai/worker-sdk/templates`. Resolve via
|
|
153
|
+
// require so we work whether the user installed both packages globally or
|
|
154
|
+
// both came from the monorepo.
|
|
155
|
+
try {
|
|
156
|
+
const workerSdkPackageJson = require.resolve("@cargo-ai/worker-sdk/package.json");
|
|
157
|
+
return path.join(path.dirname(workerSdkPackageJson), "templates");
|
|
158
|
+
}
|
|
159
|
+
catch {
|
|
160
|
+
const here = fileURLToPath(import.meta.url);
|
|
161
|
+
let cursor = path.dirname(here);
|
|
162
|
+
for (let i = 0; i < 6; i += 1) {
|
|
163
|
+
const candidate = path.join(cursor, "packages/worker-sdk/templates");
|
|
164
|
+
try {
|
|
165
|
+
require("node:fs").accessSync(candidate);
|
|
166
|
+
return candidate;
|
|
167
|
+
}
|
|
168
|
+
catch {
|
|
169
|
+
cursor = path.dirname(cursor);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
throw new Error("Could not locate @cargo-ai/worker-sdk templates. Make sure @cargo-ai/worker-sdk is installed alongside @cargo-ai/cli.");
|
|
173
|
+
}
|
|
174
|
+
};
|
|
@@ -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;AAgBxC,wBAAgB,6BAA6B,CAC3C,MAAM,EAAE,OAAO,EACf,MAAM,EAAE,MAAM,GAAG,GAChB,IAAI,CAmBN"}
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import { registerActionCommands } from "./action.js";
|
|
2
2
|
import { registerBatchCommands } from "./batch.js";
|
|
3
3
|
import { registerDraftReleaseCommands } from "./draftRelease.js";
|
|
4
|
-
import { registerLogCommands } from "./log.js";
|
|
5
4
|
import { registerNodeCommands } from "./node.js";
|
|
6
5
|
import { registerPlayCommands } from "./play.js";
|
|
7
6
|
import { registerQueryCommands } from "./query.js";
|
|
8
7
|
import { registerRecordCommands } from "./record.js";
|
|
9
8
|
import { registerReleaseCommands } from "./release.js";
|
|
10
9
|
import { registerRunCommands } from "./run.js";
|
|
10
|
+
import { registerSpanCommands } from "./span.js";
|
|
11
11
|
import { registerTemplateCommands } from "./template.js";
|
|
12
12
|
import { registerToolCommands } from "./tool.js";
|
|
13
|
+
import { registerTraceCommands } from "./trace.js";
|
|
13
14
|
import { registerWorkflowCommands } from "./workflow.js";
|
|
14
15
|
export function registerOrchestrationCommands(parent, getApi) {
|
|
15
16
|
const orchestration = parent
|
|
@@ -20,7 +21,8 @@ export function registerOrchestrationCommands(parent, getApi) {
|
|
|
20
21
|
registerPlayCommands(orchestration, getApi);
|
|
21
22
|
registerRunCommands(orchestration, getApi);
|
|
22
23
|
registerBatchCommands(orchestration, getApi);
|
|
23
|
-
|
|
24
|
+
registerSpanCommands(orchestration, getApi);
|
|
25
|
+
registerTraceCommands(orchestration, getApi);
|
|
24
26
|
registerReleaseCommands(orchestration, getApi);
|
|
25
27
|
registerDraftReleaseCommands(orchestration, getApi);
|
|
26
28
|
registerToolCommands(orchestration, getApi);
|
|
@@ -8,12 +8,12 @@ export function registerQueryCommands(parent, getApi) {
|
|
|
8
8
|
.description("Execute a read-only SQL query")
|
|
9
9
|
.argument("<sql>", "SQL query string")
|
|
10
10
|
.addHelpText("after", `
|
|
11
|
-
Available tables:
|
|
11
|
+
Available tables: spans, runs, batches, records
|
|
12
12
|
|
|
13
13
|
Examples:
|
|
14
14
|
$ cargo-ai orchestration query execute "SELECT count() FROM runs"
|
|
15
15
|
$ cargo-ai orchestration query execute "SELECT status, count() FROM batches GROUP BY status"
|
|
16
|
-
$ cargo-ai orchestration query execute "SELECT * FROM
|
|
16
|
+
$ cargo-ai orchestration query execute "SELECT * FROM spans ORDER BY execution_started_at DESC LIMIT 10"
|
|
17
17
|
$ cargo-ai orchestration query execute "WITH recent AS (SELECT * FROM runs WHERE created_at > now() - INTERVAL 1 DAY) SELECT status, count() FROM recent GROUP BY status"`)
|
|
18
18
|
.action(async (sql) => {
|
|
19
19
|
const api = getApi();
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { Command } from "commander";
|
|
2
2
|
import type { Api } from "../../api.js";
|
|
3
|
-
export declare function
|
|
4
|
-
//# sourceMappingURL=
|
|
3
|
+
export declare function registerSpanCommands(parent: Command, getApi: () => Api): void;
|
|
4
|
+
//# sourceMappingURL=span.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"span.d.ts","sourceRoot":"","sources":["../../../src/commands/orchestration/span.ts"],"names":[],"mappings":"AAAA,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,CAwO7E"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { handleApiCall, outputJson } from "../runHandler.js";
|
|
2
|
-
export function
|
|
3
|
-
const
|
|
4
|
-
|
|
2
|
+
export function registerSpanCommands(parent, getApi) {
|
|
3
|
+
const span = parent.command("span").description("Execution span operations");
|
|
4
|
+
span
|
|
5
5
|
.command("list")
|
|
6
|
-
.description("List execution
|
|
6
|
+
.description("List execution spans")
|
|
7
7
|
.option("--workflow-uuid <uuid>", "Workflow UUID (omit to include all workflows in the workspace)")
|
|
8
8
|
.option("--batch-uuid <uuid>", "Batch UUID")
|
|
9
9
|
.option("--run-uuid <uuid>", "Run UUID")
|
|
@@ -29,7 +29,7 @@ export function registerLogCommands(parent, getApi) {
|
|
|
29
29
|
.option("--offset <n>", "Offset", "0")
|
|
30
30
|
.action(async (opts) => {
|
|
31
31
|
const api = getApi();
|
|
32
|
-
const result = await handleApiCall(() => api.orchestration.
|
|
32
|
+
const result = await handleApiCall(() => api.orchestration.span.list({
|
|
33
33
|
workflowUuid: opts.workflowUuid,
|
|
34
34
|
batchUuid: opts.batchUuid,
|
|
35
35
|
runUuid: opts.runUuid,
|
|
@@ -62,9 +62,9 @@ export function registerLogCommands(parent, getApi) {
|
|
|
62
62
|
}));
|
|
63
63
|
outputJson(result);
|
|
64
64
|
});
|
|
65
|
-
|
|
65
|
+
span
|
|
66
66
|
.command("count")
|
|
67
|
-
.description("Count execution
|
|
67
|
+
.description("Count execution spans")
|
|
68
68
|
.option("--workflow-uuid <uuid>", "Workflow UUID (omit to include all workflows in the workspace)")
|
|
69
69
|
.option("--batch-uuid <uuid>", "Batch UUID")
|
|
70
70
|
.option("--run-uuid <uuid>", "Run UUID")
|
|
@@ -88,7 +88,7 @@ export function registerLogCommands(parent, getApi) {
|
|
|
88
88
|
.option("--execution-started-before <date>", "Execution started on or before (ISO date)")
|
|
89
89
|
.action(async (opts) => {
|
|
90
90
|
const api = getApi();
|
|
91
|
-
const result = await handleApiCall(() => api.orchestration.
|
|
91
|
+
const result = await handleApiCall(() => api.orchestration.span.count({
|
|
92
92
|
workflowUuid: opts.workflowUuid,
|
|
93
93
|
batchUuid: opts.batchUuid,
|
|
94
94
|
runUuid: opts.runUuid,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trace.d.ts","sourceRoot":"","sources":["../../../src/commands/orchestration/trace.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAGxC,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,OAAO,EACf,MAAM,EAAE,MAAM,GAAG,GAChB,IAAI,CAiHN"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { handleApiCall, outputJson } from "../runHandler.js";
|
|
2
|
+
export function registerTraceCommands(parent, getApi) {
|
|
3
|
+
const trace = parent
|
|
4
|
+
.command("trace")
|
|
5
|
+
.description("Trace operations (per-execution aggregation across the run lineage)");
|
|
6
|
+
trace
|
|
7
|
+
.command("list")
|
|
8
|
+
.description("List traces (aggregated over their spans)")
|
|
9
|
+
.option("--workflow-uuid <uuid>", "Workflow UUID (omit to include all workflows in the workspace)")
|
|
10
|
+
.option("--statuses <list>", "Comma-separated trace statuses (pending, error, success)")
|
|
11
|
+
.requiredOption("--started-after <date>", "Trace's first span started after (ISO date)")
|
|
12
|
+
.option("--started-before <date>", "Trace's first span started on or before (ISO date)")
|
|
13
|
+
.option("--limit <n>", "Limit", "30")
|
|
14
|
+
.option("--offset <n>", "Offset", "0")
|
|
15
|
+
.action(async (opts) => {
|
|
16
|
+
const api = getApi();
|
|
17
|
+
const result = await handleApiCall(() => api.orchestration.trace.list({
|
|
18
|
+
workflowUuid: opts.workflowUuid,
|
|
19
|
+
statuses: opts.statuses !== undefined
|
|
20
|
+
? opts.statuses.split(",").map((s) => s.trim())
|
|
21
|
+
: undefined,
|
|
22
|
+
startedAfter: opts.startedAfter,
|
|
23
|
+
startedBefore: opts.startedBefore,
|
|
24
|
+
limit: opts.limit !== undefined ? parseInt(opts.limit, 10) : undefined,
|
|
25
|
+
offset: opts.offset !== undefined ? parseInt(opts.offset, 10) : undefined,
|
|
26
|
+
}));
|
|
27
|
+
outputJson(result);
|
|
28
|
+
});
|
|
29
|
+
trace
|
|
30
|
+
.command("count")
|
|
31
|
+
.description("Count traces matching the filter")
|
|
32
|
+
.option("--workflow-uuid <uuid>", "Workflow UUID (omit to include all workflows in the workspace)")
|
|
33
|
+
.option("--statuses <list>", "Comma-separated trace statuses (pending, error, success)")
|
|
34
|
+
.requiredOption("--started-after <date>", "Trace's first span started after (ISO date)")
|
|
35
|
+
.option("--started-before <date>", "Trace's first span started on or before (ISO date)")
|
|
36
|
+
.action(async (opts) => {
|
|
37
|
+
const api = getApi();
|
|
38
|
+
const result = await handleApiCall(() => api.orchestration.trace.count({
|
|
39
|
+
workflowUuid: opts.workflowUuid,
|
|
40
|
+
statuses: opts.statuses !== undefined
|
|
41
|
+
? opts.statuses.split(",").map((s) => s.trim())
|
|
42
|
+
: undefined,
|
|
43
|
+
startedAfter: opts.startedAfter,
|
|
44
|
+
startedBefore: opts.startedBefore,
|
|
45
|
+
}));
|
|
46
|
+
outputJson(result);
|
|
47
|
+
});
|
|
48
|
+
trace
|
|
49
|
+
.command("get <uuid>")
|
|
50
|
+
.description("Get a single trace by UUID")
|
|
51
|
+
.action(async (uuid) => {
|
|
52
|
+
const api = getApi();
|
|
53
|
+
const result = await handleApiCall(() => api.orchestration.trace.get(uuid));
|
|
54
|
+
outputJson(result);
|
|
55
|
+
});
|
|
56
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"record.d.ts","sourceRoot":"","sources":["../../../src/commands/storage/record.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAGxC,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,OAAO,EACf,MAAM,EAAE,MAAM,GAAG,GAChB,IAAI,
|
|
1
|
+
{"version":3,"file":"record.d.ts","sourceRoot":"","sources":["../../../src/commands/storage/record.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAGxC,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,OAAO,EACf,MAAM,EAAE,MAAM,GAAG,GAChB,IAAI,CAsON"}
|
|
@@ -100,4 +100,55 @@ Example:
|
|
|
100
100
|
}));
|
|
101
101
|
outputJson({ ok: true });
|
|
102
102
|
});
|
|
103
|
+
record
|
|
104
|
+
.command("create-bulk")
|
|
105
|
+
.description("Create multiple storage records in a single call")
|
|
106
|
+
.requiredOption("--model-uuid <uuid>", "Model UUID (string, required)")
|
|
107
|
+
.requiredOption("--records <json>", 'JSON array of record entries: [{ "data": { ... } }, ...]')
|
|
108
|
+
.addHelpText("after", `
|
|
109
|
+
Example:
|
|
110
|
+
$ cargo-ai storage record create-bulk --model-uuid 550e8400-... \\
|
|
111
|
+
--records '[{"data":{"name":"Ada"}},{"data":{"name":"Lin"}}]'`)
|
|
112
|
+
.action(async (opts) => {
|
|
113
|
+
const api = getApi();
|
|
114
|
+
const result = await handleApiCall(() => api.storage.record.createBulk({
|
|
115
|
+
modelUuid: opts.modelUuid,
|
|
116
|
+
records: parseJson(opts.records, "--records"),
|
|
117
|
+
}));
|
|
118
|
+
outputJson(result);
|
|
119
|
+
});
|
|
120
|
+
record
|
|
121
|
+
.command("update-bulk")
|
|
122
|
+
.description("Update multiple storage records in a single call")
|
|
123
|
+
.requiredOption("--model-uuid <uuid>", "Model UUID (string, required)")
|
|
124
|
+
.requiredOption("--records <json>", 'JSON array of record entries: [{ "id": "rec_1", "data": { ... } }, ...]')
|
|
125
|
+
.addHelpText("after", `
|
|
126
|
+
Example:
|
|
127
|
+
$ cargo-ai storage record update-bulk --model-uuid 550e8400-... \\
|
|
128
|
+
--records '[{"id":"rec_1","data":{"status":"done"}},{"id":"rec_2","data":{"status":"done"}}]'`)
|
|
129
|
+
.action(async (opts) => {
|
|
130
|
+
const api = getApi();
|
|
131
|
+
const result = await handleApiCall(() => api.storage.record.updateBulk({
|
|
132
|
+
modelUuid: opts.modelUuid,
|
|
133
|
+
records: parseJson(opts.records, "--records"),
|
|
134
|
+
}));
|
|
135
|
+
outputJson(result);
|
|
136
|
+
});
|
|
137
|
+
record
|
|
138
|
+
.command("remove-bulk")
|
|
139
|
+
.description("Remove multiple storage records in a single call")
|
|
140
|
+
.requiredOption("--model-uuid <uuid>", "Model UUID (string, required)")
|
|
141
|
+
.requiredOption("--ids <json>", 'JSON array of record IDs: ["rec_1", "rec_2", ...]')
|
|
142
|
+
.addHelpText("after", `
|
|
143
|
+
Example:
|
|
144
|
+
$ cargo-ai storage record remove-bulk --model-uuid 550e8400-... \\
|
|
145
|
+
--ids '["rec_1","rec_2","rec_3"]'`)
|
|
146
|
+
.action(async (opts) => {
|
|
147
|
+
const api = getApi();
|
|
148
|
+
await handleApiCall(() => api.storage.record.removeBulk({
|
|
149
|
+
modelUuid: opts.modelUuid,
|
|
150
|
+
ids: parseJson(opts.ids, "--ids"),
|
|
151
|
+
}));
|
|
152
|
+
outputJson({ ok: true });
|
|
153
|
+
});
|
|
103
154
|
}
|
package/build/index.js
CHANGED
|
@@ -8,6 +8,7 @@ import { registerBillingCommands } from "./commands/billing/index.js";
|
|
|
8
8
|
import { registerConnectionCommands } from "./commands/connection/index.js";
|
|
9
9
|
import { registerContextCommands } from "./commands/context/index.js";
|
|
10
10
|
import { registerExpressionCommands } from "./commands/expression/index.js";
|
|
11
|
+
import { registerHostingCommands } from "./commands/hosting/index.js";
|
|
11
12
|
import { registerInitCommand } from "./commands/init.js";
|
|
12
13
|
import { registerOrchestrationCommands } from "./commands/orchestration/index.js";
|
|
13
14
|
import { registerRevenueOrganizationCommands } from "./commands/revenueOrganization/index.js";
|
|
@@ -65,6 +66,7 @@ registerExpressionCommands(program, getApi);
|
|
|
65
66
|
registerSystemOfRecordIntegrationCommands(program, getApi);
|
|
66
67
|
registerUserManagementCommands(program, getApi);
|
|
67
68
|
registerAiCommands(program, getApi);
|
|
69
|
+
registerHostingCommands(program, getApi);
|
|
68
70
|
program.parseAsync().catch((err) => {
|
|
69
71
|
failWith(err instanceof Error ? err.message : String(err));
|
|
70
72
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cargo-ai/cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.16",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Command-line interface for the Cargo API",
|
|
6
6
|
"engines": {
|
|
@@ -28,8 +28,10 @@
|
|
|
28
28
|
"format:check": "prettier --check ."
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"
|
|
32
|
-
"@cargo-ai/
|
|
31
|
+
"@cargo-ai/api": "^1.0.24",
|
|
32
|
+
"@cargo-ai/app-sdk": "^1.0.0",
|
|
33
|
+
"@cargo-ai/worker-sdk": "^1.0.0",
|
|
34
|
+
"commander": "^12.1.0"
|
|
33
35
|
},
|
|
34
36
|
"devDependencies": {
|
|
35
37
|
"@cargo-ai/eslint-config": "*",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"file.d.ts","sourceRoot":"","sources":["../../../src/commands/context/file.ts"],"names":[],"mappings":"AAAA,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,CAqD7E"}
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import { handleApiCall, outputJson } from "../runHandler.js";
|
|
2
|
-
export function registerFileCommands(parent, getApi) {
|
|
3
|
-
const file = parent.command("file").description("Context file operations");
|
|
4
|
-
file
|
|
5
|
-
.command("browse")
|
|
6
|
-
.description("Browse files in the context repository")
|
|
7
|
-
.option("--path <path>", "Path to browse (omit for root)")
|
|
8
|
-
.action(async (opts) => {
|
|
9
|
-
const api = getApi();
|
|
10
|
-
const result = await handleApiCall(() => api.context.file.browse({ path: opts.path }));
|
|
11
|
-
outputJson(result);
|
|
12
|
-
});
|
|
13
|
-
file
|
|
14
|
-
.command("read")
|
|
15
|
-
.description("Read a file from the context repository")
|
|
16
|
-
.requiredOption("--path <path>", "Full path to the file")
|
|
17
|
-
.action(async (opts) => {
|
|
18
|
-
const api = getApi();
|
|
19
|
-
const result = await handleApiCall(() => api.context.file.read({ path: opts.path }));
|
|
20
|
-
outputJson(result);
|
|
21
|
-
});
|
|
22
|
-
file
|
|
23
|
-
.command("write")
|
|
24
|
-
.description("Write a file to the context repository")
|
|
25
|
-
.requiredOption("--path <path>", "Full path to the file")
|
|
26
|
-
.requiredOption("--content <content>", "Content to write")
|
|
27
|
-
.option("--commit-message <message>", "Commit message")
|
|
28
|
-
.option("--sha <sha>", "SHA of the existing file to update")
|
|
29
|
-
.action(async (opts) => {
|
|
30
|
-
const api = getApi();
|
|
31
|
-
const result = await handleApiCall(() => api.context.file.write({
|
|
32
|
-
path: opts.path,
|
|
33
|
-
content: opts.content,
|
|
34
|
-
commitMessage: opts.commitMessage,
|
|
35
|
-
sha: opts.sha,
|
|
36
|
-
}));
|
|
37
|
-
outputJson(result);
|
|
38
|
-
});
|
|
39
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"skill.d.ts","sourceRoot":"","sources":["../../../src/commands/context/skill.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAGxC,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,OAAO,EACf,MAAM,EAAE,MAAM,GAAG,GAChB,IAAI,CAuBN"}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { handleApiCall, outputJson } from "../runHandler.js";
|
|
2
|
-
export function registerSkillCommands(parent, getApi) {
|
|
3
|
-
const skill = parent.command("skill").description("Context skill operations");
|
|
4
|
-
skill
|
|
5
|
-
.command("list")
|
|
6
|
-
.description("List all skills in the context repository")
|
|
7
|
-
.action(async () => {
|
|
8
|
-
const api = getApi();
|
|
9
|
-
const result = await handleApiCall(() => api.context.skill.list());
|
|
10
|
-
outputJson(result);
|
|
11
|
-
});
|
|
12
|
-
skill
|
|
13
|
-
.command("get")
|
|
14
|
-
.description("Get a skill by slug")
|
|
15
|
-
.requiredOption("--slug <slug>", "Skill slug (path in the repository)")
|
|
16
|
-
.action(async (opts) => {
|
|
17
|
-
const api = getApi();
|
|
18
|
-
const result = await handleApiCall(() => api.context.skill.get({ slug: opts.slug }));
|
|
19
|
-
outputJson(result);
|
|
20
|
-
});
|
|
21
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"log.d.ts","sourceRoot":"","sources":["../../../src/commands/orchestration/log.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAGxC,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,GAAG,IAAI,CAwO5E"}
|