@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.
- package/dist/.nodetool-build-stamp +1 -1
- package/dist/context.d.ts +31 -3
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +366 -158
- package/dist/context.js.map +1 -1
- package/dist/generation-registry.d.ts +8 -0
- package/dist/generation-registry.d.ts.map +1 -1
- package/dist/generation-registry.js +18 -0
- package/dist/generation-registry.js.map +1 -1
- package/dist/host-binaries.d.ts.map +1 -1
- package/dist/host-binaries.js +18 -10
- package/dist/host-binaries.js.map +1 -1
- package/dist/image-codec.d.ts +2 -0
- package/dist/image-codec.d.ts.map +1 -1
- package/dist/image-codec.js +23 -3
- package/dist/image-codec.js.map +1 -1
- package/dist/image-model-tasks.d.ts +15 -0
- package/dist/image-model-tasks.d.ts.map +1 -0
- package/dist/image-model-tasks.js +24 -0
- package/dist/image-model-tasks.js.map +1 -0
- package/dist/index.d.ts +14 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -2
- package/dist/index.js.map +1 -1
- package/dist/media-ref-bytes.d.ts +18 -2
- package/dist/media-ref-bytes.d.ts.map +1 -1
- package/dist/media-ref-bytes.js +26 -16
- package/dist/media-ref-bytes.js.map +1 -1
- package/dist/node-executor.d.ts +6 -0
- package/dist/node-executor.d.ts.map +1 -1
- package/dist/providers/aki-provider.d.ts +2 -0
- package/dist/providers/aki-provider.d.ts.map +1 -1
- package/dist/providers/aki-provider.js +6 -0
- package/dist/providers/aki-provider.js.map +1 -1
- package/dist/providers/atlascloud-provider.d.ts +2 -0
- package/dist/providers/atlascloud-provider.d.ts.map +1 -1
- package/dist/providers/atlascloud-provider.js +22 -0
- package/dist/providers/atlascloud-provider.js.map +1 -1
- package/dist/providers/base-provider.d.ts +36 -24
- package/dist/providers/base-provider.d.ts.map +1 -1
- package/dist/providers/base-provider.js +124 -148
- package/dist/providers/base-provider.js.map +1 -1
- package/dist/providers/claude-agent-provider.d.ts +6 -36
- package/dist/providers/claude-agent-provider.d.ts.map +1 -1
- package/dist/providers/claude-agent-provider.js +208 -26
- package/dist/providers/claude-agent-provider.js.map +1 -1
- package/dist/providers/codex-provider.d.ts +2 -0
- package/dist/providers/codex-provider.d.ts.map +1 -1
- package/dist/providers/codex-provider.js +15 -2
- package/dist/providers/codex-provider.js.map +1 -1
- package/dist/providers/cohere-provider.d.ts +2 -1
- package/dist/providers/cohere-provider.d.ts.map +1 -1
- package/dist/providers/cohere-provider.js +5 -0
- package/dist/providers/cohere-provider.js.map +1 -1
- package/dist/providers/core-tools.d.ts +2 -1
- package/dist/providers/core-tools.d.ts.map +1 -1
- package/dist/providers/core-tools.js +2 -1
- package/dist/providers/core-tools.js.map +1 -1
- package/dist/providers/credential-check.d.ts.map +1 -1
- package/dist/providers/credential-check.js +5 -0
- package/dist/providers/credential-check.js.map +1 -1
- package/dist/providers/custom-openai-provider.d.ts +2 -0
- package/dist/providers/custom-openai-provider.d.ts.map +1 -1
- package/dist/providers/custom-openai-provider.js +8 -0
- package/dist/providers/custom-openai-provider.js.map +1 -1
- package/dist/providers/dreamina-models.d.ts +5 -0
- package/dist/providers/dreamina-models.d.ts.map +1 -0
- package/dist/providers/dreamina-models.js +57 -0
- package/dist/providers/dreamina-models.js.map +1 -0
- package/dist/providers/dreamina-music.d.ts +52 -0
- package/dist/providers/dreamina-music.d.ts.map +1 -0
- package/dist/providers/dreamina-music.js +115 -0
- package/dist/providers/dreamina-music.js.map +1 -0
- package/dist/providers/dreamina-provider.d.ts +62 -0
- package/dist/providers/dreamina-provider.d.ts.map +1 -0
- package/dist/providers/dreamina-provider.js +790 -0
- package/dist/providers/dreamina-provider.js.map +1 -0
- package/dist/providers/elevenlabs-provider.d.ts +2 -1
- package/dist/providers/elevenlabs-provider.d.ts.map +1 -1
- package/dist/providers/elevenlabs-provider.js +5 -0
- package/dist/providers/elevenlabs-provider.js.map +1 -1
- package/dist/providers/evolink-provider.d.ts +2 -0
- package/dist/providers/evolink-provider.d.ts.map +1 -1
- package/dist/providers/evolink-provider.js +8 -0
- package/dist/providers/evolink-provider.js.map +1 -1
- package/dist/providers/fake-provider.d.ts +2 -1
- package/dist/providers/fake-provider.d.ts.map +1 -1
- package/dist/providers/fake-provider.js +10 -0
- package/dist/providers/fake-provider.js.map +1 -1
- package/dist/providers/fal-provider.d.ts +2 -1
- package/dist/providers/fal-provider.d.ts.map +1 -1
- package/dist/providers/fal-provider.js +27 -0
- package/dist/providers/fal-provider.js.map +1 -1
- package/dist/providers/gemini-provider.d.ts +2 -1
- package/dist/providers/gemini-provider.d.ts.map +1 -1
- package/dist/providers/gemini-provider.js +15 -0
- package/dist/providers/gemini-provider.js.map +1 -1
- package/dist/providers/higgsfield-provider.d.ts +2 -1
- package/dist/providers/higgsfield-provider.d.ts.map +1 -1
- package/dist/providers/higgsfield-provider.js +12 -0
- package/dist/providers/higgsfield-provider.js.map +1 -1
- package/dist/providers/huggingface-provider.d.ts +2 -1
- package/dist/providers/huggingface-provider.d.ts.map +1 -1
- package/dist/providers/huggingface-provider.js +10 -0
- package/dist/providers/huggingface-provider.js.map +1 -1
- package/dist/providers/index.d.ts +5 -2
- package/dist/providers/index.d.ts.map +1 -1
- package/dist/providers/index.js +13 -2
- package/dist/providers/index.js.map +1 -1
- package/dist/providers/jina-provider.d.ts +2 -1
- package/dist/providers/jina-provider.d.ts.map +1 -1
- package/dist/providers/jina-provider.js +5 -0
- package/dist/providers/jina-provider.js.map +1 -1
- package/dist/providers/kie-provider.d.ts +2 -1
- package/dist/providers/kie-provider.d.ts.map +1 -1
- package/dist/providers/kie-provider.js +14 -0
- package/dist/providers/kie-provider.js.map +1 -1
- package/dist/providers/llama-provider.d.ts +4 -1
- package/dist/providers/llama-provider.d.ts.map +1 -1
- package/dist/providers/llama-provider.js +9 -3
- package/dist/providers/llama-provider.js.map +1 -1
- package/dist/providers/loop-tracing.d.ts +17 -0
- package/dist/providers/loop-tracing.d.ts.map +1 -0
- package/dist/providers/loop-tracing.js +132 -0
- package/dist/providers/loop-tracing.js.map +1 -0
- package/dist/providers/meshy-provider.d.ts +2 -1
- package/dist/providers/meshy-provider.d.ts.map +1 -1
- package/dist/providers/meshy-provider.js +6 -0
- package/dist/providers/meshy-provider.js.map +1 -1
- package/dist/providers/minimax-provider.d.ts +2 -0
- package/dist/providers/minimax-provider.d.ts.map +1 -1
- package/dist/providers/minimax-provider.js +11 -0
- package/dist/providers/minimax-provider.js.map +1 -1
- package/dist/providers/mistral-provider.d.ts +2 -0
- package/dist/providers/mistral-provider.d.ts.map +1 -1
- package/dist/providers/mistral-provider.js +5 -0
- package/dist/providers/mistral-provider.js.map +1 -1
- package/dist/providers/node-llama-cpp-provider.d.ts +2 -1
- package/dist/providers/node-llama-cpp-provider.d.ts.map +1 -1
- package/dist/providers/node-llama-cpp-provider.js +8 -3
- package/dist/providers/node-llama-cpp-provider.js.map +1 -1
- package/dist/providers/nodetool-provider.d.ts +1 -1
- package/dist/providers/nodetool-provider.d.ts.map +1 -1
- package/dist/providers/nodetool-provider.js +0 -2
- package/dist/providers/nodetool-provider.js.map +1 -1
- package/dist/providers/ollama-provider.d.ts +2 -1
- package/dist/providers/ollama-provider.d.ts.map +1 -1
- package/dist/providers/ollama-provider.js +5 -0
- package/dist/providers/ollama-provider.js.map +1 -1
- package/dist/providers/openai-provider.d.ts +10 -2
- package/dist/providers/openai-provider.d.ts.map +1 -1
- package/dist/providers/openai-provider.js +63 -16
- package/dist/providers/openai-provider.js.map +1 -1
- package/dist/providers/openrouter-provider.d.ts +52 -1
- package/dist/providers/openrouter-provider.d.ts.map +1 -1
- package/dist/providers/openrouter-provider.js +372 -11
- package/dist/providers/openrouter-provider.js.map +1 -1
- package/dist/providers/provider-error.d.ts.map +1 -1
- package/dist/providers/provider-error.js +7 -1
- package/dist/providers/provider-error.js.map +1 -1
- package/dist/providers/provider-generations.d.ts +2 -2
- package/dist/providers/provider-generations.js +2 -2
- package/dist/providers/provider-request-log.d.ts.map +1 -1
- package/dist/providers/provider-request-log.js +18 -7
- package/dist/providers/provider-request-log.js.map +1 -1
- package/dist/providers/python-provider.d.ts +6 -1
- package/dist/providers/python-provider.d.ts.map +1 -1
- package/dist/providers/python-provider.js +30 -11
- package/dist/providers/python-provider.js.map +1 -1
- package/dist/providers/replicate-provider.d.ts +2 -1
- package/dist/providers/replicate-provider.d.ts.map +1 -1
- package/dist/providers/replicate-provider.js +22 -0
- package/dist/providers/replicate-provider.js.map +1 -1
- package/dist/providers/requesty-provider.d.ts +30 -0
- package/dist/providers/requesty-provider.d.ts.map +1 -0
- package/dist/providers/requesty-provider.js +87 -0
- package/dist/providers/requesty-provider.js.map +1 -0
- package/dist/providers/reve-provider.d.ts +2 -1
- package/dist/providers/reve-provider.d.ts.map +1 -1
- package/dist/providers/reve-provider.js +6 -0
- package/dist/providers/reve-provider.js.map +1 -1
- package/dist/providers/rodin-provider.d.ts +2 -1
- package/dist/providers/rodin-provider.d.ts.map +1 -1
- package/dist/providers/rodin-provider.js +6 -0
- package/dist/providers/rodin-provider.js.map +1 -1
- package/dist/providers/together-operations.d.ts +27 -0
- package/dist/providers/together-operations.d.ts.map +1 -0
- package/dist/providers/together-operations.js +95 -0
- package/dist/providers/together-operations.js.map +1 -0
- package/dist/providers/together-provider.d.ts +5 -8
- package/dist/providers/together-provider.d.ts.map +1 -1
- package/dist/providers/together-provider.js +54 -159
- package/dist/providers/together-provider.js.map +1 -1
- package/dist/providers/topaz-provider.d.ts +2 -1
- package/dist/providers/topaz-provider.d.ts.map +1 -1
- package/dist/providers/topaz-provider.js +5 -0
- package/dist/providers/topaz-provider.js.map +1 -1
- package/dist/providers/types.d.ts +38 -0
- package/dist/providers/types.d.ts.map +1 -1
- package/dist/providers/types.js.map +1 -1
- package/dist/providers/useapi-provider.d.ts +2 -1
- package/dist/providers/useapi-provider.d.ts.map +1 -1
- package/dist/providers/useapi-provider.js +8 -0
- package/dist/providers/useapi-provider.js.map +1 -1
- package/dist/providers/vllm-provider.d.ts +2 -4
- package/dist/providers/vllm-provider.d.ts.map +1 -1
- package/dist/providers/vllm-provider.js +1 -5
- package/dist/providers/vllm-provider.js.map +1 -1
- package/dist/providers/voyage-provider.d.ts +2 -1
- package/dist/providers/voyage-provider.d.ts.map +1 -1
- package/dist/providers/voyage-provider.js +5 -0
- package/dist/providers/voyage-provider.js.map +1 -1
- package/dist/providers/xai-provider.d.ts +2 -0
- package/dist/providers/xai-provider.d.ts.map +1 -1
- package/dist/providers/xai-provider.js +8 -0
- package/dist/providers/xai-provider.js.map +1 -1
- package/dist/recommended-models.d.ts.map +1 -1
- package/dist/recommended-models.js +20 -0
- package/dist/recommended-models.js.map +1 -1
- package/dist/run-context.d.ts +20 -0
- package/dist/run-context.d.ts.map +1 -0
- package/dist/run-context.js +18 -0
- package/dist/run-context.js.map +1 -0
- package/dist/run-trace-context.d.ts +30 -0
- package/dist/run-trace-context.d.ts.map +1 -0
- package/dist/run-trace-context.js +80 -0
- package/dist/run-trace-context.js.map +1 -0
- package/dist/run-trace-processor.d.ts +65 -0
- package/dist/run-trace-processor.d.ts.map +1 -0
- package/dist/run-trace-processor.js +417 -0
- package/dist/run-trace-processor.js.map +1 -0
- package/dist/run-trace-serialization.d.ts +5 -0
- package/dist/run-trace-serialization.d.ts.map +1 -0
- package/dist/run-trace-serialization.js +113 -0
- package/dist/run-trace-serialization.js.map +1 -0
- package/dist/storage-workspace.d.ts +3 -0
- package/dist/storage-workspace.d.ts.map +1 -1
- package/dist/storage-workspace.js +32 -17
- package/dist/storage-workspace.js.map +1 -1
- package/dist/telemetry.d.ts +9 -3
- package/dist/telemetry.d.ts.map +1 -1
- package/dist/telemetry.js +53 -20
- package/dist/telemetry.js.map +1 -1
- package/dist/trace-exporters.d.ts +2 -29
- package/dist/trace-exporters.d.ts.map +1 -1
- package/dist/trace-exporters.js +10 -2
- package/dist/trace-exporters.js.map +1 -1
- package/dist/tracing-helpers.d.ts +15 -22
- package/dist/tracing-helpers.d.ts.map +1 -1
- package/dist/tracing-helpers.js +38 -6
- package/dist/tracing-helpers.js.map +1 -1
- package/dist/trim-video-window.d.ts +8 -0
- package/dist/trim-video-window.d.ts.map +1 -0
- package/dist/trim-video-window.js +50 -0
- package/dist/trim-video-window.js.map +1 -0
- 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
|
-
*
|
|
39
|
-
*
|
|
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":"
|
|
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
|
-
//
|
|
203
|
-
//
|
|
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 =
|
|
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(
|
|
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
|
|
470
|
-
//
|
|
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
|
-
|
|
490
|
-
|
|
491
|
-
|
|
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
|
-
|
|
1142
|
-
|
|
1143
|
-
.
|
|
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.
|
|
1155
|
-
*
|
|
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
|