@librechat/agents 3.9.7 → 4.0.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/cjs/common/enum.cjs +1 -0
- package/dist/cjs/common/enum.cjs.map +1 -1
- package/dist/cjs/graphs/Graph.cjs +4 -3
- package/dist/cjs/graphs/Graph.cjs.map +1 -1
- package/dist/cjs/instrumentation.cjs +3 -3
- package/dist/cjs/langfuse.cjs +3 -3
- package/dist/cjs/langfuseRuntimeScope.cjs +1 -1
- package/dist/cjs/langfuseToolOutputTracing.cjs +2 -2
- package/dist/cjs/llm/bedrock/index.cjs +1 -1
- package/dist/cjs/llm/bedrock/index.cjs.map +1 -1
- package/dist/cjs/llm/bedrock/utils/message_inputs.cjs +20 -9
- package/dist/cjs/llm/bedrock/utils/message_inputs.cjs.map +1 -1
- package/dist/cjs/llm/invoke.cjs +1 -1
- package/dist/cjs/run.cjs +4 -3
- package/dist/cjs/run.cjs.map +1 -1
- package/dist/cjs/stream.cjs +7 -4
- package/dist/cjs/stream.cjs.map +1 -1
- package/dist/cjs/tools/ProgrammaticToolCalling.cjs +1 -1
- package/dist/cjs/tools/ToolNode.cjs +20 -6
- package/dist/cjs/tools/ToolNode.cjs.map +1 -1
- package/dist/cjs/tools/handlers.cjs +2 -2
- package/dist/cjs/tools/handlers.cjs.map +1 -1
- package/dist/cjs/tools/subagent/SubagentExecutor.cjs +22 -0
- package/dist/cjs/tools/subagent/SubagentExecutor.cjs.map +1 -1
- package/dist/cjs/utils/events.cjs +20 -2
- package/dist/cjs/utils/events.cjs.map +1 -1
- package/dist/esm/common/enum.mjs +1 -0
- package/dist/esm/common/enum.mjs.map +1 -1
- package/dist/esm/graphs/Graph.mjs +4 -3
- package/dist/esm/graphs/Graph.mjs.map +1 -1
- package/dist/esm/instrumentation.mjs +3 -3
- package/dist/esm/langfuse.mjs +3 -3
- package/dist/esm/langfuseRuntimeScope.mjs +1 -1
- package/dist/esm/langfuseToolOutputTracing.mjs +2 -2
- package/dist/esm/llm/bedrock/index.mjs +1 -1
- package/dist/esm/llm/bedrock/index.mjs.map +1 -1
- package/dist/esm/llm/bedrock/utils/message_inputs.mjs +20 -9
- package/dist/esm/llm/bedrock/utils/message_inputs.mjs.map +1 -1
- package/dist/esm/llm/invoke.mjs +1 -1
- package/dist/esm/run.mjs +4 -3
- package/dist/esm/run.mjs.map +1 -1
- package/dist/esm/stream.mjs +11 -7
- package/dist/esm/stream.mjs.map +1 -1
- package/dist/esm/tools/ProgrammaticToolCalling.mjs +1 -1
- package/dist/esm/tools/ToolNode.mjs +24 -9
- package/dist/esm/tools/ToolNode.mjs.map +1 -1
- package/dist/esm/tools/handlers.mjs +2 -2
- package/dist/esm/tools/handlers.mjs.map +1 -1
- package/dist/esm/tools/subagent/SubagentExecutor.mjs +22 -0
- package/dist/esm/tools/subagent/SubagentExecutor.mjs.map +1 -1
- package/dist/esm/utils/events.mjs +20 -3
- package/dist/esm/utils/events.mjs.map +1 -1
- package/dist/types/common/enum.d.ts +2 -0
- package/dist/types/graphs/Graph.d.ts +2 -2
- package/dist/types/llm/bedrock/utils/message_inputs.d.ts +13 -1
- package/dist/types/tools/handlers.d.ts +2 -1
- package/dist/types/types/graph.d.ts +3 -3
- package/dist/types/types/stream.d.ts +24 -0
- package/dist/types/types/tools.d.ts +2 -0
- package/dist/types/utils/events.d.ts +4 -0
- package/package.json +1 -1
- package/src/common/enum.ts +2 -0
- package/src/graphs/Graph.ts +5 -2
- package/src/llm/bedrock/index.ts +4 -2
- package/src/llm/bedrock/utils/message_inputs.ts +62 -15
- package/src/run.ts +9 -7
- package/src/stream.ts +12 -3
- package/src/tools/ToolNode.ts +32 -6
- package/src/tools/handlers.ts +4 -1
- package/src/tools/subagent/SubagentExecutor.ts +24 -0
- package/src/types/graph.ts +3 -0
- package/src/types/stream.ts +21 -0
- package/src/types/tools.ts +2 -0
- package/src/utils/events.ts +21 -2
|
@@ -10,9 +10,14 @@ async function safeDispatchCustomEvent(event, payload, config) {
|
|
|
10
10
|
payload = {
|
|
11
11
|
...request,
|
|
12
12
|
resolve: (results) => {
|
|
13
|
-
|
|
13
|
+
const receivedAt = Date.now();
|
|
14
|
+
const stamped = results.map((result) => ({
|
|
15
|
+
...result,
|
|
16
|
+
received_at: receivedAt
|
|
17
|
+
}));
|
|
18
|
+
traceHostToolResults(request, results, config).then(() => request.resolve(stamped), () => {
|
|
14
19
|
console.warn("Failed to record host tool execution metadata");
|
|
15
|
-
request.resolve(
|
|
20
|
+
request.resolve(stamped);
|
|
16
21
|
});
|
|
17
22
|
}
|
|
18
23
|
};
|
|
@@ -25,6 +30,18 @@ async function safeDispatchCustomEvent(event, payload, config) {
|
|
|
25
30
|
return false;
|
|
26
31
|
}
|
|
27
32
|
}
|
|
33
|
+
function createToolCallsDispatchedEvent(config, calls) {
|
|
34
|
+
const runId = config.configurable?.run_id;
|
|
35
|
+
return {
|
|
36
|
+
dispatched_at: Date.now(),
|
|
37
|
+
...typeof runId === "string" ? { runId } : {},
|
|
38
|
+
toolCalls: calls.map(({ id, name, stepId }) => ({
|
|
39
|
+
id,
|
|
40
|
+
name,
|
|
41
|
+
stepId
|
|
42
|
+
}))
|
|
43
|
+
};
|
|
44
|
+
}
|
|
28
45
|
function emitAgentLog(config, level, scope, message, data, meta, options) {
|
|
29
46
|
if (!config) return;
|
|
30
47
|
if (level === "debug" && !(options?.force ?? false) && process.env.AGENT_DEBUG_LOGGING !== "true") return;
|
|
@@ -37,6 +54,6 @@ function emitAgentLog(config, level, scope, message, data, meta, options) {
|
|
|
37
54
|
}, config);
|
|
38
55
|
}
|
|
39
56
|
//#endregion
|
|
40
|
-
export { emitAgentLog, safeDispatchCustomEvent };
|
|
57
|
+
export { createToolCallsDispatchedEvent, emitAgentLog, safeDispatchCustomEvent };
|
|
41
58
|
|
|
42
59
|
//# sourceMappingURL=events.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"events.mjs","names":[],"sources":["../../../src/utils/events.ts"],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"events.mjs","names":[],"sources":["../../../src/utils/events.ts"],"mappings":";;;;;AAcA,eAAsB,wBACpB,OACA,SACA,QACyB;CACzB,IAAI;EACF,IAAI,UAAA,mBAAuC;GACzC,MAAM,UAAU;GAChB,UAAU;IACR,GAAG;IACH,UACE,YACS;KACT,MAAM,aAAa,KAAK,IAAI;KAC5B,MAAM,UAAU,QAAQ,KAAK,YAAY;MAAE,GAAG;MAAQ,aAAa;KAAW,EAAE;KAChF,qBAA0B,SAAS,SAAS,MAAM,CAAC,CAAC,WAC5C,QAAQ,QAAQ,OAAO,SACvB;MACJ,QAAQ,KAAK,+CAA+C;MAC5D,QAAQ,QAAQ,OAAO;KACzB,CACF;IACF;GACF;EACF;EACA,MAAM,oBAAoB,OAAO,SAAS,MAAM;EAChD,OAAO;CACT,SAAS,GAAG;EAEV,IACE,aAAa,SACb,EAAE,QAAQ,SAAS,2BAA2B,KAC9C,EAAE,QAAQ,SAAS,sBAAsB,GAKzC,OAAO;EAGT,QAAQ,MAAM,mCAAmC,CAAC;EAClD,OAAO;CACT;AACF;AAGA,SAAgB,+BACd,QACA,OAI0B;CAC1B,MAAM,QAAQ,OAAO,cAAc;CACnC,OAAO;EACL,eAAe,KAAK,IAAI;EACxB,GAAI,OAAO,UAAU,WAAW,EAAE,MAAM,IAAI,CAAC;EAC7C,WAAW,MAAM,KAAK,EAAE,IAAI,MAAM,cAAc;GAAE;GAAI;GAAM;EAAO,EAAE;CACvE;AACF;AAQA,SAAgB,aACd,QACA,OACA,OACA,SACA,MACA,MACA,SACM;CACN,IAAI,CAAC,QAAQ;CACb,IACE,UAAU,WACV,EAAE,SAAS,SAAS,UACpB,QAAQ,IAAI,wBAAwB,QAEpC;CACF,wBAAK,gBAEH;EAAE;EAAO;EAAO;EAAS;EAAM,GAAG;CAAK,GACvC,MACF;AACF"}
|
|
@@ -23,6 +23,8 @@ export declare enum GraphEvents {
|
|
|
23
23
|
ON_MESSAGE_DELTA = "on_message_delta",
|
|
24
24
|
/** [Custom] Reasoning Delta events for messages */
|
|
25
25
|
ON_REASONING_DELTA = "on_reasoning_delta",
|
|
26
|
+
/** [Custom] Per-call handoff boundary between streamed tool preparation and execution */
|
|
27
|
+
ON_TOOL_CALLS_DISPATCHED = "on_tool_calls_dispatched",
|
|
26
28
|
/** [Custom] Request to execute tools - dispatched by ToolNode, handled by host */
|
|
27
29
|
ON_TOOL_EXECUTE = "on_tool_execute",
|
|
28
30
|
/** [Custom] Emitted when the summarize node begins generating a summary */
|
|
@@ -38,7 +38,7 @@ export declare abstract class Graph<T extends t.BaseGraphState = t.BaseGraphStat
|
|
|
38
38
|
abstract getStepIdByKey(stepKey: string, index?: number): string;
|
|
39
39
|
abstract getRunStep(stepId: string): t.RunStep | undefined;
|
|
40
40
|
abstract dispatchRunStep(stepKey: string, stepDetails: t.StepDetails, metadata?: Record<string, unknown>): Promise<string>;
|
|
41
|
-
abstract dispatchRunStepDelta(id: string, delta: t.ToolCallDelta, metadata?: Record<string, unknown
|
|
41
|
+
abstract dispatchRunStepDelta(id: string, delta: t.ToolCallDelta, metadata?: Record<string, unknown>, observedAt?: number): Promise<void>;
|
|
42
42
|
abstract dispatchMessageDelta(id: string, delta: t.MessageDelta, metadata?: Record<string, unknown>): Promise<void>;
|
|
43
43
|
abstract dispatchReasoningDelta(stepId: string, delta: t.ReasoningDelta, metadata?: Record<string, unknown>): Promise<void>;
|
|
44
44
|
abstract createCallModel(agentId?: string, currentModel?: t.ChatModel): (state: t.AgentSubgraphState, config?: RunnableConfig) => Promise<Partial<t.AgentSubgraphState>>;
|
|
@@ -761,7 +761,7 @@ export declare class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode>
|
|
|
761
761
|
* Kept for backward compatibility
|
|
762
762
|
*/
|
|
763
763
|
handleToolCallError(data: t.ToolErrorData, metadata?: Record<string, unknown>): Promise<boolean>;
|
|
764
|
-
dispatchRunStepDelta(id: string, delta: t.ToolCallDelta, metadata?: Record<string, unknown
|
|
764
|
+
dispatchRunStepDelta(id: string, delta: t.ToolCallDelta, metadata?: Record<string, unknown>, observedAt?: number): Promise<void>;
|
|
765
765
|
dispatchMessageDelta(id: string, delta: t.MessageDelta, metadata?: Record<string, unknown>): Promise<void>;
|
|
766
766
|
dispatchReasoningDelta: (stepId: string, delta: t.ReasoningDelta, metadata?: Record<string, unknown>) => Promise<void>;
|
|
767
767
|
}
|
|
@@ -22,10 +22,22 @@ export declare function concatenateLangchainReasoningBlocks(content: Array<Messa
|
|
|
22
22
|
* Extract image info from a base64 string or URL.
|
|
23
23
|
*/
|
|
24
24
|
export declare function extractImageInfo(base64: string): BedrockContentBlock;
|
|
25
|
+
/** Options for {@link convertToConverseMessages}. */
|
|
26
|
+
export interface ConvertToConverseMessagesOptions {
|
|
27
|
+
/** The model the request is for, which decides whether prior reasoning is replayed. */
|
|
28
|
+
model?: string;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* OpenAI Bedrock models reject prior `reasoningContent`, including on Claude-to-GPT handoffs.
|
|
32
|
+
* Only suppress replay for identified OpenAI targets; other model families retain the existing
|
|
33
|
+
* behavior because their Bedrock reasoning-replay requirements have not been verified here.
|
|
34
|
+
* Missing model IDs and opaque resource ARNs also retain the existing behavior.
|
|
35
|
+
*/
|
|
36
|
+
export declare function replaysBedrockReasoning(model?: string): boolean;
|
|
25
37
|
/**
|
|
26
38
|
* Convert LangChain messages to Bedrock Converse messages.
|
|
27
39
|
*/
|
|
28
|
-
export declare function convertToConverseMessages(messages: BaseMessage[]): {
|
|
40
|
+
export declare function convertToConverseMessages(messages: BaseMessage[], options?: ConvertToConverseMessagesOptions): {
|
|
29
41
|
converseMessages: BedrockMessage[];
|
|
30
42
|
converseSystem: BedrockSystemContentBlock[];
|
|
31
43
|
};
|
|
@@ -2,11 +2,12 @@ import type { ToolCall, ToolCallChunk } from '@langchain/core/messages/tool';
|
|
|
2
2
|
import type { Graph, MultiAgentGraph, StandardGraph } from '@/graphs';
|
|
3
3
|
import type { AgentContext } from '@/agents/AgentContext';
|
|
4
4
|
import type * as t from '@/types';
|
|
5
|
-
export declare function handleToolCallChunks({ graph, stepKey, toolCallChunks, metadata, }: {
|
|
5
|
+
export declare function handleToolCallChunks({ graph, stepKey, toolCallChunks, metadata, observedAt, }: {
|
|
6
6
|
graph: StandardGraph | MultiAgentGraph;
|
|
7
7
|
stepKey: string;
|
|
8
8
|
toolCallChunks: ToolCallChunk[];
|
|
9
9
|
metadata?: Record<string, unknown>;
|
|
10
|
+
observedAt?: number;
|
|
10
11
|
}): Promise<void>;
|
|
11
12
|
export declare const handleToolCalls: (toolCalls?: ToolCall[], metadata?: Record<string, unknown>, graph?: Graph | StandardGraph | MultiAgentGraph) => Promise<void>;
|
|
12
13
|
export declare const toolResultTypes: Set<string>;
|
|
@@ -4,7 +4,7 @@ import type { START, StateGraph, StateGraphArgs } from '@langchain/langgraph';
|
|
|
4
4
|
import type { RunnableConfig, Runnable } from '@langchain/core/runnables';
|
|
5
5
|
import type { ChatGenerationChunk } from '@langchain/core/outputs';
|
|
6
6
|
import type { GoogleAIToolType } from '@langchain/google-common';
|
|
7
|
-
import type { RunStep, ModelResponseEvent, ModelToolsClaimedEvent, RunStepDeltaEvent, RunStepResumeState, RunStepClosedEvent, MessageDeltaEvent, ReasoningDeltaEvent } from '@/types/stream';
|
|
7
|
+
import type { RunStep, ModelResponseEvent, ModelToolsClaimedEvent, RunStepDeltaEvent, RunStepResumeState, RunStepClosedEvent, ToolCallsDispatchedEvent, MessageDeltaEvent, ReasoningDeltaEvent } from '@/types/stream';
|
|
8
8
|
import type { SummarizationNodeInput, SummarizeCompleteEvent, CompactionSemanticIndex, SummarizationConfig, SummarizeStartEvent, SummarizeDeltaEvent } from '@/types/summarize';
|
|
9
9
|
import type { ToolMap, ToolSessionMap, ToolEndEvent, GenericTool, LCTool, ToolExecutionConfig, ToolExecuteBatchRequest } from '@/types/tools';
|
|
10
10
|
import type { TokenCounter, StreamLimits, StreamPreemption, TokenBudgetBreakdown } from '@/types/run';
|
|
@@ -139,7 +139,7 @@ export interface FadingTier {
|
|
|
139
139
|
/** Latched fading tiers keyed by agent ID. */
|
|
140
140
|
export type FadingTiers = Record<string, FadingTier>;
|
|
141
141
|
export interface EventHandler {
|
|
142
|
-
handle(event: string, data: StreamEventData | ModelEndData | ModelResponseEvent | ModelToolsClaimedEvent | RunStep | RunStepDeltaEvent | RunStepClosedEvent | MessageDeltaEvent | ReasoningDeltaEvent | SummarizeStartEvent | SummarizeDeltaEvent | SummarizeCompleteEvent | SubagentUpdateEvent | AgentLogEvent | ContextUsageEvent | ToolExecuteBatchRequest | {
|
|
142
|
+
handle(event: string, data: StreamEventData | ModelEndData | ModelResponseEvent | ModelToolsClaimedEvent | RunStep | RunStepDeltaEvent | RunStepClosedEvent | ToolCallsDispatchedEvent | MessageDeltaEvent | ReasoningDeltaEvent | SummarizeStartEvent | SummarizeDeltaEvent | SummarizeCompleteEvent | SubagentUpdateEvent | AgentLogEvent | ContextUsageEvent | ToolExecuteBatchRequest | {
|
|
143
143
|
result: ToolEndEvent;
|
|
144
144
|
}, metadata?: Record<string, unknown>, graph?: StandardGraph | MultiAgentGraph): void | Promise<void>;
|
|
145
145
|
}
|
|
@@ -531,7 +531,7 @@ export type ExecutableSubagentConfig = ResolvedSubagentConfig | LazySingleAgentS
|
|
|
531
531
|
/** Graph-aware config accepted by the executor. Graph configs stay eager. */
|
|
532
532
|
export type ExecutableSubagentConfigEntry = ExecutableSubagentConfig | GraphSubagentConfig;
|
|
533
533
|
/** Lifecycle phase carried on {@link SubagentUpdateEvent}. */
|
|
534
|
-
export type SubagentUpdatePhase = 'start' | 'run_step' | 'run_step_delta' | 'run_step_completed' | 'run_step_closed' | 'message_delta' | 'reasoning_delta' | 'control' | 'stop' | 'error';
|
|
534
|
+
export type SubagentUpdatePhase = 'start' | 'run_step' | 'run_step_delta' | 'tool_calls_dispatched' | 'run_step_completed' | 'run_step_closed' | 'message_delta' | 'reasoning_delta' | 'control' | 'stop' | 'error';
|
|
535
535
|
export interface SubagentAncestryEntry {
|
|
536
536
|
readonly subagentRunId: string;
|
|
537
537
|
readonly subagentType: string;
|
|
@@ -127,6 +127,8 @@ export interface RunStepDeltaEvent {
|
|
|
127
127
|
* The delta containing the fields that have changed on the run step.
|
|
128
128
|
*/
|
|
129
129
|
delta: ToolCallDelta;
|
|
130
|
+
/** Epoch ms when the SDK received this tool-call fragment, before step dispatch. */
|
|
131
|
+
observed_at?: number;
|
|
130
132
|
}
|
|
131
133
|
/**
|
|
132
134
|
* Terminal signal for a run step, emitted exactly once per step when it
|
|
@@ -218,6 +220,28 @@ export type ToolCallCompleted = {
|
|
|
218
220
|
type: 'tool_call';
|
|
219
221
|
tool_call: ProcessedToolCall;
|
|
220
222
|
};
|
|
223
|
+
/**
|
|
224
|
+
* A tool call has crossed from model-authored argument preparation into SDK
|
|
225
|
+
* execution. Emitted immediately before host dispatch or direct invocation;
|
|
226
|
+
* it does not claim the host has begun its own work. Paired with the tool
|
|
227
|
+
* completion `completed_at`, the stamp measures SDK handoff-to-result time,
|
|
228
|
+
* not MCP or database execution time. The earliest `observed_at` tool-call
|
|
229
|
+
* delta for a call bounds its argument preparation time; consumers correlate
|
|
230
|
+
* deltas by step/index until an ID is known. For a call without streamed
|
|
231
|
+
* fragments, the preparation start is unknown. Never infer a missing start.
|
|
232
|
+
* An eager call may dispatch before it has a step ID, and this observational
|
|
233
|
+
* event may arrive after completion: correlate by tool call ID and timestamps,
|
|
234
|
+
* not arrival order.
|
|
235
|
+
*/
|
|
236
|
+
export type ToolCallsDispatchedEvent = {
|
|
237
|
+
dispatched_at: number;
|
|
238
|
+
runId?: string;
|
|
239
|
+
toolCalls: Array<{
|
|
240
|
+
id: string;
|
|
241
|
+
name: string;
|
|
242
|
+
stepId?: string;
|
|
243
|
+
}>;
|
|
244
|
+
};
|
|
221
245
|
export type ToolCompleteEvent = ToolCallCompleted & {
|
|
222
246
|
/** The Step Id of the Tool Call */
|
|
223
247
|
id: string;
|
|
@@ -644,6 +644,8 @@ export type OutcomePatch = {
|
|
|
644
644
|
export type ToolExecuteResult = {
|
|
645
645
|
/** Matches ToolCallRequest.id */
|
|
646
646
|
toolCallId: string;
|
|
647
|
+
/** SDK-stamped result receipt time; never host-supplied or inferred from handler cleanup. */
|
|
648
|
+
received_at?: number;
|
|
647
649
|
/** Tool output content */
|
|
648
650
|
content: string | unknown[];
|
|
649
651
|
/** Optional artifact (for content_and_artifact format) */
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import type { RunnableConfig } from '@langchain/core/runnables';
|
|
2
|
+
import type { ToolCallsDispatchedEvent } from '@/types/stream';
|
|
3
|
+
import type { ToolExecuteBatchRequest } from '@/types/tools';
|
|
2
4
|
import type { AgentLogEvent } from '@/types/graph';
|
|
3
5
|
/**
|
|
4
6
|
* Safely dispatches a custom event and properly awaits it to avoid
|
|
5
7
|
* race conditions where events are dispatched after run cleanup.
|
|
6
8
|
*/
|
|
7
9
|
export declare function safeDispatchCustomEvent(event: string, payload: unknown, config?: RunnableConfig): Promise<boolean | void>;
|
|
10
|
+
/** Builds an argument-free snapshot once per handoff, not once per result. */
|
|
11
|
+
export declare function createToolCallsDispatchedEvent(config: RunnableConfig, calls: readonly Pick<ToolExecuteBatchRequest['toolCalls'][number], 'id' | 'name' | 'stepId'>[]): ToolCallsDispatchedEvent;
|
|
8
12
|
/**
|
|
9
13
|
* Fire-and-forget diagnostic log event.
|
|
10
14
|
* Debug-level logs are gated behind AGENT_DEBUG_LOGGING=true to avoid
|
package/package.json
CHANGED
package/src/common/enum.ts
CHANGED
|
@@ -26,6 +26,8 @@ export enum GraphEvents {
|
|
|
26
26
|
ON_MESSAGE_DELTA = 'on_message_delta',
|
|
27
27
|
/** [Custom] Reasoning Delta events for messages */
|
|
28
28
|
ON_REASONING_DELTA = 'on_reasoning_delta',
|
|
29
|
+
/** [Custom] Per-call handoff boundary between streamed tool preparation and execution */
|
|
30
|
+
ON_TOOL_CALLS_DISPATCHED = 'on_tool_calls_dispatched',
|
|
29
31
|
/** [Custom] Request to execute tools - dispatched by ToolNode, handled by host */
|
|
30
32
|
ON_TOOL_EXECUTE = 'on_tool_execute',
|
|
31
33
|
/** [Custom] Emitted when the summarize node begins generating a summary */
|
package/src/graphs/Graph.ts
CHANGED
|
@@ -766,7 +766,8 @@ export abstract class Graph<
|
|
|
766
766
|
abstract dispatchRunStepDelta(
|
|
767
767
|
id: string,
|
|
768
768
|
delta: t.ToolCallDelta,
|
|
769
|
-
metadata?: Record<string, unknown
|
|
769
|
+
metadata?: Record<string, unknown>,
|
|
770
|
+
observedAt?: number
|
|
770
771
|
): Promise<void>;
|
|
771
772
|
abstract dispatchMessageDelta(
|
|
772
773
|
id: string,
|
|
@@ -6130,7 +6131,8 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
|
|
|
6130
6131
|
async dispatchRunStepDelta(
|
|
6131
6132
|
id: string,
|
|
6132
6133
|
delta: t.ToolCallDelta,
|
|
6133
|
-
metadata?: Record<string, unknown
|
|
6134
|
+
metadata?: Record<string, unknown>,
|
|
6135
|
+
observedAt?: number
|
|
6134
6136
|
): Promise<void> {
|
|
6135
6137
|
if (!this.config) {
|
|
6136
6138
|
throw new Error('No config provided');
|
|
@@ -6140,6 +6142,7 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
|
|
|
6140
6142
|
const runStepDelta: t.RunStepDeltaEvent = {
|
|
6141
6143
|
id,
|
|
6142
6144
|
delta,
|
|
6145
|
+
...(observedAt != null && { observed_at: observedAt }),
|
|
6143
6146
|
};
|
|
6144
6147
|
const handler = this.handlerRegistry?.getHandler(
|
|
6145
6148
|
GraphEvents.ON_RUN_STEP_DELTA
|
package/src/llm/bedrock/index.ts
CHANGED
|
@@ -270,8 +270,10 @@ export class CustomChatBedrockConverse extends ChatBedrockConverse {
|
|
|
270
270
|
options: this['ParsedCallOptions'] & CustomChatBedrockConverseCallOptions,
|
|
271
271
|
runManager?: CallbackManagerForLLMRun
|
|
272
272
|
): AsyncGenerator<ChatGenerationChunk> {
|
|
273
|
-
const { converseMessages, converseSystem } =
|
|
274
|
-
|
|
273
|
+
const { converseMessages, converseSystem } = convertToConverseMessages(
|
|
274
|
+
messages,
|
|
275
|
+
{ model: this.model }
|
|
276
|
+
);
|
|
275
277
|
const params = this.invocationParams(options);
|
|
276
278
|
|
|
277
279
|
let { streamUsage } = this;
|
|
@@ -29,8 +29,8 @@ import type {
|
|
|
29
29
|
MessageContentReasoningBlock,
|
|
30
30
|
} from '../types';
|
|
31
31
|
import { serializeStructuredValueBounded } from '@/utils/toolContent';
|
|
32
|
-
import { HARD_MAX_TOOL_RESULT_CHARS } from '@/utils/truncation';
|
|
33
32
|
import { isReasoningContentBlock } from '@/messages/reasoningTypes';
|
|
33
|
+
import { HARD_MAX_TOOL_RESULT_CHARS } from '@/utils/truncation';
|
|
34
34
|
|
|
35
35
|
/**
|
|
36
36
|
* Reasoning blocks from other providers, relative to Bedrock. Bedrock's native
|
|
@@ -714,13 +714,16 @@ function coerceBedrockToolUseInput(input: unknown): Record<string, unknown> {
|
|
|
714
714
|
: {};
|
|
715
715
|
}
|
|
716
716
|
|
|
717
|
-
function convertAIMessageToConverseMessage(
|
|
717
|
+
function convertAIMessageToConverseMessage(
|
|
718
|
+
msg: BaseMessage,
|
|
719
|
+
replayReasoning = true
|
|
720
|
+
): BedrockMessage {
|
|
718
721
|
// Check for v1 format from other providers (PR #9766 fix)
|
|
719
722
|
const responseMetadata = msg.response_metadata as
|
|
720
723
|
| { output_version?: string }
|
|
721
724
|
| undefined;
|
|
722
725
|
if (responseMetadata?.output_version === 'v1') {
|
|
723
|
-
return convertFromV1ToChatBedrockConverseMessage(msg);
|
|
726
|
+
return convertFromV1ToChatBedrockConverseMessage(msg, replayReasoning);
|
|
724
727
|
}
|
|
725
728
|
|
|
726
729
|
const assistantMsg: BedrockMessage = {
|
|
@@ -733,9 +736,7 @@ function convertAIMessageToConverseMessage(msg: BaseMessage): BedrockMessage {
|
|
|
733
736
|
} else if (Array.isArray(msg.content)) {
|
|
734
737
|
const parsedToolCallIds = new Set(
|
|
735
738
|
isAIMessage(msg)
|
|
736
|
-
? (msg.tool_calls ?? []).flatMap((
|
|
737
|
-
toolCall.id != null ? [toolCall.id] : []
|
|
738
|
-
)
|
|
739
|
+
? (msg.tool_calls ?? []).flatMap(({ id }) => id ?? [])
|
|
739
740
|
: []
|
|
740
741
|
);
|
|
741
742
|
const concatenatedBlocks = concatenateLangchainReasoningBlocks(
|
|
@@ -775,10 +776,14 @@ function convertAIMessageToConverseMessage(msg: BaseMessage): BedrockMessage {
|
|
|
775
776
|
} else if (block.type === 'reasoning_content') {
|
|
776
777
|
const reasoningBlock = block as MessageContentReasoningBlock;
|
|
777
778
|
// Bedrock Converse rejects reasoningContent whose reasoningText.text is
|
|
778
|
-
// null/empty (a signature-only block that never merged with its text)
|
|
779
|
-
//
|
|
780
|
-
//
|
|
781
|
-
|
|
779
|
+
// null/empty (a signature-only block that never merged with its text),
|
|
780
|
+
// and OpenAI models reject reasoningContent outright. Drop
|
|
781
|
+
// it rather than emit an invalid request; the empty-turn placeholder
|
|
782
|
+
// below covers a turn left with no content.
|
|
783
|
+
if (
|
|
784
|
+
!replayReasoning ||
|
|
785
|
+
!isSerializableBedrockReasoningBlock(reasoningBlock)
|
|
786
|
+
) {
|
|
782
787
|
return;
|
|
783
788
|
}
|
|
784
789
|
contentBlocks.push({
|
|
@@ -856,7 +861,8 @@ function convertAIMessageToConverseMessage(msg: BaseMessage): BedrockMessage {
|
|
|
856
861
|
* (Implements PR #9766 fix for output_version v1 detection)
|
|
857
862
|
*/
|
|
858
863
|
function convertFromV1ToChatBedrockConverseMessage(
|
|
859
|
-
msg: BaseMessage
|
|
864
|
+
msg: BaseMessage,
|
|
865
|
+
replayReasoning = true
|
|
860
866
|
): BedrockMessage {
|
|
861
867
|
const contentBlocks: BedrockContentBlock[] = [];
|
|
862
868
|
const assistantMsg: BedrockMessage = {
|
|
@@ -898,7 +904,11 @@ function convertFromV1ToChatBedrockConverseMessage(
|
|
|
898
904
|
/** Bedrock Converse rejects `reasoningText` with a null/empty `text`
|
|
899
905
|
* (`Member must not be null`), e.g. when the producing model omitted
|
|
900
906
|
* reasoning text (`thinking.display: "omitted"`) — drop rather than send. */
|
|
901
|
-
if (
|
|
907
|
+
if (
|
|
908
|
+
!replayReasoning ||
|
|
909
|
+
reasoning.reasoning == null ||
|
|
910
|
+
reasoning.reasoning === ''
|
|
911
|
+
) {
|
|
902
912
|
droppedUnserializableContent = true;
|
|
903
913
|
continue;
|
|
904
914
|
}
|
|
@@ -909,7 +919,10 @@ function convertFromV1ToChatBedrockConverseMessage(
|
|
|
909
919
|
} as BedrockContentBlock);
|
|
910
920
|
} else if (block.type === 'reasoning_content') {
|
|
911
921
|
const reasoningBlock = block as MessageContentReasoningBlock;
|
|
912
|
-
if (
|
|
922
|
+
if (
|
|
923
|
+
!replayReasoning ||
|
|
924
|
+
!isSerializableBedrockReasoningBlock(reasoningBlock)
|
|
925
|
+
) {
|
|
913
926
|
droppedUnserializableContent = true;
|
|
914
927
|
continue;
|
|
915
928
|
}
|
|
@@ -1118,13 +1131,47 @@ function convertToolMessageToConverseMessage(msg: BaseMessage): BedrockMessage {
|
|
|
1118
1131
|
};
|
|
1119
1132
|
}
|
|
1120
1133
|
|
|
1134
|
+
/** Options for {@link convertToConverseMessages}. */
|
|
1135
|
+
export interface ConvertToConverseMessagesOptions {
|
|
1136
|
+
/** The model the request is for, which decides whether prior reasoning is replayed. */
|
|
1137
|
+
model?: string;
|
|
1138
|
+
}
|
|
1139
|
+
|
|
1140
|
+
/**
|
|
1141
|
+
* OpenAI Bedrock models reject prior `reasoningContent`, including on Claude-to-GPT handoffs.
|
|
1142
|
+
* Only suppress replay for identified OpenAI targets; other model families retain the existing
|
|
1143
|
+
* behavior because their Bedrock reasoning-replay requirements have not been verified here.
|
|
1144
|
+
* Missing model IDs and opaque resource ARNs also retain the existing behavior.
|
|
1145
|
+
*/
|
|
1146
|
+
export function replaysBedrockReasoning(model?: string): boolean {
|
|
1147
|
+
if (model == null || model === '') {
|
|
1148
|
+
return true;
|
|
1149
|
+
}
|
|
1150
|
+
let id = model.toLowerCase();
|
|
1151
|
+
if (id.startsWith('arn:')) {
|
|
1152
|
+
const modelId =
|
|
1153
|
+
/^arn:[^:]+:bedrock:[^:]*:[^:]*:(?:foundation-model|inference-profile)\/(.+)$/.exec(
|
|
1154
|
+
id
|
|
1155
|
+
)?.[1];
|
|
1156
|
+
if (modelId == null) {
|
|
1157
|
+
return true;
|
|
1158
|
+
}
|
|
1159
|
+
id = modelId;
|
|
1160
|
+
}
|
|
1161
|
+
return !/(?:^|\.)openai\./.test(id);
|
|
1162
|
+
}
|
|
1163
|
+
|
|
1121
1164
|
/**
|
|
1122
1165
|
* Convert LangChain messages to Bedrock Converse messages.
|
|
1123
1166
|
*/
|
|
1124
|
-
export function convertToConverseMessages(
|
|
1167
|
+
export function convertToConverseMessages(
|
|
1168
|
+
messages: BaseMessage[],
|
|
1169
|
+
options: ConvertToConverseMessagesOptions = {}
|
|
1170
|
+
): {
|
|
1125
1171
|
converseMessages: BedrockMessage[];
|
|
1126
1172
|
converseSystem: BedrockSystemContentBlock[];
|
|
1127
1173
|
} {
|
|
1174
|
+
const replayReasoning = replaysBedrockReasoning(options.model);
|
|
1128
1175
|
const converseSystem = messages
|
|
1129
1176
|
.filter((msg) => msg._getType() === 'system')
|
|
1130
1177
|
.flatMap((msg) => convertSystemMessageToConverseMessage(msg));
|
|
@@ -1133,7 +1180,7 @@ export function convertToConverseMessages(messages: BaseMessage[]): {
|
|
|
1133
1180
|
.filter((msg) => msg._getType() !== 'system')
|
|
1134
1181
|
.map((msg) => {
|
|
1135
1182
|
if (msg._getType() === 'ai') {
|
|
1136
|
-
return convertAIMessageToConverseMessage(msg);
|
|
1183
|
+
return convertAIMessageToConverseMessage(msg, replayReasoning);
|
|
1137
1184
|
} else if (msg._getType() === 'human' || msg._getType() === 'generic') {
|
|
1138
1185
|
return convertHumanMessageToConverseMessage(msg);
|
|
1139
1186
|
} else if (msg._getType() === 'tool') {
|
package/src/run.ts
CHANGED
|
@@ -37,13 +37,6 @@ import {
|
|
|
37
37
|
DEFAULT_MAX_STOP_CONTINUATIONS,
|
|
38
38
|
DEFAULT_RECURSION_LIMIT,
|
|
39
39
|
} from '@/common';
|
|
40
|
-
import {
|
|
41
|
-
ACTIVITY_PHASE_LABEL_PROMPT,
|
|
42
|
-
ACTIVITY_LABEL_PROMPT,
|
|
43
|
-
buildActivityLabelPrompt,
|
|
44
|
-
buildActivityPhaseLabelPrompt,
|
|
45
|
-
normalizeActivityPhaseLabel,
|
|
46
|
-
} from '@/prompts/activityLabel';
|
|
47
40
|
import {
|
|
48
41
|
createLangfuseTraceMetadata,
|
|
49
42
|
createLangfuseHandler,
|
|
@@ -53,6 +46,13 @@ import {
|
|
|
53
46
|
isLangfuseCallbackHandler,
|
|
54
47
|
withLangfuseAttributes,
|
|
55
48
|
} from '@/langfuse';
|
|
49
|
+
import {
|
|
50
|
+
ACTIVITY_PHASE_LABEL_PROMPT,
|
|
51
|
+
ACTIVITY_LABEL_PROMPT,
|
|
52
|
+
buildActivityLabelPrompt,
|
|
53
|
+
buildActivityPhaseLabelPrompt,
|
|
54
|
+
normalizeActivityPhaseLabel,
|
|
55
|
+
} from '@/prompts/activityLabel';
|
|
56
56
|
import {
|
|
57
57
|
requireValidSubagentResumeManifest,
|
|
58
58
|
SUBAGENT_RESUME_ATTEMPT_CONFIG_KEY,
|
|
@@ -204,6 +204,7 @@ const CUSTOM_GRAPH_EVENTS = new Set<string>([
|
|
|
204
204
|
GraphEvents.ON_RUN_STEP_DELTA,
|
|
205
205
|
GraphEvents.ON_RUN_STEP_COMPLETED,
|
|
206
206
|
GraphEvents.ON_RUN_STEP_CLOSED,
|
|
207
|
+
GraphEvents.ON_TOOL_CALLS_DISPATCHED,
|
|
207
208
|
GraphEvents.ON_MESSAGE_DELTA,
|
|
208
209
|
GraphEvents.ON_REASONING_DELTA,
|
|
209
210
|
GraphEvents.ON_TOOL_EXECUTE,
|
|
@@ -1095,6 +1096,7 @@ export class Run<_T extends t.BaseGraphState> {
|
|
|
1095
1096
|
| t.RunStep
|
|
1096
1097
|
| t.RunStepDeltaEvent
|
|
1097
1098
|
| t.RunStepClosedEvent
|
|
1099
|
+
| t.ToolCallsDispatchedEvent
|
|
1098
1100
|
| t.MessageDeltaEvent
|
|
1099
1101
|
| t.ReasoningDeltaEvent
|
|
1100
1102
|
| { result: t.ToolEndEvent },
|
package/src/stream.ts
CHANGED
|
@@ -55,13 +55,13 @@ import {
|
|
|
55
55
|
calculateMaxToolResultChars,
|
|
56
56
|
truncateToolResultContent,
|
|
57
57
|
} from '@/utils/truncation';
|
|
58
|
+
import { createToolCallsDispatchedEvent, safeDispatchCustomEvent } from '@/utils/events';
|
|
58
59
|
import { resolveToolOutcome, outcomeFieldsFromResult } from '@/tools/intentArg';
|
|
59
|
-
import { formatToolErrorContent } from '@/tools/toolErrorContent';
|
|
60
60
|
import { snapshotValidatedModelChunk } from '@/graphs/acceptedModelResponse';
|
|
61
61
|
import { TOOL_OUTPUT_REF_PATTERN } from '@/tools/toolOutputReferences';
|
|
62
|
+
import { formatToolErrorContent } from '@/tools/toolErrorContent';
|
|
62
63
|
import { PreparedSubagentError } from '@/tools/preparedSubagents';
|
|
63
64
|
import { isReasoningContentBlock } from '@/messages/core';
|
|
64
|
-
import { safeDispatchCustomEvent } from '@/utils/events';
|
|
65
65
|
import { composeAbortSignals } from '@/utils/misc';
|
|
66
66
|
import { isGoogleLike } from '@/utils/llm';
|
|
67
67
|
import { getMessageId } from '@/messages';
|
|
@@ -871,6 +871,13 @@ function startEagerToolExecutions(args: {
|
|
|
871
871
|
reject,
|
|
872
872
|
};
|
|
873
873
|
|
|
874
|
+
if (graph.config != null) {
|
|
875
|
+
void safeDispatchCustomEvent(
|
|
876
|
+
GraphEvents.ON_TOOL_CALLS_DISPATCHED,
|
|
877
|
+
createToolCallsDispatchedEvent(graph.config, batchRequest.toolCalls),
|
|
878
|
+
graph.config
|
|
879
|
+
);
|
|
880
|
+
}
|
|
874
881
|
void safeDispatchCustomEvent(
|
|
875
882
|
GraphEvents.ON_TOOL_EXECUTE,
|
|
876
883
|
batchRequest,
|
|
@@ -980,7 +987,7 @@ async function dispatchEagerToolCompletions(args: {
|
|
|
980
987
|
progress: 1,
|
|
981
988
|
...(outcome != null && { outcome }),
|
|
982
989
|
} as t.ProcessedToolCall,
|
|
983
|
-
completed_at: Date.now(),
|
|
990
|
+
completed_at: result.received_at ?? Date.now(),
|
|
984
991
|
},
|
|
985
992
|
},
|
|
986
993
|
graph.config
|
|
@@ -1701,6 +1708,7 @@ export class ChatModelStreamHandler implements t.EventHandler {
|
|
|
1701
1708
|
// Callback delivery can beat the producer's iterator. Validate before
|
|
1702
1709
|
// accounting, run steps, or eager dispatch reads raw tool descriptors.
|
|
1703
1710
|
chunk = snapshotValidatedModelChunk(chunk as AIMessageChunk);
|
|
1711
|
+
const observedAt = Date.now();
|
|
1704
1712
|
|
|
1705
1713
|
/**
|
|
1706
1714
|
* Enforced before every content-specific early return below
|
|
@@ -1923,6 +1931,7 @@ export class ChatModelStreamHandler implements t.EventHandler {
|
|
|
1923
1931
|
stepKey,
|
|
1924
1932
|
toolCallChunks: chunk.tool_call_chunks,
|
|
1925
1933
|
metadata,
|
|
1934
|
+
observedAt,
|
|
1926
1935
|
});
|
|
1927
1936
|
if (canStreamEager) {
|
|
1928
1937
|
if (runScopeInvalidated()) {
|
package/src/tools/ToolNode.ts
CHANGED
|
@@ -170,7 +170,7 @@ function stripHostExecutionConfig(
|
|
|
170
170
|
}
|
|
171
171
|
import { convertInjectedMessages } from '@/messages/injected';
|
|
172
172
|
import { stampSyntheticProviderMessage } from '@/messages/provenance';
|
|
173
|
-
import { safeDispatchCustomEvent } from '@/utils/events';
|
|
173
|
+
import { createToolCallsDispatchedEvent, safeDispatchCustomEvent } from '@/utils/events';
|
|
174
174
|
import { RunnableCallable, composeAbortSignals } from '@/utils';
|
|
175
175
|
import {
|
|
176
176
|
executeHooks,
|
|
@@ -1672,6 +1672,15 @@ export class ToolNode<T = any> extends RunnableCallable<T, T> {
|
|
|
1672
1672
|
};
|
|
1673
1673
|
this.throwIfBreakerTripped(config);
|
|
1674
1674
|
config.signal?.throwIfAborted();
|
|
1675
|
+
if (call.id != null && call.id !== '') {
|
|
1676
|
+
void safeDispatchCustomEvent(
|
|
1677
|
+
GraphEvents.ON_TOOL_CALLS_DISPATCHED,
|
|
1678
|
+
createToolCallsDispatchedEvent(config, [
|
|
1679
|
+
{ id: call.id, name: call.name, stepId: this.toolCallStepIds?.get(call.id) },
|
|
1680
|
+
]),
|
|
1681
|
+
config
|
|
1682
|
+
);
|
|
1683
|
+
}
|
|
1675
1684
|
return tool.invoke(invokeParams, runtime);
|
|
1676
1685
|
}
|
|
1677
1686
|
|
|
@@ -4334,7 +4343,9 @@ export class ToolNode<T = any> extends RunnableCallable<T, T> {
|
|
|
4334
4343
|
const dispatchRequestById = new Map(
|
|
4335
4344
|
dispatchRequests.map((request) => [request.id, request])
|
|
4336
4345
|
);
|
|
4346
|
+
const receivedAtById = new Map<string, number>();
|
|
4337
4347
|
const onResult = (result: t.ToolExecuteResult): void => {
|
|
4348
|
+
const receivedAt = Date.now();
|
|
4338
4349
|
/** Runtime-honest widening: hosts may omit the id despite the
|
|
4339
4350
|
* field type. */
|
|
4340
4351
|
const resultToolCallId = result.toolCallId as string | undefined;
|
|
@@ -4349,8 +4360,9 @@ export class ToolNode<T = any> extends RunnableCallable<T, T> {
|
|
|
4349
4360
|
return;
|
|
4350
4361
|
}
|
|
4351
4362
|
earlyCompletionDispatchedIds.add(result.toolCallId);
|
|
4363
|
+
receivedAtById.set(result.toolCallId, receivedAt);
|
|
4352
4364
|
earlyCompletionDispatches.push(
|
|
4353
|
-
this.dispatchEarlyToolCompletion(result, request, config).then(
|
|
4365
|
+
this.dispatchEarlyToolCompletion({ ...result, received_at: receivedAt }, request, config).then(
|
|
4354
4366
|
(dispatched) => {
|
|
4355
4367
|
if (!dispatched) {
|
|
4356
4368
|
earlyCompletionDispatchedIds.delete(result.toolCallId);
|
|
@@ -4402,6 +4414,12 @@ export class ToolNode<T = any> extends RunnableCallable<T, T> {
|
|
|
4402
4414
|
| undefined,
|
|
4403
4415
|
signal: config.signal,
|
|
4404
4416
|
resolve: (results): void => {
|
|
4417
|
+
const receivedAt = Date.now();
|
|
4418
|
+
for (const result of results) {
|
|
4419
|
+
if (dispatchRequestById.has(result.toolCallId)) {
|
|
4420
|
+
receivedAtById.set(result.toolCallId, result.received_at ?? receivedAt);
|
|
4421
|
+
}
|
|
4422
|
+
}
|
|
4405
4423
|
resultSettled = true;
|
|
4406
4424
|
settledResults = results;
|
|
4407
4425
|
maybeResolve();
|
|
@@ -4410,6 +4428,11 @@ export class ToolNode<T = any> extends RunnableCallable<T, T> {
|
|
|
4410
4428
|
...(canEmitEarlyCompletions && { onResult }),
|
|
4411
4429
|
};
|
|
4412
4430
|
|
|
4431
|
+
void safeDispatchCustomEvent(
|
|
4432
|
+
GraphEvents.ON_TOOL_CALLS_DISPATCHED,
|
|
4433
|
+
createToolCallsDispatchedEvent(config, dispatchRequests),
|
|
4434
|
+
config
|
|
4435
|
+
);
|
|
4413
4436
|
void safeDispatchCustomEvent(
|
|
4414
4437
|
GraphEvents.ON_TOOL_EXECUTE,
|
|
4415
4438
|
batchRequest,
|
|
@@ -4695,7 +4718,8 @@ export class ToolNode<T = any> extends RunnableCallable<T, T> {
|
|
|
4695
4718
|
request?.turn,
|
|
4696
4719
|
resolveToolOutcome(request?.args, outcomeFieldsFromResult(result), {
|
|
4697
4720
|
isError: result.status === 'error',
|
|
4698
|
-
})
|
|
4721
|
+
}),
|
|
4722
|
+
receivedAtById.get(result.toolCallId) ?? result.received_at
|
|
4699
4723
|
);
|
|
4700
4724
|
}
|
|
4701
4725
|
|
|
@@ -4997,7 +5021,8 @@ export class ToolNode<T = any> extends RunnableCallable<T, T> {
|
|
|
4997
5021
|
output: string,
|
|
4998
5022
|
config: RunnableConfig,
|
|
4999
5023
|
turn?: number,
|
|
5000
|
-
outcome?: string
|
|
5024
|
+
outcome?: string,
|
|
5025
|
+
receivedAt?: number
|
|
5001
5026
|
): Promise<boolean> {
|
|
5002
5027
|
const stepId = this.toolCallStepIds?.get(toolCallId) ?? '';
|
|
5003
5028
|
if (!stepId) {
|
|
@@ -5024,7 +5049,7 @@ export class ToolNode<T = any> extends RunnableCallable<T, T> {
|
|
|
5024
5049
|
progress: 1,
|
|
5025
5050
|
...(outcome != null && { outcome }),
|
|
5026
5051
|
} as t.ProcessedToolCall,
|
|
5027
|
-
completed_at: Date.now(),
|
|
5052
|
+
completed_at: receivedAt ?? Date.now(),
|
|
5028
5053
|
},
|
|
5029
5054
|
},
|
|
5030
5055
|
config
|
|
@@ -5064,7 +5089,8 @@ export class ToolNode<T = any> extends RunnableCallable<T, T> {
|
|
|
5064
5089
|
request.turn,
|
|
5065
5090
|
resolveToolOutcome(request.args, outcomeFieldsFromResult(result), {
|
|
5066
5091
|
isError: result.status === 'error',
|
|
5067
|
-
})
|
|
5092
|
+
}),
|
|
5093
|
+
result.received_at
|
|
5068
5094
|
);
|
|
5069
5095
|
}
|
|
5070
5096
|
|
package/src/tools/handlers.ts
CHANGED
|
@@ -26,11 +26,13 @@ export async function handleToolCallChunks({
|
|
|
26
26
|
stepKey,
|
|
27
27
|
toolCallChunks,
|
|
28
28
|
metadata,
|
|
29
|
+
observedAt = Date.now(),
|
|
29
30
|
}: {
|
|
30
31
|
graph: StandardGraph | MultiAgentGraph;
|
|
31
32
|
stepKey: string;
|
|
32
33
|
toolCallChunks: ToolCallChunk[];
|
|
33
34
|
metadata?: Record<string, unknown>;
|
|
35
|
+
observedAt?: number;
|
|
34
36
|
}): Promise<void> {
|
|
35
37
|
let prevStepId: string;
|
|
36
38
|
let prevRunStep: t.RunStep | undefined;
|
|
@@ -124,7 +126,8 @@ export async function handleToolCallChunks({
|
|
|
124
126
|
type: StepTypes.TOOL_CALLS,
|
|
125
127
|
tool_calls: toolCallChunks,
|
|
126
128
|
},
|
|
127
|
-
metadata
|
|
129
|
+
metadata,
|
|
130
|
+
observedAt
|
|
128
131
|
);
|
|
129
132
|
}
|
|
130
133
|
|