@link-assistant/agent 0.8.6 → 0.8.7
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 +50 -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 })
|
|
@@ -572,9 +581,28 @@ export namespace Session {
|
|
|
572
581
|
const safeNum = (n: number): number =>
|
|
573
582
|
Number.isNaN(n) || !Number.isFinite(n) ? 0 : n;
|
|
574
583
|
|
|
575
|
-
|
|
584
|
+
// Extract top-level cachedInputTokens
|
|
585
|
+
const topLevelCachedInputTokens = safeNum(
|
|
576
586
|
toNumber(input.usage.cachedInputTokens, 'cachedInputTokens')
|
|
577
587
|
);
|
|
588
|
+
|
|
589
|
+
// Some providers (e.g., opencode/grok-code) nest cacheRead inside inputTokens object
|
|
590
|
+
// e.g., inputTokens: { total: 12703, noCache: 12511, cacheRead: 192 }
|
|
591
|
+
// See: https://github.com/link-assistant/agent/issues/127
|
|
592
|
+
const inputTokensObj = input.usage.inputTokens;
|
|
593
|
+
const nestedCacheRead =
|
|
594
|
+
typeof inputTokensObj === 'object' && inputTokensObj !== null
|
|
595
|
+
? safeNum(
|
|
596
|
+
toNumber(
|
|
597
|
+
(inputTokensObj as { cacheRead?: unknown }).cacheRead,
|
|
598
|
+
'inputTokens.cacheRead'
|
|
599
|
+
)
|
|
600
|
+
)
|
|
601
|
+
: 0;
|
|
602
|
+
|
|
603
|
+
// Use top-level if available, otherwise fall back to nested
|
|
604
|
+
const cachedInputTokens = topLevelCachedInputTokens || nestedCacheRead;
|
|
605
|
+
|
|
578
606
|
const excludesCachedTokens = !!(
|
|
579
607
|
input.metadata?.['anthropic'] || input.metadata?.['bedrock']
|
|
580
608
|
);
|
|
@@ -595,12 +623,28 @@ export namespace Session {
|
|
|
595
623
|
)
|
|
596
624
|
);
|
|
597
625
|
|
|
626
|
+
// Extract reasoning tokens - some providers nest it inside outputTokens
|
|
627
|
+
// e.g., outputTokens: { total: 562, text: -805, reasoning: 1367 }
|
|
628
|
+
// See: https://github.com/link-assistant/agent/issues/127
|
|
629
|
+
const topLevelReasoningTokens = safeNum(
|
|
630
|
+
toNumber(input.usage?.reasoningTokens, 'reasoningTokens')
|
|
631
|
+
);
|
|
632
|
+
const outputTokensObj = input.usage.outputTokens;
|
|
633
|
+
const nestedReasoning =
|
|
634
|
+
typeof outputTokensObj === 'object' && outputTokensObj !== null
|
|
635
|
+
? safeNum(
|
|
636
|
+
toNumber(
|
|
637
|
+
(outputTokensObj as { reasoning?: unknown }).reasoning,
|
|
638
|
+
'outputTokens.reasoning'
|
|
639
|
+
)
|
|
640
|
+
)
|
|
641
|
+
: 0;
|
|
642
|
+
const reasoningTokens = topLevelReasoningTokens || nestedReasoning;
|
|
643
|
+
|
|
598
644
|
const tokens = {
|
|
599
645
|
input: Math.max(0, adjustedInputTokens), // Ensure non-negative
|
|
600
646
|
output: safeNum(toNumber(input.usage.outputTokens, 'outputTokens')),
|
|
601
|
-
reasoning:
|
|
602
|
-
toNumber(input.usage?.reasoningTokens, 'reasoningTokens')
|
|
603
|
-
),
|
|
647
|
+
reasoning: reasoningTokens,
|
|
604
648
|
cache: {
|
|
605
649
|
write: cacheWriteTokens,
|
|
606
650
|
read: cachedInputTokens,
|