@cargo-ai/cli 1.0.94 → 1.0.96
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/chat.d.ts.map +1 -1
- package/build/commands/ai/chat.js +2 -1
- package/build/commands/ai/message.d.ts.map +1 -1
- package/build/commands/ai/message.js +2 -1
- package/build/commands/ai/release.d.ts.map +1 -1
- package/build/commands/ai/release.js +7 -6
- package/build/commands/ask/harness/approvals.d.ts +7 -0
- package/build/commands/ask/harness/approvals.d.ts.map +1 -0
- package/build/commands/ask/harness/approvals.js +81 -0
- package/build/commands/ask/harness/artifacts.d.ts.map +1 -0
- package/build/commands/ask/harness/askUserQuestion.d.ts +69 -0
- package/build/commands/ask/harness/askUserQuestion.d.ts.map +1 -0
- package/build/commands/ask/harness/askUserQuestion.js +218 -0
- package/build/commands/ask/harness/claudeConfig.d.ts.map +1 -0
- package/build/commands/ask/{claudeConfig.js → harness/claudeConfig.js} +28 -13
- package/build/commands/ask/harness/create.d.ts +59 -0
- package/build/commands/ask/harness/create.d.ts.map +1 -0
- package/build/commands/ask/harness/create.js +314 -0
- package/build/commands/ask/harness/index.d.ts +9 -0
- package/build/commands/ask/harness/index.d.ts.map +1 -0
- package/build/commands/ask/harness/index.js +8 -0
- package/build/commands/ask/harness/ingest.d.ts +25 -0
- package/build/commands/ask/harness/ingest.d.ts.map +1 -0
- package/build/commands/ask/harness/ingest.js +35 -0
- package/build/commands/ask/harness/instructions.d.ts +13 -0
- package/build/commands/ask/harness/instructions.d.ts.map +1 -0
- package/build/commands/ask/harness/instructions.js +43 -0
- package/build/commands/ask/harness/layout.d.ts +23 -0
- package/build/commands/ask/harness/layout.d.ts.map +1 -0
- package/build/commands/ask/harness/layout.js +32 -0
- package/build/commands/ask/harness/mcp.d.ts +25 -0
- package/build/commands/ask/harness/mcp.d.ts.map +1 -0
- package/build/commands/ask/harness/mcp.js +72 -0
- package/build/commands/ask/harness/pnpmShim.d.ts.map +1 -0
- package/build/commands/ask/harness/release.d.ts +18 -0
- package/build/commands/ask/harness/release.d.ts.map +1 -0
- package/build/commands/ask/harness/release.js +117 -0
- package/build/commands/ask/harness/sandbox.d.ts +9 -0
- package/build/commands/ask/harness/sandbox.d.ts.map +1 -0
- package/build/commands/ask/harness/sandbox.js +27 -0
- package/build/commands/ask/harness/timing.d.ts +16 -0
- package/build/commands/ask/harness/timing.d.ts.map +1 -0
- package/build/commands/ask/harness/timing.js +72 -0
- package/build/commands/ask/harness/turn.d.ts +152 -0
- package/build/commands/ask/harness/turn.d.ts.map +1 -0
- package/build/commands/ask/harness/turn.js +676 -0
- package/build/commands/ask/harness/usage.d.ts +50 -0
- package/build/commands/ask/harness/usage.d.ts.map +1 -0
- package/build/commands/ask/harness/usage.js +87 -0
- package/build/commands/ask/index.d.ts +9 -0
- package/build/commands/ask/index.d.ts.map +1 -1
- package/build/commands/ask/index.js +7 -7
- package/build/commands/ask/input/completer.d.ts.map +1 -0
- package/build/commands/ask/input/index.d.ts +5 -0
- package/build/commands/ask/input/index.d.ts.map +1 -0
- package/build/commands/ask/input/index.js +4 -0
- package/build/commands/ask/input/prompt.d.ts.map +1 -0
- package/build/commands/ask/{prompt.js → input/prompt.js} +1 -1
- package/build/commands/ask/input/slash.d.ts.map +1 -0
- package/build/commands/ask/{slash.js → input/slash.js} +1 -1
- package/build/commands/ask/input/typeAhead.d.ts.map +1 -0
- package/build/commands/ask/{history.d.ts → persist/history.d.ts} +1 -1
- package/build/commands/ask/persist/history.d.ts.map +1 -0
- package/build/commands/ask/persist/index.d.ts +4 -0
- package/build/commands/ask/persist/index.d.ts.map +1 -0
- package/build/commands/ask/persist/index.js +3 -0
- package/build/commands/ask/persist/persist.d.ts.map +1 -0
- package/build/commands/ask/persist/state.d.ts.map +1 -0
- package/build/commands/ask/session/claim.d.ts +56 -0
- package/build/commands/ask/session/claim.d.ts.map +1 -0
- package/build/commands/ask/session/claim.js +76 -0
- package/build/commands/ask/session/index.d.ts +5 -0
- package/build/commands/ask/session/index.d.ts.map +1 -0
- package/build/commands/ask/session/index.js +4 -0
- package/build/commands/ask/session/run.d.ts +36 -0
- package/build/commands/ask/session/run.d.ts.map +1 -0
- package/build/commands/ask/session/run.js +846 -0
- package/build/commands/ask/session/thinking.d.ts.map +1 -0
- package/build/commands/ask/session/tree.d.ts +99 -0
- package/build/commands/ask/session/tree.d.ts.map +1 -0
- package/build/commands/ask/session/tree.js +356 -0
- package/package.json +6 -5
- package/build/commands/ask/artifacts.d.ts.map +0 -1
- package/build/commands/ask/binding.d.ts +0 -13
- package/build/commands/ask/binding.d.ts.map +0 -1
- package/build/commands/ask/binding.js +0 -19
- package/build/commands/ask/claudeConfig.d.ts.map +0 -1
- package/build/commands/ask/completer.d.ts.map +0 -1
- package/build/commands/ask/history.d.ts.map +0 -1
- package/build/commands/ask/localHarness.d.ts +0 -278
- package/build/commands/ask/localHarness.d.ts.map +0 -1
- package/build/commands/ask/localHarness.js +0 -1300
- package/build/commands/ask/messageStream.d.ts +0 -33
- package/build/commands/ask/messageStream.d.ts.map +0 -1
- package/build/commands/ask/messageStream.js +0 -114
- package/build/commands/ask/persist.d.ts.map +0 -1
- package/build/commands/ask/pnpmShim.d.ts.map +0 -1
- package/build/commands/ask/prompt.d.ts.map +0 -1
- package/build/commands/ask/session.d.ts +0 -101
- package/build/commands/ask/session.d.ts.map +0 -1
- package/build/commands/ask/session.js +0 -1328
- package/build/commands/ask/slash.d.ts.map +0 -1
- package/build/commands/ask/state.d.ts.map +0 -1
- package/build/commands/ask/thinking.d.ts.map +0 -1
- package/build/commands/ask/typeAhead.d.ts.map +0 -1
- /package/build/commands/ask/{artifacts.d.ts → harness/artifacts.d.ts} +0 -0
- /package/build/commands/ask/{artifacts.js → harness/artifacts.js} +0 -0
- /package/build/commands/ask/{claudeConfig.d.ts → harness/claudeConfig.d.ts} +0 -0
- /package/build/commands/ask/{pnpmShim.d.ts → harness/pnpmShim.d.ts} +0 -0
- /package/build/commands/ask/{pnpmShim.js → harness/pnpmShim.js} +0 -0
- /package/build/commands/ask/{completer.d.ts → input/completer.d.ts} +0 -0
- /package/build/commands/ask/{completer.js → input/completer.js} +0 -0
- /package/build/commands/ask/{prompt.d.ts → input/prompt.d.ts} +0 -0
- /package/build/commands/ask/{slash.d.ts → input/slash.d.ts} +0 -0
- /package/build/commands/ask/{typeAhead.d.ts → input/typeAhead.d.ts} +0 -0
- /package/build/commands/ask/{typeAhead.js → input/typeAhead.js} +0 -0
- /package/build/commands/ask/{history.js → persist/history.js} +0 -0
- /package/build/commands/ask/{persist.d.ts → persist/persist.d.ts} +0 -0
- /package/build/commands/ask/{persist.js → persist/persist.js} +0 -0
- /package/build/commands/ask/{state.d.ts → persist/state.d.ts} +0 -0
- /package/build/commands/ask/{state.js → persist/state.js} +0 -0
- /package/build/commands/ask/{thinking.d.ts → session/thinking.d.ts} +0 -0
- /package/build/commands/ask/{thinking.js → session/thinking.js} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"release.d.ts","sourceRoot":"","sources":["../../../../src/commands/ask/harness/release.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAEvD,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAC;AAE3C,sFAAsF;AACtF,eAAO,MAAM,2BAA2B,gBAAgB,CAAC;AAEzD,KAAK,QAAQ,GAAG;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ,CAAC;QACf,oBAAoB,EAAE,IAAI,CAAC;KAC5B,CAAC;IACF,OAAO,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CAC9C,CAAC;AAEF,wBAAgB,+BAA+B,CAC7C,OAAO,EAAE,EAAE,CAAC,OAAO,GAClB,MAAM,GAAG,SAAS,CAwCpB;AAED,wBAAgB,sBAAsB,CACpC,UAAU,EAAE,EAAE,CAAC,SAAS,EAAE,GACzB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAiBzB;AAED,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,GAAG,EACR,OAAO,EAAE,EAAE,CAAC,MAAM,EAAE,GACnB,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CA4B1B;AAED,wBAAgB,eAAe,CAC7B,MAAM,EAAE,EAAE,CAAC,MAAM,GAChB,aAAa,CAAC,GAAG,CAAC,oBAAoB,CAAC,QAAQ,CAAC,CAgClD"}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/** Mount prefix so agent MCP tools can be auto-approved without widening user MCP. */
|
|
2
|
+
export const CARGO_AGENT_MCP_NAME_PREFIX = "cargoagent_";
|
|
3
|
+
export function buildReleaseInstructionAppendix(release) {
|
|
4
|
+
const parts = [];
|
|
5
|
+
const resourceLines = release.resources.map((resource) => {
|
|
6
|
+
const title = resource.name !== undefined ? resource.name : resource.slug;
|
|
7
|
+
if (resource.description === undefined) {
|
|
8
|
+
return `- ${title} (${resource.kind})`;
|
|
9
|
+
}
|
|
10
|
+
return `- ${title} (${resource.kind}): ${resource.description}`;
|
|
11
|
+
});
|
|
12
|
+
if (resourceLines.length > 0) {
|
|
13
|
+
parts.push(["Workspace resources for this agent:", ...resourceLines].join("\n"));
|
|
14
|
+
}
|
|
15
|
+
const capabilityLines = release.capabilities
|
|
16
|
+
.filter((capability) => capability.slug !== "sandbox" && capability.slug !== "suggestedActions")
|
|
17
|
+
.map((capability) => `- ${capability.slug}`);
|
|
18
|
+
if (capabilityLines.length > 0) {
|
|
19
|
+
parts.push([
|
|
20
|
+
"This agent also has these Cargo capabilities; use the Cargo MCP tools for workspace data they cover:",
|
|
21
|
+
...capabilityLines,
|
|
22
|
+
].join("\n"));
|
|
23
|
+
}
|
|
24
|
+
if (parts.length === 0) {
|
|
25
|
+
return undefined;
|
|
26
|
+
}
|
|
27
|
+
return parts.join("\n\n");
|
|
28
|
+
}
|
|
29
|
+
export function buildReleaseMcpServers(mcpClients) {
|
|
30
|
+
const servers = {};
|
|
31
|
+
for (const client of mcpClients) {
|
|
32
|
+
if (client.kind !== "custom") {
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
const name = mcpServerName(client.name);
|
|
36
|
+
const headers = customMcpHeaders(client.authentication);
|
|
37
|
+
servers[name] =
|
|
38
|
+
headers === undefined
|
|
39
|
+
? { type: "http", url: client.url }
|
|
40
|
+
: { type: "http", url: client.url, headers };
|
|
41
|
+
}
|
|
42
|
+
return servers;
|
|
43
|
+
}
|
|
44
|
+
export function buildReleaseHostTools(api, actions) {
|
|
45
|
+
const tools = {};
|
|
46
|
+
for (const action of actions) {
|
|
47
|
+
tools[action.slug] = {
|
|
48
|
+
description: action.description,
|
|
49
|
+
inputSchema: {
|
|
50
|
+
type: "object",
|
|
51
|
+
additionalProperties: true,
|
|
52
|
+
},
|
|
53
|
+
execute: async (data) => {
|
|
54
|
+
try {
|
|
55
|
+
return await api.orchestration.action.execute({
|
|
56
|
+
action: toExecuteAction(action),
|
|
57
|
+
data,
|
|
58
|
+
waitUntilFinished: true,
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
return {
|
|
63
|
+
error: error instanceof Error ? error.message : "Action failed to run",
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
return tools;
|
|
70
|
+
}
|
|
71
|
+
export function toExecuteAction(action) {
|
|
72
|
+
if (action.kind === "tool") {
|
|
73
|
+
return {
|
|
74
|
+
kind: "tool",
|
|
75
|
+
toolUuid: action.toolUuid,
|
|
76
|
+
templateSlug: action.templateSlug,
|
|
77
|
+
waitUntilFinished: action.waitUntilFinished,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
if (action.kind === "agent") {
|
|
81
|
+
return {
|
|
82
|
+
kind: "agent",
|
|
83
|
+
agentUuid: action.agentUuid,
|
|
84
|
+
templateSlug: action.templateSlug,
|
|
85
|
+
waitUntilFinished: action.waitUntilFinished,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
if (action.kind === "connector") {
|
|
89
|
+
return {
|
|
90
|
+
kind: "connector",
|
|
91
|
+
integrationSlug: action.integrationSlug,
|
|
92
|
+
connectorUuid: action.connectorUuid,
|
|
93
|
+
actionSlug: action.actionSlug,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
return {
|
|
97
|
+
kind: "native",
|
|
98
|
+
actionSlug: action.actionSlug,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
function mcpServerName(name) {
|
|
102
|
+
const slug = name.toLowerCase().replace(/[^a-z0-9]+/g, "_");
|
|
103
|
+
const trimmed = slug.replace(/^_+|_+$/g, "");
|
|
104
|
+
const body = trimmed.length > 0 ? trimmed : "mcp";
|
|
105
|
+
return `${CARGO_AGENT_MCP_NAME_PREFIX}${body}`;
|
|
106
|
+
}
|
|
107
|
+
function customMcpHeaders(authentication) {
|
|
108
|
+
if (authentication === undefined) {
|
|
109
|
+
return undefined;
|
|
110
|
+
}
|
|
111
|
+
const tokenType = authentication.tokenType !== undefined
|
|
112
|
+
? authentication.tokenType
|
|
113
|
+
: "Bearer";
|
|
114
|
+
return {
|
|
115
|
+
Authorization: `${tokenType} ${authentication.accessToken}`,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { HarnessV1SandboxProvider } from "@ai-sdk/harness";
|
|
2
|
+
/**
|
|
3
|
+
* `ai-sdk-sandbox-local@0.1.2` still ships deprecated `getPortUrl` only.
|
|
4
|
+
* Claude Code's harness treats a session without `getPortEndpoint` as a basic
|
|
5
|
+
* sandbox and then demands an explicit port — wrap until the local provider
|
|
6
|
+
* catches up.
|
|
7
|
+
*/
|
|
8
|
+
export declare function withGetPortEndpoint(provider: HarnessV1SandboxProvider): HarnessV1SandboxProvider;
|
|
9
|
+
//# sourceMappingURL=sandbox.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sandbox.d.ts","sourceRoot":"","sources":["../../../../src/commands/ask/harness/sandbox.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,iBAAiB,CAAC;AAShE;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,wBAAwB,GACjC,wBAAwB,CAc1B"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `ai-sdk-sandbox-local@0.1.2` still ships deprecated `getPortUrl` only.
|
|
3
|
+
* Claude Code's harness treats a session without `getPortEndpoint` as a basic
|
|
4
|
+
* sandbox and then demands an explicit port — wrap until the local provider
|
|
5
|
+
* catches up.
|
|
6
|
+
*/
|
|
7
|
+
export function withGetPortEndpoint(provider) {
|
|
8
|
+
const resumeSession = provider.resumeSession;
|
|
9
|
+
return {
|
|
10
|
+
specificationVersion: provider.specificationVersion,
|
|
11
|
+
providerId: provider.providerId,
|
|
12
|
+
createSession: async (options) => ensureGetPortEndpoint(await provider.createSession(options)),
|
|
13
|
+
resumeSession: resumeSession === undefined
|
|
14
|
+
? undefined
|
|
15
|
+
: async (options) => ensureGetPortEndpoint(await resumeSession(options)),
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
function ensureGetPortEndpoint(session) {
|
|
19
|
+
if ("getPortEndpoint" in session) {
|
|
20
|
+
return session;
|
|
21
|
+
}
|
|
22
|
+
const getPortEndpoint = async (options) => ({
|
|
23
|
+
url: await session.getPortUrl(options),
|
|
24
|
+
});
|
|
25
|
+
Object.assign(session, { getPortEndpoint });
|
|
26
|
+
return session;
|
|
27
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { StreamLike } from "./turn.js";
|
|
2
|
+
export declare const ASK_TIMING_ENABLED: boolean;
|
|
3
|
+
export type PhaseLog = (phase: string) => void;
|
|
4
|
+
export declare function createPhaseLog(label: string): PhaseLog;
|
|
5
|
+
/**
|
|
6
|
+
* The harness prints its own diagnostics without a clock, which is what the
|
|
7
|
+
* gap needs. Reprint them relative to process start instead.
|
|
8
|
+
*/
|
|
9
|
+
export declare function reportHarnessDiagnostic(event: {
|
|
10
|
+
level: string;
|
|
11
|
+
subsystem?: string | undefined;
|
|
12
|
+
message: string;
|
|
13
|
+
}): void;
|
|
14
|
+
/** Marks when each part of a turn's stream arrives, and when it ends. */
|
|
15
|
+
export declare function timeStreamParts(stream: StreamLike, phase: PhaseLog): StreamLike;
|
|
16
|
+
//# sourceMappingURL=timing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"timing.d.ts","sourceRoot":"","sources":["../../../../src/commands/ask/harness/timing.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAgB5C,eAAO,MAAM,kBAAkB,SAC2B,CAAC;AAG3D,MAAM,MAAM,QAAQ,GAAG,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;AAE/C,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,CAkBtD;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE;IAC7C,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,OAAO,EAAE,MAAM,CAAC;CACjB,GAAG,IAAI,CAMP;AAED,yEAAyE;AACzE,wBAAgB,eAAe,CAC7B,MAAM,EAAE,UAAU,EAClB,KAAK,EAAE,QAAQ,GACd,UAAU,CAMZ"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A local turn spends far longer getting the prompt into Claude Code than it
|
|
3
|
+
* spends generating the answer, and none of that is visible from the tree or
|
|
4
|
+
* from Claude Code's own transcript. `CARGO_ASK_TIMING=1` writes the phase
|
|
5
|
+
* boundaries — and the harness's own diagnostics — to stderr. Unset, every
|
|
6
|
+
* call below is a no-op and nothing is added to the stream.
|
|
7
|
+
*
|
|
8
|
+
* `CARGO_ASK_TIMING=parts` adds the whole of each stream part next to its
|
|
9
|
+
* type. Verbose, and the only way to see what the bridge actually sends: the
|
|
10
|
+
* part names alone say a tool call arrived, not that its result came back
|
|
11
|
+
* empty or that the field a reader is looking for is spelled differently here
|
|
12
|
+
* than in the bridge that emitted it.
|
|
13
|
+
*/
|
|
14
|
+
const ASK_TIMING_LEVEL = process.env["CARGO_ASK_TIMING"];
|
|
15
|
+
export const ASK_TIMING_ENABLED = ASK_TIMING_LEVEL === "1" || ASK_TIMING_LEVEL === "parts";
|
|
16
|
+
const ASK_TIMING_DUMPS_PARTS = ASK_TIMING_LEVEL === "parts";
|
|
17
|
+
export function createPhaseLog(label) {
|
|
18
|
+
if (ASK_TIMING_ENABLED === false) {
|
|
19
|
+
return () => undefined;
|
|
20
|
+
}
|
|
21
|
+
const start = Date.now();
|
|
22
|
+
let previous = start;
|
|
23
|
+
return (phase) => {
|
|
24
|
+
const now = Date.now();
|
|
25
|
+
const total = ((now - start) / 1000).toFixed(2).padStart(6);
|
|
26
|
+
const step = ((now - previous) / 1000).toFixed(2).padStart(5);
|
|
27
|
+
previous = now;
|
|
28
|
+
process.stderr.write(`[ask:timing] ${label} ${total}s (+${step}s) ${phase}\n`);
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* The harness prints its own diagnostics without a clock, which is what the
|
|
33
|
+
* gap needs. Reprint them relative to process start instead.
|
|
34
|
+
*/
|
|
35
|
+
export function reportHarnessDiagnostic(event) {
|
|
36
|
+
const elapsed = process.uptime().toFixed(2).padStart(6);
|
|
37
|
+
process.stderr.write(`[ask:timing] harness ${elapsed}s ${event.level} ${event.subsystem ?? "-"} ${event.message}\n`);
|
|
38
|
+
}
|
|
39
|
+
/** Marks when each part of a turn's stream arrives, and when it ends. */
|
|
40
|
+
export function timeStreamParts(stream, phase) {
|
|
41
|
+
if (ASK_TIMING_ENABLED === false) {
|
|
42
|
+
return stream;
|
|
43
|
+
}
|
|
44
|
+
return { text: stream.text, fullStream: timeParts(stream.fullStream, phase) };
|
|
45
|
+
}
|
|
46
|
+
async function* timeParts(parts, phase) {
|
|
47
|
+
let seen = 0;
|
|
48
|
+
for await (const part of parts) {
|
|
49
|
+
seen += 1;
|
|
50
|
+
const type = typeof part === "object" && part !== null && "type" in part
|
|
51
|
+
? String(part.type)
|
|
52
|
+
: "unknown";
|
|
53
|
+
// Text arrives one delta per token, which would bury everything else.
|
|
54
|
+
if (type.startsWith("text-delta") === false) {
|
|
55
|
+
phase(ASK_TIMING_DUMPS_PARTS === true
|
|
56
|
+
? `part ${String(seen)}: ${type} ${dumpPart(part)}`
|
|
57
|
+
: `part ${String(seen)}: ${type}`);
|
|
58
|
+
}
|
|
59
|
+
yield part;
|
|
60
|
+
}
|
|
61
|
+
phase(`stream ended after ${String(seen)} parts`);
|
|
62
|
+
}
|
|
63
|
+
/** One stream part, flattened onto its log line. Truncated: some are huge. */
|
|
64
|
+
function dumpPart(part) {
|
|
65
|
+
try {
|
|
66
|
+
const json = JSON.stringify(part, (_key, value) => value instanceof Error ? `Error(${value.message})` : value);
|
|
67
|
+
return json === undefined ? "" : json.slice(0, 900);
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
return "<unserializable>";
|
|
71
|
+
}
|
|
72
|
+
}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { type LocalTurnAccumulator } from "./usage.js";
|
|
2
|
+
/**
|
|
3
|
+
* A built-in tool Claude Code wants to run that `permissionMode` does not
|
|
4
|
+
* auto-approve (anything that writes or shells out under `allow-reads`).
|
|
5
|
+
*/
|
|
6
|
+
export type LocalToolApproval = {
|
|
7
|
+
approvalId: string;
|
|
8
|
+
toolCallId: string;
|
|
9
|
+
toolName: string;
|
|
10
|
+
/** Compact one-line rendering of the tool input, for the prompt. */
|
|
11
|
+
summary: string;
|
|
12
|
+
input: unknown;
|
|
13
|
+
};
|
|
14
|
+
/** A tool starting or finishing, so the caller can show what is happening. */
|
|
15
|
+
export type LocalToolActivity = {
|
|
16
|
+
kind: "start";
|
|
17
|
+
toolCallId: string;
|
|
18
|
+
toolName: string;
|
|
19
|
+
summary: string;
|
|
20
|
+
} | {
|
|
21
|
+
kind: "end";
|
|
22
|
+
toolCallId: string;
|
|
23
|
+
toolName: string;
|
|
24
|
+
isError: boolean;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Announced, then never run — a tool whose input stopped mid-stream, one
|
|
28
|
+
* that was refused, or a sibling whose approval request the harness lost.
|
|
29
|
+
* None of them report a result, so `end` never comes: a caller tracking
|
|
30
|
+
* what is live has to be told, or it shows that tool for the rest of the
|
|
31
|
+
* turn. `retractAbandonedCalls` decides which calls qualify and when.
|
|
32
|
+
*/
|
|
33
|
+
| {
|
|
34
|
+
kind: "dropped";
|
|
35
|
+
toolCallId: string;
|
|
36
|
+
toolName: string;
|
|
37
|
+
};
|
|
38
|
+
export type LocalStreamHandlers = {
|
|
39
|
+
onTextDelta?: (delta: string) => void;
|
|
40
|
+
/**
|
|
41
|
+
* Decide whether the tool may run. Omitted (`--print`, non-interactive)
|
|
42
|
+
* means deny — the turn continues and the model reports what it could not
|
|
43
|
+
* do rather than silently running commands on the user's machine.
|
|
44
|
+
*/
|
|
45
|
+
onApproval?: (approval: LocalToolApproval) => Promise<boolean>;
|
|
46
|
+
/**
|
|
47
|
+
* Present `AskUserQuestion` in this session's own picker. Used by the host
|
|
48
|
+
* tool that replaces Claude Code's native picker, and by the approval path
|
|
49
|
+
* if a call is still offered. Omitted (`--print`) means the model is told
|
|
50
|
+
* to ask in its reply instead.
|
|
51
|
+
*/
|
|
52
|
+
onUserQuestion?: (input: unknown) => Promise<Record<string, string> | undefined>;
|
|
53
|
+
onActivity?: (activity: LocalToolActivity) => void;
|
|
54
|
+
/** Path of a file the turn wrote or edited, as the tool named it. */
|
|
55
|
+
onFileTouched?: (path: string) => void;
|
|
56
|
+
/** Something worth saying that is not part of the reply. */
|
|
57
|
+
onNotice?: (message: string) => void;
|
|
58
|
+
};
|
|
59
|
+
export type LocalStreamOptions = LocalStreamHandlers & {
|
|
60
|
+
/** Aborts the turn; the harness interrupts Claude Code gracefully. */
|
|
61
|
+
abortSignal?: AbortSignal;
|
|
62
|
+
/**
|
|
63
|
+
* Fired when the stall watchdog gives up, before the turn is rejected.
|
|
64
|
+
* Should abort `abortSignal` so Claude Code stops rather than being torn
|
|
65
|
+
* down out from under a still-open bridge.
|
|
66
|
+
*/
|
|
67
|
+
onStall?: () => void;
|
|
68
|
+
};
|
|
69
|
+
export type StreamLike = {
|
|
70
|
+
fullStream: AsyncIterable<unknown>;
|
|
71
|
+
text: PromiseLike<string>;
|
|
72
|
+
};
|
|
73
|
+
export type ApprovalContinuation = {
|
|
74
|
+
approvalResponse: {
|
|
75
|
+
type: "tool-approval-response";
|
|
76
|
+
approvalId: string;
|
|
77
|
+
approved: boolean;
|
|
78
|
+
reason?: string;
|
|
79
|
+
};
|
|
80
|
+
toolCall: {
|
|
81
|
+
type: "tool-call";
|
|
82
|
+
toolCallId: string;
|
|
83
|
+
toolName: string;
|
|
84
|
+
input: unknown;
|
|
85
|
+
};
|
|
86
|
+
};
|
|
87
|
+
/** The two harness calls a turn needs. Split out so tests can fake them. */
|
|
88
|
+
export type TurnDriver = {
|
|
89
|
+
start: () => Promise<StreamLike>;
|
|
90
|
+
continueWithApprovals: (continuations: readonly ApprovalContinuation[]) => Promise<StreamLike>;
|
|
91
|
+
};
|
|
92
|
+
/**
|
|
93
|
+
* Run one turn to completion, answering approval requests along the way.
|
|
94
|
+
*
|
|
95
|
+
* A turn suspends whenever Claude Code wants a tool `permissionMode` does not
|
|
96
|
+
* cover: the stream ends with the approvals still pending, and the turn only
|
|
97
|
+
* finishes once decisions are fed back in. Exported for tests.
|
|
98
|
+
*/
|
|
99
|
+
export declare function runPromptTurn(input: {
|
|
100
|
+
driver: TurnDriver;
|
|
101
|
+
handlers: LocalStreamHandlers | undefined;
|
|
102
|
+
accumulator?: LocalTurnAccumulator;
|
|
103
|
+
/**
|
|
104
|
+
* Filled with approvals the harness asked about and drained as each is
|
|
105
|
+
* answered, so a turn that ends mid-question leaves the unanswered ones
|
|
106
|
+
* behind for the caller to deny.
|
|
107
|
+
*/
|
|
108
|
+
unanswered?: LocalToolApproval[];
|
|
109
|
+
/** Overridden by tests; `Infinity` waits forever. */
|
|
110
|
+
stallTimeoutMs?: number;
|
|
111
|
+
/** The same, for the stream while a tool is executing. */
|
|
112
|
+
toolStallTimeoutMs?: number;
|
|
113
|
+
/**
|
|
114
|
+
* Called when the stall watchdog fires, before the turn is rejected — abort
|
|
115
|
+
* the harness stream so Claude Code does not keep running after we give up.
|
|
116
|
+
*/
|
|
117
|
+
onStall?: () => void;
|
|
118
|
+
}): Promise<string>;
|
|
119
|
+
/**
|
|
120
|
+
* The previous turn could not be wound down, so this session cannot take
|
|
121
|
+
* another prompt. Raised rather than pressed on with: the harness would either
|
|
122
|
+
* refuse the prompt itself or run it alongside the turn we failed to finish.
|
|
123
|
+
*
|
|
124
|
+
* The caller's recovery is to replace the session — nothing about a wedged
|
|
125
|
+
* runtime gets better by asking it again.
|
|
126
|
+
*/
|
|
127
|
+
export declare class HarnessTurnStuck extends Error {
|
|
128
|
+
constructor();
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* The turn produced nothing for `TURN_STALL_TIMEOUT_MS` while no tool was in
|
|
132
|
+
* flight. Common causes: a step that asked to run several confirmable tools at
|
|
133
|
+
* once (the harness only surfaces one approval), or the Claude Code bridge
|
|
134
|
+
* going silent. Recoverable — replace the session and ask again.
|
|
135
|
+
*/
|
|
136
|
+
export declare class HarnessTurnStalled extends Error {
|
|
137
|
+
constructor(timeoutMs: number, whileToolRunning?: boolean);
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* The Claude Code bridge dropped mid-turn. Same recovery as a stall: the
|
|
141
|
+
* process behind the session is gone, so the next question needs a new one.
|
|
142
|
+
*/
|
|
143
|
+
export declare function isBridgeClosedError(error: unknown): boolean;
|
|
144
|
+
/**
|
|
145
|
+
* Wait for `work`, but give up after `timeoutMs` rather than blocking a
|
|
146
|
+
* teardown forever. Resolves either way; the caller has already decided that
|
|
147
|
+
* an unfinished result is better than waiting.
|
|
148
|
+
*
|
|
149
|
+
* Exported for tests.
|
|
150
|
+
*/
|
|
151
|
+
export declare function settleWithin(work: Promise<unknown>, timeoutMs: number): Promise<void>;
|
|
152
|
+
//# sourceMappingURL=turn.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"turn.d.ts","sourceRoot":"","sources":["../../../../src/commands/ask/harness/turn.ts"],"names":[],"mappings":"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"}
|