@link-assistant/agent 0.8.18 → 0.8.19

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@link-assistant/agent",
3
- "version": "0.8.18",
3
+ "version": "0.8.19",
4
4
  "description": "A minimal, public domain AI CLI agent compatible with OpenCode's JSON interface. Bun-only runtime.",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
@@ -71,7 +71,7 @@
71
71
  "@standard-community/standard-json": "^0.3.5",
72
72
  "@standard-community/standard-openapi": "^0.2.9",
73
73
  "@zip.js/zip.js": "^2.8.10",
74
- "ai": "6.0.0-beta.99",
74
+ "ai": "^6.0.1",
75
75
  "chokidar": "^4.0.3",
76
76
  "clipboardy": "^5.0.0",
77
77
  "command-stream": "^0.7.1",
@@ -580,6 +580,27 @@ export namespace Session {
580
580
  metadata: z.custom<ProviderMetadata>().optional(),
581
581
  }),
582
582
  (input) => {
583
+ // Handle undefined or null usage gracefully
584
+ // Some providers (e.g., OpenCode with Kimi K2.5) may return incomplete usage data
585
+ // See: https://github.com/link-assistant/agent/issues/152
586
+ if (!input.usage) {
587
+ log.warn(() => ({
588
+ message: 'getUsage received undefined usage, returning zero values',
589
+ providerMetadata: input.metadata
590
+ ? JSON.stringify(input.metadata)
591
+ : 'none',
592
+ }));
593
+ return {
594
+ cost: 0,
595
+ tokens: {
596
+ input: 0,
597
+ output: 0,
598
+ reasoning: 0,
599
+ cache: { read: 0, write: 0 },
600
+ },
601
+ };
602
+ }
603
+
583
604
  // Log raw usage data in verbose mode for debugging
584
605
  if (Flag.OPENCODE_VERBOSE) {
585
606
  log.debug(() => ({
@@ -219,9 +219,17 @@ export namespace SessionProcessor {
219
219
  break;
220
220
 
221
221
  case 'finish-step':
222
+ // Safely handle missing or undefined usage data
223
+ // Some providers (e.g., OpenCode with Kimi K2.5) may return incomplete usage
224
+ // See: https://github.com/link-assistant/agent/issues/152
225
+ const safeUsage = value.usage ?? {
226
+ inputTokens: 0,
227
+ outputTokens: 0,
228
+ totalTokens: 0,
229
+ };
222
230
  const usage = Session.getUsage({
223
231
  model: input.model,
224
- usage: value.usage,
232
+ usage: safeUsage,
225
233
  metadata: value.providerMetadata,
226
234
  });
227
235
  // Use toFinishReason to safely convert object/string finishReason to string
@@ -322,6 +330,34 @@ export namespace SessionProcessor {
322
330
  }
323
331
  } catch (e) {
324
332
  log.error(() => ({ message: 'process', error: e }));
333
+
334
+ // Check for AI SDK usage-related TypeError (input_tokens undefined)
335
+ // This happens when providers return incomplete usage data
336
+ // See: https://github.com/link-assistant/agent/issues/152
337
+ if (
338
+ e instanceof TypeError &&
339
+ (e.message.includes('input_tokens') ||
340
+ e.message.includes('output_tokens') ||
341
+ e.message.includes("reading 'input_tokens'") ||
342
+ e.message.includes("reading 'output_tokens'"))
343
+ ) {
344
+ log.warn(() => ({
345
+ message:
346
+ 'Provider returned invalid usage data, continuing with zero usage',
347
+ errorMessage: e.message,
348
+ providerID: input.providerID,
349
+ }));
350
+ // Set default token values to prevent crash
351
+ input.assistantMessage.tokens = {
352
+ input: 0,
353
+ output: 0,
354
+ reasoning: 0,
355
+ cache: { read: 0, write: 0 },
356
+ };
357
+ // Continue processing instead of failing
358
+ continue;
359
+ }
360
+
325
361
  const error = MessageV2.fromError(e, {
326
362
  providerID: input.providerID,
327
363
  });