@genesislcap/ai-assistant 15.12.0 → 15.13.0

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 (50) hide show
  1. package/dist/ai-assistant.api.json +245 -3
  2. package/dist/ai-assistant.d.ts +127 -7
  3. package/dist/chat-driver.cjs +79 -13
  4. package/dist/chat-driver.cjs.map +2 -2
  5. package/dist/chat-driver.mjs +76 -12
  6. package/dist/chat-driver.mjs.map +2 -2
  7. package/dist/custom-elements.json +452 -359
  8. package/dist/dts/chat-driver-node.d.ts +2 -2
  9. package/dist/dts/chat-driver-node.d.ts.map +1 -1
  10. package/dist/dts/components/chat-driver/chat-driver.d.ts +45 -1
  11. package/dist/dts/components/chat-driver/chat-driver.d.ts.map +1 -1
  12. package/dist/dts/components/chat-driver/chat-driver.turn-usage.test.d.ts +2 -0
  13. package/dist/dts/components/chat-driver/chat-driver.turn-usage.test.d.ts.map +1 -0
  14. package/dist/dts/main/main.d.ts +20 -1
  15. package/dist/dts/main/main.d.ts.map +1 -1
  16. package/dist/dts/state/debug-event-log.d.ts.map +1 -1
  17. package/dist/dts/state/persistence/diagnostics.d.ts +65 -8
  18. package/dist/dts/state/persistence/diagnostics.d.ts.map +1 -1
  19. package/dist/dts/state/persistence/index.d.ts +1 -1
  20. package/dist/dts/state/persistence/index.d.ts.map +1 -1
  21. package/dist/dts/state/persistence/session-persister.d.ts +4 -3
  22. package/dist/dts/state/persistence/session-persister.d.ts.map +1 -1
  23. package/dist/dts/utils/sum-usage.d.ts +20 -0
  24. package/dist/dts/utils/sum-usage.d.ts.map +1 -1
  25. package/dist/esm/chat-driver-node.js +12 -2
  26. package/dist/esm/components/chat-driver/chat-driver.js +60 -5
  27. package/dist/esm/components/chat-driver/chat-driver.turn-usage.test.js +268 -0
  28. package/dist/esm/main/main.js +53 -28
  29. package/dist/esm/state/debug-event-log.js +7 -2
  30. package/dist/esm/state/persistence/diagnostics.js +79 -16
  31. package/dist/esm/state/persistence/diagnostics.test.js +174 -1
  32. package/dist/esm/state/persistence/index.js +1 -1
  33. package/dist/esm/state/persistence/session-persister.js +13 -5
  34. package/dist/esm/state/persistence/session-persister.test.js +31 -0
  35. package/dist/esm/utils/sum-usage.js +43 -0
  36. package/dist/esm/utils/sum-usage.test.js +45 -1
  37. package/dist/tsconfig.tsbuildinfo +1 -1
  38. package/package.json +17 -17
  39. package/src/chat-driver-node.ts +12 -2
  40. package/src/components/chat-driver/chat-driver.ts +107 -6
  41. package/src/components/chat-driver/chat-driver.turn-usage.test.ts +362 -0
  42. package/src/main/main.ts +52 -23
  43. package/src/state/debug-event-log.ts +7 -2
  44. package/src/state/persistence/diagnostics.test.ts +208 -1
  45. package/src/state/persistence/diagnostics.ts +117 -15
  46. package/src/state/persistence/index.ts +1 -1
  47. package/src/state/persistence/session-persister.test.ts +37 -0
  48. package/src/state/persistence/session-persister.ts +13 -5
  49. package/src/utils/sum-usage.test.ts +52 -1
  50. package/src/utils/sum-usage.ts +45 -0
@@ -3555,6 +3555,24 @@ function addUsage(a, b) {
3555
3555
  outputTokens: a.outputTokens + b.outputTokens
3556
3556
  };
3557
3557
  }
3558
+ function messageUsage(m) {
3559
+ if (m.cost == null && m.externalCostUsd == null && m.inputTokens == null && m.outputTokens == null && m.cacheReadTokens == null && m.cacheWriteTokens == null) {
3560
+ return void 0;
3561
+ }
3562
+ const cacheReadTokens = m.cacheReadTokens ?? 0;
3563
+ const cacheWriteTokens = m.cacheWriteTokens ?? 0;
3564
+ return {
3565
+ costUsd: (m.cost ?? 0) + (m.externalCostUsd ?? 0),
3566
+ // The uncached REMAINDER, clamped — the same arithmetic `accumulate` below applies,
3567
+ // for the same reasons. The two are deliberately separate implementations (that walk
3568
+ // mutates one accumulator rather than allocating per message) and must agree;
3569
+ // `sum-usage.test.ts` pins them together.
3570
+ uncachedInputTokens: Math.max(0, (m.inputTokens ?? 0) - cacheReadTokens - cacheWriteTokens),
3571
+ cacheReadTokens,
3572
+ cacheWriteTokens,
3573
+ outputTokens: m.outputTokens ?? 0
3574
+ };
3575
+ }
3558
3576
  function sumUsage(messages) {
3559
3577
  const total = emptyUsage();
3560
3578
  accumulate(messages, total);
@@ -4128,7 +4146,14 @@ var ChatDriver = class _ChatDriver extends EventTarget {
4128
4146
  if (resolvedName !== this.lastDispatchedProviderName) {
4129
4147
  this.lastDispatchedProviderName = resolvedName;
4130
4148
  recordMetaEvent(this.sessionKey, "provider.selected", {
4149
+ // `provider` is the registry SLOT (a tier name like 'high'), kept under that key
4150
+ // for compatibility; `model` and `vendor` are what it resolved to. Recording all
4151
+ // three is the difference between "the agent switched to its high tier" and
4152
+ // knowing which model that actually was — a tier can be repointed mid-session,
4153
+ // and a slot name alone cannot distinguish anthropic from gemini.
4131
4154
  provider: resolvedName,
4155
+ model: status.model,
4156
+ vendor: status.provider,
4132
4157
  agent: this.activeAgentName
4133
4158
  });
4134
4159
  this.dispatchEvent(
@@ -4267,6 +4292,10 @@ var ChatDriver = class _ChatDriver extends EventTarget {
4267
4292
  * Push one snapshot to the ring buffer. Called inside `runToolLoop` just
4268
4293
  * before each LLM call — that's the latest point where the prompt, tool
4269
4294
  * surface, and agent state line up with what the model is about to see.
4295
+ *
4296
+ * Returns the pushed object so the caller can back-fill what only the response
4297
+ * knows (`usage`). Mutating it after the fact is safe whether or not the ring
4298
+ * buffer has since evicted it — an evicted snapshot is simply no longer exported.
4270
4299
  */
4271
4300
  recordTurnSnapshot(resolvedSystemPrompt, temperature, toolChoice, tailContext) {
4272
4301
  let agentSnapshot;
@@ -4279,7 +4308,7 @@ var ChatDriver = class _ChatDriver extends EventTarget {
4279
4308
  }
4280
4309
  const turnIndex = String(this.globalTurnIndex);
4281
4310
  this.globalTurnIndex += 1;
4282
- this.turnSnapshots.push({
4311
+ const snapshot = {
4283
4312
  turnIndex,
4284
4313
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
4285
4314
  agentName: this.activeAgentName,
@@ -4290,10 +4319,12 @@ var ChatDriver = class _ChatDriver extends EventTarget {
4290
4319
  temperature,
4291
4320
  toolChoice,
4292
4321
  agentSnapshot
4293
- });
4322
+ };
4323
+ this.turnSnapshots.push(snapshot);
4294
4324
  if (this.turnSnapshots.length > this.maxTurnSnapshots) {
4295
4325
  this.turnSnapshots.shift();
4296
4326
  }
4327
+ return snapshot;
4297
4328
  }
4298
4329
  /**
4299
4330
  * Optional transform applied to conversation history immediately before each LLM request.
@@ -5221,7 +5252,12 @@ Output format (strict):
5221
5252
  ${tailBody}
5222
5253
  </system-reminder>` : void 0;
5223
5254
  const effectiveToolChoice = resolvedToolChoice ?? (this.isSubAgent ? "required" : void 0);
5224
- this.recordTurnSnapshot(systemPrompt, resolvedTemperature, effectiveToolChoice, tailContext);
5255
+ const turnSnapshot = this.recordTurnSnapshot(
5256
+ systemPrompt,
5257
+ resolvedTemperature,
5258
+ effectiveToolChoice,
5259
+ tailContext
5260
+ );
5225
5261
  const userInputForCall = currentInput;
5226
5262
  const attachmentsForCall = currentAttachments;
5227
5263
  currentInput = "";
@@ -5257,6 +5293,12 @@ ${tailBody}
5257
5293
  fallbacks: this.activeFallbacks
5258
5294
  };
5259
5295
  const activeProvider = await this.resolveProviderForTurn(promptCtx);
5296
+ if (this.lastResolvedProviderName !== void 0) {
5297
+ turnSnapshot.providerName = this.lastResolvedProviderName;
5298
+ }
5299
+ if (this.lastResolvedProvider !== void 0)
5300
+ turnSnapshot.provider = this.lastResolvedProvider;
5301
+ if (this.lastResolvedModel !== void 0) turnSnapshot.model = this.lastResolvedModel;
5260
5302
  let response;
5261
5303
  try {
5262
5304
  response = await activeProvider.chat(historyForCall, userInputForCall, options);
@@ -5374,6 +5416,8 @@ ${tailBody}
5374
5416
  if (this.lastResolvedProviderName !== void 0) {
5375
5417
  response.providerName = this.lastResolvedProviderName;
5376
5418
  }
5419
+ turnSnapshot.usage = messageUsage(response);
5420
+ if (response.model !== void 0) turnSnapshot.model = response.model;
5377
5421
  const isThinkingStep = response.content && response.toolCalls?.length;
5378
5422
  const isEmptyResponse = !response.content?.trim() && !response.toolCalls?.length;
5379
5423
  const isRefusal = response.responseMeta?.finishReason === "refusal";
@@ -5419,7 +5463,14 @@ ${tailBody}
5419
5463
  return this.turnDone(failureReason2);
5420
5464
  } else {
5421
5465
  const { reasoning, ...rest } = response;
5422
- const displayOnly = { cost: void 0, inputTokens: void 0, outputTokens: void 0 };
5466
+ const displayOnly = {
5467
+ cost: void 0,
5468
+ externalCostUsd: void 0,
5469
+ inputTokens: void 0,
5470
+ outputTokens: void 0,
5471
+ cacheReadTokens: void 0,
5472
+ cacheWriteTokens: void 0
5473
+ };
5423
5474
  if (reasoning) {
5424
5475
  this.appendToHistory({
5425
5476
  ...rest,
@@ -6617,23 +6668,30 @@ function buildTimelineEntries(input) {
6617
6668
  }
6618
6669
 
6619
6670
  // src/state/persistence/diagnostics.ts
6671
+ function turnIdentity(entry) {
6672
+ return `turn::${String(entry.turnIndex ?? "")}::${entry.timestamp ?? ""}::${String(entry.agentName ?? "")}`;
6673
+ }
6620
6674
  var KIND_RANK = { event: 0, turn: 1, message: 2 };
6621
6675
  var UNKNOWN_KIND_RANK = 99;
6622
6676
  function assembleDebugLog(entries, readme) {
6623
- const seen = /* @__PURE__ */ new Set();
6677
+ const seenAt = /* @__PURE__ */ new Map();
6624
6678
  let latestMeta;
6625
6679
  const timeline = [];
6626
6680
  for (const entry of entries) {
6627
- const id = JSON.stringify(entry);
6628
- if (seen.has(id)) continue;
6629
- seen.add(id);
6630
6681
  if (entry.kind === "meta-snapshot") {
6631
6682
  if (!latestMeta || (entry.timestamp ?? "") >= (latestMeta.timestamp ?? "")) {
6632
6683
  latestMeta = entry;
6633
6684
  }
6634
- } else {
6635
- timeline.push(entry);
6685
+ continue;
6636
6686
  }
6687
+ const id = entry.kind === "turn" ? turnIdentity(entry) : JSON.stringify(entry);
6688
+ const at = seenAt.get(id);
6689
+ if (at !== void 0) {
6690
+ if (entry.usage && !timeline[at].usage) timeline[at] = entry;
6691
+ continue;
6692
+ }
6693
+ seenAt.set(id, timeline.length);
6694
+ timeline.push(entry);
6637
6695
  }
6638
6696
  timeline.sort((a, b) => {
6639
6697
  const ta = a.timestamp ?? "";
@@ -6642,7 +6700,11 @@ function assembleDebugLog(entries, readme) {
6642
6700
  if (ta > tb) return 1;
6643
6701
  return (KIND_RANK[a.kind] ?? UNKNOWN_KIND_RANK) - (KIND_RANK[b.kind] ?? UNKNOWN_KIND_RANK);
6644
6702
  });
6645
- return { readme, timeline, meta: latestMeta?.meta };
6703
+ const context = latestMeta?.meta?.context;
6704
+ return { readme, sessionUsage: context?.sessionUsage, timeline, meta: latestMeta?.meta };
6705
+ }
6706
+ function withFreshMetaSnapshot(stored, fresh) {
6707
+ return [...stored.filter((e) => e.kind !== "meta-snapshot"), fresh];
6646
6708
  }
6647
6709
  export {
6648
6710
  ANTHROPIC_CACHE_READ_MULTIPLIER,
@@ -6677,11 +6739,13 @@ export {
6677
6739
  geminiTokenCost,
6678
6740
  getMetaEvents,
6679
6741
  isObservableAIProviderRegistry,
6742
+ messageUsage,
6680
6743
  restoreMachine,
6681
6744
  strictFallbackAgent,
6682
6745
  sumUsage,
6683
6746
  totalTokens,
6684
6747
  usageRows,
6685
- vendorOfModel
6748
+ vendorOfModel,
6749
+ withFreshMetaSnapshot
6686
6750
  };
6687
6751
  //# sourceMappingURL=chat-driver.mjs.map