@dvina/agents 0.14.0 → 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/eval/index.d.mts +58 -13
- package/dist/eval/index.d.ts +58 -13
- package/dist/eval/index.js +672 -29
- package/dist/eval/index.js.map +1 -1
- package/dist/eval/index.mjs +673 -30
- package/dist/eval/index.mjs.map +1 -1
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +75 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +75 -0
- package/dist/index.mjs.map +1 -1
- package/dist/{model-resolver-DjKRXKtu.d.mts → model-resolver-DSJRvrqA.d.mts} +2 -5
- package/dist/{model-resolver-DjKRXKtu.d.ts → model-resolver-DSJRvrqA.d.ts} +2 -5
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -101,6 +101,9 @@ function convertToLangchainMessages(messages) {
|
|
|
101
101
|
|
|
102
102
|
// src/runtime/langchain/agent.ts
|
|
103
103
|
var ENABLE_STREAM_DEBUG_LOGS = false;
|
|
104
|
+
var DEFAULT_EFFECTIVE_MODEL_INVOCATIONS = 25;
|
|
105
|
+
var GRACEFUL_SHUTDOWN_BUFFER_CYCLES = 3;
|
|
106
|
+
var INVOCATION_LIMIT_TOOL_ERROR = "[SYSTEM] You have reached the maximum number of tool invocations for this turn. Do NOT call any more tools. Instead, respond with a text message that:\n1. Summarizes the progress made so far and any partial results.\n2. Explains what could not be completed and why.\n3. Suggests alternative approaches or next steps the user can take.";
|
|
104
107
|
function debugLogStream(type, text) {
|
|
105
108
|
if (!ENABLE_STREAM_DEBUG_LOGS) return;
|
|
106
109
|
console.warn(`${type}: ${text}`);
|
|
@@ -109,6 +112,7 @@ var LangchainAgent = class {
|
|
|
109
112
|
constructor(params) {
|
|
110
113
|
this.params = params;
|
|
111
114
|
this.tools = params.tools;
|
|
115
|
+
this.effectiveModelLimit = params.maxModelInvocations ?? DEFAULT_EFFECTIVE_MODEL_INVOCATIONS;
|
|
112
116
|
if (!params.disableModelStreamingFor) params.disableModelStreamingFor = [];
|
|
113
117
|
if (!params.disableToolReportingFor) params.disableToolReportingFor = [];
|
|
114
118
|
if (!params.disableToolStreamingFor) params.disableToolStreamingFor = [];
|
|
@@ -170,17 +174,84 @@ var LangchainAgent = class {
|
|
|
170
174
|
});
|
|
171
175
|
}
|
|
172
176
|
}
|
|
177
|
+
}),
|
|
178
|
+
/**
|
|
179
|
+
* Tracks model invocations and gracefully stops the agent when
|
|
180
|
+
* the limit is reached. Instead of letting LangGraph throw a
|
|
181
|
+
* hard GraphRecursionError, tool calls beyond the limit receive
|
|
182
|
+
* an error message asking the model to summarize and wrap up.
|
|
183
|
+
*/
|
|
184
|
+
(0, import_langchain2.createMiddleware)({
|
|
185
|
+
name: "invocationLimitGuard",
|
|
186
|
+
wrapModelCall: async (request, handler) => {
|
|
187
|
+
this.modelInvocationCount++;
|
|
188
|
+
return handler(request);
|
|
189
|
+
},
|
|
190
|
+
wrapToolCall: async (request, handler) => {
|
|
191
|
+
if (this.modelInvocationCount > this.effectiveModelLimit) {
|
|
192
|
+
return new import_messages.ToolMessage({
|
|
193
|
+
name: request.toolCall.name,
|
|
194
|
+
content: INVOCATION_LIMIT_TOOL_ERROR,
|
|
195
|
+
tool_call_id: request.toolCall.id || "INVOCATION_LIMIT"
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
return handler(request);
|
|
199
|
+
}
|
|
173
200
|
})
|
|
174
201
|
];
|
|
175
202
|
if (params.middleware) middlewares = [...middlewares, ...params.middleware];
|
|
176
203
|
params.middleware = middlewares;
|
|
177
204
|
this.deepAgent = (0, import_deepagents.createDeepAgent)(params);
|
|
205
|
+
this.recursionLimit = this.computeRecursionLimit();
|
|
178
206
|
}
|
|
179
207
|
deepAgent;
|
|
180
208
|
toolCalls = [];
|
|
181
209
|
tools;
|
|
210
|
+
recursionLimit;
|
|
211
|
+
modelInvocationCount = 0;
|
|
212
|
+
effectiveModelLimit;
|
|
213
|
+
/**
|
|
214
|
+
* Computes an adjusted LangGraph recursion limit that compensates for
|
|
215
|
+
* middleware graph nodes. LangGraph counts every *superstep* (node visit)
|
|
216
|
+
* toward its recursion limit, but middleware hooks like `beforeModel`,
|
|
217
|
+
* `afterModel`, `beforeAgent`, and `afterAgent` each add extra graph
|
|
218
|
+
* nodes that consume steps without representing real model invocations.
|
|
219
|
+
*
|
|
220
|
+
* This method introspects the compiled graph to count how many nodes
|
|
221
|
+
* participate in one model-tool cycle and scales the limit so the agent
|
|
222
|
+
* gets {@link DEFAULT_EFFECTIVE_MODEL_INVOCATIONS} real model calls,
|
|
223
|
+
* plus a buffer of extra cycles for graceful shutdown (where tool calls
|
|
224
|
+
* return an error asking the model to wrap up).
|
|
225
|
+
*
|
|
226
|
+
* Formula:
|
|
227
|
+
* recursionLimit = N_beforeAgent
|
|
228
|
+
* + (K + buffer) * (N_beforeModel + 1 + N_afterModel + 1)
|
|
229
|
+
* + N_afterAgent
|
|
230
|
+
*
|
|
231
|
+
* Where K = desired effective model invocations, buffer =
|
|
232
|
+
* {@link GRACEFUL_SHUTDOWN_BUFFER_CYCLES}, and the +1s are for the
|
|
233
|
+
* `model_request` and `tools` core nodes.
|
|
234
|
+
*/
|
|
235
|
+
computeRecursionLimit() {
|
|
236
|
+
const graph = this.deepAgent.graph;
|
|
237
|
+
const nodeNames = graph?.nodes ? Object.keys(graph.nodes) : [];
|
|
238
|
+
let beforeAgentCount = 0;
|
|
239
|
+
let beforeModelCount = 0;
|
|
240
|
+
let afterModelCount = 0;
|
|
241
|
+
let afterAgentCount = 0;
|
|
242
|
+
for (const name of nodeNames) {
|
|
243
|
+
if (name.endsWith(".before_agent")) beforeAgentCount++;
|
|
244
|
+
else if (name.endsWith(".before_model")) beforeModelCount++;
|
|
245
|
+
else if (name.endsWith(".after_model")) afterModelCount++;
|
|
246
|
+
else if (name.endsWith(".after_agent")) afterAgentCount++;
|
|
247
|
+
}
|
|
248
|
+
const nodesPerCycle = beforeModelCount + 1 + afterModelCount + 1;
|
|
249
|
+
const totalCycles = this.effectiveModelLimit + GRACEFUL_SHUTDOWN_BUFFER_CYCLES;
|
|
250
|
+
return beforeAgentCount + totalCycles * nodesPerCycle + afterAgentCount;
|
|
251
|
+
}
|
|
182
252
|
async run(input) {
|
|
183
253
|
this.toolCalls = [];
|
|
254
|
+
this.modelInvocationCount = 0;
|
|
184
255
|
let messageCountBefore = 0;
|
|
185
256
|
try {
|
|
186
257
|
const stateBefore = await this.deepAgent.getState({
|
|
@@ -198,6 +269,8 @@ var LangchainAgent = class {
|
|
|
198
269
|
messages
|
|
199
270
|
},
|
|
200
271
|
{
|
|
272
|
+
...input.signal ? { signal: input.signal } : {},
|
|
273
|
+
recursionLimit: this.recursionLimit,
|
|
201
274
|
configurable: {
|
|
202
275
|
threadId: input.threadId,
|
|
203
276
|
thread_id: input.threadId
|
|
@@ -270,6 +343,7 @@ var LangchainAgent = class {
|
|
|
270
343
|
}
|
|
271
344
|
async *stream(input) {
|
|
272
345
|
this.toolCalls = [];
|
|
346
|
+
this.modelInvocationCount = 0;
|
|
273
347
|
const contentBlocks = [];
|
|
274
348
|
let finalValue;
|
|
275
349
|
let usageMetadata = {
|
|
@@ -286,6 +360,7 @@ var LangchainAgent = class {
|
|
|
286
360
|
const stream = await this.deepAgent.stream(
|
|
287
361
|
{ messages },
|
|
288
362
|
{
|
|
363
|
+
recursionLimit: this.recursionLimit,
|
|
289
364
|
configurable: {
|
|
290
365
|
threadId: input.threadId,
|
|
291
366
|
thread_id: input.threadId
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/runtime/langchain/factory.ts","../src/runtime/langchain/agent.ts","../src/runtime/langchain/utils.ts","../src/runtime/langchain/model-resolver.ts","../src/core/tools/tool-registry.ts","../src/core/tools/tool-cache.ts"],"sourcesContent":["// Core Interfaces & Factory\nexport { AgentFactory, CreateAgentOptions, AgentHandoff } from './core/agent.factory';\nexport {\n\tAgent,\n\tAgentRunInput,\n\tAgentResult,\n\tMessage,\n\tHumanMessage,\n\tAiMessage,\n\tToolMessage,\n\tContentBlock,\n\tUsageMeta,\n\tToolKitSpec,\n\tToolSpec,\n\tToolDefinition,\n\tToolCall,\n\tStreamEvent,\n} from './core/agent.interface';\nexport { LangchainAgentFactory } from './runtime/langchain/factory';\nexport { type LangchainModelConfig } from './runtime/langchain/model-resolver';\n\n// Tools\nexport { ToolRegistry } from './core/tools/tool-registry';\nexport { ToolProvider } from './core/tools/tool-provider';\nexport { ToolCache, RedisToolCache, InMemoryToolCache } from './core/tools/tool-cache';\n","import { AgentFactory, CreateAgentOptions } from '@core/agent.factory';\nimport { Agent } from '@core/agent.interface';\nimport { PostgresSaver } from '@langchain/langgraph-checkpoint-postgres';\n// @ts-ignore -_-\nimport { PostgresStore } from '@langchain/langgraph-checkpoint-postgres/store';\nimport { CompositeBackend, StateBackend, StoreBackend } from 'deepagents';\nimport { AgentMiddleware, llmToolSelectorMiddleware, summarizationMiddleware, tool } from 'langchain';\nimport { CreateOptions, LangchainAgent } from './agent';\nimport { LangchainModelConfig, LangchainModelResolver } from './model-resolver';\n\nexport interface PostgresSaverConfig {\n\tconnString: string;\n\tschema: string;\n}\n\nexport interface PostgresStoreConfig {\n\tconnString: string;\n\tschema: string;\n}\n\nexport class LangchainAgentFactory implements AgentFactory {\n\tprivate modelResolver: LangchainModelResolver;\n\n\tconstructor(\n\t\tprivate modelConfig: LangchainModelConfig,\n\t\tprivate saverConfig: PostgresSaverConfig,\n\t\tprivate storeConfig: PostgresStoreConfig,\n\t) {\n\t\tthis.modelResolver = new LangchainModelResolver(this.modelConfig);\n\t}\n\n\tprivate buildMemorySystemPrompt(slots: { name: string; usedFor: string }[]): string {\n\t\tconst lines = [\n\t\t\t'Long-term memory is enabled.',\n\t\t\t'Persist memories using the filesystem tools under these path prefixes:',\n\t\t\t...slots.map((slot) => {\n\t\t\t\tconst prefix = this.normalizeStoreRoutePrefix(slot.name);\n\t\t\t\treturn `- ${prefix}: ${slot.usedFor}`;\n\t\t\t}),\n\t\t];\n\n\t\treturn lines.join('\\n');\n\t}\n\n\tprivate buildHandoffsSystemPrompt(handoffs: { name: string; description: string }[]): string {\n\t\tconst lines = [\n\t\t\t'You can delegate tasks to the following subagents:',\n\t\t\t...handoffs.map((handoff) => `- ${handoff.name}: ${handoff.description}`),\n\t\t];\n\n\t\treturn lines.join('\\n');\n\t}\n\n\tprivate normalizeStoreRoutePrefix(prefix: string): string {\n\t\tconst trimmedPrefix = prefix.trim();\n\t\tif (trimmedPrefix.length === 0) {\n\t\t\tthrow new Error('Memory slot name cannot be empty');\n\t\t}\n\n\t\tconst withLeadingSlash = trimmedPrefix.startsWith('/') ? trimmedPrefix : `/${trimmedPrefix}`;\n\t\treturn withLeadingSlash.endsWith('/') ? withLeadingSlash : `${withLeadingSlash}/`;\n\t}\n\n\tasync createAgent(options: CreateAgentOptions): Promise<Agent> {\n\t\tlet deepAgentOptions: CreateOptions = {\n\t\t\tmodel: this.modelResolver.resolve(options.model, [], options.reasoning),\n\t\t};\n\n\t\tlet middlewares: AgentMiddleware[] = [];\n\t\tlet systemPrompt = options.instructions ?? '';\n\t\tlet disableStreamingForTools: string[] = [\n\t\t\t'write_todos',\n\t\t\t'ls',\n\t\t\t'read_file',\n\t\t\t'write_file',\n\t\t\t'edit_file',\n\t\t\t'glob',\n\t\t\t'grep',\n\t\t\t'task',\n\t\t];\n\t\tlet disableReportingForTools: string[] = disableStreamingForTools;\n\t\tlet disableModelStreamingFor: string[] = [];\n\n\t\tif (options.history) {\n\t\t\tconst checkpointer = PostgresSaver.fromConnString(this.saverConfig.connString, {\n\t\t\t\tschema: this.saverConfig.schema,\n\t\t\t});\n\n\t\t\tawait checkpointer.setup();\n\n\t\t\tdeepAgentOptions.checkpointer = checkpointer;\n\t\t}\n\n\t\tif (options.memory) {\n\t\t\tconst memorySystemPrompt = this.buildMemorySystemPrompt(options.memory.slots);\n\t\t\tsystemPrompt = systemPrompt ? `${systemPrompt}\\n\\n${memorySystemPrompt}` : memorySystemPrompt;\n\n\t\t\tdeepAgentOptions.store = new PostgresStore({\n\t\t\t\tconnectionOptions: this.storeConfig.connString,\n\t\t\t\tschema: this.storeConfig.schema,\n\t\t\t\tensureTables: true,\n\t\t\t});\n\t\t\t/**\n\t\t\t * StateBackend for ephemeral storage\n\t\t\t * StoreBackend for persistent storage\n\t\t\t */\n\t\t\tdeepAgentOptions.backend = (config) => {\n\t\t\t\tconst configWithAssistantId = { ...config, assistantId: options.memory?.assistantId };\n\t\t\t\tconst storeBackend = new StoreBackend(configWithAssistantId);\n\t\t\t\tconst routes = Object.fromEntries(\n\t\t\t\t\t(options.memory?.slots ?? []).map((slot) => {\n\t\t\t\t\t\tconst routePrefix = this.normalizeStoreRoutePrefix(slot.name);\n\t\t\t\t\t\treturn [routePrefix, storeBackend];\n\t\t\t\t\t}),\n\t\t\t\t);\n\n\t\t\t\treturn new CompositeBackend(new StateBackend(configWithAssistantId), {\n\t\t\t\t\t...routes,\n\t\t\t\t});\n\t\t\t};\n\t\t}\n\n\t\tif (options.tools) {\n\t\t\tdeepAgentOptions.tools = options.tools.tools.map((t) =>\n\t\t\t\ttool(\n\t\t\t\t\tasync (input, options) => {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst res = await t.exec(input);\n\n\t\t\t\t\t\t\tif (typeof res === 'string') return res;\n\n\t\t\t\t\t\t\treturn JSON.stringify(res);\n\t\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\t\tconsole.error('Error executing tool:', e);\n\t\t\t\t\t\t\treturn 'Something went wrong while executing the tool.';\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tname: t.name,\n\t\t\t\t\t\tdescription: t.description,\n\t\t\t\t\t\tschema: t.inputSchema,\n\t\t\t\t\t\tmetadata: {\n\t\t\t\t\t\t\ttoolKit: t.toolKit,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t),\n\t\t\t);\n\n\t\t\tmiddlewares.push(\n\t\t\t\tllmToolSelectorMiddleware({\n\t\t\t\t\tmodel: this.modelResolver.resolve(options.tools.model, ['tool-selector']),\n\t\t\t\t\tmaxTools: 128,\n\t\t\t\t\talwaysInclude: options.tools.alwaysIncludeTools ?? undefined,\n\t\t\t\t}),\n\t\t\t);\n\t\t\tdisableModelStreamingFor.push('tool-selector');\n\t\t}\n\n\t\tif (options.summarization)\n\t\t\tmiddlewares.push(\n\t\t\t\tsummarizationMiddleware({\n\t\t\t\t\tmodel: this.modelResolver.resolve(options.summarization.model),\n\t\t\t\t\ttrigger: {\n\t\t\t\t\t\ttokens: options.summarization.triggerAtTokens,\n\t\t\t\t\t},\n\t\t\t\t\tkeep: {\n\t\t\t\t\t\tmessages: options.summarization.keepMessages,\n\t\t\t\t\t},\n\t\t\t\t}),\n\t\t\t);\n\n\t\tif (options.handoffs) {\n\t\t\toptions.handoffs.every((h) => {\n\t\t\t\tif (!(h.agent instanceof LangchainAgent)) {\n\t\t\t\t\tthrow new Error('Handoff agent must be an instance of LangchainAgent');\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tconst handoffsSystemPrompt = this.buildHandoffsSystemPrompt(options.handoffs);\n\t\t\tsystemPrompt = systemPrompt ? `${systemPrompt}\\n\\n${handoffsSystemPrompt}` : handoffsSystemPrompt;\n\n\t\t\tdeepAgentOptions.subagents = options.handoffs.map((h) => {\n\t\t\t\treturn {\n\t\t\t\t\tname: h.name,\n\t\t\t\t\tdescription: h.description,\n\t\t\t\t\trunnable: (h.agent as LangchainAgent).getLangchainAgent(),\n\t\t\t\t};\n\t\t\t});\n\t\t}\n\n\t\tif (middlewares.length > 0) deepAgentOptions.middleware = middlewares;\n\n\t\tif (systemPrompt) deepAgentOptions.systemPrompt = systemPrompt;\n\n\t\tdeepAgentOptions.disableModelStreamingFor = disableModelStreamingFor;\n\t\tdeepAgentOptions.disableToolReportingFor = disableReportingForTools;\n\t\tdeepAgentOptions.disableToolStreamingFor = disableStreamingForTools;\n\n\t\treturn new LangchainAgent(deepAgentOptions);\n\t}\n}\n","import {\n\tAgent,\n\tAgentResult,\n\tAgentRunInput,\n\tContentBlock,\n\tStreamEvent,\n\tToolCall,\n\tUsageMeta,\n} from '@core/agent.interface';\nimport { ToolCallChunk, ToolMessage } from '@langchain/core/messages';\nimport { Command } from '@langchain/langgraph';\nimport { createDeepAgent, CreateDeepAgentParams } from 'deepagents';\nimport {\n\tAgentMiddleware,\n\tAIMessage,\n\tAIMessageChunk,\n\tBaseMessage,\n\tcreateMiddleware,\n\tReactAgent,\n\tStructuredTool,\n} from 'langchain';\nimport { convertToLangchainMessages } from './utils';\n\nconst ENABLE_STREAM_DEBUG_LOGS = false;\n\nfunction debugLogStream(type: StreamEvent['type'], text: string) {\n\tif (!ENABLE_STREAM_DEBUG_LOGS) return;\n\n\tconsole.warn(`${type}: ${text}`);\n}\n\nexport interface CreateOptions extends CreateDeepAgentParams {\n\t/**\n\t * Tool names to disable streaming for\n\t */\n\tdisableToolStreamingFor?: string[];\n\n\t/**\n\t * Tool names to disable streaming for\n\t */\n\tdisableToolReportingFor?: string[];\n\n\t/**\n\t * Model tags to disable streaming for\n\t */\n\tdisableModelStreamingFor?: string[];\n}\n\nexport class LangchainAgent implements Agent {\n\tprivate deepAgent: ReactAgent;\n\tprivate toolCalls: ToolCall[] = [];\n\tprivate tools?: StructuredTool[];\n\n\tconstructor(private params: CreateOptions) {\n\t\tthis.tools = params.tools;\n\n\t\tif (!params.disableModelStreamingFor) params.disableModelStreamingFor = [];\n\t\tif (!params.disableToolReportingFor) params.disableToolReportingFor = [];\n\t\tif (!params.disableToolStreamingFor) params.disableToolStreamingFor = [];\n\n\t\tlet middlewares: AgentMiddleware[] = [\n\t\t\t/**\n\t\t\t * Reasoning/thinking content blocks (OpenAI `reasoning`, Anthropic\n\t\t\t * `thinking`) are output-only artifacts that APIs reject when replayed\n\t\t\t * as input. This middleware strips them from the message history before\n\t\t\t * each model invocation so the agentic loop can safely continue after\n\t\t\t * a reasoning model produces tool calls.\n\t\t\t */\n\t\t\tcreateMiddleware({\n\t\t\t\tname: 'stripReasoningBlocks',\n\t\t\t\tbeforeModel: async (state: { messages: BaseMessage[] }) => {\n\t\t\t\t\tlet changed = false;\n\t\t\t\t\tconst cleaned = state.messages.map((msg) => {\n\t\t\t\t\t\tif (!AIMessage.isInstance(msg) || !Array.isArray(msg.content)) return msg;\n\n\t\t\t\t\t\tconst filtered = (msg.content as any[]).filter(\n\t\t\t\t\t\t\t(block: any) => block.type !== 'reasoning' && block.type !== 'thinking',\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\tif (filtered.length === msg.content.length) return msg;\n\n\t\t\t\t\t\tchanged = true;\n\t\t\t\t\t\treturn new AIMessage({\n\t\t\t\t\t\t\tcontent: filtered.length > 0 ? filtered : '',\n\t\t\t\t\t\t\ttool_calls: msg.tool_calls,\n\t\t\t\t\t\t\tid: msg.id,\n\t\t\t\t\t\t\tresponse_metadata: msg.response_metadata,\n\t\t\t\t\t\t\tusage_metadata: msg.usage_metadata,\n\t\t\t\t\t\t});\n\t\t\t\t\t});\n\n\t\t\t\t\tif (!changed) return;\n\n\t\t\t\t\treturn { messages: cleaned };\n\t\t\t\t},\n\t\t\t}),\n\t\t\tcreateMiddleware({\n\t\t\t\tname: 'toolCallsReporter',\n\t\t\t\twrapToolCall: async (request, handler) => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst res = await handler(request);\n\n\t\t\t\t\t\tif (this.params.disableToolReportingFor?.includes(request.tool?.name as string)) return res;\n\n\t\t\t\t\t\tthis.toolCalls.push({\n\t\t\t\t\t\t\tid: request.toolCall.id as string,\n\t\t\t\t\t\t\tname: (request.tool?.name as string) || '',\n\t\t\t\t\t\t\tinput: request.toolCall.args,\n\t\t\t\t\t\t\toutput: res.toJSON(),\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\t/**\n\t\t\t\t\t\t * Wrapped tool may sometimes return Command objects\n\t\t\t\t\t\t * which should actually trigger the \"updates\" mode\n\t\t\t\t\t\t * of stream. But we don't want that to happen. We\n\t\t\t\t\t\t * want to emit tool_result events from a single place.\n\t\t\t\t\t\t * So we extract the tool message from the update and\n\t\t\t\t\t\t * command.update.messages and return that. That way\n\t\t\t\t\t\t * 'messages' stream mode is triggered\n\t\t\t\t\t\t *\n\t\t\t\t\t\t * Hopefully this won't cause any issues.\n\t\t\t\t\t\t */\n\t\t\t\t\t\tif (res instanceof Command) {\n\t\t\t\t\t\t\tconst resCast: {\n\t\t\t\t\t\t\t\tupdate?: {\n\t\t\t\t\t\t\t\t\tmessages?: BaseMessage[];\n\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t} = res as any;\n\n\t\t\t\t\t\t\tif (!resCast.update?.messages || resCast.update.messages.length == 0) return res;\n\n\t\t\t\t\t\t\tconst toolMessage = resCast.update.messages.find((m: BaseMessage) => m.type == 'tool');\n\n\t\t\t\t\t\t\tif (!toolMessage) return res;\n\n\t\t\t\t\t\t\treturn toolMessage as ToolMessage;\n\t\t\t\t\t\t} else return res;\n\t\t\t\t\t} catch (e: any) {\n\t\t\t\t\t\treturn new ToolMessage({\n\t\t\t\t\t\t\tname: request.toolCall.name,\n\t\t\t\t\t\t\tcontent: 'Something went wrong: ' + e.message,\n\t\t\t\t\t\t\ttool_call_id: request.toolCall.id || 'TOOL_CALL_ERROR',\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t}),\n\t\t];\n\n\t\tif (params.middleware) middlewares = [...middlewares, ...params.middleware];\n\n\t\tparams.middleware = middlewares;\n\n\t\tthis.deepAgent = createDeepAgent(params);\n\t}\n\n\tasync run(input: AgentRunInput): Promise<AgentResult> {\n\t\tthis.toolCalls = []; // Reset tool calls for each run\n\n\t\t// Get current state to know how many messages existed before this turn\n\t\t// If no checkpointer is set, assume this is a fresh conversation\n\t\tlet messageCountBefore = 0;\n\t\ttry {\n\t\t\tconst stateBefore = await this.deepAgent.getState({\n\t\t\t\tconfigurable: {\n\t\t\t\t\tthreadId: input.threadId,\n\t\t\t\t\tthread_id: input.threadId,\n\t\t\t\t},\n\t\t\t});\n\t\t\tmessageCountBefore = (stateBefore as any)?.values?.messages?.length || 0;\n\t\t} catch {\n\t\t\t// No checkpointer set - this is fine, we'll count from 0\n\t\t}\n\n\t\tconst messages = convertToLangchainMessages(input.messages);\n\n\t\tconst result = await this.deepAgent.invoke(\n\t\t\t{\n\t\t\t\tmessages: messages,\n\t\t\t},\n\t\t\t{\n\t\t\t\tconfigurable: {\n\t\t\t\t\tthreadId: input.threadId,\n\t\t\t\t\tthread_id: input.threadId,\n\t\t\t\t},\n\t\t\t},\n\t\t);\n\n\t\t// Only sum usage from messages added in this turn\n\t\tconst newMessages = result.messages.slice(messageCountBefore);\n\t\tconst messagesWithUsage = newMessages.filter((m: any) => m.usage_metadata != null);\n\n\t\tlet usage = {\n\t\t\tinput_tokens: 0,\n\t\t\toutput_tokens: 0,\n\t\t\ttotal_tokens: 0,\n\t\t\tcache_read: 0,\n\t\t\treasoning_tokens: 0,\n\t\t\tcache_creation: 0,\n\t\t};\n\n\t\tmessagesWithUsage.forEach((m: any) => {\n\t\t\tconst cacheRead = m.usage_metadata.input_token_details?.cache_read || 0;\n\t\t\tconst provider = m.response_metadata?.model_provider;\n\n\t\t\t// Anthropic reports input_tokens excluding cached tokens;\n\t\t\t// OpenAI (and unknown providers) include cached tokens in input_tokens\n\t\t\tconst inputTokens =\n\t\t\t\tprovider === 'anthropic'\n\t\t\t\t\t? m.usage_metadata.input_tokens || 0\n\t\t\t\t\t: (m.usage_metadata.input_tokens || 0) - cacheRead;\n\n\t\t\tusage.input_tokens += inputTokens;\n\t\t\tusage.output_tokens += m.usage_metadata.output_tokens || 0;\n\t\t\tusage.total_tokens += inputTokens + (m.usage_metadata.output_tokens || 0);\n\t\t\tusage.cache_read += cacheRead;\n\t\t\tusage.reasoning_tokens += m.usage_metadata.output_token_details?.reasoning || 0;\n\t\t\tusage.cache_creation += m.usage_metadata.input_token_details?.cache_creation || 0;\n\t\t});\n\n\t\t// Build content blocks from new messages\n\t\tconst contentBlocks: ContentBlock[] = [];\n\t\tconst toolCallInputs: { [toolCallId: string]: any } = {};\n\n\t\tfor (const msg of newMessages) {\n\t\t\tconst m = msg as any;\n\t\t\tif (m.type === 'ai') {\n\t\t\t\t// Store tool call inputs for later pairing\n\t\t\t\tif (m.tool_calls && m.tool_calls.length > 0) {\n\t\t\t\t\tfor (const tc of m.tool_calls) {\n\t\t\t\t\t\ttoolCallInputs[tc.id] = tc.args;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// Add text content if present\n\t\t\t\tif (m.content) {\n\t\t\t\t\tconst textOutput = this.extractTextContent(m.content);\n\t\t\t\t\tif (textOutput.trim().length > 0) {\n\t\t\t\t\t\tcontentBlocks.push({\n\t\t\t\t\t\t\ttype: 'text',\n\t\t\t\t\t\t\toutput: textOutput,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if (m.type === 'tool') {\n\t\t\t\tcontentBlocks.push({\n\t\t\t\t\ttype: 'tool_call',\n\t\t\t\t\tname: m.name,\n\t\t\t\t\ttoolKit: this.getToolKitMeta(m.name).toolKit,\n\t\t\t\t\tinput: JSON.stringify(toolCallInputs[m.tool_call_id] || {}),\n\t\t\t\t\toutput: m.content.toString(),\n\t\t\t\t\ttoolCallId: m.tool_call_id,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\tcontent: contentBlocks,\n\t\t\ttoolCalls: this.toolCalls,\n\t\t\tusage: {\n\t\t\t\tpromptTokens: usage.input_tokens,\n\t\t\t\tcompletionTokens: usage.output_tokens,\n\t\t\t\ttotalTokens: usage.total_tokens,\n\t\t\t\tcachedPromptTokens: usage.cache_read,\n\t\t\t\treasoningTokens: usage.reasoning_tokens,\n\t\t\t\tcacheCreationTokens: usage.cache_creation,\n\t\t\t},\n\t\t};\n\t}\n\n\tasync *stream(input: AgentRunInput): AsyncGenerator<StreamEvent> {\n\t\tthis.toolCalls = []; // Reset tool calls for each stream\n\t\tconst contentBlocks: ContentBlock[] = []; // this will be our final return value\n\t\tlet finalValue;\n\n\t\t// Initialize usage metadata - accumulated from updates mode (current turn only)\n\t\tlet usageMetadata: UsageMeta = {\n\t\t\tpromptTokens: 0,\n\t\t\tcompletionTokens: 0,\n\t\t\ttotalTokens: 0,\n\t\t\tcachedPromptTokens: 0,\n\t\t\treasoningTokens: 0,\n\t\t\tcacheCreationTokens: 0,\n\t\t};\n\n\t\tconst messages = convertToLangchainMessages(input.messages);\n\n\t\tdebugLogStream('message_start', '');\n\n\t\t// Emit message start\n\t\tyield { type: 'message_start' };\n\n\t\tconst stream = await this.deepAgent.stream(\n\t\t\t{ messages },\n\t\t\t{\n\t\t\t\tconfigurable: {\n\t\t\t\t\tthreadId: input.threadId,\n\t\t\t\t\tthread_id: input.threadId,\n\t\t\t\t},\n\t\t\t\tstreamMode: ['messages', 'updates', 'values'],\n\t\t\t},\n\t\t);\n\n\t\tlet toolCalls: {\n\t\t\t[index: number]: {\n\t\t\t\ttoolCallId: string;\n\t\t\t\tname: string;\n\t\t\t};\n\t\t} = {};\n\t\tconst toolCallUpdates: {\n\t\t\t[toolCallId: string]: {\n\t\t\t\tname: string;\n\t\t\t\targs: any;\n\t\t\t};\n\t\t} = {};\n\n\t\t/**\n\t\t * Process chunks produced by the LLM\n\t\t */\n\t\tfor await (const chunk of stream) {\n\t\t\tconst [mode, data] = chunk;\n\n\t\t\tif (mode === 'messages') {\n\t\t\t\tconst [message, metadata] = data;\n\n\t\t\t\t/**\n\t\t\t\t * Some messages carry no meaningful information\n\t\t\t\t */\n\t\t\t\tif (this.shouldIgnoreMessage(message, metadata)) continue;\n\n\t\t\t\t/**\n\t\t\t\t * LLMs also stream the tool input tokens. If we see\n\t\t\t\t * tool_call_chunks inside the message, we know it's\n\t\t\t\t * a token stream for a tool call.\n\t\t\t\t */\n\t\t\t\tif (this.isToolCallMessage(message)) {\n\t\t\t\t\tconst aiMessage = message as AIMessageChunk;\n\t\t\t\t\tconst toolCallChunks = aiMessage.tool_call_chunks as ToolCallChunk[];\n\n\t\t\t\t\tfor (const toolChunk of toolCallChunks) {\n\t\t\t\t\t\tconst toolCallIndex = toolChunk.index as number;\n\n\t\t\t\t\t\tconst getToolCallInfo = () => {\n\t\t\t\t\t\t\treturn toolCalls[toolCallIndex];\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\t/**\n\t\t\t\t\t\t * On the first chunk, we get the tool name in\n\t\t\t\t\t\t * chunk.id. On sequential chunks this property\n\t\t\t\t\t\t * is set to defined. So if there is id in the\n\t\t\t\t\t\t * chunk; this is a tool_start event.\n\t\t\t\t\t\t *\n\t\t\t\t\t\t * Also different tool calls are separated using\n\t\t\t\t\t\t * the \"index\" property. This exists in all tool\n\t\t\t\t\t\t * chunk messages.\n\t\t\t\t\t\t */\n\t\t\t\t\t\tif (toolChunk.id) {\n\t\t\t\t\t\t\ttoolCalls[toolChunk.index as number] = {\n\t\t\t\t\t\t\t\ttoolCallId: toolChunk.id,\n\t\t\t\t\t\t\t\tname: toolChunk.name as string,\n\t\t\t\t\t\t\t};\n\n\t\t\t\t\t\t\tif (!this.shouldStreamToolEvent(getToolCallInfo().name)) continue;\n\n\t\t\t\t\t\t\tconst toolKitMeta = this.getToolKitMeta(getToolCallInfo().name);\n\n\t\t\t\t\t\t\tdebugLogStream('tool_start', `[${getToolCallInfo().toolCallId}] ${getToolCallInfo().name}`);\n\n\t\t\t\t\t\t\tyield {\n\t\t\t\t\t\t\t\ttype: 'tool_start',\n\t\t\t\t\t\t\t\tname: getToolCallInfo().name,\n\t\t\t\t\t\t\t\ttoolKit: toolKitMeta.toolKit,\n\t\t\t\t\t\t\t\tindex: toolCallIndex,\n\t\t\t\t\t\t\t\ttoolCallId: getToolCallInfo().toolCallId,\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (toolChunk.args && toolChunk.args.length > 0) {\n\t\t\t\t\t\t\tif (!this.shouldStreamToolEvent(getToolCallInfo().name)) continue;\n\n\t\t\t\t\t\t\tdebugLogStream('tool_input_delta', `[${getToolCallInfo().toolCallId}] ${toolChunk.args}`);\n\n\t\t\t\t\t\t\tyield {\n\t\t\t\t\t\t\t\ttype: 'tool_input_delta',\n\t\t\t\t\t\t\t\tname: getToolCallInfo().name,\n\t\t\t\t\t\t\t\targs: toolChunk.args || '',\n\t\t\t\t\t\t\t\tindex: toolCallIndex,\n\t\t\t\t\t\t\t\ttoolCallId: getToolCallInfo().toolCallId,\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else if (this.isReasoningMessage(message)) {\n\t\t\t\t\tconst contentArray = message.content as any[];\n\t\t\t\t\tfor (const block of contentArray) {\n\t\t\t\t\t\tconst delta =\n\t\t\t\t\t\t\t(block.type === 'reasoning' && block.reasoning) ||\n\t\t\t\t\t\t\t(block.type === 'thinking' && block.thinking);\n\t\t\t\t\t\tif (delta) {\n\t\t\t\t\t\t\tdebugLogStream('reasoning_delta', delta);\n\n\t\t\t\t\t\t\tyield {\n\t\t\t\t\t\t\t\ttype: 'reasoning_delta',\n\t\t\t\t\t\t\t\tdelta,\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else if (this.isArrayTextMessage(message)) {\n\t\t\t\t\tconst contentArray = message.content as any[];\n\t\t\t\t\tfor (const block of contentArray) {\n\t\t\t\t\t\tif (block.type === 'text' && block.text) {\n\t\t\t\t\t\t\tdebugLogStream('text_delta', block.text);\n\n\t\t\t\t\t\t\tyield {\n\t\t\t\t\t\t\t\ttype: 'text_delta',\n\t\t\t\t\t\t\t\tdelta: block.text,\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else if (message?.content && typeof message.content === 'string') {\n\t\t\t\t\tconst content = message.content;\n\n\t\t\t\t\tif (content.length === 0) continue;\n\n\t\t\t\t\tif (message.type == 'tool') {\n\t\t\t\t\t\t// I know it's odd but ToolMessage.name seems to corelate to the tool name\n\t\t\t\t\t\tconst toolName = message.name as string;\n\t\t\t\t\t\tconst toolKitMeta = this.getToolKitMeta(toolName);\n\n\t\t\t\t\t\tconst toolCall = Object.entries(toolCalls).find(\n\t\t\t\t\t\t\t([_, value]) => value.toolCallId == (message as ToolMessage).tool_call_id,\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\tif (!this.shouldStreamToolEvent(toolName)) continue;\n\n\t\t\t\t\t\tdebugLogStream('tool_result', `[${toolCall?.[1].toolCallId}] ${message.content}`);\n\n\t\t\t\t\t\tyield {\n\t\t\t\t\t\t\ttype: 'tool_result',\n\t\t\t\t\t\t\tname: toolName,\n\t\t\t\t\t\t\tinput:\n\t\t\t\t\t\t\t\tJSON.stringify(\n\t\t\t\t\t\t\t\t\tthis.toolCalls.find((tc) => tc.id == (toolCall as any)[1].toolCallId)?.input,\n\t\t\t\t\t\t\t\t) || '',\n\t\t\t\t\t\t\toutput: message.content,\n\t\t\t\t\t\t\ttoolKit: toolKitMeta.toolKit,\n\t\t\t\t\t\t\tindex: toolCall?.[0] ? parseInt(toolCall[0]) : 99999,\n\t\t\t\t\t\t\ttoolCallId: toolCall?.[1] ? toolCall[1].toolCallId : 'NO_ID_FOUND',\n\t\t\t\t\t\t};\n\t\t\t\t\t} else {\n\t\t\t\t\t\tdebugLogStream('text_delta', content);\n\n\t\t\t\t\t\tyield {\n\t\t\t\t\t\t\ttype: 'text_delta',\n\t\t\t\t\t\t\tdelta: content,\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tconsole.warn('Unexpected messages stream chunk', chunk);\n\t\t\t\t}\n\t\t\t} else if (mode == 'updates') {\n\t\t\t\tconst update = data;\n\n\t\t\t\t/**\n\t\t\t\t * This is how we get the tool INPUTS and llm\n\t\t\t\t * tokens that'll be used in returned content\n\t\t\t\t * blocks\n\t\t\t\t */\n\t\t\t\tif (update.model_request?.messages) {\n\t\t\t\t\tconst aiMessageChunks: AIMessageChunk[] = update.model_request.messages.filter(\n\t\t\t\t\t\t(m) => m.type == 'ai',\n\t\t\t\t\t) as AIMessageChunk[];\n\n\t\t\t\t\tfor (let aiChunk of aiMessageChunks) {\n\t\t\t\t\t\t// Accumulate usage metadata from current turn's AI messages\n\t\t\t\t\t\tconst um = aiChunk.usage_metadata;\n\t\t\t\t\t\tif (um) {\n\t\t\t\t\t\t\tconst cacheRead = um.input_token_details?.cache_read || 0;\n\t\t\t\t\t\t\tconst provider = aiChunk.response_metadata?.model_provider;\n\n\t\t\t\t\t\t\t// Anthropic reports input_tokens excluding cached tokens;\n\t\t\t\t\t\t\t// OpenAI (and unknown providers) include cached tokens in input_tokens\n\t\t\t\t\t\t\tconst inputTokens =\n\t\t\t\t\t\t\t\tprovider === 'anthropic' ? um.input_tokens || 0 : (um.input_tokens || 0) - cacheRead;\n\n\t\t\t\t\t\t\tusageMetadata.promptTokens += inputTokens;\n\t\t\t\t\t\t\tusageMetadata.completionTokens += um.output_tokens || 0;\n\t\t\t\t\t\t\tusageMetadata.totalTokens += inputTokens + (um.output_tokens || 0);\n\t\t\t\t\t\t\tusageMetadata.cachedPromptTokens! += cacheRead;\n\t\t\t\t\t\t\tusageMetadata.reasoningTokens =\n\t\t\t\t\t\t\t\t(usageMetadata.reasoningTokens || 0) + (um.output_token_details?.reasoning || 0);\n\t\t\t\t\t\t\tusageMetadata.cacheCreationTokens! += um.input_token_details?.cache_creation || 0;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (aiChunk.tool_calls && aiChunk.tool_calls.length > 0) {\n\t\t\t\t\t\t\tfor (let tc of aiChunk.tool_calls)\n\t\t\t\t\t\t\t\ttoolCallUpdates[tc.id as string] = {\n\t\t\t\t\t\t\t\t\tname: tc.name,\n\t\t\t\t\t\t\t\t\targs: tc.args,\n\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t} else if (aiChunk.content) {\n\t\t\t\t\t\t\tconst textOutput = this.extractTextContent(aiChunk.content);\n\t\t\t\t\t\t\tif (textOutput.trim().length > 0)\n\t\t\t\t\t\t\t\tcontentBlocks.push({\n\t\t\t\t\t\t\t\t\ttype: 'text',\n\t\t\t\t\t\t\t\t\toutput: textOutput,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t/**\n\t\t\t\t * This is how we get the tool OUTPUTS that'll be\n\t\t\t\t * used in returned content blocks\n\t\t\t\t */\n\t\t\t\tif (update.tools?.messages) {\n\t\t\t\t\tconst toolMessages: ToolMessage[] = update.tools.messages.filter(\n\t\t\t\t\t\t(m) => m.type == 'tool',\n\t\t\t\t\t) as ToolMessage[];\n\n\t\t\t\t\tfor (let tm of toolMessages) {\n\t\t\t\t\t\tconst input = JSON.stringify(toolCallUpdates[tm.tool_call_id].args);\n\t\t\t\t\t\tconst toolCall = this.toolCalls.find((tc) => tc.id == tm.tool_call_id);\n\n\t\t\t\t\t\tif (this.shouldStreamToolEvent(tm.name as string))\n\t\t\t\t\t\t\tcontentBlocks.push({\n\t\t\t\t\t\t\t\ttype: 'tool_call',\n\t\t\t\t\t\t\t\tname: tm.name as string,\n\t\t\t\t\t\t\t\ttoolKit: this.getToolKitMeta(tm.name as string).toolKit,\n\t\t\t\t\t\t\t\tinput: toolCall ? JSON.stringify(toolCall.input) : null,\n\t\t\t\t\t\t\t\toutput: tm.content.toString(),\n\t\t\t\t\t\t\t\ttoolCallId: tm.tool_call_id,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// console.error('\\n----------');\n\t\t\t\t// console.error('UPDATE');\n\t\t\t\t// console.error(JSON.stringify(data, null, 2));\n\t\t\t\t// console.error('----------\\n');\n\t\t\t} else if (mode == 'values') finalValue = data;\n\t\t}\n\n\t\tdebugLogStream('message_end', '\\n');\n\n\t\tyield { type: 'final_content', content: contentBlocks, usage: usageMetadata };\n\n\t\tyield { type: 'message_end' };\n\t}\n\n\tgetLangchainAgent(): ReactAgent {\n\t\treturn this.deepAgent;\n\t}\n\n\t/**\n\t * Tools have metadata fields that we can use\n\t * to get which toolKit this tool belongs.\n\t *\n\t * So we first find the tool using the tool's\n\t * name, then we extract the toolkit metadata\n\t * from that tool's metadata.\n\t */\n\tprivate getToolKitMeta(toolName: string): {\n\t\ttoolKit: string;\n\t} {\n\t\tif (!this.tools)\n\t\t\treturn {\n\t\t\t\ttoolKit: '',\n\t\t\t};\n\n\t\tconst tool = this.tools.find((t) => t.name === toolName);\n\n\t\tif (!tool) return { toolKit: '' };\n\n\t\treturn {\n\t\t\ttoolKit: tool.metadata?.toolKit as string,\n\t\t};\n\t}\n\n\tprivate isToolCallMessage(message: BaseMessage): boolean {\n\t\tif (!(message instanceof AIMessageChunk)) return false;\n\n\t\tconst toolCallChunks = message.tool_call_chunks;\n\n\t\tif (!toolCallChunks) return false;\n\n\t\tif (toolCallChunks.length == 0) return false;\n\n\t\treturn true;\n\t}\n\n\tprivate shouldIgnoreMessage = (message: BaseMessage, metadata: any) => {\n\t\tif (message.id == '__remove_all__') return true;\n\n\t\t/**\n\t\t * For some reason there are AIMessageChunk messages\n\t\t * with empty content + no tool_call_chunks\n\t\t */\n\t\tif (!this.isToolCallMessage(message) && (!message.content || message.content.length == 0)) return true;\n\n\t\t/**\n\t\t * This is the tool selector middleware\n\t\t */\n\t\tif (metadata?.langgraph_node?.includes('patchToolCallsMiddleware')) return true;\n\n\t\tfor (const disabled of this.params.disableModelStreamingFor || [])\n\t\t\tif (metadata?.tags.includes(disabled)) return true;\n\n\t\treturn false;\n\t};\n\n\tprivate shouldStreamToolEvent(toolName: string): boolean {\n\t\tconst shouldStream = !this.params.disableToolStreamingFor?.includes(toolName);\n\n\t\tif (!shouldStream && ENABLE_STREAM_DEBUG_LOGS) console.warn('SUPPRESSING TOOL EVENT: ' + toolName);\n\n\t\treturn shouldStream;\n\t}\n\n\tprivate isReasoningMessage(message: BaseMessage): boolean {\n\t\tif (!Array.isArray(message.content)) return false;\n\t\treturn (message.content as any[]).some((block) => block.type === 'reasoning' || block.type === 'thinking');\n\t}\n\n\tprivate isArrayTextMessage(message: BaseMessage): boolean {\n\t\tif (!Array.isArray(message.content)) return false;\n\t\treturn (message.content as any[]).some((block) => block.type === 'text');\n\t}\n\n\t/**\n\t * Extracts text from message content that may be a string\n\t * or an array of content blocks (as returned by reasoning models).\n\t */\n\tprivate extractTextContent(content: any): string {\n\t\tif (typeof content === 'string') return content;\n\n\t\tif (Array.isArray(content)) {\n\t\t\treturn content\n\t\t\t\t.filter((block) => block.type === 'text' && block.text)\n\t\t\t\t.map((block) => block.text)\n\t\t\t\t.join('');\n\t\t}\n\n\t\treturn content.toString();\n\t}\n}\n","import { Message } from '@core/agent.interface';\nimport { AIMessage, BaseMessage, HumanMessage, ToolMessage } from 'langchain';\n\nexport function convertToLangchainMessages(messages: Message[]): BaseMessage[] {\n\tconst result: BaseMessage[] = [];\n\tlet tcIdx = 0;\n\tlet pendingToolCallIds: string[] = [];\n\n\tfor (const msg of messages) {\n\t\tif (msg.role === 'human') {\n\t\t\tresult.push(\n\t\t\t\tnew HumanMessage({\n\t\t\t\t\tcontent: msg.content.map((c) => {\n\t\t\t\t\t\tif (c.type === 'image') {\n\t\t\t\t\t\t\treturn { type: 'image_url', image_url: { url: c.url } };\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn c;\n\t\t\t\t\t}) as any,\n\t\t\t\t}),\n\t\t\t);\n\t\t} else if (msg.role === 'ai') {\n\t\t\tif (msg.toolCalls && msg.toolCalls.length > 0) {\n\t\t\t\tpendingToolCallIds = msg.toolCalls.map(() => `tc_${++tcIdx}`);\n\t\t\t\tresult.push(\n\t\t\t\t\tnew AIMessage({\n\t\t\t\t\t\tcontent: msg.content,\n\t\t\t\t\t\ttool_calls: msg.toolCalls.map((tc, i) => ({\n\t\t\t\t\t\t\tid: pendingToolCallIds[i],\n\t\t\t\t\t\t\tname: tc.name,\n\t\t\t\t\t\t\targs: tc.input ? JSON.parse(tc.input) : {},\n\t\t\t\t\t\t})),\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tresult.push(new AIMessage(msg.content));\n\t\t\t}\n\t\t} else if (msg.role === 'tool') {\n\t\t\tconst toolCallId = pendingToolCallIds.shift();\n\t\t\tif (!toolCallId)\n\t\t\t\tthrow new Error(`ToolMessage for \"${msg.name}\" without a preceding AiMessage with toolCalls`);\n\t\t\tresult.push(\n\t\t\t\tnew ToolMessage({\n\t\t\t\t\tcontent: msg.output,\n\t\t\t\t\ttool_call_id: toolCallId,\n\t\t\t\t\tname: msg.name,\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t}\n\n\treturn result;\n}\n","import { BaseLanguageModel } from '@langchain/core/language_models/base';\nimport { ChatAnthropic } from '@langchain/anthropic';\nimport { AzureChatOpenAI, ChatOpenAI } from '@langchain/openai';\nimport { ReasoningEffort } from 'openai/resources';\n\nexport type LangchainOpenAIConfig = {\n\tapiKey: string;\n};\n\nexport type AzureModelProvider = 'openai' | 'anthropic';\n\nexport type LangchainAzureResourceConfig = {\n\tapiKey: string;\n\tmodels: {\n\t\tmodel: string;\n\t\tprovider: AzureModelProvider;\n\t\tendpoint: string;\n\t\tapiVersion: string;\n\t\tdeploymentName: string;\n\t}[];\n};\n\nexport type ResourceName = string;\n\nexport type LangchainModelConfig = {\n\topenai?: Record<string, LangchainOpenAIConfig>;\n\tazure?: Record<ResourceName, LangchainAzureResourceConfig>;\n};\n\nexport class LangchainModelResolver {\n\tconstructor(private config: LangchainModelConfig) {}\n\n\tresolve(modelString: string, tags?: string[], reasoningEffort?: ReasoningEffort): BaseLanguageModel {\n\t\tconst parts = modelString.split(':');\n\n\t\tif (parts.length === 1) {\n\t\t\tconst fullModelString = this.resolveFullModelString(modelString);\n\t\t\treturn this.resolve(fullModelString, tags, reasoningEffort);\n\t\t}\n\n\t\tif (parts.length === 2) {\n\t\t\tconst [provider, modelName] = parts;\n\t\t\treturn this.resolveByProvider(provider, modelName, modelName, tags, reasoningEffort);\n\t\t}\n\n\t\tif (parts.length === 3) {\n\t\t\tconst [provider, configName, modelName] = parts;\n\t\t\treturn this.resolveByProvider(provider, configName, modelName, tags, reasoningEffort);\n\t\t}\n\n\t\tthrow new Error(\n\t\t\t'Model string must follow format \"modelName\", \"provider:modelName\", or \"provider:configName:modelName\"',\n\t\t);\n\t}\n\n\tprivate resolveFullModelString(modelName: string): string {\n\t\tfor (const [provider, resources] of Object.entries(this.config)) {\n\t\t\tif (provider === 'openai') {\n\t\t\t\tif (modelName in (resources as Record<string, unknown>)) {\n\t\t\t\t\treturn `openai:${modelName}`;\n\t\t\t\t}\n\t\t\t} else if (provider === 'azure') {\n\t\t\t\tfor (const [resource, config] of Object.entries(\n\t\t\t\t\tresources as Record<string, { models: { model: string }[] }>,\n\t\t\t\t)) {\n\t\t\t\t\tif (config.models.some((m) => m.model === modelName)) {\n\t\t\t\t\t\treturn `azure:${resource}:${modelName}`;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tthrow new Error(`Model \"${modelName}\" not found in model config`);\n\t}\n\n\tprivate resolveByProvider(\n\t\tprovider: string,\n\t\tconfigName: string,\n\t\tmodelName: string,\n\t\ttags?: string[],\n\t\treasoningEffort?: ReasoningEffort,\n\t): BaseLanguageModel {\n\t\tswitch (provider) {\n\t\t\tcase 'openai':\n\t\t\t\treturn this.resolveOpenAI(configName, modelName, tags, reasoningEffort);\n\t\t\tcase 'azure':\n\t\t\t\treturn this.resolveAzure(configName, modelName, tags, reasoningEffort);\n\t\t\tdefault:\n\t\t\t\tthrow new Error(`Unsupported model provider: ${provider}`);\n\t\t}\n\t}\n\n\tprivate resolveOpenAI(\n\t\tconfigName: string,\n\t\tmodelName: string,\n\t\ttags?: string[],\n\t\treasoningEffort?: ReasoningEffort,\n\t): ChatOpenAI {\n\t\tconst providerConfig = this.config.openai?.[configName];\n\t\tif (!providerConfig) {\n\t\t\tthrow new Error(`Configuration \"${configName}\" for provider \"openai\" is missing`);\n\t\t}\n\n\t\treturn new ChatOpenAI({\n\t\t\tapiKey: providerConfig.apiKey,\n\t\t\tmodelName: modelName,\n\t\t\ttags: tags,\n\t\t\t...(reasoningEffort && {\n\t\t\t\treasoning: {\n\t\t\t\t\teffort: reasoningEffort,\n\t\t\t\t\tsummary: 'auto',\n\t\t\t\t},\n\t\t\t\tuseResponsesApi: true,\n\t\t\t}),\n\t\t});\n\t}\n\n\tprivate resolveAzure(\n\t\tresourceName: string,\n\t\tmodelName: string,\n\t\ttags?: string[],\n\t\treasoningEffort?: ReasoningEffort,\n\t): BaseLanguageModel {\n\t\tconst resource = this.config.azure?.[resourceName];\n\t\tif (!resource) {\n\t\t\tthrow new Error(`Resource \"${resourceName}\" for provider \"azure\" is missing`);\n\t\t}\n\n\t\tconst modelEntry = resource.models.find((m) => m.model === modelName);\n\t\tif (!modelEntry) {\n\t\t\tthrow new Error(`Model \"${modelName}\" not found in Azure resource \"${resourceName}\"`);\n\t\t}\n\n\t\tswitch (modelEntry.provider) {\n\t\t\tcase 'anthropic':\n\t\t\t\treturn this.resolveAzureAnthropic(resource, modelEntry, tags, reasoningEffort);\n\t\t\tcase 'openai':\n\t\t\t\treturn this.resolveAzureOpenAI(resource, modelEntry, tags, reasoningEffort);\n\t\t}\n\t}\n\n\tprivate resolveAzureOpenAI(\n\t\tresource: LangchainAzureResourceConfig,\n\t\tmodelEntry: LangchainAzureResourceConfig['models'][number],\n\t\ttags?: string[],\n\t\treasoningEffort?: ReasoningEffort,\n\t): AzureChatOpenAI {\n\t\t/**\n\t\t * OpenAI reasoning models require the Responses API which AzureChatOpenAI\n\t\t * does not support. We rewrite the endpoint to the Azure Responses API path.\n\t\t */\n\t\tconst endpoint = reasoningEffort\n\t\t\t? `${modelEntry.endpoint.replace(/\\/$/, '')}/openai/responses?api-version=${modelEntry.apiVersion}`\n\t\t\t: modelEntry.endpoint;\n\n\t\treturn new AzureChatOpenAI({\n\t\t\tmodel: modelEntry.model,\n\t\t\tazureOpenAIApiKey: resource.apiKey,\n\t\t\tazureOpenAIEndpoint: endpoint,\n\t\t\tazureOpenAIApiDeploymentName: modelEntry.deploymentName,\n\t\t\tazureOpenAIApiVersion: modelEntry.apiVersion,\n\t\t\ttags: tags,\n\t\t\t...(reasoningEffort && {\n\t\t\t\treasoning: {\n\t\t\t\t\teffort: reasoningEffort,\n\t\t\t\t\tsummary: 'auto',\n\t\t\t\t},\n\t\t\t}),\n\t\t});\n\t}\n\n\tprivate static readonly THINKING_BUDGET: Record<string, number> = {\n\t\tminimal: 1024,\n\t\tlow: 4096,\n\t\tmedium: 10000,\n\t\thigh: 16000,\n\t\txhigh: 32000,\n\t};\n\n\tprivate resolveAzureAnthropic(\n\t\tresource: LangchainAzureResourceConfig,\n\t\tmodelEntry: LangchainAzureResourceConfig['models'][number],\n\t\ttags?: string[],\n\t\treasoningEffort?: ReasoningEffort,\n\t): ChatAnthropic {\n\t\tconst budgetTokens = reasoningEffort ? LangchainModelResolver.THINKING_BUDGET[reasoningEffort] : undefined;\n\n\t\treturn new ChatAnthropic({\n\t\t\tmodel: modelEntry.model,\n\t\t\tapiKey: resource.apiKey,\n\t\t\tclientOptions: { baseURL: modelEntry.endpoint },\n\t\t\ttags: tags,\n\t\t\t...(budgetTokens && {\n\t\t\t\tmaxTokens: budgetTokens * 2,\n\t\t\t\tthinking: {\n\t\t\t\t\ttype: 'enabled',\n\t\t\t\t\tbudget_tokens: budgetTokens,\n\t\t\t\t},\n\t\t\t}),\n\t\t});\n\t}\n}\n","import { ToolDefinition, ToolKitSpec } from '@core/agent.interface';\nimport { ToolProvider } from './tool-provider';\nimport { ToolCache } from '@core/tools/tool-cache';\n\ntype ProviderEntry<TContext> = {\n\ttype: 'provider';\n\tprovider: ToolProvider<TContext>;\n};\n\ntype StaticEntry = {\n\ttype: 'static';\n\ttools: ToolDefinition[];\n};\n\ntype Entry<TContext> = ProviderEntry<TContext> | StaticEntry;\n\nexport interface ToolRegistryOptions {\n\t/**\n\t * Shared cache for tool specs (e.g. Redis). Values are stored as JSON strings.\n\t */\n\ttoolSpecCache?: ToolCache;\n}\n\nexport class ToolRegistry<TContext> {\n\tprivate entries = new Map<string, Entry<TContext>>();\n\tprivate toolSpecCache?: ToolCache;\n\n\tconstructor(options: ToolRegistryOptions = {}) {\n\t\tthis.toolSpecCache = options.toolSpecCache;\n\t}\n\n\tregisterProvider(toolKit: string, provider: ToolProvider<TContext>): void {\n\t\tthis.entries.set(toolKit, { type: 'provider', provider });\n\t}\n\n\tregisterTools(toolKit: string, tools: ToolDefinition[]): void {\n\t\tthis.entries.set(toolKit, { type: 'static', tools });\n\t}\n\n\tasync getTools(toolKits: string[], context: TContext): Promise<ToolDefinition[]> {\n\t\tconst results: ToolDefinition[] = [];\n\n\t\tfor (const kit of toolKits) {\n\t\t\tconst entry = this.entries.get(kit);\n\t\t\tif (!entry) {\n\t\t\t\tthrow new Error(`No tools or provider registered for tool kit: ${kit}`);\n\t\t\t}\n\n\t\t\tif (entry.type === 'static') {\n\t\t\t\tresults.push(...entry.tools);\n\t\t\t} else {\n\t\t\t\tconst provider = entry.provider;\n\t\t\t\tconst spec = await this.getToolKitSpec(kit, provider, context);\n\t\t\t\tconst tools = await provider.bindTools(spec.tools, context);\n\n\t\t\t\tfor (const tool of tools) {\n\t\t\t\t\ttool.toolKit = spec.name;\n\t\t\t\t}\n\n\t\t\t\tresults.push(...tools);\n\t\t\t}\n\t\t}\n\n\t\treturn results;\n\t}\n\n\tasync getToolKitSpecs(toolKits: string[], context: TContext): Promise<ToolKitSpec[]> {\n\t\tconst results: ToolKitSpec[] = [];\n\n\t\tfor (const kit of toolKits) {\n\t\t\tconst entry = this.entries.get(kit);\n\t\t\tif (!entry) {\n\t\t\t\tthrow new Error(`No tools or provider registered for tool kit: ${kit}`);\n\t\t\t}\n\n\t\t\tif (entry.type === 'static') {\n\t\t\t\tthrow new Error(`Tool kit \"${kit}\" was registered with static tools and has no ToolKitSpec`);\n\t\t\t}\n\n\t\t\tconst spec = await this.getToolKitSpec(kit, entry.provider, context);\n\t\t\tresults.push(spec);\n\t\t}\n\n\t\treturn results;\n\t}\n\n\tinvalidate(toolKit: string): void {\n\t\tconst entry = this.entries.get(toolKit);\n\n\t\tif (entry && entry.type === 'provider') this.toolSpecCache?.del(toolKit);\n\t}\n\n\tprivate async getToolKitSpec(\n\t\ttoolKit: string,\n\t\tprovider: ToolProvider<TContext>,\n\t\tcontext: TContext,\n\t): Promise<ToolKitSpec> {\n\t\tconst cache = this.toolSpecCache;\n\n\t\tif (cache) {\n\t\t\ttry {\n\t\t\t\tconst cached = await cache.get(toolKit);\n\n\t\t\t\tif (cached) return cached;\n\t\t\t} catch (e) {\n\t\t\t\tconsole.error('Something went wrong when hitting the cache', e);\n\t\t\t}\n\t\t}\n\n\t\tconst spec = await provider.listToolKitSpec(toolKit, context);\n\n\t\tif (cache) {\n\t\t\ttry {\n\t\t\t\tawait cache.set(toolKit, spec);\n\t\t\t} catch (e) {\n\t\t\t\tconsole.error('Something went wrong when setting the cache', e);\n\t\t\t}\n\t\t}\n\n\t\treturn spec;\n\t}\n}\n","import { ToolKitSpec } from '@core/agent.interface';\nimport Redis from 'ioredis';\nimport { z } from 'zod';\n\nexport interface ToolCache {\n\tget(toolKit: string): Promise<ToolKitSpec | null> | ToolKitSpec | null;\n\n\tset(toolKit: string, spec: ToolKitSpec): Promise<void>;\n\n\tdel(toolKit: string): Promise<void>;\n}\n\nexport class RedisToolCache implements ToolCache {\n\tprivate redis: Redis;\n\n\tconstructor(connectionString: string) {\n\t\tthis.redis = new Redis(connectionString);\n\t}\n\n\tasync get(toolKit: string): Promise<ToolKitSpec | null> {\n\t\tconst data = await this.redis.get(`tool-cache:${toolKit}`);\n\n\t\tif (!data) return null;\n\n\t\ttry {\n\t\t\tconst parsed = JSON.parse(data);\n\n\t\t\tif (!parsed || !Array.isArray(parsed.tools)) return null;\n\n\t\t\treturn {\n\t\t\t\t...parsed,\n\t\t\t\ttools: parsed.tools.map((spec: any) => ({\n\t\t\t\t\t...spec,\n\t\t\t\t\tinputSchema: z.fromJSONSchema(spec.inputSchema),\n\t\t\t\t})),\n\t\t\t};\n\t\t} catch (e) {\n\t\t\tconsole.error('Failed to parse cached tools', e);\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tasync set(toolKit: string, spec: ToolKitSpec): Promise<void> {\n\t\tconst serialized = {\n\t\t\t...spec,\n\t\t\ttools: spec.tools.map((tool) => ({\n\t\t\t\t...tool,\n\t\t\t\tinputSchema: tool.inputSchema.toJSONSchema(),\n\t\t\t})),\n\t\t};\n\t\tawait this.redis.set(`tool-cache:${toolKit}`, JSON.stringify(serialized));\n\t}\n\n\tasync del(toolKit: string): Promise<void> {\n\t\tawait this.redis.del(`tool-cache:${toolKit}`);\n\t}\n}\n\nexport class InMemoryToolCache implements ToolCache {\n\tprivate cache = new Map<string, ToolKitSpec>();\n\n\tget(toolKit: string): ToolKitSpec | null {\n\t\treturn this.cache.get(`tool-cache:${toolKit}`) ?? null;\n\t}\n\n\tasync set(toolKit: string, spec: ToolKitSpec): Promise<void> {\n\t\tthis.cache.set(`tool-cache:${toolKit}`, spec);\n\t}\n\n\tasync del(toolKit: string): Promise<void> {\n\t\tthis.cache.delete(`tool-cache:${toolKit}`);\n\t}\n}\n"],"mappings":"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","names":["import_deepagents","import_langchain","import_langchain","input","tool","options","tool","Redis","tool"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/runtime/langchain/factory.ts","../src/runtime/langchain/agent.ts","../src/runtime/langchain/utils.ts","../src/runtime/langchain/model-resolver.ts","../src/core/tools/tool-registry.ts","../src/core/tools/tool-cache.ts"],"sourcesContent":["// Core Interfaces & Factory\nexport { AgentFactory, CreateAgentOptions, AgentHandoff } from './core/agent.factory';\nexport {\n\tAgent,\n\tAgentRunInput,\n\tAgentResult,\n\tMessage,\n\tHumanMessage,\n\tAiMessage,\n\tToolMessage,\n\tContentBlock,\n\tUsageMeta,\n\tToolKitSpec,\n\tToolSpec,\n\tToolDefinition,\n\tToolCall,\n\tStreamEvent,\n} from './core/agent.interface';\nexport { LangchainAgentFactory } from './runtime/langchain/factory';\nexport { type LangchainModelConfig } from './runtime/langchain/model-resolver';\n\n// Tools\nexport { ToolRegistry } from './core/tools/tool-registry';\nexport { ToolProvider } from './core/tools/tool-provider';\nexport { ToolCache, RedisToolCache, InMemoryToolCache } from './core/tools/tool-cache';\n","import { AgentFactory, CreateAgentOptions } from '@core/agent.factory';\nimport { Agent } from '@core/agent.interface';\nimport { PostgresSaver } from '@langchain/langgraph-checkpoint-postgres';\n// @ts-ignore -_-\nimport { PostgresStore } from '@langchain/langgraph-checkpoint-postgres/store';\nimport { CompositeBackend, StateBackend, StoreBackend } from 'deepagents';\nimport { AgentMiddleware, llmToolSelectorMiddleware, summarizationMiddleware, tool } from 'langchain';\nimport { CreateOptions, LangchainAgent } from './agent';\nimport { LangchainModelConfig, LangchainModelResolver } from './model-resolver';\n\nexport interface PostgresSaverConfig {\n\tconnString: string;\n\tschema: string;\n}\n\nexport interface PostgresStoreConfig {\n\tconnString: string;\n\tschema: string;\n}\n\nexport class LangchainAgentFactory implements AgentFactory {\n\tprivate modelResolver: LangchainModelResolver;\n\n\tconstructor(\n\t\tprivate modelConfig: LangchainModelConfig,\n\t\tprivate saverConfig: PostgresSaverConfig,\n\t\tprivate storeConfig: PostgresStoreConfig,\n\t) {\n\t\tthis.modelResolver = new LangchainModelResolver(this.modelConfig);\n\t}\n\n\tprivate buildMemorySystemPrompt(slots: { name: string; usedFor: string }[]): string {\n\t\tconst lines = [\n\t\t\t'Long-term memory is enabled.',\n\t\t\t'Persist memories using the filesystem tools under these path prefixes:',\n\t\t\t...slots.map((slot) => {\n\t\t\t\tconst prefix = this.normalizeStoreRoutePrefix(slot.name);\n\t\t\t\treturn `- ${prefix}: ${slot.usedFor}`;\n\t\t\t}),\n\t\t];\n\n\t\treturn lines.join('\\n');\n\t}\n\n\tprivate buildHandoffsSystemPrompt(handoffs: { name: string; description: string }[]): string {\n\t\tconst lines = [\n\t\t\t'You can delegate tasks to the following subagents:',\n\t\t\t...handoffs.map((handoff) => `- ${handoff.name}: ${handoff.description}`),\n\t\t];\n\n\t\treturn lines.join('\\n');\n\t}\n\n\tprivate normalizeStoreRoutePrefix(prefix: string): string {\n\t\tconst trimmedPrefix = prefix.trim();\n\t\tif (trimmedPrefix.length === 0) {\n\t\t\tthrow new Error('Memory slot name cannot be empty');\n\t\t}\n\n\t\tconst withLeadingSlash = trimmedPrefix.startsWith('/') ? trimmedPrefix : `/${trimmedPrefix}`;\n\t\treturn withLeadingSlash.endsWith('/') ? withLeadingSlash : `${withLeadingSlash}/`;\n\t}\n\n\tasync createAgent(options: CreateAgentOptions): Promise<Agent> {\n\t\tlet deepAgentOptions: CreateOptions = {\n\t\t\tmodel: this.modelResolver.resolve(options.model, [], options.reasoning),\n\t\t};\n\n\t\tlet middlewares: AgentMiddleware[] = [];\n\t\tlet systemPrompt = options.instructions ?? '';\n\t\tlet disableStreamingForTools: string[] = [\n\t\t\t'write_todos',\n\t\t\t'ls',\n\t\t\t'read_file',\n\t\t\t'write_file',\n\t\t\t'edit_file',\n\t\t\t'glob',\n\t\t\t'grep',\n\t\t\t'task',\n\t\t];\n\t\tlet disableReportingForTools: string[] = disableStreamingForTools;\n\t\tlet disableModelStreamingFor: string[] = [];\n\n\t\tif (options.history) {\n\t\t\tconst checkpointer = PostgresSaver.fromConnString(this.saverConfig.connString, {\n\t\t\t\tschema: this.saverConfig.schema,\n\t\t\t});\n\n\t\t\tawait checkpointer.setup();\n\n\t\t\tdeepAgentOptions.checkpointer = checkpointer;\n\t\t}\n\n\t\tif (options.memory) {\n\t\t\tconst memorySystemPrompt = this.buildMemorySystemPrompt(options.memory.slots);\n\t\t\tsystemPrompt = systemPrompt ? `${systemPrompt}\\n\\n${memorySystemPrompt}` : memorySystemPrompt;\n\n\t\t\tdeepAgentOptions.store = new PostgresStore({\n\t\t\t\tconnectionOptions: this.storeConfig.connString,\n\t\t\t\tschema: this.storeConfig.schema,\n\t\t\t\tensureTables: true,\n\t\t\t});\n\t\t\t/**\n\t\t\t * StateBackend for ephemeral storage\n\t\t\t * StoreBackend for persistent storage\n\t\t\t */\n\t\t\tdeepAgentOptions.backend = (config) => {\n\t\t\t\tconst configWithAssistantId = { ...config, assistantId: options.memory?.assistantId };\n\t\t\t\tconst storeBackend = new StoreBackend(configWithAssistantId);\n\t\t\t\tconst routes = Object.fromEntries(\n\t\t\t\t\t(options.memory?.slots ?? []).map((slot) => {\n\t\t\t\t\t\tconst routePrefix = this.normalizeStoreRoutePrefix(slot.name);\n\t\t\t\t\t\treturn [routePrefix, storeBackend];\n\t\t\t\t\t}),\n\t\t\t\t);\n\n\t\t\t\treturn new CompositeBackend(new StateBackend(configWithAssistantId), {\n\t\t\t\t\t...routes,\n\t\t\t\t});\n\t\t\t};\n\t\t}\n\n\t\tif (options.tools) {\n\t\t\tdeepAgentOptions.tools = options.tools.tools.map((t) =>\n\t\t\t\ttool(\n\t\t\t\t\tasync (input, options) => {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst res = await t.exec(input);\n\n\t\t\t\t\t\t\tif (typeof res === 'string') return res;\n\n\t\t\t\t\t\t\treturn JSON.stringify(res);\n\t\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\t\tconsole.error('Error executing tool:', e);\n\t\t\t\t\t\t\treturn 'Something went wrong while executing the tool.';\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tname: t.name,\n\t\t\t\t\t\tdescription: t.description,\n\t\t\t\t\t\tschema: t.inputSchema,\n\t\t\t\t\t\tmetadata: {\n\t\t\t\t\t\t\ttoolKit: t.toolKit,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t),\n\t\t\t);\n\n\t\t\tmiddlewares.push(\n\t\t\t\tllmToolSelectorMiddleware({\n\t\t\t\t\tmodel: this.modelResolver.resolve(options.tools.model, ['tool-selector']),\n\t\t\t\t\tmaxTools: 128,\n\t\t\t\t\talwaysInclude: options.tools.alwaysIncludeTools ?? undefined,\n\t\t\t\t}),\n\t\t\t);\n\t\t\tdisableModelStreamingFor.push('tool-selector');\n\t\t}\n\n\t\tif (options.summarization)\n\t\t\tmiddlewares.push(\n\t\t\t\tsummarizationMiddleware({\n\t\t\t\t\tmodel: this.modelResolver.resolve(options.summarization.model),\n\t\t\t\t\ttrigger: {\n\t\t\t\t\t\ttokens: options.summarization.triggerAtTokens,\n\t\t\t\t\t},\n\t\t\t\t\tkeep: {\n\t\t\t\t\t\tmessages: options.summarization.keepMessages,\n\t\t\t\t\t},\n\t\t\t\t}),\n\t\t\t);\n\n\t\tif (options.handoffs) {\n\t\t\toptions.handoffs.every((h) => {\n\t\t\t\tif (!(h.agent instanceof LangchainAgent)) {\n\t\t\t\t\tthrow new Error('Handoff agent must be an instance of LangchainAgent');\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tconst handoffsSystemPrompt = this.buildHandoffsSystemPrompt(options.handoffs);\n\t\t\tsystemPrompt = systemPrompt ? `${systemPrompt}\\n\\n${handoffsSystemPrompt}` : handoffsSystemPrompt;\n\n\t\t\tdeepAgentOptions.subagents = options.handoffs.map((h) => {\n\t\t\t\treturn {\n\t\t\t\t\tname: h.name,\n\t\t\t\t\tdescription: h.description,\n\t\t\t\t\trunnable: (h.agent as LangchainAgent).getLangchainAgent(),\n\t\t\t\t};\n\t\t\t});\n\t\t}\n\n\t\tif (middlewares.length > 0) deepAgentOptions.middleware = middlewares;\n\n\t\tif (systemPrompt) deepAgentOptions.systemPrompt = systemPrompt;\n\n\t\tdeepAgentOptions.disableModelStreamingFor = disableModelStreamingFor;\n\t\tdeepAgentOptions.disableToolReportingFor = disableReportingForTools;\n\t\tdeepAgentOptions.disableToolStreamingFor = disableStreamingForTools;\n\n\t\treturn new LangchainAgent(deepAgentOptions);\n\t}\n}\n","import {\n\tAgent,\n\tAgentResult,\n\tAgentRunInput,\n\tContentBlock,\n\tStreamEvent,\n\tToolCall,\n\tUsageMeta,\n} from '@core/agent.interface';\nimport { ToolCallChunk, ToolMessage } from '@langchain/core/messages';\nimport { Command } from '@langchain/langgraph';\nimport { createDeepAgent, CreateDeepAgentParams } from 'deepagents';\nimport {\n\tAgentMiddleware,\n\tAIMessage,\n\tAIMessageChunk,\n\tBaseMessage,\n\tcreateMiddleware,\n\tReactAgent,\n\tStructuredTool,\n} from 'langchain';\nimport { convertToLangchainMessages } from './utils';\n\nconst ENABLE_STREAM_DEBUG_LOGS = false;\n\n/**\n * Default number of effective model invocations the agent should be allowed\n * before LangGraph's recursion limit kicks in. LangGraph counts every graph\n * *superstep* (node visit) toward its limit, so middleware nodes that run\n * before/after each model call inflate the raw count significantly.\n */\nconst DEFAULT_EFFECTIVE_MODEL_INVOCATIONS = 25;\n\n/**\n * Extra model-tool cycles added beyond the effective limit to give the model\n * room to receive the \"wrap up\" tool error and produce a final text response.\n * If the model stubbornly keeps issuing tool calls, each one will receive the\n * same error message until the buffer is exhausted.\n */\nconst GRACEFUL_SHUTDOWN_BUFFER_CYCLES = 3;\n\nconst INVOCATION_LIMIT_TOOL_ERROR =\n\t'[SYSTEM] You have reached the maximum number of tool invocations for this turn. ' +\n\t'Do NOT call any more tools. Instead, respond with a text message that:\\n' +\n\t'1. Summarizes the progress made so far and any partial results.\\n' +\n\t'2. Explains what could not be completed and why.\\n' +\n\t'3. Suggests alternative approaches or next steps the user can take.';\n\nfunction debugLogStream(type: StreamEvent['type'], text: string) {\n\tif (!ENABLE_STREAM_DEBUG_LOGS) return;\n\n\tconsole.warn(`${type}: ${text}`);\n}\n\nexport interface CreateOptions extends CreateDeepAgentParams {\n\t/**\n\t * Tool names to disable streaming for\n\t */\n\tdisableToolStreamingFor?: string[];\n\n\t/**\n\t * Tool names to disable streaming for\n\t */\n\tdisableToolReportingFor?: string[];\n\n\t/**\n\t * Model tags to disable streaming for\n\t */\n\tdisableModelStreamingFor?: string[];\n\n\t/**\n\t * Maximum number of effective model invocations before the agent\n\t * begins returning tool errors asking the model to wrap up.\n\t * Defaults to {@link DEFAULT_EFFECTIVE_MODEL_INVOCATIONS} (25).\n\t */\n\tmaxModelInvocations?: number;\n}\n\nexport class LangchainAgent implements Agent {\n\tprivate deepAgent: ReactAgent;\n\tprivate toolCalls: ToolCall[] = [];\n\tprivate tools?: StructuredTool[];\n\tprivate recursionLimit: number;\n\tprivate modelInvocationCount = 0;\n\tprivate effectiveModelLimit: number;\n\n\tconstructor(private params: CreateOptions) {\n\t\tthis.tools = params.tools;\n\t\tthis.effectiveModelLimit = params.maxModelInvocations ?? DEFAULT_EFFECTIVE_MODEL_INVOCATIONS;\n\n\t\tif (!params.disableModelStreamingFor) params.disableModelStreamingFor = [];\n\t\tif (!params.disableToolReportingFor) params.disableToolReportingFor = [];\n\t\tif (!params.disableToolStreamingFor) params.disableToolStreamingFor = [];\n\n\t\tlet middlewares: AgentMiddleware[] = [\n\t\t\t/**\n\t\t\t * Reasoning/thinking content blocks (OpenAI `reasoning`, Anthropic\n\t\t\t * `thinking`) are output-only artifacts that APIs reject when replayed\n\t\t\t * as input. This middleware strips them from the message history before\n\t\t\t * each model invocation so the agentic loop can safely continue after\n\t\t\t * a reasoning model produces tool calls.\n\t\t\t */\n\t\t\tcreateMiddleware({\n\t\t\t\tname: 'stripReasoningBlocks',\n\t\t\t\tbeforeModel: async (state: { messages: BaseMessage[] }) => {\n\t\t\t\t\tlet changed = false;\n\t\t\t\t\tconst cleaned = state.messages.map((msg) => {\n\t\t\t\t\t\tif (!AIMessage.isInstance(msg) || !Array.isArray(msg.content)) return msg;\n\n\t\t\t\t\t\tconst filtered = (msg.content as any[]).filter(\n\t\t\t\t\t\t\t(block: any) => block.type !== 'reasoning' && block.type !== 'thinking',\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\tif (filtered.length === msg.content.length) return msg;\n\n\t\t\t\t\t\tchanged = true;\n\t\t\t\t\t\treturn new AIMessage({\n\t\t\t\t\t\t\tcontent: filtered.length > 0 ? filtered : '',\n\t\t\t\t\t\t\ttool_calls: msg.tool_calls,\n\t\t\t\t\t\t\tid: msg.id,\n\t\t\t\t\t\t\tresponse_metadata: msg.response_metadata,\n\t\t\t\t\t\t\tusage_metadata: msg.usage_metadata,\n\t\t\t\t\t\t});\n\t\t\t\t\t});\n\n\t\t\t\t\tif (!changed) return;\n\n\t\t\t\t\treturn { messages: cleaned };\n\t\t\t\t},\n\t\t\t}),\n\t\t\tcreateMiddleware({\n\t\t\t\tname: 'toolCallsReporter',\n\t\t\t\twrapToolCall: async (request, handler) => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst res = await handler(request);\n\n\t\t\t\t\t\tif (this.params.disableToolReportingFor?.includes(request.tool?.name as string)) return res;\n\n\t\t\t\t\t\tthis.toolCalls.push({\n\t\t\t\t\t\t\tid: request.toolCall.id as string,\n\t\t\t\t\t\t\tname: (request.tool?.name as string) || '',\n\t\t\t\t\t\t\tinput: request.toolCall.args,\n\t\t\t\t\t\t\toutput: res.toJSON(),\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\t/**\n\t\t\t\t\t\t * Wrapped tool may sometimes return Command objects\n\t\t\t\t\t\t * which should actually trigger the \"updates\" mode\n\t\t\t\t\t\t * of stream. But we don't want that to happen. We\n\t\t\t\t\t\t * want to emit tool_result events from a single place.\n\t\t\t\t\t\t * So we extract the tool message from the update and\n\t\t\t\t\t\t * command.update.messages and return that. That way\n\t\t\t\t\t\t * 'messages' stream mode is triggered\n\t\t\t\t\t\t *\n\t\t\t\t\t\t * Hopefully this won't cause any issues.\n\t\t\t\t\t\t */\n\t\t\t\t\t\tif (res instanceof Command) {\n\t\t\t\t\t\t\tconst resCast: {\n\t\t\t\t\t\t\t\tupdate?: {\n\t\t\t\t\t\t\t\t\tmessages?: BaseMessage[];\n\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t} = res as any;\n\n\t\t\t\t\t\t\tif (!resCast.update?.messages || resCast.update.messages.length == 0) return res;\n\n\t\t\t\t\t\t\tconst toolMessage = resCast.update.messages.find((m: BaseMessage) => m.type == 'tool');\n\n\t\t\t\t\t\t\tif (!toolMessage) return res;\n\n\t\t\t\t\t\t\treturn toolMessage as ToolMessage;\n\t\t\t\t\t\t} else return res;\n\t\t\t\t\t} catch (e: any) {\n\t\t\t\t\t\treturn new ToolMessage({\n\t\t\t\t\t\t\tname: request.toolCall.name,\n\t\t\t\t\t\t\tcontent: 'Something went wrong: ' + e.message,\n\t\t\t\t\t\t\ttool_call_id: request.toolCall.id || 'TOOL_CALL_ERROR',\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t}),\n\t\t\t/**\n\t\t\t * Tracks model invocations and gracefully stops the agent when\n\t\t\t * the limit is reached. Instead of letting LangGraph throw a\n\t\t\t * hard GraphRecursionError, tool calls beyond the limit receive\n\t\t\t * an error message asking the model to summarize and wrap up.\n\t\t\t */\n\t\t\tcreateMiddleware({\n\t\t\t\tname: 'invocationLimitGuard',\n\t\t\t\twrapModelCall: async (request, handler) => {\n\t\t\t\t\tthis.modelInvocationCount++;\n\t\t\t\t\treturn handler(request);\n\t\t\t\t},\n\t\t\t\twrapToolCall: async (request, handler) => {\n\t\t\t\t\tif (this.modelInvocationCount > this.effectiveModelLimit) {\n\t\t\t\t\t\treturn new ToolMessage({\n\t\t\t\t\t\t\tname: request.toolCall.name,\n\t\t\t\t\t\t\tcontent: INVOCATION_LIMIT_TOOL_ERROR,\n\t\t\t\t\t\t\ttool_call_id: request.toolCall.id || 'INVOCATION_LIMIT',\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\treturn handler(request);\n\t\t\t\t},\n\t\t\t}),\n\t\t];\n\n\t\tif (params.middleware) middlewares = [...middlewares, ...params.middleware];\n\n\t\tparams.middleware = middlewares;\n\n\t\tthis.deepAgent = createDeepAgent(params);\n\t\tthis.recursionLimit = this.computeRecursionLimit();\n\t}\n\n\t/**\n\t * Computes an adjusted LangGraph recursion limit that compensates for\n\t * middleware graph nodes. LangGraph counts every *superstep* (node visit)\n\t * toward its recursion limit, but middleware hooks like `beforeModel`,\n\t * `afterModel`, `beforeAgent`, and `afterAgent` each add extra graph\n\t * nodes that consume steps without representing real model invocations.\n\t *\n\t * This method introspects the compiled graph to count how many nodes\n\t * participate in one model-tool cycle and scales the limit so the agent\n\t * gets {@link DEFAULT_EFFECTIVE_MODEL_INVOCATIONS} real model calls,\n\t * plus a buffer of extra cycles for graceful shutdown (where tool calls\n\t * return an error asking the model to wrap up).\n\t *\n\t * Formula:\n\t * recursionLimit = N_beforeAgent\n\t * + (K + buffer) * (N_beforeModel + 1 + N_afterModel + 1)\n\t * + N_afterAgent\n\t *\n\t * Where K = desired effective model invocations, buffer =\n\t * {@link GRACEFUL_SHUTDOWN_BUFFER_CYCLES}, and the +1s are for the\n\t * `model_request` and `tools` core nodes.\n\t */\n\tprivate computeRecursionLimit(): number {\n\t\tconst graph = (this.deepAgent as any).graph;\n\t\tconst nodeNames: string[] = graph?.nodes ? Object.keys(graph.nodes) : [];\n\n\t\tlet beforeAgentCount = 0;\n\t\tlet beforeModelCount = 0;\n\t\tlet afterModelCount = 0;\n\t\tlet afterAgentCount = 0;\n\n\t\tfor (const name of nodeNames) {\n\t\t\tif (name.endsWith('.before_agent')) beforeAgentCount++;\n\t\t\telse if (name.endsWith('.before_model')) beforeModelCount++;\n\t\t\telse if (name.endsWith('.after_model')) afterModelCount++;\n\t\t\telse if (name.endsWith('.after_agent')) afterAgentCount++;\n\t\t}\n\n\t\t// Nodes visited per model-tool cycle: beforeModel chain + model_request + afterModel chain + tools\n\t\tconst nodesPerCycle = beforeModelCount + 1 + afterModelCount + 1;\n\t\tconst totalCycles = this.effectiveModelLimit + GRACEFUL_SHUTDOWN_BUFFER_CYCLES;\n\n\t\treturn beforeAgentCount + totalCycles * nodesPerCycle + afterAgentCount;\n\t}\n\n\tasync run(input: AgentRunInput): Promise<AgentResult> {\n\t\tthis.toolCalls = [];\n\t\tthis.modelInvocationCount = 0;\n\n\t\t// Get current state to know how many messages existed before this turn\n\t\t// If no checkpointer is set, assume this is a fresh conversation\n\t\tlet messageCountBefore = 0;\n\t\ttry {\n\t\t\tconst stateBefore = await this.deepAgent.getState({\n\t\t\t\tconfigurable: {\n\t\t\t\t\tthreadId: input.threadId,\n\t\t\t\t\tthread_id: input.threadId,\n\t\t\t\t},\n\t\t\t});\n\t\t\tmessageCountBefore = (stateBefore as any)?.values?.messages?.length || 0;\n\t\t} catch {\n\t\t\t// No checkpointer set - this is fine, we'll count from 0\n\t\t}\n\n\t\tconst messages = convertToLangchainMessages(input.messages);\n\n\t\tconst result = await this.deepAgent.invoke(\n\t\t\t{\n\t\t\t\tmessages: messages,\n\t\t\t},\n\t\t\t{\n\t\t\t\t...(input.signal ? { signal: input.signal } : {}),\n\t\t\t\trecursionLimit: this.recursionLimit,\n\t\t\t\tconfigurable: {\n\t\t\t\t\tthreadId: input.threadId,\n\t\t\t\t\tthread_id: input.threadId,\n\t\t\t\t},\n\t\t\t},\n\t\t);\n\n\t\t// Only sum usage from messages added in this turn\n\t\tconst newMessages = result.messages.slice(messageCountBefore);\n\t\tconst messagesWithUsage = newMessages.filter((m: any) => m.usage_metadata != null);\n\n\t\tlet usage = {\n\t\t\tinput_tokens: 0,\n\t\t\toutput_tokens: 0,\n\t\t\ttotal_tokens: 0,\n\t\t\tcache_read: 0,\n\t\t\treasoning_tokens: 0,\n\t\t\tcache_creation: 0,\n\t\t};\n\n\t\tmessagesWithUsage.forEach((m: any) => {\n\t\t\tconst cacheRead = m.usage_metadata.input_token_details?.cache_read || 0;\n\t\t\tconst provider = m.response_metadata?.model_provider;\n\n\t\t\t// Anthropic reports input_tokens excluding cached tokens;\n\t\t\t// OpenAI (and unknown providers) include cached tokens in input_tokens\n\t\t\tconst inputTokens =\n\t\t\t\tprovider === 'anthropic'\n\t\t\t\t\t? m.usage_metadata.input_tokens || 0\n\t\t\t\t\t: (m.usage_metadata.input_tokens || 0) - cacheRead;\n\n\t\t\tusage.input_tokens += inputTokens;\n\t\t\tusage.output_tokens += m.usage_metadata.output_tokens || 0;\n\t\t\tusage.total_tokens += inputTokens + (m.usage_metadata.output_tokens || 0);\n\t\t\tusage.cache_read += cacheRead;\n\t\t\tusage.reasoning_tokens += m.usage_metadata.output_token_details?.reasoning || 0;\n\t\t\tusage.cache_creation += m.usage_metadata.input_token_details?.cache_creation || 0;\n\t\t});\n\n\t\t// Build content blocks from new messages\n\t\tconst contentBlocks: ContentBlock[] = [];\n\t\tconst toolCallInputs: { [toolCallId: string]: any } = {};\n\n\t\tfor (const msg of newMessages) {\n\t\t\tconst m = msg as any;\n\t\t\tif (m.type === 'ai') {\n\t\t\t\t// Store tool call inputs for later pairing\n\t\t\t\tif (m.tool_calls && m.tool_calls.length > 0) {\n\t\t\t\t\tfor (const tc of m.tool_calls) {\n\t\t\t\t\t\ttoolCallInputs[tc.id] = tc.args;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// Add text content if present\n\t\t\t\tif (m.content) {\n\t\t\t\t\tconst textOutput = this.extractTextContent(m.content);\n\t\t\t\t\tif (textOutput.trim().length > 0) {\n\t\t\t\t\t\tcontentBlocks.push({\n\t\t\t\t\t\t\ttype: 'text',\n\t\t\t\t\t\t\toutput: textOutput,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if (m.type === 'tool') {\n\t\t\t\tcontentBlocks.push({\n\t\t\t\t\ttype: 'tool_call',\n\t\t\t\t\tname: m.name,\n\t\t\t\t\ttoolKit: this.getToolKitMeta(m.name).toolKit,\n\t\t\t\t\tinput: JSON.stringify(toolCallInputs[m.tool_call_id] || {}),\n\t\t\t\t\toutput: m.content.toString(),\n\t\t\t\t\ttoolCallId: m.tool_call_id,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\tcontent: contentBlocks,\n\t\t\ttoolCalls: this.toolCalls,\n\t\t\tusage: {\n\t\t\t\tpromptTokens: usage.input_tokens,\n\t\t\t\tcompletionTokens: usage.output_tokens,\n\t\t\t\ttotalTokens: usage.total_tokens,\n\t\t\t\tcachedPromptTokens: usage.cache_read,\n\t\t\t\treasoningTokens: usage.reasoning_tokens,\n\t\t\t\tcacheCreationTokens: usage.cache_creation,\n\t\t\t},\n\t\t};\n\t}\n\n\tasync *stream(input: AgentRunInput): AsyncGenerator<StreamEvent> {\n\t\tthis.toolCalls = [];\n\t\tthis.modelInvocationCount = 0;\n\t\tconst contentBlocks: ContentBlock[] = []; // this will be our final return value\n\t\tlet finalValue;\n\n\t\t// Initialize usage metadata - accumulated from updates mode (current turn only)\n\t\tlet usageMetadata: UsageMeta = {\n\t\t\tpromptTokens: 0,\n\t\t\tcompletionTokens: 0,\n\t\t\ttotalTokens: 0,\n\t\t\tcachedPromptTokens: 0,\n\t\t\treasoningTokens: 0,\n\t\t\tcacheCreationTokens: 0,\n\t\t};\n\n\t\tconst messages = convertToLangchainMessages(input.messages);\n\n\t\tdebugLogStream('message_start', '');\n\n\t\t// Emit message start\n\t\tyield { type: 'message_start' };\n\n\t\tconst stream = await this.deepAgent.stream(\n\t\t\t{ messages },\n\t\t\t{\n\t\t\t\trecursionLimit: this.recursionLimit,\n\t\t\t\tconfigurable: {\n\t\t\t\t\tthreadId: input.threadId,\n\t\t\t\t\tthread_id: input.threadId,\n\t\t\t\t},\n\t\t\t\tstreamMode: ['messages', 'updates', 'values'],\n\t\t\t},\n\t\t);\n\n\t\tlet toolCalls: {\n\t\t\t[index: number]: {\n\t\t\t\ttoolCallId: string;\n\t\t\t\tname: string;\n\t\t\t};\n\t\t} = {};\n\t\tconst toolCallUpdates: {\n\t\t\t[toolCallId: string]: {\n\t\t\t\tname: string;\n\t\t\t\targs: any;\n\t\t\t};\n\t\t} = {};\n\n\t\t/**\n\t\t * Process chunks produced by the LLM\n\t\t */\n\t\tfor await (const chunk of stream) {\n\t\t\tconst [mode, data] = chunk;\n\n\t\t\tif (mode === 'messages') {\n\t\t\t\tconst [message, metadata] = data;\n\n\t\t\t\t/**\n\t\t\t\t * Some messages carry no meaningful information\n\t\t\t\t */\n\t\t\t\tif (this.shouldIgnoreMessage(message, metadata)) continue;\n\n\t\t\t\t/**\n\t\t\t\t * LLMs also stream the tool input tokens. If we see\n\t\t\t\t * tool_call_chunks inside the message, we know it's\n\t\t\t\t * a token stream for a tool call.\n\t\t\t\t */\n\t\t\t\tif (this.isToolCallMessage(message)) {\n\t\t\t\t\tconst aiMessage = message as AIMessageChunk;\n\t\t\t\t\tconst toolCallChunks = aiMessage.tool_call_chunks as ToolCallChunk[];\n\n\t\t\t\t\tfor (const toolChunk of toolCallChunks) {\n\t\t\t\t\t\tconst toolCallIndex = toolChunk.index as number;\n\n\t\t\t\t\t\tconst getToolCallInfo = () => {\n\t\t\t\t\t\t\treturn toolCalls[toolCallIndex];\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\t/**\n\t\t\t\t\t\t * On the first chunk, we get the tool name in\n\t\t\t\t\t\t * chunk.id. On sequential chunks this property\n\t\t\t\t\t\t * is set to defined. So if there is id in the\n\t\t\t\t\t\t * chunk; this is a tool_start event.\n\t\t\t\t\t\t *\n\t\t\t\t\t\t * Also different tool calls are separated using\n\t\t\t\t\t\t * the \"index\" property. This exists in all tool\n\t\t\t\t\t\t * chunk messages.\n\t\t\t\t\t\t */\n\t\t\t\t\t\tif (toolChunk.id) {\n\t\t\t\t\t\t\ttoolCalls[toolChunk.index as number] = {\n\t\t\t\t\t\t\t\ttoolCallId: toolChunk.id,\n\t\t\t\t\t\t\t\tname: toolChunk.name as string,\n\t\t\t\t\t\t\t};\n\n\t\t\t\t\t\t\tif (!this.shouldStreamToolEvent(getToolCallInfo().name)) continue;\n\n\t\t\t\t\t\t\tconst toolKitMeta = this.getToolKitMeta(getToolCallInfo().name);\n\n\t\t\t\t\t\t\tdebugLogStream('tool_start', `[${getToolCallInfo().toolCallId}] ${getToolCallInfo().name}`);\n\n\t\t\t\t\t\t\tyield {\n\t\t\t\t\t\t\t\ttype: 'tool_start',\n\t\t\t\t\t\t\t\tname: getToolCallInfo().name,\n\t\t\t\t\t\t\t\ttoolKit: toolKitMeta.toolKit,\n\t\t\t\t\t\t\t\tindex: toolCallIndex,\n\t\t\t\t\t\t\t\ttoolCallId: getToolCallInfo().toolCallId,\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (toolChunk.args && toolChunk.args.length > 0) {\n\t\t\t\t\t\t\tif (!this.shouldStreamToolEvent(getToolCallInfo().name)) continue;\n\n\t\t\t\t\t\t\tdebugLogStream('tool_input_delta', `[${getToolCallInfo().toolCallId}] ${toolChunk.args}`);\n\n\t\t\t\t\t\t\tyield {\n\t\t\t\t\t\t\t\ttype: 'tool_input_delta',\n\t\t\t\t\t\t\t\tname: getToolCallInfo().name,\n\t\t\t\t\t\t\t\targs: toolChunk.args || '',\n\t\t\t\t\t\t\t\tindex: toolCallIndex,\n\t\t\t\t\t\t\t\ttoolCallId: getToolCallInfo().toolCallId,\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else if (this.isReasoningMessage(message)) {\n\t\t\t\t\tconst contentArray = message.content as any[];\n\t\t\t\t\tfor (const block of contentArray) {\n\t\t\t\t\t\tconst delta =\n\t\t\t\t\t\t\t(block.type === 'reasoning' && block.reasoning) ||\n\t\t\t\t\t\t\t(block.type === 'thinking' && block.thinking);\n\t\t\t\t\t\tif (delta) {\n\t\t\t\t\t\t\tdebugLogStream('reasoning_delta', delta);\n\n\t\t\t\t\t\t\tyield {\n\t\t\t\t\t\t\t\ttype: 'reasoning_delta',\n\t\t\t\t\t\t\t\tdelta,\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else if (this.isArrayTextMessage(message)) {\n\t\t\t\t\tconst contentArray = message.content as any[];\n\t\t\t\t\tfor (const block of contentArray) {\n\t\t\t\t\t\tif (block.type === 'text' && block.text) {\n\t\t\t\t\t\t\tdebugLogStream('text_delta', block.text);\n\n\t\t\t\t\t\t\tyield {\n\t\t\t\t\t\t\t\ttype: 'text_delta',\n\t\t\t\t\t\t\t\tdelta: block.text,\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else if (message?.content && typeof message.content === 'string') {\n\t\t\t\t\tconst content = message.content;\n\n\t\t\t\t\tif (content.length === 0) continue;\n\n\t\t\t\t\tif (message.type == 'tool') {\n\t\t\t\t\t\t// I know it's odd but ToolMessage.name seems to corelate to the tool name\n\t\t\t\t\t\tconst toolName = message.name as string;\n\t\t\t\t\t\tconst toolKitMeta = this.getToolKitMeta(toolName);\n\n\t\t\t\t\t\tconst toolCall = Object.entries(toolCalls).find(\n\t\t\t\t\t\t\t([_, value]) => value.toolCallId == (message as ToolMessage).tool_call_id,\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\tif (!this.shouldStreamToolEvent(toolName)) continue;\n\n\t\t\t\t\t\tdebugLogStream('tool_result', `[${toolCall?.[1].toolCallId}] ${message.content}`);\n\n\t\t\t\t\t\tyield {\n\t\t\t\t\t\t\ttype: 'tool_result',\n\t\t\t\t\t\t\tname: toolName,\n\t\t\t\t\t\t\tinput:\n\t\t\t\t\t\t\t\tJSON.stringify(\n\t\t\t\t\t\t\t\t\tthis.toolCalls.find((tc) => tc.id == (toolCall as any)[1].toolCallId)?.input,\n\t\t\t\t\t\t\t\t) || '',\n\t\t\t\t\t\t\toutput: message.content,\n\t\t\t\t\t\t\ttoolKit: toolKitMeta.toolKit,\n\t\t\t\t\t\t\tindex: toolCall?.[0] ? parseInt(toolCall[0]) : 99999,\n\t\t\t\t\t\t\ttoolCallId: toolCall?.[1] ? toolCall[1].toolCallId : 'NO_ID_FOUND',\n\t\t\t\t\t\t};\n\t\t\t\t\t} else {\n\t\t\t\t\t\tdebugLogStream('text_delta', content);\n\n\t\t\t\t\t\tyield {\n\t\t\t\t\t\t\ttype: 'text_delta',\n\t\t\t\t\t\t\tdelta: content,\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tconsole.warn('Unexpected messages stream chunk', chunk);\n\t\t\t\t}\n\t\t\t} else if (mode == 'updates') {\n\t\t\t\tconst update = data;\n\n\t\t\t\t/**\n\t\t\t\t * This is how we get the tool INPUTS and llm\n\t\t\t\t * tokens that'll be used in returned content\n\t\t\t\t * blocks\n\t\t\t\t */\n\t\t\t\tif (update.model_request?.messages) {\n\t\t\t\t\tconst aiMessageChunks: AIMessageChunk[] = update.model_request.messages.filter(\n\t\t\t\t\t\t(m) => m.type == 'ai',\n\t\t\t\t\t) as AIMessageChunk[];\n\n\t\t\t\t\tfor (let aiChunk of aiMessageChunks) {\n\t\t\t\t\t\t// Accumulate usage metadata from current turn's AI messages\n\t\t\t\t\t\tconst um = aiChunk.usage_metadata;\n\t\t\t\t\t\tif (um) {\n\t\t\t\t\t\t\tconst cacheRead = um.input_token_details?.cache_read || 0;\n\t\t\t\t\t\t\tconst provider = aiChunk.response_metadata?.model_provider;\n\n\t\t\t\t\t\t\t// Anthropic reports input_tokens excluding cached tokens;\n\t\t\t\t\t\t\t// OpenAI (and unknown providers) include cached tokens in input_tokens\n\t\t\t\t\t\t\tconst inputTokens =\n\t\t\t\t\t\t\t\tprovider === 'anthropic' ? um.input_tokens || 0 : (um.input_tokens || 0) - cacheRead;\n\n\t\t\t\t\t\t\tusageMetadata.promptTokens += inputTokens;\n\t\t\t\t\t\t\tusageMetadata.completionTokens += um.output_tokens || 0;\n\t\t\t\t\t\t\tusageMetadata.totalTokens += inputTokens + (um.output_tokens || 0);\n\t\t\t\t\t\t\tusageMetadata.cachedPromptTokens! += cacheRead;\n\t\t\t\t\t\t\tusageMetadata.reasoningTokens =\n\t\t\t\t\t\t\t\t(usageMetadata.reasoningTokens || 0) + (um.output_token_details?.reasoning || 0);\n\t\t\t\t\t\t\tusageMetadata.cacheCreationTokens! += um.input_token_details?.cache_creation || 0;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (aiChunk.tool_calls && aiChunk.tool_calls.length > 0) {\n\t\t\t\t\t\t\tfor (let tc of aiChunk.tool_calls)\n\t\t\t\t\t\t\t\ttoolCallUpdates[tc.id as string] = {\n\t\t\t\t\t\t\t\t\tname: tc.name,\n\t\t\t\t\t\t\t\t\targs: tc.args,\n\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t} else if (aiChunk.content) {\n\t\t\t\t\t\t\tconst textOutput = this.extractTextContent(aiChunk.content);\n\t\t\t\t\t\t\tif (textOutput.trim().length > 0)\n\t\t\t\t\t\t\t\tcontentBlocks.push({\n\t\t\t\t\t\t\t\t\ttype: 'text',\n\t\t\t\t\t\t\t\t\toutput: textOutput,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t/**\n\t\t\t\t * This is how we get the tool OUTPUTS that'll be\n\t\t\t\t * used in returned content blocks\n\t\t\t\t */\n\t\t\t\tif (update.tools?.messages) {\n\t\t\t\t\tconst toolMessages: ToolMessage[] = update.tools.messages.filter(\n\t\t\t\t\t\t(m) => m.type == 'tool',\n\t\t\t\t\t) as ToolMessage[];\n\n\t\t\t\t\tfor (let tm of toolMessages) {\n\t\t\t\t\t\tconst input = JSON.stringify(toolCallUpdates[tm.tool_call_id].args);\n\t\t\t\t\t\tconst toolCall = this.toolCalls.find((tc) => tc.id == tm.tool_call_id);\n\n\t\t\t\t\t\tif (this.shouldStreamToolEvent(tm.name as string))\n\t\t\t\t\t\t\tcontentBlocks.push({\n\t\t\t\t\t\t\t\ttype: 'tool_call',\n\t\t\t\t\t\t\t\tname: tm.name as string,\n\t\t\t\t\t\t\t\ttoolKit: this.getToolKitMeta(tm.name as string).toolKit,\n\t\t\t\t\t\t\t\tinput: toolCall ? JSON.stringify(toolCall.input) : null,\n\t\t\t\t\t\t\t\toutput: tm.content.toString(),\n\t\t\t\t\t\t\t\ttoolCallId: tm.tool_call_id,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// console.error('\\n----------');\n\t\t\t\t// console.error('UPDATE');\n\t\t\t\t// console.error(JSON.stringify(data, null, 2));\n\t\t\t\t// console.error('----------\\n');\n\t\t\t} else if (mode == 'values') finalValue = data;\n\t\t}\n\n\t\tdebugLogStream('message_end', '\\n');\n\n\t\tyield { type: 'final_content', content: contentBlocks, usage: usageMetadata };\n\n\t\tyield { type: 'message_end' };\n\t}\n\n\tgetLangchainAgent(): ReactAgent {\n\t\treturn this.deepAgent;\n\t}\n\n\t/**\n\t * Tools have metadata fields that we can use\n\t * to get which toolKit this tool belongs.\n\t *\n\t * So we first find the tool using the tool's\n\t * name, then we extract the toolkit metadata\n\t * from that tool's metadata.\n\t */\n\tprivate getToolKitMeta(toolName: string): {\n\t\ttoolKit: string;\n\t} {\n\t\tif (!this.tools)\n\t\t\treturn {\n\t\t\t\ttoolKit: '',\n\t\t\t};\n\n\t\tconst tool = this.tools.find((t) => t.name === toolName);\n\n\t\tif (!tool) return { toolKit: '' };\n\n\t\treturn {\n\t\t\ttoolKit: tool.metadata?.toolKit as string,\n\t\t};\n\t}\n\n\tprivate isToolCallMessage(message: BaseMessage): boolean {\n\t\tif (!(message instanceof AIMessageChunk)) return false;\n\n\t\tconst toolCallChunks = message.tool_call_chunks;\n\n\t\tif (!toolCallChunks) return false;\n\n\t\tif (toolCallChunks.length == 0) return false;\n\n\t\treturn true;\n\t}\n\n\tprivate shouldIgnoreMessage = (message: BaseMessage, metadata: any) => {\n\t\tif (message.id == '__remove_all__') return true;\n\n\t\t/**\n\t\t * For some reason there are AIMessageChunk messages\n\t\t * with empty content + no tool_call_chunks\n\t\t */\n\t\tif (!this.isToolCallMessage(message) && (!message.content || message.content.length == 0)) return true;\n\n\t\t/**\n\t\t * This is the tool selector middleware\n\t\t */\n\t\tif (metadata?.langgraph_node?.includes('patchToolCallsMiddleware')) return true;\n\n\t\tfor (const disabled of this.params.disableModelStreamingFor || [])\n\t\t\tif (metadata?.tags.includes(disabled)) return true;\n\n\t\treturn false;\n\t};\n\n\tprivate shouldStreamToolEvent(toolName: string): boolean {\n\t\tconst shouldStream = !this.params.disableToolStreamingFor?.includes(toolName);\n\n\t\tif (!shouldStream && ENABLE_STREAM_DEBUG_LOGS) console.warn('SUPPRESSING TOOL EVENT: ' + toolName);\n\n\t\treturn shouldStream;\n\t}\n\n\tprivate isReasoningMessage(message: BaseMessage): boolean {\n\t\tif (!Array.isArray(message.content)) return false;\n\t\treturn (message.content as any[]).some((block) => block.type === 'reasoning' || block.type === 'thinking');\n\t}\n\n\tprivate isArrayTextMessage(message: BaseMessage): boolean {\n\t\tif (!Array.isArray(message.content)) return false;\n\t\treturn (message.content as any[]).some((block) => block.type === 'text');\n\t}\n\n\t/**\n\t * Extracts text from message content that may be a string\n\t * or an array of content blocks (as returned by reasoning models).\n\t */\n\tprivate extractTextContent(content: any): string {\n\t\tif (typeof content === 'string') return content;\n\n\t\tif (Array.isArray(content)) {\n\t\t\treturn content\n\t\t\t\t.filter((block) => block.type === 'text' && block.text)\n\t\t\t\t.map((block) => block.text)\n\t\t\t\t.join('');\n\t\t}\n\n\t\treturn content.toString();\n\t}\n}\n","import { Message } from '@core/agent.interface';\nimport { AIMessage, BaseMessage, HumanMessage, ToolMessage } from 'langchain';\n\nexport function convertToLangchainMessages(messages: Message[]): BaseMessage[] {\n\tconst result: BaseMessage[] = [];\n\tlet tcIdx = 0;\n\tlet pendingToolCallIds: string[] = [];\n\n\tfor (const msg of messages) {\n\t\tif (msg.role === 'human') {\n\t\t\tresult.push(\n\t\t\t\tnew HumanMessage({\n\t\t\t\t\tcontent: msg.content.map((c) => {\n\t\t\t\t\t\tif (c.type === 'image') {\n\t\t\t\t\t\t\treturn { type: 'image_url', image_url: { url: c.url } };\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn c;\n\t\t\t\t\t}) as any,\n\t\t\t\t}),\n\t\t\t);\n\t\t} else if (msg.role === 'ai') {\n\t\t\tif (msg.toolCalls && msg.toolCalls.length > 0) {\n\t\t\t\tpendingToolCallIds = msg.toolCalls.map(() => `tc_${++tcIdx}`);\n\t\t\t\tresult.push(\n\t\t\t\t\tnew AIMessage({\n\t\t\t\t\t\tcontent: msg.content,\n\t\t\t\t\t\ttool_calls: msg.toolCalls.map((tc, i) => ({\n\t\t\t\t\t\t\tid: pendingToolCallIds[i],\n\t\t\t\t\t\t\tname: tc.name,\n\t\t\t\t\t\t\targs: tc.input ? JSON.parse(tc.input) : {},\n\t\t\t\t\t\t})),\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tresult.push(new AIMessage(msg.content));\n\t\t\t}\n\t\t} else if (msg.role === 'tool') {\n\t\t\tconst toolCallId = pendingToolCallIds.shift();\n\t\t\tif (!toolCallId)\n\t\t\t\tthrow new Error(`ToolMessage for \"${msg.name}\" without a preceding AiMessage with toolCalls`);\n\t\t\tresult.push(\n\t\t\t\tnew ToolMessage({\n\t\t\t\t\tcontent: msg.output,\n\t\t\t\t\ttool_call_id: toolCallId,\n\t\t\t\t\tname: msg.name,\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t}\n\n\treturn result;\n}\n","import { BaseLanguageModel } from '@langchain/core/language_models/base';\nimport { ChatAnthropic } from '@langchain/anthropic';\nimport { AzureChatOpenAI, ChatOpenAI } from '@langchain/openai';\nimport { ReasoningEffort } from 'openai/resources';\n\nexport type LangchainOpenAIConfig = {\n\tapiKey: string;\n};\n\nexport type AzureModelProvider = 'openai' | 'anthropic';\n\nexport type LangchainAzureResourceConfig = {\n\tapiKey: string;\n\tmodels: {\n\t\tmodel: string;\n\t\tprovider: AzureModelProvider;\n\t\tendpoint: string;\n\t\tapiVersion: string;\n\t\tdeploymentName: string;\n\t}[];\n};\n\nexport type ResourceName = string;\n\nexport type LangchainModelConfig = {\n\topenai?: Record<string, LangchainOpenAIConfig>;\n\tazure?: Record<ResourceName, LangchainAzureResourceConfig>;\n};\n\nexport class LangchainModelResolver {\n\tconstructor(private config: LangchainModelConfig) {}\n\n\tresolve(modelString: string, tags?: string[], reasoningEffort?: ReasoningEffort): BaseLanguageModel {\n\t\tconst parts = modelString.split(':');\n\n\t\tif (parts.length === 1) {\n\t\t\tconst fullModelString = this.resolveFullModelString(modelString);\n\t\t\treturn this.resolve(fullModelString, tags, reasoningEffort);\n\t\t}\n\n\t\tif (parts.length === 2) {\n\t\t\tconst [provider, modelName] = parts;\n\t\t\treturn this.resolveByProvider(provider, modelName, modelName, tags, reasoningEffort);\n\t\t}\n\n\t\tif (parts.length === 3) {\n\t\t\tconst [provider, configName, modelName] = parts;\n\t\t\treturn this.resolveByProvider(provider, configName, modelName, tags, reasoningEffort);\n\t\t}\n\n\t\tthrow new Error(\n\t\t\t'Model string must follow format \"modelName\", \"provider:modelName\", or \"provider:configName:modelName\"',\n\t\t);\n\t}\n\n\tprivate resolveFullModelString(modelName: string): string {\n\t\tfor (const [provider, resources] of Object.entries(this.config)) {\n\t\t\tif (provider === 'openai') {\n\t\t\t\tif (modelName in (resources as Record<string, unknown>)) {\n\t\t\t\t\treturn `openai:${modelName}`;\n\t\t\t\t}\n\t\t\t} else if (provider === 'azure') {\n\t\t\t\tfor (const [resource, config] of Object.entries(\n\t\t\t\t\tresources as Record<string, { models: { model: string }[] }>,\n\t\t\t\t)) {\n\t\t\t\t\tif (config.models.some((m) => m.model === modelName)) {\n\t\t\t\t\t\treturn `azure:${resource}:${modelName}`;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tthrow new Error(`Model \"${modelName}\" not found in model config`);\n\t}\n\n\tprivate resolveByProvider(\n\t\tprovider: string,\n\t\tconfigName: string,\n\t\tmodelName: string,\n\t\ttags?: string[],\n\t\treasoningEffort?: ReasoningEffort,\n\t): BaseLanguageModel {\n\t\tswitch (provider) {\n\t\t\tcase 'openai':\n\t\t\t\treturn this.resolveOpenAI(configName, modelName, tags, reasoningEffort);\n\t\t\tcase 'azure':\n\t\t\t\treturn this.resolveAzure(configName, modelName, tags, reasoningEffort);\n\t\t\tdefault:\n\t\t\t\tthrow new Error(`Unsupported model provider: ${provider}`);\n\t\t}\n\t}\n\n\tprivate resolveOpenAI(\n\t\tconfigName: string,\n\t\tmodelName: string,\n\t\ttags?: string[],\n\t\treasoningEffort?: ReasoningEffort,\n\t): ChatOpenAI {\n\t\tconst providerConfig = this.config.openai?.[configName];\n\t\tif (!providerConfig) {\n\t\t\tthrow new Error(`Configuration \"${configName}\" for provider \"openai\" is missing`);\n\t\t}\n\n\t\treturn new ChatOpenAI({\n\t\t\tapiKey: providerConfig.apiKey,\n\t\t\tmodelName: modelName,\n\t\t\ttags: tags,\n\t\t\t...(reasoningEffort && {\n\t\t\t\treasoning: {\n\t\t\t\t\teffort: reasoningEffort,\n\t\t\t\t\tsummary: 'auto',\n\t\t\t\t},\n\t\t\t\tuseResponsesApi: true,\n\t\t\t}),\n\t\t});\n\t}\n\n\tprivate resolveAzure(\n\t\tresourceName: string,\n\t\tmodelName: string,\n\t\ttags?: string[],\n\t\treasoningEffort?: ReasoningEffort,\n\t): BaseLanguageModel {\n\t\tconst resource = this.config.azure?.[resourceName];\n\t\tif (!resource) {\n\t\t\tthrow new Error(`Resource \"${resourceName}\" for provider \"azure\" is missing`);\n\t\t}\n\n\t\tconst modelEntry = resource.models.find((m) => m.model === modelName);\n\t\tif (!modelEntry) {\n\t\t\tthrow new Error(`Model \"${modelName}\" not found in Azure resource \"${resourceName}\"`);\n\t\t}\n\n\t\tswitch (modelEntry.provider) {\n\t\t\tcase 'anthropic':\n\t\t\t\treturn this.resolveAzureAnthropic(resource, modelEntry, tags, reasoningEffort);\n\t\t\tcase 'openai':\n\t\t\t\treturn this.resolveAzureOpenAI(resource, modelEntry, tags, reasoningEffort);\n\t\t}\n\t}\n\n\tprivate resolveAzureOpenAI(\n\t\tresource: LangchainAzureResourceConfig,\n\t\tmodelEntry: LangchainAzureResourceConfig['models'][number],\n\t\ttags?: string[],\n\t\treasoningEffort?: ReasoningEffort,\n\t): AzureChatOpenAI {\n\t\t/**\n\t\t * OpenAI reasoning models require the Responses API which AzureChatOpenAI\n\t\t * does not support. We rewrite the endpoint to the Azure Responses API path.\n\t\t */\n\t\tconst endpoint = reasoningEffort\n\t\t\t? `${modelEntry.endpoint.replace(/\\/$/, '')}/openai/responses?api-version=${modelEntry.apiVersion}`\n\t\t\t: modelEntry.endpoint;\n\n\t\treturn new AzureChatOpenAI({\n\t\t\tmodel: modelEntry.model,\n\t\t\tazureOpenAIApiKey: resource.apiKey,\n\t\t\tazureOpenAIEndpoint: endpoint,\n\t\t\tazureOpenAIApiDeploymentName: modelEntry.deploymentName,\n\t\t\tazureOpenAIApiVersion: modelEntry.apiVersion,\n\t\t\ttags: tags,\n\t\t\t...(reasoningEffort && {\n\t\t\t\treasoning: {\n\t\t\t\t\teffort: reasoningEffort,\n\t\t\t\t\tsummary: 'auto',\n\t\t\t\t},\n\t\t\t}),\n\t\t});\n\t}\n\n\tprivate static readonly THINKING_BUDGET: Record<string, number> = {\n\t\tminimal: 1024,\n\t\tlow: 4096,\n\t\tmedium: 10000,\n\t\thigh: 16000,\n\t\txhigh: 32000,\n\t};\n\n\tprivate resolveAzureAnthropic(\n\t\tresource: LangchainAzureResourceConfig,\n\t\tmodelEntry: LangchainAzureResourceConfig['models'][number],\n\t\ttags?: string[],\n\t\treasoningEffort?: ReasoningEffort,\n\t): ChatAnthropic {\n\t\tconst budgetTokens = reasoningEffort ? LangchainModelResolver.THINKING_BUDGET[reasoningEffort] : undefined;\n\n\t\treturn new ChatAnthropic({\n\t\t\tmodel: modelEntry.model,\n\t\t\tapiKey: resource.apiKey,\n\t\t\tclientOptions: { baseURL: modelEntry.endpoint },\n\t\t\ttags: tags,\n\t\t\t...(budgetTokens && {\n\t\t\t\tmaxTokens: budgetTokens * 2,\n\t\t\t\tthinking: {\n\t\t\t\t\ttype: 'enabled',\n\t\t\t\t\tbudget_tokens: budgetTokens,\n\t\t\t\t},\n\t\t\t}),\n\t\t});\n\t}\n}\n","import { ToolDefinition, ToolKitSpec } from '@core/agent.interface';\nimport { ToolProvider } from './tool-provider';\nimport { ToolCache } from '@core/tools/tool-cache';\n\ntype ProviderEntry<TContext> = {\n\ttype: 'provider';\n\tprovider: ToolProvider<TContext>;\n};\n\ntype StaticEntry = {\n\ttype: 'static';\n\ttools: ToolDefinition[];\n};\n\ntype Entry<TContext> = ProviderEntry<TContext> | StaticEntry;\n\nexport interface ToolRegistryOptions {\n\t/**\n\t * Shared cache for tool specs (e.g. Redis). Values are stored as JSON strings.\n\t */\n\ttoolSpecCache?: ToolCache;\n}\n\nexport class ToolRegistry<TContext> {\n\tprivate entries = new Map<string, Entry<TContext>>();\n\tprivate toolSpecCache?: ToolCache;\n\n\tconstructor(options: ToolRegistryOptions = {}) {\n\t\tthis.toolSpecCache = options.toolSpecCache;\n\t}\n\n\tregisterProvider(toolKit: string, provider: ToolProvider<TContext>): void {\n\t\tthis.entries.set(toolKit, { type: 'provider', provider });\n\t}\n\n\tregisterTools(toolKit: string, tools: ToolDefinition[]): void {\n\t\tthis.entries.set(toolKit, { type: 'static', tools });\n\t}\n\n\tasync getTools(toolKits: string[], context: TContext): Promise<ToolDefinition[]> {\n\t\tconst results: ToolDefinition[] = [];\n\n\t\tfor (const kit of toolKits) {\n\t\t\tconst entry = this.entries.get(kit);\n\t\t\tif (!entry) {\n\t\t\t\tthrow new Error(`No tools or provider registered for tool kit: ${kit}`);\n\t\t\t}\n\n\t\t\tif (entry.type === 'static') {\n\t\t\t\tresults.push(...entry.tools);\n\t\t\t} else {\n\t\t\t\tconst provider = entry.provider;\n\t\t\t\tconst spec = await this.getToolKitSpec(kit, provider, context);\n\t\t\t\tconst tools = await provider.bindTools(spec.tools, context);\n\n\t\t\t\tfor (const tool of tools) {\n\t\t\t\t\ttool.toolKit = spec.name;\n\t\t\t\t}\n\n\t\t\t\tresults.push(...tools);\n\t\t\t}\n\t\t}\n\n\t\treturn results;\n\t}\n\n\tasync getToolKitSpecs(toolKits: string[], context: TContext): Promise<ToolKitSpec[]> {\n\t\tconst results: ToolKitSpec[] = [];\n\n\t\tfor (const kit of toolKits) {\n\t\t\tconst entry = this.entries.get(kit);\n\t\t\tif (!entry) {\n\t\t\t\tthrow new Error(`No tools or provider registered for tool kit: ${kit}`);\n\t\t\t}\n\n\t\t\tif (entry.type === 'static') {\n\t\t\t\tthrow new Error(`Tool kit \"${kit}\" was registered with static tools and has no ToolKitSpec`);\n\t\t\t}\n\n\t\t\tconst spec = await this.getToolKitSpec(kit, entry.provider, context);\n\t\t\tresults.push(spec);\n\t\t}\n\n\t\treturn results;\n\t}\n\n\tinvalidate(toolKit: string): void {\n\t\tconst entry = this.entries.get(toolKit);\n\n\t\tif (entry && entry.type === 'provider') this.toolSpecCache?.del(toolKit);\n\t}\n\n\tprivate async getToolKitSpec(\n\t\ttoolKit: string,\n\t\tprovider: ToolProvider<TContext>,\n\t\tcontext: TContext,\n\t): Promise<ToolKitSpec> {\n\t\tconst cache = this.toolSpecCache;\n\n\t\tif (cache) {\n\t\t\ttry {\n\t\t\t\tconst cached = await cache.get(toolKit);\n\n\t\t\t\tif (cached) return cached;\n\t\t\t} catch (e) {\n\t\t\t\tconsole.error('Something went wrong when hitting the cache', e);\n\t\t\t}\n\t\t}\n\n\t\tconst spec = await provider.listToolKitSpec(toolKit, context);\n\n\t\tif (cache) {\n\t\t\ttry {\n\t\t\t\tawait cache.set(toolKit, spec);\n\t\t\t} catch (e) {\n\t\t\t\tconsole.error('Something went wrong when setting the cache', e);\n\t\t\t}\n\t\t}\n\n\t\treturn spec;\n\t}\n}\n","import { ToolKitSpec } from '@core/agent.interface';\nimport Redis from 'ioredis';\nimport { z } from 'zod';\n\nexport interface ToolCache {\n\tget(toolKit: string): Promise<ToolKitSpec | null> | ToolKitSpec | null;\n\n\tset(toolKit: string, spec: ToolKitSpec): Promise<void>;\n\n\tdel(toolKit: string): Promise<void>;\n}\n\nexport class RedisToolCache implements ToolCache {\n\tprivate redis: Redis;\n\n\tconstructor(connectionString: string) {\n\t\tthis.redis = new Redis(connectionString);\n\t}\n\n\tasync get(toolKit: string): Promise<ToolKitSpec | null> {\n\t\tconst data = await this.redis.get(`tool-cache:${toolKit}`);\n\n\t\tif (!data) return null;\n\n\t\ttry {\n\t\t\tconst parsed = JSON.parse(data);\n\n\t\t\tif (!parsed || !Array.isArray(parsed.tools)) return null;\n\n\t\t\treturn {\n\t\t\t\t...parsed,\n\t\t\t\ttools: parsed.tools.map((spec: any) => ({\n\t\t\t\t\t...spec,\n\t\t\t\t\tinputSchema: z.fromJSONSchema(spec.inputSchema),\n\t\t\t\t})),\n\t\t\t};\n\t\t} catch (e) {\n\t\t\tconsole.error('Failed to parse cached tools', e);\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tasync set(toolKit: string, spec: ToolKitSpec): Promise<void> {\n\t\tconst serialized = {\n\t\t\t...spec,\n\t\t\ttools: spec.tools.map((tool) => ({\n\t\t\t\t...tool,\n\t\t\t\tinputSchema: tool.inputSchema.toJSONSchema(),\n\t\t\t})),\n\t\t};\n\t\tawait this.redis.set(`tool-cache:${toolKit}`, JSON.stringify(serialized));\n\t}\n\n\tasync del(toolKit: string): Promise<void> {\n\t\tawait this.redis.del(`tool-cache:${toolKit}`);\n\t}\n}\n\nexport class InMemoryToolCache implements ToolCache {\n\tprivate cache = new Map<string, ToolKitSpec>();\n\n\tget(toolKit: string): ToolKitSpec | null {\n\t\treturn this.cache.get(`tool-cache:${toolKit}`) ?? null;\n\t}\n\n\tasync set(toolKit: string, spec: ToolKitSpec): Promise<void> {\n\t\tthis.cache.set(`tool-cache:${toolKit}`, spec);\n\t}\n\n\tasync del(toolKit: string): Promise<void> {\n\t\tthis.cache.delete(`tool-cache:${toolKit}`);\n\t}\n}\n"],"mappings":"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","names":["import_deepagents","import_langchain","import_langchain","input","tool","options","tool","Redis","tool"]}
|
package/dist/index.mjs
CHANGED
|
@@ -19,6 +19,9 @@ import {
|
|
|
19
19
|
createMiddleware
|
|
20
20
|
} from "langchain";
|
|
21
21
|
var ENABLE_STREAM_DEBUG_LOGS = false;
|
|
22
|
+
var DEFAULT_EFFECTIVE_MODEL_INVOCATIONS = 25;
|
|
23
|
+
var GRACEFUL_SHUTDOWN_BUFFER_CYCLES = 3;
|
|
24
|
+
var INVOCATION_LIMIT_TOOL_ERROR = "[SYSTEM] You have reached the maximum number of tool invocations for this turn. Do NOT call any more tools. Instead, respond with a text message that:\n1. Summarizes the progress made so far and any partial results.\n2. Explains what could not be completed and why.\n3. Suggests alternative approaches or next steps the user can take.";
|
|
22
25
|
function debugLogStream(type, text) {
|
|
23
26
|
if (!ENABLE_STREAM_DEBUG_LOGS) return;
|
|
24
27
|
console.warn(`${type}: ${text}`);
|
|
@@ -27,6 +30,7 @@ var LangchainAgent = class {
|
|
|
27
30
|
constructor(params) {
|
|
28
31
|
this.params = params;
|
|
29
32
|
this.tools = params.tools;
|
|
33
|
+
this.effectiveModelLimit = params.maxModelInvocations ?? DEFAULT_EFFECTIVE_MODEL_INVOCATIONS;
|
|
30
34
|
if (!params.disableModelStreamingFor) params.disableModelStreamingFor = [];
|
|
31
35
|
if (!params.disableToolReportingFor) params.disableToolReportingFor = [];
|
|
32
36
|
if (!params.disableToolStreamingFor) params.disableToolStreamingFor = [];
|
|
@@ -88,17 +92,84 @@ var LangchainAgent = class {
|
|
|
88
92
|
});
|
|
89
93
|
}
|
|
90
94
|
}
|
|
95
|
+
}),
|
|
96
|
+
/**
|
|
97
|
+
* Tracks model invocations and gracefully stops the agent when
|
|
98
|
+
* the limit is reached. Instead of letting LangGraph throw a
|
|
99
|
+
* hard GraphRecursionError, tool calls beyond the limit receive
|
|
100
|
+
* an error message asking the model to summarize and wrap up.
|
|
101
|
+
*/
|
|
102
|
+
createMiddleware({
|
|
103
|
+
name: "invocationLimitGuard",
|
|
104
|
+
wrapModelCall: async (request, handler) => {
|
|
105
|
+
this.modelInvocationCount++;
|
|
106
|
+
return handler(request);
|
|
107
|
+
},
|
|
108
|
+
wrapToolCall: async (request, handler) => {
|
|
109
|
+
if (this.modelInvocationCount > this.effectiveModelLimit) {
|
|
110
|
+
return new ToolMessage({
|
|
111
|
+
name: request.toolCall.name,
|
|
112
|
+
content: INVOCATION_LIMIT_TOOL_ERROR,
|
|
113
|
+
tool_call_id: request.toolCall.id || "INVOCATION_LIMIT"
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
return handler(request);
|
|
117
|
+
}
|
|
91
118
|
})
|
|
92
119
|
];
|
|
93
120
|
if (params.middleware) middlewares = [...middlewares, ...params.middleware];
|
|
94
121
|
params.middleware = middlewares;
|
|
95
122
|
this.deepAgent = createDeepAgent(params);
|
|
123
|
+
this.recursionLimit = this.computeRecursionLimit();
|
|
96
124
|
}
|
|
97
125
|
deepAgent;
|
|
98
126
|
toolCalls = [];
|
|
99
127
|
tools;
|
|
128
|
+
recursionLimit;
|
|
129
|
+
modelInvocationCount = 0;
|
|
130
|
+
effectiveModelLimit;
|
|
131
|
+
/**
|
|
132
|
+
* Computes an adjusted LangGraph recursion limit that compensates for
|
|
133
|
+
* middleware graph nodes. LangGraph counts every *superstep* (node visit)
|
|
134
|
+
* toward its recursion limit, but middleware hooks like `beforeModel`,
|
|
135
|
+
* `afterModel`, `beforeAgent`, and `afterAgent` each add extra graph
|
|
136
|
+
* nodes that consume steps without representing real model invocations.
|
|
137
|
+
*
|
|
138
|
+
* This method introspects the compiled graph to count how many nodes
|
|
139
|
+
* participate in one model-tool cycle and scales the limit so the agent
|
|
140
|
+
* gets {@link DEFAULT_EFFECTIVE_MODEL_INVOCATIONS} real model calls,
|
|
141
|
+
* plus a buffer of extra cycles for graceful shutdown (where tool calls
|
|
142
|
+
* return an error asking the model to wrap up).
|
|
143
|
+
*
|
|
144
|
+
* Formula:
|
|
145
|
+
* recursionLimit = N_beforeAgent
|
|
146
|
+
* + (K + buffer) * (N_beforeModel + 1 + N_afterModel + 1)
|
|
147
|
+
* + N_afterAgent
|
|
148
|
+
*
|
|
149
|
+
* Where K = desired effective model invocations, buffer =
|
|
150
|
+
* {@link GRACEFUL_SHUTDOWN_BUFFER_CYCLES}, and the +1s are for the
|
|
151
|
+
* `model_request` and `tools` core nodes.
|
|
152
|
+
*/
|
|
153
|
+
computeRecursionLimit() {
|
|
154
|
+
const graph = this.deepAgent.graph;
|
|
155
|
+
const nodeNames = graph?.nodes ? Object.keys(graph.nodes) : [];
|
|
156
|
+
let beforeAgentCount = 0;
|
|
157
|
+
let beforeModelCount = 0;
|
|
158
|
+
let afterModelCount = 0;
|
|
159
|
+
let afterAgentCount = 0;
|
|
160
|
+
for (const name of nodeNames) {
|
|
161
|
+
if (name.endsWith(".before_agent")) beforeAgentCount++;
|
|
162
|
+
else if (name.endsWith(".before_model")) beforeModelCount++;
|
|
163
|
+
else if (name.endsWith(".after_model")) afterModelCount++;
|
|
164
|
+
else if (name.endsWith(".after_agent")) afterAgentCount++;
|
|
165
|
+
}
|
|
166
|
+
const nodesPerCycle = beforeModelCount + 1 + afterModelCount + 1;
|
|
167
|
+
const totalCycles = this.effectiveModelLimit + GRACEFUL_SHUTDOWN_BUFFER_CYCLES;
|
|
168
|
+
return beforeAgentCount + totalCycles * nodesPerCycle + afterAgentCount;
|
|
169
|
+
}
|
|
100
170
|
async run(input) {
|
|
101
171
|
this.toolCalls = [];
|
|
172
|
+
this.modelInvocationCount = 0;
|
|
102
173
|
let messageCountBefore = 0;
|
|
103
174
|
try {
|
|
104
175
|
const stateBefore = await this.deepAgent.getState({
|
|
@@ -116,6 +187,8 @@ var LangchainAgent = class {
|
|
|
116
187
|
messages
|
|
117
188
|
},
|
|
118
189
|
{
|
|
190
|
+
...input.signal ? { signal: input.signal } : {},
|
|
191
|
+
recursionLimit: this.recursionLimit,
|
|
119
192
|
configurable: {
|
|
120
193
|
threadId: input.threadId,
|
|
121
194
|
thread_id: input.threadId
|
|
@@ -188,6 +261,7 @@ var LangchainAgent = class {
|
|
|
188
261
|
}
|
|
189
262
|
async *stream(input) {
|
|
190
263
|
this.toolCalls = [];
|
|
264
|
+
this.modelInvocationCount = 0;
|
|
191
265
|
const contentBlocks = [];
|
|
192
266
|
let finalValue;
|
|
193
267
|
let usageMetadata = {
|
|
@@ -204,6 +278,7 @@ var LangchainAgent = class {
|
|
|
204
278
|
const stream = await this.deepAgent.stream(
|
|
205
279
|
{ messages },
|
|
206
280
|
{
|
|
281
|
+
recursionLimit: this.recursionLimit,
|
|
207
282
|
configurable: {
|
|
208
283
|
threadId: input.threadId,
|
|
209
284
|
thread_id: input.threadId
|