@posthog/agent 2.3.326 → 2.3.341
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/dist/adapters/claude/conversion/tool-use-to-acp.d.ts +9 -0
- package/dist/adapters/claude/conversion/tool-use-to-acp.js +15 -1
- package/dist/adapters/claude/conversion/tool-use-to-acp.js.map +1 -1
- package/dist/adapters/claude/permissions/permission-options.js +18 -11
- package/dist/adapters/claude/permissions/permission-options.js.map +1 -1
- package/dist/adapters/claude/session/jsonl-hydration.js.map +1 -1
- package/dist/adapters/claude/session/models.d.ts +2 -2
- package/dist/adapters/claude/session/models.js +12 -6
- package/dist/adapters/claude/session/models.js.map +1 -1
- package/dist/adapters/claude/tools.js +15 -13
- package/dist/adapters/claude/tools.js.map +1 -1
- package/dist/adapters/reasoning-effort.d.ts +1 -1
- package/dist/adapters/reasoning-effort.js +11 -5
- package/dist/adapters/reasoning-effort.js.map +1 -1
- package/dist/agent.d.ts +2 -0
- package/dist/agent.js +6946 -587
- package/dist/agent.js.map +1 -1
- package/dist/execution-mode.d.ts +1 -1
- package/dist/execution-mode.js +14 -12
- package/dist/execution-mode.js.map +1 -1
- package/dist/posthog-api.js +4 -3
- package/dist/posthog-api.js.map +1 -1
- package/dist/server/agent-server.d.ts +1 -1
- package/dist/server/agent-server.js +9260 -2939
- package/dist/server/agent-server.js.map +1 -1
- package/dist/server/bin.cjs +11289 -4967
- package/dist/server/bin.cjs.map +1 -1
- package/dist/types.d.ts +8 -0
- package/package.json +7 -6
- package/src/adapters/acp-connection.ts +14 -1
- package/src/adapters/claude/UPSTREAM.md +24 -4
- package/src/adapters/claude/claude-agent.ts +161 -14
- package/src/adapters/claude/conversion/sdk-to-acp.ts +14 -2
- package/src/adapters/claude/conversion/tool-use-to-acp.ts +18 -1
- package/src/adapters/claude/hooks.test.ts +189 -0
- package/src/adapters/claude/hooks.ts +93 -3
- package/src/adapters/claude/permissions/permission-handlers.ts +2 -1
- package/src/adapters/claude/permissions/permission-options.ts +5 -0
- package/src/adapters/claude/session/models.ts +11 -5
- package/src/adapters/claude/session/options.ts +19 -3
- package/src/adapters/claude/session/settings.ts +17 -9
- package/src/adapters/claude/tools.ts +1 -1
- package/src/adapters/claude/types.ts +8 -1
- package/src/adapters/codex/codex-agent.ts +15 -2
- package/src/adapters/codex/codex-client.test.ts +112 -0
- package/src/adapters/codex/codex-client.ts +14 -1
- package/src/adapters/reasoning-effort.ts +6 -1
- package/src/agent.ts +6 -0
- package/src/enrichment/file-enricher.test.ts +163 -0
- package/src/enrichment/file-enricher.ts +82 -0
- package/src/execution-mode.test.ts +1 -0
- package/src/execution-mode.ts +13 -11
- package/src/server/bin.ts +1 -1
- package/src/server/types.ts +1 -1
- package/src/types.ts +6 -0
|
@@ -2,6 +2,14 @@ import { PlanEntry, ToolCall, ToolCallContent, ToolCallLocation, ToolCallUpdate
|
|
|
2
2
|
import { ToolUseBlock, ToolResultBlockParam, WebSearchToolResultBlockParam } from '@anthropic-ai/sdk/resources';
|
|
3
3
|
import { BetaWebSearchToolResultBlockParam, BetaWebFetchToolResultBlockParam, BetaCodeExecutionToolResultBlockParam, BetaBashCodeExecutionToolResultBlockParam, BetaTextEditorCodeExecutionToolResultBlockParam, BetaRequestMCPToolResultBlockParam, BetaToolSearchToolResultBlockParam } from '@anthropic-ai/sdk/resources/beta.mjs';
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Per-toolUseId handoff from the PostToolUse hook to `toolUpdateFromToolResult`.
|
|
7
|
+
* Can't emit a standalone `tool_call_update` because the SDK emits its own
|
|
8
|
+
* when it processes the tool_result, and the renderer applies it via
|
|
9
|
+
* `Object.assign` — our earlier update would be overwritten.
|
|
10
|
+
*/
|
|
11
|
+
type EnrichedReadCache = Map<string, string>;
|
|
12
|
+
|
|
5
13
|
type ToolInfo = Pick<ToolCall, "title" | "kind" | "content" | "locations">;
|
|
6
14
|
/**
|
|
7
15
|
* Convert an absolute file path to a project-relative path for display.
|
|
@@ -22,6 +30,7 @@ declare function toolUpdateFromToolResult(toolResult: ToolResultBlockParam | Bet
|
|
|
22
30
|
supportsTerminalOutput?: boolean;
|
|
23
31
|
toolUseId?: string;
|
|
24
32
|
cachedFileContent?: Record<string, string>;
|
|
33
|
+
enrichedReadCache?: EnrichedReadCache;
|
|
25
34
|
}): Pick<ToolCallUpdate, "title" | "content" | "locations" | "_meta">;
|
|
26
35
|
type ClaudePlanEntry = {
|
|
27
36
|
content: string;
|
|
@@ -392,7 +392,20 @@ function toolUpdateFromToolResult(toolResult, toolUse, options) {
|
|
|
392
392
|
return toAcpContentUpdate(toolResult.content, true);
|
|
393
393
|
}
|
|
394
394
|
switch (toolUse?.name) {
|
|
395
|
-
case "Read":
|
|
395
|
+
case "Read": {
|
|
396
|
+
const cache = options?.enrichedReadCache;
|
|
397
|
+
const enriched = cache && options?.toolUseId ? cache.get(options.toolUseId) : void 0;
|
|
398
|
+
if (enriched !== void 0 && cache && options?.toolUseId) {
|
|
399
|
+
cache.delete(options.toolUseId);
|
|
400
|
+
return {
|
|
401
|
+
content: [
|
|
402
|
+
{
|
|
403
|
+
type: "content",
|
|
404
|
+
content: text(markdownEscape(enriched))
|
|
405
|
+
}
|
|
406
|
+
]
|
|
407
|
+
};
|
|
408
|
+
}
|
|
396
409
|
if (Array.isArray(toolResult.content) && toolResult.content.length > 0) {
|
|
397
410
|
return {
|
|
398
411
|
content: toolResult.content.map((item) => {
|
|
@@ -427,6 +440,7 @@ function toolUpdateFromToolResult(toolResult, toolUse, options) {
|
|
|
427
440
|
};
|
|
428
441
|
}
|
|
429
442
|
return {};
|
|
443
|
+
}
|
|
430
444
|
case "Bash": {
|
|
431
445
|
const result = toolResult.content;
|
|
432
446
|
const terminalId = "tool_use_id" in toolResult ? String(toolResult.tool_use_id) : "";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/adapters/claude/conversion/tool-use-to-acp.ts","../../../../src/utils/acp-content.ts","../../../../src/adapters/claude/mcp/tool-metadata.ts"],"sourcesContent":["import fs from \"node:fs\";\nimport path from \"node:path\";\nimport type {\n PlanEntry,\n ToolCall,\n ToolCallContent,\n ToolCallLocation,\n ToolCallUpdate,\n ToolKind,\n} from \"@agentclientprotocol/sdk\";\nimport type {\n ToolResultBlockParam,\n ToolUseBlock,\n WebSearchToolResultBlockParam,\n} from \"@anthropic-ai/sdk/resources\";\nimport type {\n BetaBashCodeExecutionToolResultBlockParam,\n BetaCodeExecutionToolResultBlockParam,\n BetaRequestMCPToolResultBlockParam,\n BetaTextEditorCodeExecutionToolResultBlockParam,\n BetaToolSearchToolResultBlockParam,\n BetaWebFetchToolResultBlockParam,\n BetaWebSearchToolResultBlockParam,\n} from \"@anthropic-ai/sdk/resources/beta.mjs\";\n\nconst SYSTEM_REMINDER_REGEX =\n /\\s*<system-reminder>[\\s\\S]*?<\\/system-reminder>/g;\n\nfunction stripSystemReminders(value: string): string {\n return value.replace(SYSTEM_REMINDER_REGEX, \"\");\n}\n\nimport { resourceLink, text, toolContent } from \"../../../utils/acp-content\";\nimport { getMcpToolMetadata } from \"../mcp/tool-metadata\";\n\ntype ToolInfo = Pick<ToolCall, \"title\" | \"kind\" | \"content\" | \"locations\">;\n\n/**\n * Convert an absolute file path to a project-relative path for display.\n * Returns the original path if it's outside the project directory or if no cwd is provided.\n */\nexport function toDisplayPath(filePath: string, cwd?: string): string {\n if (!cwd) return filePath;\n const resolvedCwd = path.resolve(cwd);\n const resolvedFile = path.resolve(filePath);\n if (\n resolvedFile.startsWith(resolvedCwd + path.sep) ||\n resolvedFile === resolvedCwd\n ) {\n return path.relative(resolvedCwd, resolvedFile);\n }\n return filePath;\n}\n\nexport function toolInfoFromToolUse(\n toolUse: Pick<ToolUseBlock, \"name\" | \"input\">,\n options?: {\n supportsTerminalOutput?: boolean;\n toolUseId?: string;\n cachedFileContent?: Record<string, string>;\n cwd?: string;\n },\n): ToolInfo {\n const name = toolUse.name;\n const input = toolUse.input as Record<string, unknown> | undefined;\n\n switch (name) {\n case \"Task\":\n case \"Agent\":\n return {\n title: input?.description ? String(input.description) : name,\n kind: \"think\",\n content: input?.prompt\n ? toolContent().text(String(input.prompt)).build()\n : [],\n };\n\n case \"NotebookRead\":\n return {\n title: input?.notebook_path\n ? `Read Notebook ${String(input.notebook_path)}`\n : \"Read Notebook\",\n kind: \"read\",\n content: [],\n locations: input?.notebook_path\n ? [{ path: String(input.notebook_path) }]\n : [],\n };\n\n case \"NotebookEdit\":\n return {\n title: input?.notebook_path\n ? `Edit Notebook ${String(input.notebook_path)}`\n : \"Edit Notebook\",\n kind: \"edit\",\n content: input?.new_source\n ? toolContent().text(String(input.new_source)).build()\n : [],\n locations: input?.notebook_path\n ? [{ path: String(input.notebook_path) }]\n : [],\n };\n\n case \"Bash\":\n if (options?.supportsTerminalOutput && options?.toolUseId) {\n return {\n title: input?.description\n ? String(input.description)\n : \"Execute command\",\n kind: \"execute\",\n content: [{ type: \"terminal\", terminalId: options.toolUseId }],\n };\n }\n return {\n title: input?.description\n ? String(input.description)\n : \"Execute command\",\n kind: \"execute\",\n content: input?.command\n ? toolContent().text(String(input.command)).build()\n : [],\n };\n\n case \"BashOutput\":\n return {\n title: \"Tail Logs\",\n kind: \"execute\",\n content: [],\n };\n\n case \"KillShell\":\n return {\n title: \"Kill Process\",\n kind: \"execute\",\n content: [],\n };\n\n case \"Read\": {\n let limit = \"\";\n const inputLimit = input?.limit as number | undefined;\n const inputOffset = (input?.offset as number | undefined) ?? 1;\n if (inputLimit) {\n limit = ` (${inputOffset} - ${inputOffset + inputLimit - 1})`;\n } else if (inputOffset > 1) {\n limit = ` (from line ${inputOffset})`;\n }\n const displayPath = input?.file_path\n ? toDisplayPath(String(input.file_path), options?.cwd)\n : \"File\";\n return {\n title: `Read ${displayPath}${limit}`,\n kind: \"read\",\n locations: input?.file_path\n ? [\n {\n path: String(input.file_path),\n line: inputOffset,\n },\n ]\n : [],\n content: [],\n };\n }\n\n case \"LS\":\n return {\n title: `List the ${input?.path ? `\\`${String(input.path)}\\`` : \"current\"} directory's contents`,\n kind: \"search\",\n content: [],\n locations: [],\n };\n\n case \"Edit\": {\n const filePath = input?.file_path ? String(input.file_path) : undefined;\n const displayPath = filePath\n ? toDisplayPath(filePath, options?.cwd)\n : undefined;\n let oldText: string | null = input?.old_string\n ? String(input.old_string)\n : null;\n let newText: string = input?.new_string ? String(input.new_string) : \"\";\n\n // try to display a rich diff by first checking if file content is cached\n // and valid (old_text exists in the content), then fall back to reading\n // file from disk, then fall back to fragemented snippet diff\n if (filePath && oldText !== null) {\n const fileContent = resolveFileContent(\n filePath,\n oldText,\n options?.cachedFileContent,\n );\n if (fileContent) {\n const newContent = input?.replace_all\n ? fileContent.replaceAll(oldText, newText)\n : fileContent.replace(oldText, newText);\n oldText = fileContent;\n newText = newContent;\n }\n }\n\n return {\n title: displayPath ? `Edit \\`${displayPath}\\`` : \"Edit\",\n kind: \"edit\",\n content:\n input && filePath\n ? [\n {\n type: \"diff\",\n path: filePath,\n oldText,\n newText,\n },\n ]\n : [],\n locations: filePath ? [{ path: filePath }] : [],\n };\n }\n\n case \"Write\": {\n let contentResult: ToolCallContent[] = [];\n const writeFilePath = input?.file_path\n ? String(input.file_path)\n : undefined;\n const writeDisplayPath = writeFilePath\n ? toDisplayPath(writeFilePath, options?.cwd)\n : undefined;\n const contentStr = input?.content ? String(input.content) : undefined;\n if (writeFilePath) {\n let oldContent: string | null = null;\n if (\n options?.cachedFileContent &&\n writeFilePath in options.cachedFileContent\n ) {\n oldContent = options.cachedFileContent[writeFilePath];\n } else {\n try {\n oldContent = fs.readFileSync(writeFilePath, \"utf-8\");\n } catch {\n // File doesn't exist — genuinely a new file\n }\n }\n contentResult = toolContent()\n .diff(writeFilePath, oldContent, contentStr ?? \"\")\n .build();\n } else if (contentStr) {\n contentResult = toolContent().text(contentStr).build();\n }\n return {\n title: writeDisplayPath ? `Write ${writeDisplayPath}` : \"Write\",\n kind: \"edit\",\n content: contentResult,\n locations: writeFilePath ? [{ path: writeFilePath }] : [],\n };\n }\n\n case \"Glob\": {\n let label = \"Find\";\n const pathStr = input?.path ? String(input.path) : undefined;\n if (pathStr) {\n label += ` \"${pathStr}\"`;\n }\n if (input?.pattern) {\n label += ` \"${String(input.pattern)}\"`;\n }\n return {\n title: label,\n kind: \"search\",\n content: [],\n locations: pathStr ? [{ path: pathStr }] : [],\n };\n }\n\n case \"Grep\": {\n let label = \"grep\";\n\n if (input?.[\"-i\"]) {\n label += \" -i\";\n }\n if (input?.[\"-n\"]) {\n label += \" -n\";\n }\n\n if (input?.[\"-A\"] !== undefined) {\n label += ` -A ${input[\"-A\"]}`;\n }\n if (input?.[\"-B\"] !== undefined) {\n label += ` -B ${input[\"-B\"]}`;\n }\n if (input?.[\"-C\"] !== undefined) {\n label += ` -C ${input[\"-C\"]}`;\n }\n\n if (input?.output_mode) {\n switch (input.output_mode) {\n case \"files_with_matches\":\n label += \" -l\";\n break;\n case \"count\":\n label += \" -c\";\n break;\n default:\n break;\n }\n }\n\n if (input?.head_limit !== undefined) {\n label += ` | head -${input.head_limit}`;\n }\n\n if (input?.glob) {\n label += ` --include=\"${String(input.glob)}\"`;\n }\n\n if (input?.type) {\n label += ` --type=${String(input.type)}`;\n }\n\n if (input?.multiline) {\n label += \" -P\";\n }\n\n if (input?.pattern) {\n label += ` \"${String(input.pattern)}\"`;\n }\n\n if (input?.path) {\n label += ` ${String(input.path)}`;\n }\n\n return {\n title: label,\n kind: \"search\",\n content: [],\n };\n }\n\n case \"WebFetch\":\n return {\n title: \"Fetch\",\n kind: \"fetch\",\n content: input?.url\n ? [\n {\n type: \"content\",\n content: resourceLink(String(input.url), String(input.url), {\n description: input?.prompt ? String(input.prompt) : undefined,\n }),\n },\n ]\n : [],\n };\n\n case \"WebSearch\": {\n let label = `\"${input?.query ? String(input.query) : \"\"}\"`;\n const allowedDomains = input?.allowed_domains as string[] | undefined;\n const blockedDomains = input?.blocked_domains as string[] | undefined;\n\n if (allowedDomains && allowedDomains.length > 0) {\n label += ` (allowed: ${allowedDomains.join(\", \")})`;\n }\n\n if (blockedDomains && blockedDomains.length > 0) {\n label += ` (blocked: ${blockedDomains.join(\", \")})`;\n }\n\n return {\n title: label,\n kind: \"fetch\",\n content: [],\n };\n }\n\n case \"TodoWrite\":\n return {\n title: Array.isArray(input?.todos)\n ? `Update TODOs: ${input.todos.map((todo: { content?: string }) => todo.content).join(\", \")}`\n : \"Update TODOs\",\n kind: \"think\",\n content: [],\n };\n\n case \"ExitPlanMode\":\n return {\n title: \"Ready to code?\",\n kind: \"switch_mode\",\n content: input?.plan\n ? toolContent().text(String(input.plan)).build()\n : [],\n };\n\n case \"AskUserQuestion\": {\n const questions = input?.questions as\n | Array<{ question?: string }>\n | undefined;\n return {\n title: questions?.[0]?.question || \"Question\",\n kind: \"other\" as ToolKind,\n content: questions\n ? toolContent()\n .text(JSON.stringify(questions, null, 2))\n .build()\n : [],\n };\n }\n\n case \"Other\": {\n let output: string;\n try {\n output = JSON.stringify(input, null, 2);\n } catch {\n output = typeof input === \"string\" ? input : \"{}\";\n }\n return {\n title: name || \"Unknown Tool\",\n kind: \"other\",\n content: toolContent().text(`\\`\\`\\`json\\n${output}\\`\\`\\``).build(),\n };\n }\n\n default: {\n if (name?.startsWith(\"mcp__\")) {\n return mcpToolInfo(name, input);\n }\n return {\n title: name || \"Unknown Tool\",\n kind: \"other\",\n content: [],\n };\n }\n }\n}\n\nfunction mcpToolInfo(\n name: string,\n _input: Record<string, unknown> | undefined,\n): ToolInfo {\n const metadata = getMcpToolMetadata(name);\n // Fallback: parse tool name from mcp__<server>__<tool> prefix\n const title =\n metadata?.name ?? (name.split(\"__\").slice(2).join(\"__\") || name);\n\n return {\n title,\n kind: \"other\",\n content: [],\n };\n}\n\ninterface StructuredPatchHunk {\n oldStart: number;\n oldLines: number;\n newStart: number;\n newLines: number;\n lines: string[];\n}\n\ninterface StructuredPatch {\n oldFileName: string;\n newFileName: string;\n hunks: StructuredPatchHunk[];\n}\n\nexport function toolUpdateFromEditToolResponse(\n toolResponse: unknown,\n): { content: ToolCallContent[]; locations: ToolCallLocation[] } | null {\n if (!toolResponse || typeof toolResponse !== \"object\") return null;\n const response = toolResponse as Record<string, unknown>;\n\n const patches = response.structuredPatch as StructuredPatch[] | undefined;\n if (!Array.isArray(patches) || patches.length === 0) return null;\n\n const content: ToolCallContent[] = [];\n const locations: ToolCallLocation[] = [];\n\n for (const patch of patches) {\n if (!patch.hunks || patch.hunks.length === 0) continue;\n\n const filePath = patch.newFileName || patch.oldFileName;\n\n const oldLines: string[] = [];\n const newLines: string[] = [];\n for (const hunk of patch.hunks) {\n for (const line of hunk.lines) {\n if (line.startsWith(\"-\")) {\n oldLines.push(line.slice(1));\n } else if (line.startsWith(\"+\")) {\n newLines.push(line.slice(1));\n } else if (line.startsWith(\" \")) {\n oldLines.push(line.slice(1));\n newLines.push(line.slice(1));\n }\n }\n }\n\n content.push({\n type: \"diff\",\n path: filePath,\n oldText: oldLines.join(\"\\n\"),\n newText: newLines.join(\"\\n\"),\n });\n\n const firstHunk = patch.hunks[0];\n locations.push({\n path: filePath,\n line: firstHunk.newStart,\n });\n }\n\n if (content.length === 0) return null;\n return { content, locations };\n}\n\nexport function toolUpdateFromToolResult(\n toolResult:\n | ToolResultBlockParam\n | BetaWebSearchToolResultBlockParam\n | BetaWebFetchToolResultBlockParam\n | WebSearchToolResultBlockParam\n | BetaCodeExecutionToolResultBlockParam\n | BetaBashCodeExecutionToolResultBlockParam\n | BetaTextEditorCodeExecutionToolResultBlockParam\n | BetaRequestMCPToolResultBlockParam\n | BetaToolSearchToolResultBlockParam,\n toolUse: Pick<ToolUseBlock, \"name\" | \"input\"> | undefined,\n options?: {\n supportsTerminalOutput?: boolean;\n toolUseId?: string;\n cachedFileContent?: Record<string, string>;\n },\n): Pick<ToolCallUpdate, \"title\" | \"content\" | \"locations\" | \"_meta\"> {\n if (\n \"is_error\" in toolResult &&\n toolResult.is_error &&\n toolResult.content &&\n (toolResult.content as unknown[]).length > 0\n ) {\n return toAcpContentUpdate(toolResult.content, true);\n }\n\n switch (toolUse?.name) {\n case \"Read\":\n if (Array.isArray(toolResult.content) && toolResult.content.length > 0) {\n return {\n content: toolResult.content.map((item) => {\n const itemObj = item as {\n type?: string;\n text?: string;\n source?: { data?: string; media_type?: string };\n };\n if (itemObj.type === \"text\") {\n return {\n type: \"content\" as const,\n content: text(\n markdownEscape(stripSystemReminders(itemObj.text ?? \"\")),\n ),\n };\n }\n if (itemObj.type === \"image\" && itemObj.source) {\n return {\n type: \"content\" as const,\n content: {\n type: \"image\" as const,\n data: itemObj.source.data ?? \"\",\n mimeType: itemObj.source.media_type ?? \"image/png\",\n },\n };\n }\n return {\n type: \"content\" as const,\n content: item as { type: \"text\"; text: string },\n };\n }),\n };\n } else if (\n typeof toolResult.content === \"string\" &&\n toolResult.content.length > 0\n ) {\n return {\n content: toolContent()\n .text(markdownEscape(stripSystemReminders(toolResult.content)))\n .build(),\n };\n }\n return {};\n\n case \"Bash\": {\n const result = toolResult.content;\n const terminalId =\n \"tool_use_id\" in toolResult ? String(toolResult.tool_use_id) : \"\";\n const isError = \"is_error\" in toolResult && toolResult.is_error;\n\n let output = \"\";\n let exitCode = isError ? 1 : 0;\n\n if (\n result &&\n typeof result === \"object\" &&\n \"type\" in result &&\n (result as { type: string }).type === \"bash_code_execution_result\"\n ) {\n const bashResult = result as {\n stdout?: string;\n stderr?: string;\n return_code: number;\n };\n output = [bashResult.stdout, bashResult.stderr]\n .filter(Boolean)\n .join(\"\\n\");\n exitCode = bashResult.return_code;\n } else if (typeof result === \"string\") {\n output = result;\n } else if (\n Array.isArray(result) &&\n result.length > 0 &&\n \"text\" in result[0] &&\n typeof result[0].text === \"string\"\n ) {\n output = result.map((c: { text?: string }) => c.text ?? \"\").join(\"\\n\");\n }\n\n if (options?.supportsTerminalOutput) {\n return {\n content: [{ type: \"terminal\" as const, terminalId }],\n _meta: {\n terminal_info: {\n terminal_id: terminalId,\n },\n terminal_output: {\n terminal_id: terminalId,\n data: output,\n },\n terminal_exit: {\n terminal_id: terminalId,\n exit_code: exitCode,\n signal: null,\n },\n },\n };\n }\n if (output.trim()) {\n return {\n content: toolContent()\n .text(`\\`\\`\\`console\\n${output.trimEnd()}\\n\\`\\`\\``)\n .build(),\n };\n }\n return {};\n }\n case \"Edit\":\n case \"Write\":\n return {};\n\n case \"ExitPlanMode\": {\n return { title: \"Exited Plan Mode\" };\n }\n case \"AskUserQuestion\": {\n const content = toolResult.content;\n if (Array.isArray(content) && content.length > 0) {\n const firstItem = content[0];\n if (\n typeof firstItem === \"object\" &&\n firstItem !== null &&\n \"text\" in firstItem\n ) {\n return {\n title: \"Answer received\",\n content: toolContent().text(String(firstItem.text)).build(),\n };\n }\n }\n return { title: \"Question answered\" };\n }\n case \"WebFetch\": {\n const input = toolUse?.input as Record<string, unknown> | undefined;\n const url = input?.url ? String(input.url) : \"\";\n const prompt = input?.prompt ? String(input.prompt) : undefined;\n\n const resultContent = toAcpContentUpdate(\n toolResult.content,\n \"is_error\" in toolResult ? toolResult.is_error : false,\n );\n\n const content: ToolCallContent[] = [];\n if (url) {\n content.push({\n type: \"content\",\n content: resourceLink(url, url, {\n description: prompt,\n }),\n });\n }\n if (resultContent.content) {\n content.push(...resultContent.content);\n }\n\n return { content };\n }\n default: {\n return toAcpContentUpdate(\n toolResult.content,\n \"is_error\" in toolResult ? toolResult.is_error : false,\n );\n }\n }\n}\n\nfunction itemToText(item: unknown): string | null {\n if (!item || typeof item !== \"object\") return null;\n const obj = item as Record<string, unknown>;\n // Standard text block\n if (obj.type === \"text\" && typeof obj.text === \"string\") {\n return stripSystemReminders(obj.text);\n }\n // Any other structured object — serialize it\n try {\n return JSON.stringify(obj, null, 2);\n } catch {\n return null;\n }\n}\n\nfunction toAcpContentUpdate(\n content: unknown,\n isError: boolean = false,\n): Pick<ToolCallUpdate, \"content\"> {\n if (Array.isArray(content) && content.length > 0) {\n const texts: string[] = [];\n for (const item of content) {\n const t = itemToText(item);\n if (t) texts.push(t);\n }\n if (texts.length > 0) {\n const combined = texts.join(\"\\n\");\n return {\n content: toolContent()\n .text(isError ? `\\`\\`\\`\\n${combined}\\n\\`\\`\\`` : combined)\n .build(),\n };\n }\n } else if (typeof content === \"string\" && content.length > 0) {\n return {\n content: toolContent()\n .text(isError ? `\\`\\`\\`\\n${content}\\n\\`\\`\\`` : content)\n .build(),\n };\n } else if (content && typeof content === \"object\") {\n try {\n const json = JSON.stringify(content, null, 2);\n if (json && json !== \"{}\") {\n return {\n content: toolContent().text(json).build(),\n };\n }\n } catch {\n // ignore serialization errors\n }\n }\n return {};\n}\n\nexport type ClaudePlanEntry = {\n content: string;\n status: \"pending\" | \"in_progress\" | \"completed\";\n activeForm: string;\n};\n\nexport function planEntries(input: { todos: ClaudePlanEntry[] }): PlanEntry[] {\n return input.todos.map((input) => ({\n content: input.content,\n status: input.status,\n priority: \"medium\",\n }));\n}\n\n/**\n * attempt to resolve full file contents for diff generation\n *\n * 1) check file content cache exists, and is valid (old_text in content)\n * 2) if missing or invalid, read file from disk\n * 3) if both fail, return null, we'll fall back to fragmented snippet diff\n */\nfunction resolveFileContent(\n filePath: string,\n oldText: string,\n cachedFileContent?: Record<string, string>,\n): string | null {\n if (cachedFileContent && filePath in cachedFileContent) {\n const cached = cachedFileContent[filePath];\n if (cached.includes(oldText)) {\n return cached;\n }\n }\n\n try {\n const content = fs.readFileSync(filePath, \"utf-8\");\n if (content.includes(oldText)) {\n return content;\n }\n } catch {\n return null;\n }\n\n return null;\n}\n\nfunction markdownEscape(text: string): string {\n let escapedText = \"```\";\n for (const [m] of text.matchAll(/^```+/gm)) {\n while (m.length >= escapedText.length) {\n escapedText += \"`\";\n }\n }\n return `${escapedText}\\n${text}${text.endsWith(\"\\n\") ? \"\" : \"\\n\"}${escapedText}`;\n}\n","import type { ContentBlock, ToolCallContent } from \"@agentclientprotocol/sdk\";\n\nexport function text(value: string): ContentBlock {\n return { type: \"text\", text: value };\n}\n\nexport function image(\n data: string,\n mimeType: string,\n uri?: string,\n): ContentBlock {\n return { type: \"image\", data, mimeType, uri };\n}\n\nexport function resourceLink(\n uri: string,\n name: string,\n options?: {\n mimeType?: string;\n title?: string;\n description?: string;\n size?: number | null;\n },\n): ContentBlock {\n return {\n type: \"resource_link\",\n uri,\n name,\n ...options,\n };\n}\n\nclass ToolContentBuilder {\n private items: ToolCallContent[] = [];\n\n text(value: string): this {\n this.items.push({ type: \"content\", content: text(value) });\n return this;\n }\n\n image(data: string, mimeType: string, uri?: string): this {\n this.items.push({ type: \"content\", content: image(data, mimeType, uri) });\n return this;\n }\n\n diff(path: string, oldText: string | null, newText: string): this {\n this.items.push({ type: \"diff\", path, oldText, newText });\n return this;\n }\n\n build(): ToolCallContent[] {\n return this.items;\n }\n}\n\nexport function toolContent(): ToolContentBuilder {\n return new ToolContentBuilder();\n}\n","import type { McpServerStatus, Query } from \"@anthropic-ai/claude-agent-sdk\";\nimport { Logger } from \"../../../utils/logger\";\n\nexport interface McpToolMetadata {\n readOnly: boolean;\n name: string;\n description?: string;\n}\n\nconst mcpToolMetadataCache: Map<string, McpToolMetadata> = new Map();\n\nconst PENDING_RETRY_INTERVAL_MS = 1_000;\nconst PENDING_MAX_RETRIES = 10;\n\nfunction buildToolKey(serverName: string, toolName: string): string {\n return `mcp__${serverName}__${toolName}`;\n}\n\nfunction delay(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nexport async function fetchMcpToolMetadata(\n q: Query,\n logger: Logger = new Logger({ debug: false, prefix: \"[McpToolMetadata]\" }),\n): Promise<void> {\n let retries = 0;\n\n while (retries <= PENDING_MAX_RETRIES) {\n let statuses: McpServerStatus[];\n try {\n statuses = await q.mcpServerStatus();\n } catch (error) {\n logger.error(\"Failed to fetch MCP server status\", {\n error: error instanceof Error ? error.message : String(error),\n });\n return;\n }\n\n const pendingServers = statuses.filter((s) => s.status === \"pending\");\n\n for (const server of statuses) {\n if (server.status !== \"connected\" || !server.tools) {\n continue;\n }\n\n let readOnlyCount = 0;\n for (const tool of server.tools) {\n const toolKey = buildToolKey(server.name, tool.name);\n const readOnly = tool.annotations?.readOnly === true;\n\n mcpToolMetadataCache.set(toolKey, {\n readOnly,\n name: tool.name,\n description: tool.description,\n });\n if (readOnly) readOnlyCount++;\n }\n\n logger.info(\"Fetched MCP tool metadata\", {\n serverName: server.name,\n toolCount: server.tools.length,\n readOnlyCount,\n });\n }\n\n if (pendingServers.length === 0) {\n return;\n }\n\n retries++;\n if (retries > PENDING_MAX_RETRIES) {\n logger.warn(\"Gave up waiting for pending MCP servers\", {\n pendingServers: pendingServers.map((s) => s.name),\n });\n return;\n }\n\n logger.info(\"Waiting for pending MCP servers\", {\n pendingServers: pendingServers.map((s) => s.name),\n retry: retries,\n });\n await delay(PENDING_RETRY_INTERVAL_MS);\n }\n}\n\nexport function getMcpToolMetadata(\n toolName: string,\n): McpToolMetadata | undefined {\n return mcpToolMetadataCache.get(toolName);\n}\n\nexport function isMcpToolReadOnly(toolName: string): boolean {\n const metadata = mcpToolMetadataCache.get(toolName);\n return metadata?.readOnly === true;\n}\n\nexport function getConnectedMcpServerNames(): string[] {\n const names = new Set<string>();\n for (const key of mcpToolMetadataCache.keys()) {\n const parts = key.split(\"__\");\n if (parts.length >= 3) names.add(parts[1]);\n }\n return [...names];\n}\n\nexport function clearMcpToolMetadataCache(): void {\n mcpToolMetadataCache.clear();\n}\n"],"mappings":"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","names":["path","input","text"]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/adapters/claude/conversion/tool-use-to-acp.ts","../../../../src/utils/acp-content.ts","../../../../src/adapters/claude/mcp/tool-metadata.ts"],"sourcesContent":["import fs from \"node:fs\";\nimport path from \"node:path\";\nimport type {\n PlanEntry,\n ToolCall,\n ToolCallContent,\n ToolCallLocation,\n ToolCallUpdate,\n ToolKind,\n} from \"@agentclientprotocol/sdk\";\nimport type {\n ToolResultBlockParam,\n ToolUseBlock,\n WebSearchToolResultBlockParam,\n} from \"@anthropic-ai/sdk/resources\";\nimport type {\n BetaBashCodeExecutionToolResultBlockParam,\n BetaCodeExecutionToolResultBlockParam,\n BetaRequestMCPToolResultBlockParam,\n BetaTextEditorCodeExecutionToolResultBlockParam,\n BetaToolSearchToolResultBlockParam,\n BetaWebFetchToolResultBlockParam,\n BetaWebSearchToolResultBlockParam,\n} from \"@anthropic-ai/sdk/resources/beta.mjs\";\n\nconst SYSTEM_REMINDER_REGEX =\n /\\s*<system-reminder>[\\s\\S]*?<\\/system-reminder>/g;\n\nfunction stripSystemReminders(value: string): string {\n return value.replace(SYSTEM_REMINDER_REGEX, \"\");\n}\n\nimport { resourceLink, text, toolContent } from \"../../../utils/acp-content\";\nimport type { EnrichedReadCache } from \"../hooks\";\nimport { getMcpToolMetadata } from \"../mcp/tool-metadata\";\n\ntype ToolInfo = Pick<ToolCall, \"title\" | \"kind\" | \"content\" | \"locations\">;\n\n/**\n * Convert an absolute file path to a project-relative path for display.\n * Returns the original path if it's outside the project directory or if no cwd is provided.\n */\nexport function toDisplayPath(filePath: string, cwd?: string): string {\n if (!cwd) return filePath;\n const resolvedCwd = path.resolve(cwd);\n const resolvedFile = path.resolve(filePath);\n if (\n resolvedFile.startsWith(resolvedCwd + path.sep) ||\n resolvedFile === resolvedCwd\n ) {\n return path.relative(resolvedCwd, resolvedFile);\n }\n return filePath;\n}\n\nexport function toolInfoFromToolUse(\n toolUse: Pick<ToolUseBlock, \"name\" | \"input\">,\n options?: {\n supportsTerminalOutput?: boolean;\n toolUseId?: string;\n cachedFileContent?: Record<string, string>;\n cwd?: string;\n },\n): ToolInfo {\n const name = toolUse.name;\n const input = toolUse.input as Record<string, unknown> | undefined;\n\n switch (name) {\n case \"Task\":\n case \"Agent\":\n return {\n title: input?.description ? String(input.description) : name,\n kind: \"think\",\n content: input?.prompt\n ? toolContent().text(String(input.prompt)).build()\n : [],\n };\n\n case \"NotebookRead\":\n return {\n title: input?.notebook_path\n ? `Read Notebook ${String(input.notebook_path)}`\n : \"Read Notebook\",\n kind: \"read\",\n content: [],\n locations: input?.notebook_path\n ? [{ path: String(input.notebook_path) }]\n : [],\n };\n\n case \"NotebookEdit\":\n return {\n title: input?.notebook_path\n ? `Edit Notebook ${String(input.notebook_path)}`\n : \"Edit Notebook\",\n kind: \"edit\",\n content: input?.new_source\n ? toolContent().text(String(input.new_source)).build()\n : [],\n locations: input?.notebook_path\n ? [{ path: String(input.notebook_path) }]\n : [],\n };\n\n case \"Bash\":\n if (options?.supportsTerminalOutput && options?.toolUseId) {\n return {\n title: input?.description\n ? String(input.description)\n : \"Execute command\",\n kind: \"execute\",\n content: [{ type: \"terminal\", terminalId: options.toolUseId }],\n };\n }\n return {\n title: input?.description\n ? String(input.description)\n : \"Execute command\",\n kind: \"execute\",\n content: input?.command\n ? toolContent().text(String(input.command)).build()\n : [],\n };\n\n case \"BashOutput\":\n return {\n title: \"Tail Logs\",\n kind: \"execute\",\n content: [],\n };\n\n case \"KillShell\":\n return {\n title: \"Kill Process\",\n kind: \"execute\",\n content: [],\n };\n\n case \"Read\": {\n let limit = \"\";\n const inputLimit = input?.limit as number | undefined;\n const inputOffset = (input?.offset as number | undefined) ?? 1;\n if (inputLimit) {\n limit = ` (${inputOffset} - ${inputOffset + inputLimit - 1})`;\n } else if (inputOffset > 1) {\n limit = ` (from line ${inputOffset})`;\n }\n const displayPath = input?.file_path\n ? toDisplayPath(String(input.file_path), options?.cwd)\n : \"File\";\n return {\n title: `Read ${displayPath}${limit}`,\n kind: \"read\",\n locations: input?.file_path\n ? [\n {\n path: String(input.file_path),\n line: inputOffset,\n },\n ]\n : [],\n content: [],\n };\n }\n\n case \"LS\":\n return {\n title: `List the ${input?.path ? `\\`${String(input.path)}\\`` : \"current\"} directory's contents`,\n kind: \"search\",\n content: [],\n locations: [],\n };\n\n case \"Edit\": {\n const filePath = input?.file_path ? String(input.file_path) : undefined;\n const displayPath = filePath\n ? toDisplayPath(filePath, options?.cwd)\n : undefined;\n let oldText: string | null = input?.old_string\n ? String(input.old_string)\n : null;\n let newText: string = input?.new_string ? String(input.new_string) : \"\";\n\n // try to display a rich diff by first checking if file content is cached\n // and valid (old_text exists in the content), then fall back to reading\n // file from disk, then fall back to fragemented snippet diff\n if (filePath && oldText !== null) {\n const fileContent = resolveFileContent(\n filePath,\n oldText,\n options?.cachedFileContent,\n );\n if (fileContent) {\n const newContent = input?.replace_all\n ? fileContent.replaceAll(oldText, newText)\n : fileContent.replace(oldText, newText);\n oldText = fileContent;\n newText = newContent;\n }\n }\n\n return {\n title: displayPath ? `Edit \\`${displayPath}\\`` : \"Edit\",\n kind: \"edit\",\n content:\n input && filePath\n ? [\n {\n type: \"diff\",\n path: filePath,\n oldText,\n newText,\n },\n ]\n : [],\n locations: filePath ? [{ path: filePath }] : [],\n };\n }\n\n case \"Write\": {\n let contentResult: ToolCallContent[] = [];\n const writeFilePath = input?.file_path\n ? String(input.file_path)\n : undefined;\n const writeDisplayPath = writeFilePath\n ? toDisplayPath(writeFilePath, options?.cwd)\n : undefined;\n const contentStr = input?.content ? String(input.content) : undefined;\n if (writeFilePath) {\n let oldContent: string | null = null;\n if (\n options?.cachedFileContent &&\n writeFilePath in options.cachedFileContent\n ) {\n oldContent = options.cachedFileContent[writeFilePath];\n } else {\n try {\n oldContent = fs.readFileSync(writeFilePath, \"utf-8\");\n } catch {\n // File doesn't exist — genuinely a new file\n }\n }\n contentResult = toolContent()\n .diff(writeFilePath, oldContent, contentStr ?? \"\")\n .build();\n } else if (contentStr) {\n contentResult = toolContent().text(contentStr).build();\n }\n return {\n title: writeDisplayPath ? `Write ${writeDisplayPath}` : \"Write\",\n kind: \"edit\",\n content: contentResult,\n locations: writeFilePath ? [{ path: writeFilePath }] : [],\n };\n }\n\n case \"Glob\": {\n let label = \"Find\";\n const pathStr = input?.path ? String(input.path) : undefined;\n if (pathStr) {\n label += ` \"${pathStr}\"`;\n }\n if (input?.pattern) {\n label += ` \"${String(input.pattern)}\"`;\n }\n return {\n title: label,\n kind: \"search\",\n content: [],\n locations: pathStr ? [{ path: pathStr }] : [],\n };\n }\n\n case \"Grep\": {\n let label = \"grep\";\n\n if (input?.[\"-i\"]) {\n label += \" -i\";\n }\n if (input?.[\"-n\"]) {\n label += \" -n\";\n }\n\n if (input?.[\"-A\"] !== undefined) {\n label += ` -A ${input[\"-A\"]}`;\n }\n if (input?.[\"-B\"] !== undefined) {\n label += ` -B ${input[\"-B\"]}`;\n }\n if (input?.[\"-C\"] !== undefined) {\n label += ` -C ${input[\"-C\"]}`;\n }\n\n if (input?.output_mode) {\n switch (input.output_mode) {\n case \"files_with_matches\":\n label += \" -l\";\n break;\n case \"count\":\n label += \" -c\";\n break;\n default:\n break;\n }\n }\n\n if (input?.head_limit !== undefined) {\n label += ` | head -${input.head_limit}`;\n }\n\n if (input?.glob) {\n label += ` --include=\"${String(input.glob)}\"`;\n }\n\n if (input?.type) {\n label += ` --type=${String(input.type)}`;\n }\n\n if (input?.multiline) {\n label += \" -P\";\n }\n\n if (input?.pattern) {\n label += ` \"${String(input.pattern)}\"`;\n }\n\n if (input?.path) {\n label += ` ${String(input.path)}`;\n }\n\n return {\n title: label,\n kind: \"search\",\n content: [],\n };\n }\n\n case \"WebFetch\":\n return {\n title: \"Fetch\",\n kind: \"fetch\",\n content: input?.url\n ? [\n {\n type: \"content\",\n content: resourceLink(String(input.url), String(input.url), {\n description: input?.prompt ? String(input.prompt) : undefined,\n }),\n },\n ]\n : [],\n };\n\n case \"WebSearch\": {\n let label = `\"${input?.query ? String(input.query) : \"\"}\"`;\n const allowedDomains = input?.allowed_domains as string[] | undefined;\n const blockedDomains = input?.blocked_domains as string[] | undefined;\n\n if (allowedDomains && allowedDomains.length > 0) {\n label += ` (allowed: ${allowedDomains.join(\", \")})`;\n }\n\n if (blockedDomains && blockedDomains.length > 0) {\n label += ` (blocked: ${blockedDomains.join(\", \")})`;\n }\n\n return {\n title: label,\n kind: \"fetch\",\n content: [],\n };\n }\n\n case \"TodoWrite\":\n return {\n title: Array.isArray(input?.todos)\n ? `Update TODOs: ${input.todos.map((todo: { content?: string }) => todo.content).join(\", \")}`\n : \"Update TODOs\",\n kind: \"think\",\n content: [],\n };\n\n case \"ExitPlanMode\":\n return {\n title: \"Ready to code?\",\n kind: \"switch_mode\",\n content: input?.plan\n ? toolContent().text(String(input.plan)).build()\n : [],\n };\n\n case \"AskUserQuestion\": {\n const questions = input?.questions as\n | Array<{ question?: string }>\n | undefined;\n return {\n title: questions?.[0]?.question || \"Question\",\n kind: \"other\" as ToolKind,\n content: questions\n ? toolContent()\n .text(JSON.stringify(questions, null, 2))\n .build()\n : [],\n };\n }\n\n case \"Other\": {\n let output: string;\n try {\n output = JSON.stringify(input, null, 2);\n } catch {\n output = typeof input === \"string\" ? input : \"{}\";\n }\n return {\n title: name || \"Unknown Tool\",\n kind: \"other\",\n content: toolContent().text(`\\`\\`\\`json\\n${output}\\`\\`\\``).build(),\n };\n }\n\n default: {\n if (name?.startsWith(\"mcp__\")) {\n return mcpToolInfo(name, input);\n }\n return {\n title: name || \"Unknown Tool\",\n kind: \"other\",\n content: [],\n };\n }\n }\n}\n\nfunction mcpToolInfo(\n name: string,\n _input: Record<string, unknown> | undefined,\n): ToolInfo {\n const metadata = getMcpToolMetadata(name);\n // Fallback: parse tool name from mcp__<server>__<tool> prefix\n const title =\n metadata?.name ?? (name.split(\"__\").slice(2).join(\"__\") || name);\n\n return {\n title,\n kind: \"other\",\n content: [],\n };\n}\n\ninterface StructuredPatchHunk {\n oldStart: number;\n oldLines: number;\n newStart: number;\n newLines: number;\n lines: string[];\n}\n\ninterface StructuredPatch {\n oldFileName: string;\n newFileName: string;\n hunks: StructuredPatchHunk[];\n}\n\nexport function toolUpdateFromEditToolResponse(\n toolResponse: unknown,\n): { content: ToolCallContent[]; locations: ToolCallLocation[] } | null {\n if (!toolResponse || typeof toolResponse !== \"object\") return null;\n const response = toolResponse as Record<string, unknown>;\n\n const patches = response.structuredPatch as StructuredPatch[] | undefined;\n if (!Array.isArray(patches) || patches.length === 0) return null;\n\n const content: ToolCallContent[] = [];\n const locations: ToolCallLocation[] = [];\n\n for (const patch of patches) {\n if (!patch.hunks || patch.hunks.length === 0) continue;\n\n const filePath = patch.newFileName || patch.oldFileName;\n\n const oldLines: string[] = [];\n const newLines: string[] = [];\n for (const hunk of patch.hunks) {\n for (const line of hunk.lines) {\n if (line.startsWith(\"-\")) {\n oldLines.push(line.slice(1));\n } else if (line.startsWith(\"+\")) {\n newLines.push(line.slice(1));\n } else if (line.startsWith(\" \")) {\n oldLines.push(line.slice(1));\n newLines.push(line.slice(1));\n }\n }\n }\n\n content.push({\n type: \"diff\",\n path: filePath,\n oldText: oldLines.join(\"\\n\"),\n newText: newLines.join(\"\\n\"),\n });\n\n const firstHunk = patch.hunks[0];\n locations.push({\n path: filePath,\n line: firstHunk.newStart,\n });\n }\n\n if (content.length === 0) return null;\n return { content, locations };\n}\n\nexport function toolUpdateFromToolResult(\n toolResult:\n | ToolResultBlockParam\n | BetaWebSearchToolResultBlockParam\n | BetaWebFetchToolResultBlockParam\n | WebSearchToolResultBlockParam\n | BetaCodeExecutionToolResultBlockParam\n | BetaBashCodeExecutionToolResultBlockParam\n | BetaTextEditorCodeExecutionToolResultBlockParam\n | BetaRequestMCPToolResultBlockParam\n | BetaToolSearchToolResultBlockParam,\n toolUse: Pick<ToolUseBlock, \"name\" | \"input\"> | undefined,\n options?: {\n supportsTerminalOutput?: boolean;\n toolUseId?: string;\n cachedFileContent?: Record<string, string>;\n enrichedReadCache?: EnrichedReadCache;\n },\n): Pick<ToolCallUpdate, \"title\" | \"content\" | \"locations\" | \"_meta\"> {\n if (\n \"is_error\" in toolResult &&\n toolResult.is_error &&\n toolResult.content &&\n (toolResult.content as unknown[]).length > 0\n ) {\n return toAcpContentUpdate(toolResult.content, true);\n }\n\n switch (toolUse?.name) {\n case \"Read\": {\n const cache = options?.enrichedReadCache;\n const enriched =\n cache && options?.toolUseId ? cache.get(options.toolUseId) : undefined;\n if (enriched !== undefined && cache && options?.toolUseId) {\n cache.delete(options.toolUseId);\n return {\n content: [\n {\n type: \"content\" as const,\n content: text(markdownEscape(enriched)),\n },\n ],\n };\n }\n if (Array.isArray(toolResult.content) && toolResult.content.length > 0) {\n return {\n content: toolResult.content.map((item) => {\n const itemObj = item as {\n type?: string;\n text?: string;\n source?: { data?: string; media_type?: string };\n };\n if (itemObj.type === \"text\") {\n return {\n type: \"content\" as const,\n content: text(\n markdownEscape(stripSystemReminders(itemObj.text ?? \"\")),\n ),\n };\n }\n if (itemObj.type === \"image\" && itemObj.source) {\n return {\n type: \"content\" as const,\n content: {\n type: \"image\" as const,\n data: itemObj.source.data ?? \"\",\n mimeType: itemObj.source.media_type ?? \"image/png\",\n },\n };\n }\n return {\n type: \"content\" as const,\n content: item as { type: \"text\"; text: string },\n };\n }),\n };\n } else if (\n typeof toolResult.content === \"string\" &&\n toolResult.content.length > 0\n ) {\n return {\n content: toolContent()\n .text(markdownEscape(stripSystemReminders(toolResult.content)))\n .build(),\n };\n }\n return {};\n }\n\n case \"Bash\": {\n const result = toolResult.content;\n const terminalId =\n \"tool_use_id\" in toolResult ? String(toolResult.tool_use_id) : \"\";\n const isError = \"is_error\" in toolResult && toolResult.is_error;\n\n let output = \"\";\n let exitCode = isError ? 1 : 0;\n\n if (\n result &&\n typeof result === \"object\" &&\n \"type\" in result &&\n (result as { type: string }).type === \"bash_code_execution_result\"\n ) {\n const bashResult = result as {\n stdout?: string;\n stderr?: string;\n return_code: number;\n };\n output = [bashResult.stdout, bashResult.stderr]\n .filter(Boolean)\n .join(\"\\n\");\n exitCode = bashResult.return_code;\n } else if (typeof result === \"string\") {\n output = result;\n } else if (\n Array.isArray(result) &&\n result.length > 0 &&\n \"text\" in result[0] &&\n typeof result[0].text === \"string\"\n ) {\n output = result.map((c: { text?: string }) => c.text ?? \"\").join(\"\\n\");\n }\n\n if (options?.supportsTerminalOutput) {\n return {\n content: [{ type: \"terminal\" as const, terminalId }],\n _meta: {\n terminal_info: {\n terminal_id: terminalId,\n },\n terminal_output: {\n terminal_id: terminalId,\n data: output,\n },\n terminal_exit: {\n terminal_id: terminalId,\n exit_code: exitCode,\n signal: null,\n },\n },\n };\n }\n if (output.trim()) {\n return {\n content: toolContent()\n .text(`\\`\\`\\`console\\n${output.trimEnd()}\\n\\`\\`\\``)\n .build(),\n };\n }\n return {};\n }\n case \"Edit\":\n case \"Write\":\n return {};\n\n case \"ExitPlanMode\": {\n return { title: \"Exited Plan Mode\" };\n }\n case \"AskUserQuestion\": {\n const content = toolResult.content;\n if (Array.isArray(content) && content.length > 0) {\n const firstItem = content[0];\n if (\n typeof firstItem === \"object\" &&\n firstItem !== null &&\n \"text\" in firstItem\n ) {\n return {\n title: \"Answer received\",\n content: toolContent().text(String(firstItem.text)).build(),\n };\n }\n }\n return { title: \"Question answered\" };\n }\n case \"WebFetch\": {\n const input = toolUse?.input as Record<string, unknown> | undefined;\n const url = input?.url ? String(input.url) : \"\";\n const prompt = input?.prompt ? String(input.prompt) : undefined;\n\n const resultContent = toAcpContentUpdate(\n toolResult.content,\n \"is_error\" in toolResult ? toolResult.is_error : false,\n );\n\n const content: ToolCallContent[] = [];\n if (url) {\n content.push({\n type: \"content\",\n content: resourceLink(url, url, {\n description: prompt,\n }),\n });\n }\n if (resultContent.content) {\n content.push(...resultContent.content);\n }\n\n return { content };\n }\n default: {\n return toAcpContentUpdate(\n toolResult.content,\n \"is_error\" in toolResult ? toolResult.is_error : false,\n );\n }\n }\n}\n\nfunction itemToText(item: unknown): string | null {\n if (!item || typeof item !== \"object\") return null;\n const obj = item as Record<string, unknown>;\n // Standard text block\n if (obj.type === \"text\" && typeof obj.text === \"string\") {\n return stripSystemReminders(obj.text);\n }\n // Any other structured object — serialize it\n try {\n return JSON.stringify(obj, null, 2);\n } catch {\n return null;\n }\n}\n\nfunction toAcpContentUpdate(\n content: unknown,\n isError: boolean = false,\n): Pick<ToolCallUpdate, \"content\"> {\n if (Array.isArray(content) && content.length > 0) {\n const texts: string[] = [];\n for (const item of content) {\n const t = itemToText(item);\n if (t) texts.push(t);\n }\n if (texts.length > 0) {\n const combined = texts.join(\"\\n\");\n return {\n content: toolContent()\n .text(isError ? `\\`\\`\\`\\n${combined}\\n\\`\\`\\`` : combined)\n .build(),\n };\n }\n } else if (typeof content === \"string\" && content.length > 0) {\n return {\n content: toolContent()\n .text(isError ? `\\`\\`\\`\\n${content}\\n\\`\\`\\`` : content)\n .build(),\n };\n } else if (content && typeof content === \"object\") {\n try {\n const json = JSON.stringify(content, null, 2);\n if (json && json !== \"{}\") {\n return {\n content: toolContent().text(json).build(),\n };\n }\n } catch {\n // ignore serialization errors\n }\n }\n return {};\n}\n\nexport type ClaudePlanEntry = {\n content: string;\n status: \"pending\" | \"in_progress\" | \"completed\";\n activeForm: string;\n};\n\nexport function planEntries(input: { todos: ClaudePlanEntry[] }): PlanEntry[] {\n return input.todos.map((input) => ({\n content: input.content,\n status: input.status,\n priority: \"medium\",\n }));\n}\n\n/**\n * attempt to resolve full file contents for diff generation\n *\n * 1) check file content cache exists, and is valid (old_text in content)\n * 2) if missing or invalid, read file from disk\n * 3) if both fail, return null, we'll fall back to fragmented snippet diff\n */\nfunction resolveFileContent(\n filePath: string,\n oldText: string,\n cachedFileContent?: Record<string, string>,\n): string | null {\n if (cachedFileContent && filePath in cachedFileContent) {\n const cached = cachedFileContent[filePath];\n if (cached.includes(oldText)) {\n return cached;\n }\n }\n\n try {\n const content = fs.readFileSync(filePath, \"utf-8\");\n if (content.includes(oldText)) {\n return content;\n }\n } catch {\n return null;\n }\n\n return null;\n}\n\nfunction markdownEscape(text: string): string {\n let escapedText = \"```\";\n for (const [m] of text.matchAll(/^```+/gm)) {\n while (m.length >= escapedText.length) {\n escapedText += \"`\";\n }\n }\n return `${escapedText}\\n${text}${text.endsWith(\"\\n\") ? \"\" : \"\\n\"}${escapedText}`;\n}\n","import type { ContentBlock, ToolCallContent } from \"@agentclientprotocol/sdk\";\n\nexport function text(value: string): ContentBlock {\n return { type: \"text\", text: value };\n}\n\nexport function image(\n data: string,\n mimeType: string,\n uri?: string,\n): ContentBlock {\n return { type: \"image\", data, mimeType, uri };\n}\n\nexport function resourceLink(\n uri: string,\n name: string,\n options?: {\n mimeType?: string;\n title?: string;\n description?: string;\n size?: number | null;\n },\n): ContentBlock {\n return {\n type: \"resource_link\",\n uri,\n name,\n ...options,\n };\n}\n\nclass ToolContentBuilder {\n private items: ToolCallContent[] = [];\n\n text(value: string): this {\n this.items.push({ type: \"content\", content: text(value) });\n return this;\n }\n\n image(data: string, mimeType: string, uri?: string): this {\n this.items.push({ type: \"content\", content: image(data, mimeType, uri) });\n return this;\n }\n\n diff(path: string, oldText: string | null, newText: string): this {\n this.items.push({ type: \"diff\", path, oldText, newText });\n return this;\n }\n\n build(): ToolCallContent[] {\n return this.items;\n }\n}\n\nexport function toolContent(): ToolContentBuilder {\n return new ToolContentBuilder();\n}\n","import type { McpServerStatus, Query } from \"@anthropic-ai/claude-agent-sdk\";\nimport { Logger } from \"../../../utils/logger\";\n\nexport interface McpToolMetadata {\n readOnly: boolean;\n name: string;\n description?: string;\n}\n\nconst mcpToolMetadataCache: Map<string, McpToolMetadata> = new Map();\n\nconst PENDING_RETRY_INTERVAL_MS = 1_000;\nconst PENDING_MAX_RETRIES = 10;\n\nfunction buildToolKey(serverName: string, toolName: string): string {\n return `mcp__${serverName}__${toolName}`;\n}\n\nfunction delay(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nexport async function fetchMcpToolMetadata(\n q: Query,\n logger: Logger = new Logger({ debug: false, prefix: \"[McpToolMetadata]\" }),\n): Promise<void> {\n let retries = 0;\n\n while (retries <= PENDING_MAX_RETRIES) {\n let statuses: McpServerStatus[];\n try {\n statuses = await q.mcpServerStatus();\n } catch (error) {\n logger.error(\"Failed to fetch MCP server status\", {\n error: error instanceof Error ? error.message : String(error),\n });\n return;\n }\n\n const pendingServers = statuses.filter((s) => s.status === \"pending\");\n\n for (const server of statuses) {\n if (server.status !== \"connected\" || !server.tools) {\n continue;\n }\n\n let readOnlyCount = 0;\n for (const tool of server.tools) {\n const toolKey = buildToolKey(server.name, tool.name);\n const readOnly = tool.annotations?.readOnly === true;\n\n mcpToolMetadataCache.set(toolKey, {\n readOnly,\n name: tool.name,\n description: tool.description,\n });\n if (readOnly) readOnlyCount++;\n }\n\n logger.info(\"Fetched MCP tool metadata\", {\n serverName: server.name,\n toolCount: server.tools.length,\n readOnlyCount,\n });\n }\n\n if (pendingServers.length === 0) {\n return;\n }\n\n retries++;\n if (retries > PENDING_MAX_RETRIES) {\n logger.warn(\"Gave up waiting for pending MCP servers\", {\n pendingServers: pendingServers.map((s) => s.name),\n });\n return;\n }\n\n logger.info(\"Waiting for pending MCP servers\", {\n pendingServers: pendingServers.map((s) => s.name),\n retry: retries,\n });\n await delay(PENDING_RETRY_INTERVAL_MS);\n }\n}\n\nexport function getMcpToolMetadata(\n toolName: string,\n): McpToolMetadata | undefined {\n return mcpToolMetadataCache.get(toolName);\n}\n\nexport function isMcpToolReadOnly(toolName: string): boolean {\n const metadata = mcpToolMetadataCache.get(toolName);\n return metadata?.readOnly === true;\n}\n\nexport function getConnectedMcpServerNames(): string[] {\n const names = new Set<string>();\n for (const key of mcpToolMetadataCache.keys()) {\n const parts = key.split(\"__\");\n if (parts.length >= 3) names.add(parts[1]);\n }\n return [...names];\n}\n\nexport function clearMcpToolMetadataCache(): void {\n mcpToolMetadataCache.clear();\n}\n"],"mappings":"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","names":["path","input","text"]}
|
|
@@ -19,18 +19,20 @@ var availableModes = [
|
|
|
19
19
|
name: "Plan Mode",
|
|
20
20
|
description: "Planning mode, no actual tool execution"
|
|
21
21
|
}
|
|
22
|
-
// {
|
|
23
|
-
// id: "dontAsk",
|
|
24
|
-
// name: "Don't Ask",
|
|
25
|
-
// description: "Don't prompt for permissions, deny if not pre-approved",
|
|
26
|
-
// },
|
|
27
22
|
];
|
|
28
23
|
if (ALLOW_BYPASS) {
|
|
29
|
-
availableModes.push(
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
24
|
+
availableModes.push(
|
|
25
|
+
{
|
|
26
|
+
id: "bypassPermissions",
|
|
27
|
+
name: "Bypass Permissions",
|
|
28
|
+
description: "Auto-accept all permission requests"
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
id: "auto",
|
|
32
|
+
name: "Auto Mode",
|
|
33
|
+
description: "Use a model classifier to approve/deny permission prompts"
|
|
34
|
+
}
|
|
35
|
+
);
|
|
34
36
|
}
|
|
35
37
|
var codexModes = [
|
|
36
38
|
{
|
|
@@ -79,10 +81,10 @@ var BASE_ALLOWED_TOOLS = [
|
|
|
79
81
|
...AGENT_TOOLS
|
|
80
82
|
];
|
|
81
83
|
var AUTO_ALLOWED_TOOLS = {
|
|
84
|
+
auto: new Set(BASE_ALLOWED_TOOLS),
|
|
82
85
|
default: new Set(BASE_ALLOWED_TOOLS),
|
|
83
86
|
acceptEdits: /* @__PURE__ */ new Set([...BASE_ALLOWED_TOOLS, ...WRITE_TOOLS]),
|
|
84
87
|
plan: new Set(BASE_ALLOWED_TOOLS)
|
|
85
|
-
// dontAsk: new Set(BASE_ALLOWED_TOOLS),
|
|
86
88
|
};
|
|
87
89
|
|
|
88
90
|
// src/adapters/claude/permissions/permission-options.ts
|
|
@@ -158,6 +160,11 @@ function buildExitPlanModePermissionOptions() {
|
|
|
158
160
|
});
|
|
159
161
|
}
|
|
160
162
|
options.push(
|
|
163
|
+
{
|
|
164
|
+
kind: "allow_always",
|
|
165
|
+
name: 'Yes, and use "auto" mode',
|
|
166
|
+
optionId: "auto"
|
|
167
|
+
},
|
|
161
168
|
{
|
|
162
169
|
kind: "allow_always",
|
|
163
170
|
name: "Yes, and auto-accept edits",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/utils/common.ts","../../../../src/execution-mode.ts","../../../../src/adapters/claude/tools.ts","../../../../src/adapters/claude/permissions/permission-options.ts"],"sourcesContent":["import type { Logger } from \"./logger\";\n\n/**\n * Races an operation against a timeout.\n * Returns success with the value if the operation completes in time,\n * or timeout if the operation takes longer than the specified duration.\n */\nexport async function withTimeout<T>(\n operation: Promise<T>,\n timeoutMs: number,\n): Promise<{ result: \"success\"; value: T } | { result: \"timeout\" }> {\n const timeoutPromise = new Promise<{ result: \"timeout\" }>((resolve) =>\n setTimeout(() => resolve({ result: \"timeout\" }), timeoutMs),\n );\n const operationPromise = operation.then((value) => ({\n result: \"success\" as const,\n value,\n }));\n return Promise.race([operationPromise, timeoutPromise]);\n}\n\nexport const IS_ROOT =\n typeof process !== \"undefined\" &&\n (process.geteuid?.() ?? process.getuid?.()) === 0;\n\nexport function unreachable(value: never, logger: Logger): void {\n let valueAsString: string;\n try {\n valueAsString = JSON.stringify(value);\n } catch {\n valueAsString = String(value);\n }\n logger.error(`Unexpected case: ${valueAsString}`);\n}\n","import { IS_ROOT } from \"./utils/common\";\n\nexport interface ModeInfo {\n id: string;\n name: string;\n description: string;\n}\n\n// Helper constant that can easily be toggled for env/feature flag/etc\nconst ALLOW_BYPASS = !IS_ROOT;\n\nconst availableModes: ModeInfo[] = [\n {\n id: \"default\",\n name: \"Default\",\n description: \"Standard behavior, prompts for dangerous operations\",\n },\n {\n id: \"acceptEdits\",\n name: \"Accept Edits\",\n description: \"Auto-accept file edit operations\",\n },\n {\n id: \"plan\",\n name: \"Plan Mode\",\n description: \"Planning mode, no actual tool execution\",\n },\n // {\n // id: \"dontAsk\",\n // name: \"Don't Ask\",\n // description: \"Don't prompt for permissions, deny if not pre-approved\",\n // },\n];\n\nif (ALLOW_BYPASS) {\n availableModes.push({\n id: \"bypassPermissions\",\n name: \"Auto-accept Permissions\",\n description: \"Auto-accept all permission requests\",\n });\n}\n\n// Expose execution mode IDs in type-safe order for type checks\nexport const CODE_EXECUTION_MODES = [\n \"default\",\n \"acceptEdits\",\n \"plan\",\n // \"dontAsk\",\n \"bypassPermissions\",\n] as const;\n\nexport type CodeExecutionMode = (typeof CODE_EXECUTION_MODES)[number];\n\nexport function isCodeExecutionMode(mode: string): mode is CodeExecutionMode {\n return (CODE_EXECUTION_MODES as readonly string[]).includes(mode);\n}\n\nexport function getAvailableModes(): ModeInfo[] {\n return IS_ROOT\n ? availableModes.filter((m) => m.id !== \"bypassPermissions\")\n : availableModes;\n}\n\n// --- Codex-native modes ---\n\nexport const CODEX_NATIVE_MODES = [\"auto\", \"read-only\", \"full-access\"] as const;\n\nexport type CodexNativeMode = (typeof CODEX_NATIVE_MODES)[number];\n\n/** Union of all permission mode IDs across adapters */\nexport type PermissionMode = CodeExecutionMode | CodexNativeMode;\n\nexport function isCodexNativeMode(mode: string): mode is CodexNativeMode {\n return (CODEX_NATIVE_MODES as readonly string[]).includes(mode);\n}\n\nconst codexModes: ModeInfo[] = [\n {\n id: \"read-only\",\n name: \"Read Only\",\n description: \"Read-only access, no file modifications\",\n },\n {\n id: \"auto\",\n name: \"Auto\",\n description: \"Standard behavior, prompts for dangerous operations\",\n },\n];\n\nif (ALLOW_BYPASS) {\n codexModes.push({\n id: \"full-access\",\n name: \"Full Access\",\n description: \"Auto-accept all permission requests\",\n });\n}\n\nexport function getAvailableCodexModes(): ModeInfo[] {\n return IS_ROOT\n ? codexModes.filter((m) => m.id !== \"full-access\")\n : codexModes;\n}\n","export {\n CODE_EXECUTION_MODES,\n type CodeExecutionMode,\n getAvailableModes,\n type ModeInfo,\n} from \"../../execution-mode\";\n\nimport type { CodeExecutionMode } from \"../../execution-mode\";\nimport { isMcpToolReadOnly } from \"./mcp/tool-metadata\";\n\nexport const READ_TOOLS: Set<string> = new Set([\"Read\", \"NotebookRead\"]);\n\nexport const WRITE_TOOLS: Set<string> = new Set([\n \"Edit\",\n \"Write\",\n \"NotebookEdit\",\n]);\n\nexport const BASH_TOOLS: Set<string> = new Set([\n \"Bash\",\n \"BashOutput\",\n \"KillShell\",\n]);\n\nexport const SEARCH_TOOLS: Set<string> = new Set([\"Glob\", \"Grep\", \"LS\"]);\n\nexport const WEB_TOOLS: Set<string> = new Set([\"WebSearch\", \"WebFetch\"]);\n\nexport const AGENT_TOOLS: Set<string> = new Set([\n \"Task\",\n \"Agent\",\n \"TodoWrite\",\n \"Skill\",\n]);\n\nconst BASE_ALLOWED_TOOLS = [\n ...READ_TOOLS,\n ...SEARCH_TOOLS,\n ...WEB_TOOLS,\n ...AGENT_TOOLS,\n];\n\nconst AUTO_ALLOWED_TOOLS: Record<string, Set<string>> = {\n default: new Set(BASE_ALLOWED_TOOLS),\n acceptEdits: new Set([...BASE_ALLOWED_TOOLS, ...WRITE_TOOLS]),\n plan: new Set(BASE_ALLOWED_TOOLS),\n // dontAsk: new Set(BASE_ALLOWED_TOOLS),\n};\n\nexport function isToolAllowedForMode(\n toolName: string,\n mode: CodeExecutionMode,\n): boolean {\n if (mode === \"bypassPermissions\") {\n return true;\n }\n if (AUTO_ALLOWED_TOOLS[mode]?.has(toolName) === true) {\n return true;\n }\n if (isMcpToolReadOnly(toolName)) {\n return true;\n }\n return false;\n}\n","import type { PermissionUpdate } from \"@anthropic-ai/claude-agent-sdk\";\nimport { IS_ROOT } from \"../../../utils/common\";\nimport { BASH_TOOLS, READ_TOOLS, SEARCH_TOOLS, WRITE_TOOLS } from \"../tools\";\n\nexport interface PermissionOption {\n kind: \"allow_once\" | \"allow_always\" | \"reject_once\" | \"reject_always\";\n name: string;\n optionId: string;\n _meta?: { description?: string; customInput?: boolean };\n}\n\nfunction permissionOptions(allowAlwaysLabel: string): PermissionOption[] {\n return [\n { kind: \"allow_once\", name: \"Yes\", optionId: \"allow\" },\n { kind: \"allow_always\", name: allowAlwaysLabel, optionId: \"allow_always\" },\n {\n kind: \"reject_once\",\n name: \"No, and tell the agent what to do differently\",\n optionId: \"reject\",\n _meta: { customInput: true },\n },\n ];\n}\n\nexport function buildPermissionOptions(\n toolName: string,\n toolInput: Record<string, unknown>,\n cwd?: string,\n suggestions?: PermissionUpdate[],\n): PermissionOption[] {\n if (BASH_TOOLS.has(toolName)) {\n const rawRuleContent = suggestions\n ?.flatMap((s) => (\"rules\" in s ? s.rules : []))\n .find((r) => r.toolName === \"Bash\" && r.ruleContent)?.ruleContent;\n const ruleContent = rawRuleContent?.replace(/:?\\*$/, \"\");\n\n const command = toolInput?.command as string | undefined;\n const cmdName = command?.split(/\\s+/)[0] ?? \"this command\";\n const cwdLabel = cwd ? ` in ${cwd}` : \"\";\n const label = ruleContent ?? `\\`${cmdName}\\` commands`;\n\n return permissionOptions(\n `Yes, and don't ask again for ${label}${cwdLabel}`,\n );\n }\n\n if (toolName === \"BashOutput\") {\n return permissionOptions(\"Yes, allow all background process reads\");\n }\n\n if (toolName === \"KillShell\") {\n return permissionOptions(\"Yes, allow killing processes\");\n }\n\n if (WRITE_TOOLS.has(toolName)) {\n return permissionOptions(\"Yes, allow all edits during this session\");\n }\n\n if (READ_TOOLS.has(toolName)) {\n return permissionOptions(\"Yes, allow all reads during this session\");\n }\n\n if (SEARCH_TOOLS.has(toolName)) {\n return permissionOptions(\"Yes, allow all searches during this session\");\n }\n\n if (toolName === \"WebFetch\") {\n const url = toolInput?.url as string | undefined;\n let domain = \"\";\n try {\n domain = url ? new URL(url).hostname : \"\";\n } catch {}\n return permissionOptions(\n domain\n ? `Yes, allow all fetches from ${domain}`\n : \"Yes, allow all fetches\",\n );\n }\n\n if (toolName === \"WebSearch\") {\n return permissionOptions(\"Yes, allow all web searches\");\n }\n\n if (toolName === \"Task\") {\n return permissionOptions(\"Yes, allow all sub-tasks\");\n }\n\n if (toolName === \"TodoWrite\") {\n return permissionOptions(\"Yes, allow all todo updates\");\n }\n\n return permissionOptions(\"Yes, always allow\");\n}\n\nconst ALLOW_BYPASS = !IS_ROOT || !!process.env.IS_SANDBOX;\n\nexport function buildExitPlanModePermissionOptions(): PermissionOption[] {\n const options: PermissionOption[] = [];\n\n if (ALLOW_BYPASS) {\n options.push({\n kind: \"allow_always\",\n name: \"Yes, bypass all permissions\",\n optionId: \"bypassPermissions\",\n });\n }\n\n options.push(\n {\n kind: \"allow_always\",\n name: \"Yes, and auto-accept edits\",\n optionId: \"acceptEdits\",\n },\n {\n kind: \"allow_once\",\n name: \"Yes, and manually approve edits\",\n optionId: \"default\",\n },\n {\n kind: \"reject_once\",\n name: \"No, and tell the agent what to do differently\",\n optionId: \"reject_with_feedback\",\n _meta: { customInput: true },\n },\n );\n\n return options;\n}\n"],"mappings":"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","names":["ALLOW_BYPASS"]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/utils/common.ts","../../../../src/execution-mode.ts","../../../../src/adapters/claude/tools.ts","../../../../src/adapters/claude/permissions/permission-options.ts"],"sourcesContent":["import type { Logger } from \"./logger\";\n\n/**\n * Races an operation against a timeout.\n * Returns success with the value if the operation completes in time,\n * or timeout if the operation takes longer than the specified duration.\n */\nexport async function withTimeout<T>(\n operation: Promise<T>,\n timeoutMs: number,\n): Promise<{ result: \"success\"; value: T } | { result: \"timeout\" }> {\n const timeoutPromise = new Promise<{ result: \"timeout\" }>((resolve) =>\n setTimeout(() => resolve({ result: \"timeout\" }), timeoutMs),\n );\n const operationPromise = operation.then((value) => ({\n result: \"success\" as const,\n value,\n }));\n return Promise.race([operationPromise, timeoutPromise]);\n}\n\nexport const IS_ROOT =\n typeof process !== \"undefined\" &&\n (process.geteuid?.() ?? process.getuid?.()) === 0;\n\nexport function unreachable(value: never, logger: Logger): void {\n let valueAsString: string;\n try {\n valueAsString = JSON.stringify(value);\n } catch {\n valueAsString = String(value);\n }\n logger.error(`Unexpected case: ${valueAsString}`);\n}\n","import { IS_ROOT } from \"./utils/common\";\n\nexport interface ModeInfo {\n id: string;\n name: string;\n description: string;\n}\n\n// Helper constant that can easily be toggled for env/feature flag/etc\nconst ALLOW_BYPASS = !IS_ROOT;\n\nconst availableModes: ModeInfo[] = [\n {\n id: \"default\",\n name: \"Default\",\n description: \"Standard behavior, prompts for dangerous operations\",\n },\n {\n id: \"acceptEdits\",\n name: \"Accept Edits\",\n description: \"Auto-accept file edit operations\",\n },\n {\n id: \"plan\",\n name: \"Plan Mode\",\n description: \"Planning mode, no actual tool execution\",\n },\n];\n\nif (ALLOW_BYPASS) {\n availableModes.push(\n {\n id: \"bypassPermissions\",\n name: \"Bypass Permissions\",\n description: \"Auto-accept all permission requests\",\n },\n {\n id: \"auto\",\n name: \"Auto Mode\",\n description: \"Use a model classifier to approve/deny permission prompts\",\n },\n );\n}\n\n// Expose execution mode IDs in type-safe order for type checks\nexport const CODE_EXECUTION_MODES = [\n \"default\",\n \"acceptEdits\",\n \"plan\",\n \"bypassPermissions\",\n \"auto\",\n] as const;\n\nexport type CodeExecutionMode = (typeof CODE_EXECUTION_MODES)[number];\n\nexport function isCodeExecutionMode(mode: string): mode is CodeExecutionMode {\n return (CODE_EXECUTION_MODES as readonly string[]).includes(mode);\n}\n\nexport function getAvailableModes(): ModeInfo[] {\n return IS_ROOT\n ? availableModes.filter((m) => m.id !== \"bypassPermissions\")\n : availableModes;\n}\n\n// --- Codex-native modes ---\n\nexport const CODEX_NATIVE_MODES = [\"auto\", \"read-only\", \"full-access\"] as const;\n\nexport type CodexNativeMode = (typeof CODEX_NATIVE_MODES)[number];\n\n/** Union of all permission mode IDs across adapters */\nexport type PermissionMode = CodeExecutionMode | CodexNativeMode;\n\nexport function isCodexNativeMode(mode: string): mode is CodexNativeMode {\n return (CODEX_NATIVE_MODES as readonly string[]).includes(mode);\n}\n\nconst codexModes: ModeInfo[] = [\n {\n id: \"read-only\",\n name: \"Read Only\",\n description: \"Read-only access, no file modifications\",\n },\n {\n id: \"auto\",\n name: \"Auto\",\n description: \"Standard behavior, prompts for dangerous operations\",\n },\n];\n\nif (ALLOW_BYPASS) {\n codexModes.push({\n id: \"full-access\",\n name: \"Full Access\",\n description: \"Auto-accept all permission requests\",\n });\n}\n\nexport function getAvailableCodexModes(): ModeInfo[] {\n return IS_ROOT\n ? codexModes.filter((m) => m.id !== \"full-access\")\n : codexModes;\n}\n","export {\n CODE_EXECUTION_MODES,\n type CodeExecutionMode,\n getAvailableModes,\n type ModeInfo,\n} from \"../../execution-mode\";\n\nimport type { CodeExecutionMode } from \"../../execution-mode\";\nimport { isMcpToolReadOnly } from \"./mcp/tool-metadata\";\n\nexport const READ_TOOLS: Set<string> = new Set([\"Read\", \"NotebookRead\"]);\n\nexport const WRITE_TOOLS: Set<string> = new Set([\n \"Edit\",\n \"Write\",\n \"NotebookEdit\",\n]);\n\nexport const BASH_TOOLS: Set<string> = new Set([\n \"Bash\",\n \"BashOutput\",\n \"KillShell\",\n]);\n\nexport const SEARCH_TOOLS: Set<string> = new Set([\"Glob\", \"Grep\", \"LS\"]);\n\nexport const WEB_TOOLS: Set<string> = new Set([\"WebSearch\", \"WebFetch\"]);\n\nexport const AGENT_TOOLS: Set<string> = new Set([\n \"Task\",\n \"Agent\",\n \"TodoWrite\",\n \"Skill\",\n]);\n\nconst BASE_ALLOWED_TOOLS = [\n ...READ_TOOLS,\n ...SEARCH_TOOLS,\n ...WEB_TOOLS,\n ...AGENT_TOOLS,\n];\n\nconst AUTO_ALLOWED_TOOLS: Record<string, Set<string>> = {\n auto: new Set(BASE_ALLOWED_TOOLS),\n default: new Set(BASE_ALLOWED_TOOLS),\n acceptEdits: new Set([...BASE_ALLOWED_TOOLS, ...WRITE_TOOLS]),\n plan: new Set(BASE_ALLOWED_TOOLS),\n};\n\nexport function isToolAllowedForMode(\n toolName: string,\n mode: CodeExecutionMode,\n): boolean {\n if (mode === \"bypassPermissions\") {\n return true;\n }\n if (AUTO_ALLOWED_TOOLS[mode]?.has(toolName) === true) {\n return true;\n }\n if (isMcpToolReadOnly(toolName)) {\n return true;\n }\n return false;\n}\n","import type { PermissionUpdate } from \"@anthropic-ai/claude-agent-sdk\";\nimport { IS_ROOT } from \"../../../utils/common\";\nimport { BASH_TOOLS, READ_TOOLS, SEARCH_TOOLS, WRITE_TOOLS } from \"../tools\";\n\nexport interface PermissionOption {\n kind: \"allow_once\" | \"allow_always\" | \"reject_once\" | \"reject_always\";\n name: string;\n optionId: string;\n _meta?: { description?: string; customInput?: boolean };\n}\n\nfunction permissionOptions(allowAlwaysLabel: string): PermissionOption[] {\n return [\n { kind: \"allow_once\", name: \"Yes\", optionId: \"allow\" },\n { kind: \"allow_always\", name: allowAlwaysLabel, optionId: \"allow_always\" },\n {\n kind: \"reject_once\",\n name: \"No, and tell the agent what to do differently\",\n optionId: \"reject\",\n _meta: { customInput: true },\n },\n ];\n}\n\nexport function buildPermissionOptions(\n toolName: string,\n toolInput: Record<string, unknown>,\n cwd?: string,\n suggestions?: PermissionUpdate[],\n): PermissionOption[] {\n if (BASH_TOOLS.has(toolName)) {\n const rawRuleContent = suggestions\n ?.flatMap((s) => (\"rules\" in s ? s.rules : []))\n .find((r) => r.toolName === \"Bash\" && r.ruleContent)?.ruleContent;\n const ruleContent = rawRuleContent?.replace(/:?\\*$/, \"\");\n\n const command = toolInput?.command as string | undefined;\n const cmdName = command?.split(/\\s+/)[0] ?? \"this command\";\n const cwdLabel = cwd ? ` in ${cwd}` : \"\";\n const label = ruleContent ?? `\\`${cmdName}\\` commands`;\n\n return permissionOptions(\n `Yes, and don't ask again for ${label}${cwdLabel}`,\n );\n }\n\n if (toolName === \"BashOutput\") {\n return permissionOptions(\"Yes, allow all background process reads\");\n }\n\n if (toolName === \"KillShell\") {\n return permissionOptions(\"Yes, allow killing processes\");\n }\n\n if (WRITE_TOOLS.has(toolName)) {\n return permissionOptions(\"Yes, allow all edits during this session\");\n }\n\n if (READ_TOOLS.has(toolName)) {\n return permissionOptions(\"Yes, allow all reads during this session\");\n }\n\n if (SEARCH_TOOLS.has(toolName)) {\n return permissionOptions(\"Yes, allow all searches during this session\");\n }\n\n if (toolName === \"WebFetch\") {\n const url = toolInput?.url as string | undefined;\n let domain = \"\";\n try {\n domain = url ? new URL(url).hostname : \"\";\n } catch {}\n return permissionOptions(\n domain\n ? `Yes, allow all fetches from ${domain}`\n : \"Yes, allow all fetches\",\n );\n }\n\n if (toolName === \"WebSearch\") {\n return permissionOptions(\"Yes, allow all web searches\");\n }\n\n if (toolName === \"Task\") {\n return permissionOptions(\"Yes, allow all sub-tasks\");\n }\n\n if (toolName === \"TodoWrite\") {\n return permissionOptions(\"Yes, allow all todo updates\");\n }\n\n return permissionOptions(\"Yes, always allow\");\n}\n\nconst ALLOW_BYPASS = !IS_ROOT || !!process.env.IS_SANDBOX;\n\nexport function buildExitPlanModePermissionOptions(): PermissionOption[] {\n const options: PermissionOption[] = [];\n\n if (ALLOW_BYPASS) {\n options.push({\n kind: \"allow_always\",\n name: \"Yes, bypass all permissions\",\n optionId: \"bypassPermissions\",\n });\n }\n\n options.push(\n {\n kind: \"allow_always\",\n name: 'Yes, and use \"auto\" mode',\n optionId: \"auto\",\n },\n {\n kind: \"allow_always\",\n name: \"Yes, and auto-accept edits\",\n optionId: \"acceptEdits\",\n },\n {\n kind: \"allow_once\",\n name: \"Yes, and manually approve edits\",\n optionId: \"default\",\n },\n {\n kind: \"reject_once\",\n name: \"No, and tell the agent what to do differently\",\n optionId: \"reject_with_feedback\",\n _meta: { customInput: true },\n },\n );\n\n return options;\n}\n"],"mappings":"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","names":["ALLOW_BYPASS"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/adapters/claude/session/jsonl-hydration.ts","../../../../src/adapters/claude/session/models.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport * as fs from \"node:fs/promises\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport type { ContentBlock } from \"@agentclientprotocol/sdk\";\nimport type { PostHogAPIClient } from \"../../../posthog-api\";\nimport type { StoredEntry } from \"../../../types\";\nimport { supports1MContext } from \"./models\";\n\ninterface ConversationTurn {\n role: \"user\" | \"assistant\";\n content: ContentBlock[];\n toolCalls?: ToolCallInfo[];\n}\n\ninterface ToolCallInfo {\n toolCallId: string;\n toolName: string;\n input: unknown;\n result?: unknown;\n}\n\ninterface JsonlConfig {\n sessionId: string;\n cwd: string;\n model?: string;\n version?: string;\n gitBranch?: string;\n slug?: string;\n permissionMode?: string;\n}\n\ninterface ClaudeCodeMeta {\n toolCallId?: string;\n toolName?: string;\n toolInput?: unknown;\n toolResponse?: unknown;\n}\n\ninterface SessionUpdate {\n sessionUpdate: string;\n content?: ContentBlock | ContentBlock[];\n _meta?: { claudeCode?: ClaudeCodeMeta };\n}\n\nconst MAX_PROJECT_KEY_LENGTH = 200;\n\nfunction hashString(s: string): string {\n let hash = 0;\n for (let i = 0; i < s.length; i++) {\n hash = (hash << 5) - hash + s.charCodeAt(i);\n hash |= 0;\n }\n return Math.abs(hash).toString(36);\n}\n\nexport function getSessionJsonlPath(sessionId: string, cwd: string): string {\n const configDir =\n process.env.CLAUDE_CONFIG_DIR || path.join(os.homedir(), \".claude\");\n let projectKey = cwd.replace(/[^a-zA-Z0-9]/g, \"-\");\n if (projectKey.length > MAX_PROJECT_KEY_LENGTH) {\n projectKey = `${projectKey.slice(0, MAX_PROJECT_KEY_LENGTH)}-${hashString(cwd)}`;\n }\n return path.join(configDir, \"projects\", projectKey, `${sessionId}.jsonl`);\n}\n\nexport function rebuildConversation(\n entries: StoredEntry[],\n): ConversationTurn[] {\n const turns: ConversationTurn[] = [];\n let currentAssistantContent: ContentBlock[] = [];\n let currentToolCalls: ToolCallInfo[] = [];\n\n for (const entry of entries) {\n const method = entry.notification?.method;\n const params = entry.notification?.params as Record<string, unknown>;\n\n if (method === \"session/update\" && params?.update) {\n const update = params.update as SessionUpdate;\n\n switch (update.sessionUpdate) {\n case \"user_message\":\n case \"user_message_chunk\": {\n if (\n currentAssistantContent.length > 0 ||\n currentToolCalls.length > 0\n ) {\n turns.push({\n role: \"assistant\",\n content: currentAssistantContent,\n toolCalls:\n currentToolCalls.length > 0 ? currentToolCalls : undefined,\n });\n currentAssistantContent = [];\n currentToolCalls = [];\n }\n\n const content = update.content;\n const contentArray = Array.isArray(content)\n ? content\n : content\n ? [content]\n : [];\n\n const lastTurn = turns[turns.length - 1];\n if (lastTurn?.role === \"user\") {\n lastTurn.content.push(...contentArray);\n } else {\n turns.push({ role: \"user\", content: contentArray });\n }\n break;\n }\n\n case \"agent_message\":\n case \"agent_message_chunk\":\n case \"agent_thought_chunk\": {\n const content = update.content;\n if (content && !Array.isArray(content)) {\n if (\n content.type === \"text\" &&\n currentAssistantContent.length > 0 &&\n currentAssistantContent[currentAssistantContent.length - 1]\n .type === \"text\"\n ) {\n const lastBlock = currentAssistantContent[\n currentAssistantContent.length - 1\n ] as { type: \"text\"; text: string };\n lastBlock.text += (\n content as { type: \"text\"; text: string }\n ).text;\n } else {\n currentAssistantContent.push(content);\n }\n }\n break;\n }\n\n case \"tool_call\":\n case \"tool_call_update\": {\n const meta = update._meta?.claudeCode;\n if (meta) {\n const { toolCallId, toolName, toolInput, toolResponse } = meta;\n\n if (toolCallId && toolName) {\n let toolCall = currentToolCalls.find(\n (tc) => tc.toolCallId === toolCallId,\n );\n if (!toolCall) {\n toolCall = { toolCallId, toolName, input: toolInput };\n currentToolCalls.push(toolCall);\n }\n if (toolResponse !== undefined) {\n toolCall.result = toolResponse;\n }\n }\n }\n break;\n }\n\n case \"tool_result\": {\n const meta = update._meta?.claudeCode;\n if (meta) {\n const { toolCallId, toolResponse } = meta;\n if (toolCallId) {\n const toolCall = currentToolCalls.find(\n (tc) => tc.toolCallId === toolCallId,\n );\n if (toolCall && toolResponse !== undefined) {\n toolCall.result = toolResponse;\n }\n }\n }\n break;\n }\n }\n }\n }\n\n if (currentAssistantContent.length > 0 || currentToolCalls.length > 0) {\n turns.push({\n role: \"assistant\",\n content: currentAssistantContent,\n toolCalls: currentToolCalls.length > 0 ? currentToolCalls : undefined,\n });\n }\n\n return turns;\n}\n\nconst CHARS_PER_TOKEN = 4;\nconst DEFAULT_MAX_TOKENS = 150_000;\nconst LARGE_CONTEXT_MAX_TOKENS = 800_000;\n\nfunction estimateTurnTokens(turn: ConversationTurn): number {\n let chars = 0;\n for (const block of turn.content) {\n if (\"text\" in block && typeof block.text === \"string\") {\n chars += block.text.length;\n }\n }\n if (turn.toolCalls) {\n for (const tc of turn.toolCalls) {\n chars += JSON.stringify(tc.input ?? \"\").length;\n if (tc.result !== undefined) {\n chars +=\n typeof tc.result === \"string\"\n ? tc.result.length\n : JSON.stringify(tc.result).length;\n }\n }\n }\n return Math.ceil(chars / CHARS_PER_TOKEN);\n}\n\nexport function selectRecentTurns(\n turns: ConversationTurn[],\n maxTokens = DEFAULT_MAX_TOKENS,\n): ConversationTurn[] {\n let budget = maxTokens;\n let startIndex = turns.length;\n\n for (let i = turns.length - 1; i >= 0; i--) {\n const cost = estimateTurnTokens(turns[i]);\n if (cost > budget) break;\n budget -= cost;\n startIndex = i;\n }\n\n // Ensure we start on a user turn so the conversation is well-formed\n while (startIndex < turns.length && turns[startIndex].role !== \"user\") {\n startIndex++;\n }\n\n return turns.slice(startIndex);\n}\n\nconst BASE62 = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\";\n\nfunction generateMessageId(): string {\n const bytes = new Uint8Array(24);\n crypto.getRandomValues(bytes);\n let id = \"msg_01\";\n for (const b of bytes) {\n id += BASE62[b % 62];\n }\n return id;\n}\n\nconst ADJECTIVES = [\n \"bright\",\n \"calm\",\n \"daring\",\n \"eager\",\n \"fair\",\n \"gentle\",\n \"happy\",\n \"keen\",\n \"lively\",\n \"merry\",\n \"noble\",\n \"polite\",\n \"quick\",\n \"sharp\",\n \"warm\",\n \"witty\",\n];\nconst VERBS = [\n \"blazing\",\n \"crafting\",\n \"dashing\",\n \"flowing\",\n \"gliding\",\n \"humming\",\n \"jumping\",\n \"linking\",\n \"melting\",\n \"nesting\",\n \"pacing\",\n \"roaming\",\n \"sailing\",\n \"turning\",\n \"waving\",\n \"zoning\",\n];\nconst NOUNS = [\n \"aurora\",\n \"breeze\",\n \"cedar\",\n \"delta\",\n \"ember\",\n \"frost\",\n \"grove\",\n \"haven\",\n \"inlet\",\n \"jewel\",\n \"knoll\",\n \"lotus\",\n \"maple\",\n \"nexus\",\n \"oasis\",\n \"prism\",\n];\n\nfunction generateSlug(): string {\n const pick = (arr: string[]) => arr[Math.floor(Math.random() * arr.length)];\n return `${pick(ADJECTIVES)}-${pick(VERBS)}-${pick(NOUNS)}`;\n}\n\nexport function conversationTurnsToJsonlEntries(\n turns: ConversationTurn[],\n config: JsonlConfig,\n): string[] {\n const lines: string[] = [];\n let parentUuid: string | null = null;\n const model = config.model ?? \"claude-opus-4-6\";\n const version = config.version ?? \"2.1.63\";\n const gitBranch = config.gitBranch ?? \"\";\n const slug = config.slug ?? generateSlug();\n const permissionMode = config.permissionMode ?? \"default\";\n const baseTime = Date.now() - turns.length * 3000;\n let turnIndex = 0;\n\n for (const turn of turns) {\n const timestamp = new Date(baseTime + turnIndex * 3000).toISOString();\n turnIndex++;\n if (turn.role === \"user\") {\n lines.push(\n JSON.stringify({\n type: \"queue-operation\",\n operation: \"enqueue\",\n timestamp,\n sessionId: config.sessionId,\n }),\n );\n lines.push(\n JSON.stringify({\n type: \"queue-operation\",\n operation: \"dequeue\",\n timestamp,\n sessionId: config.sessionId,\n }),\n );\n\n const uuid = randomUUID();\n const textParts = turn.content\n .filter(\n (block) =>\n \"text\" in block && typeof block.text === \"string\" && block.text,\n )\n .map((block) => (block as { text: string }).text);\n\n const userText = textParts.length > 0 ? textParts.join(\"\") : \" \";\n\n lines.push(\n JSON.stringify({\n parentUuid,\n isSidechain: false,\n userType: \"external\",\n cwd: config.cwd,\n sessionId: config.sessionId,\n version,\n gitBranch,\n slug,\n type: \"user\",\n message: {\n role: \"user\",\n content: [{ type: \"text\", text: userText }],\n },\n uuid,\n timestamp,\n permissionMode,\n }),\n );\n parentUuid = uuid;\n } else {\n const allBlocks: unknown[] = [];\n\n for (const block of turn.content) {\n const blockType = (block as { type: string }).type;\n if (blockType === \"thinking\" || blockType === \"text\") {\n allBlocks.push(block);\n }\n }\n\n if (turn.toolCalls) {\n for (const tc of turn.toolCalls) {\n allBlocks.push({\n type: \"tool_use\",\n id: tc.toolCallId,\n name: tc.toolName,\n input: tc.input,\n });\n }\n }\n\n const msgId = generateMessageId();\n const hasToolUse = allBlocks.some(\n (b) => (b as { type: string }).type === \"tool_use\",\n );\n const lastStopReason = hasToolUse ? \"tool_use\" : \"end_turn\";\n\n for (let i = 0; i < allBlocks.length; i++) {\n const block = allBlocks[i];\n const isLast = i === allBlocks.length - 1;\n const uuid = randomUUID();\n\n lines.push(\n JSON.stringify({\n parentUuid,\n isSidechain: false,\n userType: \"external\",\n cwd: config.cwd,\n sessionId: config.sessionId,\n version,\n gitBranch,\n slug,\n type: \"assistant\",\n message: {\n model,\n id: msgId,\n type: \"message\",\n role: \"assistant\",\n content: [block],\n stop_reason: isLast ? lastStopReason : null,\n stop_sequence: null,\n usage: {\n input_tokens: 0,\n cache_creation_input_tokens: 0,\n cache_read_input_tokens: 0,\n output_tokens: 0,\n },\n },\n uuid,\n timestamp,\n }),\n );\n parentUuid = uuid;\n }\n\n if (turn.toolCalls) {\n for (const tc of turn.toolCalls) {\n if (tc.result === undefined) continue;\n\n const uuid = randomUUID();\n const resultText =\n typeof tc.result === \"string\"\n ? tc.result\n : JSON.stringify(tc.result);\n\n lines.push(\n JSON.stringify({\n parentUuid,\n isSidechain: false,\n userType: \"external\",\n cwd: config.cwd,\n sessionId: config.sessionId,\n version,\n gitBranch,\n slug,\n type: \"user\",\n message: {\n role: \"user\",\n content: [\n {\n type: \"tool_result\",\n tool_use_id: tc.toolCallId,\n content: resultText,\n },\n ],\n },\n uuid,\n timestamp,\n }),\n );\n parentUuid = uuid;\n }\n }\n }\n }\n\n return lines;\n}\n\ninterface HydrationLog {\n info: (msg: string, data?: unknown) => void;\n warn: (msg: string, data?: unknown) => void;\n}\n\nexport async function hydrateSessionJsonl(params: {\n sessionId: string;\n cwd: string;\n taskId: string;\n runId: string;\n model?: string;\n gitBranch?: string;\n permissionMode?: string;\n posthogAPI: PostHogAPIClient;\n log: HydrationLog;\n}): Promise<boolean> {\n const { posthogAPI, log } = params;\n\n try {\n const jsonlPath = getSessionJsonlPath(params.sessionId, params.cwd);\n try {\n await fs.access(jsonlPath);\n return true;\n } catch {\n // File doesn't exist, proceed with hydration\n }\n\n const taskRun = await posthogAPI.getTaskRun(params.taskId, params.runId);\n if (!taskRun.log_url) {\n log.info(\"No log URL, skipping JSONL hydration\");\n return false;\n }\n\n const entries = await posthogAPI.fetchTaskRunLogs(taskRun);\n if (entries.length === 0) {\n log.info(\"No S3 log entries, skipping JSONL hydration\");\n return false;\n }\n\n const entryCounts: Record<string, number> = {};\n for (const entry of entries) {\n const method = entry.notification?.method ?? \"unknown\";\n const entryParams = entry.notification?.params as\n | Record<string, unknown>\n | undefined;\n const update = entryParams?.update as\n | { sessionUpdate?: string }\n | undefined;\n const key = update?.sessionUpdate\n ? `${method}:${update.sessionUpdate}`\n : method;\n entryCounts[key] = (entryCounts[key] ?? 0) + 1;\n }\n log.info(\"S3 log entry breakdown\", {\n totalEntries: entries.length,\n types: entryCounts,\n });\n\n const allTurns = rebuildConversation(entries);\n if (allTurns.length === 0) {\n log.info(\"No conversation in S3 logs, skipping JSONL hydration\");\n return false;\n }\n\n const maxTokens = supports1MContext(params.model ?? \"\")\n ? LARGE_CONTEXT_MAX_TOKENS\n : DEFAULT_MAX_TOKENS;\n const conversation = selectRecentTurns(allTurns, maxTokens);\n log.info(\"Selected recent turns for hydration\", {\n totalTurns: allTurns.length,\n selectedTurns: conversation.length,\n turnRoles: conversation.map((t) => t.role),\n });\n\n const jsonlLines = conversationTurnsToJsonlEntries(conversation, {\n sessionId: params.sessionId,\n cwd: params.cwd,\n model: params.model,\n gitBranch: params.gitBranch,\n permissionMode: params.permissionMode,\n });\n\n await fs.mkdir(path.dirname(jsonlPath), { recursive: true });\n\n const tmpPath = `${jsonlPath}.tmp.${Date.now()}`;\n await fs.writeFile(tmpPath, `${jsonlLines.join(\"\\n\")}\\n`);\n await fs.rename(tmpPath, jsonlPath);\n\n log.info(\"Hydrated session JSONL from S3\", {\n sessionId: params.sessionId,\n turns: conversation.length,\n lines: jsonlLines.length,\n });\n return true;\n } catch (err) {\n log.warn(\"Failed to hydrate session JSONL, continuing\", {\n sessionId: params.sessionId,\n error: err instanceof Error ? err.message : String(err),\n });\n return false;\n }\n}\n","export const DEFAULT_MODEL = \"opus\";\n\nconst GATEWAY_TO_SDK_MODEL: Record<string, string> = {\n \"claude-opus-4-5\": \"opus\",\n \"claude-opus-4-6\": \"opus\",\n \"claude-opus-4-7\": \"opus\",\n \"claude-sonnet-4-5\": \"sonnet\",\n \"claude-sonnet-4-6\": \"sonnet\",\n \"claude-haiku-4-5\": \"haiku\",\n};\n\nexport function toSdkModelId(modelId: string): string {\n return GATEWAY_TO_SDK_MODEL[modelId] ?? modelId;\n}\n\nconst MODELS_WITH_1M_CONTEXT = new Set([\n \"claude-opus-4-6\",\n \"claude-opus-4-7\",\n \"claude-sonnet-4-6\",\n]);\n\nexport function supports1MContext(modelId: string): boolean {\n return MODELS_WITH_1M_CONTEXT.has(modelId);\n}\n\nconst MODELS_WITH_EFFORT = new Set([\n \"claude-opus-4-5\",\n \"claude-opus-4-6\",\n \"claude-opus-4-7\",\n \"claude-sonnet-4-6\",\n]);\n\nconst MODELS_WITH_MAX_EFFORT = new Set([\"claude-opus-4-6\", \"claude-opus-4-7\"]);\n\nexport function supportsEffort(modelId: string): boolean {\n return MODELS_WITH_EFFORT.has(modelId);\n}\n\nexport function supportsMaxEffort(modelId: string): boolean {\n return MODELS_WITH_MAX_EFFORT.has(modelId);\n}\n\nconst MODELS_TO_EXCLUDE_MCP_TOOLS = new Set([\"claude-haiku-4-5\"]);\n\nexport function supportsMcpInjection(modelId: string): boolean {\n return !MODELS_TO_EXCLUDE_MCP_TOOLS.has(modelId);\n}\n\ninterface EffortOption {\n value: string;\n name: string;\n}\n\nexport function getEffortOptions(modelId: string): EffortOption[] | null {\n if (!supportsEffort(modelId)) return null;\n\n const options: EffortOption[] = [\n { value: \"low\", name: \"Low\" },\n { value: \"medium\", name: \"Medium\" },\n { value: \"high\", name: \"High\" },\n ];\n\n if (supportsMaxEffort(modelId)) {\n options.push({ value: \"max\", name: \"Max\" });\n }\n\n return options;\n}\n\n// Model alias resolution — lets callers use human-friendly aliases like\n// \"opus\" or \"sonnet\" instead of full model IDs like \"claude-opus-4-6\".\n\nconst MODEL_CONTEXT_HINT_PATTERN = /\\[(\\d+m)\\]$/i;\n\nfunction tokenizeModelPreference(model: string): {\n tokens: string[];\n contextHint?: string;\n} {\n const lower = model.trim().toLowerCase();\n const contextHint = lower\n .match(MODEL_CONTEXT_HINT_PATTERN)?.[1]\n ?.toLowerCase();\n\n const normalized = lower.replace(MODEL_CONTEXT_HINT_PATTERN, \" $1 \");\n const rawTokens = normalized.split(/[^a-z0-9]+/).filter(Boolean);\n const tokens = rawTokens\n .map((token) => {\n if (token === \"opusplan\") return \"opus\";\n if (token === \"best\" || token === \"default\") return \"\";\n return token;\n })\n .filter((token) => token && token !== \"claude\")\n .filter((token) => /[a-z]/.test(token) || token.endsWith(\"m\"));\n\n return { tokens, contextHint };\n}\n\ninterface ModelOption {\n value: string;\n name?: string;\n description?: string;\n}\n\nfunction scoreModelMatch(\n model: ModelOption,\n tokens: string[],\n contextHint?: string,\n): number {\n const haystack = `${model.value} ${model.name ?? \"\"}`.toLowerCase();\n let score = 0;\n for (const token of tokens) {\n if (haystack.includes(token)) {\n score += token === contextHint ? 3 : 1;\n }\n }\n return score;\n}\n\nexport function resolveModelPreference(\n preference: string,\n options: ModelOption[],\n): string | null {\n const trimmed = preference.trim();\n if (!trimmed) return null;\n\n const lower = trimmed.toLowerCase();\n\n // Exact match on value or display name\n const directMatch = options.find(\n (o) =>\n o.value === trimmed ||\n o.value.toLowerCase() === lower ||\n (o.name && o.name.toLowerCase() === lower),\n );\n if (directMatch) return directMatch.value;\n\n // Substring match\n const includesMatch = options.find((o) => {\n const value = o.value.toLowerCase();\n const display = (o.name ?? \"\").toLowerCase();\n return (\n value.includes(lower) || display.includes(lower) || lower.includes(value)\n );\n });\n if (includesMatch) return includesMatch.value;\n\n // Tokenized matching for aliases like \"opus[1m]\"\n const { tokens, contextHint } = tokenizeModelPreference(trimmed);\n if (tokens.length === 0) return null;\n\n let bestMatch: ModelOption | null = null;\n let bestScore = 0;\n for (const model of options) {\n const score = scoreModelMatch(model, tokens, contextHint);\n if (0 < score && (!bestMatch || bestScore < score)) {\n bestMatch = model;\n bestScore = score;\n }\n }\n\n return bestMatch?.value ?? null;\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/adapters/claude/session/jsonl-hydration.ts","../../../../src/adapters/claude/session/models.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport * as fs from \"node:fs/promises\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport type { ContentBlock } from \"@agentclientprotocol/sdk\";\nimport type { PostHogAPIClient } from \"../../../posthog-api\";\nimport type { StoredEntry } from \"../../../types\";\nimport { supports1MContext } from \"./models\";\n\ninterface ConversationTurn {\n role: \"user\" | \"assistant\";\n content: ContentBlock[];\n toolCalls?: ToolCallInfo[];\n}\n\ninterface ToolCallInfo {\n toolCallId: string;\n toolName: string;\n input: unknown;\n result?: unknown;\n}\n\ninterface JsonlConfig {\n sessionId: string;\n cwd: string;\n model?: string;\n version?: string;\n gitBranch?: string;\n slug?: string;\n permissionMode?: string;\n}\n\ninterface ClaudeCodeMeta {\n toolCallId?: string;\n toolName?: string;\n toolInput?: unknown;\n toolResponse?: unknown;\n}\n\ninterface SessionUpdate {\n sessionUpdate: string;\n content?: ContentBlock | ContentBlock[];\n _meta?: { claudeCode?: ClaudeCodeMeta };\n}\n\nconst MAX_PROJECT_KEY_LENGTH = 200;\n\nfunction hashString(s: string): string {\n let hash = 0;\n for (let i = 0; i < s.length; i++) {\n hash = (hash << 5) - hash + s.charCodeAt(i);\n hash |= 0;\n }\n return Math.abs(hash).toString(36);\n}\n\nexport function getSessionJsonlPath(sessionId: string, cwd: string): string {\n const configDir =\n process.env.CLAUDE_CONFIG_DIR || path.join(os.homedir(), \".claude\");\n let projectKey = cwd.replace(/[^a-zA-Z0-9]/g, \"-\");\n if (projectKey.length > MAX_PROJECT_KEY_LENGTH) {\n projectKey = `${projectKey.slice(0, MAX_PROJECT_KEY_LENGTH)}-${hashString(cwd)}`;\n }\n return path.join(configDir, \"projects\", projectKey, `${sessionId}.jsonl`);\n}\n\nexport function rebuildConversation(\n entries: StoredEntry[],\n): ConversationTurn[] {\n const turns: ConversationTurn[] = [];\n let currentAssistantContent: ContentBlock[] = [];\n let currentToolCalls: ToolCallInfo[] = [];\n\n for (const entry of entries) {\n const method = entry.notification?.method;\n const params = entry.notification?.params as Record<string, unknown>;\n\n if (method === \"session/update\" && params?.update) {\n const update = params.update as SessionUpdate;\n\n switch (update.sessionUpdate) {\n case \"user_message\":\n case \"user_message_chunk\": {\n if (\n currentAssistantContent.length > 0 ||\n currentToolCalls.length > 0\n ) {\n turns.push({\n role: \"assistant\",\n content: currentAssistantContent,\n toolCalls:\n currentToolCalls.length > 0 ? currentToolCalls : undefined,\n });\n currentAssistantContent = [];\n currentToolCalls = [];\n }\n\n const content = update.content;\n const contentArray = Array.isArray(content)\n ? content\n : content\n ? [content]\n : [];\n\n const lastTurn = turns[turns.length - 1];\n if (lastTurn?.role === \"user\") {\n lastTurn.content.push(...contentArray);\n } else {\n turns.push({ role: \"user\", content: contentArray });\n }\n break;\n }\n\n case \"agent_message\":\n case \"agent_message_chunk\":\n case \"agent_thought_chunk\": {\n const content = update.content;\n if (content && !Array.isArray(content)) {\n if (\n content.type === \"text\" &&\n currentAssistantContent.length > 0 &&\n currentAssistantContent[currentAssistantContent.length - 1]\n .type === \"text\"\n ) {\n const lastBlock = currentAssistantContent[\n currentAssistantContent.length - 1\n ] as { type: \"text\"; text: string };\n lastBlock.text += (\n content as { type: \"text\"; text: string }\n ).text;\n } else {\n currentAssistantContent.push(content);\n }\n }\n break;\n }\n\n case \"tool_call\":\n case \"tool_call_update\": {\n const meta = update._meta?.claudeCode;\n if (meta) {\n const { toolCallId, toolName, toolInput, toolResponse } = meta;\n\n if (toolCallId && toolName) {\n let toolCall = currentToolCalls.find(\n (tc) => tc.toolCallId === toolCallId,\n );\n if (!toolCall) {\n toolCall = { toolCallId, toolName, input: toolInput };\n currentToolCalls.push(toolCall);\n }\n if (toolResponse !== undefined) {\n toolCall.result = toolResponse;\n }\n }\n }\n break;\n }\n\n case \"tool_result\": {\n const meta = update._meta?.claudeCode;\n if (meta) {\n const { toolCallId, toolResponse } = meta;\n if (toolCallId) {\n const toolCall = currentToolCalls.find(\n (tc) => tc.toolCallId === toolCallId,\n );\n if (toolCall && toolResponse !== undefined) {\n toolCall.result = toolResponse;\n }\n }\n }\n break;\n }\n }\n }\n }\n\n if (currentAssistantContent.length > 0 || currentToolCalls.length > 0) {\n turns.push({\n role: \"assistant\",\n content: currentAssistantContent,\n toolCalls: currentToolCalls.length > 0 ? currentToolCalls : undefined,\n });\n }\n\n return turns;\n}\n\nconst CHARS_PER_TOKEN = 4;\nconst DEFAULT_MAX_TOKENS = 150_000;\nconst LARGE_CONTEXT_MAX_TOKENS = 800_000;\n\nfunction estimateTurnTokens(turn: ConversationTurn): number {\n let chars = 0;\n for (const block of turn.content) {\n if (\"text\" in block && typeof block.text === \"string\") {\n chars += block.text.length;\n }\n }\n if (turn.toolCalls) {\n for (const tc of turn.toolCalls) {\n chars += JSON.stringify(tc.input ?? \"\").length;\n if (tc.result !== undefined) {\n chars +=\n typeof tc.result === \"string\"\n ? tc.result.length\n : JSON.stringify(tc.result).length;\n }\n }\n }\n return Math.ceil(chars / CHARS_PER_TOKEN);\n}\n\nexport function selectRecentTurns(\n turns: ConversationTurn[],\n maxTokens = DEFAULT_MAX_TOKENS,\n): ConversationTurn[] {\n let budget = maxTokens;\n let startIndex = turns.length;\n\n for (let i = turns.length - 1; i >= 0; i--) {\n const cost = estimateTurnTokens(turns[i]);\n if (cost > budget) break;\n budget -= cost;\n startIndex = i;\n }\n\n // Ensure we start on a user turn so the conversation is well-formed\n while (startIndex < turns.length && turns[startIndex].role !== \"user\") {\n startIndex++;\n }\n\n return turns.slice(startIndex);\n}\n\nconst BASE62 = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\";\n\nfunction generateMessageId(): string {\n const bytes = new Uint8Array(24);\n crypto.getRandomValues(bytes);\n let id = \"msg_01\";\n for (const b of bytes) {\n id += BASE62[b % 62];\n }\n return id;\n}\n\nconst ADJECTIVES = [\n \"bright\",\n \"calm\",\n \"daring\",\n \"eager\",\n \"fair\",\n \"gentle\",\n \"happy\",\n \"keen\",\n \"lively\",\n \"merry\",\n \"noble\",\n \"polite\",\n \"quick\",\n \"sharp\",\n \"warm\",\n \"witty\",\n];\nconst VERBS = [\n \"blazing\",\n \"crafting\",\n \"dashing\",\n \"flowing\",\n \"gliding\",\n \"humming\",\n \"jumping\",\n \"linking\",\n \"melting\",\n \"nesting\",\n \"pacing\",\n \"roaming\",\n \"sailing\",\n \"turning\",\n \"waving\",\n \"zoning\",\n];\nconst NOUNS = [\n \"aurora\",\n \"breeze\",\n \"cedar\",\n \"delta\",\n \"ember\",\n \"frost\",\n \"grove\",\n \"haven\",\n \"inlet\",\n \"jewel\",\n \"knoll\",\n \"lotus\",\n \"maple\",\n \"nexus\",\n \"oasis\",\n \"prism\",\n];\n\nfunction generateSlug(): string {\n const pick = (arr: string[]) => arr[Math.floor(Math.random() * arr.length)];\n return `${pick(ADJECTIVES)}-${pick(VERBS)}-${pick(NOUNS)}`;\n}\n\nexport function conversationTurnsToJsonlEntries(\n turns: ConversationTurn[],\n config: JsonlConfig,\n): string[] {\n const lines: string[] = [];\n let parentUuid: string | null = null;\n const model = config.model ?? \"claude-opus-4-6\";\n const version = config.version ?? \"2.1.63\";\n const gitBranch = config.gitBranch ?? \"\";\n const slug = config.slug ?? generateSlug();\n const permissionMode = config.permissionMode ?? \"default\";\n const baseTime = Date.now() - turns.length * 3000;\n let turnIndex = 0;\n\n for (const turn of turns) {\n const timestamp = new Date(baseTime + turnIndex * 3000).toISOString();\n turnIndex++;\n if (turn.role === \"user\") {\n lines.push(\n JSON.stringify({\n type: \"queue-operation\",\n operation: \"enqueue\",\n timestamp,\n sessionId: config.sessionId,\n }),\n );\n lines.push(\n JSON.stringify({\n type: \"queue-operation\",\n operation: \"dequeue\",\n timestamp,\n sessionId: config.sessionId,\n }),\n );\n\n const uuid = randomUUID();\n const textParts = turn.content\n .filter(\n (block) =>\n \"text\" in block && typeof block.text === \"string\" && block.text,\n )\n .map((block) => (block as { text: string }).text);\n\n const userText = textParts.length > 0 ? textParts.join(\"\") : \" \";\n\n lines.push(\n JSON.stringify({\n parentUuid,\n isSidechain: false,\n userType: \"external\",\n cwd: config.cwd,\n sessionId: config.sessionId,\n version,\n gitBranch,\n slug,\n type: \"user\",\n message: {\n role: \"user\",\n content: [{ type: \"text\", text: userText }],\n },\n uuid,\n timestamp,\n permissionMode,\n }),\n );\n parentUuid = uuid;\n } else {\n const allBlocks: unknown[] = [];\n\n for (const block of turn.content) {\n const blockType = (block as { type: string }).type;\n if (blockType === \"thinking\" || blockType === \"text\") {\n allBlocks.push(block);\n }\n }\n\n if (turn.toolCalls) {\n for (const tc of turn.toolCalls) {\n allBlocks.push({\n type: \"tool_use\",\n id: tc.toolCallId,\n name: tc.toolName,\n input: tc.input,\n });\n }\n }\n\n const msgId = generateMessageId();\n const hasToolUse = allBlocks.some(\n (b) => (b as { type: string }).type === \"tool_use\",\n );\n const lastStopReason = hasToolUse ? \"tool_use\" : \"end_turn\";\n\n for (let i = 0; i < allBlocks.length; i++) {\n const block = allBlocks[i];\n const isLast = i === allBlocks.length - 1;\n const uuid = randomUUID();\n\n lines.push(\n JSON.stringify({\n parentUuid,\n isSidechain: false,\n userType: \"external\",\n cwd: config.cwd,\n sessionId: config.sessionId,\n version,\n gitBranch,\n slug,\n type: \"assistant\",\n message: {\n model,\n id: msgId,\n type: \"message\",\n role: \"assistant\",\n content: [block],\n stop_reason: isLast ? lastStopReason : null,\n stop_sequence: null,\n usage: {\n input_tokens: 0,\n cache_creation_input_tokens: 0,\n cache_read_input_tokens: 0,\n output_tokens: 0,\n },\n },\n uuid,\n timestamp,\n }),\n );\n parentUuid = uuid;\n }\n\n if (turn.toolCalls) {\n for (const tc of turn.toolCalls) {\n if (tc.result === undefined) continue;\n\n const uuid = randomUUID();\n const resultText =\n typeof tc.result === \"string\"\n ? tc.result\n : JSON.stringify(tc.result);\n\n lines.push(\n JSON.stringify({\n parentUuid,\n isSidechain: false,\n userType: \"external\",\n cwd: config.cwd,\n sessionId: config.sessionId,\n version,\n gitBranch,\n slug,\n type: \"user\",\n message: {\n role: \"user\",\n content: [\n {\n type: \"tool_result\",\n tool_use_id: tc.toolCallId,\n content: resultText,\n },\n ],\n },\n uuid,\n timestamp,\n }),\n );\n parentUuid = uuid;\n }\n }\n }\n }\n\n return lines;\n}\n\ninterface HydrationLog {\n info: (msg: string, data?: unknown) => void;\n warn: (msg: string, data?: unknown) => void;\n}\n\nexport async function hydrateSessionJsonl(params: {\n sessionId: string;\n cwd: string;\n taskId: string;\n runId: string;\n model?: string;\n gitBranch?: string;\n permissionMode?: string;\n posthogAPI: PostHogAPIClient;\n log: HydrationLog;\n}): Promise<boolean> {\n const { posthogAPI, log } = params;\n\n try {\n const jsonlPath = getSessionJsonlPath(params.sessionId, params.cwd);\n try {\n await fs.access(jsonlPath);\n return true;\n } catch {\n // File doesn't exist, proceed with hydration\n }\n\n const taskRun = await posthogAPI.getTaskRun(params.taskId, params.runId);\n if (!taskRun.log_url) {\n log.info(\"No log URL, skipping JSONL hydration\");\n return false;\n }\n\n const entries = await posthogAPI.fetchTaskRunLogs(taskRun);\n if (entries.length === 0) {\n log.info(\"No S3 log entries, skipping JSONL hydration\");\n return false;\n }\n\n const entryCounts: Record<string, number> = {};\n for (const entry of entries) {\n const method = entry.notification?.method ?? \"unknown\";\n const entryParams = entry.notification?.params as\n | Record<string, unknown>\n | undefined;\n const update = entryParams?.update as\n | { sessionUpdate?: string }\n | undefined;\n const key = update?.sessionUpdate\n ? `${method}:${update.sessionUpdate}`\n : method;\n entryCounts[key] = (entryCounts[key] ?? 0) + 1;\n }\n log.info(\"S3 log entry breakdown\", {\n totalEntries: entries.length,\n types: entryCounts,\n });\n\n const allTurns = rebuildConversation(entries);\n if (allTurns.length === 0) {\n log.info(\"No conversation in S3 logs, skipping JSONL hydration\");\n return false;\n }\n\n const maxTokens = supports1MContext(params.model ?? \"\")\n ? LARGE_CONTEXT_MAX_TOKENS\n : DEFAULT_MAX_TOKENS;\n const conversation = selectRecentTurns(allTurns, maxTokens);\n log.info(\"Selected recent turns for hydration\", {\n totalTurns: allTurns.length,\n selectedTurns: conversation.length,\n turnRoles: conversation.map((t) => t.role),\n });\n\n const jsonlLines = conversationTurnsToJsonlEntries(conversation, {\n sessionId: params.sessionId,\n cwd: params.cwd,\n model: params.model,\n gitBranch: params.gitBranch,\n permissionMode: params.permissionMode,\n });\n\n await fs.mkdir(path.dirname(jsonlPath), { recursive: true });\n\n const tmpPath = `${jsonlPath}.tmp.${Date.now()}`;\n await fs.writeFile(tmpPath, `${jsonlLines.join(\"\\n\")}\\n`);\n await fs.rename(tmpPath, jsonlPath);\n\n log.info(\"Hydrated session JSONL from S3\", {\n sessionId: params.sessionId,\n turns: conversation.length,\n lines: jsonlLines.length,\n });\n return true;\n } catch (err) {\n log.warn(\"Failed to hydrate session JSONL, continuing\", {\n sessionId: params.sessionId,\n error: err instanceof Error ? err.message : String(err),\n });\n return false;\n }\n}\n","export const DEFAULT_MODEL = \"opus\";\n\nconst GATEWAY_TO_SDK_MODEL: Record<string, string> = {\n \"claude-opus-4-5\": \"opus\",\n \"claude-opus-4-6\": \"opus\",\n \"claude-opus-4-7\": \"opus\",\n \"claude-sonnet-4-5\": \"sonnet\",\n \"claude-sonnet-4-6\": \"sonnet\",\n \"claude-haiku-4-5\": \"haiku\",\n};\n\nexport function toSdkModelId(modelId: string): string {\n return GATEWAY_TO_SDK_MODEL[modelId] ?? modelId;\n}\n\nconst MODELS_WITH_1M_CONTEXT = new Set([\n \"claude-opus-4-6\",\n \"claude-opus-4-7\",\n \"claude-sonnet-4-6\",\n]);\n\nexport function supports1MContext(modelId: string): boolean {\n return MODELS_WITH_1M_CONTEXT.has(modelId);\n}\n\nconst MODELS_WITH_EFFORT = new Set([\n \"claude-opus-4-5\",\n \"claude-opus-4-6\",\n \"claude-opus-4-7\",\n \"claude-sonnet-4-6\",\n]);\n\nconst MODELS_WITH_XHIGH_EFFORT = new Set([\n \"claude-opus-4-6\",\n \"claude-opus-4-7\",\n]);\n\nexport function supportsEffort(modelId: string): boolean {\n return MODELS_WITH_EFFORT.has(modelId);\n}\n\nexport function supportsXhighEffort(modelId: string): boolean {\n return MODELS_WITH_XHIGH_EFFORT.has(modelId);\n}\n\nconst MODELS_TO_EXCLUDE_MCP_TOOLS = new Set([\"claude-haiku-4-5\"]);\n\nexport function supportsMcpInjection(modelId: string): boolean {\n return !MODELS_TO_EXCLUDE_MCP_TOOLS.has(modelId);\n}\n\ninterface EffortOption {\n value: string;\n name: string;\n}\n\nexport function getEffortOptions(modelId: string): EffortOption[] | null {\n if (!supportsEffort(modelId)) return null;\n\n const options: EffortOption[] = [\n { value: \"low\", name: \"Low\" },\n { value: \"medium\", name: \"Medium\" },\n { value: \"high\", name: \"High\" },\n ];\n\n if (supportsXhighEffort(modelId)) {\n options.push(\n { value: \"xhigh\", name: \"Extra High\" },\n { value: \"max\", name: \"Max\" },\n );\n }\n\n return options;\n}\n\n// Model alias resolution — lets callers use human-friendly aliases like\n// \"opus\" or \"sonnet\" instead of full model IDs like \"claude-opus-4-6\".\n\nconst MODEL_CONTEXT_HINT_PATTERN = /\\[(\\d+m)\\]$/i;\n\nfunction tokenizeModelPreference(model: string): {\n tokens: string[];\n contextHint?: string;\n} {\n const lower = model.trim().toLowerCase();\n const contextHint = lower\n .match(MODEL_CONTEXT_HINT_PATTERN)?.[1]\n ?.toLowerCase();\n\n const normalized = lower.replace(MODEL_CONTEXT_HINT_PATTERN, \" $1 \");\n const rawTokens = normalized.split(/[^a-z0-9]+/).filter(Boolean);\n const tokens = rawTokens\n .map((token) => {\n if (token === \"opusplan\") return \"opus\";\n if (token === \"best\" || token === \"default\") return \"\";\n return token;\n })\n .filter((token) => token && token !== \"claude\")\n .filter((token) => /[a-z]/.test(token) || token.endsWith(\"m\"));\n\n return { tokens, contextHint };\n}\n\ninterface ModelOption {\n value: string;\n name?: string;\n description?: string;\n}\n\nfunction scoreModelMatch(\n model: ModelOption,\n tokens: string[],\n contextHint?: string,\n): number {\n const haystack = `${model.value} ${model.name ?? \"\"}`.toLowerCase();\n let score = 0;\n for (const token of tokens) {\n if (haystack.includes(token)) {\n score += token === contextHint ? 3 : 1;\n }\n }\n return score;\n}\n\nexport function resolveModelPreference(\n preference: string,\n options: ModelOption[],\n): string | null {\n const trimmed = preference.trim();\n if (!trimmed) return null;\n\n const lower = trimmed.toLowerCase();\n\n // Exact match on value or display name\n const directMatch = options.find(\n (o) =>\n o.value === trimmed ||\n o.value.toLowerCase() === lower ||\n (o.name && o.name.toLowerCase() === lower),\n );\n if (directMatch) return directMatch.value;\n\n // Substring match\n const includesMatch = options.find((o) => {\n const value = o.value.toLowerCase();\n const display = (o.name ?? \"\").toLowerCase();\n return (\n value.includes(lower) || display.includes(lower) || lower.includes(value)\n );\n });\n if (includesMatch) return includesMatch.value;\n\n // Tokenized matching for aliases like \"opus[1m]\"\n const { tokens, contextHint } = tokenizeModelPreference(trimmed);\n if (tokens.length === 0) return null;\n\n let bestMatch: ModelOption | null = null;\n let bestScore = 0;\n for (const model of options) {\n const score = scoreModelMatch(model, tokens, contextHint);\n if (0 < score && (!bestMatch || bestScore < score)) {\n bestMatch = model;\n bestScore = score;\n }\n }\n\n return bestMatch?.value ?? null;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -2,7 +2,7 @@ declare const DEFAULT_MODEL = "opus";
|
|
|
2
2
|
declare function toSdkModelId(modelId: string): string;
|
|
3
3
|
declare function supports1MContext(modelId: string): boolean;
|
|
4
4
|
declare function supportsEffort(modelId: string): boolean;
|
|
5
|
-
declare function
|
|
5
|
+
declare function supportsXhighEffort(modelId: string): boolean;
|
|
6
6
|
declare function supportsMcpInjection(modelId: string): boolean;
|
|
7
7
|
interface EffortOption {
|
|
8
8
|
value: string;
|
|
@@ -16,4 +16,4 @@ interface ModelOption {
|
|
|
16
16
|
}
|
|
17
17
|
declare function resolveModelPreference(preference: string, options: ModelOption[]): string | null;
|
|
18
18
|
|
|
19
|
-
export { DEFAULT_MODEL, getEffortOptions, resolveModelPreference, supports1MContext, supportsEffort,
|
|
19
|
+
export { DEFAULT_MODEL, getEffortOptions, resolveModelPreference, supports1MContext, supportsEffort, supportsMcpInjection, supportsXhighEffort, toSdkModelId };
|
|
@@ -25,12 +25,15 @@ var MODELS_WITH_EFFORT = /* @__PURE__ */ new Set([
|
|
|
25
25
|
"claude-opus-4-7",
|
|
26
26
|
"claude-sonnet-4-6"
|
|
27
27
|
]);
|
|
28
|
-
var
|
|
28
|
+
var MODELS_WITH_XHIGH_EFFORT = /* @__PURE__ */ new Set([
|
|
29
|
+
"claude-opus-4-6",
|
|
30
|
+
"claude-opus-4-7"
|
|
31
|
+
]);
|
|
29
32
|
function supportsEffort(modelId) {
|
|
30
33
|
return MODELS_WITH_EFFORT.has(modelId);
|
|
31
34
|
}
|
|
32
|
-
function
|
|
33
|
-
return
|
|
35
|
+
function supportsXhighEffort(modelId) {
|
|
36
|
+
return MODELS_WITH_XHIGH_EFFORT.has(modelId);
|
|
34
37
|
}
|
|
35
38
|
var MODELS_TO_EXCLUDE_MCP_TOOLS = /* @__PURE__ */ new Set(["claude-haiku-4-5"]);
|
|
36
39
|
function supportsMcpInjection(modelId) {
|
|
@@ -43,8 +46,11 @@ function getEffortOptions(modelId) {
|
|
|
43
46
|
{ value: "medium", name: "Medium" },
|
|
44
47
|
{ value: "high", name: "High" }
|
|
45
48
|
];
|
|
46
|
-
if (
|
|
47
|
-
options.push(
|
|
49
|
+
if (supportsXhighEffort(modelId)) {
|
|
50
|
+
options.push(
|
|
51
|
+
{ value: "xhigh", name: "Extra High" },
|
|
52
|
+
{ value: "max", name: "Max" }
|
|
53
|
+
);
|
|
48
54
|
}
|
|
49
55
|
return options;
|
|
50
56
|
}
|
|
@@ -104,8 +110,8 @@ export {
|
|
|
104
110
|
resolveModelPreference,
|
|
105
111
|
supports1MContext,
|
|
106
112
|
supportsEffort,
|
|
107
|
-
supportsMaxEffort,
|
|
108
113
|
supportsMcpInjection,
|
|
114
|
+
supportsXhighEffort,
|
|
109
115
|
toSdkModelId
|
|
110
116
|
};
|
|
111
117
|
//# sourceMappingURL=models.js.map
|