@lelemondev/sdk 0.7.0 → 0.7.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/dist/index.d.mts +116 -2
- package/dist/index.d.ts +116 -2
- package/dist/index.js +293 -58
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +291 -59
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { AsyncLocalStorage } from 'async_hooks';
|
|
2
|
+
|
|
1
3
|
/* @lelemondev/sdk - LLM Observability */
|
|
2
4
|
var __defProp = Object.defineProperty;
|
|
3
5
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
@@ -102,9 +104,9 @@ var Transport = class {
|
|
|
102
104
|
* Enqueue a trace for sending
|
|
103
105
|
* Fire-and-forget - never blocks
|
|
104
106
|
*/
|
|
105
|
-
enqueue(
|
|
107
|
+
enqueue(trace2) {
|
|
106
108
|
if (this.config.disabled) return;
|
|
107
|
-
this.queue.push(
|
|
109
|
+
this.queue.push(trace2);
|
|
108
110
|
if (this.queue.length >= this.config.batchSize) {
|
|
109
111
|
this.flush();
|
|
110
112
|
} else {
|
|
@@ -286,6 +288,64 @@ function getNestedValue(obj, path) {
|
|
|
286
288
|
function isValidNumber(value) {
|
|
287
289
|
return typeof value === "number" && !isNaN(value) && isFinite(value);
|
|
288
290
|
}
|
|
291
|
+
var traceStorage = new AsyncLocalStorage();
|
|
292
|
+
function generateId() {
|
|
293
|
+
if (typeof crypto !== "undefined" && crypto.randomUUID) {
|
|
294
|
+
return crypto.randomUUID();
|
|
295
|
+
}
|
|
296
|
+
return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 11)}`;
|
|
297
|
+
}
|
|
298
|
+
function getTraceContext() {
|
|
299
|
+
return traceStorage.getStore();
|
|
300
|
+
}
|
|
301
|
+
async function trace(nameOrOptions, fn) {
|
|
302
|
+
const options = typeof nameOrOptions === "string" ? { name: nameOrOptions } : nameOrOptions;
|
|
303
|
+
const parentContext = getTraceContext();
|
|
304
|
+
const traceId = parentContext?.traceId ?? generateId();
|
|
305
|
+
const rootSpanId = generateId();
|
|
306
|
+
const context = {
|
|
307
|
+
traceId,
|
|
308
|
+
rootSpanId,
|
|
309
|
+
currentSpanId: rootSpanId,
|
|
310
|
+
parentSpanId: parentContext?.currentSpanId,
|
|
311
|
+
name: options.name,
|
|
312
|
+
startTime: Date.now(),
|
|
313
|
+
input: options.input,
|
|
314
|
+
metadata: options.metadata,
|
|
315
|
+
tags: options.tags
|
|
316
|
+
};
|
|
317
|
+
return traceStorage.run(context, async () => {
|
|
318
|
+
try {
|
|
319
|
+
const result = await fn();
|
|
320
|
+
return result;
|
|
321
|
+
} finally {
|
|
322
|
+
}
|
|
323
|
+
});
|
|
324
|
+
}
|
|
325
|
+
function span(options) {
|
|
326
|
+
const context = getTraceContext();
|
|
327
|
+
if (!context) {
|
|
328
|
+
if (process.env.NODE_ENV !== "production") {
|
|
329
|
+
console.warn("[Lelemon] span() called outside of trace() - span will not be captured");
|
|
330
|
+
}
|
|
331
|
+
return;
|
|
332
|
+
}
|
|
333
|
+
captureSpan({
|
|
334
|
+
type: options.type,
|
|
335
|
+
name: options.name,
|
|
336
|
+
input: options.input,
|
|
337
|
+
output: options.output,
|
|
338
|
+
durationMs: options.durationMs ?? 0,
|
|
339
|
+
status: options.status ?? "success",
|
|
340
|
+
errorMessage: options.errorMessage,
|
|
341
|
+
metadata: {
|
|
342
|
+
...options.metadata,
|
|
343
|
+
// Include trace context
|
|
344
|
+
_traceId: context.traceId,
|
|
345
|
+
_parentSpanId: context.currentSpanId
|
|
346
|
+
}
|
|
347
|
+
});
|
|
348
|
+
}
|
|
289
349
|
|
|
290
350
|
// src/core/capture.ts
|
|
291
351
|
var globalContext = {};
|
|
@@ -303,7 +363,8 @@ function captureTrace(params) {
|
|
|
303
363
|
debug("Transport disabled, skipping trace capture");
|
|
304
364
|
return;
|
|
305
365
|
}
|
|
306
|
-
const
|
|
366
|
+
const globalContext2 = getGlobalContext();
|
|
367
|
+
const traceContext = getTraceContext();
|
|
307
368
|
const request = {
|
|
308
369
|
provider: params.provider,
|
|
309
370
|
model: params.model,
|
|
@@ -314,10 +375,26 @@ function captureTrace(params) {
|
|
|
314
375
|
durationMs: params.durationMs,
|
|
315
376
|
status: params.status,
|
|
316
377
|
streaming: params.streaming,
|
|
317
|
-
sessionId:
|
|
318
|
-
userId:
|
|
319
|
-
|
|
320
|
-
|
|
378
|
+
sessionId: globalContext2.sessionId,
|
|
379
|
+
userId: globalContext2.userId,
|
|
380
|
+
// Hierarchy fields (Phase 7.2) - use trace context if available
|
|
381
|
+
traceId: traceContext?.traceId,
|
|
382
|
+
spanId: generateId(),
|
|
383
|
+
parentSpanId: traceContext?.currentSpanId,
|
|
384
|
+
metadata: {
|
|
385
|
+
...globalContext2.metadata,
|
|
386
|
+
...params.metadata,
|
|
387
|
+
// Include trace name for debugging
|
|
388
|
+
...traceContext ? { _traceName: traceContext.name } : {}
|
|
389
|
+
},
|
|
390
|
+
tags: globalContext2.tags,
|
|
391
|
+
// Extended fields (Phase 7.1)
|
|
392
|
+
stopReason: params.stopReason,
|
|
393
|
+
cacheReadTokens: params.cacheReadTokens,
|
|
394
|
+
cacheWriteTokens: params.cacheWriteTokens,
|
|
395
|
+
reasoningTokens: params.reasoningTokens,
|
|
396
|
+
firstTokenMs: params.firstTokenMs,
|
|
397
|
+
thinking: params.thinking
|
|
321
398
|
};
|
|
322
399
|
traceCapture(params.provider, params.model, params.durationMs, params.status);
|
|
323
400
|
transport.enqueue(request);
|
|
@@ -332,7 +409,8 @@ function captureError(params) {
|
|
|
332
409
|
debug("Transport disabled, skipping error capture");
|
|
333
410
|
return;
|
|
334
411
|
}
|
|
335
|
-
const
|
|
412
|
+
const globalContext2 = getGlobalContext();
|
|
413
|
+
const traceContext = getTraceContext();
|
|
336
414
|
const request = {
|
|
337
415
|
provider: params.provider,
|
|
338
416
|
model: params.model,
|
|
@@ -345,10 +423,18 @@ function captureError(params) {
|
|
|
345
423
|
errorMessage: params.error.message,
|
|
346
424
|
errorStack: params.error.stack,
|
|
347
425
|
streaming: params.streaming,
|
|
348
|
-
sessionId:
|
|
349
|
-
userId:
|
|
350
|
-
|
|
351
|
-
|
|
426
|
+
sessionId: globalContext2.sessionId,
|
|
427
|
+
userId: globalContext2.userId,
|
|
428
|
+
// Hierarchy fields (Phase 7.2)
|
|
429
|
+
traceId: traceContext?.traceId,
|
|
430
|
+
spanId: generateId(),
|
|
431
|
+
parentSpanId: traceContext?.currentSpanId,
|
|
432
|
+
metadata: {
|
|
433
|
+
...globalContext2.metadata,
|
|
434
|
+
...params.metadata,
|
|
435
|
+
...traceContext ? { _traceName: traceContext.name } : {}
|
|
436
|
+
},
|
|
437
|
+
tags: globalContext2.tags
|
|
352
438
|
};
|
|
353
439
|
traceCapture(params.provider, params.model, params.durationMs, "error");
|
|
354
440
|
debug("Error details", { message: params.error.message, stack: params.error.stack });
|
|
@@ -364,7 +450,13 @@ function captureSpan(options) {
|
|
|
364
450
|
debug("Transport disabled, skipping span capture");
|
|
365
451
|
return;
|
|
366
452
|
}
|
|
367
|
-
const
|
|
453
|
+
const globalContext2 = getGlobalContext();
|
|
454
|
+
const traceContext = getTraceContext();
|
|
455
|
+
const metadataTraceId = options.metadata?._traceId;
|
|
456
|
+
const metadataParentSpanId = options.metadata?._parentSpanId;
|
|
457
|
+
const cleanMetadata = { ...globalContext2.metadata, ...options.metadata };
|
|
458
|
+
delete cleanMetadata._traceId;
|
|
459
|
+
delete cleanMetadata._parentSpanId;
|
|
368
460
|
const request = {
|
|
369
461
|
spanType: options.type,
|
|
370
462
|
name: options.name,
|
|
@@ -380,11 +472,15 @@ function captureSpan(options) {
|
|
|
380
472
|
status: options.status || "success",
|
|
381
473
|
errorMessage: options.errorMessage,
|
|
382
474
|
streaming: false,
|
|
383
|
-
sessionId:
|
|
384
|
-
userId:
|
|
475
|
+
sessionId: globalContext2.sessionId,
|
|
476
|
+
userId: globalContext2.userId,
|
|
477
|
+
// Hierarchy fields (Phase 7.2)
|
|
478
|
+
traceId: metadataTraceId ?? traceContext?.traceId,
|
|
479
|
+
spanId: generateId(),
|
|
480
|
+
parentSpanId: metadataParentSpanId ?? traceContext?.currentSpanId,
|
|
385
481
|
toolCallId: options.toolCallId,
|
|
386
|
-
metadata:
|
|
387
|
-
tags:
|
|
482
|
+
metadata: cleanMetadata,
|
|
483
|
+
tags: globalContext2.tags
|
|
388
484
|
};
|
|
389
485
|
debug(`Span captured: ${options.type}/${options.name}`, { durationMs: options.durationMs });
|
|
390
486
|
transport.enqueue(request);
|
|
@@ -397,7 +493,8 @@ function captureToolSpans(toolCalls, provider) {
|
|
|
397
493
|
try {
|
|
398
494
|
const transport = getTransport();
|
|
399
495
|
if (!transport.isEnabled()) continue;
|
|
400
|
-
const
|
|
496
|
+
const globalContext2 = getGlobalContext();
|
|
497
|
+
const traceContext = getTraceContext();
|
|
401
498
|
const request = {
|
|
402
499
|
spanType: "tool",
|
|
403
500
|
name: tool.name,
|
|
@@ -412,11 +509,19 @@ function captureToolSpans(toolCalls, provider) {
|
|
|
412
509
|
// Duration unknown at this point
|
|
413
510
|
status: "success",
|
|
414
511
|
streaming: false,
|
|
415
|
-
sessionId:
|
|
416
|
-
userId:
|
|
512
|
+
sessionId: globalContext2.sessionId,
|
|
513
|
+
userId: globalContext2.userId,
|
|
514
|
+
// Hierarchy fields (Phase 7.2)
|
|
515
|
+
traceId: traceContext?.traceId,
|
|
516
|
+
spanId: generateId(),
|
|
517
|
+
parentSpanId: traceContext?.currentSpanId,
|
|
417
518
|
toolCallId: tool.id,
|
|
418
|
-
metadata: {
|
|
419
|
-
|
|
519
|
+
metadata: {
|
|
520
|
+
...globalContext2.metadata,
|
|
521
|
+
toolUseDetected: true,
|
|
522
|
+
...traceContext ? { _traceName: traceContext.name } : {}
|
|
523
|
+
},
|
|
524
|
+
tags: globalContext2.tags
|
|
420
525
|
};
|
|
421
526
|
debug(`Tool span captured: ${tool.name}`, { toolCallId: tool.id });
|
|
422
527
|
transport.enqueue(request);
|
|
@@ -489,7 +594,10 @@ function wrapChatCreate(originalFn) {
|
|
|
489
594
|
outputTokens: extracted.tokens?.outputTokens || 0,
|
|
490
595
|
durationMs,
|
|
491
596
|
status: "success",
|
|
492
|
-
streaming: false
|
|
597
|
+
streaming: false,
|
|
598
|
+
// Extended fields
|
|
599
|
+
stopReason: extracted.finishReason || void 0,
|
|
600
|
+
reasoningTokens: extracted.tokens?.reasoningTokens
|
|
493
601
|
});
|
|
494
602
|
return response;
|
|
495
603
|
} catch (error) {
|
|
@@ -619,14 +727,26 @@ function isAsyncIterable(value) {
|
|
|
619
727
|
async function* wrapStream(stream, request, startTime) {
|
|
620
728
|
const chunks = [];
|
|
621
729
|
let tokens = null;
|
|
730
|
+
let finishReason;
|
|
622
731
|
let error = null;
|
|
732
|
+
let firstTokenMs;
|
|
733
|
+
let firstTokenReceived = false;
|
|
623
734
|
try {
|
|
624
735
|
for await (const chunk of stream) {
|
|
625
|
-
const
|
|
736
|
+
const streamChunk = chunk;
|
|
737
|
+
const content = extractStreamChunkContent(streamChunk);
|
|
626
738
|
if (content) {
|
|
739
|
+
if (!firstTokenReceived) {
|
|
740
|
+
firstTokenReceived = true;
|
|
741
|
+
firstTokenMs = Date.now() - startTime;
|
|
742
|
+
}
|
|
627
743
|
chunks.push(content);
|
|
628
744
|
}
|
|
629
|
-
const
|
|
745
|
+
const chunkFinishReason = streamChunk?.choices?.[0]?.finish_reason;
|
|
746
|
+
if (chunkFinishReason) {
|
|
747
|
+
finishReason = chunkFinishReason;
|
|
748
|
+
}
|
|
749
|
+
const chunkTokens = extractStreamChunkTokens(streamChunk);
|
|
630
750
|
if (chunkTokens) {
|
|
631
751
|
tokens = chunkTokens;
|
|
632
752
|
}
|
|
@@ -657,7 +777,11 @@ async function* wrapStream(stream, request, startTime) {
|
|
|
657
777
|
outputTokens: tokens?.outputTokens || 0,
|
|
658
778
|
durationMs,
|
|
659
779
|
status: "success",
|
|
660
|
-
streaming: true
|
|
780
|
+
streaming: true,
|
|
781
|
+
// Extended fields
|
|
782
|
+
stopReason: finishReason,
|
|
783
|
+
reasoningTokens: tokens?.reasoningTokens,
|
|
784
|
+
firstTokenMs
|
|
661
785
|
});
|
|
662
786
|
}
|
|
663
787
|
}
|
|
@@ -668,8 +792,12 @@ function extractChatCompletion(response) {
|
|
|
668
792
|
() => getNestedValue(response, "choices.0.message.content"),
|
|
669
793
|
null
|
|
670
794
|
);
|
|
795
|
+
const finishReason = safeExtract(
|
|
796
|
+
() => getNestedValue(response, "choices.0.finish_reason"),
|
|
797
|
+
null
|
|
798
|
+
);
|
|
671
799
|
const tokens = extractTokens(response);
|
|
672
|
-
return { model, output, tokens };
|
|
800
|
+
return { model, output, tokens, finishReason };
|
|
673
801
|
}
|
|
674
802
|
function extractLegacyCompletion(response) {
|
|
675
803
|
const model = safeExtract(() => getNestedValue(response, "model"), null);
|
|
@@ -691,10 +819,16 @@ function extractTokens(response) {
|
|
|
691
819
|
if (!isValidNumber(promptTokens) && !isValidNumber(completionTokens)) {
|
|
692
820
|
return null;
|
|
693
821
|
}
|
|
822
|
+
let reasoningTokens;
|
|
823
|
+
const completionDetails = u.completion_tokens_details;
|
|
824
|
+
if (completionDetails && isValidNumber(completionDetails.reasoning_tokens)) {
|
|
825
|
+
reasoningTokens = completionDetails.reasoning_tokens;
|
|
826
|
+
}
|
|
694
827
|
return {
|
|
695
828
|
inputTokens: isValidNumber(promptTokens) ? promptTokens : 0,
|
|
696
829
|
outputTokens: isValidNumber(completionTokens) ? completionTokens : 0,
|
|
697
|
-
totalTokens: isValidNumber(totalTokens) ? totalTokens : 0
|
|
830
|
+
totalTokens: isValidNumber(totalTokens) ? totalTokens : 0,
|
|
831
|
+
reasoningTokens
|
|
698
832
|
};
|
|
699
833
|
} catch {
|
|
700
834
|
return null;
|
|
@@ -847,7 +981,12 @@ function wrapMessagesCreate(originalFn) {
|
|
|
847
981
|
outputTokens: extracted.tokens?.outputTokens || 0,
|
|
848
982
|
durationMs,
|
|
849
983
|
status: "success",
|
|
850
|
-
streaming: false
|
|
984
|
+
streaming: false,
|
|
985
|
+
// Extended fields
|
|
986
|
+
stopReason: extracted.stopReason || void 0,
|
|
987
|
+
cacheReadTokens: extracted.tokens?.cacheReadTokens,
|
|
988
|
+
cacheWriteTokens: extracted.tokens?.cacheWriteTokens,
|
|
989
|
+
thinking: extracted.thinking || void 0
|
|
851
990
|
});
|
|
852
991
|
const toolCalls = extractToolCalls(messageResponse);
|
|
853
992
|
if (toolCalls.length > 0) {
|
|
@@ -901,12 +1040,19 @@ function wrapAnthropicStream(stream, request, startTime) {
|
|
|
901
1040
|
return stream;
|
|
902
1041
|
}
|
|
903
1042
|
const chunks = [];
|
|
1043
|
+
const thinkingChunks = [];
|
|
904
1044
|
let inputTokens = 0;
|
|
905
1045
|
let outputTokens = 0;
|
|
1046
|
+
let cacheReadTokens;
|
|
1047
|
+
let cacheWriteTokens;
|
|
1048
|
+
let stopReason;
|
|
906
1049
|
let model = request.model || "unknown";
|
|
907
1050
|
let captured = false;
|
|
1051
|
+
let firstTokenMs;
|
|
1052
|
+
let firstTokenReceived = false;
|
|
908
1053
|
const toolCalls = [];
|
|
909
1054
|
let currentToolIndex = null;
|
|
1055
|
+
let currentBlockType = null;
|
|
910
1056
|
const wrappedIterator = async function* () {
|
|
911
1057
|
try {
|
|
912
1058
|
for await (const event of originalStream) {
|
|
@@ -914,10 +1060,23 @@ function wrapAnthropicStream(stream, request, startTime) {
|
|
|
914
1060
|
model = event.message.model || model;
|
|
915
1061
|
if (event.message.usage) {
|
|
916
1062
|
inputTokens = event.message.usage.input_tokens || 0;
|
|
1063
|
+
cacheReadTokens = event.message.usage.cache_read_input_tokens;
|
|
1064
|
+
cacheWriteTokens = event.message.usage.cache_creation_input_tokens;
|
|
917
1065
|
}
|
|
918
1066
|
}
|
|
1067
|
+
if (event.type === "content_block_start" && event.content_block) {
|
|
1068
|
+
currentBlockType = event.content_block.type;
|
|
1069
|
+
}
|
|
919
1070
|
if (event.type === "content_block_delta" && event.delta?.text) {
|
|
920
|
-
|
|
1071
|
+
if (!firstTokenReceived) {
|
|
1072
|
+
firstTokenReceived = true;
|
|
1073
|
+
firstTokenMs = Date.now() - startTime;
|
|
1074
|
+
}
|
|
1075
|
+
if (currentBlockType === "thinking") {
|
|
1076
|
+
thinkingChunks.push(event.delta.text);
|
|
1077
|
+
} else {
|
|
1078
|
+
chunks.push(event.delta.text);
|
|
1079
|
+
}
|
|
921
1080
|
}
|
|
922
1081
|
if (event.type === "content_block_start" && event.content_block?.type === "tool_use") {
|
|
923
1082
|
const block = event.content_block;
|
|
@@ -937,18 +1096,27 @@ function wrapAnthropicStream(stream, request, startTime) {
|
|
|
937
1096
|
tool.inputJson += event.delta.partial_json;
|
|
938
1097
|
}
|
|
939
1098
|
}
|
|
940
|
-
if (event.type === "content_block_stop"
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
1099
|
+
if (event.type === "content_block_stop") {
|
|
1100
|
+
if (currentToolIndex !== null) {
|
|
1101
|
+
const tool = toolCalls[currentToolIndex];
|
|
1102
|
+
if (tool && tool.inputJson) {
|
|
1103
|
+
try {
|
|
1104
|
+
tool.input = JSON.parse(tool.inputJson);
|
|
1105
|
+
} catch {
|
|
1106
|
+
}
|
|
946
1107
|
}
|
|
1108
|
+
currentToolIndex = null;
|
|
947
1109
|
}
|
|
948
|
-
|
|
1110
|
+
currentBlockType = null;
|
|
949
1111
|
}
|
|
950
|
-
if (event.type === "message_delta"
|
|
951
|
-
|
|
1112
|
+
if (event.type === "message_delta") {
|
|
1113
|
+
if (event.usage) {
|
|
1114
|
+
outputTokens = event.usage.output_tokens || 0;
|
|
1115
|
+
}
|
|
1116
|
+
const delta = event;
|
|
1117
|
+
if (delta.delta?.stop_reason) {
|
|
1118
|
+
stopReason = delta.delta.stop_reason;
|
|
1119
|
+
}
|
|
952
1120
|
}
|
|
953
1121
|
yield event;
|
|
954
1122
|
}
|
|
@@ -979,7 +1147,13 @@ function wrapAnthropicStream(stream, request, startTime) {
|
|
|
979
1147
|
outputTokens,
|
|
980
1148
|
durationMs,
|
|
981
1149
|
status: "success",
|
|
982
|
-
streaming: true
|
|
1150
|
+
streaming: true,
|
|
1151
|
+
// Extended fields
|
|
1152
|
+
stopReason,
|
|
1153
|
+
cacheReadTokens,
|
|
1154
|
+
cacheWriteTokens,
|
|
1155
|
+
firstTokenMs,
|
|
1156
|
+
thinking: thinkingChunks.length > 0 ? thinkingChunks.join("") : void 0
|
|
983
1157
|
});
|
|
984
1158
|
if (toolCalls.length > 0) {
|
|
985
1159
|
captureToolSpans(
|
|
@@ -1001,22 +1175,42 @@ function wrapAnthropicStream(stream, request, startTime) {
|
|
|
1001
1175
|
}
|
|
1002
1176
|
async function* wrapStream2(stream, request, startTime) {
|
|
1003
1177
|
const chunks = [];
|
|
1178
|
+
const thinkingChunks = [];
|
|
1004
1179
|
let inputTokens = 0;
|
|
1005
1180
|
let outputTokens = 0;
|
|
1181
|
+
let cacheReadTokens;
|
|
1182
|
+
let cacheWriteTokens;
|
|
1183
|
+
let stopReason;
|
|
1006
1184
|
let model = request.model || "unknown";
|
|
1007
1185
|
let error = null;
|
|
1186
|
+
let firstTokenMs;
|
|
1187
|
+
let firstTokenReceived = false;
|
|
1008
1188
|
const toolCalls = [];
|
|
1009
1189
|
let currentToolIndex = null;
|
|
1190
|
+
let currentBlockType = null;
|
|
1010
1191
|
try {
|
|
1011
1192
|
for await (const event of stream) {
|
|
1012
1193
|
if (event.type === "message_start" && event.message) {
|
|
1013
1194
|
model = event.message.model || model;
|
|
1014
1195
|
if (event.message.usage) {
|
|
1015
1196
|
inputTokens = event.message.usage.input_tokens || 0;
|
|
1197
|
+
cacheReadTokens = event.message.usage.cache_read_input_tokens;
|
|
1198
|
+
cacheWriteTokens = event.message.usage.cache_creation_input_tokens;
|
|
1016
1199
|
}
|
|
1017
1200
|
}
|
|
1201
|
+
if (event.type === "content_block_start" && event.content_block) {
|
|
1202
|
+
currentBlockType = event.content_block.type;
|
|
1203
|
+
}
|
|
1018
1204
|
if (event.type === "content_block_delta" && event.delta?.text) {
|
|
1019
|
-
|
|
1205
|
+
if (!firstTokenReceived) {
|
|
1206
|
+
firstTokenReceived = true;
|
|
1207
|
+
firstTokenMs = Date.now() - startTime;
|
|
1208
|
+
}
|
|
1209
|
+
if (currentBlockType === "thinking") {
|
|
1210
|
+
thinkingChunks.push(event.delta.text);
|
|
1211
|
+
} else {
|
|
1212
|
+
chunks.push(event.delta.text);
|
|
1213
|
+
}
|
|
1020
1214
|
}
|
|
1021
1215
|
if (event.type === "content_block_start" && event.content_block?.type === "tool_use") {
|
|
1022
1216
|
const block = event.content_block;
|
|
@@ -1036,18 +1230,27 @@ async function* wrapStream2(stream, request, startTime) {
|
|
|
1036
1230
|
tool.inputJson += event.delta.partial_json;
|
|
1037
1231
|
}
|
|
1038
1232
|
}
|
|
1039
|
-
if (event.type === "content_block_stop"
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1233
|
+
if (event.type === "content_block_stop") {
|
|
1234
|
+
if (currentToolIndex !== null) {
|
|
1235
|
+
const tool = toolCalls[currentToolIndex];
|
|
1236
|
+
if (tool && tool.inputJson) {
|
|
1237
|
+
try {
|
|
1238
|
+
tool.input = JSON.parse(tool.inputJson);
|
|
1239
|
+
} catch {
|
|
1240
|
+
}
|
|
1045
1241
|
}
|
|
1242
|
+
currentToolIndex = null;
|
|
1046
1243
|
}
|
|
1047
|
-
|
|
1244
|
+
currentBlockType = null;
|
|
1048
1245
|
}
|
|
1049
|
-
if (event.type === "message_delta"
|
|
1050
|
-
|
|
1246
|
+
if (event.type === "message_delta") {
|
|
1247
|
+
if (event.usage) {
|
|
1248
|
+
outputTokens = event.usage.output_tokens || 0;
|
|
1249
|
+
}
|
|
1250
|
+
const delta = event;
|
|
1251
|
+
if (delta.delta?.stop_reason) {
|
|
1252
|
+
stopReason = delta.delta.stop_reason;
|
|
1253
|
+
}
|
|
1051
1254
|
}
|
|
1052
1255
|
yield event;
|
|
1053
1256
|
}
|
|
@@ -1075,7 +1278,13 @@ async function* wrapStream2(stream, request, startTime) {
|
|
|
1075
1278
|
outputTokens,
|
|
1076
1279
|
durationMs,
|
|
1077
1280
|
status: "success",
|
|
1078
|
-
streaming: true
|
|
1281
|
+
streaming: true,
|
|
1282
|
+
// Extended fields
|
|
1283
|
+
stopReason,
|
|
1284
|
+
cacheReadTokens,
|
|
1285
|
+
cacheWriteTokens,
|
|
1286
|
+
firstTokenMs,
|
|
1287
|
+
thinking: thinkingChunks.length > 0 ? thinkingChunks.join("") : void 0
|
|
1079
1288
|
});
|
|
1080
1289
|
if (toolCalls.length > 0) {
|
|
1081
1290
|
captureToolSpans(
|
|
@@ -1088,13 +1297,19 @@ async function* wrapStream2(stream, request, startTime) {
|
|
|
1088
1297
|
}
|
|
1089
1298
|
function extractMessageResponse(response) {
|
|
1090
1299
|
const model = safeExtract(() => response.model ?? null, null);
|
|
1300
|
+
const stopReason = safeExtract(() => response.stop_reason ?? null, null);
|
|
1091
1301
|
const output = safeExtract(() => {
|
|
1092
1302
|
if (!response.content || !Array.isArray(response.content)) return null;
|
|
1093
1303
|
const textBlocks = response.content.filter((block) => block.type === "text" && block.text).map((block) => block.text);
|
|
1094
1304
|
return textBlocks.join("") || null;
|
|
1095
1305
|
}, null);
|
|
1306
|
+
const thinking = safeExtract(() => {
|
|
1307
|
+
if (!response.content || !Array.isArray(response.content)) return null;
|
|
1308
|
+
const thinkingBlocks = response.content.filter((block) => block.type === "thinking" && block.thinking).map((block) => block.thinking);
|
|
1309
|
+
return thinkingBlocks.join("\n\n") || null;
|
|
1310
|
+
}, null);
|
|
1096
1311
|
const tokens = extractTokens2(response);
|
|
1097
|
-
return { model, output, tokens };
|
|
1312
|
+
return { model, output, tokens, stopReason, thinking };
|
|
1098
1313
|
}
|
|
1099
1314
|
function extractTokens2(response) {
|
|
1100
1315
|
try {
|
|
@@ -1108,7 +1323,10 @@ function extractTokens2(response) {
|
|
|
1108
1323
|
return {
|
|
1109
1324
|
inputTokens: isValidNumber(inputTokens) ? inputTokens : 0,
|
|
1110
1325
|
outputTokens: isValidNumber(outputTokens) ? outputTokens : 0,
|
|
1111
|
-
totalTokens: (isValidNumber(inputTokens) ? inputTokens : 0) + (isValidNumber(outputTokens) ? outputTokens : 0)
|
|
1326
|
+
totalTokens: (isValidNumber(inputTokens) ? inputTokens : 0) + (isValidNumber(outputTokens) ? outputTokens : 0),
|
|
1327
|
+
// Cache tokens (Anthropic prompt caching)
|
|
1328
|
+
cacheReadTokens: isValidNumber(usage.cache_read_input_tokens) ? usage.cache_read_input_tokens : void 0,
|
|
1329
|
+
cacheWriteTokens: isValidNumber(usage.cache_creation_input_tokens) ? usage.cache_creation_input_tokens : void 0
|
|
1112
1330
|
};
|
|
1113
1331
|
} catch {
|
|
1114
1332
|
return null;
|
|
@@ -1188,11 +1406,12 @@ async function handleConverse(send, command) {
|
|
|
1188
1406
|
durationMs,
|
|
1189
1407
|
status: "success",
|
|
1190
1408
|
streaming: false,
|
|
1409
|
+
// Extended fields (Phase 7.1)
|
|
1410
|
+
stopReason: response.stopReason,
|
|
1411
|
+
cacheReadTokens: extracted.cacheReadTokens,
|
|
1412
|
+
cacheWriteTokens: extracted.cacheWriteTokens,
|
|
1191
1413
|
metadata: {
|
|
1192
|
-
stopReason: response.stopReason,
|
|
1193
1414
|
hasToolUse: extracted.hasToolUse,
|
|
1194
|
-
cacheReadTokens: extracted.cacheReadTokens,
|
|
1195
|
-
cacheWriteTokens: extracted.cacheWriteTokens,
|
|
1196
1415
|
latencyMs: response.metrics?.latencyMs
|
|
1197
1416
|
}
|
|
1198
1417
|
});
|
|
@@ -1242,10 +1461,17 @@ async function* wrapConverseStream(stream, input, startTime) {
|
|
|
1242
1461
|
let inputTokens = 0;
|
|
1243
1462
|
let outputTokens = 0;
|
|
1244
1463
|
let error = null;
|
|
1464
|
+
let stopReason;
|
|
1465
|
+
let firstTokenMs;
|
|
1466
|
+
let firstContentReceived = false;
|
|
1245
1467
|
const toolCalls = /* @__PURE__ */ new Map();
|
|
1246
1468
|
try {
|
|
1247
1469
|
for await (const event of stream) {
|
|
1248
|
-
if (event.contentBlockDelta?.delta?.text) {
|
|
1470
|
+
if (event.contentBlockDelta?.delta?.text && !firstContentReceived) {
|
|
1471
|
+
firstContentReceived = true;
|
|
1472
|
+
firstTokenMs = Date.now() - startTime;
|
|
1473
|
+
chunks.push(event.contentBlockDelta.delta.text);
|
|
1474
|
+
} else if (event.contentBlockDelta?.delta?.text) {
|
|
1249
1475
|
chunks.push(event.contentBlockDelta.delta.text);
|
|
1250
1476
|
}
|
|
1251
1477
|
if (event.contentBlockStart?.start?.toolUse) {
|
|
@@ -1262,6 +1488,9 @@ async function* wrapConverseStream(stream, input, startTime) {
|
|
|
1262
1488
|
tool.inputJson += event.contentBlockDelta.delta.toolUse.input;
|
|
1263
1489
|
}
|
|
1264
1490
|
}
|
|
1491
|
+
if (event.messageStop?.stopReason) {
|
|
1492
|
+
stopReason = event.messageStop.stopReason;
|
|
1493
|
+
}
|
|
1265
1494
|
if (event.metadata?.usage) {
|
|
1266
1495
|
inputTokens = event.metadata.usage.inputTokens || 0;
|
|
1267
1496
|
outputTokens = event.metadata.usage.outputTokens || 0;
|
|
@@ -1292,7 +1521,10 @@ async function* wrapConverseStream(stream, input, startTime) {
|
|
|
1292
1521
|
outputTokens,
|
|
1293
1522
|
durationMs,
|
|
1294
1523
|
status: "success",
|
|
1295
|
-
streaming: true
|
|
1524
|
+
streaming: true,
|
|
1525
|
+
// Extended fields (Phase 7.1)
|
|
1526
|
+
stopReason,
|
|
1527
|
+
firstTokenMs
|
|
1296
1528
|
});
|
|
1297
1529
|
if (toolCalls.size > 0) {
|
|
1298
1530
|
const tools = Array.from(toolCalls.values()).map((t) => {
|
|
@@ -2117,6 +2349,6 @@ function createObserve(defaultOptions) {
|
|
|
2117
2349
|
};
|
|
2118
2350
|
}
|
|
2119
2351
|
|
|
2120
|
-
export { captureSpan, createObserve, flush, init, isEnabled, observe };
|
|
2352
|
+
export { captureSpan, createObserve, flush, getTraceContext, init, isEnabled, observe, span, trace };
|
|
2121
2353
|
//# sourceMappingURL=index.mjs.map
|
|
2122
2354
|
//# sourceMappingURL=index.mjs.map
|