@cargo-ai/cli 1.0.17 → 1.0.18
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/build/commands/ai/mcpServer.js +2 -2
- package/build/commands/ai/memory.js +6 -6
- package/build/commands/ai/message.d.ts.map +1 -1
- package/build/commands/ai/message.js +4 -0
- package/build/commands/ai/release.d.ts.map +1 -1
- package/build/commands/ai/release.js +10 -0
- package/build/commands/orchestration/action.d.ts.map +1 -1
- package/build/commands/orchestration/action.js +16 -0
- package/build/commands/version.d.ts +3 -0
- package/build/commands/version.d.ts.map +1 -0
- package/build/commands/version.js +29 -0
- package/build/commands/workspaceManagement/index.d.ts.map +1 -1
- package/build/commands/workspaceManagement/index.js +3 -1
- package/build/commands/workspaceManagement/session.d.ts +4 -0
- package/build/commands/workspaceManagement/session.d.ts.map +1 -0
- package/build/commands/workspaceManagement/session.js +31 -0
- package/build/credentials.d.ts +1 -0
- package/build/credentials.d.ts.map +1 -1
- package/build/credentials.js +3 -0
- package/build/index.js +7 -1
- package/build/updateNotifier.d.ts +9 -0
- package/build/updateNotifier.d.ts.map +1 -0
- package/build/updateNotifier.js +38 -0
- package/build/version.d.ts +25 -0
- package/build/version.d.ts.map +1 -0
- package/build/version.js +91 -0
- package/package.json +3 -3
|
@@ -30,13 +30,13 @@ Examples:
|
|
|
30
30
|
$ cargo-ai ai mcp-server create --name "My Server"
|
|
31
31
|
$ cargo-ai ai mcp-server create --name "My Server" \\
|
|
32
32
|
--actions '[{"slug":"my-action","kind":"tool","name":null,"description":null,"isBulkAllowed":false,"config":{}}]' \\
|
|
33
|
-
--resources '[{"kind":"model","slug":"my-resource","name":"My Resource","description":null,"integrationSlug":"hubspot","modelUuid":null,"filter":null,"selectedColumnSlugs":null,"limit":null,"prompt":null}]'
|
|
33
|
+
--resources '[{"kind":"model","slug":"my-resource","name":"My Resource","description":null,"integrationSlug":"hubspot","modelUuid":null,"filter":null,"selectedColumnSlugs":null,"limit":null,"prompt":null,"isReadOnly":true}]'
|
|
34
34
|
|
|
35
35
|
Action object shape:
|
|
36
36
|
{ "slug": string, "kind": "tool", "name": string | null, "description": string | null, "isBulkAllowed": boolean, "config": object }
|
|
37
37
|
|
|
38
38
|
Resource object shapes:
|
|
39
|
-
Model: { "kind": "model", "slug": string, "name": string, "description": string | null, "integrationSlug": string, "modelUuid": string | null, "filter": object | null, "selectedColumnSlugs": string[] | null, "limit": number | null, "prompt": string | null }
|
|
39
|
+
Model: { "kind": "model", "slug": string, "name": string, "description": string | null, "integrationSlug": string, "modelUuid": string | null, "filter": object | null, "selectedColumnSlugs": string[] | null, "limit": number | null, "prompt": string | null, "isReadOnly": boolean }
|
|
40
40
|
File: { "kind": "file", "slug": string, "name": string, "description": string | null, "items": [{"kind":"file","fileUuid": string}], "prompt": string | null }`)
|
|
41
41
|
.action(async (opts) => {
|
|
42
42
|
const api = getApi();
|
|
@@ -4,13 +4,13 @@ export function registerMemoryCommands(parent, getApi) {
|
|
|
4
4
|
memory
|
|
5
5
|
.command("list")
|
|
6
6
|
.description("List memories")
|
|
7
|
-
.requiredOption("--scope <scope>", "Scope (
|
|
7
|
+
.requiredOption("--scope <scope>", "Scope (user, agent)")
|
|
8
8
|
.option("--agent-uuid <uuid>", "Agent UUID (required when scope is agent)")
|
|
9
9
|
.action(async (opts) => {
|
|
10
10
|
const api = getApi();
|
|
11
11
|
const payload = opts.scope === "agent"
|
|
12
12
|
? { scope: "agent", agentUuid: opts.agentUuid }
|
|
13
|
-
: { scope:
|
|
13
|
+
: { scope: "user" };
|
|
14
14
|
const result = await handleApiCall(() => api.ai.memory.list(payload));
|
|
15
15
|
outputJson(result);
|
|
16
16
|
});
|
|
@@ -18,13 +18,13 @@ export function registerMemoryCommands(parent, getApi) {
|
|
|
18
18
|
.command("remove")
|
|
19
19
|
.description("Remove a memory")
|
|
20
20
|
.requiredOption("--mem0-id <id>", "Memory ID")
|
|
21
|
-
.requiredOption("--scope <scope>", "Scope (
|
|
21
|
+
.requiredOption("--scope <scope>", "Scope (user, agent)")
|
|
22
22
|
.option("--agent-uuid <uuid>", "Agent UUID (required when scope is agent)")
|
|
23
23
|
.action(async (opts) => {
|
|
24
24
|
const api = getApi();
|
|
25
25
|
const scopePayload = opts.scope === "agent"
|
|
26
26
|
? { scope: "agent", agentUuid: opts.agentUuid }
|
|
27
|
-
: { scope:
|
|
27
|
+
: { scope: "user" };
|
|
28
28
|
await handleApiCall(() => api.ai.memory.remove({ mem0Id: opts.mem0Id, ...scopePayload }));
|
|
29
29
|
outputJson({ ok: true });
|
|
30
30
|
});
|
|
@@ -33,13 +33,13 @@ export function registerMemoryCommands(parent, getApi) {
|
|
|
33
33
|
.description("Update a memory")
|
|
34
34
|
.requiredOption("--mem0-id <id>", "Memory ID")
|
|
35
35
|
.requiredOption("--content <text>", "Memory content")
|
|
36
|
-
.requiredOption("--scope <scope>", "Scope (
|
|
36
|
+
.requiredOption("--scope <scope>", "Scope (user, agent)")
|
|
37
37
|
.option("--agent-uuid <uuid>", "Agent UUID (required when scope is agent)")
|
|
38
38
|
.action(async (opts) => {
|
|
39
39
|
const api = getApi();
|
|
40
40
|
const scopePayload = opts.scope === "agent"
|
|
41
41
|
? { scope: "agent", agentUuid: opts.agentUuid }
|
|
42
|
-
: { scope:
|
|
42
|
+
: { scope: "user" };
|
|
43
43
|
const result = await handleApiCall(() => api.ai.memory.update({
|
|
44
44
|
mem0Id: opts.mem0Id,
|
|
45
45
|
content: opts.content,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"message.d.ts","sourceRoot":"","sources":["../../../src/commands/ai/message.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAQxC,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,OAAO,EACf,MAAM,EAAE,MAAM,GAAG,GAChB,IAAI,
|
|
1
|
+
{"version":3,"file":"message.d.ts","sourceRoot":"","sources":["../../../src/commands/ai/message.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAQxC,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,OAAO,EACf,MAAM,EAAE,MAAM,GAAG,GAChB,IAAI,CAgMN"}
|
|
@@ -19,6 +19,7 @@ export function registerMessageCommands(parent, getApi) {
|
|
|
19
19
|
.option("--integration-slug <slug>", "Integration slug (string)")
|
|
20
20
|
.option("--connector-uuid <uuid>", "Connector UUID (string)")
|
|
21
21
|
.option("--language-model-slug <slug>", "Language model slug (string)")
|
|
22
|
+
.option("--output <json>", 'Output format for the assistant message (JSON object, e.g. \'{"type":"text"}\' or \'{"type":"jsonSchema","jsonSchema":{...}}\'). Defaults to text when omitted.')
|
|
22
23
|
.option("--wait-until-finished", "Poll the assistant message until finished before returning (boolean flag)")
|
|
23
24
|
.option("--polling-interval <ms>", "Polling interval in milliseconds, used with --wait-until-finished (integer, default: 5000)", "5000")
|
|
24
25
|
.addHelpText("after", `
|
|
@@ -59,6 +60,9 @@ MCP client shape: { "name": string, "url": string }`)
|
|
|
59
60
|
integrationSlug: opts.integrationSlug,
|
|
60
61
|
connectorUuid: opts.connectorUuid,
|
|
61
62
|
languageModelSlug: opts.languageModelSlug,
|
|
63
|
+
output: opts.output !== undefined
|
|
64
|
+
? parseJson(opts.output, "--output")
|
|
65
|
+
: undefined,
|
|
62
66
|
}));
|
|
63
67
|
if (opts.waitUntilFinished === true) {
|
|
64
68
|
const intervalMs = parseInt(opts.pollingInterval, 10);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"release.d.ts","sourceRoot":"","sources":["../../../src/commands/ai/release.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,
|
|
1
|
+
{"version":3,"file":"release.d.ts","sourceRoot":"","sources":["../../../src/commands/ai/release.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,CAqSN"}
|
|
@@ -68,6 +68,16 @@ export function registerReleaseCommands(parent, getApi) {
|
|
|
68
68
|
.option("--capabilities <json>", "Capabilities to enable (JSON array of capability objects)")
|
|
69
69
|
.option("--suggested-actions <json>", "Suggested actions for the chat UI (JSON array of action objects)")
|
|
70
70
|
.option("--options <json>", "Additional options (JSON object)")
|
|
71
|
+
.addHelpText("after", `
|
|
72
|
+
Examples:
|
|
73
|
+
$ cargo-ai ai release update-draft --agent-uuid <uuid> \\
|
|
74
|
+
--resources '[{"kind":"model","slug":"my-resource","name":"My Resource","description":null,"integrationSlug":"hubspot","modelUuid":null,"filter":null,"selectedColumnSlugs":null,"limit":null,"prompt":null,"isReadOnly":true}]'
|
|
75
|
+
|
|
76
|
+
Resource object shapes:
|
|
77
|
+
Model: { "kind": "model", "slug": string, "name": string, "description": string | null, "integrationSlug": string, "modelUuid": string | null, "filter": object | null, "selectedColumnSlugs": string[] | null, "limit": number | null, "prompt": string | null, "isReadOnly": boolean }
|
|
78
|
+
File: { "kind": "file", "slug": string, "name": string, "description": string | null, "items": [{"kind":"file","fileUuid": string}], "prompt": string | null }
|
|
79
|
+
|
|
80
|
+
Set "isReadOnly": false on a model resource to grant the agent write tools (insert/update/upsert/delete/custom columns).`)
|
|
71
81
|
.action(async (opts) => {
|
|
72
82
|
const api = getApi();
|
|
73
83
|
const result = await handleApiCall(() => api.ai.release.updateDraft({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"action.d.ts","sourceRoot":"","sources":["../../../src/commands/orchestration/action.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AASxC,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,OAAO,EACf,MAAM,EAAE,MAAM,GAAG,GAChB,IAAI,
|
|
1
|
+
{"version":3,"file":"action.d.ts","sourceRoot":"","sources":["../../../src/commands/orchestration/action.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AASxC,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,OAAO,EACf,MAAM,EAAE,MAAM,GAAG,GAChB,IAAI,CA8JN"}
|
|
@@ -61,4 +61,20 @@ Examples:
|
|
|
61
61
|
}
|
|
62
62
|
outputJson(result);
|
|
63
63
|
});
|
|
64
|
+
action
|
|
65
|
+
.command("get-output-schema")
|
|
66
|
+
.description("Resolve the JSON schema of an action's data output without executing it")
|
|
67
|
+
.requiredOption("--action <json>", 'Action definition (JSON object, required). Example: \'{"kind":"tool","toolUuid":"550e8400-...","config":{}}\'')
|
|
68
|
+
.addHelpText("after", `
|
|
69
|
+
Examples:
|
|
70
|
+
$ cargo-ai orchestration action get-output-schema --action '{"kind":"tool","toolUuid":"550e8400-...","config":{}}'
|
|
71
|
+
$ cargo-ai orchestration action get-output-schema --action '{"kind":"connector","integrationSlug":"clearbit","actionSlug":"company_enrich","config":{}}'`)
|
|
72
|
+
.action(async (opts) => {
|
|
73
|
+
const actionPayload = parseJson(opts.action, "--action");
|
|
74
|
+
const api = getApi();
|
|
75
|
+
const result = await handleApiCall(() => api.orchestration.action.getOutputSchema({
|
|
76
|
+
action: actionPayload,
|
|
77
|
+
}));
|
|
78
|
+
outputJson(result);
|
|
79
|
+
});
|
|
64
80
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../../src/commands/version.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAOzC,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,OAAO,EACf,cAAc,EAAE,MAAM,GACrB,IAAI,CAoCN"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { fetchLatestVersion, isOutdated, UPDATE_COMMAND } from "../version.js";
|
|
2
|
+
import { failWith, outputJson } from "./runHandler.js";
|
|
3
|
+
const CHECK_FETCH_TIMEOUT_MS = 5000;
|
|
4
|
+
export function registerVersionCommand(parent, currentVersion) {
|
|
5
|
+
parent
|
|
6
|
+
.command("version")
|
|
7
|
+
.description("Print the installed CLI version, or check npm for a newer release with --check")
|
|
8
|
+
.option("--check", "Query the npm registry and report whether a newer version is available")
|
|
9
|
+
.action(async (opts) => {
|
|
10
|
+
if (opts.check !== true) {
|
|
11
|
+
outputJson({ version: currentVersion });
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
let latest;
|
|
15
|
+
try {
|
|
16
|
+
latest = await fetchLatestVersion(CHECK_FETCH_TIMEOUT_MS);
|
|
17
|
+
}
|
|
18
|
+
catch (error) {
|
|
19
|
+
failWith(`Could not reach the npm registry to check for updates: ${error instanceof Error ? error.message : String(error)}`);
|
|
20
|
+
}
|
|
21
|
+
const upToDate = isOutdated(currentVersion, latest) === false;
|
|
22
|
+
outputJson({
|
|
23
|
+
current: currentVersion,
|
|
24
|
+
latest,
|
|
25
|
+
upToDate,
|
|
26
|
+
updateCommand: upToDate ? undefined : UPDATE_COMMAND,
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/workspaceManagement/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/workspaceManagement/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAUxC,wBAAgB,mCAAmC,CACjD,MAAM,EAAE,OAAO,EACf,MAAM,EAAE,MAAM,GAAG,GAChB,IAAI,CAeN"}
|
|
@@ -2,13 +2,14 @@ import { registerFileCommands } from "./file.js";
|
|
|
2
2
|
import { registerFolderCommands } from "./folder.js";
|
|
3
3
|
import { registerReportCommands } from "./report.js";
|
|
4
4
|
import { registerRoleCommands } from "./role.js";
|
|
5
|
+
import { registerSessionCommands } from "./session.js";
|
|
5
6
|
import { registerTokenCommands } from "./token.js";
|
|
6
7
|
import { registerUserCommands } from "./user.js";
|
|
7
8
|
import { registerWorkspacesCommands } from "./workspaces.js";
|
|
8
9
|
export function registerWorkspaceManagementCommands(parent, getApi) {
|
|
9
10
|
const workspaceManagement = parent
|
|
10
11
|
.command("workspaceManagement")
|
|
11
|
-
.description("Workspaces, users, tokens, roles, folders, reports");
|
|
12
|
+
.description("Workspaces, users, tokens, roles, folders, reports, sessions");
|
|
12
13
|
registerWorkspacesCommands(workspaceManagement, getApi);
|
|
13
14
|
registerUserCommands(workspaceManagement, getApi);
|
|
14
15
|
registerTokenCommands(workspaceManagement, getApi);
|
|
@@ -16,4 +17,5 @@ export function registerWorkspaceManagementCommands(parent, getApi) {
|
|
|
16
17
|
registerFolderCommands(workspaceManagement, getApi);
|
|
17
18
|
registerFileCommands(workspaceManagement, getApi);
|
|
18
19
|
registerReportCommands(workspaceManagement, getApi);
|
|
20
|
+
registerSessionCommands(workspaceManagement, getApi);
|
|
19
21
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../../src/commands/workspaceManagement/session.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,CAiDN"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { handleApiCall, outputJson } from "../runHandler.js";
|
|
2
|
+
export function registerSessionCommands(parent, getApi) {
|
|
3
|
+
const session = parent
|
|
4
|
+
.command("session")
|
|
5
|
+
.description("Claude Code session tracking");
|
|
6
|
+
session
|
|
7
|
+
.command("upsert")
|
|
8
|
+
.description("Create or update a Claude Code session")
|
|
9
|
+
.requiredOption("--session-id <sessionId>", "Claude Code session id")
|
|
10
|
+
.requiredOption("--title <title>", "Short title for the session")
|
|
11
|
+
.requiredOption("--summary <summary>", "Summary of what happened in the session")
|
|
12
|
+
.option("--finished", "Mark the session as finished now (sets finishedAt = now)")
|
|
13
|
+
.option("--finished-at <timestamp>", "Explicit ISO timestamp for when the session finished")
|
|
14
|
+
.action(async (opts) => {
|
|
15
|
+
let finishedAt;
|
|
16
|
+
if (opts.finishedAt !== undefined) {
|
|
17
|
+
finishedAt = opts.finishedAt;
|
|
18
|
+
}
|
|
19
|
+
else if (opts.finished === true) {
|
|
20
|
+
finishedAt = new Date().toISOString();
|
|
21
|
+
}
|
|
22
|
+
const api = getApi();
|
|
23
|
+
const result = await handleApiCall(() => api.workspaceManagement.session.upsert({
|
|
24
|
+
sessionId: opts.sessionId,
|
|
25
|
+
title: opts.title,
|
|
26
|
+
summary: opts.summary,
|
|
27
|
+
finishedAt,
|
|
28
|
+
}));
|
|
29
|
+
outputJson(result);
|
|
30
|
+
});
|
|
31
|
+
}
|
package/build/credentials.d.ts
CHANGED
|
@@ -7,4 +7,5 @@ export declare function loadCredentials(): Credentials | undefined;
|
|
|
7
7
|
export declare function saveCredentials(creds: Credentials): void;
|
|
8
8
|
export declare function clearCredentials(): boolean;
|
|
9
9
|
export declare function getCredentialsPath(): string;
|
|
10
|
+
export declare function getConfigDir(): string;
|
|
10
11
|
//# sourceMappingURL=credentials.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"credentials.d.ts","sourceRoot":"","sources":["../src/credentials.ts"],"names":[],"mappings":"AAUA,MAAM,MAAM,WAAW,GAAG;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAKF,wBAAgB,eAAe,IAAI,WAAW,GAAG,SAAS,CAQzD;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI,CAKxD;AAED,wBAAgB,gBAAgB,IAAI,OAAO,CAI1C;AAED,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C"}
|
|
1
|
+
{"version":3,"file":"credentials.d.ts","sourceRoot":"","sources":["../src/credentials.ts"],"names":[],"mappings":"AAUA,MAAM,MAAM,WAAW,GAAG;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAKF,wBAAgB,eAAe,IAAI,WAAW,GAAG,SAAS,CAQzD;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI,CAKxD;AAED,wBAAgB,gBAAgB,IAAI,OAAO,CAI1C;AAED,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAED,wBAAgB,YAAY,IAAI,MAAM,CAErC"}
|
package/build/credentials.js
CHANGED
package/build/index.js
CHANGED
|
@@ -17,8 +17,10 @@ import { registerSegmentationCommands } from "./commands/segmentation/index.js";
|
|
|
17
17
|
import { registerStorageCommands } from "./commands/storage/index.js";
|
|
18
18
|
import { registerSystemOfRecordIntegrationCommands } from "./commands/systemOfRecordIntegration/index.js";
|
|
19
19
|
import { registerUserManagementCommands } from "./commands/userManagement/index.js";
|
|
20
|
+
import { registerVersionCommand } from "./commands/version.js";
|
|
20
21
|
import { registerWorkspaceManagementCommands } from "./commands/workspaceManagement/index.js";
|
|
21
22
|
import { getConfig } from "./config.js";
|
|
23
|
+
import { maybeNotifyUpdate } from "./updateNotifier.js";
|
|
22
24
|
const require = createRequire(import.meta.url);
|
|
23
25
|
const { version } = require("../package.json");
|
|
24
26
|
const program = new Command();
|
|
@@ -53,6 +55,7 @@ const getApi = () => {
|
|
|
53
55
|
return createApi({ baseUrl, accessToken, workspaceUuid });
|
|
54
56
|
};
|
|
55
57
|
registerAuthCommands(program, getApi);
|
|
58
|
+
registerVersionCommand(program, version);
|
|
56
59
|
registerInitCommand(program, getApi);
|
|
57
60
|
registerOrchestrationCommands(program, getApi);
|
|
58
61
|
registerWorkspaceManagementCommands(program, getApi);
|
|
@@ -67,6 +70,9 @@ registerSystemOfRecordIntegrationCommands(program, getApi);
|
|
|
67
70
|
registerUserManagementCommands(program, getApi);
|
|
68
71
|
registerAiCommands(program, getApi);
|
|
69
72
|
registerHostingCommands(program, getApi);
|
|
70
|
-
program
|
|
73
|
+
program
|
|
74
|
+
.parseAsync()
|
|
75
|
+
.then(() => maybeNotifyUpdate(version))
|
|
76
|
+
.catch((err) => {
|
|
71
77
|
failWith(err instanceof Error ? err.message : String(err));
|
|
72
78
|
});
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Best-effort "update available" nudge, printed to stderr after a command's
|
|
3
|
+
* own output. The registry is checked at most once per 24h (result cached in
|
|
4
|
+
* the config dir). Stays silent on non-TTY stderr (scripts/CI), when disabled
|
|
5
|
+
* via CARGO_NO_UPDATE_NOTIFIER, and on any network/parse failure — it must
|
|
6
|
+
* never block, delay, or break the command that triggered it.
|
|
7
|
+
*/
|
|
8
|
+
export declare function maybeNotifyUpdate(currentVersion: string): Promise<void>;
|
|
9
|
+
//# sourceMappingURL=updateNotifier.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"updateNotifier.d.ts","sourceRoot":"","sources":["../src/updateNotifier.ts"],"names":[],"mappings":"AAmBA;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA0B7E"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { colors, info } from "./commands/runHandler.js";
|
|
2
|
+
import { fetchLatestVersion, isOutdated, readUpdateCache, UPDATE_COMMAND, writeUpdateCache, } from "./version.js";
|
|
3
|
+
const CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000; // once per day
|
|
4
|
+
const NOTIFY_FETCH_TIMEOUT_MS = 1500;
|
|
5
|
+
const isDisabled = () => {
|
|
6
|
+
const flag = process.env["CARGO_NO_UPDATE_NOTIFIER"];
|
|
7
|
+
return (flag === "1" || flag === "true" || process.env["NO_UPDATE_NOTIFIER"] === "1");
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Best-effort "update available" nudge, printed to stderr after a command's
|
|
11
|
+
* own output. The registry is checked at most once per 24h (result cached in
|
|
12
|
+
* the config dir). Stays silent on non-TTY stderr (scripts/CI), when disabled
|
|
13
|
+
* via CARGO_NO_UPDATE_NOTIFIER, and on any network/parse failure — it must
|
|
14
|
+
* never block, delay, or break the command that triggered it.
|
|
15
|
+
*/
|
|
16
|
+
export async function maybeNotifyUpdate(currentVersion) {
|
|
17
|
+
// Only nudge interactive users; never pollute scripted/CI stderr.
|
|
18
|
+
if (process.stderr.isTTY !== true)
|
|
19
|
+
return;
|
|
20
|
+
if (isDisabled())
|
|
21
|
+
return;
|
|
22
|
+
try {
|
|
23
|
+
let cache = readUpdateCache();
|
|
24
|
+
const now = Date.now();
|
|
25
|
+
if (cache === undefined || now - cache.lastCheck > CHECK_INTERVAL_MS) {
|
|
26
|
+
const latestVersion = await fetchLatestVersion(NOTIFY_FETCH_TIMEOUT_MS);
|
|
27
|
+
cache = { lastCheck: now, latestVersion };
|
|
28
|
+
writeUpdateCache(cache);
|
|
29
|
+
}
|
|
30
|
+
if (isOutdated(currentVersion, cache.latestVersion)) {
|
|
31
|
+
info(`${colors.yellow("⚠")} A new version of cargo-ai is available: ${colors.dim(currentVersion)} → ${colors.green(cache.latestVersion)}`);
|
|
32
|
+
info(` Update with: ${colors.cyan(UPDATE_COMMAND)}`);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
// Fail open: an update check must never get in the way of the command.
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export declare const UPDATE_COMMAND = "npm install -g @cargo-ai/cli@latest";
|
|
2
|
+
export type UpdateCache = {
|
|
3
|
+
/** Epoch milliseconds of the last successful registry check. */
|
|
4
|
+
lastCheck: number;
|
|
5
|
+
/** Latest version reported by the npm registry at that time. */
|
|
6
|
+
latestVersion: string;
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* Fetch the latest published version of the CLI from the npm registry.
|
|
10
|
+
* Throws on network error, timeout, or unexpected response shape — callers
|
|
11
|
+
* decide whether to surface or swallow the failure.
|
|
12
|
+
*/
|
|
13
|
+
export declare function fetchLatestVersion(timeoutMs?: number): Promise<string>;
|
|
14
|
+
/**
|
|
15
|
+
* Compare two semver-ish strings. Returns 1 if `a > b`, -1 if `a < b`, 0 if
|
|
16
|
+
* equal. Only the major.minor.patch core is compared numerically; a version
|
|
17
|
+
* carrying a prerelease tag (e.g. `1.2.0-beta.1`) ranks below the same core
|
|
18
|
+
* without one, matching semver precedence rules.
|
|
19
|
+
*/
|
|
20
|
+
export declare function compareSemver(a: string, b: string): number;
|
|
21
|
+
/** True when `current` is strictly older than `latest`. */
|
|
22
|
+
export declare function isOutdated(current: string, latest: string): boolean;
|
|
23
|
+
export declare function readUpdateCache(): UpdateCache | undefined;
|
|
24
|
+
export declare function writeUpdateCache(cache: UpdateCache): void;
|
|
25
|
+
//# sourceMappingURL=version.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AASA,eAAO,MAAM,cAAc,wCAAwC,CAAC;AAEpE,MAAM,MAAM,WAAW,GAAG;IACxB,gEAAgE;IAChE,SAAS,EAAE,MAAM,CAAC;IAClB,gEAAgE;IAChE,aAAa,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF;;;;GAIG;AACH,wBAAsB,kBAAkB,CACtC,SAAS,GAAE,MAAiC,GAC3C,OAAO,CAAC,MAAM,CAAC,CAiBjB;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CA2B1D;AAED,2DAA2D;AAC3D,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAEnE;AAED,wBAAgB,eAAe,IAAI,WAAW,GAAG,SAAS,CAsBzD;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI,CAOzD"}
|
package/build/version.js
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { getConfigDir } from "./credentials.js";
|
|
4
|
+
const NPM_REGISTRY_URL = "https://registry.npmjs.org/@cargo-ai/cli/latest";
|
|
5
|
+
const DEFAULT_FETCH_TIMEOUT_MS = 1500;
|
|
6
|
+
const UPDATE_CACHE_FILE = join(getConfigDir(), "update-check.json");
|
|
7
|
+
export const UPDATE_COMMAND = "npm install -g @cargo-ai/cli@latest";
|
|
8
|
+
/**
|
|
9
|
+
* Fetch the latest published version of the CLI from the npm registry.
|
|
10
|
+
* Throws on network error, timeout, or unexpected response shape — callers
|
|
11
|
+
* decide whether to surface or swallow the failure.
|
|
12
|
+
*/
|
|
13
|
+
export async function fetchLatestVersion(timeoutMs = DEFAULT_FETCH_TIMEOUT_MS) {
|
|
14
|
+
const response = await fetch(NPM_REGISTRY_URL, {
|
|
15
|
+
signal: AbortSignal.timeout(timeoutMs),
|
|
16
|
+
headers: { accept: "application/json" },
|
|
17
|
+
});
|
|
18
|
+
if (response.ok === false) {
|
|
19
|
+
throw new Error(`npm registry returned HTTP ${response.status}`);
|
|
20
|
+
}
|
|
21
|
+
const body = (await response.json());
|
|
22
|
+
if (typeof body.version !== "string") {
|
|
23
|
+
throw new Error("npm registry response did not include a version");
|
|
24
|
+
}
|
|
25
|
+
return body.version;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Compare two semver-ish strings. Returns 1 if `a > b`, -1 if `a < b`, 0 if
|
|
29
|
+
* equal. Only the major.minor.patch core is compared numerically; a version
|
|
30
|
+
* carrying a prerelease tag (e.g. `1.2.0-beta.1`) ranks below the same core
|
|
31
|
+
* without one, matching semver precedence rules.
|
|
32
|
+
*/
|
|
33
|
+
export function compareSemver(a, b) {
|
|
34
|
+
const parse = (v) => {
|
|
35
|
+
const clean = v.trim().replace(/^v/, "");
|
|
36
|
+
const [core = "", pre = ""] = clean.split("-", 2);
|
|
37
|
+
const nums = core.split(".").map((n) => {
|
|
38
|
+
const parsed = Number.parseInt(n, 10);
|
|
39
|
+
return Number.isNaN(parsed) ? 0 : parsed;
|
|
40
|
+
});
|
|
41
|
+
return { nums: [nums[0] ?? 0, nums[1] ?? 0, nums[2] ?? 0], pre };
|
|
42
|
+
};
|
|
43
|
+
const pa = parse(a);
|
|
44
|
+
const pb = parse(b);
|
|
45
|
+
for (let i = 0; i < 3; i += 1) {
|
|
46
|
+
const na = pa.nums[i] ?? 0;
|
|
47
|
+
const nb = pb.nums[i] ?? 0;
|
|
48
|
+
if (na !== nb) {
|
|
49
|
+
return na > nb ? 1 : -1;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
if (pa.pre === pb.pre)
|
|
53
|
+
return 0;
|
|
54
|
+
// A version without a prerelease tag outranks one that has it.
|
|
55
|
+
if (pa.pre === "")
|
|
56
|
+
return 1;
|
|
57
|
+
if (pb.pre === "")
|
|
58
|
+
return -1;
|
|
59
|
+
return pa.pre > pb.pre ? 1 : -1;
|
|
60
|
+
}
|
|
61
|
+
/** True when `current` is strictly older than `latest`. */
|
|
62
|
+
export function isOutdated(current, latest) {
|
|
63
|
+
return compareSemver(current, latest) < 0;
|
|
64
|
+
}
|
|
65
|
+
export function readUpdateCache() {
|
|
66
|
+
if (existsSync(UPDATE_CACHE_FILE) === false)
|
|
67
|
+
return undefined;
|
|
68
|
+
try {
|
|
69
|
+
const parsed = JSON.parse(readFileSync(UPDATE_CACHE_FILE, "utf-8"));
|
|
70
|
+
if (typeof parsed.lastCheck === "number" &&
|
|
71
|
+
typeof parsed.latestVersion === "string") {
|
|
72
|
+
return {
|
|
73
|
+
lastCheck: parsed.lastCheck,
|
|
74
|
+
latestVersion: parsed.latestVersion,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
return undefined;
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
return undefined;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
export function writeUpdateCache(cache) {
|
|
84
|
+
try {
|
|
85
|
+
mkdirSync(getConfigDir(), { recursive: true });
|
|
86
|
+
writeFileSync(UPDATE_CACHE_FILE, JSON.stringify(cache, null, 2) + "\n");
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
// Best-effort cache: a write failure should never break a command.
|
|
90
|
+
}
|
|
91
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cargo-ai/cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.18",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Command-line interface for the Cargo API",
|
|
6
6
|
"engines": {
|
|
@@ -28,9 +28,9 @@
|
|
|
28
28
|
"format:check": "prettier --check ."
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@cargo-ai/api": "^1.0.
|
|
31
|
+
"@cargo-ai/api": "^1.0.26",
|
|
32
32
|
"@cargo-ai/app-sdk": "^1.0.0",
|
|
33
|
-
"@cargo-ai/worker-sdk": "^1.0.
|
|
33
|
+
"@cargo-ai/worker-sdk": "^1.0.1",
|
|
34
34
|
"commander": "^12.1.0"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|