@cargo-ai/cli 1.0.77 → 1.0.80

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 (73) hide show
  1. package/README.md +12 -0
  2. package/build/commands/ai/chat.d.ts.map +1 -1
  3. package/build/commands/ai/chat.js +6 -0
  4. package/build/commands/ai/message.d.ts.map +1 -1
  5. package/build/commands/ai/message.js +10 -0
  6. package/build/commands/ai/release.d.ts.map +1 -1
  7. package/build/commands/ai/release.js +29 -2
  8. package/build/commands/ask/argvFlags.d.ts +18 -0
  9. package/build/commands/ask/argvFlags.d.ts.map +1 -0
  10. package/build/commands/ask/argvFlags.js +46 -0
  11. package/build/commands/ask/artifacts.d.ts +2 -0
  12. package/build/commands/ask/artifacts.d.ts.map +1 -0
  13. package/build/commands/ask/artifacts.js +100 -0
  14. package/build/commands/ask/binding.d.ts +13 -0
  15. package/build/commands/ask/binding.d.ts.map +1 -0
  16. package/build/commands/ask/binding.js +19 -0
  17. package/build/commands/ask/claudeConfig.d.ts +23 -0
  18. package/build/commands/ask/claudeConfig.d.ts.map +1 -0
  19. package/build/commands/ask/claudeConfig.js +33 -0
  20. package/build/commands/ask/completer.d.ts +48 -0
  21. package/build/commands/ask/completer.d.ts.map +1 -0
  22. package/build/commands/ask/completer.js +217 -0
  23. package/build/commands/ask/history.d.ts +32 -0
  24. package/build/commands/ask/history.d.ts.map +1 -0
  25. package/build/commands/ask/history.js +122 -0
  26. package/build/commands/ask/index.d.ts +14 -0
  27. package/build/commands/ask/index.d.ts.map +1 -0
  28. package/build/commands/ask/index.js +111 -0
  29. package/build/commands/ask/localHarness.d.ts +225 -0
  30. package/build/commands/ask/localHarness.d.ts.map +1 -0
  31. package/build/commands/ask/localHarness.js +1074 -0
  32. package/build/commands/ask/messageStream.d.ts +33 -0
  33. package/build/commands/ask/messageStream.d.ts.map +1 -0
  34. package/build/commands/ask/messageStream.js +114 -0
  35. package/build/commands/ask/persist.d.ts +5 -0
  36. package/build/commands/ask/persist.d.ts.map +1 -0
  37. package/build/commands/ask/persist.js +31 -0
  38. package/build/commands/ask/pnpmShim.d.ts +20 -0
  39. package/build/commands/ask/pnpmShim.d.ts.map +1 -0
  40. package/build/commands/ask/pnpmShim.js +39 -0
  41. package/build/commands/ask/prompt.d.ts +20 -0
  42. package/build/commands/ask/prompt.d.ts.map +1 -0
  43. package/build/commands/ask/prompt.js +228 -0
  44. package/build/commands/ask/rewriteChatFlag.d.ts +9 -0
  45. package/build/commands/ask/rewriteChatFlag.d.ts.map +1 -0
  46. package/build/commands/ask/rewriteChatFlag.js +26 -0
  47. package/build/commands/ask/session.d.ts +94 -0
  48. package/build/commands/ask/session.d.ts.map +1 -0
  49. package/build/commands/ask/session.js +965 -0
  50. package/build/commands/ask/slash.d.ts +20 -0
  51. package/build/commands/ask/slash.d.ts.map +1 -0
  52. package/build/commands/ask/slash.js +73 -0
  53. package/build/commands/ask/state.d.ts +9 -0
  54. package/build/commands/ask/state.d.ts.map +1 -0
  55. package/build/commands/ask/state.js +18 -0
  56. package/build/commands/bookDemo.d.ts +14 -0
  57. package/build/commands/bookDemo.d.ts.map +1 -0
  58. package/build/commands/bookDemo.js +100 -0
  59. package/build/commands/runHandler.d.ts +9 -1
  60. package/build/commands/runHandler.d.ts.map +1 -1
  61. package/build/commands/runHandler.js +16 -1
  62. package/build/index.js +56 -18
  63. package/build/paletteLayout.d.ts +6 -1
  64. package/build/paletteLayout.d.ts.map +1 -1
  65. package/build/paletteLayout.js +35 -9
  66. package/build/utils/cdkState.d.ts +17 -4
  67. package/build/utils/cdkState.d.ts.map +1 -1
  68. package/build/utils/cdkState.js +26 -4
  69. package/build/utils/loadCompiledAgent.d.ts.map +1 -1
  70. package/build/utils/loadCompiledAgent.js +51 -11
  71. package/build/utils/prompt.d.ts.map +1 -1
  72. package/build/utils/prompt.js +4 -1
  73. package/package.json +8 -4
package/README.md CHANGED
@@ -54,6 +54,18 @@ cargo-ai whoami
54
54
  cargo-ai logout
55
55
  ```
56
56
 
57
+ ### Book a demo
58
+
59
+ `cargo-ai book-demo` opens the same Cal.com form as the website's **Talk to sales** button. A person still has to pick a time — the command does not create a booking. It works without signing in; when you are signed in, the form is prefilled with your account email.
60
+
61
+ ```bash
62
+ cargo-ai book-demo
63
+ cargo-ai book-demo --email you@company.com
64
+ cargo-ai book-demo --no-open # print the URL only
65
+ ```
66
+
67
+ This is not the guided product tour. That is `cargo-ai start --continue demo`.
68
+
57
69
  ### Sign-in without a browser (`--email`)
58
70
 
59
71
  `cargo-ai login --email you@company.com` emails you a one-time code, then creates your account (on first use) and a workspace — no browser and no dashboard visit at any point. On a terminal the code is read back from a prompt. Where there is no terminal (sandboxes, agent shells) the first call sends the code and exits, so you can finish with:
@@ -1 +1 @@
1
- {"version":3,"file":"chat.d.ts","sourceRoot":"","sources":["../../../src/commands/ai/chat.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,CA0H7E"}
1
+ {"version":3,"file":"chat.d.ts","sourceRoot":"","sources":["../../../src/commands/ai/chat.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,CAyI7E"}
@@ -41,6 +41,8 @@ export function registerChatCommands(parent, getApi) {
41
41
  .option("--name <name>", "Chat name (string)")
42
42
  .option("--agent-uuid <uuid>", "Agent UUID to associate with (string)")
43
43
  .option("--release-uuid <uuid>", "Release UUID to pin to (string)")
44
+ .option("--harness-slug <slug>", "Coding-agent runtime. Currently only claudeCode. When omitted, later turns use the agent's pinned release, if any.")
45
+ .option("--repository <json>", "Git workspace for a coding harness (JSON object: connectorUuid, repository as owner/name, defaultBranch, rootDirectory, env)")
44
46
  .addHelpText("after", `
45
47
  Examples:
46
48
  $ cargo-ai ai chat create --trigger '{"type":"draft"}'
@@ -56,6 +58,10 @@ Trigger object shapes:
56
58
  name: opts.name,
57
59
  agentUuid: opts.agentUuid,
58
60
  releaseUuid: opts.releaseUuid,
61
+ harnessSlug: opts.harnessSlug,
62
+ repository: opts.repository !== undefined
63
+ ? parseJson(opts.repository, "--repository")
64
+ : undefined,
59
65
  }));
60
66
  outputJson(result);
61
67
  });
@@ -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;AAkCxC,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,OAAO,EACf,MAAM,EAAE,MAAM,GAAG,GAChB,IAAI,CAgSN"}
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;AAoCxC,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,OAAO,EACf,MAAM,EAAE,MAAM,GAAG,GAChB,IAAI,CAmTN"}
@@ -27,6 +27,8 @@ export function registerMessageCommands(parent, getApi) {
27
27
  .option("--integration-slug <slug>", "Integration slug (string)")
28
28
  .option("--connector-uuid <uuid>", "Connector UUID (string)")
29
29
  .option("--language-model-slug <slug>", "Language model slug (string)")
30
+ .option("--harness-slug <slug>", "Coding-agent runtime. Currently only claudeCode. When omitted, later turns use the agent's pinned release, if any.")
31
+ .option("--repository <json>", "Git workspace for a coding harness (JSON object: connectorUuid, repository as owner/name, defaultBranch, rootDirectory, env)")
30
32
  .option("--output <json>", 'Output format for the assistant message (JSON object, e.g. \'{"type":"text"}\' or \'{"type":"jsonSchema","jsonSchema":{...}}\'). Defaults to text when omitted.')
31
33
  .option("--wait-until-finished [true|false]", "Poll the assistant message until finished before returning (defaults to true when passed bare)", parseBooleanOption)
32
34
  .option("--polling-interval <ms>", "Polling interval in milliseconds, used with --wait-until-finished (integer, default: 5000)", "5000")
@@ -65,6 +67,8 @@ MCP client shape: { "name": string, "url": string }`)
65
67
  ["--integration-slug", opts.integrationSlug],
66
68
  ["--connector-uuid", opts.connectorUuid],
67
69
  ["--language-model-slug", opts.languageModelSlug],
70
+ ["--harness-slug", opts.harnessSlug],
71
+ ["--repository", opts.repository],
68
72
  ["--output", opts.output],
69
73
  ]
70
74
  .filter(([, value]) => value !== undefined)
@@ -85,6 +89,8 @@ MCP client shape: { "name": string, "url": string }`)
85
89
  maxSteps: resolved.maxSteps,
86
90
  connectorUuid: resolved.connectorUuid,
87
91
  languageModelSlug: resolved.languageModelSlug,
92
+ harnessSlug: resolved.harnessSlug,
93
+ repository: resolved.repository,
88
94
  output: resolved.output,
89
95
  };
90
96
  if (resolved.connectorUuid !== undefined) {
@@ -119,6 +125,10 @@ MCP client shape: { "name": string, "url": string }`)
119
125
  integrationSlug: opts.integrationSlug,
120
126
  connectorUuid: opts.connectorUuid,
121
127
  languageModelSlug: opts.languageModelSlug,
128
+ harnessSlug: opts.harnessSlug,
129
+ repository: opts.repository !== undefined
130
+ ? parseJson(opts.repository, "--repository")
131
+ : undefined,
122
132
  output: opts.output !== undefined
123
133
  ? parseJson(opts.output, "--output")
124
134
  : undefined,
@@ -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;AAIxC,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,OAAO,EACf,MAAM,EAAE,MAAM,GAAG,GAChB,IAAI,CA0SN"}
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;AAIxC,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,OAAO,EACf,MAAM,EAAE,MAAM,GAAG,GAChB,IAAI,CA0VN"}
@@ -63,6 +63,8 @@ export function registerReleaseCommands(parent, getApi) {
63
63
  .option("--integration-slug <slug>", "LLM integration slug (string)")
64
64
  .option("--connector-uuid <uuid>", "Connector UUID (string)")
65
65
  .option("--language-model-slug <slug>", "Language model slug (string)")
66
+ .option("--harness-slug <slug>", "Coding-agent runtime. Currently only claudeCode.")
67
+ .option("--repository <json>", "Git workspace for a coding harness (JSON object: connectorUuid, repository as owner/name, defaultBranch, rootDirectory, env)")
66
68
  .option("--actions <json>", "Actions configuration (JSON array of action objects)")
67
69
  .option("--mcp-clients <json>", "MCP clients configuration (JSON array of MCP client objects)")
68
70
  .option("--resources <json>", "Resources configuration (JSON array of resource objects)")
@@ -95,6 +97,10 @@ Set "isReadOnly": false on a model resource to grant the agent write tools (inse
95
97
  integrationSlug: opts.integrationSlug,
96
98
  connectorUuid: opts.connectorUuid,
97
99
  languageModelSlug: opts.languageModelSlug,
100
+ harnessSlug: opts.harnessSlug,
101
+ repository: opts.repository !== undefined
102
+ ? parseJson(opts.repository, "--repository")
103
+ : undefined,
98
104
  actions: opts.actions !== undefined
99
105
  ? parseJson(opts.actions, "--actions")
100
106
  : undefined,
@@ -120,8 +126,10 @@ Set "isReadOnly": false on a model resource to grant the agent write tools (inse
120
126
  .command("deploy-draft")
121
127
  .description("Deploy the draft release to production")
122
128
  .requiredOption("--agent-uuid <uuid>", "Agent UUID (string, required)")
123
- .requiredOption("--integration-slug <slug>", "LLM integration slug (string, required)")
124
- .requiredOption("--language-model-slug <slug>", "Language model slug (string, required)")
129
+ .option("--integration-slug <slug>", "LLM integration slug (string). Unused when --harness-slug is set.")
130
+ .option("--language-model-slug <slug>", "Language model slug (string). Unused when --harness-slug is set.")
131
+ .option("--harness-slug <slug>", "Coding-agent runtime. Currently only claudeCode. When set, --integration-slug and --language-model-slug are unused.")
132
+ .option("--repository <json>", "Git workspace for a coding harness (JSON object: connectorUuid, repository as owner/name, defaultBranch, rootDirectory, env)")
125
133
  .option("--version <version>", "Semver release version, e.g. 1.0.0 (string, auto-incremented if omitted)")
126
134
  .requiredOption("--actions <json>", "Actions configuration (JSON array of action objects, required)")
127
135
  .requiredOption("--mcp-clients <json>", "MCP clients configuration (JSON array, required)")
@@ -135,12 +143,31 @@ Set "isReadOnly": false on a model resource to grant the agent write tools (inse
135
143
  .option("--connector-uuid <uuid>", "Connector UUID (string)")
136
144
  .option("--description <text>", "Release description (string)")
137
145
  .option("--options <json>", "Additional options (JSON object)")
146
+ .addHelpText("after", `
147
+ Examples:
148
+ $ cargo-ai ai release deploy-draft --agent-uuid <uuid> \\
149
+ --integration-slug openai --language-model-slug gpt-4o \\
150
+ --actions '[]' --mcp-clients '[]' --resources '[]' \\
151
+ --capabilities '[]' --suggested-actions '[]'
152
+
153
+ $ cargo-ai ai release deploy-draft --agent-uuid <uuid> \\
154
+ --harness-slug claudeCode \\
155
+ --repository '{"connectorUuid":"<github-uuid>","repository":"acme/app"}' \\
156
+ --actions '[]' --mcp-clients '[]' --resources '[]' \\
157
+ --capabilities '[]' --suggested-actions '[]'
158
+
159
+ A tool-loop agent needs --integration-slug and --language-model-slug. A
160
+ --harness-slug claudeCode agent does not — those flags are unused.`)
138
161
  .action(async (opts) => {
139
162
  const api = getApi();
140
163
  const result = await handleApiCall(() => api.ai.release.deployDraft({
141
164
  agentUuid: opts.agentUuid,
142
165
  integrationSlug: opts.integrationSlug,
143
166
  languageModelSlug: opts.languageModelSlug,
167
+ harnessSlug: opts.harnessSlug,
168
+ repository: opts.repository !== undefined
169
+ ? parseJson(opts.repository, "--repository")
170
+ : undefined,
144
171
  version: opts.version,
145
172
  actions: parseJson(opts.actions, "--actions"),
146
173
  mcpClients: parseJson(opts.mcpClients, "--mcp-clients"),
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Stop Ask's boolean flags from eating the question.
3
+ *
4
+ * They are declared `--flag [true|false]` so `--flag false` works and the
5
+ * palette can offer the two values as a menu. Commander reads an optional-value
6
+ * option greedily, though: in `ask --print "summarise this"` the message
7
+ * becomes the flag's value and `parseBooleanOption` rejects it, so the
8
+ * documented form fails at parse time.
9
+ *
10
+ * Writing the value inline (`--print=true`) settles the option before Commander
11
+ * looks at the next token, so the message stays a positional argument. Only
12
+ * done when the next token is not a boolean, which leaves `--print false` and
13
+ * `--print=false` exactly as the caller typed them.
14
+ *
15
+ * Exported for tests; `index.ts` is the only production caller.
16
+ */
17
+ export declare function pinAskBooleanFlags(argv: readonly string[]): string[];
18
+ //# sourceMappingURL=argvFlags.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"argvFlags.d.ts","sourceRoot":"","sources":["../../../src/commands/ask/argvFlags.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,EAAE,CAoCpE"}
@@ -0,0 +1,46 @@
1
+ /** Ask's boolean flags, declared as `--flag [true|false]`. */
2
+ const ASK_BOOLEAN_FLAGS = ["--print", "--continue"];
3
+ /**
4
+ * Stop Ask's boolean flags from eating the question.
5
+ *
6
+ * They are declared `--flag [true|false]` so `--flag false` works and the
7
+ * palette can offer the two values as a menu. Commander reads an optional-value
8
+ * option greedily, though: in `ask --print "summarise this"` the message
9
+ * becomes the flag's value and `parseBooleanOption` rejects it, so the
10
+ * documented form fails at parse time.
11
+ *
12
+ * Writing the value inline (`--print=true`) settles the option before Commander
13
+ * looks at the next token, so the message stays a positional argument. Only
14
+ * done when the next token is not a boolean, which leaves `--print false` and
15
+ * `--print=false` exactly as the caller typed them.
16
+ *
17
+ * Exported for tests; `index.ts` is the only production caller.
18
+ */
19
+ export function pinAskBooleanFlags(argv) {
20
+ const prefix = argv.slice(0, 2);
21
+ const rest = argv.slice(2);
22
+ if (rest[0] !== "ask") {
23
+ return [...argv];
24
+ }
25
+ const pinned = [];
26
+ for (let index = 0; index < rest.length; index += 1) {
27
+ const arg = rest[index];
28
+ if (arg === undefined) {
29
+ continue;
30
+ }
31
+ // Everything after `--` is a positional the caller quoted deliberately.
32
+ if (arg === "--") {
33
+ pinned.push(...rest.slice(index));
34
+ break;
35
+ }
36
+ if (ASK_BOOLEAN_FLAGS.includes(arg) === true) {
37
+ const next = rest[index + 1];
38
+ if (next !== "true" && next !== "false") {
39
+ pinned.push(`${arg}=true`);
40
+ continue;
41
+ }
42
+ }
43
+ pinned.push(arg);
44
+ }
45
+ return [...prefix, ...pinned];
46
+ }
@@ -0,0 +1,2 @@
1
+ export declare function pruneHarnessArtifacts(dir: string, now?: number): void;
2
+ //# sourceMappingURL=artifacts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"artifacts.d.ts","sourceRoot":"","sources":["../../../src/commands/ask/artifacts.ts"],"names":[],"mappings":"AAwBA,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,SAAa,GAAG,IAAI,CAGzE"}
@@ -0,0 +1,100 @@
1
+ import { readdirSync, rmdirSync, rmSync, statSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ /**
4
+ * Every local turn writes bridge state into the directory Ask runs from —
5
+ * `.agent-runs/<sessionId>/bridge` carries the event log and the start config,
6
+ * and the start config carries the proxy token — and nothing upstream ever
7
+ * removes it. Left alone, a working copy fills with dead sessions and keeps
8
+ * spent tokens on disk long after the chat that minted them.
9
+ *
10
+ * A run is kept while a chat could still reattach to it, and swept once it is
11
+ * older than that. `claude-code-<sessionId>` directories are the per-session
12
+ * work directories the harness derives, which local sessions leave empty; only
13
+ * an empty, aged-out one is removed, so anything a session actually put there
14
+ * — or is using now — survives.
15
+ *
16
+ * Best-effort throughout: a directory that is locked, half-written, or being
17
+ * used by another Ask process is skipped rather than allowed to take the
18
+ * session down with it.
19
+ */
20
+ const RUN_RETENTION_MS = 3 * 24 * 60 * 60 * 1000;
21
+ const WORK_DIR_PREFIX = "claude-code-";
22
+ export function pruneHarnessArtifacts(dir, now = Date.now()) {
23
+ removeStaleRuns(join(dir, ".agent-runs"), now);
24
+ removeEmptyWorkDirs(dir, now);
25
+ }
26
+ function removeStaleRuns(runsDir, now) {
27
+ let entries;
28
+ try {
29
+ entries = readdirSync(runsDir);
30
+ }
31
+ catch {
32
+ return;
33
+ }
34
+ for (const entry of entries) {
35
+ const path = join(runsDir, entry);
36
+ try {
37
+ if (now - newestMtimeMs(path) < RUN_RETENTION_MS) {
38
+ continue;
39
+ }
40
+ rmSync(path, { recursive: true, force: true });
41
+ }
42
+ catch {
43
+ continue;
44
+ }
45
+ }
46
+ try {
47
+ rmdirSync(runsDir);
48
+ }
49
+ catch {
50
+ // Runs we kept are still in there, which is the ordinary case.
51
+ }
52
+ }
53
+ function removeEmptyWorkDirs(dir, now) {
54
+ let entries;
55
+ try {
56
+ entries = readdirSync(dir);
57
+ }
58
+ catch {
59
+ return;
60
+ }
61
+ for (const entry of entries) {
62
+ if (entry.startsWith(WORK_DIR_PREFIX) === false) {
63
+ continue;
64
+ }
65
+ const path = join(dir, entry);
66
+ try {
67
+ // An empty directory's mtime is when it was created, so age is what
68
+ // separates a dead session from one another Ask process is working in
69
+ // right now — that one is its agent's cwd and must survive.
70
+ if (now - statSync(path).mtimeMs < RUN_RETENTION_MS) {
71
+ continue;
72
+ }
73
+ rmdirSync(path);
74
+ }
75
+ catch {
76
+ // Not empty, or not ours to remove.
77
+ continue;
78
+ }
79
+ }
80
+ }
81
+ /**
82
+ * A run directory's own mtime only moves when entries are added or removed, so
83
+ * a session that streamed into an existing event log for an hour can still look
84
+ * untouched. The newest mtime underneath it is what says when the run was last
85
+ * alive.
86
+ */
87
+ function newestMtimeMs(path) {
88
+ const stats = statSync(path);
89
+ if (stats.isDirectory() === false) {
90
+ return stats.mtimeMs;
91
+ }
92
+ let newest = stats.mtimeMs;
93
+ for (const entry of readdirSync(path)) {
94
+ const candidate = newestMtimeMs(join(path, entry));
95
+ if (candidate > newest) {
96
+ newest = candidate;
97
+ }
98
+ }
99
+ return newest;
100
+ }
@@ -0,0 +1,13 @@
1
+ type RepositoryLike = {
2
+ connectorUuid?: string;
3
+ repository?: string;
4
+ } | null | undefined;
5
+ /**
6
+ * A usable GitHub workspace: connector + owner/name. Matches
7
+ * parseHarnessBinding's required fields, without decrypting env.
8
+ *
9
+ * Exported for tests.
10
+ */
11
+ export declare function isBoundRepository(repository: RepositoryLike): boolean;
12
+ export {};
13
+ //# sourceMappingURL=binding.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"binding.d.ts","sourceRoot":"","sources":["../../../src/commands/ask/binding.ts"],"names":[],"mappings":"AAAA,KAAK,cAAc,GACf;IACE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,GACD,IAAI,GACJ,SAAS,CAAC;AAEd;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,cAAc,GAAG,OAAO,CAgBrE"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * A usable GitHub workspace: connector + owner/name. Matches
3
+ * parseHarnessBinding's required fields, without decrypting env.
4
+ *
5
+ * Exported for tests.
6
+ */
7
+ export function isBoundRepository(repository) {
8
+ if (repository === undefined || repository === null) {
9
+ return false;
10
+ }
11
+ if (repository.connectorUuid === undefined) {
12
+ return false;
13
+ }
14
+ if (repository.repository === undefined) {
15
+ return false;
16
+ }
17
+ const slashIndex = repository.repository.indexOf("/");
18
+ return slashIndex > 0 && slashIndex < repository.repository.length - 1;
19
+ }
@@ -0,0 +1,23 @@
1
+ /**
2
+ * The Claude Agent SDK loads every filesystem settings source it can find when
3
+ * `settingSources` is omitted, and the harness bridge omits it. A local turn
4
+ * therefore inherits the user's `~/.claude` setup — hooks, plugins, and every
5
+ * globally configured MCP server — and Claude Code blocks on all of it before
6
+ * the model takes its first step. Because a turn relaunches Claude Code, that
7
+ * is paid per message, not per session: on one machine it was 14 seconds of a
8
+ * 22 second turn, most of it a SessionStart hook running a global npm install
9
+ * and a skills sync.
10
+ *
11
+ * Pointing Claude Code at a directory Ask owns keeps a turn's cost to what the
12
+ * turn needs. Project settings and CLAUDE.md resolve from the working
13
+ * directory rather than here, so anything the repo commits still applies.
14
+ *
15
+ * The directory persists between runs: Claude Code keeps its own state and
16
+ * session transcripts under it, and a fresh one each turn would pay first-run
17
+ * costs again.
18
+ *
19
+ * Set `CLAUDE_CONFIG_DIR` to share a config with the `claude` CLI instead —
20
+ * that reinstates the user's hooks and MCP servers, and their startup cost.
21
+ */
22
+ export declare function askClaudeConfigDir(): string;
23
+ //# sourceMappingURL=claudeConfig.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claudeConfig.d.ts","sourceRoot":"","sources":["../../../src/commands/ask/claudeConfig.ts"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CAY3C"}
@@ -0,0 +1,33 @@
1
+ import { mkdirSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { getConfigDir } from "@cargo-ai/cdk/cli";
4
+ /**
5
+ * The Claude Agent SDK loads every filesystem settings source it can find when
6
+ * `settingSources` is omitted, and the harness bridge omits it. A local turn
7
+ * therefore inherits the user's `~/.claude` setup — hooks, plugins, and every
8
+ * globally configured MCP server — and Claude Code blocks on all of it before
9
+ * the model takes its first step. Because a turn relaunches Claude Code, that
10
+ * is paid per message, not per session: on one machine it was 14 seconds of a
11
+ * 22 second turn, most of it a SessionStart hook running a global npm install
12
+ * and a skills sync.
13
+ *
14
+ * Pointing Claude Code at a directory Ask owns keeps a turn's cost to what the
15
+ * turn needs. Project settings and CLAUDE.md resolve from the working
16
+ * directory rather than here, so anything the repo commits still applies.
17
+ *
18
+ * The directory persists between runs: Claude Code keeps its own state and
19
+ * session transcripts under it, and a fresh one each turn would pay first-run
20
+ * costs again.
21
+ *
22
+ * Set `CLAUDE_CONFIG_DIR` to share a config with the `claude` CLI instead —
23
+ * that reinstates the user's hooks and MCP servers, and their startup cost.
24
+ */
25
+ export function askClaudeConfigDir() {
26
+ const configured = process.env["CLAUDE_CONFIG_DIR"];
27
+ if (configured !== undefined && configured !== "") {
28
+ return configured;
29
+ }
30
+ const dir = join(getConfigDir(), "ask-claude-config");
31
+ mkdirSync(dir, { recursive: true });
32
+ return dir;
33
+ }
@@ -0,0 +1,48 @@
1
+ /** Chat slash commands offered on Tab when the line is `/…`. */
2
+ export declare const ASK_SLASH_COMMANDS: readonly ["/help", "/clear", "/new", "/agent", "/cancel", "/exit"];
3
+ export type AskCompleter = (line: string) => [string[], string];
4
+ /** What a `/…` token turned out to be. */
5
+ export type SlashTokenKind = "command" | "path" | "unknown";
6
+ /**
7
+ * Decide whether a `/…` token is a chat command, a filesystem path, or
8
+ * neither.
9
+ *
10
+ * The completer and the slash parser both need this answer, and they must
11
+ * agree: anything the completer offers has to be accepted when the user
12
+ * presses Enter on it. Written twice, the two drifted — `/tmp` completed as a
13
+ * path and was then answered with "is not a chat command".
14
+ *
15
+ * Shape settles most tokens, but a bare `/word` is ambiguous: `/tmp` and
16
+ * `/orchestration` are spelled the same. Only the filesystem separates them,
17
+ * so an unknown word is looked up — cheap, and reached only for a single
18
+ * bare word that no command matches.
19
+ */
20
+ export declare function classifySlashToken(token: string): SlashTokenKind;
21
+ /** Max rows shown in the live Ask suggestion menu. */
22
+ export declare const ASK_COMPLETION_MENU_LIMIT = 8;
23
+ /**
24
+ * Tab completer for the Ask prompt: slash commands when the line is `/…`,
25
+ * otherwise local path completion for a path-like last token.
26
+ */
27
+ export declare function createAskCompleter(cwd: string): AskCompleter;
28
+ /**
29
+ * Matches for the live suggestion menu (slash commands, else path hits).
30
+ * Empty when the line is plain prose.
31
+ */
32
+ export declare function listCompletions(line: string, cwd: string): string[];
33
+ /**
34
+ * Replace the completed span with `completion`: whole line for slash
35
+ * commands, last token for paths.
36
+ */
37
+ export declare function applyCompletion(line: string, completion: string): string;
38
+ /**
39
+ * `/hel` → `/help`. Only when the whole line is a single `/token` (no spaces)
40
+ * and it matches a chat command prefix. `/tmp` falls through to path completion.
41
+ */
42
+ export declare function completeSlash(line: string): [string[], string] | undefined;
43
+ /**
44
+ * Complete the last whitespace-separated token when it looks like a path.
45
+ * Exported for tests.
46
+ */
47
+ export declare function completePath(line: string, cwd: string): [string[], string];
48
+ //# sourceMappingURL=completer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"completer.d.ts","sourceRoot":"","sources":["../../../src/commands/ask/completer.ts"],"names":[],"mappings":"AAYA,gEAAgE;AAChE,eAAO,MAAM,kBAAkB,oEAOrB,CAAC;AAEX,MAAM,MAAM,YAAY,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,CAAC,MAAM,EAAE,EAAE,MAAM,CAAC,CAAC;AAEhE,0CAA0C;AAC1C,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAAC;AAE5D;;;;;;;;;;;;;GAaG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,cAAc,CAgBhE;AAED,sDAAsD;AACtD,eAAO,MAAM,yBAAyB,IAAI,CAAC;AAE3C;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,CAU5D;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CASnE;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAYxE;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,EAAE,MAAM,CAAC,GAAG,SAAS,CAY1E;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,EAAE,MAAM,CAAC,CAwE1E"}