@agentclientprotocol/claude-agent-acp 0.81.3-preview.1 → 0.82.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -5
- package/dist/acp-agent.d.ts +31 -37
- package/dist/acp-agent.d.ts.map +1 -1
- package/dist/acp-agent.js +546 -534
- package/dist/acp-subagents.d.ts +6 -0
- package/dist/acp-subagents.d.ts.map +1 -1
- package/dist/air-extension.d.ts +31 -1
- package/dist/air-extension.d.ts.map +1 -1
- package/dist/air-extension.js +35 -1
- package/dist/async-tasks.d.ts +39 -2
- package/dist/async-tasks.d.ts.map +1 -1
- package/dist/async-tasks.js +147 -44
- package/dist/context-compaction-meta.d.ts +6 -5
- package/dist/context-compaction-meta.d.ts.map +1 -1
- package/dist/context-compaction-meta.js +10 -10
- package/dist/context-compaction.d.ts +3 -0
- package/dist/context-compaction.d.ts.map +1 -1
- package/dist/context-compaction.js +23 -57
- package/dist/diff.d.ts +73 -5
- package/dist/diff.d.ts.map +1 -1
- package/dist/diff.js +435 -64
- package/dist/elicitation.d.ts +1 -1
- package/dist/elicitation.d.ts.map +1 -1
- package/dist/elicitation.js +12 -14
- package/dist/native-subagents.d.ts +58 -0
- package/dist/native-subagents.d.ts.map +1 -1
- package/dist/native-subagents.js +186 -34
- package/dist/paths.d.ts +3 -0
- package/dist/paths.d.ts.map +1 -0
- package/dist/paths.js +6 -0
- package/dist/permissions/presentation.d.ts +13 -2
- package/dist/permissions/presentation.d.ts.map +1 -1
- package/dist/permissions/presentation.js +49 -44
- package/dist/resumed-session.d.ts +11 -0
- package/dist/resumed-session.d.ts.map +1 -1
- package/dist/resumed-session.js +106 -4
- package/dist/session-mode.d.ts +2 -0
- package/dist/session-mode.d.ts.map +1 -1
- package/dist/session-mode.js +12 -5
- package/dist/settings.js +2 -2
- package/dist/subagent-history.d.ts +20 -0
- package/dist/subagent-history.d.ts.map +1 -0
- package/dist/subagent-history.js +46 -0
- package/dist/tool-calls/background.d.ts +20 -0
- package/dist/tool-calls/background.d.ts.map +1 -0
- package/dist/tool-calls/background.js +41 -0
- package/dist/tool-calls/changed-meta-filter.d.ts +27 -0
- package/dist/tool-calls/changed-meta-filter.d.ts.map +1 -0
- package/dist/tool-calls/changed-meta-filter.js +102 -0
- package/dist/tool-calls/client-capabilities.d.ts +51 -0
- package/dist/tool-calls/client-capabilities.d.ts.map +1 -0
- package/dist/tool-calls/client-capabilities.js +43 -0
- package/dist/tool-calls/content.d.ts +59 -0
- package/dist/tool-calls/content.d.ts.map +1 -0
- package/dist/tool-calls/content.js +194 -0
- package/dist/tool-calls/facts.d.ts +116 -0
- package/dist/tool-calls/facts.d.ts.map +1 -0
- package/dist/tool-calls/facts.js +1 -0
- package/dist/tool-calls/field-tracker.d.ts +58 -0
- package/dist/tool-calls/field-tracker.d.ts.map +1 -0
- package/dist/tool-calls/field-tracker.js +167 -0
- package/dist/tool-calls/renderer.d.ts +216 -0
- package/dist/tool-calls/renderer.d.ts.map +1 -0
- package/dist/tool-calls/renderer.js +487 -0
- package/dist/tool-calls/reporters/agent.d.ts +7 -0
- package/dist/tool-calls/reporters/agent.d.ts.map +1 -0
- package/dist/tool-calls/reporters/agent.js +190 -0
- package/dist/tool-calls/reporters/bash.d.ts +9 -0
- package/dist/tool-calls/reporters/bash.d.ts.map +1 -0
- package/dist/tool-calls/reporters/bash.js +83 -0
- package/dist/tool-calls/reporters/compaction.d.ts +24 -0
- package/dist/tool-calls/reporters/compaction.d.ts.map +1 -0
- package/dist/tool-calls/reporters/compaction.js +66 -0
- package/dist/tool-calls/reporters/file-edit.d.ts +46 -0
- package/dist/tool-calls/reporters/file-edit.d.ts.map +1 -0
- package/dist/tool-calls/reporters/file-edit.js +180 -0
- package/dist/tool-calls/reporters/index.d.ts +4 -0
- package/dist/tool-calls/reporters/index.d.ts.map +1 -0
- package/dist/tool-calls/reporters/index.js +40 -0
- package/dist/tool-calls/reporters/interaction.d.ts +71 -0
- package/dist/tool-calls/reporters/interaction.d.ts.map +1 -0
- package/dist/tool-calls/reporters/interaction.js +222 -0
- package/dist/tool-calls/reporters/read.d.ts +7 -0
- package/dist/tool-calls/reporters/read.d.ts.map +1 -0
- package/dist/tool-calls/reporters/read.js +64 -0
- package/dist/tool-calls/reporters/search.d.ts +10 -0
- package/dist/tool-calls/reporters/search.d.ts.map +1 -0
- package/dist/tool-calls/reporters/search.js +50 -0
- package/dist/tool-calls/reporters/web.d.ts +11 -0
- package/dist/tool-calls/reporters/web.d.ts.map +1 -0
- package/dist/tool-calls/reporters/web.js +42 -0
- package/dist/tools.d.ts +32 -37
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +48 -970
- package/package.json +4 -1
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { ContentBlock, ToolCallContent } from "@agentclientprotocol/sdk";
|
|
2
|
+
import { DocumentBlockParam, ImageBlockParam, TextBlockParam, ToolResultBlockParam, WebSearchResultBlock, WebSearchToolResultBlockParam, WebSearchToolResultError } from "@anthropic-ai/sdk/resources";
|
|
3
|
+
import { BetaBashCodeExecutionResultBlock, BetaBashCodeExecutionToolResultBlockParam, BetaBashCodeExecutionToolResultError, BetaCodeExecutionResultBlock, BetaCodeExecutionToolResultBlockParam, BetaCodeExecutionToolResultError, BetaImageBlockParam, BetaRequestMCPToolResultBlockParam, BetaTextEditorCodeExecutionCreateResultBlock, BetaTextEditorCodeExecutionStrReplaceResultBlock, BetaTextEditorCodeExecutionToolResultBlockParam, BetaTextEditorCodeExecutionToolResultError, BetaTextEditorCodeExecutionViewResultBlock, BetaToolReferenceBlock, BetaToolResultBlockParam, BetaToolSearchToolResultBlockParam, BetaToolSearchToolResultError, BetaToolSearchToolSearchResultBlock, BetaWebFetchBlock, BetaWebFetchToolResultBlockParam, BetaWebFetchToolResultErrorBlock, BetaWebSearchToolResultBlockParam } from "@anthropic-ai/sdk/resources/beta.mjs";
|
|
4
|
+
/**
|
|
5
|
+
* Union of all possible content types that can appear in tool results from the Anthropic SDK.
|
|
6
|
+
* These are transformed to valid ACP ContentBlock types by toValidAcpContent().
|
|
7
|
+
*/
|
|
8
|
+
export type ToolResultContent = TextBlockParam | DocumentBlockParam | ImageBlockParam | BetaImageBlockParam | BetaToolReferenceBlock | BetaToolSearchToolSearchResultBlock | BetaToolSearchToolResultError | WebSearchResultBlock | WebSearchToolResultError | BetaWebFetchBlock | BetaWebFetchToolResultErrorBlock | BetaCodeExecutionResultBlock | BetaCodeExecutionToolResultError | BetaBashCodeExecutionResultBlock | BetaBashCodeExecutionToolResultError | BetaTextEditorCodeExecutionViewResultBlock | BetaTextEditorCodeExecutionCreateResultBlock | BetaTextEditorCodeExecutionStrReplaceResultBlock | BetaTextEditorCodeExecutionToolResultError;
|
|
9
|
+
/**
|
|
10
|
+
* Convert an absolute file path to a project-relative path for display.
|
|
11
|
+
* Returns the original path if it's outside the project directory or if no cwd is provided.
|
|
12
|
+
*/
|
|
13
|
+
export declare function toDisplayPath(filePath: string, cwd?: string): string;
|
|
14
|
+
/**
|
|
15
|
+
* Narrow the untyped message-level `tool_use_result` toward a per-tool Output
|
|
16
|
+
* shape: rejects everything but a plain non-null object (arrays pass a bare
|
|
17
|
+
* `typeof === "object"` check, so they're excluded here). The returned value
|
|
18
|
+
* is only *nominally* typed — it arrives over the wire from arbitrary CLI
|
|
19
|
+
* versions, so each caller must still guard the specific fields it reads
|
|
20
|
+
* before trusting them.
|
|
21
|
+
*/
|
|
22
|
+
export declare function structuredResult<T extends object>(toolUseResult: unknown): T | undefined;
|
|
23
|
+
/** One display format for a web-search hit, shared by the structured
|
|
24
|
+
* WebSearchOutput render and the server-side `web_search_result` block so
|
|
25
|
+
* the two paths can't drift. */
|
|
26
|
+
export declare function formatWebSearchHit(hit: {
|
|
27
|
+
title: string;
|
|
28
|
+
url: string;
|
|
29
|
+
}): string;
|
|
30
|
+
export declare function toAcpContentUpdate(content: any, isError?: boolean): {
|
|
31
|
+
content?: ToolCallContent[];
|
|
32
|
+
};
|
|
33
|
+
export declare function toAcpContentBlock(content: ToolResultContent, isError: boolean): ContentBlock;
|
|
34
|
+
export declare function markdownEscape(text: string): string;
|
|
35
|
+
/** Every SDK block that reports the result of a tool use. */
|
|
36
|
+
export type ToolResultBlock = ToolResultBlockParam | BetaToolResultBlockParam | BetaWebSearchToolResultBlockParam | BetaWebFetchToolResultBlockParam | WebSearchToolResultBlockParam | BetaCodeExecutionToolResultBlockParam | BetaBashCodeExecutionToolResultBlockParam | BetaTextEditorCodeExecutionToolResultBlockParam | BetaRequestMCPToolResultBlockParam | BetaToolSearchToolResultBlockParam;
|
|
37
|
+
/** One text content block. */
|
|
38
|
+
export declare function textContent(text: string): ToolCallContent;
|
|
39
|
+
/** The result text that the model saw, as the result to show. */
|
|
40
|
+
export declare function resultText(result: {
|
|
41
|
+
content?: unknown;
|
|
42
|
+
is_error?: boolean | null;
|
|
43
|
+
}): {
|
|
44
|
+
content?: ToolCallContent[];
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* The marker fields of a PostToolUse `tool_response` that clients read.
|
|
48
|
+
*
|
|
49
|
+
* The full `tool_response` repeats the tool output. A Read holds the whole
|
|
50
|
+
* file, a Bash holds stdout and stderr, and a Write holds the content. The
|
|
51
|
+
* tool-call content already carries that output. JetBrains AIR reads
|
|
52
|
+
* `status` and `isAsync` to detect an async subagent launch, so only those
|
|
53
|
+
* fields stay. Returns undefined when neither field is present.
|
|
54
|
+
*/
|
|
55
|
+
export declare function toolResponseMarkers(toolResponse: unknown): {
|
|
56
|
+
status?: string;
|
|
57
|
+
isAsync?: boolean;
|
|
58
|
+
} | undefined;
|
|
59
|
+
//# sourceMappingURL=content.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"content.d.ts","sourceRoot":"","sources":["../../src/tool-calls/content.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC9E,OAAO,EACL,kBAAkB,EAClB,eAAe,EACf,cAAc,EACd,oBAAoB,EACpB,oBAAoB,EACpB,6BAA6B,EAC7B,wBAAwB,EACzB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,gCAAgC,EAChC,yCAAyC,EACzC,oCAAoC,EACpC,4BAA4B,EAC5B,qCAAqC,EACrC,gCAAgC,EAChC,mBAAmB,EACnB,kCAAkC,EAClC,4CAA4C,EAC5C,gDAAgD,EAChD,+CAA+C,EAC/C,0CAA0C,EAC1C,0CAA0C,EAC1C,sBAAsB,EACtB,wBAAwB,EACxB,kCAAkC,EAClC,6BAA6B,EAC7B,mCAAmC,EACnC,iBAAiB,EACjB,gCAAgC,EAChC,gCAAgC,EAChC,iCAAiC,EAClC,MAAM,sCAAsC,CAAC;AAG9C;;;GAGG;AACH,MAAM,MAAM,iBAAiB,GACzB,cAAc,GACd,kBAAkB,GAClB,eAAe,GACf,mBAAmB,GACnB,sBAAsB,GACtB,mCAAmC,GACnC,6BAA6B,GAC7B,oBAAoB,GACpB,wBAAwB,GACxB,iBAAiB,GACjB,gCAAgC,GAChC,4BAA4B,GAC5B,gCAAgC,GAChC,gCAAgC,GAChC,oCAAoC,GACpC,0CAA0C,GAC1C,4CAA4C,GAC5C,gDAAgD,GAChD,0CAA0C,CAAC;AAE/C;;;GAGG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAQpE;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,MAAM,EAAE,aAAa,EAAE,OAAO,GAAG,CAAC,GAAG,SAAS,CAMxF;AAED;;iCAEiC;AACjC,wBAAgB,kBAAkB,CAAC,GAAG,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAE9E;AAUD,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,GAAG,EACZ,OAAO,GAAE,OAAe,GACvB;IAAE,OAAO,CAAC,EAAE,eAAe,EAAE,CAAA;CAAE,CA+BjC;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,iBAAiB,EAAE,OAAO,EAAE,OAAO,GAAG,YAAY,CA6F5F;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAQnD;AAED,6DAA6D;AAC7D,MAAM,MAAM,eAAe,GACvB,oBAAoB,GACpB,wBAAwB,GACxB,iCAAiC,GACjC,gCAAgC,GAChC,6BAA6B,GAC7B,qCAAqC,GACrC,yCAAyC,GACzC,+CAA+C,GAC/C,kCAAkC,GAClC,kCAAkC,CAAC;AAEvC,8BAA8B;AAC9B,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,CAEzD;AAED,iEAAiE;AACjE,wBAAgB,UAAU,CAAC,MAAM,EAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,GAAG,IAAI,CAAA;CAAE,GAAG;IACpF,OAAO,CAAC,EAAE,eAAe,EAAE,CAAC;CAC7B,CAEA;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CACjC,YAAY,EAAE,OAAO,GACpB;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,SAAS,CAUpD"}
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
/**
|
|
3
|
+
* Convert an absolute file path to a project-relative path for display.
|
|
4
|
+
* Returns the original path if it's outside the project directory or if no cwd is provided.
|
|
5
|
+
*/
|
|
6
|
+
export function toDisplayPath(filePath, cwd) {
|
|
7
|
+
if (!cwd)
|
|
8
|
+
return filePath;
|
|
9
|
+
const resolvedCwd = path.resolve(cwd);
|
|
10
|
+
const resolvedFile = path.resolve(filePath);
|
|
11
|
+
if (resolvedFile.startsWith(resolvedCwd + path.sep) || resolvedFile === resolvedCwd) {
|
|
12
|
+
return path.relative(resolvedCwd, resolvedFile);
|
|
13
|
+
}
|
|
14
|
+
return filePath;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Narrow the untyped message-level `tool_use_result` toward a per-tool Output
|
|
18
|
+
* shape: rejects everything but a plain non-null object (arrays pass a bare
|
|
19
|
+
* `typeof === "object"` check, so they're excluded here). The returned value
|
|
20
|
+
* is only *nominally* typed — it arrives over the wire from arbitrary CLI
|
|
21
|
+
* versions, so each caller must still guard the specific fields it reads
|
|
22
|
+
* before trusting them.
|
|
23
|
+
*/
|
|
24
|
+
export function structuredResult(toolUseResult) {
|
|
25
|
+
return toolUseResult !== null &&
|
|
26
|
+
typeof toolUseResult === "object" &&
|
|
27
|
+
!Array.isArray(toolUseResult)
|
|
28
|
+
? toolUseResult
|
|
29
|
+
: undefined;
|
|
30
|
+
}
|
|
31
|
+
/** One display format for a web-search hit, shared by the structured
|
|
32
|
+
* WebSearchOutput render and the server-side `web_search_result` block so
|
|
33
|
+
* the two paths can't drift. */
|
|
34
|
+
export function formatWebSearchHit(hit) {
|
|
35
|
+
return `${hit.title} (${hit.url})`;
|
|
36
|
+
}
|
|
37
|
+
/** Human-readable size for the document placeholder ("312 B", "2.4 KB",
|
|
38
|
+
* "1.3 MB"). */
|
|
39
|
+
function formatByteSize(bytes) {
|
|
40
|
+
if (bytes < 1024)
|
|
41
|
+
return `${bytes} B`;
|
|
42
|
+
if (bytes < 1024 * 1024)
|
|
43
|
+
return `${(bytes / 1024).toFixed(1)} KB`;
|
|
44
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
45
|
+
}
|
|
46
|
+
export function toAcpContentUpdate(content, isError = false) {
|
|
47
|
+
if (Array.isArray(content) && content.length > 0) {
|
|
48
|
+
return {
|
|
49
|
+
content: content.map((c) => ({
|
|
50
|
+
type: "content",
|
|
51
|
+
content: toAcpContentBlock(c, isError),
|
|
52
|
+
})),
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
else if (typeof content === "object" && content !== null && "type" in content) {
|
|
56
|
+
return {
|
|
57
|
+
content: [
|
|
58
|
+
{
|
|
59
|
+
type: "content",
|
|
60
|
+
content: toAcpContentBlock(content, isError),
|
|
61
|
+
},
|
|
62
|
+
],
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
else if (typeof content === "string" && content.length > 0) {
|
|
66
|
+
return {
|
|
67
|
+
content: [
|
|
68
|
+
{
|
|
69
|
+
type: "content",
|
|
70
|
+
content: {
|
|
71
|
+
type: "text",
|
|
72
|
+
text: isError ? `\`\`\`\n${content}\n\`\`\`` : content,
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
],
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
return {};
|
|
79
|
+
}
|
|
80
|
+
export function toAcpContentBlock(content, isError) {
|
|
81
|
+
const wrapText = (text) => ({
|
|
82
|
+
type: "text",
|
|
83
|
+
text: isError ? `\`\`\`\n${text}\n\`\`\`` : text,
|
|
84
|
+
});
|
|
85
|
+
switch (content.type) {
|
|
86
|
+
case "text":
|
|
87
|
+
return {
|
|
88
|
+
type: "text",
|
|
89
|
+
text: isError ? `\`\`\`\n${content.text}\n\`\`\`` : content.text,
|
|
90
|
+
};
|
|
91
|
+
case "image":
|
|
92
|
+
if (content.source.type === "base64") {
|
|
93
|
+
return {
|
|
94
|
+
type: "image",
|
|
95
|
+
data: content.source.data,
|
|
96
|
+
mimeType: content.source.media_type,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
// URL and file-based images can't be converted to ACP format (requires data)
|
|
100
|
+
return wrapText(content.source.type === "url"
|
|
101
|
+
? `[image: ${content.source.url}]`
|
|
102
|
+
: "[image: file reference]");
|
|
103
|
+
case "document": {
|
|
104
|
+
// A PDF Read delivers its raw `document` block inside the tool_result
|
|
105
|
+
// content (SDK 0.3.243 moved it here from a separate follow-up user
|
|
106
|
+
// message; the MultiRead documents lane always lived here). ACP has no
|
|
107
|
+
// document block and the base64 payload can be megabytes — render a
|
|
108
|
+
// compact placeholder, never the data, matching the CLI's own compact
|
|
109
|
+
// "Read PDF (size)" rendering.
|
|
110
|
+
const title = typeof content.title === "string" && content.title.length > 0 ? ` "${content.title}"` : "";
|
|
111
|
+
const source = content.source;
|
|
112
|
+
switch (source.type) {
|
|
113
|
+
case "url":
|
|
114
|
+
return wrapText(`[document${title}: ${source.url}]`);
|
|
115
|
+
case "base64":
|
|
116
|
+
case "text":
|
|
117
|
+
// base64 inflates the byte count by 4/3; plain text is 1:1.
|
|
118
|
+
return wrapText(`[document${title}: ${source.media_type}, ${formatByteSize(source.type === "base64"
|
|
119
|
+
? Math.floor((source.data.length * 3) / 4)
|
|
120
|
+
: source.data.length)}]`);
|
|
121
|
+
default:
|
|
122
|
+
return wrapText(`[document${title}]`);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
case "tool_reference":
|
|
126
|
+
return wrapText(`Tool: ${content.tool_name}`);
|
|
127
|
+
case "tool_search_tool_search_result":
|
|
128
|
+
return wrapText(`Tools found: ${content.tool_references.map((r) => r.tool_name).join(", ") || "none"}`);
|
|
129
|
+
case "tool_search_tool_result_error":
|
|
130
|
+
return wrapText(`Error: ${content.error_code}${content.error_message ? ` - ${content.error_message}` : ""}`);
|
|
131
|
+
case "web_search_result":
|
|
132
|
+
return wrapText(formatWebSearchHit(content));
|
|
133
|
+
case "web_search_tool_result_error":
|
|
134
|
+
return wrapText(`Error: ${content.error_code}`);
|
|
135
|
+
case "web_fetch_result":
|
|
136
|
+
return wrapText(`Fetched: ${content.url}`);
|
|
137
|
+
case "web_fetch_tool_result_error":
|
|
138
|
+
return wrapText(`Error: ${content.error_code}`);
|
|
139
|
+
case "code_execution_result":
|
|
140
|
+
return wrapText(`Output: ${content.stdout || content.stderr || ""}`);
|
|
141
|
+
case "bash_code_execution_result":
|
|
142
|
+
return wrapText(`Output: ${content.stdout || content.stderr || ""}`);
|
|
143
|
+
case "code_execution_tool_result_error":
|
|
144
|
+
case "bash_code_execution_tool_result_error":
|
|
145
|
+
return wrapText(`Error: ${content.error_code}`);
|
|
146
|
+
case "text_editor_code_execution_view_result":
|
|
147
|
+
return wrapText(content.content);
|
|
148
|
+
case "text_editor_code_execution_create_result":
|
|
149
|
+
return wrapText(content.is_file_update ? "File updated" : "File created");
|
|
150
|
+
case "text_editor_code_execution_str_replace_result":
|
|
151
|
+
return wrapText(content.lines?.join("\n") || "");
|
|
152
|
+
case "text_editor_code_execution_tool_result_error":
|
|
153
|
+
return wrapText(`Error: ${content.error_code}${content.error_message ? ` - ${content.error_message}` : ""}`);
|
|
154
|
+
default:
|
|
155
|
+
return wrapText(JSON.stringify(content));
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
export function markdownEscape(text) {
|
|
159
|
+
let escape = "```";
|
|
160
|
+
for (const [m] of text.matchAll(/^```+/gm)) {
|
|
161
|
+
while (m.length >= escape.length) {
|
|
162
|
+
escape += "`";
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
return escape + "\n" + text + (text.endsWith("\n") ? "" : "\n") + escape;
|
|
166
|
+
}
|
|
167
|
+
/** One text content block. */
|
|
168
|
+
export function textContent(text) {
|
|
169
|
+
return { type: "content", content: { type: "text", text } };
|
|
170
|
+
}
|
|
171
|
+
/** The result text that the model saw, as the result to show. */
|
|
172
|
+
export function resultText(result) {
|
|
173
|
+
return toAcpContentUpdate(result.content, result.is_error === true);
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* The marker fields of a PostToolUse `tool_response` that clients read.
|
|
177
|
+
*
|
|
178
|
+
* The full `tool_response` repeats the tool output. A Read holds the whole
|
|
179
|
+
* file, a Bash holds stdout and stderr, and a Write holds the content. The
|
|
180
|
+
* tool-call content already carries that output. JetBrains AIR reads
|
|
181
|
+
* `status` and `isAsync` to detect an async subagent launch, so only those
|
|
182
|
+
* fields stay. Returns undefined when neither field is present.
|
|
183
|
+
*/
|
|
184
|
+
export function toolResponseMarkers(toolResponse) {
|
|
185
|
+
if (!toolResponse || typeof toolResponse !== "object" || Array.isArray(toolResponse)) {
|
|
186
|
+
return undefined;
|
|
187
|
+
}
|
|
188
|
+
const { status, isAsync } = toolResponse;
|
|
189
|
+
const markers = {
|
|
190
|
+
...(typeof status === "string" ? { status } : {}),
|
|
191
|
+
...(typeof isAsync === "boolean" ? { isAsync } : {}),
|
|
192
|
+
};
|
|
193
|
+
return Object.keys(markers).length > 0 ? markers : undefined;
|
|
194
|
+
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import type { ToolCallContent, ToolCallLocation, ToolKind } from "@agentclientprotocol/sdk";
|
|
2
|
+
import type { ClientCapabilities } from "./client-capabilities.js";
|
|
3
|
+
/** A tool use as the SDK reports it. */
|
|
4
|
+
export interface ToolUse {
|
|
5
|
+
id: string;
|
|
6
|
+
name: string;
|
|
7
|
+
input: unknown;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* The facts of a tool use, read once from its input. The
|
|
11
|
+
* {@link AcpToolCallRenderer} decides which ACP field carries each fact.
|
|
12
|
+
*/
|
|
13
|
+
export interface ToolUseFacts {
|
|
14
|
+
/** A short label. Not the input and not the output. */
|
|
15
|
+
title: string;
|
|
16
|
+
kind: ToolKind;
|
|
17
|
+
locations?: ToolCallLocation[];
|
|
18
|
+
/** The file change that the input makes, as diff content. */
|
|
19
|
+
change?: ToolCallContent[];
|
|
20
|
+
/**
|
|
21
|
+
* The input keys whose text a diff holds: {@link change}, or for a Write of a
|
|
22
|
+
* client with diffPatch, the approval preview or the hook patch. `rawInput`
|
|
23
|
+
* leaves them out.
|
|
24
|
+
*/
|
|
25
|
+
fileTextKeys?: readonly string[];
|
|
26
|
+
/**
|
|
27
|
+
* A display copy of the input that the user reads: a plan, a subagent
|
|
28
|
+
* prompt, a question, a command description. A client that renders
|
|
29
|
+
* `rawInput` itself gets no display copy.
|
|
30
|
+
*/
|
|
31
|
+
display?: ToolCallContent[];
|
|
32
|
+
/** The tool runs a command. Its output goes to the terminal channel. */
|
|
33
|
+
command?: boolean;
|
|
34
|
+
/**
|
|
35
|
+
* The absolute path of the plan file that holds the plan text of the input.
|
|
36
|
+
* Set only for a `planFile` client and an existing file. `rawInput` then
|
|
37
|
+
* carries this path and not the plan text.
|
|
38
|
+
*/
|
|
39
|
+
planFilePath?: string;
|
|
40
|
+
}
|
|
41
|
+
/** The output of a command, for the terminal channel. */
|
|
42
|
+
export interface CommandOutput {
|
|
43
|
+
output: string;
|
|
44
|
+
exitCode: number;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* The facts of a tool result, read once from the SDK tool_result.
|
|
48
|
+
*
|
|
49
|
+
* `rawOutput` is present when the reporter decided what the raw output is.
|
|
50
|
+
* Otherwise the renderer sends the raw tool_result as `rawOutput` only when
|
|
51
|
+
* nothing else carries the result.
|
|
52
|
+
*/
|
|
53
|
+
export interface ToolResultFacts {
|
|
54
|
+
title?: string;
|
|
55
|
+
/** The result to show. */
|
|
56
|
+
content?: ToolCallContent[];
|
|
57
|
+
/** The final locations of an edit. */
|
|
58
|
+
locations?: ToolCallLocation[];
|
|
59
|
+
/** The output of a command. */
|
|
60
|
+
command?: CommandOutput;
|
|
61
|
+
/** A result that has no display form. */
|
|
62
|
+
rawOutput?: unknown;
|
|
63
|
+
/** The plan file of the tool use, as {@link ToolUseFacts.planFilePath} defines it. */
|
|
64
|
+
planFilePath?: string;
|
|
65
|
+
/**
|
|
66
|
+
* The plan is done with its file: the user approved it and the session left
|
|
67
|
+
* Plan mode. AIR then gets the clear signal of the plan file.
|
|
68
|
+
*/
|
|
69
|
+
planFileReleased?: boolean;
|
|
70
|
+
}
|
|
71
|
+
/** What a reporter reads besides the input of the tool use. */
|
|
72
|
+
export interface ToolUseContext {
|
|
73
|
+
cwd?: string;
|
|
74
|
+
capabilities: ClientCapabilities;
|
|
75
|
+
/**
|
|
76
|
+
* True when the tool use comes from the history of a loaded session. The
|
|
77
|
+
* files on disk then show a later state, so a reporter must not read them.
|
|
78
|
+
*/
|
|
79
|
+
replay?: boolean;
|
|
80
|
+
}
|
|
81
|
+
/** What a reporter reads to report a tool result. */
|
|
82
|
+
export interface ToolResultContext {
|
|
83
|
+
toolUse: ToolUse;
|
|
84
|
+
/** The SDK tool_result block. */
|
|
85
|
+
result: {
|
|
86
|
+
content?: unknown;
|
|
87
|
+
is_error?: boolean | null;
|
|
88
|
+
tool_use_id?: string;
|
|
89
|
+
};
|
|
90
|
+
/** The structured `tool_use_result` of the SDK message, when it is known. */
|
|
91
|
+
structured?: unknown;
|
|
92
|
+
capabilities: ClientCapabilities;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Turns the SDK data of one tool kind into tool facts. A reporter holds no
|
|
96
|
+
* state and knows nothing about the ACP fields.
|
|
97
|
+
*/
|
|
98
|
+
export interface ToolReporter {
|
|
99
|
+
toolUse(input: unknown, context: ToolUseContext): ToolUseFacts;
|
|
100
|
+
/**
|
|
101
|
+
* The facts of a successful result. Without this method, the result text
|
|
102
|
+
* that the model saw is the result to show.
|
|
103
|
+
*/
|
|
104
|
+
toolResult?(context: ToolResultContext): ToolResultFacts;
|
|
105
|
+
/**
|
|
106
|
+
* The facts of an error result. Without this method, the error text is the
|
|
107
|
+
* result to show.
|
|
108
|
+
*/
|
|
109
|
+
errorResult?(context: ToolResultContext): ToolResultFacts | undefined;
|
|
110
|
+
/**
|
|
111
|
+
* The facts of the PostToolUse hook `tool_response`: the final file change
|
|
112
|
+
* of an edit tool.
|
|
113
|
+
*/
|
|
114
|
+
hookResult?(toolResponse: unknown, context: ToolUseContext): Promise<ToolResultFacts>;
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=facts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"facts.d.ts","sourceRoot":"","sources":["../../src/tool-calls/facts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAC5F,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAEnE,wCAAwC;AACxC,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,OAAO,CAAC;CAChB;AAED;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,uDAAuD;IACvD,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,QAAQ,CAAC;IACf,SAAS,CAAC,EAAE,gBAAgB,EAAE,CAAC;IAC/B,6DAA6D;IAC7D,MAAM,CAAC,EAAE,eAAe,EAAE,CAAC;IAC3B;;;;OAIG;IACH,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC;;;;OAIG;IACH,OAAO,CAAC,EAAE,eAAe,EAAE,CAAC;IAC5B,wEAAwE;IACxE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,yDAAyD;AACzD,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,eAAe;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0BAA0B;IAC1B,OAAO,CAAC,EAAE,eAAe,EAAE,CAAC;IAC5B,sCAAsC;IACtC,SAAS,CAAC,EAAE,gBAAgB,EAAE,CAAC;IAC/B,+BAA+B;IAC/B,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,yCAAyC;IACzC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,sFAAsF;IACtF,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,+DAA+D;AAC/D,MAAM,WAAW,cAAc;IAC7B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,kBAAkB,CAAC;IACjC;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,qDAAqD;AACrD,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,OAAO,CAAC;IACjB,iCAAiC;IACjC,MAAM,EAAE;QAAE,OAAO,CAAC,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/E,6EAA6E;IAC7E,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,YAAY,EAAE,kBAAkB,CAAC;CAClC;AAED;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,OAAO,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,cAAc,GAAG,YAAY,CAAC;IAC/D;;;OAGG;IACH,UAAU,CAAC,CAAC,OAAO,EAAE,iBAAiB,GAAG,eAAe,CAAC;IACzD;;;OAGG;IACH,WAAW,CAAC,CAAC,OAAO,EAAE,iBAAiB,GAAG,eAAe,GAAG,SAAS,CAAC;IACtE;;;OAGG;IACH,UAAU,CAAC,CAAC,YAAY,EAAE,OAAO,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;CACvF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { SessionNotification, ToolCallContent } from "@agentclientprotocol/sdk";
|
|
2
|
+
type SessionUpdate = SessionNotification["update"];
|
|
3
|
+
/**
|
|
4
|
+
* Remembers what the client holds for each open tool call, so that a
|
|
5
|
+
* `tool_call_update` carries only the fields that changed.
|
|
6
|
+
*
|
|
7
|
+
* A client overwrites a field that an update carries and merges `_meta` by
|
|
8
|
+
* key. An update that repeats a field value therefore only costs bandwidth,
|
|
9
|
+
* and for a Write it repeats the whole file. The tracker drops such fields.
|
|
10
|
+
* It never drops `_meta`, because a client appends `terminal_output_delta`
|
|
11
|
+
* data.
|
|
12
|
+
*
|
|
13
|
+
* An entry starts at the `tool_call` and ends after both the tool_result and
|
|
14
|
+
* the PostToolUse hook callback, or when the session is torn down.
|
|
15
|
+
*/
|
|
16
|
+
export declare class ToolCallFieldTracker {
|
|
17
|
+
private readonly calls;
|
|
18
|
+
/**
|
|
19
|
+
* Records a `tool_call`, or removes the unchanged fields of a
|
|
20
|
+
* `tool_call_update` and records the rest.
|
|
21
|
+
*
|
|
22
|
+
* Returns false when the update carries nothing new: no replaced field
|
|
23
|
+
* remains, `_meta` has no key besides `claudeCode` and `jetbrains`, and
|
|
24
|
+
* every `claudeCode` and `jetbrains.air` key repeats its value. The caller
|
|
25
|
+
* then skips the update. An update for a tool call that the tracker does
|
|
26
|
+
* not know passes through unchanged.
|
|
27
|
+
*
|
|
28
|
+
* `replacePinnedContent` lets the final result of the tool replace an exact
|
|
29
|
+
* approval patch (see {@link pinContent}).
|
|
30
|
+
*/
|
|
31
|
+
apply(update: SessionUpdate, options?: {
|
|
32
|
+
replacePinnedContent?: boolean;
|
|
33
|
+
}): boolean;
|
|
34
|
+
/**
|
|
35
|
+
* Records the exact approval patch that the client shows for a tool call.
|
|
36
|
+
*
|
|
37
|
+
* The streamed tool input later refines the call with a standard diff of
|
|
38
|
+
* the Edit snippet. That diff must not replace the exact patch, so the
|
|
39
|
+
* content stays until an update passes `replacePinnedContent`.
|
|
40
|
+
*/
|
|
41
|
+
pinContent(toolCallId: string, content: ToolCallContent[]): void;
|
|
42
|
+
/**
|
|
43
|
+
* Marks the tool_result of a tool call. The entry ends now, or after the
|
|
44
|
+
* PostToolUse hook callback when `hookPending` is true.
|
|
45
|
+
*/
|
|
46
|
+
finishResult(toolCallId: string, hookPending: boolean): void;
|
|
47
|
+
/**
|
|
48
|
+
* Marks the end of the PostToolUse hook callback of a tool call. The entry
|
|
49
|
+
* ends when the tool_result was seen. Otherwise the tool_result ends it.
|
|
50
|
+
*/
|
|
51
|
+
finishHook(toolCallId: string): void;
|
|
52
|
+
/** Forgets one tool call. */
|
|
53
|
+
delete(toolCallId: string): void;
|
|
54
|
+
/** Forgets every tool call, when the session is torn down. */
|
|
55
|
+
clear(): void;
|
|
56
|
+
}
|
|
57
|
+
export {};
|
|
58
|
+
//# sourceMappingURL=field-tracker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"field-tracker.d.ts","sourceRoot":"","sources":["../../src/tool-calls/field-tracker.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAErF,KAAK,aAAa,GAAG,mBAAmB,CAAC,QAAQ,CAAC,CAAC;AA+BnD;;;;;;;;;;;;GAYG;AACH,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAmC;IAEzD;;;;;;;;;;;;OAYG;IACH,KAAK,CAAC,MAAM,EAAE,aAAa,EAAE,OAAO,CAAC,EAAE;QAAE,oBAAoB,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO;IA8CnF;;;;;;OAMG;IACH,UAAU,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,EAAE,GAAG,IAAI;IAOhE;;;OAGG;IACH,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,GAAG,IAAI;IAO5D;;;OAGG;IACH,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAIpC,6BAA6B;IAC7B,MAAM,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAIhC,8DAA8D;IAC9D,KAAK,IAAI,IAAI;CAGd"}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The tool-call fields that a client overwrites when a `tool_call_update`
|
|
3
|
+
* carries them. ACP replaces a present `content` or `locations` list as a
|
|
4
|
+
* whole, and `rawInput` and `rawOutput` are whole values.
|
|
5
|
+
*/
|
|
6
|
+
const REPLACED_FIELDS = [
|
|
7
|
+
"status",
|
|
8
|
+
"title",
|
|
9
|
+
"kind",
|
|
10
|
+
"content",
|
|
11
|
+
"locations",
|
|
12
|
+
"rawInput",
|
|
13
|
+
"rawOutput",
|
|
14
|
+
];
|
|
15
|
+
/**
|
|
16
|
+
* Remembers what the client holds for each open tool call, so that a
|
|
17
|
+
* `tool_call_update` carries only the fields that changed.
|
|
18
|
+
*
|
|
19
|
+
* A client overwrites a field that an update carries and merges `_meta` by
|
|
20
|
+
* key. An update that repeats a field value therefore only costs bandwidth,
|
|
21
|
+
* and for a Write it repeats the whole file. The tracker drops such fields.
|
|
22
|
+
* It never drops `_meta`, because a client appends `terminal_output_delta`
|
|
23
|
+
* data.
|
|
24
|
+
*
|
|
25
|
+
* An entry starts at the `tool_call` and ends after both the tool_result and
|
|
26
|
+
* the PostToolUse hook callback, or when the session is torn down.
|
|
27
|
+
*/
|
|
28
|
+
export class ToolCallFieldTracker {
|
|
29
|
+
calls = new Map();
|
|
30
|
+
/**
|
|
31
|
+
* Records a `tool_call`, or removes the unchanged fields of a
|
|
32
|
+
* `tool_call_update` and records the rest.
|
|
33
|
+
*
|
|
34
|
+
* Returns false when the update carries nothing new: no replaced field
|
|
35
|
+
* remains, `_meta` has no key besides `claudeCode` and `jetbrains`, and
|
|
36
|
+
* every `claudeCode` and `jetbrains.air` key repeats its value. The caller
|
|
37
|
+
* then skips the update. An update for a tool call that the tracker does
|
|
38
|
+
* not know passes through unchanged.
|
|
39
|
+
*
|
|
40
|
+
* `replacePinnedContent` lets the final result of the tool replace an exact
|
|
41
|
+
* approval patch (see {@link pinContent}).
|
|
42
|
+
*/
|
|
43
|
+
apply(update, options) {
|
|
44
|
+
if (update.sessionUpdate === "tool_call") {
|
|
45
|
+
const entry = {
|
|
46
|
+
fields: new Map(),
|
|
47
|
+
mergedMeta: new Map(),
|
|
48
|
+
contentPinned: false,
|
|
49
|
+
resultSeen: false,
|
|
50
|
+
};
|
|
51
|
+
this.calls.set(update.toolCallId, entry);
|
|
52
|
+
for (const field of REPLACED_FIELDS) {
|
|
53
|
+
const value = update[field];
|
|
54
|
+
if (value !== undefined)
|
|
55
|
+
entry.fields.set(field, JSON.stringify(value));
|
|
56
|
+
}
|
|
57
|
+
recordMergedMeta(entry, update._meta);
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
if (update.sessionUpdate !== "tool_call_update")
|
|
61
|
+
return true;
|
|
62
|
+
const entry = this.calls.get(update.toolCallId);
|
|
63
|
+
if (!entry)
|
|
64
|
+
return true;
|
|
65
|
+
const fields = update;
|
|
66
|
+
let changed = false;
|
|
67
|
+
for (const field of REPLACED_FIELDS) {
|
|
68
|
+
const value = fields[field];
|
|
69
|
+
if (value === undefined)
|
|
70
|
+
continue;
|
|
71
|
+
if (field === "content" && entry.contentPinned) {
|
|
72
|
+
if (!options?.replacePinnedContent) {
|
|
73
|
+
delete fields[field];
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
entry.contentPinned = false;
|
|
77
|
+
}
|
|
78
|
+
const json = JSON.stringify(value);
|
|
79
|
+
if (entry.fields.get(field) === json) {
|
|
80
|
+
delete fields[field];
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
entry.fields.set(field, json);
|
|
84
|
+
changed = true;
|
|
85
|
+
}
|
|
86
|
+
const meta = update._meta;
|
|
87
|
+
if (meta && Object.keys(meta).some((key) => !MERGED_META_NAMESPACES.has(key)))
|
|
88
|
+
changed = true;
|
|
89
|
+
if (recordMergedMeta(entry, meta))
|
|
90
|
+
changed = true;
|
|
91
|
+
return changed;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Records the exact approval patch that the client shows for a tool call.
|
|
95
|
+
*
|
|
96
|
+
* The streamed tool input later refines the call with a standard diff of
|
|
97
|
+
* the Edit snippet. That diff must not replace the exact patch, so the
|
|
98
|
+
* content stays until an update passes `replacePinnedContent`.
|
|
99
|
+
*/
|
|
100
|
+
pinContent(toolCallId, content) {
|
|
101
|
+
const entry = this.calls.get(toolCallId);
|
|
102
|
+
if (!entry)
|
|
103
|
+
return;
|
|
104
|
+
entry.fields.set("content", JSON.stringify(content));
|
|
105
|
+
entry.contentPinned = true;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Marks the tool_result of a tool call. The entry ends now, or after the
|
|
109
|
+
* PostToolUse hook callback when `hookPending` is true.
|
|
110
|
+
*/
|
|
111
|
+
finishResult(toolCallId, hookPending) {
|
|
112
|
+
const entry = this.calls.get(toolCallId);
|
|
113
|
+
if (!entry)
|
|
114
|
+
return;
|
|
115
|
+
if (hookPending)
|
|
116
|
+
entry.resultSeen = true;
|
|
117
|
+
else
|
|
118
|
+
this.calls.delete(toolCallId);
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Marks the end of the PostToolUse hook callback of a tool call. The entry
|
|
122
|
+
* ends when the tool_result was seen. Otherwise the tool_result ends it.
|
|
123
|
+
*/
|
|
124
|
+
finishHook(toolCallId) {
|
|
125
|
+
if (this.calls.get(toolCallId)?.resultSeen)
|
|
126
|
+
this.calls.delete(toolCallId);
|
|
127
|
+
}
|
|
128
|
+
/** Forgets one tool call. */
|
|
129
|
+
delete(toolCallId) {
|
|
130
|
+
this.calls.delete(toolCallId);
|
|
131
|
+
}
|
|
132
|
+
/** Forgets every tool call, when the session is torn down. */
|
|
133
|
+
clear() {
|
|
134
|
+
this.calls.clear();
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
/** The `_meta` namespaces that a client merges by key. */
|
|
138
|
+
const MERGED_META_NAMESPACES = new Set(["claudeCode", "jetbrains"]);
|
|
139
|
+
/** Merges the `claudeCode` and `jetbrains.air` keys of `meta`. Returns true
|
|
140
|
+
* when a key changed. */
|
|
141
|
+
function recordMergedMeta(entry, meta) {
|
|
142
|
+
let changed = false;
|
|
143
|
+
const record = (key, value) => {
|
|
144
|
+
const json = JSON.stringify(value);
|
|
145
|
+
if (entry.mergedMeta.get(key) === json)
|
|
146
|
+
return;
|
|
147
|
+
entry.mergedMeta.set(key, json);
|
|
148
|
+
changed = true;
|
|
149
|
+
};
|
|
150
|
+
const merge = (prefix, values) => {
|
|
151
|
+
if (!values || typeof values !== "object" || Array.isArray(values))
|
|
152
|
+
return;
|
|
153
|
+
for (const [key, value] of Object.entries(values))
|
|
154
|
+
record(prefix + key, value);
|
|
155
|
+
};
|
|
156
|
+
merge("claudeCode.", meta?.claudeCode);
|
|
157
|
+
const jetbrains = meta?.jetbrains;
|
|
158
|
+
if (jetbrains && typeof jetbrains === "object" && !Array.isArray(jetbrains)) {
|
|
159
|
+
for (const [key, value] of Object.entries(jetbrains)) {
|
|
160
|
+
if (key === "air")
|
|
161
|
+
merge("jetbrains.air.", value);
|
|
162
|
+
else
|
|
163
|
+
record(`jetbrains.${key}`, value);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
return changed;
|
|
167
|
+
}
|