@xsai-ext/telemetry 0.5.0-beta.2 → 0.5.0-beta.4
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/index.js +57 -65
- package/package.json +8 -8
package/dist/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { embed as embed$1, clean, embedMany as embedMany$1, trampoline,
|
|
1
|
+
import { embed as embed$1, clean, embedMany as embedMany$1, trampoline, resolvePrepareStep, chat, responseJSON, normalizeChatCompletionUsage, computeTotalUsage, InvalidResponseError, stepCountAtLeast, executeTool, shouldStop, DelayedPromise, objCamelToSnake } from 'xsai';
|
|
2
2
|
export * from 'xsai';
|
|
3
3
|
import { trace, SpanStatusCode } from '@opentelemetry/api';
|
|
4
4
|
import { createControlledStream, errorControllers, closeControllers, EventSourceParserStream, JsonMessageTransformStream } from '@xsai/shared-stream';
|
|
5
5
|
|
|
6
|
-
var version = "0.5.0-beta.
|
|
6
|
+
var version = "0.5.0-beta.4";
|
|
7
7
|
var pkg = {
|
|
8
8
|
version: version};
|
|
9
9
|
|
|
@@ -135,8 +135,8 @@ const generateText = async (options) => {
|
|
|
135
135
|
const rawGenerateText = async (options2) => {
|
|
136
136
|
const messages = options2.steps == null ? structuredClone(options2.messages) : options2.messages;
|
|
137
137
|
const steps = options2.steps ?? [];
|
|
138
|
-
const stepOptions = await
|
|
139
|
-
messages,
|
|
138
|
+
const stepOptions = await resolvePrepareStep({
|
|
139
|
+
input: messages,
|
|
140
140
|
model: options2.model,
|
|
141
141
|
prepareStep: options2.prepareStep,
|
|
142
142
|
stepNumber: steps.length,
|
|
@@ -145,20 +145,22 @@ const generateText = async (options) => {
|
|
|
145
145
|
});
|
|
146
146
|
return recordSpan(chatSpan({
|
|
147
147
|
...options2,
|
|
148
|
-
messages: stepOptions.
|
|
148
|
+
messages: stepOptions.input,
|
|
149
149
|
model: stepOptions.model,
|
|
150
150
|
toolChoice: stepOptions.toolChoice
|
|
151
151
|
}, tracer), async (span) => chat({
|
|
152
152
|
...options2,
|
|
153
|
-
|
|
154
|
-
messages: stepOptions.messages,
|
|
153
|
+
messages: stepOptions.input,
|
|
155
154
|
model: stepOptions.model,
|
|
156
155
|
steps: void 0,
|
|
157
|
-
stopWhen: void 0,
|
|
158
156
|
stream: false,
|
|
159
|
-
|
|
157
|
+
telemetry: void 0,
|
|
158
|
+
toolChoice: stepOptions.toolChoice,
|
|
159
|
+
totalUsage: void 0
|
|
160
160
|
}).then(responseJSON).then(async (res) => {
|
|
161
|
-
const { choices
|
|
161
|
+
const { choices } = res;
|
|
162
|
+
const usage = normalizeChatCompletionUsage(res.usage);
|
|
163
|
+
const totalUsage = computeTotalUsage(options2.totalUsage, usage);
|
|
162
164
|
if (!choices?.length) {
|
|
163
165
|
const responseBody = JSON.stringify(res);
|
|
164
166
|
throw new InvalidResponseError(`No choices returned, response body: ${responseBody}`, {
|
|
@@ -182,13 +184,17 @@ const generateText = async (options) => {
|
|
|
182
184
|
tools: options2.tools
|
|
183
185
|
}))
|
|
184
186
|
);
|
|
185
|
-
for (const { completionToolCall, completionToolResult,
|
|
187
|
+
for (const { completionToolCall, completionToolResult, result } of results) {
|
|
186
188
|
toolCalls.push(completionToolCall);
|
|
187
189
|
toolResults.push(completionToolResult);
|
|
188
|
-
messages.push(
|
|
190
|
+
messages.push({
|
|
191
|
+
content: result,
|
|
192
|
+
role: "tool",
|
|
193
|
+
tool_call_id: completionToolCall.toolCallId
|
|
194
|
+
});
|
|
189
195
|
}
|
|
190
196
|
}
|
|
191
|
-
const
|
|
197
|
+
const step = {
|
|
192
198
|
finishReason,
|
|
193
199
|
text: Array.isArray(message.content) ? message.content.filter((m) => m.type === "text").map((m) => m.text).join("\n") : message.content,
|
|
194
200
|
toolCalls,
|
|
@@ -196,25 +202,16 @@ const generateText = async (options) => {
|
|
|
196
202
|
usage
|
|
197
203
|
};
|
|
198
204
|
const stop = shouldStop(stopWhen, {
|
|
199
|
-
messages,
|
|
200
|
-
step
|
|
201
|
-
steps: [...steps,
|
|
205
|
+
input: messages,
|
|
206
|
+
step,
|
|
207
|
+
steps: [...steps, step]
|
|
202
208
|
});
|
|
203
209
|
const willContinue = toolCalls.length > 0 && !stop;
|
|
204
|
-
const step = {
|
|
205
|
-
...stopStep,
|
|
206
|
-
stepType: determineStepType({
|
|
207
|
-
finishReason,
|
|
208
|
-
stepsLength: steps.length,
|
|
209
|
-
toolCallsLength: toolCalls.length,
|
|
210
|
-
willContinue
|
|
211
|
-
})
|
|
212
|
-
};
|
|
213
210
|
steps.push(step);
|
|
214
211
|
span.setAttributes({
|
|
215
212
|
"gen_ai.response.finish_reasons": [step.finishReason],
|
|
216
|
-
"gen_ai.usage.input_tokens": step.usage.
|
|
217
|
-
"gen_ai.usage.output_tokens": step.usage.
|
|
213
|
+
"gen_ai.usage.input_tokens": step.usage.inputTokens,
|
|
214
|
+
"gen_ai.usage.output_tokens": step.usage.outputTokens
|
|
218
215
|
});
|
|
219
216
|
if (options2.onStepFinish)
|
|
220
217
|
await options2.onStepFinish(step);
|
|
@@ -227,13 +224,15 @@ const generateText = async (options) => {
|
|
|
227
224
|
text: step.text,
|
|
228
225
|
toolCalls: step.toolCalls,
|
|
229
226
|
toolResults: step.toolResults,
|
|
227
|
+
totalUsage,
|
|
230
228
|
usage: step.usage
|
|
231
229
|
};
|
|
232
230
|
} else {
|
|
233
231
|
return async () => rawGenerateText({
|
|
234
232
|
...options2,
|
|
235
233
|
messages,
|
|
236
|
-
steps
|
|
234
|
+
steps,
|
|
235
|
+
totalUsage
|
|
237
236
|
});
|
|
238
237
|
}
|
|
239
238
|
}));
|
|
@@ -257,6 +256,7 @@ const streamText = (options) => {
|
|
|
257
256
|
const resultUsage = new DelayedPromise();
|
|
258
257
|
const resultTotalUsage = new DelayedPromise();
|
|
259
258
|
const [eventStream, eventCtrl] = createControlledStream();
|
|
259
|
+
const [fullStream, fullCtrl] = createControlledStream();
|
|
260
260
|
const [textStream, textCtrl] = createControlledStream();
|
|
261
261
|
const [reasoningTextStream, reasoningTextCtrl] = createControlledStream();
|
|
262
262
|
const pushEvent = (stepEvent) => {
|
|
@@ -269,8 +269,8 @@ const streamText = (options) => {
|
|
|
269
269
|
};
|
|
270
270
|
const tools = options.tools != null && options.tools.length > 0 ? options.tools.map((tool) => wrapTool(tool, tracer)) : void 0;
|
|
271
271
|
const doStream = async () => {
|
|
272
|
-
const stepOptions = await
|
|
273
|
-
messages,
|
|
272
|
+
const stepOptions = await resolvePrepareStep({
|
|
273
|
+
input: messages,
|
|
274
274
|
model: options.model,
|
|
275
275
|
prepareStep: options.prepareStep,
|
|
276
276
|
stepNumber: steps.length,
|
|
@@ -279,28 +279,25 @@ const streamText = (options) => {
|
|
|
279
279
|
});
|
|
280
280
|
return recordSpan(chatSpan({
|
|
281
281
|
...options,
|
|
282
|
-
messages: stepOptions.
|
|
282
|
+
messages: stepOptions.input,
|
|
283
283
|
model: stepOptions.model,
|
|
284
284
|
toolChoice: stepOptions.toolChoice
|
|
285
285
|
}, tracer), async (span) => {
|
|
286
286
|
const { body: stream } = await chat({
|
|
287
287
|
...options,
|
|
288
|
-
|
|
289
|
-
messages: stepOptions.messages,
|
|
288
|
+
messages: stepOptions.input,
|
|
290
289
|
model: stepOptions.model,
|
|
291
|
-
stopWhen: void 0,
|
|
292
290
|
stream: true,
|
|
293
291
|
streamOptions: options.streamOptions != null ? objCamelToSnake(options.streamOptions) : void 0,
|
|
292
|
+
telemetry: void 0,
|
|
294
293
|
toolChoice: stepOptions.toolChoice,
|
|
295
294
|
tools
|
|
296
295
|
});
|
|
297
296
|
const pushUsage = (u) => {
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
total_tokens: totalUsage.total_tokens + u.total_tokens
|
|
303
|
-
} : u;
|
|
297
|
+
if (u == null)
|
|
298
|
+
return;
|
|
299
|
+
usage = normalizeChatCompletionUsage(u);
|
|
300
|
+
totalUsage = computeTotalUsage(totalUsage, usage);
|
|
304
301
|
};
|
|
305
302
|
let text = "";
|
|
306
303
|
let reasoningText;
|
|
@@ -309,8 +306,7 @@ const streamText = (options) => {
|
|
|
309
306
|
text += content;
|
|
310
307
|
};
|
|
311
308
|
const pushReasoningText = (reasoningContent) => {
|
|
312
|
-
|
|
313
|
-
reasoningText = "";
|
|
309
|
+
reasoningText ??= "";
|
|
314
310
|
reasoningTextCtrl.current?.enqueue(reasoningContent);
|
|
315
311
|
reasoningText += reasoningContent;
|
|
316
312
|
};
|
|
@@ -320,14 +316,14 @@ const streamText = (options) => {
|
|
|
320
316
|
let finishReason = "other";
|
|
321
317
|
await stream.pipeThrough(new TextDecoderStream()).pipeThrough(new EventSourceParserStream()).pipeThrough(new JsonMessageTransformStream()).pipeTo(new WritableStream({
|
|
322
318
|
abort: (reason) => {
|
|
323
|
-
errorControllers(reason, eventCtrl, textCtrl, reasoningTextCtrl);
|
|
319
|
+
errorControllers(reason, eventCtrl, fullCtrl, textCtrl, reasoningTextCtrl);
|
|
324
320
|
},
|
|
325
321
|
close: () => {
|
|
326
322
|
},
|
|
327
323
|
// eslint-disable-next-line sonarjs/cognitive-complexity
|
|
328
324
|
write: (chunk) => {
|
|
329
|
-
|
|
330
|
-
|
|
325
|
+
fullCtrl.current?.enqueue(chunk);
|
|
326
|
+
pushUsage(chunk.usage);
|
|
331
327
|
if (chunk.choices == null || chunk.choices.length === 0)
|
|
332
328
|
return;
|
|
333
329
|
const choice = chunk.choices[0];
|
|
@@ -400,10 +396,14 @@ const streamText = (options) => {
|
|
|
400
396
|
tools
|
|
401
397
|
}))
|
|
402
398
|
);
|
|
403
|
-
for (const { completionToolCall, completionToolResult,
|
|
399
|
+
for (const { completionToolCall, completionToolResult, result } of results) {
|
|
404
400
|
toolCalls.push(completionToolCall);
|
|
405
401
|
toolResults.push(completionToolResult);
|
|
406
|
-
messages.push(
|
|
402
|
+
messages.push({
|
|
403
|
+
content: result,
|
|
404
|
+
role: "tool",
|
|
405
|
+
tool_call_id: completionToolCall.toolCallId
|
|
406
|
+
});
|
|
407
407
|
pushEvent({ ...completionToolCall, type: "tool-call" });
|
|
408
408
|
pushEvent({ ...completionToolResult, type: "tool-result" });
|
|
409
409
|
}
|
|
@@ -414,7 +414,7 @@ const streamText = (options) => {
|
|
|
414
414
|
usage
|
|
415
415
|
});
|
|
416
416
|
}
|
|
417
|
-
const
|
|
417
|
+
const step = {
|
|
418
418
|
finishReason,
|
|
419
419
|
text,
|
|
420
420
|
toolCalls,
|
|
@@ -422,26 +422,17 @@ const streamText = (options) => {
|
|
|
422
422
|
usage
|
|
423
423
|
};
|
|
424
424
|
const stop = shouldStop(stopWhen, {
|
|
425
|
-
messages,
|
|
426
|
-
step
|
|
427
|
-
steps: [...steps,
|
|
425
|
+
input: messages,
|
|
426
|
+
step,
|
|
427
|
+
steps: [...steps, step]
|
|
428
428
|
});
|
|
429
429
|
const willContinue = toolCalls.length > 0 && !stop;
|
|
430
|
-
const step = {
|
|
431
|
-
...stopStep,
|
|
432
|
-
stepType: determineStepType({
|
|
433
|
-
finishReason,
|
|
434
|
-
stepsLength: steps.length,
|
|
435
|
-
toolCallsLength: toolCalls.length,
|
|
436
|
-
willContinue
|
|
437
|
-
})
|
|
438
|
-
};
|
|
439
430
|
pushStep(step);
|
|
440
431
|
span.setAttributes({
|
|
441
432
|
"gen_ai.response.finish_reasons": [step.finishReason],
|
|
442
433
|
...step.usage && {
|
|
443
|
-
"gen_ai.usage.input_tokens": step.usage.
|
|
444
|
-
"gen_ai.usage.output_tokens": step.usage.
|
|
434
|
+
"gen_ai.usage.input_tokens": step.usage.inputTokens,
|
|
435
|
+
"gen_ai.usage.output_tokens": step.usage.outputTokens
|
|
445
436
|
}
|
|
446
437
|
});
|
|
447
438
|
if (willContinue)
|
|
@@ -461,21 +452,22 @@ const streamText = (options) => {
|
|
|
461
452
|
finalError ??= err;
|
|
462
453
|
}
|
|
463
454
|
if (finalError != null) {
|
|
464
|
-
errorControllers(finalError, eventCtrl, textCtrl, reasoningTextCtrl);
|
|
455
|
+
errorControllers(finalError, eventCtrl, fullCtrl, textCtrl, reasoningTextCtrl);
|
|
465
456
|
resultSteps.reject(finalError);
|
|
466
457
|
resultMessages.reject(finalError);
|
|
467
458
|
resultUsage.reject(finalError);
|
|
468
459
|
resultTotalUsage.reject(finalError);
|
|
469
460
|
return;
|
|
470
461
|
}
|
|
471
|
-
closeControllers(eventCtrl, textCtrl, reasoningTextCtrl);
|
|
462
|
+
closeControllers(eventCtrl, fullCtrl, textCtrl, reasoningTextCtrl);
|
|
472
463
|
resultSteps.resolve(steps);
|
|
473
464
|
resultMessages.resolve(messages);
|
|
474
465
|
resultUsage.resolve(usage);
|
|
475
466
|
resultTotalUsage.resolve(totalUsage);
|
|
476
467
|
})();
|
|
477
468
|
return {
|
|
478
|
-
|
|
469
|
+
eventStream,
|
|
470
|
+
fullStream,
|
|
479
471
|
messages: resultMessages.promise,
|
|
480
472
|
reasoningTextStream,
|
|
481
473
|
steps: resultSteps.promise,
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xsai-ext/telemetry",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.5.0-beta.
|
|
4
|
+
"version": "0.5.0-beta.4",
|
|
5
5
|
"description": "extra-small AI SDK.",
|
|
6
6
|
"author": "Moeru AI",
|
|
7
7
|
"license": "MIT",
|
|
@@ -29,15 +29,15 @@
|
|
|
29
29
|
"dist"
|
|
30
30
|
],
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@opentelemetry/api": "^1.9.
|
|
33
|
-
"@xsai/shared-stream": "
|
|
34
|
-
"xsai": "
|
|
32
|
+
"@opentelemetry/api": "^1.9.1",
|
|
33
|
+
"@xsai/shared-stream": "0.5.0-beta.4",
|
|
34
|
+
"xsai": "0.5.0-beta.4"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
|
-
"@langfuse/otel": "^
|
|
38
|
-
"@opentelemetry/sdk-trace-base": "^2.
|
|
39
|
-
"@opentelemetry/sdk-trace-node": "^2.
|
|
40
|
-
"zod": "^4.
|
|
37
|
+
"@langfuse/otel": "^5.1.0",
|
|
38
|
+
"@opentelemetry/sdk-trace-base": "^2.6.1",
|
|
39
|
+
"@opentelemetry/sdk-trace-node": "^2.6.1",
|
|
40
|
+
"zod": "^4.3.6"
|
|
41
41
|
},
|
|
42
42
|
"scripts": {
|
|
43
43
|
"build": "pkgroll",
|