@link-assistant/agent 0.8.6 → 0.8.9
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/package.json +1 -1
- package/src/session/index.ts +62 -6
package/package.json
CHANGED
package/src/session/index.ts
CHANGED
|
@@ -408,9 +408,18 @@ export namespace Session {
|
|
|
408
408
|
}
|
|
409
409
|
|
|
410
410
|
try {
|
|
411
|
-
// Handle undefined/null
|
|
411
|
+
// Handle undefined/null gracefully by returning 0
|
|
412
|
+
// These are expected for optional fields like cachedInputTokens, reasoningTokens
|
|
413
|
+
// See: https://github.com/link-assistant/agent/issues/127
|
|
412
414
|
if (value === undefined || value === null) {
|
|
413
|
-
|
|
415
|
+
if (Flag.OPENCODE_VERBOSE) {
|
|
416
|
+
log.debug(() => ({
|
|
417
|
+
message: 'toNumber received undefined/null, returning 0',
|
|
418
|
+
context,
|
|
419
|
+
valueType: typeof value,
|
|
420
|
+
}));
|
|
421
|
+
}
|
|
422
|
+
return 0;
|
|
414
423
|
}
|
|
415
424
|
|
|
416
425
|
// Handle objects with a 'total' field (e.g., { total: 8707, noCache: 6339, cacheRead: 2368 })
|
|
@@ -538,6 +547,18 @@ export namespace Session {
|
|
|
538
547
|
return obj.reason;
|
|
539
548
|
}
|
|
540
549
|
|
|
550
|
+
// Handle AI SDK unified/raw format: {unified: "tool-calls", raw: "tool_calls"}
|
|
551
|
+
// See: https://github.com/link-assistant/agent/issues/129
|
|
552
|
+
if (typeof obj.unified === 'string') {
|
|
553
|
+
if (Flag.OPENCODE_VERBOSE) {
|
|
554
|
+
log.debug(() => ({
|
|
555
|
+
message: 'toFinishReason extracted unified from object',
|
|
556
|
+
result: obj.unified,
|
|
557
|
+
}));
|
|
558
|
+
}
|
|
559
|
+
return obj.unified;
|
|
560
|
+
}
|
|
561
|
+
|
|
541
562
|
// If we can't extract a specific field, return JSON representation
|
|
542
563
|
if (Flag.OPENCODE_VERBOSE) {
|
|
543
564
|
log.debug(() => ({
|
|
@@ -572,9 +593,28 @@ export namespace Session {
|
|
|
572
593
|
const safeNum = (n: number): number =>
|
|
573
594
|
Number.isNaN(n) || !Number.isFinite(n) ? 0 : n;
|
|
574
595
|
|
|
575
|
-
|
|
596
|
+
// Extract top-level cachedInputTokens
|
|
597
|
+
const topLevelCachedInputTokens = safeNum(
|
|
576
598
|
toNumber(input.usage.cachedInputTokens, 'cachedInputTokens')
|
|
577
599
|
);
|
|
600
|
+
|
|
601
|
+
// Some providers (e.g., opencode/grok-code) nest cacheRead inside inputTokens object
|
|
602
|
+
// e.g., inputTokens: { total: 12703, noCache: 12511, cacheRead: 192 }
|
|
603
|
+
// See: https://github.com/link-assistant/agent/issues/127
|
|
604
|
+
const inputTokensObj = input.usage.inputTokens;
|
|
605
|
+
const nestedCacheRead =
|
|
606
|
+
typeof inputTokensObj === 'object' && inputTokensObj !== null
|
|
607
|
+
? safeNum(
|
|
608
|
+
toNumber(
|
|
609
|
+
(inputTokensObj as { cacheRead?: unknown }).cacheRead,
|
|
610
|
+
'inputTokens.cacheRead'
|
|
611
|
+
)
|
|
612
|
+
)
|
|
613
|
+
: 0;
|
|
614
|
+
|
|
615
|
+
// Use top-level if available, otherwise fall back to nested
|
|
616
|
+
const cachedInputTokens = topLevelCachedInputTokens || nestedCacheRead;
|
|
617
|
+
|
|
578
618
|
const excludesCachedTokens = !!(
|
|
579
619
|
input.metadata?.['anthropic'] || input.metadata?.['bedrock']
|
|
580
620
|
);
|
|
@@ -595,12 +635,28 @@ export namespace Session {
|
|
|
595
635
|
)
|
|
596
636
|
);
|
|
597
637
|
|
|
638
|
+
// Extract reasoning tokens - some providers nest it inside outputTokens
|
|
639
|
+
// e.g., outputTokens: { total: 562, text: -805, reasoning: 1367 }
|
|
640
|
+
// See: https://github.com/link-assistant/agent/issues/127
|
|
641
|
+
const topLevelReasoningTokens = safeNum(
|
|
642
|
+
toNumber(input.usage?.reasoningTokens, 'reasoningTokens')
|
|
643
|
+
);
|
|
644
|
+
const outputTokensObj = input.usage.outputTokens;
|
|
645
|
+
const nestedReasoning =
|
|
646
|
+
typeof outputTokensObj === 'object' && outputTokensObj !== null
|
|
647
|
+
? safeNum(
|
|
648
|
+
toNumber(
|
|
649
|
+
(outputTokensObj as { reasoning?: unknown }).reasoning,
|
|
650
|
+
'outputTokens.reasoning'
|
|
651
|
+
)
|
|
652
|
+
)
|
|
653
|
+
: 0;
|
|
654
|
+
const reasoningTokens = topLevelReasoningTokens || nestedReasoning;
|
|
655
|
+
|
|
598
656
|
const tokens = {
|
|
599
657
|
input: Math.max(0, adjustedInputTokens), // Ensure non-negative
|
|
600
658
|
output: safeNum(toNumber(input.usage.outputTokens, 'outputTokens')),
|
|
601
|
-
reasoning:
|
|
602
|
-
toNumber(input.usage?.reasoningTokens, 'reasoningTokens')
|
|
603
|
-
),
|
|
659
|
+
reasoning: reasoningTokens,
|
|
604
660
|
cache: {
|
|
605
661
|
write: cacheWriteTokens,
|
|
606
662
|
read: cachedInputTokens,
|