@librechat/agents 3.1.86 → 3.1.88
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +69 -0
- package/dist/cjs/events.cjs +23 -0
- package/dist/cjs/events.cjs.map +1 -1
- package/dist/cjs/graphs/Graph.cjs +133 -18
- package/dist/cjs/graphs/Graph.cjs.map +1 -1
- package/dist/cjs/graphs/MultiAgentGraph.cjs +1 -1
- package/dist/cjs/graphs/MultiAgentGraph.cjs.map +1 -1
- package/dist/cjs/llm/anthropic/index.cjs +251 -53
- package/dist/cjs/llm/anthropic/index.cjs.map +1 -1
- package/dist/cjs/llm/init.cjs +1 -5
- package/dist/cjs/llm/init.cjs.map +1 -1
- package/dist/cjs/llm/openai/index.cjs +113 -24
- package/dist/cjs/llm/openai/index.cjs.map +1 -1
- package/dist/cjs/llm/openai/utils/index.cjs.map +1 -1
- package/dist/cjs/llm/openrouter/index.cjs +3 -1
- package/dist/cjs/llm/openrouter/index.cjs.map +1 -1
- package/dist/cjs/main.cjs +18 -5
- package/dist/cjs/main.cjs.map +1 -1
- package/dist/cjs/openai/index.cjs +253 -0
- package/dist/cjs/openai/index.cjs.map +1 -0
- package/dist/cjs/responses/index.cjs +448 -0
- package/dist/cjs/responses/index.cjs.map +1 -0
- package/dist/cjs/run.cjs +108 -7
- package/dist/cjs/run.cjs.map +1 -1
- package/dist/cjs/session/AgentSession.cjs +1057 -0
- package/dist/cjs/session/AgentSession.cjs.map +1 -0
- package/dist/cjs/session/JsonlSessionStore.cjs +425 -0
- package/dist/cjs/session/JsonlSessionStore.cjs.map +1 -0
- package/dist/cjs/session/handlers.cjs +221 -0
- package/dist/cjs/session/handlers.cjs.map +1 -0
- package/dist/cjs/session/ids.cjs +22 -0
- package/dist/cjs/session/ids.cjs.map +1 -0
- package/dist/cjs/session/messageSerialization.cjs +179 -0
- package/dist/cjs/session/messageSerialization.cjs.map +1 -0
- package/dist/cjs/stream.cjs +475 -11
- package/dist/cjs/stream.cjs.map +1 -1
- package/dist/cjs/summarization/node.cjs +1 -1
- package/dist/cjs/summarization/node.cjs.map +1 -1
- package/dist/cjs/tools/ToolNode.cjs +177 -59
- package/dist/cjs/tools/ToolNode.cjs.map +1 -1
- package/dist/cjs/tools/eagerEventExecution.cjs +113 -0
- package/dist/cjs/tools/eagerEventExecution.cjs.map +1 -0
- package/dist/cjs/tools/handlers.cjs +1 -1
- package/dist/cjs/tools/handlers.cjs.map +1 -1
- package/dist/cjs/tools/streamedToolCallSeals.cjs +42 -0
- package/dist/cjs/tools/streamedToolCallSeals.cjs.map +1 -0
- package/dist/esm/events.mjs +23 -1
- package/dist/esm/events.mjs.map +1 -1
- package/dist/esm/graphs/Graph.mjs +133 -18
- package/dist/esm/graphs/Graph.mjs.map +1 -1
- package/dist/esm/graphs/MultiAgentGraph.mjs +1 -1
- package/dist/esm/graphs/MultiAgentGraph.mjs.map +1 -1
- package/dist/esm/llm/anthropic/index.mjs +251 -53
- package/dist/esm/llm/anthropic/index.mjs.map +1 -1
- package/dist/esm/llm/init.mjs +1 -5
- package/dist/esm/llm/init.mjs.map +1 -1
- package/dist/esm/llm/openai/index.mjs +113 -25
- package/dist/esm/llm/openai/index.mjs.map +1 -1
- package/dist/esm/llm/openai/utils/index.mjs.map +1 -1
- package/dist/esm/llm/openrouter/index.mjs +4 -2
- package/dist/esm/llm/openrouter/index.mjs.map +1 -1
- package/dist/esm/main.mjs +5 -1
- package/dist/esm/main.mjs.map +1 -1
- package/dist/esm/openai/index.mjs +246 -0
- package/dist/esm/openai/index.mjs.map +1 -0
- package/dist/esm/responses/index.mjs +440 -0
- package/dist/esm/responses/index.mjs.map +1 -0
- package/dist/esm/run.mjs +108 -7
- package/dist/esm/run.mjs.map +1 -1
- package/dist/esm/session/AgentSession.mjs +1054 -0
- package/dist/esm/session/AgentSession.mjs.map +1 -0
- package/dist/esm/session/JsonlSessionStore.mjs +422 -0
- package/dist/esm/session/JsonlSessionStore.mjs.map +1 -0
- package/dist/esm/session/handlers.mjs +219 -0
- package/dist/esm/session/handlers.mjs.map +1 -0
- package/dist/esm/session/ids.mjs +17 -0
- package/dist/esm/session/ids.mjs.map +1 -0
- package/dist/esm/session/messageSerialization.mjs +173 -0
- package/dist/esm/session/messageSerialization.mjs.map +1 -0
- package/dist/esm/stream.mjs +476 -12
- package/dist/esm/stream.mjs.map +1 -1
- package/dist/esm/summarization/node.mjs +1 -1
- package/dist/esm/summarization/node.mjs.map +1 -1
- package/dist/esm/tools/ToolNode.mjs +177 -59
- package/dist/esm/tools/ToolNode.mjs.map +1 -1
- package/dist/esm/tools/eagerEventExecution.mjs +107 -0
- package/dist/esm/tools/eagerEventExecution.mjs.map +1 -0
- package/dist/esm/tools/handlers.mjs +1 -1
- package/dist/esm/tools/handlers.mjs.map +1 -1
- package/dist/esm/tools/streamedToolCallSeals.mjs +36 -0
- package/dist/esm/tools/streamedToolCallSeals.mjs.map +1 -0
- package/dist/types/events.d.ts +1 -0
- package/dist/types/graphs/Graph.d.ts +24 -9
- package/dist/types/index.d.ts +1 -0
- package/dist/types/llm/openai/index.d.ts +1 -0
- package/dist/types/openai/index.d.ts +75 -0
- package/dist/types/responses/index.d.ts +97 -0
- package/dist/types/run.d.ts +2 -0
- package/dist/types/session/AgentSession.d.ts +32 -0
- package/dist/types/session/JsonlSessionStore.d.ts +67 -0
- package/dist/types/session/handlers.d.ts +8 -0
- package/dist/types/session/ids.d.ts +4 -0
- package/dist/types/session/index.d.ts +5 -0
- package/dist/types/session/messageSerialization.d.ts +7 -0
- package/dist/types/session/types.d.ts +191 -0
- package/dist/types/tools/ToolNode.d.ts +12 -1
- package/dist/types/tools/eagerEventExecution.d.ts +23 -0
- package/dist/types/tools/streamedToolCallSeals.d.ts +13 -0
- package/dist/types/types/hitl.d.ts +4 -0
- package/dist/types/types/run.d.ts +11 -1
- package/dist/types/types/tools.d.ts +36 -0
- package/package.json +19 -2
- package/src/__tests__/stream.eagerEventExecution.test.ts +2571 -0
- package/src/events.ts +29 -0
- package/src/graphs/Graph.ts +224 -50
- package/src/graphs/MultiAgentGraph.ts +1 -1
- package/src/graphs/__tests__/composition.smoke.test.ts +30 -0
- package/src/index.ts +3 -0
- package/src/llm/anthropic/index.ts +356 -84
- package/src/llm/anthropic/llm.spec.ts +64 -0
- package/src/llm/custom-chat-models.smoke.test.ts +175 -4
- package/src/llm/openai/contentBlocks.test.ts +35 -0
- package/src/llm/openai/deepseek.test.ts +201 -2
- package/src/llm/openai/index.ts +171 -26
- package/src/llm/openai/utils/index.ts +22 -0
- package/src/llm/openrouter/index.ts +4 -2
- package/src/openai/__tests__/openai.test.ts +337 -0
- package/src/openai/index.ts +404 -0
- package/src/responses/__tests__/responses.test.ts +652 -0
- package/src/responses/index.ts +677 -0
- package/src/run.ts +158 -8
- package/src/scripts/compare_pi_vs_ours.ts +592 -173
- package/src/scripts/session_live.ts +548 -0
- package/src/session/AgentSession.ts +1432 -0
- package/src/session/JsonlSessionStore.ts +572 -0
- package/src/session/__tests__/JsonlSessionStore.test.ts +1410 -0
- package/src/session/__tests__/handlers.test.ts +161 -0
- package/src/session/handlers.ts +272 -0
- package/src/session/ids.ts +17 -0
- package/src/session/index.ts +44 -0
- package/src/session/messageSerialization.ts +207 -0
- package/src/session/types.ts +275 -0
- package/src/specs/custom-event-await.test.ts +89 -0
- package/src/specs/summarization.test.ts +1 -1
- package/src/stream.ts +756 -48
- package/src/summarization/node.ts +1 -1
- package/src/tools/ToolNode.ts +299 -126
- package/src/tools/__tests__/ToolNode.eagerEventExecution.test.ts +373 -0
- package/src/tools/__tests__/handlers.test.ts +2 -1
- package/src/tools/__tests__/hitl.test.ts +206 -110
- package/src/tools/eagerEventExecution.ts +153 -0
- package/src/tools/handlers.ts +8 -4
- package/src/tools/streamedToolCallSeals.ts +57 -0
- package/src/types/hitl.ts +4 -0
- package/src/types/run.ts +11 -0
- package/src/types/tools.ts +36 -0
- package/dist/cjs/llm/text.cjs +0 -69
- package/dist/cjs/llm/text.cjs.map +0 -1
- package/dist/esm/llm/text.mjs +0 -67
- package/dist/esm/llm/text.mjs.map +0 -1
|
@@ -4,17 +4,15 @@ var messages = require('@langchain/core/messages');
|
|
|
4
4
|
var langgraph = require('@langchain/langgraph');
|
|
5
5
|
var singletons = require('@langchain/core/singletons');
|
|
6
6
|
var _enum = require('../common/enum.cjs');
|
|
7
|
-
require('
|
|
8
|
-
require('../messages/core.cjs');
|
|
9
|
-
var truncation = require('../utils/truncation.cjs');
|
|
10
|
-
var langchain = require('../messages/langchain.cjs');
|
|
11
|
-
var events = require('../utils/events.cjs');
|
|
12
|
-
require('uuid');
|
|
7
|
+
require('../stream.cjs');
|
|
13
8
|
var run = require('../utils/run.cjs');
|
|
14
9
|
require('ai-tokenizer');
|
|
15
10
|
require('zod-to-json-schema');
|
|
11
|
+
var truncation = require('../utils/truncation.cjs');
|
|
12
|
+
var events = require('../utils/events.cjs');
|
|
16
13
|
var executeHooks = require('../hooks/executeHooks.cjs');
|
|
17
14
|
require('../hooks/createWorkspacePolicyHook.cjs');
|
|
15
|
+
var langchain = require('../messages/langchain.cjs');
|
|
18
16
|
var toolOutputReferences = require('./toolOutputReferences.cjs');
|
|
19
17
|
require('./local/CompileCheckTool.cjs');
|
|
20
18
|
require('path');
|
|
@@ -30,6 +28,7 @@ require('./ProgrammaticToolCalling.cjs');
|
|
|
30
28
|
require('./BashProgrammaticToolCalling.cjs');
|
|
31
29
|
var resolveLocalExecutionTools = require('./local/resolveLocalExecutionTools.cjs');
|
|
32
30
|
require('./local/attachments.cjs');
|
|
31
|
+
var eagerEventExecution = require('./eagerEventExecution.cjs');
|
|
33
32
|
|
|
34
33
|
/**
|
|
35
34
|
* Helper to check if a value is a Send object
|
|
@@ -260,6 +259,12 @@ class ToolNode extends run.RunnableCallable {
|
|
|
260
259
|
sessions;
|
|
261
260
|
/** When true, dispatches ON_TOOL_EXECUTE events instead of invoking tools directly */
|
|
262
261
|
eventDrivenMode = false;
|
|
262
|
+
/** Opt-in stream-layer prestart config for event-driven tools. */
|
|
263
|
+
eagerEventToolExecution;
|
|
264
|
+
/** Shared per-run prestarted tool registry populated by ChatModelStreamHandler. */
|
|
265
|
+
eagerEventToolExecutions;
|
|
266
|
+
/** Shared per-run per-tool turn counter used by eager and normal event dispatch. */
|
|
267
|
+
eagerEventToolUsageCount;
|
|
263
268
|
/** Agent ID for event-driven mode */
|
|
264
269
|
agentId;
|
|
265
270
|
/** Tool names that bypass event dispatch and execute directly (e.g., graph-managed handoff tools) */
|
|
@@ -303,7 +308,7 @@ class ToolNode extends run.RunnableCallable {
|
|
|
303
308
|
* other's in-flight state.
|
|
304
309
|
*/
|
|
305
310
|
anonBatchCounter = 0;
|
|
306
|
-
constructor({ tools, toolMap, name, tags, errorHandler, toolCallStepIds, handleToolErrors, loadRuntimeTools, toolRegistry, sessions, eventDrivenMode, agentId, directToolNames, maxContextTokens, maxToolResultChars, hookRegistry, humanInTheLoop, toolOutputReferences: toolOutputReferences$1, toolOutputRegistry, toolExecution, fileCheckpointer, }) {
|
|
311
|
+
constructor({ tools, toolMap, name, tags, errorHandler, toolCallStepIds, handleToolErrors, loadRuntimeTools, toolRegistry, sessions, eventDrivenMode, eagerEventToolExecution, eagerEventToolExecutions, eagerEventToolUsageCount, agentId, directToolNames, maxContextTokens, maxToolResultChars, hookRegistry, humanInTheLoop, toolOutputReferences: toolOutputReferences$1, toolOutputRegistry, toolExecution, fileCheckpointer, }) {
|
|
307
312
|
super({ name, tags, func: (input, config) => this.run(input, config) });
|
|
308
313
|
this.toolMap = toolMap ?? new Map(tools.map((tool) => [tool.name, tool]));
|
|
309
314
|
this.toolCallStepIds = toolCallStepIds;
|
|
@@ -317,6 +322,9 @@ class ToolNode extends run.RunnableCallable {
|
|
|
317
322
|
});
|
|
318
323
|
this.sessions = sessions;
|
|
319
324
|
this.eventDrivenMode = eventDrivenMode ?? false;
|
|
325
|
+
this.eagerEventToolExecution = eagerEventToolExecution;
|
|
326
|
+
this.eagerEventToolExecutions = eagerEventToolExecutions;
|
|
327
|
+
this.eagerEventToolUsageCount = eagerEventToolUsageCount;
|
|
320
328
|
this.agentId = agentId;
|
|
321
329
|
this.directToolNames = directToolNames;
|
|
322
330
|
this.maxToolResultChars =
|
|
@@ -495,6 +503,18 @@ class ToolNode extends run.RunnableCallable {
|
|
|
495
503
|
getToolUsageCounts() {
|
|
496
504
|
return new Map(this.toolUsageCount); // Return a copy
|
|
497
505
|
}
|
|
506
|
+
recordToolUsageTurn(toolName, turn, callId) {
|
|
507
|
+
this.toolUsageCount.set(toolName, Math.max(this.toolUsageCount.get(toolName) ?? 0, turn + 1));
|
|
508
|
+
if (callId != null && callId !== '') {
|
|
509
|
+
this.toolCallTurns.set(callId, turn);
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
recordEventToolPlanningTurn(toolName, turn, callId) {
|
|
513
|
+
this.recordToolUsageTurn(toolName, turn, callId);
|
|
514
|
+
if (this.canConsumeEagerEventExecution()) {
|
|
515
|
+
this.eagerEventToolUsageCount?.set(toolName, Math.max(this.eagerEventToolUsageCount.get(toolName) ?? 0, turn + 1));
|
|
516
|
+
}
|
|
517
|
+
}
|
|
498
518
|
/**
|
|
499
519
|
* Runs a single tool call with error handling.
|
|
500
520
|
*
|
|
@@ -1300,7 +1320,7 @@ class ToolNode extends run.RunnableCallable {
|
|
|
1300
1320
|
* by `runTool`. Threaded as a local map (instead of instance state)
|
|
1301
1321
|
* so concurrent batches cannot read each other's entries.
|
|
1302
1322
|
*/
|
|
1303
|
-
handleRunToolCompletions(calls, outputs, config, resolvedArgsByCallId) {
|
|
1323
|
+
async handleRunToolCompletions(calls, outputs, config, resolvedArgsByCallId) {
|
|
1304
1324
|
for (let i = 0; i < calls.length; i++) {
|
|
1305
1325
|
const call = calls[i];
|
|
1306
1326
|
const output = outputs[i];
|
|
@@ -1346,7 +1366,7 @@ class ToolNode extends run.RunnableCallable {
|
|
|
1346
1366
|
output: contentString,
|
|
1347
1367
|
progress: 1,
|
|
1348
1368
|
};
|
|
1349
|
-
events.safeDispatchCustomEvent(_enum.GraphEvents.ON_RUN_STEP_COMPLETED, {
|
|
1369
|
+
await events.safeDispatchCustomEvent(_enum.GraphEvents.ON_RUN_STEP_COMPLETED, {
|
|
1350
1370
|
result: {
|
|
1351
1371
|
id: stepId,
|
|
1352
1372
|
index: turn,
|
|
@@ -1515,9 +1535,9 @@ class ToolNode extends run.RunnableCallable {
|
|
|
1515
1535
|
reason,
|
|
1516
1536
|
});
|
|
1517
1537
|
};
|
|
1518
|
-
const flushDeferredBlockedSideEffects = () => {
|
|
1538
|
+
const flushDeferredBlockedSideEffects = async () => {
|
|
1519
1539
|
for (const item of deferredBlockedSideEffects) {
|
|
1520
|
-
this.dispatchStepCompleted(item.callId, item.toolName, item.args, item.contentString, config);
|
|
1540
|
+
await this.dispatchStepCompleted(item.callId, item.toolName, item.args, item.contentString, config);
|
|
1521
1541
|
if (hookRegistry.hasHookFor('PermissionDenied', runId)) {
|
|
1522
1542
|
executeHooks.executeHooks({
|
|
1523
1543
|
registry: hookRegistry,
|
|
@@ -1740,7 +1760,7 @@ class ToolNode extends run.RunnableCallable {
|
|
|
1740
1760
|
* no risk of being rolled back by a subsequent throw, so
|
|
1741
1761
|
* no risk of a duplicate `ON_RUN_STEP_COMPLETED` event.
|
|
1742
1762
|
*/
|
|
1743
|
-
this.dispatchStepCompleted(entry.call.id, entry.call.name, entry.args, truncatedResponse, config);
|
|
1763
|
+
await this.dispatchStepCompleted(entry.call.id, entry.call.name, entry.args, truncatedResponse, config);
|
|
1744
1764
|
continue;
|
|
1745
1765
|
}
|
|
1746
1766
|
if (decision.type === 'edit') {
|
|
@@ -1806,7 +1826,7 @@ class ToolNode extends run.RunnableCallable {
|
|
|
1806
1826
|
* dispatches in the same relative position as the pre-deferral
|
|
1807
1827
|
* code did (after hook processing, before tool execution).
|
|
1808
1828
|
*/
|
|
1809
|
-
flushDeferredBlockedSideEffects();
|
|
1829
|
+
await flushDeferredBlockedSideEffects();
|
|
1810
1830
|
}
|
|
1811
1831
|
else {
|
|
1812
1832
|
approvedEntries.push(...preToolCalls);
|
|
@@ -1814,50 +1834,92 @@ class ToolNode extends run.RunnableCallable {
|
|
|
1814
1834
|
const injected = [];
|
|
1815
1835
|
const batchIndexByCallId = new Map();
|
|
1816
1836
|
if (approvedEntries.length > 0) {
|
|
1817
|
-
const
|
|
1818
|
-
|
|
1819
|
-
|
|
1837
|
+
const plan = eagerEventExecution.buildToolExecutionRequestPlan({
|
|
1838
|
+
toolCalls: approvedEntries.map((entry) => {
|
|
1839
|
+
const codeSessionContext = _enum.CODE_EXECUTION_TOOLS.has(entry.call.name) ||
|
|
1840
|
+
entry.call.name === _enum.Constants.SKILL_TOOL ||
|
|
1841
|
+
entry.call.name === _enum.Constants.READ_FILE
|
|
1842
|
+
? this.getCodeSessionContext()
|
|
1843
|
+
: undefined;
|
|
1844
|
+
return {
|
|
1845
|
+
id: entry.call.id,
|
|
1846
|
+
name: entry.call.name,
|
|
1847
|
+
args: entry.args,
|
|
1848
|
+
stepId: entry.stepId,
|
|
1849
|
+
codeSessionContext,
|
|
1850
|
+
};
|
|
1851
|
+
}),
|
|
1852
|
+
usageCount: this.toolUsageCount,
|
|
1853
|
+
invalidArgsBehavior: 'error-result',
|
|
1854
|
+
recordTurn: (toolName, reservedTurn, callId) => {
|
|
1855
|
+
this.recordEventToolPlanningTurn(toolName, reservedTurn, callId);
|
|
1856
|
+
},
|
|
1857
|
+
});
|
|
1858
|
+
if (plan == null) {
|
|
1859
|
+
throw new Error('Unable to build event tool execution request plan');
|
|
1860
|
+
}
|
|
1861
|
+
const requests = plan.requests;
|
|
1862
|
+
for (const entry of approvedEntries) {
|
|
1820
1863
|
if (entry.batchIndex != null && entry.call.id != null) {
|
|
1821
1864
|
batchIndexByCallId.set(entry.call.id, entry.batchIndex);
|
|
1822
1865
|
}
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
* - `SKILL_TOOL` — skill files live alongside code-env state.
|
|
1835
|
-
* - `READ_FILE` — when the requested path is a code-env artifact
|
|
1836
|
-
* (e.g. `/mnt/data/...`) the host falls back to reading via the
|
|
1837
|
-
* same sandbox session; without the seeded `session_id` /
|
|
1838
|
-
* `_injected_files` here, that fallback can't see prior-turn
|
|
1839
|
-
* artifacts on the very first call of a turn.
|
|
1840
|
-
*/
|
|
1841
|
-
if (_enum.CODE_EXECUTION_TOOLS.has(entry.call.name) ||
|
|
1842
|
-
entry.call.name === _enum.Constants.SKILL_TOOL ||
|
|
1843
|
-
entry.call.name === _enum.Constants.READ_FILE) {
|
|
1844
|
-
request.codeSessionContext = this.getCodeSessionContext();
|
|
1866
|
+
}
|
|
1867
|
+
for (const result of plan.rejectedResults) {
|
|
1868
|
+
this.eagerEventToolExecutions?.delete(result.toolCallId);
|
|
1869
|
+
}
|
|
1870
|
+
const requestMap = new Map(plan.allRequests.map((r) => [r.id, r]));
|
|
1871
|
+
const eagerExecutions = [];
|
|
1872
|
+
const dispatchRequests = [];
|
|
1873
|
+
for (const request of requests) {
|
|
1874
|
+
const eagerExecution = this.takeMatchingEagerEventExecution(request);
|
|
1875
|
+
if (eagerExecution != null) {
|
|
1876
|
+
eagerExecutions.push({ request, execution: eagerExecution });
|
|
1845
1877
|
}
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1878
|
+
else {
|
|
1879
|
+
dispatchRequests.push(request);
|
|
1880
|
+
}
|
|
1881
|
+
}
|
|
1882
|
+
const dispatchPromise = dispatchRequests.length === 0
|
|
1883
|
+
? Promise.resolve([])
|
|
1884
|
+
: new Promise((resolve, reject) => {
|
|
1885
|
+
let dispatchSettled = false;
|
|
1886
|
+
let resultSettled = false;
|
|
1887
|
+
let settledResults;
|
|
1888
|
+
const maybeResolve = () => {
|
|
1889
|
+
if (dispatchSettled && resultSettled) {
|
|
1890
|
+
resolve(settledResults ?? []);
|
|
1891
|
+
}
|
|
1892
|
+
};
|
|
1893
|
+
const batchRequest = {
|
|
1894
|
+
toolCalls: dispatchRequests,
|
|
1895
|
+
userId: config.configurable?.user_id,
|
|
1896
|
+
agentId: this.agentId,
|
|
1897
|
+
configurable: config.configurable,
|
|
1898
|
+
metadata: config.metadata,
|
|
1899
|
+
resolve: (results) => {
|
|
1900
|
+
resultSettled = true;
|
|
1901
|
+
settledResults = results;
|
|
1902
|
+
maybeResolve();
|
|
1903
|
+
},
|
|
1904
|
+
reject,
|
|
1905
|
+
};
|
|
1906
|
+
void events.safeDispatchCustomEvent(_enum.GraphEvents.ON_TOOL_EXECUTE, batchRequest, config)
|
|
1907
|
+
.then(() => {
|
|
1908
|
+
dispatchSettled = true;
|
|
1909
|
+
maybeResolve();
|
|
1910
|
+
})
|
|
1911
|
+
.catch(reject);
|
|
1912
|
+
});
|
|
1913
|
+
const eagerResultsPromise = Promise.all(eagerExecutions.map(({ request, execution }) => this.resolveEagerEventExecution(request, execution))).then((results) => results.flat());
|
|
1914
|
+
const [eagerResults, dispatchedResults] = await Promise.all([
|
|
1915
|
+
eagerResultsPromise,
|
|
1916
|
+
dispatchPromise,
|
|
1917
|
+
]);
|
|
1918
|
+
const results = [
|
|
1919
|
+
...plan.rejectedResults,
|
|
1920
|
+
...eagerResults,
|
|
1921
|
+
...dispatchedResults,
|
|
1922
|
+
];
|
|
1861
1923
|
this.storeCodeSessionFromResults(results, requestMap);
|
|
1862
1924
|
const hasPostHook = this.hookRegistry?.hasHookFor('PostToolUse', runId) === true;
|
|
1863
1925
|
const hasFailureHook = this.hookRegistry?.hasHookFor('PostToolUseFailure', runId) === true;
|
|
@@ -1996,7 +2058,7 @@ class ToolNode extends run.RunnableCallable {
|
|
|
1996
2058
|
}),
|
|
1997
2059
|
});
|
|
1998
2060
|
}
|
|
1999
|
-
this.dispatchStepCompleted(result.toolCallId, toolName, request?.args ?? {}, contentString, config, request?.turn);
|
|
2061
|
+
await this.dispatchStepCompleted(result.toolCallId, toolName, request?.args ?? {}, contentString, config, request?.turn);
|
|
2000
2062
|
postToolBatchEntryByCallId.set(result.toolCallId, {
|
|
2001
2063
|
toolName,
|
|
2002
2064
|
toolInput: request?.args ?? {},
|
|
@@ -2024,6 +2086,62 @@ class ToolNode extends run.RunnableCallable {
|
|
|
2024
2086
|
});
|
|
2025
2087
|
return { toolMessages, injected };
|
|
2026
2088
|
}
|
|
2089
|
+
canConsumeEagerEventExecution() {
|
|
2090
|
+
return (this.eventDrivenMode &&
|
|
2091
|
+
this.eagerEventToolExecution?.enabled === true &&
|
|
2092
|
+
this.hookRegistry == null &&
|
|
2093
|
+
this.humanInTheLoop?.enabled !== true &&
|
|
2094
|
+
this.toolOutputRegistry == null);
|
|
2095
|
+
}
|
|
2096
|
+
takeMatchingEagerEventExecution(request) {
|
|
2097
|
+
if (!this.canConsumeEagerEventExecution()) {
|
|
2098
|
+
return undefined;
|
|
2099
|
+
}
|
|
2100
|
+
const execution = this.eagerEventToolExecutions?.get(request.id);
|
|
2101
|
+
if (execution == null) {
|
|
2102
|
+
return undefined;
|
|
2103
|
+
}
|
|
2104
|
+
this.eagerEventToolExecutions?.delete(request.id);
|
|
2105
|
+
if (execution.toolName !== request.name ||
|
|
2106
|
+
!eagerEventExecution.recordArgsEqual(execution.args, request.args) ||
|
|
2107
|
+
execution.request.turn !== request.turn) {
|
|
2108
|
+
return {
|
|
2109
|
+
toolCallId: request.id,
|
|
2110
|
+
toolName: request.name,
|
|
2111
|
+
args: request.args,
|
|
2112
|
+
request,
|
|
2113
|
+
promise: Promise.resolve({
|
|
2114
|
+
results: [
|
|
2115
|
+
{
|
|
2116
|
+
toolCallId: request.id,
|
|
2117
|
+
status: 'error',
|
|
2118
|
+
content: '',
|
|
2119
|
+
errorMessage: 'Tool call changed after eager execution started; refusing to re-run the tool to avoid duplicate side effects.',
|
|
2120
|
+
},
|
|
2121
|
+
],
|
|
2122
|
+
}),
|
|
2123
|
+
};
|
|
2124
|
+
}
|
|
2125
|
+
return execution;
|
|
2126
|
+
}
|
|
2127
|
+
async resolveEagerEventExecution(request, execution) {
|
|
2128
|
+
const outcome = await execution.promise;
|
|
2129
|
+
if (outcome.error != null) {
|
|
2130
|
+
throw outcome.error;
|
|
2131
|
+
}
|
|
2132
|
+
const results = outcome.results.filter((result) => result.toolCallId === request.id);
|
|
2133
|
+
if (results.length > 0) {
|
|
2134
|
+
return results;
|
|
2135
|
+
}
|
|
2136
|
+
return [
|
|
2137
|
+
{
|
|
2138
|
+
toolCallId: request.id,
|
|
2139
|
+
status: 'error',
|
|
2140
|
+
content: '',
|
|
2141
|
+
errorMessage: 'Tool execution completed without a result for this tool call',
|
|
2142
|
+
},
|
|
2143
|
+
];
|
|
2144
|
+
}
|
|
2027
2145
|
/**
|
|
2028
2146
|
* Fires the `PostToolBatch` hook (if registered) and appends the
|
|
2029
2147
|
* accumulated batch-level `additionalContext` strings to `injected`
|
|
@@ -2089,7 +2207,7 @@ class ToolNode extends run.RunnableCallable {
|
|
|
2089
2207
|
}));
|
|
2090
2208
|
}
|
|
2091
2209
|
}
|
|
2092
|
-
dispatchStepCompleted(toolCallId, toolName, args, output, config, turn) {
|
|
2210
|
+
async dispatchStepCompleted(toolCallId, toolName, args, output, config, turn) {
|
|
2093
2211
|
const stepId = this.toolCallStepIds?.get(toolCallId) ?? '';
|
|
2094
2212
|
if (!stepId) {
|
|
2095
2213
|
// eslint-disable-next-line no-console
|
|
@@ -2097,7 +2215,7 @@ class ToolNode extends run.RunnableCallable {
|
|
|
2097
2215
|
'This indicates a race between the stream consumer and graph execution. ' +
|
|
2098
2216
|
`Map size: ${this.toolCallStepIds?.size ?? 0}`);
|
|
2099
2217
|
}
|
|
2100
|
-
events.safeDispatchCustomEvent(_enum.GraphEvents.ON_RUN_STEP_COMPLETED, {
|
|
2218
|
+
await events.safeDispatchCustomEvent(_enum.GraphEvents.ON_RUN_STEP_COMPLETED, {
|
|
2101
2219
|
result: {
|
|
2102
2220
|
id: stepId,
|
|
2103
2221
|
index: turn ?? this.toolUsageCount.get(toolName) ?? 0,
|
|
@@ -2216,7 +2334,7 @@ class ToolNode extends run.RunnableCallable {
|
|
|
2216
2334
|
}),
|
|
2217
2335
|
]
|
|
2218
2336
|
: [sendOutput];
|
|
2219
|
-
this.handleRunToolCompletions([input.lg_tool_call],
|
|
2337
|
+
await this.handleRunToolCompletions([input.lg_tool_call],
|
|
2220
2338
|
// Pass only the tool output to completion handling; the
|
|
2221
2339
|
// HumanMessage isn't a tool result.
|
|
2222
2340
|
[sendOutput], config, resolvedArgsByCallId);
|
|
@@ -2340,7 +2458,7 @@ class ToolNode extends run.RunnableCallable {
|
|
|
2340
2458
|
})))
|
|
2341
2459
|
: [];
|
|
2342
2460
|
if (directCalls.length > 0 && directOutputs.length > 0) {
|
|
2343
|
-
this.handleRunToolCompletions(directCalls, directOutputs, config, resolvedArgsByCallId);
|
|
2461
|
+
await this.handleRunToolCompletions(directCalls, directOutputs, config, resolvedArgsByCallId);
|
|
2344
2462
|
}
|
|
2345
2463
|
const eventResult = eventCalls.length > 0
|
|
2346
2464
|
? await this.dispatchToolEvents(eventCalls, config, {
|
|
@@ -2388,7 +2506,7 @@ class ToolNode extends run.RunnableCallable {
|
|
|
2388
2506
|
preBatchSnapshot,
|
|
2389
2507
|
additionalContextsSink: directAdditionalContexts,
|
|
2390
2508
|
})));
|
|
2391
|
-
this.handleRunToolCompletions(filteredCalls, toolOutputs, config, resolvedArgsByCallId);
|
|
2509
|
+
await this.handleRunToolCompletions(filteredCalls, toolOutputs, config, resolvedArgsByCallId);
|
|
2392
2510
|
// Append accumulated additionalContexts as a single
|
|
2393
2511
|
// HumanMessage so the next model turn sees them. Codex P2 #39.
|
|
2394
2512
|
outputs =
|