@librechat/agents 3.1.86 → 3.1.87
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 +472 -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 +473 -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 +2458 -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 +755 -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
package/src/events.ts
CHANGED
|
@@ -21,6 +21,35 @@ export class HandlerRegistry {
|
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
+
export function composeEventHandlers(
|
|
25
|
+
...handlerSets: Array<Record<string, t.EventHandler> | undefined>
|
|
26
|
+
): Record<string, t.EventHandler> {
|
|
27
|
+
const composed: Partial<Record<string, t.EventHandler>> = {};
|
|
28
|
+
|
|
29
|
+
for (const handlerSet of handlerSets) {
|
|
30
|
+
if (!handlerSet) {
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
for (const [eventType, handler] of Object.entries(handlerSet)) {
|
|
34
|
+
const previous = composed[eventType];
|
|
35
|
+
if (previous === undefined) {
|
|
36
|
+
composed[eventType] = handler;
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
composed[eventType] = {
|
|
40
|
+
handle: async (
|
|
41
|
+
...args: Parameters<t.EventHandler['handle']>
|
|
42
|
+
): Promise<void> => {
|
|
43
|
+
await previous.handle(...args);
|
|
44
|
+
await handler.handle(...args);
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return composed as Record<string, t.EventHandler>;
|
|
51
|
+
}
|
|
52
|
+
|
|
24
53
|
export class ModelEndHandler implements t.EventHandler {
|
|
25
54
|
collectedUsage?: UsageMetadata[];
|
|
26
55
|
constructor(collectedUsage?: UsageMetadata[]) {
|
package/src/graphs/Graph.ts
CHANGED
|
@@ -70,6 +70,13 @@ const { AGENT, TOOLS, SUMMARIZE } = GraphNodeKeys;
|
|
|
70
70
|
/** Minimum relative variance before calibrated toolSchemaTokens overrides current value. */
|
|
71
71
|
const CALIBRATION_VARIANCE_THRESHOLD = 0.15;
|
|
72
72
|
|
|
73
|
+
function getHandlerDispatchedEventKey(
|
|
74
|
+
eventName: string,
|
|
75
|
+
stepId: string
|
|
76
|
+
): string {
|
|
77
|
+
return `${eventName}:${stepId}`;
|
|
78
|
+
}
|
|
79
|
+
|
|
73
80
|
export abstract class Graph<
|
|
74
81
|
T extends t.BaseGraphState = t.BaseGraphState,
|
|
75
82
|
_TNodeName extends string = string,
|
|
@@ -99,15 +106,18 @@ export abstract class Graph<
|
|
|
99
106
|
): Promise<string>;
|
|
100
107
|
abstract dispatchRunStepDelta(
|
|
101
108
|
id: string,
|
|
102
|
-
delta: t.ToolCallDelta
|
|
109
|
+
delta: t.ToolCallDelta,
|
|
110
|
+
metadata?: Record<string, unknown>
|
|
103
111
|
): Promise<void>;
|
|
104
112
|
abstract dispatchMessageDelta(
|
|
105
113
|
id: string,
|
|
106
|
-
delta: t.MessageDelta
|
|
114
|
+
delta: t.MessageDelta,
|
|
115
|
+
metadata?: Record<string, unknown>
|
|
107
116
|
): Promise<void>;
|
|
108
117
|
abstract dispatchReasoningDelta(
|
|
109
118
|
stepId: string,
|
|
110
|
-
delta: t.ReasoningDelta
|
|
119
|
+
delta: t.ReasoningDelta,
|
|
120
|
+
metadata?: Record<string, unknown>
|
|
111
121
|
): Promise<void>;
|
|
112
122
|
abstract createCallModel(
|
|
113
123
|
agentId?: string,
|
|
@@ -125,11 +135,12 @@ export abstract class Graph<
|
|
|
125
135
|
contentIndexMap: Map<string, number> = new Map();
|
|
126
136
|
toolCallStepIds: Map<string, string> = new Map();
|
|
127
137
|
/**
|
|
128
|
-
* Step IDs
|
|
129
|
-
*
|
|
130
|
-
*
|
|
138
|
+
* Step IDs dispatched through the handler registry during this run.
|
|
139
|
+
* Event echo suppression is tracked separately so repeated deltas for
|
|
140
|
+
* the same step are scoped to the active custom event dispatch.
|
|
131
141
|
*/
|
|
132
142
|
handlerDispatchedStepIds: Set<string> = new Set();
|
|
143
|
+
protected handlerDispatchedEventCounts: Map<string, number> = new Map();
|
|
133
144
|
signal?: AbortSignal;
|
|
134
145
|
/** Set of invoked tool call IDs from non-message run steps completed mid-run, if any */
|
|
135
146
|
invokedToolIds?: Set<string>;
|
|
@@ -148,6 +159,20 @@ export abstract class Graph<
|
|
|
148
159
|
* graph compiles.
|
|
149
160
|
*/
|
|
150
161
|
toolOutputReferences: t.ToolOutputReferencesConfig | undefined;
|
|
162
|
+
/**
|
|
163
|
+
* Run-scoped opt-in for eager event-driven tool execution. The stream
|
|
164
|
+
* handler may prestart eligible event-driven tools; ToolNode later
|
|
165
|
+
* consumes the settled promises while preserving final ToolMessage order.
|
|
166
|
+
*/
|
|
167
|
+
eagerEventToolExecution: t.EagerEventToolExecutionConfig | undefined;
|
|
168
|
+
eagerEventToolExecutions: Map<string, t.EagerEventToolExecution> = new Map();
|
|
169
|
+
eagerEventToolUsageCount: Map<string, number> = new Map();
|
|
170
|
+
private eagerEventToolUsageCountsByAgentId: Map<
|
|
171
|
+
string,
|
|
172
|
+
Map<string, number>
|
|
173
|
+
> = new Map();
|
|
174
|
+
eagerEventToolCallChunks: Map<string, t.EagerEventToolCallChunkState> =
|
|
175
|
+
new Map();
|
|
151
176
|
/**
|
|
152
177
|
* Run-scoped execution backend for built-in code tools. Defaults to the
|
|
153
178
|
* remote Code API sandbox when unset.
|
|
@@ -187,7 +212,12 @@ export abstract class Graph<
|
|
|
187
212
|
this.hookRegistry = undefined;
|
|
188
213
|
this.humanInTheLoop = undefined;
|
|
189
214
|
this.toolOutputReferences = undefined;
|
|
215
|
+
this.eagerEventToolExecution = undefined;
|
|
216
|
+
this.eagerEventToolExecutions.clear();
|
|
217
|
+
this.clearEagerEventToolUsageCounts();
|
|
218
|
+
this.eagerEventToolCallChunks.clear();
|
|
190
219
|
this.toolExecution = undefined;
|
|
220
|
+
this.handlerDispatchedEventCounts.clear();
|
|
191
221
|
/**
|
|
192
222
|
* ToolNodes compiled from this graph captured the registry
|
|
193
223
|
* instance at construction time, so simply dropping the Graph's
|
|
@@ -218,6 +248,46 @@ export abstract class Graph<
|
|
|
218
248
|
this.sessions.clear();
|
|
219
249
|
}
|
|
220
250
|
|
|
251
|
+
getEagerEventToolUsageCount(agentId?: string): Map<string, number> {
|
|
252
|
+
if (agentId == null || agentId === '') {
|
|
253
|
+
return this.eagerEventToolUsageCount;
|
|
254
|
+
}
|
|
255
|
+
let usageCount = this.eagerEventToolUsageCountsByAgentId.get(agentId);
|
|
256
|
+
if (usageCount == null) {
|
|
257
|
+
usageCount = new Map<string, number>();
|
|
258
|
+
this.eagerEventToolUsageCountsByAgentId.set(agentId, usageCount);
|
|
259
|
+
}
|
|
260
|
+
return usageCount;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
protected clearEagerEventToolUsageCounts(): void {
|
|
264
|
+
this.eagerEventToolUsageCount.clear();
|
|
265
|
+
for (const usageCount of this.eagerEventToolUsageCountsByAgentId.values()) {
|
|
266
|
+
usageCount.clear();
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
markHandlerDispatchedEvent(eventName: string, stepId: string): () => void {
|
|
271
|
+
const key = getHandlerDispatchedEventKey(eventName, stepId);
|
|
272
|
+
this.handlerDispatchedEventCounts.set(
|
|
273
|
+
key,
|
|
274
|
+
(this.handlerDispatchedEventCounts.get(key) ?? 0) + 1
|
|
275
|
+
);
|
|
276
|
+
return () => {
|
|
277
|
+
const count = this.handlerDispatchedEventCounts.get(key) ?? 0;
|
|
278
|
+
if (count <= 1) {
|
|
279
|
+
this.handlerDispatchedEventCounts.delete(key);
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
this.handlerDispatchedEventCounts.set(key, count - 1);
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
hasHandlerDispatchedEvent(eventName: string, stepId: string): boolean {
|
|
287
|
+
const key = getHandlerDispatchedEventKey(eventName, stepId);
|
|
288
|
+
return (this.handlerDispatchedEventCounts.get(key) ?? 0) > 0;
|
|
289
|
+
}
|
|
290
|
+
|
|
221
291
|
/**
|
|
222
292
|
* Subclass hook to register a freshly compiled ToolNode so
|
|
223
293
|
* `clearHeavyState` can flush its per-Run direct-path turn cache
|
|
@@ -279,9 +349,7 @@ export abstract class Graph<
|
|
|
279
349
|
private _compiledToolNodes: Set<{
|
|
280
350
|
clearDirectPathTurns(): void;
|
|
281
351
|
}> = new Set();
|
|
282
|
-
public getOrCreateFileCheckpointer():
|
|
283
|
-
| t.LocalFileCheckpointer
|
|
284
|
-
| undefined {
|
|
352
|
+
public getOrCreateFileCheckpointer(): t.LocalFileCheckpointer | undefined {
|
|
285
353
|
// Return the cached instance unconditionally if one exists. The
|
|
286
354
|
// toolExecution check below decides whether to *create* a new
|
|
287
355
|
// one — `clearHeavyState` nulls `this.toolExecution` at end-of-
|
|
@@ -301,9 +369,7 @@ export abstract class Graph<
|
|
|
301
369
|
// cleanup hooks fire). The bundle factory itself accepts a pre-
|
|
302
370
|
// supplied checkpointer when present, so re-injecting this one
|
|
303
371
|
// into every ToolNode is idempotent.
|
|
304
|
-
const bundle = createLocalCodingToolBundle(
|
|
305
|
-
this.toolExecution.local ?? {}
|
|
306
|
-
);
|
|
372
|
+
const bundle = createLocalCodingToolBundle(this.toolExecution.local ?? {});
|
|
307
373
|
this._fileCheckpointer = bundle.checkpointer;
|
|
308
374
|
return this._fileCheckpointer;
|
|
309
375
|
}
|
|
@@ -381,10 +447,17 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
|
|
|
381
447
|
* a stale reference on 2nd+ processStream calls.
|
|
382
448
|
*/
|
|
383
449
|
this.toolCallStepIds.clear();
|
|
450
|
+
this.eagerEventToolExecutions.clear();
|
|
451
|
+
this.clearEagerEventToolUsageCounts();
|
|
452
|
+
this.eagerEventToolCallChunks.clear();
|
|
384
453
|
this.handlerDispatchedStepIds = resetIfNotEmpty(
|
|
385
454
|
this.handlerDispatchedStepIds,
|
|
386
455
|
new Set()
|
|
387
456
|
);
|
|
457
|
+
this.handlerDispatchedEventCounts = resetIfNotEmpty(
|
|
458
|
+
this.handlerDispatchedEventCounts,
|
|
459
|
+
new Map()
|
|
460
|
+
);
|
|
388
461
|
this.messageIdsByStepKey = resetIfNotEmpty(
|
|
389
462
|
this.messageIdsByStepKey,
|
|
390
463
|
new Map()
|
|
@@ -679,6 +752,11 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
|
|
|
679
752
|
toolRegistry: agentContext?.toolRegistry,
|
|
680
753
|
hookRegistry: this.hookRegistry,
|
|
681
754
|
humanInTheLoop: this.humanInTheLoop,
|
|
755
|
+
eagerEventToolExecution: this.eagerEventToolExecution,
|
|
756
|
+
eagerEventToolExecutions: this.eagerEventToolExecutions,
|
|
757
|
+
eagerEventToolUsageCount: this.getEagerEventToolUsageCount(
|
|
758
|
+
agentContext?.agentId
|
|
759
|
+
),
|
|
682
760
|
toolExecution: this.toolExecution,
|
|
683
761
|
directToolNames: directToolNames.size > 0 ? directToolNames : undefined,
|
|
684
762
|
maxContextTokens: agentContext?.maxContextTokens,
|
|
@@ -1307,9 +1385,13 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
|
|
|
1307
1385
|
);
|
|
1308
1386
|
const stepId = this.getStepIdByKey(stepKey);
|
|
1309
1387
|
if (typeof content === 'string') {
|
|
1310
|
-
await this.dispatchMessageDelta(
|
|
1311
|
-
|
|
1312
|
-
|
|
1388
|
+
await this.dispatchMessageDelta(
|
|
1389
|
+
stepId,
|
|
1390
|
+
{
|
|
1391
|
+
content: [{ type: ContentTypes.TEXT, text: content }],
|
|
1392
|
+
},
|
|
1393
|
+
metadata
|
|
1394
|
+
);
|
|
1313
1395
|
} else if (
|
|
1314
1396
|
Array.isArray(content) &&
|
|
1315
1397
|
content.every(
|
|
@@ -1320,9 +1402,13 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
|
|
|
1320
1402
|
c.type.startsWith('text')
|
|
1321
1403
|
)
|
|
1322
1404
|
) {
|
|
1323
|
-
await this.dispatchMessageDelta(
|
|
1324
|
-
|
|
1325
|
-
|
|
1405
|
+
await this.dispatchMessageDelta(
|
|
1406
|
+
stepId,
|
|
1407
|
+
{
|
|
1408
|
+
content: content as t.MessageDelta['content'],
|
|
1409
|
+
},
|
|
1410
|
+
metadata
|
|
1411
|
+
);
|
|
1326
1412
|
}
|
|
1327
1413
|
}
|
|
1328
1414
|
}
|
|
@@ -1360,9 +1446,13 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
|
|
|
1360
1446
|
const stepId = this.getStepIdByKey(stepKey);
|
|
1361
1447
|
const content = responseMessage.content;
|
|
1362
1448
|
if (typeof content === 'string') {
|
|
1363
|
-
await this.dispatchMessageDelta(
|
|
1364
|
-
|
|
1365
|
-
|
|
1449
|
+
await this.dispatchMessageDelta(
|
|
1450
|
+
stepId,
|
|
1451
|
+
{
|
|
1452
|
+
content: [{ type: ContentTypes.TEXT, text: content }],
|
|
1453
|
+
},
|
|
1454
|
+
metadata
|
|
1455
|
+
);
|
|
1366
1456
|
} else if (
|
|
1367
1457
|
Array.isArray(content) &&
|
|
1368
1458
|
content.every(
|
|
@@ -1373,9 +1463,13 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
|
|
|
1373
1463
|
c.type.startsWith('text')
|
|
1374
1464
|
)
|
|
1375
1465
|
) {
|
|
1376
|
-
await this.dispatchMessageDelta(
|
|
1377
|
-
|
|
1378
|
-
|
|
1466
|
+
await this.dispatchMessageDelta(
|
|
1467
|
+
stepId,
|
|
1468
|
+
{
|
|
1469
|
+
content: content as t.MessageDelta['content'],
|
|
1470
|
+
},
|
|
1471
|
+
metadata
|
|
1472
|
+
);
|
|
1379
1473
|
}
|
|
1380
1474
|
}
|
|
1381
1475
|
}
|
|
@@ -1613,12 +1707,22 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
|
|
|
1613
1707
|
this.handlerDispatchedStepIds.add(runStep.id);
|
|
1614
1708
|
}
|
|
1615
1709
|
|
|
1616
|
-
|
|
1617
|
-
|
|
1710
|
+
const unmarkHandlerDispatchedEvent = handler
|
|
1711
|
+
? this.markHandlerDispatchedEvent(
|
|
1618
1712
|
GraphEvents.ON_RUN_STEP,
|
|
1619
|
-
runStep
|
|
1620
|
-
|
|
1621
|
-
|
|
1713
|
+
runStep.id
|
|
1714
|
+
)
|
|
1715
|
+
: undefined;
|
|
1716
|
+
try {
|
|
1717
|
+
if (resolvedConfig) {
|
|
1718
|
+
await safeDispatchCustomEvent(
|
|
1719
|
+
GraphEvents.ON_RUN_STEP,
|
|
1720
|
+
runStep,
|
|
1721
|
+
resolvedConfig
|
|
1722
|
+
);
|
|
1723
|
+
}
|
|
1724
|
+
} finally {
|
|
1725
|
+
unmarkHandlerDispatchedEvent?.();
|
|
1622
1726
|
}
|
|
1623
1727
|
},
|
|
1624
1728
|
dispatchRunStepCompleted: async (
|
|
@@ -1663,7 +1767,7 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
|
|
|
1663
1767
|
const StateAnnotation = Annotation.Root({
|
|
1664
1768
|
messages: Annotation<BaseMessage[]>({
|
|
1665
1769
|
reducer: (a, b) => {
|
|
1666
|
-
if (!
|
|
1770
|
+
if (!this.messages.length) {
|
|
1667
1771
|
this.startIndex = a.length + b.length;
|
|
1668
1772
|
}
|
|
1669
1773
|
const result = messagesStateReducer(a, b);
|
|
@@ -1782,11 +1886,18 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
|
|
|
1782
1886
|
// but the primary dispatch above guarantees the event reaches the handler.
|
|
1783
1887
|
// The customEventCallback in run.ts skips events already dispatched above
|
|
1784
1888
|
// to prevent double handling.
|
|
1785
|
-
|
|
1786
|
-
GraphEvents.ON_RUN_STEP,
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1889
|
+
const unmarkHandlerDispatchedEvent = handler
|
|
1890
|
+
? this.markHandlerDispatchedEvent(GraphEvents.ON_RUN_STEP, stepId)
|
|
1891
|
+
: undefined;
|
|
1892
|
+
try {
|
|
1893
|
+
await safeDispatchCustomEvent(
|
|
1894
|
+
GraphEvents.ON_RUN_STEP,
|
|
1895
|
+
runStep,
|
|
1896
|
+
this.config
|
|
1897
|
+
);
|
|
1898
|
+
} finally {
|
|
1899
|
+
unmarkHandlerDispatchedEvent?.();
|
|
1900
|
+
}
|
|
1790
1901
|
return stepId;
|
|
1791
1902
|
}
|
|
1792
1903
|
|
|
@@ -1858,7 +1969,8 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
|
|
|
1858
1969
|
|
|
1859
1970
|
async dispatchRunStepDelta(
|
|
1860
1971
|
id: string,
|
|
1861
|
-
delta: t.ToolCallDelta
|
|
1972
|
+
delta: t.ToolCallDelta,
|
|
1973
|
+
metadata?: Record<string, unknown>
|
|
1862
1974
|
): Promise<void> {
|
|
1863
1975
|
if (!this.config) {
|
|
1864
1976
|
throw new Error('No config provided');
|
|
@@ -1869,14 +1981,37 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
|
|
|
1869
1981
|
id,
|
|
1870
1982
|
delta,
|
|
1871
1983
|
};
|
|
1872
|
-
|
|
1873
|
-
GraphEvents.ON_RUN_STEP_DELTA
|
|
1874
|
-
runStepDelta,
|
|
1875
|
-
this.config
|
|
1984
|
+
const handler = this.handlerRegistry?.getHandler(
|
|
1985
|
+
GraphEvents.ON_RUN_STEP_DELTA
|
|
1876
1986
|
);
|
|
1987
|
+
if (handler) {
|
|
1988
|
+
await handler.handle(
|
|
1989
|
+
GraphEvents.ON_RUN_STEP_DELTA,
|
|
1990
|
+
runStepDelta,
|
|
1991
|
+
metadata,
|
|
1992
|
+
this
|
|
1993
|
+
);
|
|
1994
|
+
this.handlerDispatchedStepIds.add(id);
|
|
1995
|
+
}
|
|
1996
|
+
const unmarkHandlerDispatchedEvent = handler
|
|
1997
|
+
? this.markHandlerDispatchedEvent(GraphEvents.ON_RUN_STEP_DELTA, id)
|
|
1998
|
+
: undefined;
|
|
1999
|
+
try {
|
|
2000
|
+
await safeDispatchCustomEvent(
|
|
2001
|
+
GraphEvents.ON_RUN_STEP_DELTA,
|
|
2002
|
+
runStepDelta,
|
|
2003
|
+
this.config
|
|
2004
|
+
);
|
|
2005
|
+
} finally {
|
|
2006
|
+
unmarkHandlerDispatchedEvent?.();
|
|
2007
|
+
}
|
|
1877
2008
|
}
|
|
1878
2009
|
|
|
1879
|
-
async dispatchMessageDelta(
|
|
2010
|
+
async dispatchMessageDelta(
|
|
2011
|
+
id: string,
|
|
2012
|
+
delta: t.MessageDelta,
|
|
2013
|
+
metadata?: Record<string, unknown>
|
|
2014
|
+
): Promise<void> {
|
|
1880
2015
|
if (!this.config) {
|
|
1881
2016
|
throw new Error('No config provided');
|
|
1882
2017
|
}
|
|
@@ -1884,16 +2019,36 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
|
|
|
1884
2019
|
id,
|
|
1885
2020
|
delta,
|
|
1886
2021
|
};
|
|
1887
|
-
|
|
1888
|
-
GraphEvents.ON_MESSAGE_DELTA
|
|
1889
|
-
messageDelta,
|
|
1890
|
-
this.config
|
|
2022
|
+
const handler = this.handlerRegistry?.getHandler(
|
|
2023
|
+
GraphEvents.ON_MESSAGE_DELTA
|
|
1891
2024
|
);
|
|
2025
|
+
if (handler) {
|
|
2026
|
+
await handler.handle(
|
|
2027
|
+
GraphEvents.ON_MESSAGE_DELTA,
|
|
2028
|
+
messageDelta,
|
|
2029
|
+
metadata,
|
|
2030
|
+
this
|
|
2031
|
+
);
|
|
2032
|
+
this.handlerDispatchedStepIds.add(id);
|
|
2033
|
+
}
|
|
2034
|
+
const unmarkHandlerDispatchedEvent = handler
|
|
2035
|
+
? this.markHandlerDispatchedEvent(GraphEvents.ON_MESSAGE_DELTA, id)
|
|
2036
|
+
: undefined;
|
|
2037
|
+
try {
|
|
2038
|
+
await safeDispatchCustomEvent(
|
|
2039
|
+
GraphEvents.ON_MESSAGE_DELTA,
|
|
2040
|
+
messageDelta,
|
|
2041
|
+
this.config
|
|
2042
|
+
);
|
|
2043
|
+
} finally {
|
|
2044
|
+
unmarkHandlerDispatchedEvent?.();
|
|
2045
|
+
}
|
|
1892
2046
|
}
|
|
1893
2047
|
|
|
1894
2048
|
dispatchReasoningDelta = async (
|
|
1895
2049
|
stepId: string,
|
|
1896
|
-
delta: t.ReasoningDelta
|
|
2050
|
+
delta: t.ReasoningDelta,
|
|
2051
|
+
metadata?: Record<string, unknown>
|
|
1897
2052
|
): Promise<void> => {
|
|
1898
2053
|
if (!this.config) {
|
|
1899
2054
|
throw new Error('No config provided');
|
|
@@ -1902,10 +2057,29 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
|
|
|
1902
2057
|
id: stepId,
|
|
1903
2058
|
delta,
|
|
1904
2059
|
};
|
|
1905
|
-
|
|
1906
|
-
GraphEvents.ON_REASONING_DELTA
|
|
1907
|
-
reasoningDelta,
|
|
1908
|
-
this.config
|
|
2060
|
+
const handler = this.handlerRegistry?.getHandler(
|
|
2061
|
+
GraphEvents.ON_REASONING_DELTA
|
|
1909
2062
|
);
|
|
2063
|
+
if (handler) {
|
|
2064
|
+
await handler.handle(
|
|
2065
|
+
GraphEvents.ON_REASONING_DELTA,
|
|
2066
|
+
reasoningDelta,
|
|
2067
|
+
metadata,
|
|
2068
|
+
this
|
|
2069
|
+
);
|
|
2070
|
+
this.handlerDispatchedStepIds.add(stepId);
|
|
2071
|
+
}
|
|
2072
|
+
const unmarkHandlerDispatchedEvent = handler
|
|
2073
|
+
? this.markHandlerDispatchedEvent(GraphEvents.ON_REASONING_DELTA, stepId)
|
|
2074
|
+
: undefined;
|
|
2075
|
+
try {
|
|
2076
|
+
await safeDispatchCustomEvent(
|
|
2077
|
+
GraphEvents.ON_REASONING_DELTA,
|
|
2078
|
+
reasoningDelta,
|
|
2079
|
+
this.config
|
|
2080
|
+
);
|
|
2081
|
+
} finally {
|
|
2082
|
+
unmarkHandlerDispatchedEvent?.();
|
|
2083
|
+
}
|
|
1910
2084
|
};
|
|
1911
2085
|
}
|
|
@@ -723,7 +723,7 @@ export class MultiAgentGraph extends StandardGraph {
|
|
|
723
723
|
const StateAnnotation = Annotation.Root({
|
|
724
724
|
messages: Annotation<BaseMessage[]>({
|
|
725
725
|
reducer: (a, b) => {
|
|
726
|
-
if (!
|
|
726
|
+
if (!this.messages.length) {
|
|
727
727
|
this.startIndex = a.length + b.length;
|
|
728
728
|
}
|
|
729
729
|
const result = messagesStateReducer(a, b);
|
|
@@ -73,6 +73,36 @@ const expectCompiledWorkflow = (
|
|
|
73
73
|
};
|
|
74
74
|
|
|
75
75
|
describe('LangGraph composition smoke tests', () => {
|
|
76
|
+
it('clears run-scoped eager tool state on reset', () => {
|
|
77
|
+
const graph = new StandardGraph({
|
|
78
|
+
runId: 'standard-eager-reset',
|
|
79
|
+
agents: [makeAgent('agent')],
|
|
80
|
+
});
|
|
81
|
+
const executions = graph.eagerEventToolExecutions;
|
|
82
|
+
const usageCount = graph.eagerEventToolUsageCount;
|
|
83
|
+
const scopedUsageCount = graph.getEagerEventToolUsageCount('agent');
|
|
84
|
+
const chunks = graph.eagerEventToolCallChunks;
|
|
85
|
+
|
|
86
|
+
graph.eagerEventToolExecutions.set(
|
|
87
|
+
'call_weather',
|
|
88
|
+
{} as t.EagerEventToolExecution
|
|
89
|
+
);
|
|
90
|
+
graph.eagerEventToolUsageCount.set('weather', 1);
|
|
91
|
+
scopedUsageCount.set('weather', 1);
|
|
92
|
+
graph.eagerEventToolCallChunks.set('0', { argsText: '{"city":"NYC"}' });
|
|
93
|
+
|
|
94
|
+
graph.resetValues();
|
|
95
|
+
|
|
96
|
+
expect(graph.eagerEventToolExecutions).toBe(executions);
|
|
97
|
+
expect(graph.eagerEventToolUsageCount).toBe(usageCount);
|
|
98
|
+
expect(graph.getEagerEventToolUsageCount('agent')).toBe(scopedUsageCount);
|
|
99
|
+
expect(graph.eagerEventToolCallChunks).toBe(chunks);
|
|
100
|
+
expect(graph.eagerEventToolExecutions.size).toBe(0);
|
|
101
|
+
expect(graph.eagerEventToolUsageCount.size).toBe(0);
|
|
102
|
+
expect(scopedUsageCount.size).toBe(0);
|
|
103
|
+
expect(graph.eagerEventToolCallChunks.size).toBe(0);
|
|
104
|
+
});
|
|
105
|
+
|
|
76
106
|
it('compiles and invokes the standard single-agent graph', async () => {
|
|
77
107
|
const graph = new StandardGraph({
|
|
78
108
|
runId: 'standard-smoke',
|