@botbotgo/agent-harness 0.0.475 → 0.0.476
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -1234
- package/README.zh.md +3 -1191
- package/dist/acp.js +1 -1
- package/dist/api.js +1 -404
- package/dist/benchmark/checkpoint-resume-cost-benchmark.js +1 -55
- package/dist/benchmark/deepagent-local-model-benchmark.js +2 -35
- package/dist/benchmark/upstream-runtime-ab-benchmark.js +1 -179
- package/dist/cli/chat-interactive.js +25 -244
- package/dist/cli/chat-rendering.js +6 -100
- package/dist/cli/chat-stream.js +23 -512
- package/dist/cli/chat-ui.js +21 -199
- package/dist/cli/chat-workspace.js +2 -210
- package/dist/cli/main.js +21 -428
- package/dist/cli/managed-service-commands.js +9 -63
- package/dist/cli/managed-service.js +2 -137
- package/dist/cli/options-init-chat.js +1 -108
- package/dist/cli/options-runtime.js +1 -158
- package/dist/cli/options-serve.js +1 -282
- package/dist/cli/options.js +2 -19
- package/dist/cli/process-guards.js +1 -139
- package/dist/cli/request-tree.js +7 -296
- package/dist/cli/runtime-commands.js +12 -258
- package/dist/cli/runtime-output.js +16 -155
- package/dist/cli/server-commands.js +16 -270
- package/dist/cli/workspace.js +1 -67
- package/dist/cli.js +1 -7
- package/dist/client/acp.js +1 -1
- package/dist/client/in-process.js +1 -67
- package/dist/client/index.js +1 -2
- package/dist/client/types.js +0 -1
- package/dist/client.js +1 -1
- package/dist/contracts/core.js +1 -1
- package/dist/contracts/runtime-evaluation.js +0 -1
- package/dist/contracts/runtime-memory.js +0 -1
- package/dist/contracts/runtime-observability.js +0 -1
- package/dist/contracts/runtime-requests.js +0 -1
- package/dist/contracts/runtime-scheduling.js +0 -1
- package/dist/contracts/runtime.js +1 -27
- package/dist/contracts/types.js +1 -3
- package/dist/contracts/workspace.js +0 -1
- package/dist/flow/build-flow-graph.js +1 -50
- package/dist/flow/export-mermaid.js +2 -464
- package/dist/flow/export-sequence-mermaid.js +2 -325
- package/dist/flow/flow-graph-normalization.js +1 -214
- package/dist/flow/flow-graph-runtime.js +1 -107
- package/dist/flow/flow-graph-upstream.js +1 -494
- package/dist/flow/index.js +1 -3
- package/dist/flow/types.js +0 -1
- package/dist/index.js +1 -5
- package/dist/init-project.js +1 -1
- package/dist/knowledge/config.js +1 -32
- package/dist/knowledge/contracts.js +0 -1
- package/dist/knowledge/index.js +1 -2
- package/dist/knowledge/module.js +12 -909
- package/dist/knowledge/procedural/config.js +1 -125
- package/dist/knowledge/procedural/index.js +1 -2
- package/dist/knowledge/procedural/manager.js +9 -345
- package/dist/mcp.js +1 -2
- package/dist/package-version.d.ts +1 -1
- package/dist/package-version.js +1 -2
- package/dist/persistence/file-store.js +3 -758
- package/dist/persistence/sqlite-request-context-store.js +5 -54
- package/dist/persistence/sqlite-request-queue-store.js +10 -108
- package/dist/persistence/sqlite-runtime.js +1 -86
- package/dist/persistence/sqlite-store.js +62 -810
- package/dist/persistence/types.js +0 -1
- package/dist/projections/presentation.js +37 -206
- package/dist/projections/request-events.js +2 -502
- package/dist/projections/upstream-events.js +1 -201
- package/dist/protocol/a2a/http-discovery.js +1 -178
- package/dist/protocol/a2a/http-rpc.js +6 -622
- package/dist/protocol/a2a/http.js +1 -138
- package/dist/protocol/a2a/task-state.js +3 -317
- package/dist/protocol/acp/client.js +8 -294
- package/dist/protocol/acp/harness-client.js +1 -218
- package/dist/protocol/acp/http.js +5 -130
- package/dist/protocol/acp/server.js +1 -310
- package/dist/protocol/acp/stdio.js +2 -69
- package/dist/protocol/ag-ui/http.js +3 -378
- package/dist/protocol/mcp/server.js +1 -428
- package/dist/resource/backend/workspace-scoped-backend.js +1 -319
- package/dist/resource/isolation.js +1 -237
- package/dist/resource/mcp/tool-support.js +3 -296
- package/dist/resource/mcp-tool-support.js +1 -2
- package/dist/resource/providers/resource-provider.js +1 -215
- package/dist/resource/resource-impl.js +1 -3
- package/dist/resource/resource-types.js +0 -1
- package/dist/resource/resource.js +1 -1
- package/dist/resource/sources.js +1 -247
- package/dist/resource/tools/function-tool-resolver.js +2 -272
- package/dist/runtime/adapter/compat/deepagent-compat.js +1 -29
- package/dist/runtime/adapter/compat/openai-compatible.js +1 -55
- package/dist/runtime/adapter/direct-builtin-utility.js +2 -90
- package/dist/runtime/adapter/flow/execution-context.js +1 -71
- package/dist/runtime/adapter/flow/invocation-flow.js +8 -425
- package/dist/runtime/adapter/flow/invoke-runtime.js +1 -20
- package/dist/runtime/adapter/flow/stream-runtime.js +11 -1395
- package/dist/runtime/adapter/invocation-result.js +2 -473
- package/dist/runtime/adapter/local-tool-invocation.js +6 -638
- package/dist/runtime/adapter/middleware/context-hygiene.js +1 -83
- package/dist/runtime/adapter/middleware-assembly.js +5 -477
- package/dist/runtime/adapter/model/invocation-request.js +3 -183
- package/dist/runtime/adapter/model/message-assembly.js +1 -28
- package/dist/runtime/adapter/model/model-providers.js +23 -1115
- package/dist/runtime/adapter/model/prompted-json-tool-call-capture.js +1 -40
- package/dist/runtime/adapter/model/prompted-json-tool-policy.js +1 -22
- package/dist/runtime/adapter/resilience.js +1 -104
- package/dist/runtime/adapter/runtime-adapter-support.js +3 -141
- package/dist/runtime/adapter/runtime-shell.js +5 -166
- package/dist/runtime/adapter/stream-event-projection.js +2 -622
- package/dist/runtime/adapter/stream-text-consumption.js +1 -18
- package/dist/runtime/adapter/terminal-status.js +2 -67
- package/dist/runtime/adapter/tool/builtin-middleware-tools.js +6 -627
- package/dist/runtime/adapter/tool/declared-middleware.js +1 -154
- package/dist/runtime/adapter/tool/interrupt-policy.js +1 -34
- package/dist/runtime/adapter/tool/provider-tool.js +1 -25
- package/dist/runtime/adapter/tool/resolved-tool.js +1 -225
- package/dist/runtime/adapter/tool/tool-arguments.js +3 -486
- package/dist/runtime/adapter/tool/tool-hitl.js +1 -346
- package/dist/runtime/adapter/tool/tool-name-mapping.js +1 -128
- package/dist/runtime/adapter/tool/tool-output-artifacts.js +2 -88
- package/dist/runtime/adapter/tool/tool-replay.js +1 -37
- package/dist/runtime/adapter/tool-resolution.js +1 -86
- package/dist/runtime/adapter/upstream-configurable-keys.js +1 -2
- package/dist/runtime/agent-runtime-adapter.js +60 -2338
- package/dist/runtime/agent-runtime-assembly.js +7 -249
- package/dist/runtime/env/runtime-env.js +1 -62
- package/dist/runtime/harness/background-runtime.js +1 -8
- package/dist/runtime/harness/bindings.js +1 -58
- package/dist/runtime/harness/events/event-bus.js +1 -16
- package/dist/runtime/harness/events/event-sink.js +1 -61
- package/dist/runtime/harness/events/events.js +1 -80
- package/dist/runtime/harness/events/listener-runtime.js +1 -13
- package/dist/runtime/harness/events/runtime-event-operations.js +1 -9
- package/dist/runtime/harness/events/streaming.js +1 -100
- package/dist/runtime/harness/events/timeline.js +1 -52
- package/dist/runtime/harness/public-shapes.js +1 -186
- package/dist/runtime/harness/run/artifact-paths.js +1 -15
- package/dist/runtime/harness/run/governance.js +1 -295
- package/dist/runtime/harness/run/helpers.js +1 -71
- package/dist/runtime/harness/run/inspection.js +1 -409
- package/dist/runtime/harness/run/operator-overview.js +1 -80
- package/dist/runtime/harness/run/queue-diagnostics.js +1 -15
- package/dist/runtime/harness/run/recovery.js +1 -162
- package/dist/runtime/harness/run/resources.js +1 -60
- package/dist/runtime/harness/run/resume.js +1 -56
- package/dist/runtime/harness/run/routing.js +1 -48
- package/dist/runtime/harness/run/run-lifecycle.js +1 -66
- package/dist/runtime/harness/run/run-operations.js +1 -217
- package/dist/runtime/harness/run/run-queue.js +1 -43
- package/dist/runtime/harness/run/run-slot-acquisition.js +1 -157
- package/dist/runtime/harness/run/session-records.js +1 -97
- package/dist/runtime/harness/run/start-run.js +1 -120
- package/dist/runtime/harness/run/startup-runtime.js +1 -69
- package/dist/runtime/harness/run/stream-run.js +8 -1418
- package/dist/runtime/harness/run/surface-semantics.js +1 -79
- package/dist/runtime/harness/runtime-defaults.js +1 -39
- package/dist/runtime/harness/system/boundary-analysis.js +1 -234
- package/dist/runtime/harness/system/health-monitor.js +1 -258
- package/dist/runtime/harness/system/inventory.js +1 -129
- package/dist/runtime/harness/system/mem0-ingestion-sync.js +5 -345
- package/dist/runtime/harness/system/policy-engine.js +1 -175
- package/dist/runtime/harness/system/runtime-memory-candidates.js +4 -110
- package/dist/runtime/harness/system/runtime-memory-consolidation.js +1 -51
- package/dist/runtime/harness/system/runtime-memory-manager.js +10 -693
- package/dist/runtime/harness/system/runtime-memory-policy.js +1 -155
- package/dist/runtime/harness/system/runtime-memory-records.js +11 -577
- package/dist/runtime/harness/system/runtime-memory-sync.js +5 -206
- package/dist/runtime/harness/system/session-memory-sync.js +3 -113
- package/dist/runtime/harness/system/skill-requirements.js +1 -112
- package/dist/runtime/harness/system/store.js +9 -365
- package/dist/runtime/harness/tool-gateway/index.js +1 -2
- package/dist/runtime/harness/tool-gateway/policy.js +1 -45
- package/dist/runtime/harness/tool-gateway/validation.js +1 -176
- package/dist/runtime/harness/tool-schema.js +1 -3
- package/dist/runtime/harness.js +3 -1490
- package/dist/runtime/index.js +1 -3
- package/dist/runtime/layout/runtime-layout.js +1 -31
- package/dist/runtime/maintenance/checkpoint-maintenance.js +2 -178
- package/dist/runtime/maintenance/file-checkpoint-saver.js +1 -106
- package/dist/runtime/maintenance/runtime-record-maintenance.js +2 -169
- package/dist/runtime/maintenance/sqlite-checkpoint-saver.js +4 -289
- package/dist/runtime/parsing/output-content.js +10 -550
- package/dist/runtime/parsing/output-parsing.js +1 -4
- package/dist/runtime/parsing/output-recovery.js +3 -213
- package/dist/runtime/parsing/output-tool-args.js +7 -663
- package/dist/runtime/parsing/stream-event-parsing.js +3 -362
- package/dist/runtime/prompts/runtime-prompts.js +4 -73
- package/dist/runtime/scheduling/system-schedule-manager.js +11 -532
- package/dist/runtime/skills/skill-metadata.js +1 -197
- package/dist/runtime/startup-tracing.js +2 -37
- package/dist/runtime/support/compiled-binding.js +1 -290
- package/dist/runtime/support/embedding-models.js +1 -118
- package/dist/runtime/support/harness-support.js +5 -137
- package/dist/runtime/support/llamaindex.js +1 -108
- package/dist/runtime/support/runtime-adapter-options.js +1 -29
- package/dist/runtime/support/runtime-factories.js +1 -51
- package/dist/runtime/support/vector-stores.js +9 -270
- package/dist/scaffold/init-project.js +54 -233
- package/dist/tooling/extensions.js +1 -311
- package/dist/tooling/module-loader.js +1 -55
- package/dist/tools.js +1 -176
- package/dist/utils/agent-display.js +1 -18
- package/dist/utils/bundled-text.js +4 -39
- package/dist/utils/compiled-binding.js +1 -33
- package/dist/utils/fs.js +2 -45
- package/dist/utils/id.js +1 -9
- package/dist/utils/message-content.js +1 -30
- package/dist/utils/object.js +1 -6
- package/dist/workspace/agent-binding-compiler.js +3 -613
- package/dist/workspace/compile.js +1 -472
- package/dist/workspace/framework-contract-validation.js +2 -322
- package/dist/workspace/index.js +1 -1
- package/dist/workspace/object-loader-paths.js +1 -71
- package/dist/workspace/object-loader-readers.js +1 -187
- package/dist/workspace/object-loader.js +1 -754
- package/dist/workspace/resource-compilers.js +1 -374
- package/dist/workspace/support/agent-capabilities.js +1 -37
- package/dist/workspace/support/agent-execution-config.js +1 -44
- package/dist/workspace/support/discovery.js +1 -147
- package/dist/workspace/support/source-collectors.js +1 -30
- package/dist/workspace/support/source-protocols.js +2 -192
- package/dist/workspace/support/workspace-ref-utils.js +1 -362
- package/dist/workspace/tool-hydration.js +1 -280
- package/dist/workspace/validate.js +1 -99
- package/dist/workspace/yaml-object-reader.js +1 -285
- package/package.json +7 -3
|
@@ -1,1115 +1,23 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
const
|
|
24
|
-
"Available tools are listed below.",
|
|
25
|
-
"You must call exactly one available tool now.",
|
|
26
|
-
'Return only one JSON object with this exact shape: {"name":"tool_name","arguments":{"key":"value"}}',
|
|
27
|
-
"Do not add markdown, prose, explanations, analysis, or code fences.",
|
|
28
|
-
"Do not answer normally on this turn.",
|
|
29
|
-
].join("\n");
|
|
30
|
-
const PROMPTED_JSON_FINAL_TOOL_CALL_REMINDER = [
|
|
31
|
-
"Final tool-call rule:",
|
|
32
|
-
"If the correct next step is a tool call, return exactly one JSON object and no prose.",
|
|
33
|
-
"If a TOOL_RESULT is already present for the requested work, do not repeat that tool call; answer normally.",
|
|
34
|
-
'Shape: {"name":"tool_name","arguments":{}}',
|
|
35
|
-
].join("\n");
|
|
36
|
-
const NO_THINK_CONTROL_TOKEN = "/no_think";
|
|
37
|
-
function readModelText(value) {
|
|
38
|
-
if (typeof value === "string") {
|
|
39
|
-
return value.trim();
|
|
40
|
-
}
|
|
41
|
-
if (typeof value !== "object" || value === null) {
|
|
42
|
-
return "";
|
|
43
|
-
}
|
|
44
|
-
const typed = value;
|
|
45
|
-
if (typeof typed.content === "string") {
|
|
46
|
-
return typed.content.trim();
|
|
47
|
-
}
|
|
48
|
-
if (Array.isArray(typed.content)) {
|
|
49
|
-
return typed.content
|
|
50
|
-
.map((item) => typeof item === "string"
|
|
51
|
-
? item
|
|
52
|
-
: typeof item === "object" && item !== null && typeof item.text === "string"
|
|
53
|
-
? item.text
|
|
54
|
-
: "")
|
|
55
|
-
.join("")
|
|
56
|
-
.trim();
|
|
57
|
-
}
|
|
58
|
-
return "";
|
|
59
|
-
}
|
|
60
|
-
function readPromptContent(value) {
|
|
61
|
-
if (typeof value === "string") {
|
|
62
|
-
return value.trim();
|
|
63
|
-
}
|
|
64
|
-
if (Array.isArray(value)) {
|
|
65
|
-
return value.map((item) => readPromptContent(item)).filter(Boolean).join("\n").trim();
|
|
66
|
-
}
|
|
67
|
-
if (typeof value !== "object" || value === null) {
|
|
68
|
-
return "";
|
|
69
|
-
}
|
|
70
|
-
if (typeof value.content === "string" || Array.isArray(value.content)) {
|
|
71
|
-
return readModelText(value);
|
|
72
|
-
}
|
|
73
|
-
if (typeof value.text === "string") {
|
|
74
|
-
return String(value.text).trim();
|
|
75
|
-
}
|
|
76
|
-
return "";
|
|
77
|
-
}
|
|
78
|
-
function readMessageType(value) {
|
|
79
|
-
if (typeof value !== "object" || value === null) {
|
|
80
|
-
return undefined;
|
|
81
|
-
}
|
|
82
|
-
if (typeof value._getType === "function") {
|
|
83
|
-
return String(value._getType() ?? "");
|
|
84
|
-
}
|
|
85
|
-
if (typeof value.getType === "function") {
|
|
86
|
-
return String(value.getType() ?? "");
|
|
87
|
-
}
|
|
88
|
-
const ids = Array.isArray(value.id)
|
|
89
|
-
? (value.id).filter((item) => typeof item === "string")
|
|
90
|
-
: [];
|
|
91
|
-
const typeName = ids.at(-1);
|
|
92
|
-
if (typeName === "HumanMessage")
|
|
93
|
-
return "human";
|
|
94
|
-
if (typeName === "SystemMessage")
|
|
95
|
-
return "system";
|
|
96
|
-
if (typeName === "AIMessage")
|
|
97
|
-
return "ai";
|
|
98
|
-
if (typeName === "ToolMessage")
|
|
99
|
-
return "tool";
|
|
100
|
-
return undefined;
|
|
101
|
-
}
|
|
102
|
-
function mapMessageRole(value) {
|
|
103
|
-
const directRole = typeof value?.role === "string"
|
|
104
|
-
? String(value.role).trim().toLowerCase()
|
|
105
|
-
: undefined;
|
|
106
|
-
if (directRole) {
|
|
107
|
-
if (directRole === "assistant")
|
|
108
|
-
return "ASSISTANT";
|
|
109
|
-
if (directRole === "tool")
|
|
110
|
-
return "TOOL";
|
|
111
|
-
return directRole.toUpperCase();
|
|
112
|
-
}
|
|
113
|
-
const messageType = readMessageType(value);
|
|
114
|
-
if (messageType === "system")
|
|
115
|
-
return "SYSTEM";
|
|
116
|
-
if (messageType === "human")
|
|
117
|
-
return "USER";
|
|
118
|
-
if (messageType === "ai")
|
|
119
|
-
return "ASSISTANT";
|
|
120
|
-
if (messageType === "tool")
|
|
121
|
-
return "TOOL";
|
|
122
|
-
return "USER";
|
|
123
|
-
}
|
|
124
|
-
function readToolCalls(value) {
|
|
125
|
-
if (typeof value !== "object" || value === null) {
|
|
126
|
-
return [];
|
|
127
|
-
}
|
|
128
|
-
if (Array.isArray(value.tool_calls)) {
|
|
129
|
-
return value.tool_calls;
|
|
130
|
-
}
|
|
131
|
-
if (typeof value.kwargs === "object" && value.kwargs !== null) {
|
|
132
|
-
const toolCalls = value.kwargs.tool_calls;
|
|
133
|
-
return Array.isArray(toolCalls) ? toolCalls : [];
|
|
134
|
-
}
|
|
135
|
-
return [];
|
|
136
|
-
}
|
|
137
|
-
function formatStructuredMessage(value) {
|
|
138
|
-
const role = mapMessageRole(value);
|
|
139
|
-
const content = readPromptContent(value);
|
|
140
|
-
if (role === "ASSISTANT") {
|
|
141
|
-
const toolCalls = readToolCalls(value);
|
|
142
|
-
if (toolCalls.length > 0) {
|
|
143
|
-
return [
|
|
144
|
-
"ASSISTANT_TOOL_CALLS:",
|
|
145
|
-
JSON.stringify(toolCalls),
|
|
146
|
-
].join("\n");
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
if (role === "TOOL") {
|
|
150
|
-
const typed = value;
|
|
151
|
-
const name = typeof typed.name === "string"
|
|
152
|
-
? typed.name
|
|
153
|
-
: typeof typed.kwargs === "object" && typed.kwargs !== null && typeof typed.kwargs.name === "string"
|
|
154
|
-
? String(typed.kwargs.name)
|
|
155
|
-
: typeof typed.lc_kwargs === "object" && typed.lc_kwargs !== null && typeof typed.lc_kwargs.name === "string"
|
|
156
|
-
? String(typed.lc_kwargs.name)
|
|
157
|
-
: "";
|
|
158
|
-
const toolCallId = typeof typed.tool_call_id === "string"
|
|
159
|
-
? typed.tool_call_id
|
|
160
|
-
: typeof typed.kwargs === "object" && typed.kwargs !== null && typeof typed.kwargs.tool_call_id === "string"
|
|
161
|
-
? String(typed.kwargs.tool_call_id)
|
|
162
|
-
: typeof typed.lc_kwargs === "object" && typed.lc_kwargs !== null && typeof typed.lc_kwargs.tool_call_id === "string"
|
|
163
|
-
? String(typed.lc_kwargs.tool_call_id)
|
|
164
|
-
: "";
|
|
165
|
-
return [
|
|
166
|
-
"TOOL_RESULT:",
|
|
167
|
-
name ? `name=${name}` : "",
|
|
168
|
-
toolCallId ? `tool_call_id=${toolCallId}` : "",
|
|
169
|
-
content,
|
|
170
|
-
].filter(Boolean).join("\n");
|
|
171
|
-
}
|
|
172
|
-
return content ? `${role}:\n${content}` : "";
|
|
173
|
-
}
|
|
174
|
-
function readToolMessageMetadata(value) {
|
|
175
|
-
if (typeof value !== "object" || value === null) {
|
|
176
|
-
return {};
|
|
177
|
-
}
|
|
178
|
-
const typed = value;
|
|
179
|
-
const kwargs = typeof typed.kwargs === "object" && typed.kwargs !== null ? typed.kwargs : undefined;
|
|
180
|
-
const lcKwargs = typeof typed.lc_kwargs === "object" && typed.lc_kwargs !== null ? typed.lc_kwargs : undefined;
|
|
181
|
-
const name = typeof typed.name === "string"
|
|
182
|
-
? typed.name
|
|
183
|
-
: typeof kwargs?.name === "string"
|
|
184
|
-
? kwargs.name
|
|
185
|
-
: typeof lcKwargs?.name === "string"
|
|
186
|
-
? lcKwargs.name
|
|
187
|
-
: undefined;
|
|
188
|
-
const toolCallId = typeof typed.tool_call_id === "string"
|
|
189
|
-
? typed.tool_call_id
|
|
190
|
-
: typeof kwargs?.tool_call_id === "string"
|
|
191
|
-
? kwargs.tool_call_id
|
|
192
|
-
: typeof lcKwargs?.tool_call_id === "string"
|
|
193
|
-
? lcKwargs.tool_call_id
|
|
194
|
-
: undefined;
|
|
195
|
-
return { name, toolCallId };
|
|
196
|
-
}
|
|
197
|
-
function canonicalToolName(value) {
|
|
198
|
-
return value
|
|
199
|
-
.trim()
|
|
200
|
-
.toLowerCase()
|
|
201
|
-
.replace(/^tool_call_/, "")
|
|
202
|
-
.replace(/[^a-z0-9]+/g, "_")
|
|
203
|
-
.replace(/^_+|_+$/g, "");
|
|
204
|
-
}
|
|
205
|
-
function readToolCallId(value) {
|
|
206
|
-
if (typeof value !== "object" || value === null) {
|
|
207
|
-
return undefined;
|
|
208
|
-
}
|
|
209
|
-
const typed = value;
|
|
210
|
-
return typeof typed.id === "string"
|
|
211
|
-
? typed.id
|
|
212
|
-
: typeof typed.tool_call_id === "string"
|
|
213
|
-
? typed.tool_call_id
|
|
214
|
-
: undefined;
|
|
215
|
-
}
|
|
216
|
-
function buildToolResultNameLookup(messages) {
|
|
217
|
-
const namesByToolCallId = new Map();
|
|
218
|
-
for (const message of messages) {
|
|
219
|
-
if (mapMessageRole(message) !== "ASSISTANT") {
|
|
220
|
-
continue;
|
|
221
|
-
}
|
|
222
|
-
for (const toolCall of readToolCalls(message)) {
|
|
223
|
-
if (typeof toolCall !== "object" || toolCall === null) {
|
|
224
|
-
continue;
|
|
225
|
-
}
|
|
226
|
-
const id = readToolCallId(toolCall);
|
|
227
|
-
const name = typeof toolCall.name === "string"
|
|
228
|
-
? toolCall.name
|
|
229
|
-
: "";
|
|
230
|
-
if (id && name) {
|
|
231
|
-
namesByToolCallId.set(id, name);
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
return namesByToolCallId;
|
|
236
|
-
}
|
|
237
|
-
function hasPriorToolResultForToolName(input, toolName) {
|
|
238
|
-
if (!toolName) {
|
|
239
|
-
return false;
|
|
240
|
-
}
|
|
241
|
-
const expectedName = canonicalToolName(toolName);
|
|
242
|
-
if (Array.isArray(input)) {
|
|
243
|
-
const namesByToolCallId = buildToolResultNameLookup(input);
|
|
244
|
-
return input.some((message) => {
|
|
245
|
-
if (mapMessageRole(message) !== "TOOL") {
|
|
246
|
-
return false;
|
|
247
|
-
}
|
|
248
|
-
const metadata = readToolMessageMetadata(message);
|
|
249
|
-
const observedName = metadata.name ?? (metadata.toolCallId ? namesByToolCallId.get(metadata.toolCallId) : undefined);
|
|
250
|
-
return typeof observedName === "string" && canonicalToolName(observedName) === expectedName;
|
|
251
|
-
});
|
|
252
|
-
}
|
|
253
|
-
if (typeof input === "object" && input !== null && Array.isArray(input.messages)) {
|
|
254
|
-
return hasPriorToolResultForToolName(input.messages, toolName);
|
|
255
|
-
}
|
|
256
|
-
return false;
|
|
257
|
-
}
|
|
258
|
-
function hasAnyPriorToolResult(input) {
|
|
259
|
-
if (Array.isArray(input)) {
|
|
260
|
-
return input.some((message) => mapMessageRole(message) === "TOOL");
|
|
261
|
-
}
|
|
262
|
-
if (typeof input === "object" && input !== null && Array.isArray(input.messages)) {
|
|
263
|
-
return hasAnyPriorToolResult(input.messages);
|
|
264
|
-
}
|
|
265
|
-
return false;
|
|
266
|
-
}
|
|
267
|
-
function hasPriorNonPlanningToolCall(input) {
|
|
268
|
-
if (Array.isArray(input)) {
|
|
269
|
-
return input.some((message) => readToolCalls(message).some((toolCall) => {
|
|
270
|
-
if (typeof toolCall !== "object" || toolCall === null) {
|
|
271
|
-
return false;
|
|
272
|
-
}
|
|
273
|
-
const name = typeof toolCall.name === "string"
|
|
274
|
-
? toolCall.name
|
|
275
|
-
: "";
|
|
276
|
-
return name.length > 0 && !isTodoPlanningToolName(name);
|
|
277
|
-
}));
|
|
278
|
-
}
|
|
279
|
-
if (typeof input === "object" && input !== null && Array.isArray(input.messages)) {
|
|
280
|
-
return hasPriorNonPlanningToolCall(input.messages);
|
|
281
|
-
}
|
|
282
|
-
return false;
|
|
283
|
-
}
|
|
284
|
-
function readLatestToolResultContent(input) {
|
|
285
|
-
if (Array.isArray(input)) {
|
|
286
|
-
for (let index = input.length - 1; index >= 0; index -= 1) {
|
|
287
|
-
const message = input[index];
|
|
288
|
-
if (mapMessageRole(message) === "TOOL") {
|
|
289
|
-
const content = readPromptContent(message);
|
|
290
|
-
return content || null;
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
return null;
|
|
294
|
-
}
|
|
295
|
-
if (typeof input === "object" && input !== null && Array.isArray(input.messages)) {
|
|
296
|
-
return readLatestToolResultContent(input.messages);
|
|
297
|
-
}
|
|
298
|
-
return null;
|
|
299
|
-
}
|
|
300
|
-
function readBoundToolName(tool) {
|
|
301
|
-
return typeof tool === "object" && tool !== null && typeof tool.name === "string"
|
|
302
|
-
? tool.name.trim()
|
|
303
|
-
: "";
|
|
304
|
-
}
|
|
305
|
-
function readBoundToolDescription(tool) {
|
|
306
|
-
return typeof tool === "object" && tool !== null && typeof tool.description === "string"
|
|
307
|
-
? tool.description.trim()
|
|
308
|
-
: "";
|
|
309
|
-
}
|
|
310
|
-
function summarizeSchemaKeys(schema) {
|
|
311
|
-
const normalized = normalizeModelFacingToolSchema(schema);
|
|
312
|
-
const properties = typeof normalized.properties === "object" && normalized.properties !== null
|
|
313
|
-
? Object.keys(normalized.properties)
|
|
314
|
-
: [];
|
|
315
|
-
const required = Array.isArray(normalized.required)
|
|
316
|
-
? normalized.required.filter((item) => typeof item === "string")
|
|
317
|
-
: [];
|
|
318
|
-
if (properties.length === 0) {
|
|
319
|
-
return "{}";
|
|
320
|
-
}
|
|
321
|
-
return `{${properties.map((key) => required.includes(key) ? `${key}:required` : `${key}:optional`).join(", ")}}`;
|
|
322
|
-
}
|
|
323
|
-
function isTodoPlanningToolName(name) {
|
|
324
|
-
return name === "write_todos"
|
|
325
|
-
|| name === "read_todos"
|
|
326
|
-
|| name === "tool_call_write_todos"
|
|
327
|
-
|| name === "tool_call_read_todos"
|
|
328
|
-
|| name === "call_write_todos"
|
|
329
|
-
|| name === "call_read_todos";
|
|
330
|
-
}
|
|
331
|
-
function hasPriorNonPlanningToolResult(input, tools) {
|
|
332
|
-
const toolNames = tools
|
|
333
|
-
.map((tool) => readBoundToolName(tool))
|
|
334
|
-
.filter((name) => name && !isTodoPlanningToolName(name));
|
|
335
|
-
return toolNames.some((name) => hasPriorToolResultForToolName(input, name));
|
|
336
|
-
}
|
|
337
|
-
function hasPriorPlanningToolResult(input) {
|
|
338
|
-
return hasPriorToolResultForToolName(input, "write_todos")
|
|
339
|
-
|| hasPriorToolResultForToolName(input, "tool_call_write_todos")
|
|
340
|
-
|| hasPriorToolResultForToolName(input, "call_write_todos")
|
|
341
|
-
|| hasPriorToolResultForToolName(input, "read_todos")
|
|
342
|
-
|| hasPriorToolResultForToolName(input, "tool_call_read_todos")
|
|
343
|
-
|| hasPriorToolResultForToolName(input, "call_read_todos");
|
|
344
|
-
}
|
|
345
|
-
function shouldLimitToolsToPlanning(input, boundTools) {
|
|
346
|
-
return readPromptedJsonToolPolicy(input) === "planning"
|
|
347
|
-
&& !hasPriorToolResultForToolName(input, "write_todos")
|
|
348
|
-
&& !hasPriorToolResultForToolName(input, "tool_call_write_todos")
|
|
349
|
-
&& !hasPriorToolResultForToolName(input, "call_write_todos")
|
|
350
|
-
&& !hasPriorNonPlanningToolResult(input, boundTools);
|
|
351
|
-
}
|
|
352
|
-
function selectPlanningToolsForTurn(input, boundTools) {
|
|
353
|
-
if (!shouldLimitToolsToPlanning(input, boundTools)) {
|
|
354
|
-
return boundTools;
|
|
355
|
-
}
|
|
356
|
-
const planningTools = boundTools.filter((tool) => isTodoPlanningToolName(readBoundToolName(tool)));
|
|
357
|
-
return planningTools.length > 0 ? planningTools : boundTools;
|
|
358
|
-
}
|
|
359
|
-
function shouldLimitToolsToNonPlanningEvidence(input, boundTools) {
|
|
360
|
-
return (hasPriorPlanningToolResult(input) || readPromptedJsonToolPolicy(input) === "nonPlanningEvidence")
|
|
361
|
-
&& !hasPriorNonPlanningToolResult(input, boundTools);
|
|
362
|
-
}
|
|
363
|
-
function selectNonPlanningToolsForTurn(boundTools) {
|
|
364
|
-
const nonPlanningTools = boundTools.filter((tool) => {
|
|
365
|
-
const name = readBoundToolName(tool);
|
|
366
|
-
return name.length > 0 && !isTodoPlanningToolName(name);
|
|
367
|
-
});
|
|
368
|
-
return nonPlanningTools.length > 0 ? nonPlanningTools : boundTools;
|
|
369
|
-
}
|
|
370
|
-
function isAllowedPromptedJsonToolCall(toolName, effectiveBoundTools) {
|
|
371
|
-
const allowedToolNames = new Set(effectiveBoundTools.map((tool) => readBoundToolName(tool)).filter(Boolean));
|
|
372
|
-
return allowedToolNames.has(toolName);
|
|
373
|
-
}
|
|
374
|
-
function normalizeReadFileToolContent(name, content) {
|
|
375
|
-
if (name !== "read_file") {
|
|
376
|
-
return content;
|
|
377
|
-
}
|
|
378
|
-
const lines = content.split("\n");
|
|
379
|
-
const nonEmptyLines = lines.filter((line) => line.trim().length > 0);
|
|
380
|
-
if (nonEmptyLines.length === 0 || !nonEmptyLines.every((line) => /^\d+\t/.test(line))) {
|
|
381
|
-
return content;
|
|
382
|
-
}
|
|
383
|
-
return lines.map((line) => line.replace(/^\d+\t/, "")).join("\n");
|
|
384
|
-
}
|
|
385
|
-
function normalizeProviderFacingToolMessage(message) {
|
|
386
|
-
if (mapMessageRole(message) !== "TOOL") {
|
|
387
|
-
return message;
|
|
388
|
-
}
|
|
389
|
-
if (typeof message !== "object" || message === null) {
|
|
390
|
-
return message;
|
|
391
|
-
}
|
|
392
|
-
const { name, toolCallId } = readToolMessageMetadata(message);
|
|
393
|
-
const normalizedContent = normalizeReadFileToolContent(name, readPromptContent(message));
|
|
394
|
-
const messageType = readMessageType(message);
|
|
395
|
-
if (messageType === "tool" && toolCallId) {
|
|
396
|
-
return new ToolMessage({
|
|
397
|
-
...(name ? { name } : {}),
|
|
398
|
-
tool_call_id: toolCallId,
|
|
399
|
-
content: normalizedContent,
|
|
400
|
-
});
|
|
401
|
-
}
|
|
402
|
-
return {
|
|
403
|
-
...message,
|
|
404
|
-
content: normalizedContent,
|
|
405
|
-
};
|
|
406
|
-
}
|
|
407
|
-
function normalizeProviderFacingInput(input) {
|
|
408
|
-
if (Array.isArray(input)) {
|
|
409
|
-
return input.map((message) => normalizeProviderFacingToolMessage(message));
|
|
410
|
-
}
|
|
411
|
-
if (typeof input === "object" && input !== null && Array.isArray(input.messages)) {
|
|
412
|
-
return {
|
|
413
|
-
...input,
|
|
414
|
-
messages: normalizeProviderFacingInput(input.messages),
|
|
415
|
-
};
|
|
416
|
-
}
|
|
417
|
-
return input;
|
|
418
|
-
}
|
|
419
|
-
function createProviderToolMessageCompatModel(model, boundTools = []) {
|
|
420
|
-
const resolveTargetForTurn = (input) => {
|
|
421
|
-
if (boundTools.length === 0 || typeof model.bindTools !== "function") {
|
|
422
|
-
return model;
|
|
423
|
-
}
|
|
424
|
-
const effectiveBoundTools = selectPlanningToolsForTurn(input, boundTools);
|
|
425
|
-
return model.bindTools.call(model, effectiveBoundTools);
|
|
426
|
-
};
|
|
427
|
-
return new Proxy(model, {
|
|
428
|
-
has(target, prop) {
|
|
429
|
-
if (prop === "bindTools" || prop === "invoke" || prop === "stream" || prop === "streamEvents" || prop === "withConfig") {
|
|
430
|
-
return true;
|
|
431
|
-
}
|
|
432
|
-
return prop in target;
|
|
433
|
-
},
|
|
434
|
-
get(target, prop, receiver) {
|
|
435
|
-
if (prop === "bindTools") {
|
|
436
|
-
return (tools) => createProviderToolMessageCompatModel(target, tools);
|
|
437
|
-
}
|
|
438
|
-
if (prop === "invoke") {
|
|
439
|
-
return (input, config) => {
|
|
440
|
-
const effectiveTarget = resolveTargetForTurn(input);
|
|
441
|
-
return effectiveTarget.invoke.call(effectiveTarget, normalizeProviderFacingInput(input), config);
|
|
442
|
-
};
|
|
443
|
-
}
|
|
444
|
-
if (prop === "stream") {
|
|
445
|
-
return (input, config) => {
|
|
446
|
-
const effectiveTarget = resolveTargetForTurn(input);
|
|
447
|
-
return effectiveTarget.stream.call(effectiveTarget, normalizeProviderFacingInput(input), config);
|
|
448
|
-
};
|
|
449
|
-
}
|
|
450
|
-
if (prop === "streamEvents") {
|
|
451
|
-
return (input, config) => {
|
|
452
|
-
const effectiveTarget = resolveTargetForTurn(input);
|
|
453
|
-
if (typeof effectiveTarget.streamEvents === "function") {
|
|
454
|
-
return effectiveTarget.streamEvents.call(effectiveTarget, normalizeProviderFacingInput(input), config);
|
|
455
|
-
}
|
|
456
|
-
return (async function* () {
|
|
457
|
-
const output = await effectiveTarget.invoke.call(effectiveTarget, normalizeProviderFacingInput(input), config);
|
|
458
|
-
yield {
|
|
459
|
-
event: "on_chat_model_end",
|
|
460
|
-
name: typeof effectiveTarget.constructor?.name === "string" ? effectiveTarget.constructor.name : "ChatModel",
|
|
461
|
-
data: { output },
|
|
462
|
-
};
|
|
463
|
-
})();
|
|
464
|
-
};
|
|
465
|
-
}
|
|
466
|
-
if (prop === "withConfig" && typeof target.withConfig === "function") {
|
|
467
|
-
return (config) => createProviderToolMessageCompatModel(target.withConfig.call(target, config));
|
|
468
|
-
}
|
|
469
|
-
const member = Reflect.get(target, prop, receiver);
|
|
470
|
-
return typeof member === "function" ? member.bind(target) : member;
|
|
471
|
-
},
|
|
472
|
-
});
|
|
473
|
-
}
|
|
474
|
-
function stringifyNodeLlamaCppInput(input) {
|
|
475
|
-
if (typeof input === "string") {
|
|
476
|
-
return input;
|
|
477
|
-
}
|
|
478
|
-
if (Array.isArray(input)) {
|
|
479
|
-
return input
|
|
480
|
-
.map((message) => formatStructuredMessage(message))
|
|
481
|
-
.filter(Boolean)
|
|
482
|
-
.join("\n\n")
|
|
483
|
-
.trim();
|
|
484
|
-
}
|
|
485
|
-
if (typeof input === "object" && input !== null && Array.isArray(input.messages)) {
|
|
486
|
-
return stringifyNodeLlamaCppInput(input.messages);
|
|
487
|
-
}
|
|
488
|
-
return readPromptContent(input);
|
|
489
|
-
}
|
|
490
|
-
function extractToolCallPayload(text) {
|
|
491
|
-
const trimmed = text.trim();
|
|
492
|
-
if (!trimmed) {
|
|
493
|
-
return null;
|
|
494
|
-
}
|
|
495
|
-
const direct = tryParseJson(trimmed);
|
|
496
|
-
if (direct) {
|
|
497
|
-
return direct;
|
|
498
|
-
}
|
|
499
|
-
const salvagedToolCall = salvageJsonToolCalls(trimmed)[0];
|
|
500
|
-
if (salvagedToolCall) {
|
|
501
|
-
return {
|
|
502
|
-
name: salvagedToolCall.name,
|
|
503
|
-
arguments: salvagedToolCall.args,
|
|
504
|
-
};
|
|
505
|
-
}
|
|
506
|
-
const firstJsonObject = extractFirstJsonObjectPayload(trimmed);
|
|
507
|
-
if (firstJsonObject) {
|
|
508
|
-
return firstJsonObject;
|
|
509
|
-
}
|
|
510
|
-
const fenced = extractFencePayload(trimmed);
|
|
511
|
-
if (fenced) {
|
|
512
|
-
const parsed = tryParseJson(fenced);
|
|
513
|
-
if (parsed) {
|
|
514
|
-
return parsed;
|
|
515
|
-
}
|
|
516
|
-
}
|
|
517
|
-
const xml = extractTaggedContent(trimmed, "tool_call");
|
|
518
|
-
if (xml) {
|
|
519
|
-
const parsed = tryParseJson(xml);
|
|
520
|
-
if (parsed) {
|
|
521
|
-
return parsed;
|
|
522
|
-
}
|
|
523
|
-
}
|
|
524
|
-
const toolCallsXml = extractTaggedContent(trimmed, "tool_calls");
|
|
525
|
-
if (toolCallsXml) {
|
|
526
|
-
const parsed = tryParseJson(toolCallsXml);
|
|
527
|
-
if (parsed) {
|
|
528
|
-
return parsed;
|
|
529
|
-
}
|
|
530
|
-
}
|
|
531
|
-
const codeBlock = extractToolCodePayload(trimmed);
|
|
532
|
-
if (codeBlock) {
|
|
533
|
-
return codeBlock;
|
|
534
|
-
}
|
|
535
|
-
return null;
|
|
536
|
-
}
|
|
537
|
-
function extractFirstJsonObjectPayload(text) {
|
|
538
|
-
let start = -1;
|
|
539
|
-
let depth = 0;
|
|
540
|
-
let inString = false;
|
|
541
|
-
let escaped = false;
|
|
542
|
-
for (let index = 0; index < text.length; index += 1) {
|
|
543
|
-
const char = text[index];
|
|
544
|
-
if (start < 0) {
|
|
545
|
-
if (char === "{") {
|
|
546
|
-
start = index;
|
|
547
|
-
depth = 1;
|
|
548
|
-
}
|
|
549
|
-
continue;
|
|
550
|
-
}
|
|
551
|
-
if (escaped) {
|
|
552
|
-
escaped = false;
|
|
553
|
-
continue;
|
|
554
|
-
}
|
|
555
|
-
if (char === "\\") {
|
|
556
|
-
escaped = inString;
|
|
557
|
-
continue;
|
|
558
|
-
}
|
|
559
|
-
if (char === "\"") {
|
|
560
|
-
inString = !inString;
|
|
561
|
-
continue;
|
|
562
|
-
}
|
|
563
|
-
if (inString) {
|
|
564
|
-
continue;
|
|
565
|
-
}
|
|
566
|
-
if (char === "{") {
|
|
567
|
-
depth += 1;
|
|
568
|
-
continue;
|
|
569
|
-
}
|
|
570
|
-
if (char === "}") {
|
|
571
|
-
depth -= 1;
|
|
572
|
-
if (depth === 0) {
|
|
573
|
-
const parsed = tryParseJson(text.slice(start, index + 1));
|
|
574
|
-
if (parsed) {
|
|
575
|
-
return parsed;
|
|
576
|
-
}
|
|
577
|
-
start = -1;
|
|
578
|
-
}
|
|
579
|
-
}
|
|
580
|
-
}
|
|
581
|
-
return null;
|
|
582
|
-
}
|
|
583
|
-
function extractFencePayload(text) {
|
|
584
|
-
const start = text.indexOf("```");
|
|
585
|
-
if (start < 0) {
|
|
586
|
-
return null;
|
|
587
|
-
}
|
|
588
|
-
const contentStart = text.indexOf("\n", start + 3);
|
|
589
|
-
const bodyStart = contentStart >= 0 ? contentStart + 1 : start + 3;
|
|
590
|
-
const end = text.indexOf("```", bodyStart);
|
|
591
|
-
if (end < 0) {
|
|
592
|
-
return null;
|
|
593
|
-
}
|
|
594
|
-
return text.slice(bodyStart, end).trim();
|
|
595
|
-
}
|
|
596
|
-
function extractTaggedContent(text, tagName) {
|
|
597
|
-
const lowerText = text.toLowerCase();
|
|
598
|
-
const openTag = `<${tagName}>`;
|
|
599
|
-
const closeTag = `</${tagName}>`;
|
|
600
|
-
const start = lowerText.indexOf(openTag);
|
|
601
|
-
if (start < 0) {
|
|
602
|
-
return null;
|
|
603
|
-
}
|
|
604
|
-
const bodyStart = start + openTag.length;
|
|
605
|
-
const end = lowerText.indexOf(closeTag, bodyStart);
|
|
606
|
-
if (end < 0) {
|
|
607
|
-
return null;
|
|
608
|
-
}
|
|
609
|
-
return text.slice(bodyStart, end).trim();
|
|
610
|
-
}
|
|
611
|
-
function extractToolCodePayload(text) {
|
|
612
|
-
const name = extractTaggedContent(text, "tool_code");
|
|
613
|
-
if (!name) {
|
|
614
|
-
return null;
|
|
615
|
-
}
|
|
616
|
-
const rawArgs = extractTaggedContent(text, "tool_args");
|
|
617
|
-
const parsedArgs = rawArgs ? tryParseJson(rawArgs.trim()) : null;
|
|
618
|
-
const args = typeof parsedArgs === "object" && parsedArgs !== null && !Array.isArray(parsedArgs)
|
|
619
|
-
? parsedArgs
|
|
620
|
-
: Array.isArray(parsedArgs)
|
|
621
|
-
? { args: parsedArgs }
|
|
622
|
-
: {};
|
|
623
|
-
return { name, arguments: args };
|
|
624
|
-
}
|
|
625
|
-
function normalizeParsedToolCall(payload) {
|
|
626
|
-
if (typeof payload !== "object" || payload === null) {
|
|
627
|
-
return null;
|
|
628
|
-
}
|
|
629
|
-
if (Array.isArray(payload)) {
|
|
630
|
-
return normalizeParsedToolCall(payload[0]);
|
|
631
|
-
}
|
|
632
|
-
const typed = payload;
|
|
633
|
-
if (Array.isArray(typed.tool_calls)) {
|
|
634
|
-
return normalizeParsedToolCall(typed.tool_calls[0]);
|
|
635
|
-
}
|
|
636
|
-
const functionPayload = typeof typed.function === "object" && typed.function !== null ? typed.function : undefined;
|
|
637
|
-
const nameCandidate = typed.name
|
|
638
|
-
?? typed.tool_name
|
|
639
|
-
?? typed.tool
|
|
640
|
-
?? functionPayload?.name
|
|
641
|
-
?? (typeof typed.function === "string" ? typed.function : undefined);
|
|
642
|
-
const name = typeof nameCandidate === "string" ? nameCandidate.trim() : "";
|
|
643
|
-
if (!name) {
|
|
644
|
-
return null;
|
|
645
|
-
}
|
|
646
|
-
const argsCandidate = typed.arguments
|
|
647
|
-
?? typed.args
|
|
648
|
-
?? typed.parameters
|
|
649
|
-
?? typed.input
|
|
650
|
-
?? functionPayload?.arguments
|
|
651
|
-
?? functionPayload?.args
|
|
652
|
-
?? functionPayload?.parameters
|
|
653
|
-
?? {};
|
|
654
|
-
const args = Array.isArray(argsCandidate)
|
|
655
|
-
? { args: argsCandidate }
|
|
656
|
-
: salvageToolArgs(argsCandidate) ?? {};
|
|
657
|
-
return { name, args: normalizeKnownToolArgs(name, args) };
|
|
658
|
-
}
|
|
659
|
-
function buildInvalidPromptedJsonToolCall(toolCall) {
|
|
660
|
-
return new AIMessage({
|
|
661
|
-
content: "",
|
|
662
|
-
invalid_tool_calls: [{
|
|
663
|
-
id: `invalid-tool-${Math.random().toString(36).slice(2, 10)}`,
|
|
664
|
-
name: toolCall.name,
|
|
665
|
-
args: JSON.stringify(toolCall.args),
|
|
666
|
-
error: `Prompted-json model requested unavailable tool: ${toolCall.name}`,
|
|
667
|
-
type: "invalid_tool_call",
|
|
668
|
-
}],
|
|
669
|
-
});
|
|
670
|
-
}
|
|
671
|
-
function buildFallbackTodoContents() {
|
|
672
|
-
return [
|
|
673
|
-
"Identify the concrete evidence tool required for this request",
|
|
674
|
-
"Run the selected non-planning evidence tool and inspect its result",
|
|
675
|
-
"Update TODO status from the observed evidence",
|
|
676
|
-
"Return the final answer grounded in tool output",
|
|
677
|
-
];
|
|
678
|
-
}
|
|
679
|
-
function buildFallbackPlanningToolCall(input, planningTools, rawText) {
|
|
680
|
-
void input;
|
|
681
|
-
void rawText;
|
|
682
|
-
const toolName = planningTools.map((tool) => readBoundToolName(tool)).find((name) => name === "write_todos" || name === "tool_call_write_todos" || name === "call_write_todos");
|
|
683
|
-
if (!toolName) {
|
|
684
|
-
return null;
|
|
685
|
-
}
|
|
686
|
-
const todos = buildFallbackTodoContents().map((content, index) => ({
|
|
687
|
-
content,
|
|
688
|
-
status: index === 0 ? "in_progress" : "pending",
|
|
689
|
-
}));
|
|
690
|
-
return new AIMessage({
|
|
691
|
-
content: "",
|
|
692
|
-
tool_calls: [{
|
|
693
|
-
id: `tool-${Math.random().toString(36).slice(2, 10)}`,
|
|
694
|
-
name: toolName,
|
|
695
|
-
args: { todos },
|
|
696
|
-
type: "tool_call",
|
|
697
|
-
}],
|
|
698
|
-
});
|
|
699
|
-
}
|
|
700
|
-
function buildFallbackTodoCompletionToolCall(input, tools) {
|
|
701
|
-
const prompt = stringifyNodeLlamaCppInput(input);
|
|
702
|
-
if (/TODO completed:|\[x\]/i.test(prompt)) {
|
|
703
|
-
return null;
|
|
704
|
-
}
|
|
705
|
-
const planningToolName = tools.map((tool) => readBoundToolName(tool)).find((name) => name === "write_todos" || name === "tool_call_write_todos" || name === "call_write_todos");
|
|
706
|
-
if (!planningToolName) {
|
|
707
|
-
return null;
|
|
708
|
-
}
|
|
709
|
-
if (!hasPriorNonPlanningToolResult(input, tools)) {
|
|
710
|
-
return null;
|
|
711
|
-
}
|
|
712
|
-
const todos = buildFallbackTodoContents().map((content) => ({
|
|
713
|
-
content,
|
|
714
|
-
status: "completed",
|
|
715
|
-
}));
|
|
716
|
-
return new AIMessage({
|
|
717
|
-
content: "",
|
|
718
|
-
tool_calls: [{
|
|
719
|
-
id: `fallback-complete-${Math.random().toString(36).slice(2, 10)}`,
|
|
720
|
-
name: planningToolName,
|
|
721
|
-
args: { todos },
|
|
722
|
-
type: "tool_call",
|
|
723
|
-
}],
|
|
724
|
-
});
|
|
725
|
-
}
|
|
726
|
-
function parsedToolCallCompletesTodoPlan(toolCall) {
|
|
727
|
-
if (!isTodoPlanningToolName(toolCall.name)) {
|
|
728
|
-
return false;
|
|
729
|
-
}
|
|
730
|
-
const todos = toolCall.args.todos;
|
|
731
|
-
if (!Array.isArray(todos) || todos.length === 0) {
|
|
732
|
-
return false;
|
|
733
|
-
}
|
|
734
|
-
return todos.every((todo) => typeof todo === "object"
|
|
735
|
-
&& todo !== null
|
|
736
|
-
&& todo.status === "completed");
|
|
737
|
-
}
|
|
738
|
-
function normalizeInitialTodoPlanToolCall(toolCall) {
|
|
739
|
-
if (!parsedToolCallCompletesTodoPlan(toolCall)) {
|
|
740
|
-
return toolCall;
|
|
741
|
-
}
|
|
742
|
-
const todos = toolCall.args.todos.map((todo, index) => typeof todo === "object" && todo !== null && !Array.isArray(todo)
|
|
743
|
-
? { ...todo, status: index === 0 ? "in_progress" : "pending" }
|
|
744
|
-
: todo);
|
|
745
|
-
return {
|
|
746
|
-
name: toolCall.name,
|
|
747
|
-
args: {
|
|
748
|
-
...toolCall.args,
|
|
749
|
-
todos,
|
|
750
|
-
},
|
|
751
|
-
};
|
|
752
|
-
}
|
|
753
|
-
function formatBoundToolInstruction(tool) {
|
|
754
|
-
if (typeof tool !== "object" || tool === null) {
|
|
755
|
-
return null;
|
|
756
|
-
}
|
|
757
|
-
const typed = tool;
|
|
758
|
-
const name = typeof typed.name === "string" ? typed.name.trim() : "";
|
|
759
|
-
if (!name) {
|
|
760
|
-
return null;
|
|
761
|
-
}
|
|
762
|
-
const description = typeof typed.description === "string" ? typed.description.trim() : "";
|
|
763
|
-
const schema = normalizeModelFacingToolSchema(typed);
|
|
764
|
-
return [
|
|
765
|
-
`Tool: ${name}`,
|
|
766
|
-
description ? `Description: ${description}` : "",
|
|
767
|
-
`Arguments JSON schema: ${JSON.stringify(schema)}`,
|
|
768
|
-
].filter(Boolean).join("\n");
|
|
769
|
-
}
|
|
770
|
-
function formatCompactBoundToolInstruction(tool) {
|
|
771
|
-
const name = readBoundToolName(tool);
|
|
772
|
-
if (!name) {
|
|
773
|
-
return null;
|
|
774
|
-
}
|
|
775
|
-
const description = readBoundToolDescription(tool).split(/\n/u)[0]?.trim() ?? "";
|
|
776
|
-
return [
|
|
777
|
-
`Tool: ${name}`,
|
|
778
|
-
description ? `Description: ${description}` : "",
|
|
779
|
-
`Arguments keys: ${summarizeSchemaKeys(tool)}`,
|
|
780
|
-
].filter(Boolean).join("\n");
|
|
781
|
-
}
|
|
782
|
-
function withPromptedJsonToolPrompt(input, tools, options = {}) {
|
|
783
|
-
const toolInstructions = tools.map((tool) => formatBoundToolInstruction(tool)).filter((value) => Boolean(value));
|
|
784
|
-
const compactToolInstructions = tools.map((tool) => formatCompactBoundToolInstruction(tool)).filter((value) => Boolean(value));
|
|
785
|
-
if (toolInstructions.length === 0) {
|
|
786
|
-
return stringifyNodeLlamaCppInput(input);
|
|
787
|
-
}
|
|
788
|
-
const forcedToolInstruction = options.forceToolCall === "planning"
|
|
789
|
-
? [
|
|
790
|
-
"Required planning tool call:",
|
|
791
|
-
"You must call write_todos now before any domain tool or final answer.",
|
|
792
|
-
"Return exactly one JSON object for write_todos with concrete todo items and statuses.",
|
|
793
|
-
"Do not write prose, markdown, analysis, or a plain-text plan.",
|
|
794
|
-
].join("\n")
|
|
795
|
-
: options.forceToolCall === "nonPlanningEvidence"
|
|
796
|
-
? [
|
|
797
|
-
"Required evidence tool call:",
|
|
798
|
-
"A todo board already exists. Your next action must be exactly one non-planning tool call chosen from the available tool descriptions and schemas.",
|
|
799
|
-
"Honor any structured workspace or runtime evidence-tool contract already supplied in this turn.",
|
|
800
|
-
"Do not choose tools by matching free-form request or TODO text.",
|
|
801
|
-
"Do not call write_todos or read_todos now.",
|
|
802
|
-
"Do not write prose, markdown, analysis, or a plain-text plan.",
|
|
803
|
-
].join("\n")
|
|
804
|
-
: "";
|
|
805
|
-
const baseToolInstruction = options.forceToolCall
|
|
806
|
-
? FORCED_NODE_LLAMA_CPP_TOOL_CALL_INSTRUCTION
|
|
807
|
-
: NODE_LLAMA_CPP_TOOL_CALL_INSTRUCTION;
|
|
808
|
-
const systemContent = [
|
|
809
|
-
baseToolInstruction,
|
|
810
|
-
forcedToolInstruction,
|
|
811
|
-
(options.forceToolCall ? compactToolInstructions : toolInstructions).join("\n\n"),
|
|
812
|
-
forcedToolInstruction,
|
|
813
|
-
].filter(Boolean).join("\n\n");
|
|
814
|
-
const prompt = stringifyNodeLlamaCppInput(input);
|
|
815
|
-
return [
|
|
816
|
-
options.suppressThinking ? NO_THINK_CONTROL_TOKEN : "",
|
|
817
|
-
systemContent,
|
|
818
|
-
forcedToolInstruction,
|
|
819
|
-
prompt,
|
|
820
|
-
PROMPTED_JSON_FINAL_TOOL_CALL_REMINDER,
|
|
821
|
-
].filter(Boolean).join("\n\n");
|
|
822
|
-
}
|
|
823
|
-
function debugPromptedJsonTurn(input) {
|
|
824
|
-
if (process.env.AGENT_HARNESS_PROMPTED_JSON_DEBUG !== "1") {
|
|
825
|
-
return;
|
|
826
|
-
}
|
|
827
|
-
const promptText = typeof input.prompt === "string" ? input.prompt : stringifyNodeLlamaCppInput(input.prompt);
|
|
828
|
-
console.error(JSON.stringify({
|
|
829
|
-
type: "prompted-json-turn",
|
|
830
|
-
forcePlanningToolCall: input.forcePlanningToolCall,
|
|
831
|
-
forceNonPlanningEvidenceToolCall: input.forceNonPlanningEvidenceToolCall,
|
|
832
|
-
effectiveToolNames: input.effectiveToolNames,
|
|
833
|
-
inputSummary: summarizePromptedJsonInput(input.rawInput),
|
|
834
|
-
promptHead: promptText.slice(0, 2000),
|
|
835
|
-
}));
|
|
836
|
-
}
|
|
837
|
-
function debugPromptedJsonResult(input) {
|
|
838
|
-
if (process.env.AGENT_HARNESS_PROMPTED_JSON_DEBUG !== "1") {
|
|
839
|
-
return;
|
|
840
|
-
}
|
|
841
|
-
console.error(JSON.stringify({
|
|
842
|
-
type: "prompted-json-result",
|
|
843
|
-
forcePlanningToolCall: input.forcePlanningToolCall,
|
|
844
|
-
forceNonPlanningEvidenceToolCall: input.forceNonPlanningEvidenceToolCall,
|
|
845
|
-
parsedToolName: input.parsedToolName ?? null,
|
|
846
|
-
textHead: input.text.slice(0, 2000),
|
|
847
|
-
}));
|
|
848
|
-
}
|
|
849
|
-
function summarizePromptedJsonInput(input) {
|
|
850
|
-
const messages = typeof input === "object" && input !== null && Array.isArray(input.messages)
|
|
851
|
-
? input.messages
|
|
852
|
-
: Array.isArray(input)
|
|
853
|
-
? input
|
|
854
|
-
: [];
|
|
855
|
-
return messages.slice(-8).map((message) => ({
|
|
856
|
-
role: mapMessageRole(message),
|
|
857
|
-
type: readMessageType(message),
|
|
858
|
-
name: readToolMessageMetadata(message).name,
|
|
859
|
-
toolCallNames: readToolCalls(message).map((toolCall) => typeof toolCall === "object" && toolCall !== null && typeof toolCall.name === "string"
|
|
860
|
-
? toolCall.name
|
|
861
|
-
: ""),
|
|
862
|
-
contentHead: readPromptContent(message).slice(0, 120),
|
|
863
|
-
}));
|
|
864
|
-
}
|
|
865
|
-
function createPromptedJsonToolBindableModel(model, boundTools = [], options = {}) {
|
|
866
|
-
return new Proxy(model, {
|
|
867
|
-
has(target, prop) {
|
|
868
|
-
if (prop === "bindTools" || prop === "invoke" || prop === "stream" || prop === "streamEvents" || prop === "withConfig") {
|
|
869
|
-
return true;
|
|
870
|
-
}
|
|
871
|
-
return prop in target;
|
|
872
|
-
},
|
|
873
|
-
get(target, prop, receiver) {
|
|
874
|
-
if (prop === "bindTools") {
|
|
875
|
-
return (tools) => createPromptedJsonToolBindableModel(target, tools, options);
|
|
876
|
-
}
|
|
877
|
-
if (prop === "invoke") {
|
|
878
|
-
return async (input, config) => {
|
|
879
|
-
const forcePlanningToolCall = shouldLimitToolsToPlanning(input, boundTools);
|
|
880
|
-
const forceNonPlanningEvidenceToolCall = !forcePlanningToolCall && shouldLimitToolsToNonPlanningEvidence(input, boundTools);
|
|
881
|
-
const effectiveBoundTools = forcePlanningToolCall
|
|
882
|
-
? selectPlanningToolsForTurn(input, boundTools)
|
|
883
|
-
: forceNonPlanningEvidenceToolCall
|
|
884
|
-
? selectNonPlanningToolsForTurn(boundTools)
|
|
885
|
-
: boundTools;
|
|
886
|
-
if (options.settleCompletedToolResults === true
|
|
887
|
-
&& !forcePlanningToolCall
|
|
888
|
-
&& effectiveBoundTools.length > 0
|
|
889
|
-
&& hasAnyPriorToolResult(input)
|
|
890
|
-
&& hasPriorNonPlanningToolCall(input)) {
|
|
891
|
-
return new AIMessage({
|
|
892
|
-
content: readLatestToolResultContent(input) ?? "",
|
|
893
|
-
});
|
|
894
|
-
}
|
|
895
|
-
const promptedInput = effectiveBoundTools.length > 0
|
|
896
|
-
? withPromptedJsonToolPrompt(input, effectiveBoundTools, {
|
|
897
|
-
...options,
|
|
898
|
-
forceToolCall: forcePlanningToolCall
|
|
899
|
-
? "planning"
|
|
900
|
-
: forceNonPlanningEvidenceToolCall
|
|
901
|
-
? "nonPlanningEvidence"
|
|
902
|
-
: undefined,
|
|
903
|
-
})
|
|
904
|
-
: input;
|
|
905
|
-
debugPromptedJsonTurn({
|
|
906
|
-
forcePlanningToolCall,
|
|
907
|
-
forceNonPlanningEvidenceToolCall,
|
|
908
|
-
effectiveToolNames: effectiveBoundTools.map(readBoundToolName).filter(Boolean),
|
|
909
|
-
rawInput: input,
|
|
910
|
-
prompt: promptedInput,
|
|
911
|
-
});
|
|
912
|
-
const rawResult = await target.invoke(promptedInput, config);
|
|
913
|
-
if (effectiveBoundTools.length === 0) {
|
|
914
|
-
return rawResult;
|
|
915
|
-
}
|
|
916
|
-
const text = readModelText(rawResult);
|
|
917
|
-
const parsedToolCall = normalizeParsedToolCall(extractToolCallPayload(text));
|
|
918
|
-
debugPromptedJsonResult({
|
|
919
|
-
forcePlanningToolCall,
|
|
920
|
-
forceNonPlanningEvidenceToolCall,
|
|
921
|
-
text,
|
|
922
|
-
parsedToolName: parsedToolCall?.name,
|
|
923
|
-
});
|
|
924
|
-
if (!parsedToolCall) {
|
|
925
|
-
if (forcePlanningToolCall) {
|
|
926
|
-
const fallbackToolCall = buildFallbackPlanningToolCall(input, effectiveBoundTools, text);
|
|
927
|
-
if (fallbackToolCall) {
|
|
928
|
-
return fallbackToolCall;
|
|
929
|
-
}
|
|
930
|
-
}
|
|
931
|
-
else if (!forceNonPlanningEvidenceToolCall) {
|
|
932
|
-
const fallbackCompletionToolCall = buildFallbackTodoCompletionToolCall(input, effectiveBoundTools);
|
|
933
|
-
if (fallbackCompletionToolCall) {
|
|
934
|
-
return fallbackCompletionToolCall;
|
|
935
|
-
}
|
|
936
|
-
}
|
|
937
|
-
return rawResult;
|
|
938
|
-
}
|
|
939
|
-
if (!isAllowedPromptedJsonToolCall(parsedToolCall.name, effectiveBoundTools)) {
|
|
940
|
-
return buildInvalidPromptedJsonToolCall(parsedToolCall);
|
|
941
|
-
}
|
|
942
|
-
const effectiveParsedToolCall = forcePlanningToolCall
|
|
943
|
-
? normalizeInitialTodoPlanToolCall(parsedToolCall)
|
|
944
|
-
: parsedToolCall;
|
|
945
|
-
if (parsedToolCallCompletesTodoPlan(effectiveParsedToolCall) && !hasPriorNonPlanningToolResult(input, effectiveBoundTools)) {
|
|
946
|
-
return rawResult;
|
|
947
|
-
}
|
|
948
|
-
recordPromptedJsonToolCall({
|
|
949
|
-
name: effectiveParsedToolCall.name,
|
|
950
|
-
args: effectiveParsedToolCall.args,
|
|
951
|
-
rawArgsInput: text,
|
|
952
|
-
});
|
|
953
|
-
return new AIMessage({
|
|
954
|
-
content: "",
|
|
955
|
-
tool_calls: [{
|
|
956
|
-
id: `tool-${Math.random().toString(36).slice(2, 10)}`,
|
|
957
|
-
name: effectiveParsedToolCall.name,
|
|
958
|
-
args: effectiveParsedToolCall.args,
|
|
959
|
-
type: "tool_call",
|
|
960
|
-
}],
|
|
961
|
-
});
|
|
962
|
-
};
|
|
963
|
-
}
|
|
964
|
-
if (prop === "stream") {
|
|
965
|
-
return async (input, config) => {
|
|
966
|
-
const value = await receiver.invoke(input, config);
|
|
967
|
-
return (async function* () {
|
|
968
|
-
yield value;
|
|
969
|
-
})();
|
|
970
|
-
};
|
|
971
|
-
}
|
|
972
|
-
if (prop === "streamEvents") {
|
|
973
|
-
return async (input, config) => {
|
|
974
|
-
const value = await receiver.invoke(input, config);
|
|
975
|
-
return (async function* () {
|
|
976
|
-
yield {
|
|
977
|
-
event: "on_chat_model_end",
|
|
978
|
-
name: typeof target.constructor?.name === "string" ? target.constructor.name : "ChatModel",
|
|
979
|
-
data: { output: value },
|
|
980
|
-
};
|
|
981
|
-
})();
|
|
982
|
-
};
|
|
983
|
-
}
|
|
984
|
-
if (prop === "withConfig" && typeof target.withConfig === "function") {
|
|
985
|
-
return (config) => createPromptedJsonToolBindableModel(target.withConfig(config), boundTools, options);
|
|
986
|
-
}
|
|
987
|
-
const member = Reflect.get(target, prop, receiver);
|
|
988
|
-
return typeof member === "function" ? member.bind(target) : member;
|
|
989
|
-
},
|
|
990
|
-
getOwnPropertyDescriptor(target, prop) {
|
|
991
|
-
if (prop === "bindTools" || prop === "invoke" || prop === "stream" || prop === "streamEvents" || prop === "withConfig") {
|
|
992
|
-
return {
|
|
993
|
-
configurable: true,
|
|
994
|
-
enumerable: false,
|
|
995
|
-
writable: false,
|
|
996
|
-
value: this.get?.(target, prop, target),
|
|
997
|
-
};
|
|
998
|
-
}
|
|
999
|
-
return Reflect.getOwnPropertyDescriptor(target, prop);
|
|
1000
|
-
},
|
|
1001
|
-
});
|
|
1002
|
-
}
|
|
1003
|
-
function createPromptedJsonPlanningToolBindableModel(model, boundTools = [], options = {}) {
|
|
1004
|
-
return new Proxy(model, {
|
|
1005
|
-
has(target, prop) {
|
|
1006
|
-
if (prop === "bindTools" || prop === "invoke" || prop === "stream" || prop === "streamEvents" || prop === "withConfig") {
|
|
1007
|
-
return true;
|
|
1008
|
-
}
|
|
1009
|
-
return prop in target;
|
|
1010
|
-
},
|
|
1011
|
-
get(target, prop, receiver) {
|
|
1012
|
-
if (prop === "bindTools") {
|
|
1013
|
-
return (tools) => createPromptedJsonPlanningToolBindableModel(target, tools, options);
|
|
1014
|
-
}
|
|
1015
|
-
if (prop === "invoke") {
|
|
1016
|
-
return async (input, config) => {
|
|
1017
|
-
if (shouldLimitToolsToPlanning(input, boundTools)) {
|
|
1018
|
-
const prompted = createPromptedJsonToolBindableModel(target, boundTools, options);
|
|
1019
|
-
return prompted.invoke(input, config);
|
|
1020
|
-
}
|
|
1021
|
-
const nativeModel = typeof target.bindTools === "function"
|
|
1022
|
-
? target.bindTools(boundTools)
|
|
1023
|
-
: target;
|
|
1024
|
-
if (typeof nativeModel.invoke === "function") {
|
|
1025
|
-
return nativeModel.invoke(input, config);
|
|
1026
|
-
}
|
|
1027
|
-
return target.invoke(input, config);
|
|
1028
|
-
};
|
|
1029
|
-
}
|
|
1030
|
-
if (prop === "withConfig" && typeof target.withConfig === "function") {
|
|
1031
|
-
return (config) => createPromptedJsonPlanningToolBindableModel(target.withConfig(config), boundTools, options);
|
|
1032
|
-
}
|
|
1033
|
-
const member = Reflect.get(target, prop, receiver);
|
|
1034
|
-
return typeof member === "function" ? member.bind(target) : member;
|
|
1035
|
-
},
|
|
1036
|
-
});
|
|
1037
|
-
}
|
|
1038
|
-
function inferNodeLlamaCppModelPath(model) {
|
|
1039
|
-
const modelPath = typeof model.init?.modelPath === "string" ? model.init.modelPath.trim() : "";
|
|
1040
|
-
if (modelPath) {
|
|
1041
|
-
return modelPath;
|
|
1042
|
-
}
|
|
1043
|
-
return model.model.includes("/") || model.model.endsWith(".gguf") ? model.model : undefined;
|
|
1044
|
-
}
|
|
1045
|
-
async function createNodeLlamaCppModel(model) {
|
|
1046
|
-
const modelPath = inferNodeLlamaCppModelPath(model);
|
|
1047
|
-
if (!modelPath) {
|
|
1048
|
-
throw new Error(`Model ${model.id} with provider ${model.provider} must define a GGUF path via top-level modelPath or use model as the GGUF path.`);
|
|
1049
|
-
}
|
|
1050
|
-
try {
|
|
1051
|
-
const { ChatLlamaCpp } = await import("@langchain/community/chat_models/llama_cpp");
|
|
1052
|
-
return createPromptedJsonToolBindableModel(await ChatLlamaCpp.initialize({
|
|
1053
|
-
...model.init,
|
|
1054
|
-
modelPath,
|
|
1055
|
-
}));
|
|
1056
|
-
}
|
|
1057
|
-
catch (error) {
|
|
1058
|
-
throw new Error(`Failed to initialize ${model.provider} model ${model.id}. Install @langchain/community and node-llama-cpp in the application workspace and ensure the GGUF file exists at ${modelPath}.`, { cause: error });
|
|
1059
|
-
}
|
|
1060
|
-
}
|
|
1061
|
-
export async function createResolvedModel(model, modelResolver) {
|
|
1062
|
-
if (modelResolver) {
|
|
1063
|
-
return modelResolver(model.id);
|
|
1064
|
-
}
|
|
1065
|
-
if (model.provider === "ollama") {
|
|
1066
|
-
const { toolCallingMode, ...init } = model.init ?? {};
|
|
1067
|
-
const resolved = new ChatOllama({ model: model.model, ...init });
|
|
1068
|
-
if (toolCallingMode === "prompted-json") {
|
|
1069
|
-
return createPromptedJsonToolBindableModel(resolved, [], {
|
|
1070
|
-
settleCompletedToolResults: true,
|
|
1071
|
-
suppressThinking: init.think === false,
|
|
1072
|
-
});
|
|
1073
|
-
}
|
|
1074
|
-
if (toolCallingMode === "prompted-json-planning") {
|
|
1075
|
-
return createPromptedJsonPlanningToolBindableModel(resolved, [], {
|
|
1076
|
-
settleCompletedToolResults: true,
|
|
1077
|
-
suppressThinking: init.think === false,
|
|
1078
|
-
});
|
|
1079
|
-
}
|
|
1080
|
-
return createProviderToolMessageCompatModel(resolved);
|
|
1081
|
-
}
|
|
1082
|
-
if (model.provider === "openai-compatible") {
|
|
1083
|
-
const { toolCallingMode, ...init } = model.init ?? {};
|
|
1084
|
-
const resolved = new ChatOpenAI({
|
|
1085
|
-
model: model.model,
|
|
1086
|
-
...normalizeOpenAICompatibleInit(init),
|
|
1087
|
-
});
|
|
1088
|
-
if (toolCallingMode === "prompted-json") {
|
|
1089
|
-
return createPromptedJsonToolBindableModel(resolved, [], {
|
|
1090
|
-
settleCompletedToolResults: true,
|
|
1091
|
-
suppressThinking: true,
|
|
1092
|
-
});
|
|
1093
|
-
}
|
|
1094
|
-
if (toolCallingMode === "prompted-json-planning") {
|
|
1095
|
-
return createPromptedJsonPlanningToolBindableModel(resolved, [], {
|
|
1096
|
-
settleCompletedToolResults: true,
|
|
1097
|
-
suppressThinking: true,
|
|
1098
|
-
});
|
|
1099
|
-
}
|
|
1100
|
-
return createProviderToolMessageCompatModel(resolved);
|
|
1101
|
-
}
|
|
1102
|
-
if (model.provider === "openai") {
|
|
1103
|
-
return createProviderToolMessageCompatModel(new ChatOpenAI({ model: model.model, ...model.init }));
|
|
1104
|
-
}
|
|
1105
|
-
if (model.provider === "anthropic") {
|
|
1106
|
-
return createProviderToolMessageCompatModel(new ChatAnthropic({ model: model.model, ...model.init }));
|
|
1107
|
-
}
|
|
1108
|
-
if (model.provider === "google" || model.provider === "google-genai" || model.provider === "gemini") {
|
|
1109
|
-
return createProviderToolMessageCompatModel(new ChatGoogle({ model: model.model, ...model.init }));
|
|
1110
|
-
}
|
|
1111
|
-
if (model.provider === "node-llama-cpp" || model.provider === "llama-cpp") {
|
|
1112
|
-
return createNodeLlamaCppModel(model);
|
|
1113
|
-
}
|
|
1114
|
-
return initChatModel(model.model, { modelProvider: model.provider, ...model.init });
|
|
1115
|
-
}
|
|
1
|
+
import{ChatAnthropic as Y}from"@langchain/anthropic";import{ChatGoogle as W}from"@langchain/google";import{ToolMessage as X}from"@langchain/core/messages";import{ChatOllama as Q}from"@langchain/ollama";import{ChatOpenAI as J}from"@langchain/openai";import{AIMessage as C}from"langchain";import{initChatModel as V}from"langchain";import{salvageToolArgs as Z,tryParseJson as T}from"../../parsing/output-parsing.js";import{normalizeKnownToolArgs as ee,salvageJsonToolCalls as ne}from"../../parsing/output-tool-args.js";import{normalizeModelFacingToolSchema as $}from"../tool/resolved-tool.js";import{normalizeOpenAICompatibleInit as te}from"../compat/openai-compatible.js";import{recordPromptedJsonToolCall as oe}from"./prompted-json-tool-call-capture.js";import{readPromptedJsonToolPolicy as B}from"./prompted-json-tool-policy.js";const re=["Available tools are listed below.","If you need a tool, respond with only one JSON object.",'Use this exact shape: {"name":"tool_name","arguments":{"key":"value"}}',"Do not add markdown, prose, or code fences unless the output is wrapped inside <tool_call>...</tool_call>.","When the latest user message explicitly requests a tool call or provides a tool-call JSON object, call that tool instead of answering locally.","If the conversation already contains TOOL_RESULT for the requested work, answer from that result instead of repeating the same tool call.","If no tool is needed, answer normally."].join(`
|
|
2
|
+
`),le=["Available tools are listed below.","You must call exactly one available tool now.",'Return only one JSON object with this exact shape: {"name":"tool_name","arguments":{"key":"value"}}',"Do not add markdown, prose, explanations, analysis, or code fences.","Do not answer normally on this turn."].join(`
|
|
3
|
+
`),ie=["Final tool-call rule:","If the correct next step is a tool call, return exactly one JSON object and no prose.","If a TOOL_RESULT is already present for the requested work, do not repeat that tool call; answer normally.",'Shape: {"name":"tool_name","arguments":{}}'].join(`
|
|
4
|
+
`),se="/no_think";function D(e){if(typeof e=="string")return e.trim();if(typeof e!="object"||e===null)return"";const n=e;return typeof n.content=="string"?n.content.trim():Array.isArray(n.content)?n.content.map(o=>typeof o=="string"?o:typeof o=="object"&&o!==null&&typeof o.text=="string"?o.text:"").join("").trim():""}function _(e){return typeof e=="string"?e.trim():Array.isArray(e)?e.map(n=>_(n)).filter(Boolean).join(`
|
|
5
|
+
`).trim():typeof e!="object"||e===null?"":typeof e.content=="string"||Array.isArray(e.content)?D(e):typeof e.text=="string"?String(e.text).trim():""}function L(e){if(typeof e!="object"||e===null)return;if(typeof e._getType=="function")return String(e._getType()??"");if(typeof e.getType=="function")return String(e.getType()??"");const o=(Array.isArray(e.id)?e.id.filter(t=>typeof t=="string"):[]).at(-1);if(o==="HumanMessage")return"human";if(o==="SystemMessage")return"system";if(o==="AIMessage")return"ai";if(o==="ToolMessage")return"tool"}function g(e){const n=typeof e?.role=="string"?String(e.role).trim().toLowerCase():void 0;if(n)return n==="assistant"?"ASSISTANT":n==="tool"?"TOOL":n.toUpperCase();const o=L(e);return o==="system"?"SYSTEM":o==="human"?"USER":o==="ai"?"ASSISTANT":o==="tool"?"TOOL":"USER"}function S(e){if(typeof e!="object"||e===null)return[];if(Array.isArray(e.tool_calls))return e.tool_calls;if(typeof e.kwargs=="object"&&e.kwargs!==null){const n=e.kwargs.tool_calls;return Array.isArray(n)?n:[]}return[]}function ae(e){const n=g(e),o=_(e);if(n==="ASSISTANT"){const t=S(e);if(t.length>0)return["ASSISTANT_TOOL_CALLS:",JSON.stringify(t)].join(`
|
|
6
|
+
`)}if(n==="TOOL"){const t=e,r=typeof t.name=="string"?t.name:typeof t.kwargs=="object"&&t.kwargs!==null&&typeof t.kwargs.name=="string"?String(t.kwargs.name):typeof t.lc_kwargs=="object"&&t.lc_kwargs!==null&&typeof t.lc_kwargs.name=="string"?String(t.lc_kwargs.name):"",l=typeof t.tool_call_id=="string"?t.tool_call_id:typeof t.kwargs=="object"&&t.kwargs!==null&&typeof t.kwargs.tool_call_id=="string"?String(t.kwargs.tool_call_id):typeof t.lc_kwargs=="object"&&t.lc_kwargs!==null&&typeof t.lc_kwargs.tool_call_id=="string"?String(t.lc_kwargs.tool_call_id):"";return["TOOL_RESULT:",r?`name=${r}`:"",l?`tool_call_id=${l}`:"",o].filter(Boolean).join(`
|
|
7
|
+
`)}return o?`${n}:
|
|
8
|
+
${o}`:""}function R(e){if(typeof e!="object"||e===null)return{};const n=e,o=typeof n.kwargs=="object"&&n.kwargs!==null?n.kwargs:void 0,t=typeof n.lc_kwargs=="object"&&n.lc_kwargs!==null?n.lc_kwargs:void 0,r=typeof n.name=="string"?n.name:typeof o?.name=="string"?o.name:typeof t?.name=="string"?t.name:void 0,l=typeof n.tool_call_id=="string"?n.tool_call_id:typeof o?.tool_call_id=="string"?o.tool_call_id:typeof t?.tool_call_id=="string"?t.tool_call_id:void 0;return{name:r,toolCallId:l}}function F(e){return e.trim().toLowerCase().replace(/^tool_call_/,"").replace(/[^a-z0-9]+/g,"_").replace(/^_+|_+$/g,"")}function ce(e){if(typeof e!="object"||e===null)return;const n=e;return typeof n.id=="string"?n.id:typeof n.tool_call_id=="string"?n.tool_call_id:void 0}function fe(e){const n=new Map;for(const o of e)if(g(o)==="ASSISTANT")for(const t of S(o)){if(typeof t!="object"||t===null)continue;const r=ce(t),l=typeof t.name=="string"?t.name:"";r&&l&&n.set(r,l)}return n}function f(e,n){if(!n)return!1;const o=F(n);if(Array.isArray(e)){const t=fe(e);return e.some(r=>{if(g(r)!=="TOOL")return!1;const l=R(r),a=l.name??(l.toolCallId?t.get(l.toolCallId):void 0);return typeof a=="string"&&F(a)===o})}return typeof e=="object"&&e!==null&&Array.isArray(e.messages)?f(e.messages,n):!1}function z(e){return Array.isArray(e)?e.some(n=>g(n)==="TOOL"):typeof e=="object"&&e!==null&&Array.isArray(e.messages)?z(e.messages):!1}function U(e){return Array.isArray(e)?e.some(n=>S(n).some(o=>{if(typeof o!="object"||o===null)return!1;const t=typeof o.name=="string"?o.name:"";return t.length>0&&!b(t)})):typeof e=="object"&&e!==null&&Array.isArray(e.messages)?U(e.messages):!1}function q(e){if(Array.isArray(e)){for(let n=e.length-1;n>=0;n-=1){const o=e[n];if(g(o)==="TOOL")return _(o)||null}return null}return typeof e=="object"&&e!==null&&Array.isArray(e.messages)?q(e.messages):null}function m(e){return typeof e=="object"&&e!==null&&typeof e.name=="string"?e.name.trim():""}function ue(e){return typeof e=="object"&&e!==null&&typeof e.description=="string"?e.description.trim():""}function de(e){const n=$(e),o=typeof n.properties=="object"&&n.properties!==null?Object.keys(n.properties):[],t=Array.isArray(n.required)?n.required.filter(r=>typeof r=="string"):[];return o.length===0?"{}":`{${o.map(r=>t.includes(r)?`${r}:required`:`${r}:optional`).join(", ")}}`}function b(e){return e==="write_todos"||e==="read_todos"||e==="tool_call_write_todos"||e==="tool_call_read_todos"||e==="call_write_todos"||e==="call_read_todos"}function N(e,n){return n.map(t=>m(t)).filter(t=>t&&!b(t)).some(t=>f(e,t))}function me(e){return f(e,"write_todos")||f(e,"tool_call_write_todos")||f(e,"call_write_todos")||f(e,"read_todos")||f(e,"tool_call_read_todos")||f(e,"call_read_todos")}function E(e,n){return B(e)==="planning"&&!f(e,"write_todos")&&!f(e,"tool_call_write_todos")&&!f(e,"call_write_todos")&&!N(e,n)}function G(e,n){if(!E(e,n))return n;const o=n.filter(t=>b(m(t)));return o.length>0?o:n}function ge(e,n){return(me(e)||B(e)==="nonPlanningEvidence")&&!N(e,n)}function ye(e){const n=e.filter(o=>{const t=m(o);return t.length>0&&!b(t)});return n.length>0?n:e}function pe(e,n){return new Set(n.map(t=>m(t)).filter(Boolean)).has(e)}function Te(e,n){if(e!=="read_file")return n;const o=n.split(`
|
|
9
|
+
`),t=o.filter(r=>r.trim().length>0);return t.length===0||!t.every(r=>/^\d+\t/.test(r))?n:o.map(r=>r.replace(/^\d+\t/,"")).join(`
|
|
10
|
+
`)}function _e(e){if(g(e)!=="TOOL"||typeof e!="object"||e===null)return e;const{name:n,toolCallId:o}=R(e),t=Te(n,_(e));return L(e)==="tool"&&o?new X({...n?{name:n}:{},tool_call_id:o,content:t}):{...e,content:t}}function P(e){return Array.isArray(e)?e.map(n=>_e(n)):typeof e=="object"&&e!==null&&Array.isArray(e.messages)?{...e,messages:P(e.messages)}:e}function y(e,n=[]){const o=t=>{if(n.length===0||typeof e.bindTools!="function")return e;const r=G(t,n);return e.bindTools.call(e,r)};return new Proxy(e,{has(t,r){return r==="bindTools"||r==="invoke"||r==="stream"||r==="streamEvents"||r==="withConfig"?!0:r in t},get(t,r,l){if(r==="bindTools")return i=>y(t,i);if(r==="invoke")return(i,c)=>{const s=o(i);return s.invoke.call(s,P(i),c)};if(r==="stream")return(i,c)=>{const s=o(i);return s.stream.call(s,P(i),c)};if(r==="streamEvents")return(i,c)=>{const s=o(i);return typeof s.streamEvents=="function"?s.streamEvents.call(s,P(i),c):(async function*(){const d=await s.invoke.call(s,P(i),c);yield{event:"on_chat_model_end",name:typeof s.constructor?.name=="string"?s.constructor.name:"ChatModel",data:{output:d}}})()};if(r==="withConfig"&&typeof t.withConfig=="function")return i=>y(t.withConfig.call(t,i));const a=Reflect.get(t,r,l);return typeof a=="function"?a.bind(t):a}})}function O(e){return typeof e=="string"?e:Array.isArray(e)?e.map(n=>ae(n)).filter(Boolean).join(`
|
|
11
|
+
|
|
12
|
+
`).trim():typeof e=="object"&&e!==null&&Array.isArray(e.messages)?O(e.messages):_(e)}function we(e){const n=e.trim();if(!n)return null;const o=T(n);if(o)return o;const t=ne(n)[0];if(t)return{name:t.name,arguments:t.args};const r=he(n);if(r)return r;const l=Ae(n);if(l){const s=T(l);if(s)return s}const a=v(n,"tool_call");if(a){const s=T(a);if(s)return s}const i=v(n,"tool_calls");if(i){const s=T(i);if(s)return s}const c=Ce(n);return c||null}function he(e){let n=-1,o=0,t=!1,r=!1;for(let l=0;l<e.length;l+=1){const a=e[l];if(n<0){a==="{"&&(n=l,o=1);continue}if(r){r=!1;continue}if(a==="\\"){r=t;continue}if(a==='"'){t=!t;continue}if(!t){if(a==="{"){o+=1;continue}if(a==="}"&&(o-=1,o===0)){const i=T(e.slice(n,l+1));if(i)return i;n=-1}}}return null}function Ae(e){const n=e.indexOf("```");if(n<0)return null;const o=e.indexOf(`
|
|
13
|
+
`,n+3),t=o>=0?o+1:n+3,r=e.indexOf("```",t);return r<0?null:e.slice(t,r).trim()}function v(e,n){const o=e.toLowerCase(),t=`<${n}>`,r=`</${n}>`,l=o.indexOf(t);if(l<0)return null;const a=l+t.length,i=o.indexOf(r,a);return i<0?null:e.slice(a,i).trim()}function Ce(e){const n=v(e,"tool_code");if(!n)return null;const o=v(e,"tool_args"),t=o?T(o.trim()):null,r=typeof t=="object"&&t!==null&&!Array.isArray(t)?t:Array.isArray(t)?{args:t}:{};return{name:n,arguments:r}}function M(e){if(typeof e!="object"||e===null)return null;if(Array.isArray(e))return M(e[0]);const n=e;if(Array.isArray(n.tool_calls))return M(n.tool_calls[0]);const o=typeof n.function=="object"&&n.function!==null?n.function:void 0,t=n.name??n.tool_name??n.tool??o?.name??(typeof n.function=="string"?n.function:void 0),r=typeof t=="string"?t.trim():"";if(!r)return null;const l=n.arguments??n.args??n.parameters??n.input??o?.arguments??o?.args??o?.parameters??{},a=Array.isArray(l)?{args:l}:Z(l)??{};return{name:r,args:ee(r,a)}}function be(e){return new C({content:"",invalid_tool_calls:[{id:`invalid-tool-${Math.random().toString(36).slice(2,10)}`,name:e.name,args:JSON.stringify(e.args),error:`Prompted-json model requested unavailable tool: ${e.name}`,type:"invalid_tool_call"}]})}function H(){return["Identify the concrete evidence tool required for this request","Run the selected non-planning evidence tool and inspect its result","Update TODO status from the observed evidence","Return the final answer grounded in tool output"]}function Pe(e,n,o){const t=n.map(l=>m(l)).find(l=>l==="write_todos"||l==="tool_call_write_todos"||l==="call_write_todos");if(!t)return null;const r=H().map((l,a)=>({content:l,status:a===0?"in_progress":"pending"}));return new C({content:"",tool_calls:[{id:`tool-${Math.random().toString(36).slice(2,10)}`,name:t,args:{todos:r},type:"tool_call"}]})}function Oe(e,n){const o=O(e);if(/TODO completed:|\[x\]/i.test(o))return null;const t=n.map(l=>m(l)).find(l=>l==="write_todos"||l==="tool_call_write_todos"||l==="call_write_todos");if(!t||!N(e,n))return null;const r=H().map(l=>({content:l,status:"completed"}));return new C({content:"",tool_calls:[{id:`fallback-complete-${Math.random().toString(36).slice(2,10)}`,name:t,args:{todos:r},type:"tool_call"}]})}function K(e){if(!b(e.name))return!1;const n=e.args.todos;return!Array.isArray(n)||n.length===0?!1:n.every(o=>typeof o=="object"&&o!==null&&o.status==="completed")}function ke(e){if(!K(e))return e;const n=e.args.todos.map((o,t)=>typeof o=="object"&&o!==null&&!Array.isArray(o)?{...o,status:t===0?"in_progress":"pending"}:o);return{name:e.name,args:{...e.args,todos:n}}}function je(e){if(typeof e!="object"||e===null)return null;const n=e,o=typeof n.name=="string"?n.name.trim():"";if(!o)return null;const t=typeof n.description=="string"?n.description.trim():"",r=$(n);return[`Tool: ${o}`,t?`Description: ${t}`:"",`Arguments JSON schema: ${JSON.stringify(r)}`].filter(Boolean).join(`
|
|
14
|
+
`)}function Se(e){const n=m(e);if(!n)return null;const o=ue(e).split(/\n/u)[0]?.trim()??"";return[`Tool: ${n}`,o?`Description: ${o}`:"",`Arguments keys: ${de(e)}`].filter(Boolean).join(`
|
|
15
|
+
`)}function Ne(e,n,o={}){const t=n.map(s=>je(s)).filter(s=>!!s),r=n.map(s=>Se(s)).filter(s=>!!s);if(t.length===0)return O(e);const l=o.forceToolCall==="planning"?["Required planning tool call:","You must call write_todos now before any domain tool or final answer.","Return exactly one JSON object for write_todos with concrete todo items and statuses.","Do not write prose, markdown, analysis, or a plain-text plan."].join(`
|
|
16
|
+
`):o.forceToolCall==="nonPlanningEvidence"?["Required evidence tool call:","A todo board already exists. Your next action must be exactly one non-planning tool call chosen from the available tool descriptions and schemas.","Honor any structured workspace or runtime evidence-tool contract already supplied in this turn.","Do not choose tools by matching free-form request or TODO text.","Do not call write_todos or read_todos now.","Do not write prose, markdown, analysis, or a plain-text plan."].join(`
|
|
17
|
+
`):"",i=[o.forceToolCall?le:re,l,(o.forceToolCall?r:t).join(`
|
|
18
|
+
|
|
19
|
+
`),l].filter(Boolean).join(`
|
|
20
|
+
|
|
21
|
+
`),c=O(e);return[o.suppressThinking?se:"",i,l,c,ie].filter(Boolean).join(`
|
|
22
|
+
|
|
23
|
+
`)}function ve(e){if(process.env.AGENT_HARNESS_PROMPTED_JSON_DEBUG!=="1")return;const n=typeof e.prompt=="string"?e.prompt:O(e.prompt);console.error(JSON.stringify({type:"prompted-json-turn",forcePlanningToolCall:e.forcePlanningToolCall,forceNonPlanningEvidenceToolCall:e.forceNonPlanningEvidenceToolCall,effectiveToolNames:e.effectiveToolNames,inputSummary:Le(e.rawInput),promptHead:n.slice(0,2e3)}))}function Ie(e){process.env.AGENT_HARNESS_PROMPTED_JSON_DEBUG==="1"&&console.error(JSON.stringify({type:"prompted-json-result",forcePlanningToolCall:e.forcePlanningToolCall,forceNonPlanningEvidenceToolCall:e.forceNonPlanningEvidenceToolCall,parsedToolName:e.parsedToolName??null,textHead:e.text.slice(0,2e3)}))}function Le(e){return(typeof e=="object"&&e!==null&&Array.isArray(e.messages)?e.messages:Array.isArray(e)?e:[]).slice(-8).map(o=>({role:g(o),type:L(o),name:R(o).name,toolCallNames:S(o).map(t=>typeof t=="object"&&t!==null&&typeof t.name=="string"?t.name:""),contentHead:_(o).slice(0,120)}))}function w(e,n=[],o={}){return new Proxy(e,{has(t,r){return r==="bindTools"||r==="invoke"||r==="stream"||r==="streamEvents"||r==="withConfig"?!0:r in t},get(t,r,l){if(r==="bindTools")return i=>w(t,i,o);if(r==="invoke")return async(i,c)=>{const s=E(i,n),d=!s&&ge(i,n),u=s?G(i,n):d?ye(n):n;if(o.settleCompletedToolResults===!0&&!s&&u.length>0&&z(i)&&U(i))return new C({content:q(i)??""});const x=u.length>0?Ne(i,u,{...o,forceToolCall:s?"planning":d?"nonPlanningEvidence":void 0}):i;ve({forcePlanningToolCall:s,forceNonPlanningEvidenceToolCall:d,effectiveToolNames:u.map(m).filter(Boolean),rawInput:i,prompt:x});const k=await t.invoke(x,c);if(u.length===0)return k;const j=D(k),p=M(we(j));if(Ie({forcePlanningToolCall:s,forceNonPlanningEvidenceToolCall:d,text:j,parsedToolName:p?.name}),!p){if(s){const A=Pe(i,u,j);if(A)return A}else if(!d){const A=Oe(i,u);if(A)return A}return k}if(!pe(p.name,u))return be(p);const h=s?ke(p):p;return K(h)&&!N(i,u)?k:(oe({name:h.name,args:h.args,rawArgsInput:j}),new C({content:"",tool_calls:[{id:`tool-${Math.random().toString(36).slice(2,10)}`,name:h.name,args:h.args,type:"tool_call"}]}))};if(r==="stream")return async(i,c)=>{const s=await l.invoke(i,c);return(async function*(){yield s})()};if(r==="streamEvents")return async(i,c)=>{const s=await l.invoke(i,c);return(async function*(){yield{event:"on_chat_model_end",name:typeof t.constructor?.name=="string"?t.constructor.name:"ChatModel",data:{output:s}}})()};if(r==="withConfig"&&typeof t.withConfig=="function")return i=>w(t.withConfig(i),n,o);const a=Reflect.get(t,r,l);return typeof a=="function"?a.bind(t):a},getOwnPropertyDescriptor(t,r){return r==="bindTools"||r==="invoke"||r==="stream"||r==="streamEvents"||r==="withConfig"?{configurable:!0,enumerable:!1,writable:!1,value:this.get?.(t,r,t)}:Reflect.getOwnPropertyDescriptor(t,r)}})}function I(e,n=[],o={}){return new Proxy(e,{has(t,r){return r==="bindTools"||r==="invoke"||r==="stream"||r==="streamEvents"||r==="withConfig"?!0:r in t},get(t,r,l){if(r==="bindTools")return i=>I(t,i,o);if(r==="invoke")return async(i,c)=>{if(E(i,n))return w(t,n,o).invoke(i,c);const s=typeof t.bindTools=="function"?t.bindTools(n):t;return typeof s.invoke=="function"?s.invoke(i,c):t.invoke(i,c)};if(r==="withConfig"&&typeof t.withConfig=="function")return i=>I(t.withConfig(i),n,o);const a=Reflect.get(t,r,l);return typeof a=="function"?a.bind(t):a}})}function Re(e){const n=typeof e.init?.modelPath=="string"?e.init.modelPath.trim():"";return n||(e.model.includes("/")||e.model.endsWith(".gguf")?e.model:void 0)}async function Ee(e){const n=Re(e);if(!n)throw new Error(`Model ${e.id} with provider ${e.provider} must define a GGUF path via top-level modelPath or use model as the GGUF path.`);try{const{ChatLlamaCpp:o}=await import("@langchain/community/chat_models/llama_cpp");return w(await o.initialize({...e.init,modelPath:n}))}catch(o){throw new Error(`Failed to initialize ${e.provider} model ${e.id}. Install @langchain/community and node-llama-cpp in the application workspace and ensure the GGUF file exists at ${n}.`,{cause:o})}}async function Ye(e,n){if(n)return n(e.id);if(e.provider==="ollama"){const{toolCallingMode:o,...t}=e.init??{},r=new Q({model:e.model,...t});return o==="prompted-json"?w(r,[],{settleCompletedToolResults:!0,suppressThinking:t.think===!1}):o==="prompted-json-planning"?I(r,[],{settleCompletedToolResults:!0,suppressThinking:t.think===!1}):y(r)}if(e.provider==="openai-compatible"){const{toolCallingMode:o,...t}=e.init??{},r=new J({model:e.model,...te(t)});return o==="prompted-json"?w(r,[],{settleCompletedToolResults:!0,suppressThinking:!0}):o==="prompted-json-planning"?I(r,[],{settleCompletedToolResults:!0,suppressThinking:!0}):y(r)}return e.provider==="openai"?y(new J({model:e.model,...e.init})):e.provider==="anthropic"?y(new Y({model:e.model,...e.init})):e.provider==="google"||e.provider==="google-genai"||e.provider==="gemini"?y(new W({model:e.model,...e.init})):e.provider==="node-llama-cpp"||e.provider==="llama-cpp"?Ee(e):V(e.model,{modelProvider:e.provider,...e.init})}export{Ye as createResolvedModel};
|