talon-agent 3.33.4 → 3.34.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.
Files changed (98) hide show
  1. package/package.json +5 -2
  2. package/src/app.ts +16 -8
  3. package/src/backend/claude-sdk/handler.ts +428 -415
  4. package/src/backend/claude-sdk/stream.ts +76 -53
  5. package/src/backend/codex/handler/message.ts +275 -366
  6. package/src/backend/codex/handler/rollout-accounting.ts +137 -0
  7. package/src/backend/openai-agents/handler/message.ts +282 -356
  8. package/src/backend/remote-server/chat-turn.ts +66 -122
  9. package/src/backend/remote-server/index.ts +4 -0
  10. package/src/backend/remote-server/mcp.ts +73 -9
  11. package/src/backend/remote-server/model-catalog/presentation.ts +269 -228
  12. package/src/backend/remote-server/sessions.ts +2 -2
  13. package/src/backend/remote-server/turn.ts +58 -55
  14. package/src/backend/shared/cache-telemetry.ts +17 -1
  15. package/src/backend/shared/handler-to-events.ts +11 -16
  16. package/src/backend/shared/index.ts +14 -15
  17. package/src/backend/shared/result-events.ts +30 -0
  18. package/src/backend/shared/turn-phases.ts +277 -0
  19. package/src/bootstrap.ts +120 -79
  20. package/src/cli/setup.ts +375 -349
  21. package/src/core/background/cron-spec.ts +273 -0
  22. package/src/core/background/heartbeat/agent.ts +167 -104
  23. package/src/core/background/triggers/exit.ts +19 -2
  24. package/src/core/background/triggers/resume.ts +14 -7
  25. package/src/core/background/triggers/state.ts +9 -0
  26. package/src/core/engine/backend-controller/pool.ts +2 -0
  27. package/src/core/engine/backend-controller/state.ts +25 -12
  28. package/src/core/engine/gateway-actions/cron.ts +28 -292
  29. package/src/core/engine/gateway-routes.ts +239 -0
  30. package/src/core/engine/gateway.ts +66 -238
  31. package/src/core/mcp-hub/child-transport.ts +215 -0
  32. package/src/core/mcp-hub/children.ts +72 -13
  33. package/src/core/mcp-hub/index.ts +32 -13
  34. package/src/core/models/active-model.ts +29 -6
  35. package/src/core/vfs/mounts/files.ts +128 -115
  36. package/src/core/weaver/shuttle.ts +33 -2
  37. package/src/core/weaver/weaver.ts +37 -6
  38. package/src/frontend/discord/callbacks/components/agent-buttons.ts +82 -0
  39. package/src/frontend/discord/callbacks/components/backend-select.ts +149 -0
  40. package/src/frontend/discord/callbacks/components/effort.ts +72 -0
  41. package/src/frontend/discord/callbacks/components/index.ts +120 -0
  42. package/src/frontend/discord/callbacks/components/metrics.ts +24 -0
  43. package/src/frontend/discord/callbacks/components/model-nav.ts +93 -0
  44. package/src/frontend/discord/callbacks/components/model-select.ts +118 -0
  45. package/src/frontend/discord/callbacks/components/model.ts +33 -0
  46. package/src/frontend/discord/callbacks/components/pulse.ts +93 -0
  47. package/src/frontend/discord/callbacks/components/settings.ts +243 -0
  48. package/src/frontend/discord/callbacks/components/types.ts +34 -0
  49. package/src/frontend/discord/callbacks/index.ts +4 -4
  50. package/src/frontend/discord/connection.ts +36 -0
  51. package/src/frontend/discord/diagnostics.ts +62 -0
  52. package/src/frontend/discord/guild-policy.ts +89 -0
  53. package/src/frontend/discord/index.ts +44 -305
  54. package/src/frontend/discord/outbound.ts +61 -0
  55. package/src/frontend/discord/ready.ts +73 -0
  56. package/src/frontend/discord/runtime.ts +55 -0
  57. package/src/frontend/native/chat-lifecycle.ts +39 -0
  58. package/src/frontend/native/chat-wire.ts +69 -0
  59. package/src/frontend/native/context.ts +106 -0
  60. package/src/frontend/native/control.ts +78 -0
  61. package/src/frontend/native/emit.ts +167 -0
  62. package/src/frontend/native/empty-chat-sweep.ts +50 -0
  63. package/src/frontend/native/handlers.ts +121 -0
  64. package/src/frontend/native/history.ts +101 -0
  65. package/src/frontend/native/index.ts +90 -1293
  66. package/src/frontend/native/media.ts +43 -0
  67. package/src/frontend/native/models.ts +221 -0
  68. package/src/frontend/native/queue.ts +47 -0
  69. package/src/frontend/native/reset.ts +50 -0
  70. package/src/frontend/native/routes/chats.ts +115 -0
  71. package/src/frontend/native/routes/daemon.ts +70 -0
  72. package/src/frontend/native/routes/host.ts +151 -0
  73. package/src/frontend/native/routes/index.ts +22 -0
  74. package/src/frontend/native/routes/mesh.ts +72 -0
  75. package/src/frontend/native/routes/models.ts +54 -0
  76. package/src/frontend/native/routes/params.ts +29 -0
  77. package/src/frontend/native/routes/pre-auth.ts +94 -0
  78. package/src/frontend/native/routes/table.ts +92 -0
  79. package/src/frontend/native/runtime.ts +109 -0
  80. package/src/frontend/native/server.ts +30 -555
  81. package/src/frontend/native/status.ts +26 -0
  82. package/src/frontend/native/tool-result.ts +48 -0
  83. package/src/frontend/native/turn.ts +341 -0
  84. package/src/frontend/telegram/admin.ts +75 -52
  85. package/src/frontend/whatsapp/access.ts +67 -0
  86. package/src/frontend/whatsapp/connection.ts +280 -0
  87. package/src/frontend/whatsapp/inbound.ts +327 -0
  88. package/src/frontend/whatsapp/index.ts +28 -599
  89. package/src/frontend/whatsapp/runtime.ts +74 -0
  90. package/src/storage/metrics.ts +18 -0
  91. package/src/storage/session-record.ts +29 -0
  92. package/src/storage/sessions.ts +24 -0
  93. package/src/storage/trigger-store.ts +8 -0
  94. package/src/util/boot-timer.ts +31 -0
  95. package/src/util/concurrency.ts +28 -0
  96. package/src/util/watchdog.ts +32 -7
  97. package/src/frontend/discord/callbacks/components.ts +0 -793
  98. package/src/frontend/discord/callbacks/shared.ts +0 -22
@@ -334,6 +334,79 @@ export function extractToolResults(msg: SDKUserMessage): ToolResultInfo[] {
334
334
  return results;
335
335
  }
336
336
 
337
+ /** Context fill of the last API iteration + whether the turn's first request hit the cache. */
338
+ function readContextFill(
339
+ state: StreamState,
340
+ usage: SDKResultMessage["usage"],
341
+ ): void {
342
+ if (
343
+ !usage ||
344
+ !Array.isArray(usage.iterations) ||
345
+ usage.iterations.length === 0
346
+ )
347
+ return;
348
+ const last = usage.iterations[usage.iterations.length - 1];
349
+ state.contextTokens =
350
+ (last.input_tokens ?? 0) +
351
+ (last.cache_read_input_tokens ?? 0) +
352
+ (last.cache_creation_input_tokens ?? 0);
353
+ // The same array answers a question the per-turn totals can't: whether
354
+ // the FIRST request of this turn read a cache or paid to write one.
355
+ state.cacheStats = turnCacheStats(usage.iterations);
356
+ }
357
+
358
+ /**
359
+ * Token counts from the ACTIVE model's usage only. modelUsage is keyed by
360
+ * the exact SDK model string (e.g. "sonnet[1m]") and holds cumulative
361
+ * session totals per model — summing all entries double-counts when
362
+ * switching models mid-session.
363
+ */
364
+ function readModelUsage(
365
+ state: StreamState,
366
+ modelUsage: Record<string, ModelUsage>,
367
+ sdkModel: string,
368
+ ): void {
369
+ // Drift check: modelUsage is keyed by the model that ACTUALLY served
370
+ // the turn. If none of the keys is (an alias of) the model we asked
371
+ // for, the API substituted — warn instead of burying it in the
372
+ // accounting line.
373
+ checkModelDrift(sdkModel, Object.keys(modelUsage ?? {}));
374
+ const mu = modelUsage[sdkModel] ?? Object.values(modelUsage).at(-1);
375
+ if (!mu) return;
376
+ state.sdkInputTokens = mu.inputTokens ?? 0;
377
+ state.sdkOutputTokens = mu.outputTokens ?? 0;
378
+ state.sdkCacheRead = mu.cacheReadInputTokens ?? 0;
379
+ state.sdkCacheWrite = mu.cacheCreationInputTokens ?? 0;
380
+ if (mu.contextWindow > 0) {
381
+ state.contextWindow = mu.contextWindow;
382
+ }
383
+ }
384
+
385
+ /**
386
+ * Failed turn. Two shapes (see StreamState.resultErrorText):
387
+ * - error subtype: no `result` field, but `errors[]` carries diagnostics.
388
+ * - success subtype with is_error: `result` (and the trailing assistant
389
+ * text) IS the API error message, e.g. "You've hit your weekly limit
390
+ * · resets Jul 10, 9am". Prefer that text — it's the user-facing one.
391
+ */
392
+ function readResultError(msg: SDKResultMessage, state: StreamState): void {
393
+ if (msg.subtype !== "success") {
394
+ const diagnostics = (msg.errors ?? [])
395
+ .filter((e) => typeof e === "string" && !e.startsWith("[ede_diagnostic]"))
396
+ .join("; ")
397
+ .slice(0, 500);
398
+ state.resultErrorText =
399
+ state.lastTrailingText.trim() ||
400
+ diagnostics ||
401
+ `Claude SDK turn failed (${msg.subtype})`;
402
+ } else if (msg.is_error) {
403
+ state.resultErrorText =
404
+ (typeof msg.result === "string" && msg.result.trim()) ||
405
+ state.lastTrailingText.trim() ||
406
+ "Claude SDK turn failed (API error)";
407
+ }
408
+ }
409
+
337
410
  /**
338
411
  * Process the final result message — extracts token counts, context info,
339
412
  * and API call counts from the typed SDK result.
@@ -350,39 +423,8 @@ export function processResultMessage(
350
423
  state.costUsd = msg.total_cost_usd;
351
424
  }
352
425
 
353
- // Context fill from last API iteration
354
- const usage = msg.usage;
355
- if (usage && Array.isArray(usage.iterations) && usage.iterations.length > 0) {
356
- const last = usage.iterations[usage.iterations.length - 1];
357
- state.contextTokens =
358
- (last.input_tokens ?? 0) +
359
- (last.cache_read_input_tokens ?? 0) +
360
- (last.cache_creation_input_tokens ?? 0);
361
- // The same array answers a question the per-turn totals can't: whether
362
- // the FIRST request of this turn read a cache or paid to write one.
363
- state.cacheStats = turnCacheStats(usage.iterations);
364
- }
365
-
366
- // Read token counts from the ACTIVE model's usage only.
367
- // modelUsage is keyed by the exact SDK model string (e.g. "sonnet[1m]")
368
- // and contains cumulative session totals per model — summing all entries
369
- // double-counts when switching models mid-session.
370
- const modelUsage: Record<string, ModelUsage> = msg.modelUsage;
371
- // Drift check: modelUsage is keyed by the model that ACTUALLY served
372
- // the turn. If none of the keys is (an alias of) the model we asked
373
- // for, the API substituted — warn instead of burying it in the
374
- // accounting line.
375
- checkModelDrift(sdkModel, Object.keys(modelUsage ?? {}));
376
- const mu = modelUsage[sdkModel] ?? Object.values(modelUsage).at(-1);
377
- if (mu) {
378
- state.sdkInputTokens = mu.inputTokens ?? 0;
379
- state.sdkOutputTokens = mu.outputTokens ?? 0;
380
- state.sdkCacheRead = mu.cacheReadInputTokens ?? 0;
381
- state.sdkCacheWrite = mu.cacheCreationInputTokens ?? 0;
382
- if (mu.contextWindow > 0) {
383
- state.contextWindow = mu.contextWindow;
384
- }
385
- }
426
+ readContextFill(state, msg.usage);
427
+ readModelUsage(state, msg.modelUsage, sdkModel);
386
428
 
387
429
  log(
388
430
  "agent",
@@ -400,26 +442,7 @@ export function processResultMessage(
400
442
  state.currentBlockText = msg.result;
401
443
  }
402
444
 
403
- // Failed turn. Two shapes (see StreamState.resultErrorText):
404
- // - error subtype: no `result` field, but `errors[]` carries diagnostics.
405
- // - success subtype with is_error: `result` (and the trailing assistant
406
- // text) IS the API error message, e.g. "You've hit your weekly limit
407
- // · resets Jul 10, 9am". Prefer that text — it's the user-facing one.
408
- if (msg.subtype !== "success") {
409
- const diagnostics = (msg.errors ?? [])
410
- .filter((e) => typeof e === "string" && !e.startsWith("[ede_diagnostic]"))
411
- .join("; ")
412
- .slice(0, 500);
413
- state.resultErrorText =
414
- state.lastTrailingText.trim() ||
415
- diagnostics ||
416
- `Claude SDK turn failed (${msg.subtype})`;
417
- } else if (msg.is_error) {
418
- state.resultErrorText =
419
- (typeof msg.result === "string" && msg.result.trim()) ||
420
- state.lastTrailingText.trim() ||
421
- "Claude SDK turn failed (API error)";
422
- }
445
+ readResultError(msg, state);
423
446
  }
424
447
 
425
448
  // ── Trailing-text fallback dedup ────────────────────────────────────────────