@grafana/sigil-sdk-js 0.0.1
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/LICENSE +3 -0
- package/README.md +367 -0
- package/dist/client.d.ts +102 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +1502 -0
- package/dist/client.js.map +1 -0
- package/dist/config.d.ts +9 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +190 -0
- package/dist/config.js.map +1 -0
- package/dist/content_capture.d.ts +35 -0
- package/dist/content_capture.d.ts.map +1 -0
- package/dist/content_capture.js +123 -0
- package/dist/content_capture.js.map +1 -0
- package/dist/context.d.ts +11 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +53 -0
- package/dist/context.js.map +1 -0
- package/dist/exporters/default.d.ts +3 -0
- package/dist/exporters/default.d.ts.map +1 -0
- package/dist/exporters/default.js +34 -0
- package/dist/exporters/default.js.map +1 -0
- package/dist/exporters/grpc.d.ts +14 -0
- package/dist/exporters/grpc.d.ts.map +1 -0
- package/dist/exporters/grpc.js +369 -0
- package/dist/exporters/grpc.js.map +1 -0
- package/dist/exporters/http.d.ts +8 -0
- package/dist/exporters/http.d.ts.map +1 -0
- package/dist/exporters/http.js +258 -0
- package/dist/exporters/http.js.map +1 -0
- package/dist/frameworks/google-adk/index.d.ts +136 -0
- package/dist/frameworks/google-adk/index.d.ts.map +1 -0
- package/dist/frameworks/google-adk/index.js +509 -0
- package/dist/frameworks/google-adk/index.js.map +1 -0
- package/dist/frameworks/langchain/index.d.ts +29 -0
- package/dist/frameworks/langchain/index.d.ts.map +1 -0
- package/dist/frameworks/langchain/index.js +70 -0
- package/dist/frameworks/langchain/index.js.map +1 -0
- package/dist/frameworks/langgraph/index.d.ts +29 -0
- package/dist/frameworks/langgraph/index.d.ts.map +1 -0
- package/dist/frameworks/langgraph/index.js +70 -0
- package/dist/frameworks/langgraph/index.js.map +1 -0
- package/dist/frameworks/llamaindex/index.d.ts +43 -0
- package/dist/frameworks/llamaindex/index.d.ts.map +1 -0
- package/dist/frameworks/llamaindex/index.js +493 -0
- package/dist/frameworks/llamaindex/index.js.map +1 -0
- package/dist/frameworks/openai-agents/index.d.ts +33 -0
- package/dist/frameworks/openai-agents/index.d.ts.map +1 -0
- package/dist/frameworks/openai-agents/index.js +531 -0
- package/dist/frameworks/openai-agents/index.js.map +1 -0
- package/dist/frameworks/shared.d.ts +57 -0
- package/dist/frameworks/shared.d.ts.map +1 -0
- package/dist/frameworks/shared.js +1032 -0
- package/dist/frameworks/shared.js.map +1 -0
- package/dist/frameworks/vercel-ai-sdk/hooks.d.ts +18 -0
- package/dist/frameworks/vercel-ai-sdk/hooks.d.ts.map +1 -0
- package/dist/frameworks/vercel-ai-sdk/hooks.js +672 -0
- package/dist/frameworks/vercel-ai-sdk/hooks.js.map +1 -0
- package/dist/frameworks/vercel-ai-sdk/index.d.ts +8 -0
- package/dist/frameworks/vercel-ai-sdk/index.d.ts.map +1 -0
- package/dist/frameworks/vercel-ai-sdk/index.js +7 -0
- package/dist/frameworks/vercel-ai-sdk/index.js.map +1 -0
- package/dist/frameworks/vercel-ai-sdk/mapping.d.ts +49 -0
- package/dist/frameworks/vercel-ai-sdk/mapping.d.ts.map +1 -0
- package/dist/frameworks/vercel-ai-sdk/mapping.js +660 -0
- package/dist/frameworks/vercel-ai-sdk/mapping.js.map +1 -0
- package/dist/frameworks/vercel-ai-sdk/types.d.ts +126 -0
- package/dist/frameworks/vercel-ai-sdk/types.d.ts.map +1 -0
- package/dist/frameworks/vercel-ai-sdk/types.js +2 -0
- package/dist/frameworks/vercel-ai-sdk/types.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/providers/anthropic.d.ts +35 -0
- package/dist/providers/anthropic.d.ts.map +1 -0
- package/dist/providers/anthropic.js +581 -0
- package/dist/providers/anthropic.js.map +1 -0
- package/dist/providers/gemini.d.ts +42 -0
- package/dist/providers/gemini.d.ts.map +1 -0
- package/dist/providers/gemini.js +650 -0
- package/dist/providers/gemini.js.map +1 -0
- package/dist/providers/openai.d.ts +67 -0
- package/dist/providers/openai.d.ts.map +1 -0
- package/dist/providers/openai.js +1007 -0
- package/dist/providers/openai.js.map +1 -0
- package/dist/types.d.ts +461 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/utils.d.ts +25 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +331 -0
- package/dist/utils.js.map +1 -0
- package/docs/frameworks/google-adk.md +84 -0
- package/docs/frameworks/langchain.md +102 -0
- package/docs/frameworks/langgraph.md +137 -0
- package/docs/frameworks/llamaindex.md +82 -0
- package/docs/frameworks/openai-agents.md +88 -0
- package/docs/frameworks/vercel-ai-sdk.md +124 -0
- package/docs/index.md +22 -0
- package/docs/providers/anthropic.md +69 -0
- package/docs/providers/gemini.md +86 -0
- package/docs/providers/openai.md +151 -0
- package/package.json +80 -0
- package/proto/opentelemetry/proto/collector/trace/v1/trace_service.proto +77 -0
- package/proto/opentelemetry/proto/common/v1/common.proto +115 -0
- package/proto/opentelemetry/proto/resource/v1/resource.proto +44 -0
- package/proto/opentelemetry/proto/trace/v1/trace.proto +357 -0
- package/proto/sigil/v1/generation_ingest.proto +145 -0
|
@@ -0,0 +1,672 @@
|
|
|
1
|
+
import { buildFrameworkMetadata, buildFrameworkTags, extractStepNumber, isTextChunk, mapInputMessages, mapModelFromStepStart, mapResponseFromStepFinish, mapStepOutput, mapUsageFromStepFinish, parseToolCallFinish, parseToolCallStart, resolveConversationId, shouldTreatStepAsError, } from './mapping.js';
|
|
2
|
+
export class SigilVercelAiSdkInstrumentation {
|
|
3
|
+
client;
|
|
4
|
+
agentName;
|
|
5
|
+
agentVersion;
|
|
6
|
+
captureInputs;
|
|
7
|
+
captureOutputs;
|
|
8
|
+
extraTags;
|
|
9
|
+
extraMetadata;
|
|
10
|
+
resolveConversationIdFn;
|
|
11
|
+
callSequence = 0;
|
|
12
|
+
constructor(client, options = {}) {
|
|
13
|
+
this.client = client;
|
|
14
|
+
this.agentName = normalizeOptionalString(options.agentName);
|
|
15
|
+
this.agentVersion = normalizeOptionalString(options.agentVersion);
|
|
16
|
+
this.captureInputs = options.captureInputs ?? true;
|
|
17
|
+
this.captureOutputs = options.captureOutputs ?? true;
|
|
18
|
+
this.extraTags = { ...(options.extraTags ?? {}) };
|
|
19
|
+
this.extraMetadata = { ...(options.extraMetadata ?? {}) };
|
|
20
|
+
this.resolveConversationIdFn = options.resolveConversationId;
|
|
21
|
+
}
|
|
22
|
+
generateTextHooks(callOptions = {}) {
|
|
23
|
+
return this.createHooks('SYNC', 'generateText', callOptions, false);
|
|
24
|
+
}
|
|
25
|
+
streamTextHooks(callOptions = {}) {
|
|
26
|
+
return this.createHooks('STREAM', 'streamText', callOptions, true);
|
|
27
|
+
}
|
|
28
|
+
createHooks(mode, operationName, callOptions, includeStreamHandlers) {
|
|
29
|
+
const callID = `call-${++this.callSequence}`;
|
|
30
|
+
const callStartedAt = new Date();
|
|
31
|
+
const state = {
|
|
32
|
+
stepStates: new Map(),
|
|
33
|
+
toolStates: new Map(),
|
|
34
|
+
completedToolCallIds: new Set(),
|
|
35
|
+
nextSyntheticStepNumber: 0,
|
|
36
|
+
};
|
|
37
|
+
const explicitConversationId = normalizeOptionalString(callOptions.conversationId);
|
|
38
|
+
const callAgentName = normalizeOptionalString(callOptions.agentName) ?? this.agentName;
|
|
39
|
+
const mergedCallMetadata = {
|
|
40
|
+
...this.extraMetadata,
|
|
41
|
+
...(callOptions.extraMetadata ?? {}),
|
|
42
|
+
};
|
|
43
|
+
const tags = buildFrameworkTags(this.extraTags);
|
|
44
|
+
let streamObservedStartAt;
|
|
45
|
+
let hasCreatedStreamStepState = false;
|
|
46
|
+
const noteStreamObservedStartAt = (timestamp) => {
|
|
47
|
+
if (mode !== 'STREAM') {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
if (streamObservedStartAt === undefined || timestamp.getTime() < streamObservedStartAt.getTime()) {
|
|
51
|
+
streamObservedStartAt = timestamp;
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
const createGenerationRecorder = (params) => {
|
|
55
|
+
const model = mapModelFromStepStart(params.stepStartEvent);
|
|
56
|
+
return mode === 'STREAM'
|
|
57
|
+
? this.client.startStreamingGeneration({
|
|
58
|
+
conversationId: params.conversationId,
|
|
59
|
+
agentName: callAgentName,
|
|
60
|
+
agentVersion: this.agentVersion,
|
|
61
|
+
mode,
|
|
62
|
+
operationName,
|
|
63
|
+
model: {
|
|
64
|
+
provider: model.provider,
|
|
65
|
+
name: model.modelName,
|
|
66
|
+
},
|
|
67
|
+
tags,
|
|
68
|
+
metadata: buildFrameworkMetadata(mergedCallMetadata, undefined, undefined),
|
|
69
|
+
startedAt: params.startedAt,
|
|
70
|
+
})
|
|
71
|
+
: this.client.startGeneration({
|
|
72
|
+
conversationId: params.conversationId,
|
|
73
|
+
agentName: callAgentName,
|
|
74
|
+
agentVersion: this.agentVersion,
|
|
75
|
+
mode,
|
|
76
|
+
operationName,
|
|
77
|
+
model: {
|
|
78
|
+
provider: model.provider,
|
|
79
|
+
name: model.modelName,
|
|
80
|
+
},
|
|
81
|
+
tags,
|
|
82
|
+
metadata: buildFrameworkMetadata(mergedCallMetadata, undefined, undefined),
|
|
83
|
+
startedAt: params.startedAt,
|
|
84
|
+
});
|
|
85
|
+
};
|
|
86
|
+
const ensureStepRecorder = (stepState, conversationId) => {
|
|
87
|
+
if (stepState.recorder !== undefined) {
|
|
88
|
+
return stepState.recorder;
|
|
89
|
+
}
|
|
90
|
+
const recorder = createGenerationRecorder({
|
|
91
|
+
stepStartEvent: stepState.stepStartEvent,
|
|
92
|
+
conversationId,
|
|
93
|
+
startedAt: stepState.startedAt,
|
|
94
|
+
});
|
|
95
|
+
stepState.recorder = recorder;
|
|
96
|
+
return recorder;
|
|
97
|
+
};
|
|
98
|
+
const createStepState = (params) => {
|
|
99
|
+
const conversation = resolveConversationId({
|
|
100
|
+
explicitConversationId,
|
|
101
|
+
resolver: this.resolveConversationIdFn,
|
|
102
|
+
stepStartEvent: params.stepStartEvent,
|
|
103
|
+
fallbackSeed: `${callID}:step-${params.stepNumber}`,
|
|
104
|
+
});
|
|
105
|
+
const stepState = {
|
|
106
|
+
recorder: mode === 'STREAM' && hasStepStartModelRef(params.stepStartEvent)
|
|
107
|
+
? createGenerationRecorder({
|
|
108
|
+
stepStartEvent: params.stepStartEvent,
|
|
109
|
+
conversationId: conversation.conversationId,
|
|
110
|
+
startedAt: params.startedAt,
|
|
111
|
+
})
|
|
112
|
+
: undefined,
|
|
113
|
+
startedAt: params.startedAt,
|
|
114
|
+
inputMessages: params.inputMessages,
|
|
115
|
+
conversation,
|
|
116
|
+
fallbackSeed: `${callID}:step-${params.stepNumber}`,
|
|
117
|
+
firstTokenRecorded: false,
|
|
118
|
+
firstTokenAt: undefined,
|
|
119
|
+
stepStartEvent: params.stepStartEvent,
|
|
120
|
+
toolCallIds: new Set(),
|
|
121
|
+
hasToolCalls: false,
|
|
122
|
+
};
|
|
123
|
+
state.stepStates.set(params.stepNumber, stepState);
|
|
124
|
+
if (mode === 'STREAM') {
|
|
125
|
+
hasCreatedStreamStepState = true;
|
|
126
|
+
}
|
|
127
|
+
return stepState;
|
|
128
|
+
};
|
|
129
|
+
const resolveOrCreateStepStateForFinish = (params) => {
|
|
130
|
+
const resolvedStepNumber = resolveStepNumberForEvent(state, params.eventStepNumber);
|
|
131
|
+
if (resolvedStepNumber !== undefined) {
|
|
132
|
+
const resolvedState = state.stepStates.get(resolvedStepNumber);
|
|
133
|
+
if (resolvedState !== undefined) {
|
|
134
|
+
return { stepNumber: resolvedStepNumber, stepState: resolvedState };
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
const syntheticStepNumber = extractStepNumber({ stepNumber: params.eventStepNumber }, state.nextSyntheticStepNumber);
|
|
138
|
+
state.nextSyntheticStepNumber = Math.max(state.nextSyntheticStepNumber + 1, syntheticStepNumber + 1);
|
|
139
|
+
const syntheticStepStartEvent = {
|
|
140
|
+
stepNumber: syntheticStepNumber,
|
|
141
|
+
model: params.responseModel !== undefined ? { modelId: params.responseModel } : undefined,
|
|
142
|
+
};
|
|
143
|
+
const now = new Date();
|
|
144
|
+
const syntheticStartedAt = mode === 'STREAM' ? (hasCreatedStreamStepState ? now : (streamObservedStartAt ?? callStartedAt)) : now;
|
|
145
|
+
const syntheticStepState = createStepState({
|
|
146
|
+
stepNumber: syntheticStepNumber,
|
|
147
|
+
stepStartEvent: syntheticStepStartEvent,
|
|
148
|
+
startedAt: syntheticStartedAt,
|
|
149
|
+
inputMessages: [],
|
|
150
|
+
});
|
|
151
|
+
return { stepNumber: syntheticStepNumber, stepState: syntheticStepState };
|
|
152
|
+
};
|
|
153
|
+
const resolveOrCreateStepStateForObservedEvent = (params) => {
|
|
154
|
+
const resolvedStepNumber = resolveStepNumberForEvent(state, params.eventStepNumber);
|
|
155
|
+
if (resolvedStepNumber !== undefined) {
|
|
156
|
+
const resolvedState = state.stepStates.get(resolvedStepNumber);
|
|
157
|
+
if (resolvedState !== undefined) {
|
|
158
|
+
return { stepNumber: resolvedStepNumber, stepState: resolvedState };
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
const syntheticStepNumber = extractStepNumber({ stepNumber: params.eventStepNumber }, state.nextSyntheticStepNumber);
|
|
162
|
+
state.nextSyntheticStepNumber = Math.max(state.nextSyntheticStepNumber + 1, syntheticStepNumber + 1);
|
|
163
|
+
const syntheticStepStartEvent = {
|
|
164
|
+
stepNumber: syntheticStepNumber,
|
|
165
|
+
};
|
|
166
|
+
const syntheticStepState = createStepState({
|
|
167
|
+
stepNumber: syntheticStepNumber,
|
|
168
|
+
stepStartEvent: syntheticStepStartEvent,
|
|
169
|
+
startedAt: params.observedAt,
|
|
170
|
+
inputMessages: [],
|
|
171
|
+
});
|
|
172
|
+
return { stepNumber: syntheticStepNumber, stepState: syntheticStepState };
|
|
173
|
+
};
|
|
174
|
+
const parseJSONIfPossible = (value) => {
|
|
175
|
+
if (typeof value !== 'string') {
|
|
176
|
+
return undefined;
|
|
177
|
+
}
|
|
178
|
+
const trimmed = value.trim();
|
|
179
|
+
if (trimmed.length === 0) {
|
|
180
|
+
return undefined;
|
|
181
|
+
}
|
|
182
|
+
try {
|
|
183
|
+
return JSON.parse(trimmed);
|
|
184
|
+
}
|
|
185
|
+
catch {
|
|
186
|
+
return trimmed;
|
|
187
|
+
}
|
|
188
|
+
};
|
|
189
|
+
const extractToolPartsFromStepOutput = (output) => {
|
|
190
|
+
const toolCalls = [];
|
|
191
|
+
const toolResults = [];
|
|
192
|
+
if (!Array.isArray(output)) {
|
|
193
|
+
return { toolCalls, toolResults };
|
|
194
|
+
}
|
|
195
|
+
for (const message of output) {
|
|
196
|
+
if (!Array.isArray(message.parts)) {
|
|
197
|
+
continue;
|
|
198
|
+
}
|
|
199
|
+
for (const part of message.parts) {
|
|
200
|
+
if (part.type === 'tool_call') {
|
|
201
|
+
toolCalls.push(part.toolCall);
|
|
202
|
+
continue;
|
|
203
|
+
}
|
|
204
|
+
if (part.type === 'tool_result') {
|
|
205
|
+
toolResults.push(part.toolResult);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
return { toolCalls, toolResults };
|
|
210
|
+
};
|
|
211
|
+
const recordToolExecutionFromStepFinish = (params) => {
|
|
212
|
+
const { toolCalls, toolResults } = extractToolPartsFromStepOutput(params.output);
|
|
213
|
+
if (toolResults.length === 0) {
|
|
214
|
+
return undefined;
|
|
215
|
+
}
|
|
216
|
+
const toolCallsByID = new Map();
|
|
217
|
+
const toolCallsByName = new Map();
|
|
218
|
+
for (const toolCall of toolCalls) {
|
|
219
|
+
if (toolCall.id !== undefined) {
|
|
220
|
+
toolCallsByID.set(toolCall.id, toolCall);
|
|
221
|
+
}
|
|
222
|
+
const existing = toolCallsByName.get(toolCall.name) ?? [];
|
|
223
|
+
existing.push(toolCall);
|
|
224
|
+
toolCallsByName.set(toolCall.name, existing);
|
|
225
|
+
}
|
|
226
|
+
let firstError;
|
|
227
|
+
for (const [index, toolResult] of toolResults.entries()) {
|
|
228
|
+
let toolCallID = toolResult.toolCallId;
|
|
229
|
+
let matchedToolCall = toolCallID !== undefined ? toolCallsByID.get(toolCallID) : undefined;
|
|
230
|
+
if (matchedToolCall === undefined && toolResult.name !== undefined) {
|
|
231
|
+
const matchingByName = toolCallsByName.get(toolResult.name);
|
|
232
|
+
matchedToolCall = matchingByName?.shift();
|
|
233
|
+
}
|
|
234
|
+
if (toolCallID === undefined || toolCallID.length === 0) {
|
|
235
|
+
toolCallID = matchedToolCall?.id ?? `${callID}:step-${params.stepNumber}:tool-${index}`;
|
|
236
|
+
}
|
|
237
|
+
if (state.completedToolCallIds.has(toolCallID)) {
|
|
238
|
+
continue;
|
|
239
|
+
}
|
|
240
|
+
const liveToolState = state.toolStates.get(toolCallID);
|
|
241
|
+
if (liveToolState !== undefined) {
|
|
242
|
+
try {
|
|
243
|
+
const toolResultPayload = {
|
|
244
|
+
completedAt: new Date(),
|
|
245
|
+
};
|
|
246
|
+
if (this.captureInputs) {
|
|
247
|
+
toolResultPayload.arguments = liveToolState.input;
|
|
248
|
+
}
|
|
249
|
+
if (this.captureOutputs) {
|
|
250
|
+
toolResultPayload.result = parseJSONIfPossible(toolResult.contentJSON) ?? toolResult.content;
|
|
251
|
+
}
|
|
252
|
+
if (toolResult.isError) {
|
|
253
|
+
liveToolState.recorder.setCallError(toolResult.content ?? new Error('tool call failed'));
|
|
254
|
+
}
|
|
255
|
+
liveToolState.recorder.setResult(toolResultPayload);
|
|
256
|
+
}
|
|
257
|
+
finally {
|
|
258
|
+
liveToolState.recorder.end();
|
|
259
|
+
}
|
|
260
|
+
const recorderError = liveToolState.recorder.getError();
|
|
261
|
+
if (firstError === undefined && recorderError !== undefined && !toolResult.isError) {
|
|
262
|
+
firstError = recorderError;
|
|
263
|
+
}
|
|
264
|
+
state.toolStates.delete(toolCallID);
|
|
265
|
+
const liveStepState = state.stepStates.get(liveToolState.stepNumber);
|
|
266
|
+
liveStepState?.toolCallIds.delete(toolCallID);
|
|
267
|
+
state.completedToolCallIds.add(toolCallID);
|
|
268
|
+
continue;
|
|
269
|
+
}
|
|
270
|
+
const resolvedToolName = toolResult.name ?? matchedToolCall?.name ?? 'framework_tool';
|
|
271
|
+
const recorder = this.client.startToolExecution({
|
|
272
|
+
toolName: resolvedToolName,
|
|
273
|
+
toolCallId: toolCallID,
|
|
274
|
+
conversationId: params.conversationId,
|
|
275
|
+
agentName: callAgentName,
|
|
276
|
+
agentVersion: this.agentVersion,
|
|
277
|
+
includeContent: this.captureInputs || this.captureOutputs,
|
|
278
|
+
startedAt: params.stepState.startedAt,
|
|
279
|
+
});
|
|
280
|
+
try {
|
|
281
|
+
const toolResultPayload = {
|
|
282
|
+
completedAt: new Date(),
|
|
283
|
+
};
|
|
284
|
+
if (this.captureInputs) {
|
|
285
|
+
toolResultPayload.arguments = parseJSONIfPossible(matchedToolCall?.inputJSON);
|
|
286
|
+
}
|
|
287
|
+
if (this.captureOutputs) {
|
|
288
|
+
toolResultPayload.result = parseJSONIfPossible(toolResult.contentJSON) ?? toolResult.content;
|
|
289
|
+
}
|
|
290
|
+
if (toolResult.isError) {
|
|
291
|
+
recorder.setCallError(toolResult.content ?? new Error('tool call failed'));
|
|
292
|
+
}
|
|
293
|
+
recorder.setResult(toolResultPayload);
|
|
294
|
+
}
|
|
295
|
+
finally {
|
|
296
|
+
recorder.end();
|
|
297
|
+
}
|
|
298
|
+
const recorderError = recorder.getError();
|
|
299
|
+
if (firstError === undefined && recorderError !== undefined && !toolResult.isError) {
|
|
300
|
+
firstError = recorderError;
|
|
301
|
+
}
|
|
302
|
+
state.completedToolCallIds.add(toolCallID);
|
|
303
|
+
}
|
|
304
|
+
return firstError;
|
|
305
|
+
};
|
|
306
|
+
const hooks = {
|
|
307
|
+
experimental_onStepStart: (event) => {
|
|
308
|
+
noteStreamObservedStartAt(new Date());
|
|
309
|
+
const fallbackStep = state.nextSyntheticStepNumber;
|
|
310
|
+
const stepNumber = extractStepNumber(event, fallbackStep);
|
|
311
|
+
state.nextSyntheticStepNumber = Math.max(state.nextSyntheticStepNumber + 1, stepNumber + 1);
|
|
312
|
+
if (state.stepStates.has(stepNumber)) {
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
315
|
+
const inputMessages = this.captureInputs ? mapInputMessages(event.messages) : [];
|
|
316
|
+
createStepState({
|
|
317
|
+
stepNumber,
|
|
318
|
+
stepStartEvent: event,
|
|
319
|
+
startedAt: new Date(),
|
|
320
|
+
inputMessages,
|
|
321
|
+
});
|
|
322
|
+
},
|
|
323
|
+
onStepFinish: (event) => {
|
|
324
|
+
const response = mapResponseFromStepFinish(event);
|
|
325
|
+
const { stepNumber, stepState } = resolveOrCreateStepStateForFinish({
|
|
326
|
+
eventStepNumber: event.stepNumber,
|
|
327
|
+
responseModel: response.responseModel,
|
|
328
|
+
});
|
|
329
|
+
const conversation = stepState.conversation;
|
|
330
|
+
if (stepState.recorder === undefined && response.responseModel !== undefined) {
|
|
331
|
+
stepState.stepStartEvent = {
|
|
332
|
+
...stepState.stepStartEvent,
|
|
333
|
+
model: {
|
|
334
|
+
...(stepState.stepStartEvent.model !== null && typeof stepState.stepStartEvent.model === 'object'
|
|
335
|
+
? stepState.stepStartEvent.model
|
|
336
|
+
: {}),
|
|
337
|
+
modelId: response.responseModel,
|
|
338
|
+
},
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
let recorder;
|
|
342
|
+
try {
|
|
343
|
+
recorder = ensureStepRecorder(stepState, conversation.conversationId);
|
|
344
|
+
}
|
|
345
|
+
catch (error) {
|
|
346
|
+
state.stepStates.delete(stepNumber);
|
|
347
|
+
if (stepState.toolCallIds.size > 0) {
|
|
348
|
+
closeStepTools(state, stepState, error);
|
|
349
|
+
}
|
|
350
|
+
throw error;
|
|
351
|
+
}
|
|
352
|
+
if (stepState.firstTokenAt !== undefined) {
|
|
353
|
+
recorder.setFirstTokenAt(stepState.firstTokenAt);
|
|
354
|
+
}
|
|
355
|
+
const outputMapping = mapStepOutput(event);
|
|
356
|
+
const metadata = buildFrameworkMetadata(mergedCallMetadata, outputMapping.stepType, this.captureOutputs ? outputMapping.reasoningText : undefined);
|
|
357
|
+
const usage = mapUsageFromStepFinish(event);
|
|
358
|
+
const isError = shouldTreatStepAsError(event);
|
|
359
|
+
try {
|
|
360
|
+
recorder.setResult({
|
|
361
|
+
conversationId: conversation.conversationId,
|
|
362
|
+
agentName: callAgentName,
|
|
363
|
+
agentVersion: this.agentVersion,
|
|
364
|
+
operationName,
|
|
365
|
+
input: this.captureInputs ? stepState.inputMessages : undefined,
|
|
366
|
+
output: this.captureOutputs ? outputMapping.output : undefined,
|
|
367
|
+
usage,
|
|
368
|
+
stopReason: response.finishReason,
|
|
369
|
+
responseId: response.responseId,
|
|
370
|
+
responseModel: response.responseModel,
|
|
371
|
+
tags,
|
|
372
|
+
metadata,
|
|
373
|
+
completedAt: new Date(),
|
|
374
|
+
});
|
|
375
|
+
if (isError) {
|
|
376
|
+
recorder.setCallError(event.error ?? new Error('step finished with error'));
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
finally {
|
|
380
|
+
recorder.end();
|
|
381
|
+
}
|
|
382
|
+
const recorderError = recorder.getError();
|
|
383
|
+
const fallbackToolRecorderError = recordToolExecutionFromStepFinish({
|
|
384
|
+
stepNumber,
|
|
385
|
+
stepState,
|
|
386
|
+
conversationId: conversation.conversationId,
|
|
387
|
+
output: outputMapping.output,
|
|
388
|
+
});
|
|
389
|
+
state.stepStates.delete(stepNumber);
|
|
390
|
+
if (stepState.toolCallIds.size > 0) {
|
|
391
|
+
const closeError = isError
|
|
392
|
+
? (event.error ?? new Error('parent step failed'))
|
|
393
|
+
: new Error('tool call did not finish before step completion');
|
|
394
|
+
closeStepTools(state, stepState, closeError);
|
|
395
|
+
}
|
|
396
|
+
if (recorderError !== undefined) {
|
|
397
|
+
throw recorderError;
|
|
398
|
+
}
|
|
399
|
+
if (fallbackToolRecorderError !== undefined) {
|
|
400
|
+
throw fallbackToolRecorderError;
|
|
401
|
+
}
|
|
402
|
+
},
|
|
403
|
+
experimental_onToolCallStart: (event) => {
|
|
404
|
+
const parsed = parseToolCallStart(event);
|
|
405
|
+
if (parsed === undefined) {
|
|
406
|
+
return;
|
|
407
|
+
}
|
|
408
|
+
state.completedToolCallIds.delete(parsed.toolCallId);
|
|
409
|
+
if (state.toolStates.has(parsed.toolCallId)) {
|
|
410
|
+
return;
|
|
411
|
+
}
|
|
412
|
+
const startedAt = new Date();
|
|
413
|
+
if (mode === 'STREAM') {
|
|
414
|
+
noteStreamObservedStartAt(startedAt);
|
|
415
|
+
}
|
|
416
|
+
const { stepNumber, stepState } = resolveOrCreateStepStateForObservedEvent({
|
|
417
|
+
eventStepNumber: event.stepNumber,
|
|
418
|
+
observedAt: startedAt,
|
|
419
|
+
});
|
|
420
|
+
const recorder = this.client.startToolExecution({
|
|
421
|
+
toolName: parsed.toolName,
|
|
422
|
+
toolCallId: parsed.toolCallId,
|
|
423
|
+
toolType: parsed.toolType,
|
|
424
|
+
toolDescription: parsed.description,
|
|
425
|
+
conversationId: stepState.conversation.conversationId,
|
|
426
|
+
agentName: callAgentName,
|
|
427
|
+
agentVersion: this.agentVersion,
|
|
428
|
+
includeContent: this.captureInputs || this.captureOutputs,
|
|
429
|
+
startedAt,
|
|
430
|
+
});
|
|
431
|
+
state.toolStates.set(parsed.toolCallId, {
|
|
432
|
+
recorder,
|
|
433
|
+
startedAt,
|
|
434
|
+
stepNumber,
|
|
435
|
+
input: parsed.input,
|
|
436
|
+
});
|
|
437
|
+
stepState.hasToolCalls = true;
|
|
438
|
+
stepState.toolCallIds.add(parsed.toolCallId);
|
|
439
|
+
},
|
|
440
|
+
experimental_onToolCallFinish: (event) => {
|
|
441
|
+
const parsed = parseToolCallFinish(event);
|
|
442
|
+
if (parsed === undefined) {
|
|
443
|
+
return;
|
|
444
|
+
}
|
|
445
|
+
const toolState = state.toolStates.get(parsed.toolCallId);
|
|
446
|
+
if (toolState === undefined) {
|
|
447
|
+
return;
|
|
448
|
+
}
|
|
449
|
+
const completedAt = parsed.durationMs !== undefined ? new Date(toolState.startedAt.getTime() + parsed.durationMs) : new Date();
|
|
450
|
+
try {
|
|
451
|
+
if (parsed.success) {
|
|
452
|
+
const result = {
|
|
453
|
+
completedAt,
|
|
454
|
+
};
|
|
455
|
+
if (this.captureInputs) {
|
|
456
|
+
result.arguments = toolState.input;
|
|
457
|
+
}
|
|
458
|
+
if (this.captureOutputs) {
|
|
459
|
+
result.result = parsed.output;
|
|
460
|
+
}
|
|
461
|
+
toolState.recorder.setResult(result);
|
|
462
|
+
}
|
|
463
|
+
else {
|
|
464
|
+
toolState.recorder.setCallError(parsed.error ?? new Error('tool call failed'));
|
|
465
|
+
toolState.recorder.setResult({ completedAt });
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
finally {
|
|
469
|
+
toolState.recorder.end();
|
|
470
|
+
}
|
|
471
|
+
const recorderError = toolState.recorder.getError();
|
|
472
|
+
state.toolStates.delete(parsed.toolCallId);
|
|
473
|
+
const stepState = state.stepStates.get(toolState.stepNumber);
|
|
474
|
+
stepState?.toolCallIds.delete(parsed.toolCallId);
|
|
475
|
+
state.completedToolCallIds.add(parsed.toolCallId);
|
|
476
|
+
if (parsed.success && recorderError !== undefined) {
|
|
477
|
+
throw recorderError;
|
|
478
|
+
}
|
|
479
|
+
},
|
|
480
|
+
};
|
|
481
|
+
if (includeStreamHandlers) {
|
|
482
|
+
const finalizeStreamFailure = (error) => {
|
|
483
|
+
const observedAt = new Date();
|
|
484
|
+
const fallbackStreamStartedAt = streamObservedStartAt ?? (hasCreatedStreamStepState ? observedAt : callStartedAt);
|
|
485
|
+
noteStreamObservedStartAt(observedAt);
|
|
486
|
+
if (state.stepStates.size === 0) {
|
|
487
|
+
resolveOrCreateStepStateForObservedEvent({
|
|
488
|
+
eventStepNumber: undefined,
|
|
489
|
+
observedAt: fallbackStreamStartedAt,
|
|
490
|
+
});
|
|
491
|
+
}
|
|
492
|
+
const stepEntries = [...state.stepStates.entries()];
|
|
493
|
+
let firstError;
|
|
494
|
+
for (const [, stepState] of stepEntries) {
|
|
495
|
+
let recorder = stepState.recorder;
|
|
496
|
+
if (recorder === undefined) {
|
|
497
|
+
try {
|
|
498
|
+
recorder = ensureStepRecorder(stepState, stepState.conversation.conversationId);
|
|
499
|
+
}
|
|
500
|
+
catch (error) {
|
|
501
|
+
if (firstError === undefined) {
|
|
502
|
+
firstError = error instanceof Error ? error : new Error(String(error));
|
|
503
|
+
}
|
|
504
|
+
if (stepState.toolCallIds.size > 0) {
|
|
505
|
+
closeStepTools(state, stepState, error);
|
|
506
|
+
}
|
|
507
|
+
continue;
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
if (stepState.firstTokenAt !== undefined) {
|
|
511
|
+
recorder.setFirstTokenAt(stepState.firstTokenAt);
|
|
512
|
+
}
|
|
513
|
+
try {
|
|
514
|
+
recorder.setCallError(error);
|
|
515
|
+
}
|
|
516
|
+
finally {
|
|
517
|
+
recorder.end();
|
|
518
|
+
}
|
|
519
|
+
const recorderError = recorder.getError();
|
|
520
|
+
if (firstError === undefined && recorderError !== undefined) {
|
|
521
|
+
firstError = recorderError;
|
|
522
|
+
}
|
|
523
|
+
if (stepState.toolCallIds.size > 0) {
|
|
524
|
+
closeStepTools(state, stepState, error);
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
state.stepStates.clear();
|
|
528
|
+
if (state.toolStates.size > 0) {
|
|
529
|
+
closeAllTools(state, error);
|
|
530
|
+
}
|
|
531
|
+
if (firstError !== undefined) {
|
|
532
|
+
throw firstError;
|
|
533
|
+
}
|
|
534
|
+
};
|
|
535
|
+
hooks.onChunk = (event) => {
|
|
536
|
+
const observedAt = new Date();
|
|
537
|
+
noteStreamObservedStartAt(observedAt);
|
|
538
|
+
const { stepState } = resolveOrCreateStepStateForObservedEvent({
|
|
539
|
+
eventStepNumber: event.stepNumber,
|
|
540
|
+
observedAt,
|
|
541
|
+
});
|
|
542
|
+
if (!isTextChunk(event)) {
|
|
543
|
+
return;
|
|
544
|
+
}
|
|
545
|
+
const recorder = stepState.recorder;
|
|
546
|
+
if (recorder === undefined || stepState.firstTokenRecorded) {
|
|
547
|
+
if (!stepState.firstTokenRecorded) {
|
|
548
|
+
stepState.firstTokenRecorded = true;
|
|
549
|
+
stepState.firstTokenAt = observedAt;
|
|
550
|
+
}
|
|
551
|
+
return;
|
|
552
|
+
}
|
|
553
|
+
stepState.firstTokenRecorded = true;
|
|
554
|
+
stepState.firstTokenAt = undefined;
|
|
555
|
+
recorder.setFirstTokenAt(observedAt);
|
|
556
|
+
};
|
|
557
|
+
hooks.onError = (event) => {
|
|
558
|
+
finalizeStreamFailure(unwrapStreamError(event));
|
|
559
|
+
};
|
|
560
|
+
hooks.onAbort = (event) => {
|
|
561
|
+
const abortError = unwrapStreamAbortError(event);
|
|
562
|
+
finalizeStreamFailure(abortError);
|
|
563
|
+
};
|
|
564
|
+
}
|
|
565
|
+
return hooks;
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
function unwrapStreamError(event) {
|
|
569
|
+
if (event === null || typeof event !== 'object' || !('error' in event)) {
|
|
570
|
+
return event;
|
|
571
|
+
}
|
|
572
|
+
return event.error;
|
|
573
|
+
}
|
|
574
|
+
function unwrapStreamAbortError(event) {
|
|
575
|
+
const unwrapped = unwrapStreamError(event);
|
|
576
|
+
if (unwrapped === undefined || unwrapped === null) {
|
|
577
|
+
return new Error('stream aborted');
|
|
578
|
+
}
|
|
579
|
+
if (unwrapped instanceof Error) {
|
|
580
|
+
return unwrapped;
|
|
581
|
+
}
|
|
582
|
+
if (typeof unwrapped === 'string') {
|
|
583
|
+
const trimmed = unwrapped.trim();
|
|
584
|
+
return new Error(trimmed.length > 0 ? trimmed : 'stream aborted');
|
|
585
|
+
}
|
|
586
|
+
return new Error('stream aborted');
|
|
587
|
+
}
|
|
588
|
+
function closeStepTools(state, stepState, error) {
|
|
589
|
+
for (const toolCallId of stepState.toolCallIds) {
|
|
590
|
+
const toolState = state.toolStates.get(toolCallId);
|
|
591
|
+
if (toolState === undefined) {
|
|
592
|
+
continue;
|
|
593
|
+
}
|
|
594
|
+
try {
|
|
595
|
+
toolState.recorder.setCallError(error);
|
|
596
|
+
}
|
|
597
|
+
finally {
|
|
598
|
+
toolState.recorder.end();
|
|
599
|
+
}
|
|
600
|
+
state.toolStates.delete(toolCallId);
|
|
601
|
+
state.completedToolCallIds.add(toolCallId);
|
|
602
|
+
}
|
|
603
|
+
stepState.toolCallIds.clear();
|
|
604
|
+
}
|
|
605
|
+
function closeAllTools(state, error) {
|
|
606
|
+
const entries = [...state.toolStates.entries()];
|
|
607
|
+
for (const [toolCallId, toolState] of entries) {
|
|
608
|
+
try {
|
|
609
|
+
toolState.recorder.setCallError(error);
|
|
610
|
+
}
|
|
611
|
+
finally {
|
|
612
|
+
toolState.recorder.end();
|
|
613
|
+
}
|
|
614
|
+
state.toolStates.delete(toolCallId);
|
|
615
|
+
state.completedToolCallIds.add(toolCallId);
|
|
616
|
+
const stepState = state.stepStates.get(toolState.stepNumber);
|
|
617
|
+
stepState?.toolCallIds.delete(toolCallId);
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
function resolveStepNumberForEvent(state, eventStepNumber) {
|
|
621
|
+
const parsed = parseOptionalStepNumber(eventStepNumber);
|
|
622
|
+
if (parsed !== undefined) {
|
|
623
|
+
if (state.stepStates.has(parsed)) {
|
|
624
|
+
return parsed;
|
|
625
|
+
}
|
|
626
|
+
return undefined;
|
|
627
|
+
}
|
|
628
|
+
if (state.stepStates.size !== 1) {
|
|
629
|
+
return undefined;
|
|
630
|
+
}
|
|
631
|
+
const [only] = state.stepStates.keys();
|
|
632
|
+
return only;
|
|
633
|
+
}
|
|
634
|
+
function parseOptionalStepNumber(value) {
|
|
635
|
+
if (typeof value === 'number') {
|
|
636
|
+
if (!Number.isFinite(value) || value < 0) {
|
|
637
|
+
return undefined;
|
|
638
|
+
}
|
|
639
|
+
return Math.trunc(value);
|
|
640
|
+
}
|
|
641
|
+
if (typeof value === 'string') {
|
|
642
|
+
const trimmed = value.trim();
|
|
643
|
+
if (trimmed.length === 0) {
|
|
644
|
+
return undefined;
|
|
645
|
+
}
|
|
646
|
+
const parsed = Number.parseInt(trimmed, 10);
|
|
647
|
+
if (Number.isNaN(parsed) || parsed < 0) {
|
|
648
|
+
return undefined;
|
|
649
|
+
}
|
|
650
|
+
return parsed;
|
|
651
|
+
}
|
|
652
|
+
return undefined;
|
|
653
|
+
}
|
|
654
|
+
function hasStepStartModelRef(event) {
|
|
655
|
+
const model = event.model;
|
|
656
|
+
if (model === null || typeof model !== 'object') {
|
|
657
|
+
return false;
|
|
658
|
+
}
|
|
659
|
+
const modelRef = model;
|
|
660
|
+
return hasNonEmptyString(modelRef.modelId) || hasNonEmptyString(modelRef.id) || hasNonEmptyString(modelRef.name);
|
|
661
|
+
}
|
|
662
|
+
function hasNonEmptyString(value) {
|
|
663
|
+
return typeof value === 'string' && value.trim().length > 0;
|
|
664
|
+
}
|
|
665
|
+
function normalizeOptionalString(value) {
|
|
666
|
+
if (typeof value !== 'string') {
|
|
667
|
+
return undefined;
|
|
668
|
+
}
|
|
669
|
+
const trimmed = value.trim();
|
|
670
|
+
return trimmed.length > 0 ? trimmed : undefined;
|
|
671
|
+
}
|
|
672
|
+
//# sourceMappingURL=hooks.js.map
|