@cargo-ai/cli 1.0.44 → 1.0.46

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.
Files changed (62) hide show
  1. package/README.md +50 -10
  2. package/build/api.d.ts +2 -1
  3. package/build/api.d.ts.map +1 -1
  4. package/build/api.js +5 -1
  5. package/build/commands/auth/auth0.d.ts +33 -0
  6. package/build/commands/auth/auth0.d.ts.map +1 -0
  7. package/build/commands/auth/auth0.js +90 -0
  8. package/build/commands/auth/email.d.ts +16 -0
  9. package/build/commands/auth/email.d.ts.map +1 -0
  10. package/build/commands/auth/email.js +93 -0
  11. package/build/commands/auth/index.d.ts +19 -1
  12. package/build/commands/auth/index.d.ts.map +1 -1
  13. package/build/commands/auth/index.js +121 -59
  14. package/build/commands/auth/loginChannel.d.ts +21 -0
  15. package/build/commands/auth/loginChannel.d.ts.map +1 -0
  16. package/build/commands/auth/loginChannel.js +42 -0
  17. package/build/commands/auth/oauth.d.ts +2 -6
  18. package/build/commands/auth/oauth.d.ts.map +1 -1
  19. package/build/commands/auth/oauth.js +54 -91
  20. package/build/commands/auth/passwordless.d.ts +22 -0
  21. package/build/commands/auth/passwordless.d.ts.map +1 -0
  22. package/build/commands/auth/passwordless.js +70 -0
  23. package/build/commands/auth/session.d.ts +21 -0
  24. package/build/commands/auth/session.d.ts.map +1 -0
  25. package/build/commands/auth/session.js +55 -0
  26. package/build/commands/auth/workspace.d.ts +9 -1
  27. package/build/commands/auth/workspace.d.ts.map +1 -1
  28. package/build/commands/auth/workspace.js +42 -69
  29. package/build/commands/billing/addPaymentMethod.d.ts +26 -0
  30. package/build/commands/billing/addPaymentMethod.d.ts.map +1 -0
  31. package/build/commands/billing/addPaymentMethod.js +57 -0
  32. package/build/commands/billing/subscription.d.ts.map +1 -1
  33. package/build/commands/billing/subscription.js +28 -1
  34. package/build/commands/doctor.js +3 -3
  35. package/build/commands/mcp.d.ts.map +1 -1
  36. package/build/commands/mcp.js +35 -8
  37. package/build/commands/orchestration/action.d.ts.map +1 -1
  38. package/build/commands/orchestration/action.js +11 -1
  39. package/build/commands/orchestration/index.d.ts.map +1 -1
  40. package/build/commands/orchestration/index.js +6 -1
  41. package/build/commands/orchestration/node.d.ts.map +1 -1
  42. package/build/commands/orchestration/node.js +41 -1
  43. package/build/commands/runHandler.d.ts +6 -0
  44. package/build/commands/runHandler.d.ts.map +1 -1
  45. package/build/commands/runHandler.js +34 -4
  46. package/build/config.d.ts +22 -1
  47. package/build/config.d.ts.map +1 -1
  48. package/build/config.js +44 -3
  49. package/build/credentials.d.ts +1 -10
  50. package/build/credentials.d.ts.map +1 -1
  51. package/build/credentials.js +4 -34
  52. package/build/index.js +14 -7
  53. package/build/oauthConfig.d.ts +1 -6
  54. package/build/oauthConfig.d.ts.map +1 -1
  55. package/build/oauthConfig.js +9 -14
  56. package/build/utils/openBrowser.d.ts +7 -0
  57. package/build/utils/openBrowser.d.ts.map +1 -0
  58. package/build/utils/openBrowser.js +29 -0
  59. package/build/utils/prompt.d.ts +12 -0
  60. package/build/utils/prompt.d.ts.map +1 -0
  61. package/build/utils/prompt.js +38 -0
  62. package/package.json +4 -2
package/build/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from "node:module";
3
- import { registerCommands as registerCdkCommands, registerManifestCommands, } from "@cargo-ai/cdk/cli";
3
+ import { registerCommands as registerCdkCommands, registerManifestCommands, SessionExpiredError, } from "@cargo-ai/cdk/cli";
4
4
  import { Command } from "commander";
5
5
  import { createApi } from "./api.js";
6
6
  import { registerAiCommands } from "./commands/ai/index.js";
@@ -35,8 +35,9 @@ program
35
35
  .version(version)
36
36
  .addHelpText("after", `
37
37
  Authentication:
38
- With API token: cargo-ai login --token <your-token>
38
+ Emailed code: cargo-ai login --email you@company.com (no browser; signs you up on first use)
39
39
  Browser sign-in: cargo-ai login --oauth
40
+ With API token: cargo-ai login --token <your-token>
40
41
  Use env variables: CARGO_API_TOKEN, CARGO_WORKSPACE_UUID, CARGO_BASE_URL
41
42
  Check status: cargo-ai whoami
42
43
 
@@ -53,11 +54,11 @@ Exit codes:
53
54
  Run "cargo-ai <command> --help" for details on a specific command group.
54
55
  Run "cargo-ai <command> <subcommand> --help" for details on a subcommand.`);
55
56
  const getApi = () => {
56
- const { baseUrl, accessToken, workspaceUuid } = getConfig();
57
- if (accessToken === undefined) {
58
- failWith("Not authenticated. Run 'cargo-ai login --token <token>' or 'cargo-ai login --oauth'.", { code: ExitCodes.NotAuthenticated });
57
+ const { baseUrl, getAccessToken, workspaceUuid } = getConfig();
58
+ if (getAccessToken === undefined) {
59
+ failWith("Not authenticated. Run 'cargo-ai login --email <email>' (no browser needed) or 'cargo-ai login --oauth'.", { code: ExitCodes.NotAuthenticated });
59
60
  }
60
- return createApi({ baseUrl, accessToken, workspaceUuid });
61
+ return createApi({ baseUrl, getAccessToken, workspaceUuid });
61
62
  };
62
63
  registerAuthCommands(program, getApi);
63
64
  registerVersionCommand(program, version);
@@ -89,5 +90,11 @@ program
89
90
  .parseAsync()
90
91
  .then(() => maybeNotifyUpdate(version))
91
92
  .catch((err) => {
92
- failWith(err instanceof Error ? err.message : String(err));
93
+ // An expired session is the ordinary way to lose authentication, so it has
94
+ // to carry the documented exit code rather than the generic one.
95
+ failWith(err instanceof Error ? err.message : String(err), {
96
+ code: err instanceof SessionExpiredError
97
+ ? ExitCodes.NotAuthenticated
98
+ : undefined,
99
+ });
93
100
  });
@@ -4,10 +4,5 @@ export type OAuthConfig = {
4
4
  audience: string;
5
5
  scope: string;
6
6
  };
7
- export type OAuthConfigOverrides = {
8
- domain?: string;
9
- clientId?: string;
10
- audience?: string;
11
- };
12
- export declare function getOAuthConfig(overrides: OAuthConfigOverrides): OAuthConfig;
7
+ export declare function getOAuthConfig(): OAuthConfig;
13
8
  //# sourceMappingURL=oauthConfig.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"oauthConfig.d.ts","sourceRoot":"","sources":["../src/oauthConfig.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,WAAW,GAAG;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAOF,wBAAgB,cAAc,CAAC,SAAS,EAAE,oBAAoB,GAAG,WAAW,CAO3E"}
1
+ {"version":3,"file":"oauthConfig.d.ts","sourceRoot":"","sources":["../src/oauthConfig.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,WAAW,GAAG;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAOF,wBAAgB,cAAc,IAAI,WAAW,CAO5C"}
@@ -1,17 +1,12 @@
1
- const DEFAULT_DOMAIN = "auth.getcargo.io";
2
- const DEFAULT_AUDIENCE = "https://api.getcargo.io";
3
- const DEFAULT_SCOPE = "openid profile email offline_access";
4
- const DEFAULT_CLIENT_ID = "oUc99KlLSMAYUAPgxTUyqazef0sxR93b";
5
- export function getOAuthConfig(overrides) {
1
+ const DOMAIN = "auth.getcargo.io";
2
+ const AUDIENCE = "https://api.getcargo.io";
3
+ const SCOPE = "openid profile email offline_access";
4
+ const CLIENT_ID = "oUc99KlLSMAYUAPgxTUyqazef0sxR93b";
5
+ export function getOAuthConfig() {
6
6
  return {
7
- domain: pickString(overrides.domain, DEFAULT_DOMAIN),
8
- audience: pickString(overrides.audience, DEFAULT_AUDIENCE),
9
- clientId: pickString(overrides.clientId, DEFAULT_CLIENT_ID),
10
- scope: DEFAULT_SCOPE,
7
+ domain: DOMAIN,
8
+ audience: AUDIENCE,
9
+ clientId: CLIENT_ID,
10
+ scope: SCOPE,
11
11
  };
12
12
  }
13
- const pickString = (override, fallback) => {
14
- if (override !== undefined && override.length > 0)
15
- return override;
16
- return fallback;
17
- };
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Best-effort browser launch. Every caller also prints the URL, so a failure
3
+ * here is never fatal: headless boxes and sandboxes simply fall back to the
4
+ * user opening the link themselves.
5
+ */
6
+ export declare function openBrowser(url: string): void;
7
+ //# sourceMappingURL=openBrowser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openBrowser.d.ts","sourceRoot":"","sources":["../../src/utils/openBrowser.ts"],"names":[],"mappings":"AAGA;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAc7C"}
@@ -0,0 +1,29 @@
1
+ import { spawn } from "node:child_process";
2
+ import { platform } from "node:process";
3
+ /**
4
+ * Best-effort browser launch. Every caller also prints the URL, so a failure
5
+ * here is never fatal: headless boxes and sandboxes simply fall back to the
6
+ * user opening the link themselves.
7
+ */
8
+ export function openBrowser(url) {
9
+ const command = pickOpenCommand();
10
+ const args = platform === "win32" ? ["/c", "start", "", url] : [url];
11
+ try {
12
+ const child = spawn(command, args, {
13
+ detached: true,
14
+ stdio: "ignore",
15
+ });
16
+ child.on("error", () => undefined);
17
+ child.unref();
18
+ }
19
+ catch {
20
+ // Intentionally ignored — see above.
21
+ }
22
+ }
23
+ function pickOpenCommand() {
24
+ if (platform === "darwin")
25
+ return "open";
26
+ if (platform === "win32")
27
+ return "cmd";
28
+ return "xdg-open";
29
+ }
@@ -0,0 +1,12 @@
1
+ /// <reference types="node" resolution-mode="require"/>
2
+ export type PromptInput = {
3
+ stream: NodeJS.ReadableStream;
4
+ close: () => void;
5
+ };
6
+ export declare function openPromptInput(): PromptInput | undefined;
7
+ /**
8
+ * Asks a single question on the controlling terminal. Prompts are written to
9
+ * stderr so that piping stdout to `jq` keeps working.
10
+ */
11
+ export declare function askQuestion(input: NodeJS.ReadableStream, question: string): Promise<string | undefined>;
12
+ //# sourceMappingURL=prompt.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt.d.ts","sourceRoot":"","sources":["../../src/utils/prompt.ts"],"names":[],"mappings":";AAIA,MAAM,MAAM,WAAW,GAAG;IACxB,MAAM,EAAE,MAAM,CAAC,cAAc,CAAC;IAC9B,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB,CAAC;AAMF,wBAAgB,eAAe,IAAI,WAAW,GAAG,SAAS,CAYzD;AAED;;;GAGG;AACH,wBAAsB,WAAW,CAC/B,KAAK,EAAE,MAAM,CAAC,cAAc,EAC5B,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAe7B"}
@@ -0,0 +1,38 @@
1
+ import * as fs from "node:fs";
2
+ import * as readline from "node:readline/promises";
3
+ import * as tty from "node:tty";
4
+ // Interactive prompts must not assume stdin is a terminal: `curl | sh`
5
+ // installers and agent-driven shells pipe stdin while the controlling
6
+ // terminal stays reachable via /dev/tty. Prefer stdin when it is a TTY,
7
+ // otherwise fall back to opening /dev/tty directly.
8
+ export function openPromptInput() {
9
+ if (process.stdin.isTTY === true) {
10
+ return { stream: process.stdin, close: () => undefined };
11
+ }
12
+ try {
13
+ const fd = fs.openSync("/dev/tty", "r");
14
+ const stream = new tty.ReadStream(fd);
15
+ return { stream, close: () => stream.destroy() };
16
+ }
17
+ catch {
18
+ return undefined;
19
+ }
20
+ }
21
+ /**
22
+ * Asks a single question on the controlling terminal. Prompts are written to
23
+ * stderr so that piping stdout to `jq` keeps working.
24
+ */
25
+ export async function askQuestion(input, question) {
26
+ const rl = readline.createInterface({ input, output: process.stderr });
27
+ try {
28
+ const answer = await rl.question(question);
29
+ const trimmed = answer.trim();
30
+ if (trimmed === "") {
31
+ return undefined;
32
+ }
33
+ return trimmed;
34
+ }
35
+ finally {
36
+ rl.close();
37
+ }
38
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cargo-ai/cli",
3
- "version": "1.0.44",
3
+ "version": "1.0.46",
4
4
  "private": false,
5
5
  "license": "UNLICENSED",
6
6
  "description": "Command-line interface for the Cargo API",
@@ -23,6 +23,8 @@
23
23
  "build": "tsc --build",
24
24
  "dev": "tsx watch src/index.ts",
25
25
  "start": "node build/index.js",
26
+ "test": "npm run build && node --test \"test/**/*.test.mjs\"",
27
+ "test:watch": "node --test --watch \"test/**/*.test.mjs\"",
26
28
  "type:check": "tsc --noEmit",
27
29
  "lint": "eslint ./ --fix",
28
30
  "lint:check": "eslint ./ --max-warnings=0",
@@ -30,7 +32,7 @@
30
32
  "format:check": "prettier --check ."
31
33
  },
32
34
  "dependencies": {
33
- "@cargo-ai/api": "^1.0.56",
35
+ "@cargo-ai/api": "^1.0.57",
34
36
  "@cargo-ai/app-sdk": "^1.0.5",
35
37
  "@cargo-ai/cdk": "*",
36
38
  "@cargo-ai/types": "*",