@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.
Files changed (227) hide show
  1. package/README.md +3 -1234
  2. package/README.zh.md +3 -1191
  3. package/dist/acp.js +1 -1
  4. package/dist/api.js +1 -404
  5. package/dist/benchmark/checkpoint-resume-cost-benchmark.js +1 -55
  6. package/dist/benchmark/deepagent-local-model-benchmark.js +2 -35
  7. package/dist/benchmark/upstream-runtime-ab-benchmark.js +1 -179
  8. package/dist/cli/chat-interactive.js +25 -244
  9. package/dist/cli/chat-rendering.js +6 -100
  10. package/dist/cli/chat-stream.js +23 -512
  11. package/dist/cli/chat-ui.js +21 -199
  12. package/dist/cli/chat-workspace.js +2 -210
  13. package/dist/cli/main.js +21 -428
  14. package/dist/cli/managed-service-commands.js +9 -63
  15. package/dist/cli/managed-service.js +2 -137
  16. package/dist/cli/options-init-chat.js +1 -108
  17. package/dist/cli/options-runtime.js +1 -158
  18. package/dist/cli/options-serve.js +1 -282
  19. package/dist/cli/options.js +2 -19
  20. package/dist/cli/process-guards.js +1 -139
  21. package/dist/cli/request-tree.js +7 -296
  22. package/dist/cli/runtime-commands.js +12 -258
  23. package/dist/cli/runtime-output.js +16 -155
  24. package/dist/cli/server-commands.js +16 -270
  25. package/dist/cli/workspace.js +1 -67
  26. package/dist/cli.js +1 -7
  27. package/dist/client/acp.js +1 -1
  28. package/dist/client/in-process.js +1 -67
  29. package/dist/client/index.js +1 -2
  30. package/dist/client/types.js +0 -1
  31. package/dist/client.js +1 -1
  32. package/dist/contracts/core.js +1 -1
  33. package/dist/contracts/runtime-evaluation.js +0 -1
  34. package/dist/contracts/runtime-memory.js +0 -1
  35. package/dist/contracts/runtime-observability.js +0 -1
  36. package/dist/contracts/runtime-requests.js +0 -1
  37. package/dist/contracts/runtime-scheduling.js +0 -1
  38. package/dist/contracts/runtime.js +1 -27
  39. package/dist/contracts/types.js +1 -3
  40. package/dist/contracts/workspace.js +0 -1
  41. package/dist/flow/build-flow-graph.js +1 -50
  42. package/dist/flow/export-mermaid.js +2 -464
  43. package/dist/flow/export-sequence-mermaid.js +2 -325
  44. package/dist/flow/flow-graph-normalization.js +1 -214
  45. package/dist/flow/flow-graph-runtime.js +1 -107
  46. package/dist/flow/flow-graph-upstream.js +1 -494
  47. package/dist/flow/index.js +1 -3
  48. package/dist/flow/types.js +0 -1
  49. package/dist/index.js +1 -5
  50. package/dist/init-project.js +1 -1
  51. package/dist/knowledge/config.js +1 -32
  52. package/dist/knowledge/contracts.js +0 -1
  53. package/dist/knowledge/index.js +1 -2
  54. package/dist/knowledge/module.js +12 -909
  55. package/dist/knowledge/procedural/config.js +1 -125
  56. package/dist/knowledge/procedural/index.js +1 -2
  57. package/dist/knowledge/procedural/manager.js +9 -345
  58. package/dist/mcp.js +1 -2
  59. package/dist/package-version.d.ts +1 -1
  60. package/dist/package-version.js +1 -2
  61. package/dist/persistence/file-store.js +3 -758
  62. package/dist/persistence/sqlite-request-context-store.js +5 -54
  63. package/dist/persistence/sqlite-request-queue-store.js +10 -108
  64. package/dist/persistence/sqlite-runtime.js +1 -86
  65. package/dist/persistence/sqlite-store.js +62 -810
  66. package/dist/persistence/types.js +0 -1
  67. package/dist/projections/presentation.js +37 -206
  68. package/dist/projections/request-events.js +2 -502
  69. package/dist/projections/upstream-events.js +1 -201
  70. package/dist/protocol/a2a/http-discovery.js +1 -178
  71. package/dist/protocol/a2a/http-rpc.js +6 -622
  72. package/dist/protocol/a2a/http.js +1 -138
  73. package/dist/protocol/a2a/task-state.js +3 -317
  74. package/dist/protocol/acp/client.js +8 -294
  75. package/dist/protocol/acp/harness-client.js +1 -218
  76. package/dist/protocol/acp/http.js +5 -130
  77. package/dist/protocol/acp/server.js +1 -310
  78. package/dist/protocol/acp/stdio.js +2 -69
  79. package/dist/protocol/ag-ui/http.js +3 -378
  80. package/dist/protocol/mcp/server.js +1 -428
  81. package/dist/resource/backend/workspace-scoped-backend.js +1 -319
  82. package/dist/resource/isolation.js +1 -237
  83. package/dist/resource/mcp/tool-support.js +3 -296
  84. package/dist/resource/mcp-tool-support.js +1 -2
  85. package/dist/resource/providers/resource-provider.js +1 -215
  86. package/dist/resource/resource-impl.js +1 -3
  87. package/dist/resource/resource-types.js +0 -1
  88. package/dist/resource/resource.js +1 -1
  89. package/dist/resource/sources.js +1 -247
  90. package/dist/resource/tools/function-tool-resolver.js +2 -272
  91. package/dist/runtime/adapter/compat/deepagent-compat.js +1 -29
  92. package/dist/runtime/adapter/compat/openai-compatible.js +1 -55
  93. package/dist/runtime/adapter/direct-builtin-utility.js +2 -90
  94. package/dist/runtime/adapter/flow/execution-context.js +1 -71
  95. package/dist/runtime/adapter/flow/invocation-flow.js +8 -425
  96. package/dist/runtime/adapter/flow/invoke-runtime.js +1 -20
  97. package/dist/runtime/adapter/flow/stream-runtime.js +11 -1395
  98. package/dist/runtime/adapter/invocation-result.js +2 -473
  99. package/dist/runtime/adapter/local-tool-invocation.js +6 -638
  100. package/dist/runtime/adapter/middleware/context-hygiene.js +1 -83
  101. package/dist/runtime/adapter/middleware-assembly.js +5 -477
  102. package/dist/runtime/adapter/model/invocation-request.js +3 -183
  103. package/dist/runtime/adapter/model/message-assembly.js +1 -28
  104. package/dist/runtime/adapter/model/model-providers.js +23 -1115
  105. package/dist/runtime/adapter/model/prompted-json-tool-call-capture.js +1 -40
  106. package/dist/runtime/adapter/model/prompted-json-tool-policy.js +1 -22
  107. package/dist/runtime/adapter/resilience.js +1 -104
  108. package/dist/runtime/adapter/runtime-adapter-support.js +3 -141
  109. package/dist/runtime/adapter/runtime-shell.js +5 -166
  110. package/dist/runtime/adapter/stream-event-projection.js +2 -622
  111. package/dist/runtime/adapter/stream-text-consumption.js +1 -18
  112. package/dist/runtime/adapter/terminal-status.js +2 -67
  113. package/dist/runtime/adapter/tool/builtin-middleware-tools.js +6 -627
  114. package/dist/runtime/adapter/tool/declared-middleware.js +1 -154
  115. package/dist/runtime/adapter/tool/interrupt-policy.js +1 -34
  116. package/dist/runtime/adapter/tool/provider-tool.js +1 -25
  117. package/dist/runtime/adapter/tool/resolved-tool.js +1 -225
  118. package/dist/runtime/adapter/tool/tool-arguments.js +3 -486
  119. package/dist/runtime/adapter/tool/tool-hitl.js +1 -346
  120. package/dist/runtime/adapter/tool/tool-name-mapping.js +1 -128
  121. package/dist/runtime/adapter/tool/tool-output-artifacts.js +2 -88
  122. package/dist/runtime/adapter/tool/tool-replay.js +1 -37
  123. package/dist/runtime/adapter/tool-resolution.js +1 -86
  124. package/dist/runtime/adapter/upstream-configurable-keys.js +1 -2
  125. package/dist/runtime/agent-runtime-adapter.js +60 -2338
  126. package/dist/runtime/agent-runtime-assembly.js +7 -249
  127. package/dist/runtime/env/runtime-env.js +1 -62
  128. package/dist/runtime/harness/background-runtime.js +1 -8
  129. package/dist/runtime/harness/bindings.js +1 -58
  130. package/dist/runtime/harness/events/event-bus.js +1 -16
  131. package/dist/runtime/harness/events/event-sink.js +1 -61
  132. package/dist/runtime/harness/events/events.js +1 -80
  133. package/dist/runtime/harness/events/listener-runtime.js +1 -13
  134. package/dist/runtime/harness/events/runtime-event-operations.js +1 -9
  135. package/dist/runtime/harness/events/streaming.js +1 -100
  136. package/dist/runtime/harness/events/timeline.js +1 -52
  137. package/dist/runtime/harness/public-shapes.js +1 -186
  138. package/dist/runtime/harness/run/artifact-paths.js +1 -15
  139. package/dist/runtime/harness/run/governance.js +1 -295
  140. package/dist/runtime/harness/run/helpers.js +1 -71
  141. package/dist/runtime/harness/run/inspection.js +1 -409
  142. package/dist/runtime/harness/run/operator-overview.js +1 -80
  143. package/dist/runtime/harness/run/queue-diagnostics.js +1 -15
  144. package/dist/runtime/harness/run/recovery.js +1 -162
  145. package/dist/runtime/harness/run/resources.js +1 -60
  146. package/dist/runtime/harness/run/resume.js +1 -56
  147. package/dist/runtime/harness/run/routing.js +1 -48
  148. package/dist/runtime/harness/run/run-lifecycle.js +1 -66
  149. package/dist/runtime/harness/run/run-operations.js +1 -217
  150. package/dist/runtime/harness/run/run-queue.js +1 -43
  151. package/dist/runtime/harness/run/run-slot-acquisition.js +1 -157
  152. package/dist/runtime/harness/run/session-records.js +1 -97
  153. package/dist/runtime/harness/run/start-run.js +1 -120
  154. package/dist/runtime/harness/run/startup-runtime.js +1 -69
  155. package/dist/runtime/harness/run/stream-run.js +8 -1418
  156. package/dist/runtime/harness/run/surface-semantics.js +1 -79
  157. package/dist/runtime/harness/runtime-defaults.js +1 -39
  158. package/dist/runtime/harness/system/boundary-analysis.js +1 -234
  159. package/dist/runtime/harness/system/health-monitor.js +1 -258
  160. package/dist/runtime/harness/system/inventory.js +1 -129
  161. package/dist/runtime/harness/system/mem0-ingestion-sync.js +5 -345
  162. package/dist/runtime/harness/system/policy-engine.js +1 -175
  163. package/dist/runtime/harness/system/runtime-memory-candidates.js +4 -110
  164. package/dist/runtime/harness/system/runtime-memory-consolidation.js +1 -51
  165. package/dist/runtime/harness/system/runtime-memory-manager.js +10 -693
  166. package/dist/runtime/harness/system/runtime-memory-policy.js +1 -155
  167. package/dist/runtime/harness/system/runtime-memory-records.js +11 -577
  168. package/dist/runtime/harness/system/runtime-memory-sync.js +5 -206
  169. package/dist/runtime/harness/system/session-memory-sync.js +3 -113
  170. package/dist/runtime/harness/system/skill-requirements.js +1 -112
  171. package/dist/runtime/harness/system/store.js +9 -365
  172. package/dist/runtime/harness/tool-gateway/index.js +1 -2
  173. package/dist/runtime/harness/tool-gateway/policy.js +1 -45
  174. package/dist/runtime/harness/tool-gateway/validation.js +1 -176
  175. package/dist/runtime/harness/tool-schema.js +1 -3
  176. package/dist/runtime/harness.js +3 -1490
  177. package/dist/runtime/index.js +1 -3
  178. package/dist/runtime/layout/runtime-layout.js +1 -31
  179. package/dist/runtime/maintenance/checkpoint-maintenance.js +2 -178
  180. package/dist/runtime/maintenance/file-checkpoint-saver.js +1 -106
  181. package/dist/runtime/maintenance/runtime-record-maintenance.js +2 -169
  182. package/dist/runtime/maintenance/sqlite-checkpoint-saver.js +4 -289
  183. package/dist/runtime/parsing/output-content.js +10 -550
  184. package/dist/runtime/parsing/output-parsing.js +1 -4
  185. package/dist/runtime/parsing/output-recovery.js +3 -213
  186. package/dist/runtime/parsing/output-tool-args.js +7 -663
  187. package/dist/runtime/parsing/stream-event-parsing.js +3 -362
  188. package/dist/runtime/prompts/runtime-prompts.js +4 -73
  189. package/dist/runtime/scheduling/system-schedule-manager.js +11 -532
  190. package/dist/runtime/skills/skill-metadata.js +1 -197
  191. package/dist/runtime/startup-tracing.js +2 -37
  192. package/dist/runtime/support/compiled-binding.js +1 -290
  193. package/dist/runtime/support/embedding-models.js +1 -118
  194. package/dist/runtime/support/harness-support.js +5 -137
  195. package/dist/runtime/support/llamaindex.js +1 -108
  196. package/dist/runtime/support/runtime-adapter-options.js +1 -29
  197. package/dist/runtime/support/runtime-factories.js +1 -51
  198. package/dist/runtime/support/vector-stores.js +9 -270
  199. package/dist/scaffold/init-project.js +54 -233
  200. package/dist/tooling/extensions.js +1 -311
  201. package/dist/tooling/module-loader.js +1 -55
  202. package/dist/tools.js +1 -176
  203. package/dist/utils/agent-display.js +1 -18
  204. package/dist/utils/bundled-text.js +4 -39
  205. package/dist/utils/compiled-binding.js +1 -33
  206. package/dist/utils/fs.js +2 -45
  207. package/dist/utils/id.js +1 -9
  208. package/dist/utils/message-content.js +1 -30
  209. package/dist/utils/object.js +1 -6
  210. package/dist/workspace/agent-binding-compiler.js +3 -613
  211. package/dist/workspace/compile.js +1 -472
  212. package/dist/workspace/framework-contract-validation.js +2 -322
  213. package/dist/workspace/index.js +1 -1
  214. package/dist/workspace/object-loader-paths.js +1 -71
  215. package/dist/workspace/object-loader-readers.js +1 -187
  216. package/dist/workspace/object-loader.js +1 -754
  217. package/dist/workspace/resource-compilers.js +1 -374
  218. package/dist/workspace/support/agent-capabilities.js +1 -37
  219. package/dist/workspace/support/agent-execution-config.js +1 -44
  220. package/dist/workspace/support/discovery.js +1 -147
  221. package/dist/workspace/support/source-collectors.js +1 -30
  222. package/dist/workspace/support/source-protocols.js +2 -192
  223. package/dist/workspace/support/workspace-ref-utils.js +1 -362
  224. package/dist/workspace/tool-hydration.js +1 -280
  225. package/dist/workspace/validate.js +1 -99
  226. package/dist/workspace/yaml-object-reader.js +1 -285
  227. package/package.json +7 -3
@@ -1,1115 +1,23 @@
1
- import { ChatAnthropic } from "@langchain/anthropic";
2
- import { ChatGoogle } from "@langchain/google";
3
- import { ToolMessage } from "@langchain/core/messages";
4
- import { ChatOllama } from "@langchain/ollama";
5
- import { ChatOpenAI } from "@langchain/openai";
6
- import { AIMessage } from "langchain";
7
- import { initChatModel } from "langchain";
8
- import { salvageToolArgs, tryParseJson } from "../../parsing/output-parsing.js";
9
- import { normalizeKnownToolArgs, salvageJsonToolCalls } from "../../parsing/output-tool-args.js";
10
- import { normalizeModelFacingToolSchema } from "../tool/resolved-tool.js";
11
- import { normalizeOpenAICompatibleInit } from "../compat/openai-compatible.js";
12
- import { recordPromptedJsonToolCall } from "./prompted-json-tool-call-capture.js";
13
- import { readPromptedJsonToolPolicy } from "./prompted-json-tool-policy.js";
14
- const NODE_LLAMA_CPP_TOOL_CALL_INSTRUCTION = [
15
- "Available tools are listed below.",
16
- "If you need a tool, respond with only one JSON object.",
17
- 'Use this exact shape: {"name":"tool_name","arguments":{"key":"value"}}',
18
- "Do not add markdown, prose, or code fences unless the output is wrapped inside <tool_call>...</tool_call>.",
19
- "When the latest user message explicitly requests a tool call or provides a tool-call JSON object, call that tool instead of answering locally.",
20
- "If the conversation already contains TOOL_RESULT for the requested work, answer from that result instead of repeating the same tool call.",
21
- "If no tool is needed, answer normally.",
22
- ].join("\n");
23
- const FORCED_NODE_LLAMA_CPP_TOOL_CALL_INSTRUCTION = [
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};