@nodetool-ai/runtime 0.8.1 → 0.8.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (256) hide show
  1. package/dist/.nodetool-build-stamp +1 -1
  2. package/dist/context.d.ts +31 -3
  3. package/dist/context.d.ts.map +1 -1
  4. package/dist/context.js +366 -158
  5. package/dist/context.js.map +1 -1
  6. package/dist/generation-registry.d.ts +8 -0
  7. package/dist/generation-registry.d.ts.map +1 -1
  8. package/dist/generation-registry.js +18 -0
  9. package/dist/generation-registry.js.map +1 -1
  10. package/dist/host-binaries.d.ts.map +1 -1
  11. package/dist/host-binaries.js +18 -10
  12. package/dist/host-binaries.js.map +1 -1
  13. package/dist/image-codec.d.ts +2 -0
  14. package/dist/image-codec.d.ts.map +1 -1
  15. package/dist/image-codec.js +23 -3
  16. package/dist/image-codec.js.map +1 -1
  17. package/dist/image-model-tasks.d.ts +15 -0
  18. package/dist/image-model-tasks.d.ts.map +1 -0
  19. package/dist/image-model-tasks.js +24 -0
  20. package/dist/image-model-tasks.js.map +1 -0
  21. package/dist/index.d.ts +14 -3
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +10 -2
  24. package/dist/index.js.map +1 -1
  25. package/dist/media-ref-bytes.d.ts +18 -2
  26. package/dist/media-ref-bytes.d.ts.map +1 -1
  27. package/dist/media-ref-bytes.js +26 -16
  28. package/dist/media-ref-bytes.js.map +1 -1
  29. package/dist/node-executor.d.ts +6 -0
  30. package/dist/node-executor.d.ts.map +1 -1
  31. package/dist/providers/aki-provider.d.ts +2 -0
  32. package/dist/providers/aki-provider.d.ts.map +1 -1
  33. package/dist/providers/aki-provider.js +6 -0
  34. package/dist/providers/aki-provider.js.map +1 -1
  35. package/dist/providers/atlascloud-provider.d.ts +2 -0
  36. package/dist/providers/atlascloud-provider.d.ts.map +1 -1
  37. package/dist/providers/atlascloud-provider.js +22 -0
  38. package/dist/providers/atlascloud-provider.js.map +1 -1
  39. package/dist/providers/base-provider.d.ts +36 -24
  40. package/dist/providers/base-provider.d.ts.map +1 -1
  41. package/dist/providers/base-provider.js +124 -148
  42. package/dist/providers/base-provider.js.map +1 -1
  43. package/dist/providers/claude-agent-provider.d.ts +6 -36
  44. package/dist/providers/claude-agent-provider.d.ts.map +1 -1
  45. package/dist/providers/claude-agent-provider.js +208 -26
  46. package/dist/providers/claude-agent-provider.js.map +1 -1
  47. package/dist/providers/codex-provider.d.ts +2 -0
  48. package/dist/providers/codex-provider.d.ts.map +1 -1
  49. package/dist/providers/codex-provider.js +15 -2
  50. package/dist/providers/codex-provider.js.map +1 -1
  51. package/dist/providers/cohere-provider.d.ts +2 -1
  52. package/dist/providers/cohere-provider.d.ts.map +1 -1
  53. package/dist/providers/cohere-provider.js +5 -0
  54. package/dist/providers/cohere-provider.js.map +1 -1
  55. package/dist/providers/core-tools.d.ts +2 -1
  56. package/dist/providers/core-tools.d.ts.map +1 -1
  57. package/dist/providers/core-tools.js +2 -1
  58. package/dist/providers/core-tools.js.map +1 -1
  59. package/dist/providers/credential-check.d.ts.map +1 -1
  60. package/dist/providers/credential-check.js +5 -0
  61. package/dist/providers/credential-check.js.map +1 -1
  62. package/dist/providers/custom-openai-provider.d.ts +2 -0
  63. package/dist/providers/custom-openai-provider.d.ts.map +1 -1
  64. package/dist/providers/custom-openai-provider.js +8 -0
  65. package/dist/providers/custom-openai-provider.js.map +1 -1
  66. package/dist/providers/dreamina-models.d.ts +5 -0
  67. package/dist/providers/dreamina-models.d.ts.map +1 -0
  68. package/dist/providers/dreamina-models.js +57 -0
  69. package/dist/providers/dreamina-models.js.map +1 -0
  70. package/dist/providers/dreamina-music.d.ts +52 -0
  71. package/dist/providers/dreamina-music.d.ts.map +1 -0
  72. package/dist/providers/dreamina-music.js +115 -0
  73. package/dist/providers/dreamina-music.js.map +1 -0
  74. package/dist/providers/dreamina-provider.d.ts +62 -0
  75. package/dist/providers/dreamina-provider.d.ts.map +1 -0
  76. package/dist/providers/dreamina-provider.js +790 -0
  77. package/dist/providers/dreamina-provider.js.map +1 -0
  78. package/dist/providers/elevenlabs-provider.d.ts +2 -1
  79. package/dist/providers/elevenlabs-provider.d.ts.map +1 -1
  80. package/dist/providers/elevenlabs-provider.js +5 -0
  81. package/dist/providers/elevenlabs-provider.js.map +1 -1
  82. package/dist/providers/evolink-provider.d.ts +2 -0
  83. package/dist/providers/evolink-provider.d.ts.map +1 -1
  84. package/dist/providers/evolink-provider.js +8 -0
  85. package/dist/providers/evolink-provider.js.map +1 -1
  86. package/dist/providers/fake-provider.d.ts +2 -1
  87. package/dist/providers/fake-provider.d.ts.map +1 -1
  88. package/dist/providers/fake-provider.js +10 -0
  89. package/dist/providers/fake-provider.js.map +1 -1
  90. package/dist/providers/fal-provider.d.ts +2 -1
  91. package/dist/providers/fal-provider.d.ts.map +1 -1
  92. package/dist/providers/fal-provider.js +27 -0
  93. package/dist/providers/fal-provider.js.map +1 -1
  94. package/dist/providers/gemini-provider.d.ts +2 -1
  95. package/dist/providers/gemini-provider.d.ts.map +1 -1
  96. package/dist/providers/gemini-provider.js +15 -0
  97. package/dist/providers/gemini-provider.js.map +1 -1
  98. package/dist/providers/higgsfield-provider.d.ts +2 -1
  99. package/dist/providers/higgsfield-provider.d.ts.map +1 -1
  100. package/dist/providers/higgsfield-provider.js +12 -0
  101. package/dist/providers/higgsfield-provider.js.map +1 -1
  102. package/dist/providers/huggingface-provider.d.ts +2 -1
  103. package/dist/providers/huggingface-provider.d.ts.map +1 -1
  104. package/dist/providers/huggingface-provider.js +10 -0
  105. package/dist/providers/huggingface-provider.js.map +1 -1
  106. package/dist/providers/index.d.ts +5 -2
  107. package/dist/providers/index.d.ts.map +1 -1
  108. package/dist/providers/index.js +13 -2
  109. package/dist/providers/index.js.map +1 -1
  110. package/dist/providers/jina-provider.d.ts +2 -1
  111. package/dist/providers/jina-provider.d.ts.map +1 -1
  112. package/dist/providers/jina-provider.js +5 -0
  113. package/dist/providers/jina-provider.js.map +1 -1
  114. package/dist/providers/kie-provider.d.ts +2 -1
  115. package/dist/providers/kie-provider.d.ts.map +1 -1
  116. package/dist/providers/kie-provider.js +14 -0
  117. package/dist/providers/kie-provider.js.map +1 -1
  118. package/dist/providers/llama-provider.d.ts +4 -1
  119. package/dist/providers/llama-provider.d.ts.map +1 -1
  120. package/dist/providers/llama-provider.js +9 -3
  121. package/dist/providers/llama-provider.js.map +1 -1
  122. package/dist/providers/loop-tracing.d.ts +17 -0
  123. package/dist/providers/loop-tracing.d.ts.map +1 -0
  124. package/dist/providers/loop-tracing.js +132 -0
  125. package/dist/providers/loop-tracing.js.map +1 -0
  126. package/dist/providers/meshy-provider.d.ts +2 -1
  127. package/dist/providers/meshy-provider.d.ts.map +1 -1
  128. package/dist/providers/meshy-provider.js +6 -0
  129. package/dist/providers/meshy-provider.js.map +1 -1
  130. package/dist/providers/minimax-provider.d.ts +2 -0
  131. package/dist/providers/minimax-provider.d.ts.map +1 -1
  132. package/dist/providers/minimax-provider.js +11 -0
  133. package/dist/providers/minimax-provider.js.map +1 -1
  134. package/dist/providers/mistral-provider.d.ts +2 -0
  135. package/dist/providers/mistral-provider.d.ts.map +1 -1
  136. package/dist/providers/mistral-provider.js +5 -0
  137. package/dist/providers/mistral-provider.js.map +1 -1
  138. package/dist/providers/node-llama-cpp-provider.d.ts +2 -1
  139. package/dist/providers/node-llama-cpp-provider.d.ts.map +1 -1
  140. package/dist/providers/node-llama-cpp-provider.js +8 -3
  141. package/dist/providers/node-llama-cpp-provider.js.map +1 -1
  142. package/dist/providers/nodetool-provider.d.ts +1 -1
  143. package/dist/providers/nodetool-provider.d.ts.map +1 -1
  144. package/dist/providers/nodetool-provider.js +0 -2
  145. package/dist/providers/nodetool-provider.js.map +1 -1
  146. package/dist/providers/ollama-provider.d.ts +2 -1
  147. package/dist/providers/ollama-provider.d.ts.map +1 -1
  148. package/dist/providers/ollama-provider.js +5 -0
  149. package/dist/providers/ollama-provider.js.map +1 -1
  150. package/dist/providers/openai-provider.d.ts +10 -2
  151. package/dist/providers/openai-provider.d.ts.map +1 -1
  152. package/dist/providers/openai-provider.js +63 -16
  153. package/dist/providers/openai-provider.js.map +1 -1
  154. package/dist/providers/openrouter-provider.d.ts +52 -1
  155. package/dist/providers/openrouter-provider.d.ts.map +1 -1
  156. package/dist/providers/openrouter-provider.js +372 -11
  157. package/dist/providers/openrouter-provider.js.map +1 -1
  158. package/dist/providers/provider-error.d.ts.map +1 -1
  159. package/dist/providers/provider-error.js +7 -1
  160. package/dist/providers/provider-error.js.map +1 -1
  161. package/dist/providers/provider-generations.d.ts +2 -2
  162. package/dist/providers/provider-generations.js +2 -2
  163. package/dist/providers/provider-request-log.d.ts.map +1 -1
  164. package/dist/providers/provider-request-log.js +18 -7
  165. package/dist/providers/provider-request-log.js.map +1 -1
  166. package/dist/providers/python-provider.d.ts +6 -1
  167. package/dist/providers/python-provider.d.ts.map +1 -1
  168. package/dist/providers/python-provider.js +30 -11
  169. package/dist/providers/python-provider.js.map +1 -1
  170. package/dist/providers/replicate-provider.d.ts +2 -1
  171. package/dist/providers/replicate-provider.d.ts.map +1 -1
  172. package/dist/providers/replicate-provider.js +22 -0
  173. package/dist/providers/replicate-provider.js.map +1 -1
  174. package/dist/providers/requesty-provider.d.ts +30 -0
  175. package/dist/providers/requesty-provider.d.ts.map +1 -0
  176. package/dist/providers/requesty-provider.js +87 -0
  177. package/dist/providers/requesty-provider.js.map +1 -0
  178. package/dist/providers/reve-provider.d.ts +2 -1
  179. package/dist/providers/reve-provider.d.ts.map +1 -1
  180. package/dist/providers/reve-provider.js +6 -0
  181. package/dist/providers/reve-provider.js.map +1 -1
  182. package/dist/providers/rodin-provider.d.ts +2 -1
  183. package/dist/providers/rodin-provider.d.ts.map +1 -1
  184. package/dist/providers/rodin-provider.js +6 -0
  185. package/dist/providers/rodin-provider.js.map +1 -1
  186. package/dist/providers/together-operations.d.ts +27 -0
  187. package/dist/providers/together-operations.d.ts.map +1 -0
  188. package/dist/providers/together-operations.js +95 -0
  189. package/dist/providers/together-operations.js.map +1 -0
  190. package/dist/providers/together-provider.d.ts +5 -8
  191. package/dist/providers/together-provider.d.ts.map +1 -1
  192. package/dist/providers/together-provider.js +54 -159
  193. package/dist/providers/together-provider.js.map +1 -1
  194. package/dist/providers/topaz-provider.d.ts +2 -1
  195. package/dist/providers/topaz-provider.d.ts.map +1 -1
  196. package/dist/providers/topaz-provider.js +5 -0
  197. package/dist/providers/topaz-provider.js.map +1 -1
  198. package/dist/providers/types.d.ts +38 -0
  199. package/dist/providers/types.d.ts.map +1 -1
  200. package/dist/providers/types.js.map +1 -1
  201. package/dist/providers/useapi-provider.d.ts +2 -1
  202. package/dist/providers/useapi-provider.d.ts.map +1 -1
  203. package/dist/providers/useapi-provider.js +8 -0
  204. package/dist/providers/useapi-provider.js.map +1 -1
  205. package/dist/providers/vllm-provider.d.ts +2 -4
  206. package/dist/providers/vllm-provider.d.ts.map +1 -1
  207. package/dist/providers/vllm-provider.js +1 -5
  208. package/dist/providers/vllm-provider.js.map +1 -1
  209. package/dist/providers/voyage-provider.d.ts +2 -1
  210. package/dist/providers/voyage-provider.d.ts.map +1 -1
  211. package/dist/providers/voyage-provider.js +5 -0
  212. package/dist/providers/voyage-provider.js.map +1 -1
  213. package/dist/providers/xai-provider.d.ts +2 -0
  214. package/dist/providers/xai-provider.d.ts.map +1 -1
  215. package/dist/providers/xai-provider.js +8 -0
  216. package/dist/providers/xai-provider.js.map +1 -1
  217. package/dist/recommended-models.d.ts.map +1 -1
  218. package/dist/recommended-models.js +20 -0
  219. package/dist/recommended-models.js.map +1 -1
  220. package/dist/run-context.d.ts +20 -0
  221. package/dist/run-context.d.ts.map +1 -0
  222. package/dist/run-context.js +18 -0
  223. package/dist/run-context.js.map +1 -0
  224. package/dist/run-trace-context.d.ts +30 -0
  225. package/dist/run-trace-context.d.ts.map +1 -0
  226. package/dist/run-trace-context.js +80 -0
  227. package/dist/run-trace-context.js.map +1 -0
  228. package/dist/run-trace-processor.d.ts +65 -0
  229. package/dist/run-trace-processor.d.ts.map +1 -0
  230. package/dist/run-trace-processor.js +417 -0
  231. package/dist/run-trace-processor.js.map +1 -0
  232. package/dist/run-trace-serialization.d.ts +5 -0
  233. package/dist/run-trace-serialization.d.ts.map +1 -0
  234. package/dist/run-trace-serialization.js +113 -0
  235. package/dist/run-trace-serialization.js.map +1 -0
  236. package/dist/storage-workspace.d.ts +3 -0
  237. package/dist/storage-workspace.d.ts.map +1 -1
  238. package/dist/storage-workspace.js +32 -17
  239. package/dist/storage-workspace.js.map +1 -1
  240. package/dist/telemetry.d.ts +9 -3
  241. package/dist/telemetry.d.ts.map +1 -1
  242. package/dist/telemetry.js +53 -20
  243. package/dist/telemetry.js.map +1 -1
  244. package/dist/trace-exporters.d.ts +2 -29
  245. package/dist/trace-exporters.d.ts.map +1 -1
  246. package/dist/trace-exporters.js +10 -2
  247. package/dist/trace-exporters.js.map +1 -1
  248. package/dist/tracing-helpers.d.ts +15 -22
  249. package/dist/tracing-helpers.d.ts.map +1 -1
  250. package/dist/tracing-helpers.js +38 -6
  251. package/dist/tracing-helpers.js.map +1 -1
  252. package/dist/trim-video-window.d.ts +8 -0
  253. package/dist/trim-video-window.d.ts.map +1 -0
  254. package/dist/trim-video-window.js +50 -0
  255. package/dist/trim-video-window.js.map +1 -0
  256. package/package.json +19 -5
@@ -1,46 +1,14 @@
1
- /**
2
- * ClaudeAgentProvider — Claude reached through the official
3
- * `@anthropic-ai/claude-agent-sdk` instead of an API key.
4
- *
5
- * Unlike {@link AnthropicProvider}, this provider sends no `ANTHROPIC_API_KEY`:
6
- * the SDK drives the bundled `claude` binary (shipped as an optional platform
7
- * dependency, so there is nothing to install on PATH) and lets it authenticate
8
- * with the machine's logged-in Claude subscription (the credentials stored
9
- * under `~/.claude`). The SDK streams `SDKMessage`s, which we translate into the
10
- * cross-provider {@link ProviderStreamItem} stream.
11
- *
12
- * `@anthropic-ai/claude-agent-sdk` is a *soft* (optional peer) dependency: it is
13
- * not installed by default and must be added with the package manager before
14
- * this provider can run. It is loaded lazily via {@link loadSdk}, so a missing
15
- * package surfaces as a clear install hint only when the provider is actually
16
- * used — the rest of the runtime, and the browser worker bundle, never need it.
17
- *
18
- * It is a *pure LLM* provider: the agentic tool loop is collapsed to a single
19
- * turn with every built-in tool disabled (`allowedTools: []`), filesystem
20
- * settings/skills disabled (`settingSources: []`), permission prompts neutered
21
- * (`permissionMode: "dontAsk"`), and the default agent system prompt fully
22
- * replaced (`systemPrompt`), so the model behaves like a plain chat completion —
23
- * text in, text (and thinking) out.
24
- *
25
- * Session continuity: when a `threadId` is supplied the provider routes the
26
- * thread through a single upstream session and, on subsequent turns, resumes it
27
- * (`options.resume`) and sends only the new user delta. The continuation token
28
- * ({@link ProviderSession}) is surfaced as a {@link ProviderSessionUpdate} and
29
- * persisted by the chat layer onto the assistant message; the in-memory map
30
- * below is only a within-process cache (the DB column is authoritative).
31
- */
32
- import type { McpSdkServerConfigWithInstance, Options, SdkMcpToolDefinition, SDKMessage } from "@anthropic-ai/claude-agent-sdk";
1
+ import type { McpSdkServerConfigWithInstance, Options, SdkMcpToolDefinition, SDKMessage, SDKUserMessage } from "@anthropic-ai/claude-agent-sdk";
33
2
  import { BaseProvider } from "./base-provider.js";
34
3
  import { type LanguageModel, type Message, type MessageContent, type ProviderSession, type ProviderStreamItem, type ProviderSkill, type ProviderTool, type ToolCall } from "./types.js";
35
4
  import type { RunBudget, TurnBudget } from "../turn-budget.js";
36
5
  /**
37
6
  * The subset of the SDK `query` signature this provider depends on. We only
38
- * ever pass a string prompt and consume the result as an async iterable, so the
39
- * real `query` (which also accepts an async-iterable prompt and returns the
40
- * richer `Query`) is assignable to this. Injectable for tests.
7
+ * pass a string for text-only turns or a structured user message for images,
8
+ * and consume the result as an async iterable. Injectable for tests.
41
9
  */
42
10
  export type ClaudeQueryFn = (params: {
43
- prompt: string;
11
+ prompt: string | AsyncIterable<SDKUserMessage>;
44
12
  options?: Options;
45
13
  }) => AsyncIterable<SDKMessage>;
46
14
  /** The SDK `createSdkMcpServer` factory. Injectable for tests. */
@@ -102,6 +70,7 @@ export declare class ClaudeAgentProvider extends BaseProvider {
102
70
  executeTool?: (toolCall: ToolCall) => Promise<string | MessageContent[]>;
103
71
  resolveMedia?: (messages: Message[]) => Promise<Message[]>;
104
72
  maxIterations?: number;
73
+ providedToolsOnly?: boolean;
105
74
  turnBudget?: TurnBudget | RunBudget;
106
75
  workspaceDir?: string;
107
76
  /**
@@ -113,6 +82,7 @@ export declare class ClaudeAgentProvider extends BaseProvider {
113
82
  */
114
83
  skills?: ProviderSkill[];
115
84
  }): AsyncGenerator<ProviderStreamItem>;
85
+ private generateSdkLoop;
116
86
  generateMessages(args: {
117
87
  messages: Message[];
118
88
  model: string;
@@ -1 +1 @@
1
- {"version":3,"file":"claude-agent-provider.d.ts","sourceRoot":"","sources":["../../src/providers/claude-agent-provider.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"claude-agent-provider.d.ts","sourceRoot":"","sources":["../../src/providers/claude-agent-provider.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,5 @@
1
+ import { getTracer } from "../telemetry.js";
2
+ import { tracedProviderLoop, tracedToolCall, beginProviderRound, providerRoundContext, traceContentAllowed, messageTraceContent, traceTextContent } from "./loop-tracing.js";
1
3
  /**
2
4
  * ClaudeAgentProvider — Claude reached through the official
3
5
  * `@anthropic-ai/claude-agent-sdk` instead of an API key.
@@ -35,7 +37,7 @@ import * as path from "node:path";
35
37
  import { createLogger, importOptionalModule } from "@nodetool-ai/config";
36
38
  import { z } from "zod";
37
39
  import { BaseProvider, budgetStopItem, resolveTurnBudget } from "./base-provider.js";
38
- import { sdkNativeReplacements } from "./core-tools.js";
40
+ import { SDK_NATIVE_TOOL_REPLACEMENTS, sdkNativeReplacements } from "./core-tools.js";
39
41
  import { isProviderMessageEvent, isProviderSessionUpdate, isProviderStop } from "./types.js";
40
42
  import { hashSystemPrompt } from "./provider-session.js";
41
43
  import { PROVIDER_IDS, isFiniteNumber, isNonEmptyString, isObjectLike, isString } from "@nodetool-ai/protocol";
@@ -63,6 +65,8 @@ const SDK_BUILTIN_TOOLS = [
63
65
  "Task",
64
66
  "TodoWrite"
65
67
  ];
68
+ /** The built-ins a tool-using turn keeps even when it offered no counterpart. */
69
+ const SDK_WEB_TOOLS = ["WebSearch", "WebFetch"];
66
70
  /**
67
71
  * Env vars a nested Claude subscription session leaks into its children. The
68
72
  * SDK spawns the bundled CLI as a subprocess; left in place these would make it
@@ -72,6 +76,13 @@ const SDK_BUILTIN_TOOLS = [
72
76
  const NESTED_SESSION_ENV = /^(CLAUDECODE|CLAUDE_(CODE|SESSION|ENABLE|AFTER|AUTO)_[A-Za-z0-9_]*)$/;
73
77
  /** MCP server name under which NodeTool's tools are exposed to the SDK. */
74
78
  const TOOL_SERVER_NAME = "nodetool_tools";
79
+ /**
80
+ * Turns a structured-output call may take. The SDK validates the answer
81
+ * against the schema and, when it does not match, hands the model the errors
82
+ * and asks again — each retry is a turn. With one turn, the first answer that
83
+ * misses the schema fails the call as `error_max_turns`.
84
+ */
85
+ const STRUCTURED_OUTPUT_MAX_TURNS = 3;
75
86
  const TOOL_PREFIX = `mcp__${TOOL_SERVER_NAME}__`;
76
87
  /**
77
88
  * The member expression the retired guest toolbelt was called through:
@@ -178,6 +189,9 @@ export class ClaudeAgentProvider extends BaseProvider {
178
189
  * persistable {@link ProviderMessageEvent}s.
179
190
  */
180
191
  async *generateLoop(args) {
192
+ return yield* tracedProviderLoop(this.provider, args.model, () => this.generateSdkLoop(args));
193
+ }
194
+ async *generateSdkLoop(args) {
181
195
  // The SDK owns the loop, so honoring the budget is this override's job:
182
196
  // reserve before the first turn, and again after every assistant turn that
183
197
  // requested tools — that is the point where the SDK will make another call.
@@ -199,17 +213,19 @@ export class ClaudeAgentProvider extends BaseProvider {
199
213
  }
200
214
  reservations.push(first);
201
215
  }
202
- // Drop every NodeTool tool the SDK ships a built-in for. Those built-ins
203
- // are live under bypassPermissions, so keeping the MCP copy would give one
204
- // capability two surfaces and make the model pick between them.
216
+ // Normally prefer native equivalents to duplicate MCP surfaces. A caller
217
+ // restricting the loop keeps its own dispatch instead.
205
218
  const offered = args.tools ?? [];
206
- const replaced = sdkNativeReplacements(offered.map((t) => t.name), args.workspaceDir);
219
+ const replaced = args.providedToolsOnly
220
+ ? new Set()
221
+ : sdkNativeReplacements(offered.map((t) => t.name), args.workspaceDir);
207
222
  const tools = offered.filter((t) => !replaced.has(t.name));
208
223
  if (replaced.size > 0) {
209
224
  log.debug("Using SDK built-ins in place of NodeTool tools", {
210
225
  replaced: [...replaced]
211
226
  });
212
227
  }
228
+ beginProviderRound(this.provider, args.model);
213
229
  const executeTool = args.executeTool;
214
230
  // A tool dispatches either through its own `execute` or the harness
215
231
  // `executeTool`; build the MCP server when at least one route exists.
@@ -236,13 +252,11 @@ export class ClaudeAgentProvider extends BaseProvider {
236
252
  // so a clock alone would hand them one id.
237
253
  const toolCallId = `call_${name}_${crypto.randomUUID()}`;
238
254
  const result = t.execute
239
- ? await t.execute(toolArgs, toolCallId)
255
+ ? await tracedToolCall({ id: toolCallId, name, args: toolArgs }, () => { const execute = t.execute; if (!execute) {
256
+ throw new Error("Tool dispatch was removed");
257
+ } return execute(toolArgs, toolCallId); })
240
258
  : executeTool
241
- ? await executeTool({
242
- id: toolCallId,
243
- name,
244
- args: toolArgs
245
- })
259
+ ? await tracedToolCall({ id: toolCallId, name, args: toolArgs }, () => executeTool({ id: toolCallId, name, args: toolArgs }))
246
260
  : `Tool "${name}" is not available`;
247
261
  // A terminal tool ends the SDK loop after its result is delivered.
248
262
  if (t.terminal)
@@ -263,7 +277,7 @@ export class ClaudeAgentProvider extends BaseProvider {
263
277
  // native skill loader discovers. Best-effort: a disk failure drops skills
264
278
  // for the turn, it does not sink it. Cleaned up in the `finally` below.
265
279
  let skillsPlugin = null;
266
- if ((args.skills?.length ?? 0) > 0) {
280
+ if (!args.providedToolsOnly && (args.skills?.length ?? 0) > 0) {
267
281
  try {
268
282
  skillsPlugin = await materializeSkillsPlugin(args.skills ?? []);
269
283
  }
@@ -286,6 +300,10 @@ export class ClaudeAgentProvider extends BaseProvider {
286
300
  maxTurns: offered.length > 0 ? (args.maxIterations ?? DEFAULT_TOOL_TURNS) : 1,
287
301
  mcp,
288
302
  toolsOffered: offered.length > 0,
303
+ providedToolsOnly: args.providedToolsOnly,
304
+ builtinTools: args.providedToolsOnly
305
+ ? []
306
+ : turnBuiltins(replaced, offered.length > 0, skillsPlugin !== null),
289
307
  cwd: args.workspaceDir,
290
308
  skillsPlugin
291
309
  });
@@ -362,9 +380,10 @@ export class ClaudeAgentProvider extends BaseProvider {
362
380
  const resultSchema = resultTool?.inputSchema;
363
381
  const config = {
364
382
  emitMessages: false,
365
- maxTurns: args.maxTurns ?? 1,
383
+ maxTurns: args.maxTurns ?? (resultTool ? STRUCTURED_OUTPUT_MAX_TURNS : 1),
366
384
  mcp: null,
367
- toolsOffered: false
385
+ toolsOffered: false,
386
+ builtinTools: []
368
387
  };
369
388
  if (resultTool && resultSchema) {
370
389
  config.outputFormat = { type: "json_schema", schema: resultSchema };
@@ -466,8 +485,8 @@ export class ClaudeAgentProvider extends BaseProvider {
466
485
  // Do NOT load repo .claude / CLAUDE.md / skills.
467
486
  settingSources: [],
468
487
  // Run without asking for permissions: never prompt AND never deny. This
469
- // lets the SDK agent use its built-in tools (WebSearch/WebFetch/Bash/…)
470
- // alongside NodeTool's MCP tools. bypassPermissions requires the explicit
488
+ // lets the SDK agent use the built-ins `tools` keeps alongside
489
+ // NodeTool's MCP tools. bypassPermissions requires the explicit
471
490
  // safety flag below.
472
491
  permissionMode: "bypassPermissions",
473
492
  allowDangerouslySkipPermissions: true,
@@ -486,15 +505,35 @@ export class ClaudeAgentProvider extends BaseProvider {
486
505
  // deferred, and NodeTool defers none — it registers its handful of tools
487
506
  // in-process — so the search always comes back empty. A model that fell
488
507
  // back to it after a mis-named tool call got nothing and stalled the turn.
489
- disallowedTools: plan.config.toolsOffered
490
- ? ["ToolSearch"]
491
- : [...SDK_BUILTIN_TOOLS, "ToolSearch"],
508
+ // Supplied-only loops also disable Skill and keep all supplied dispatch
509
+ // inside the caller's MCP boundary.
510
+ disallowedTools: plan.config.providedToolsOnly
511
+ ? [...SDK_BUILTIN_TOOLS, "Skill", "ToolSearch"]
512
+ : plan.config.toolsOffered
513
+ ? ["ToolSearch"]
514
+ : [...SDK_BUILTIN_TOOLS, "ToolSearch"],
515
+ tools: plan.config.builtinTools,
516
+ // Only the in-process NodeTool server. Without this the child also loads
517
+ // the account's claude.ai connectors and the user's MCP servers, and
518
+ // their tool schemas grow every request of the loop.
519
+ strictMcpConfig: true,
520
+ // Hide the skills bundled with the SDK. The plugin below names its own.
521
+ skills: [],
492
522
  includePartialMessages: true,
493
523
  // Setting env REPLACES the child env, so spread process.env minus the
494
524
  // nested-session leakage. Preserves PATH/HOME/ANTHROPIC_BASE_URL/proxies.
495
525
  env: buildChildEnv(),
496
526
  abortController
497
527
  };
528
+ if (args.effort !== undefined) {
529
+ options.effort = args.effort;
530
+ }
531
+ if (args.thinking) {
532
+ options.thinking =
533
+ args.thinking.type === "manual"
534
+ ? { type: "enabled", budgetTokens: args.thinking.budgetTokens }
535
+ : { type: args.thinking.type };
536
+ }
498
537
  if (plan.config.outputFormat) {
499
538
  options.outputFormat = plan.config.outputFormat;
500
539
  }
@@ -544,11 +583,35 @@ export class ClaudeAgentProvider extends BaseProvider {
544
583
  model: args.model,
545
584
  resume: Boolean(plan.resume)
546
585
  });
586
+ const tracer = getTracer();
587
+ const startLlm = () => {
588
+ const span = tracer?.startSpan(`llm.stream ${this.provider}/${args.model}`, {}, providerRoundContext());
589
+ span?.setAttributes({ "llm.provider": this.provider, "llm.model": args.model, "llm.request.stream": true });
590
+ if (traceContentAllowed()) {
591
+ span?.setAttribute("llm.request.messages", messageTraceContent(args.messages));
592
+ }
593
+ return span;
594
+ };
595
+ let llmSpan = startLlm();
596
+ let llmResponse = "";
597
+ let observedTurn = false;
598
+ const closeLlm = () => {
599
+ if (traceContentAllowed()) {
600
+ llmSpan?.setAttribute("llm.response.content", llmResponse);
601
+ }
602
+ llmSpan?.end();
603
+ llmSpan = undefined;
604
+ llmResponse = "";
605
+ };
547
606
  let resolvedModel = args.model;
548
607
  // When partial deltas stream, we render from them and skip the final
549
608
  // assistant message to avoid duplication; if a build omits partials we fall
550
609
  // back to the final message's content blocks.
551
610
  let streamedFromPartials = false;
611
+ // The CLI answers a refused login with a synthetic assistant message, then
612
+ // a "success" result flagged `is_error`. Hold its text back from the stream
613
+ // and fail the call with it instead.
614
+ let authFailure = null;
552
615
  // The SDK splits one API assistant turn into one frame per content block —
553
616
  // thinking, then text, then each tool_use. Emitting a message per frame
554
617
  // would hand the consumer a text-only assistant message in the middle of a
@@ -575,7 +638,7 @@ export class ClaudeAgentProvider extends BaseProvider {
575
638
  };
576
639
  };
577
640
  try {
578
- for await (const msg of queryFn({ prompt: plan.prompt, options })) {
641
+ for await (const msg of queryFn({ prompt: sdkPrompt(plan.prompt), options })) {
579
642
  if (msg.type === "system" && msg.subtype === "init") {
580
643
  // Capture the session and surface it immediately so a streaming
581
644
  // consumer can persist it onto the assistant message it creates.
@@ -596,6 +659,17 @@ export class ClaudeAgentProvider extends BaseProvider {
596
659
  continue;
597
660
  }
598
661
  if (msg.type === "stream_event") {
662
+ if (msg.event.type === "message_start") {
663
+ if (observedTurn) {
664
+ closeLlm();
665
+ beginProviderRound(this.provider, args.model);
666
+ llmSpan = startLlm();
667
+ }
668
+ observedTurn = true;
669
+ }
670
+ if (msg.event.type === "message_stop") {
671
+ closeLlm();
672
+ }
599
673
  const captured = capturedModelFromPartial(msg);
600
674
  if (captured)
601
675
  resolvedModel = captured;
@@ -603,6 +677,9 @@ export class ClaudeAgentProvider extends BaseProvider {
603
677
  if (delta?.text != null) {
604
678
  streamedFromPartials = true;
605
679
  plan.emitted.content = true;
680
+ if (traceContentAllowed()) {
681
+ llmResponse = traceTextContent(llmResponse + delta.text);
682
+ }
606
683
  yield { type: "chunk", content: delta.text, done: false };
607
684
  }
608
685
  else if (delta?.thinking != null) {
@@ -618,6 +695,13 @@ export class ClaudeAgentProvider extends BaseProvider {
618
695
  continue;
619
696
  }
620
697
  if (msg.type === "assistant") {
698
+ if (msg.error === "authentication_failed") {
699
+ authFailure = finalBlocks(msg)
700
+ .filter((block) => !block.thinking)
701
+ .map((block) => block.content)
702
+ .join("");
703
+ continue;
704
+ }
621
705
  const m = msg.message;
622
706
  if (m && isNonEmptyString(m.model))
623
707
  resolvedModel = m.model;
@@ -625,6 +709,9 @@ export class ClaudeAgentProvider extends BaseProvider {
625
709
  // final content blocks — kept strictly separate, never merged.
626
710
  if (!streamedFromPartials) {
627
711
  for (const block of finalBlocks(msg)) {
712
+ if (!block.thinking && traceContentAllowed()) {
713
+ llmResponse = traceTextContent(llmResponse + block.content);
714
+ }
628
715
  plan.emitted.content = true;
629
716
  yield block.thinking
630
717
  ? {
@@ -682,6 +769,9 @@ export class ClaudeAgentProvider extends BaseProvider {
682
769
  // Bill every terminal result, not just the successful ones: an
683
770
  // errored/max-turns run still consumed (and was charged for) tokens.
684
771
  this.trackResultUsage(msg, resolvedModel);
772
+ if (authFailure !== null && msg.is_error) {
773
+ throw claudeAuthError(authFailure);
774
+ }
685
775
  if (msg.subtype === "success") {
686
776
  const flushed = flushPending();
687
777
  if (flushed)
@@ -718,6 +808,7 @@ export class ClaudeAgentProvider extends BaseProvider {
718
808
  throw err instanceof Error ? err : new Error(String(err));
719
809
  }
720
810
  finally {
811
+ closeLlm();
721
812
  // Terminate the SDK query on every exit path. On normal completion the
722
813
  // query has already finished and this is a no-op; on an early `break`
723
814
  // (consumer cancelled) or a throw it is the only thing that stops the
@@ -792,8 +883,30 @@ function buildChildEnv() {
792
883
  continue;
793
884
  env[key] = value;
794
885
  }
886
+ // The claude.ai connectors come from the account login, not from settings.
887
+ // This turns them off in the child.
888
+ env.ENABLE_CLAUDEAI_MCP_SERVERS = "false";
795
889
  return env;
796
890
  }
891
+ /**
892
+ * The built-ins one loop turn keeps: those that replace an offered NodeTool
893
+ * tool, the web pair when the caller offered any tool, and `Skill` when a
894
+ * skills plugin is loaded.
895
+ */
896
+ function turnBuiltins(replaced, toolsOffered, hasSkillsPlugin) {
897
+ const builtins = new Set();
898
+ for (const name of replaced) {
899
+ const builtin = SDK_NATIVE_TOOL_REPLACEMENTS.get(name);
900
+ if (builtin)
901
+ builtins.add(builtin);
902
+ }
903
+ if (toolsOffered)
904
+ for (const name of SDK_WEB_TOOLS)
905
+ builtins.add(name);
906
+ if (hasSkillsPlugin)
907
+ builtins.add("Skill");
908
+ return [...builtins];
909
+ }
797
910
  /**
798
911
  * A DB skill name that is safe to use as a filesystem directory. The DB
799
912
  * validates names (lowercase `a-z0-9-`), but path safety is enforced here too:
@@ -1095,6 +1208,16 @@ function jsonPropToZod(prop) {
1095
1208
  }
1096
1209
  return desc ? zt.describe(desc) : zt;
1097
1210
  }
1211
+ /**
1212
+ * A refused Claude login, carrying status 401 so the provider layer classifies
1213
+ * it as a credential failure and the UI offers to sign in again.
1214
+ */
1215
+ function claudeAuthError(detail) {
1216
+ const message = detail.trim() || "The Claude login was refused";
1217
+ return Object.assign(new Error(`Claude sign-in failed (401): ${message}`), {
1218
+ status: 401
1219
+ });
1220
+ }
1098
1221
  /** Build a descriptive Error from a non-success `result` message. */
1099
1222
  function resultError(msg) {
1100
1223
  const parts = [`Claude Agent SDK query failed (${msg.subtype})`];
@@ -1138,9 +1261,14 @@ function extractSystemPrompt(messages) {
1138
1261
  * user input).
1139
1262
  */
1140
1263
  function buildResumeDelta(messages, checkpoint) {
1141
- return messages
1142
- .slice(checkpoint)
1143
- .filter((m) => m.role === "user")
1264
+ const delta = messages.slice(checkpoint).filter((m) => m.role === "user");
1265
+ if (hasImages(delta)) {
1266
+ return delta.flatMap((message, index) => [
1267
+ ...(index ? [{ type: "text", text: "\n\n" }] : []),
1268
+ ...promptBlocks(message.content)
1269
+ ]);
1270
+ }
1271
+ return delta
1144
1272
  .map((m) => textOf(m.content))
1145
1273
  .filter(Boolean)
1146
1274
  .join("\n\n");
@@ -1151,19 +1279,33 @@ function buildResumeDelta(messages, checkpoint) {
1151
1279
  * edited/branched conversation) we prime context ONCE with a single delimited
1152
1280
  * user message instead of rebuilding a `Human:/Assistant:` transcript — the SDK
1153
1281
  * cannot import external assistant turns, so this is deliberate context priming,
1154
- * not a faithful reconstruction. Only final assistant TEXT is included
1155
- * (thinking is stripped by {@link textOf}).
1282
+ * not a faithful reconstruction. Text and inline images are retained, while
1283
+ * thinking is stripped.
1156
1284
  */
1157
1285
  function buildFreshPrompt(messages) {
1158
1286
  const convo = messages.filter((m) => m.role !== "system");
1159
1287
  if (convo.length === 0)
1160
1288
  return "";
1161
1289
  if (convo.length === 1 && convo[0].role === "user") {
1162
- return textOf(convo[0].content);
1290
+ return hasImages(convo) ? promptBlocks(convo[0].content) : textOf(convo[0].content);
1163
1291
  }
1164
1292
  const last = convo[convo.length - 1];
1165
1293
  const newTurn = last.role === "user" ? textOf(last.content) : "";
1166
1294
  const prior = last.role === "user" ? convo.slice(0, -1) : convo;
1295
+ if (hasImages(convo)) {
1296
+ const blocks = [];
1297
+ if (prior.length) {
1298
+ blocks.push({ type: "text", text: "<conversation_so_far>\n" });
1299
+ for (const message of prior) {
1300
+ blocks.push({ type: "text", text: `${message.role === "assistant" ? "Assistant" : "User"}: ` }, ...promptBlocks(message.content), { type: "text", text: "\n\n" });
1301
+ }
1302
+ blocks.push({ type: "text", text: "</conversation_so_far>\n\n" });
1303
+ }
1304
+ if (last.role === "user") {
1305
+ blocks.push(...promptBlocks(last.content));
1306
+ }
1307
+ return blocks;
1308
+ }
1167
1309
  const transcript = prior
1168
1310
  .map((m) => {
1169
1311
  const text = textOf(m.content);
@@ -1178,4 +1320,44 @@ function buildFreshPrompt(messages) {
1178
1320
  : "";
1179
1321
  return [primed, newTurn].filter(Boolean).join("\n\n");
1180
1322
  }
1323
+ function hasImages(messages) {
1324
+ return messages.some((message) => Array.isArray(message.content) &&
1325
+ message.content.some((part) => part.type === "image_url"));
1326
+ }
1327
+ /** Images must already be inline. This boundary never fetches caller URLs. */
1328
+ function promptBlocks(content) {
1329
+ if (isString(content)) {
1330
+ return [{ type: "text", text: content }];
1331
+ }
1332
+ const blocks = [];
1333
+ for (const part of content ?? []) {
1334
+ if (part.type === "text") {
1335
+ blocks.push({ type: "text", text: part.text });
1336
+ }
1337
+ else if (part.type === "image_url") {
1338
+ const image = toMcpImageBlock(part.image);
1339
+ if (!image) {
1340
+ throw new Error("Claude Agent image messages require inline image data. Resolve the media reference before dispatch.");
1341
+ }
1342
+ const mime = image.mimeType;
1343
+ if (mime !== "image/png" && mime !== "image/jpeg" && mime !== "image/gif" && mime !== "image/webp") {
1344
+ throw new Error(`Claude Agent image messages do not support ${mime}. Convert the image before dispatch.`);
1345
+ }
1346
+ blocks.push({ type: "image", source: { type: "base64", media_type: mime, data: image.data } });
1347
+ }
1348
+ }
1349
+ return blocks;
1350
+ }
1351
+ function sdkPrompt(content) {
1352
+ if (isString(content)) {
1353
+ return content;
1354
+ }
1355
+ return (async function* () {
1356
+ yield {
1357
+ type: "user",
1358
+ parent_tool_use_id: null,
1359
+ message: { role: "user", content }
1360
+ };
1361
+ })();
1362
+ }
1181
1363
  //# sourceMappingURL=claude-agent-provider.js.map