@genesislcap/ai-assistant 15.15.2 → 15.16.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 (58) hide show
  1. package/dist/ai-assistant.api.json +271 -2
  2. package/dist/ai-assistant.d.ts +90 -1
  3. package/dist/chat-driver.cjs +72 -0
  4. package/dist/chat-driver.cjs.map +2 -2
  5. package/dist/chat-driver.mjs +72 -0
  6. package/dist/chat-driver.mjs.map +2 -2
  7. package/dist/custom-elements.json +221 -97
  8. package/dist/dts/components/ai-driver/ai-driver.d.ts +11 -0
  9. package/dist/dts/components/ai-driver/ai-driver.d.ts.map +1 -1
  10. package/dist/dts/components/chat-driver/chat-driver.d.ts +31 -1
  11. package/dist/dts/components/chat-driver/chat-driver.d.ts.map +1 -1
  12. package/dist/dts/components/chat-interaction-wrapper/chat-interaction-wrapper.d.ts +10 -0
  13. package/dist/dts/components/chat-interaction-wrapper/chat-interaction-wrapper.d.ts.map +1 -1
  14. package/dist/dts/components/orchestrating-driver/orchestrating-driver.cost.test.d.ts +2 -0
  15. package/dist/dts/components/orchestrating-driver/orchestrating-driver.cost.test.d.ts.map +1 -0
  16. package/dist/dts/components/orchestrating-driver/orchestrating-driver.d.ts +3 -0
  17. package/dist/dts/components/orchestrating-driver/orchestrating-driver.d.ts.map +1 -1
  18. package/dist/dts/index.d.ts +1 -1
  19. package/dist/dts/index.d.ts.map +1 -1
  20. package/dist/dts/main/file-attachments.test.d.ts +2 -0
  21. package/dist/dts/main/file-attachments.test.d.ts.map +1 -0
  22. package/dist/dts/main/interaction-cost.test.d.ts +2 -0
  23. package/dist/dts/main/interaction-cost.test.d.ts.map +1 -0
  24. package/dist/dts/main/main.d.ts +27 -0
  25. package/dist/dts/main/main.d.ts.map +1 -1
  26. package/dist/dts/main/main.template.d.ts.map +1 -1
  27. package/dist/dts/react.d.ts +2 -1
  28. package/dist/dts/state/debug-event-log.d.ts +1 -1
  29. package/dist/dts/state/debug-event-log.d.ts.map +1 -1
  30. package/dist/dts/types/ai-chat-widget.d.ts +8 -0
  31. package/dist/dts/types/ai-chat-widget.d.ts.map +1 -1
  32. package/dist/esm/components/chat-driver/chat-driver.js +75 -1
  33. package/dist/esm/components/chat-driver/chat-driver.test.js +90 -0
  34. package/dist/esm/components/chat-interaction-wrapper/chat-interaction-wrapper.js +22 -0
  35. package/dist/esm/components/orchestrating-driver/orchestrating-driver.cost.test.js +76 -0
  36. package/dist/esm/components/orchestrating-driver/orchestrating-driver.js +14 -0
  37. package/dist/esm/main/file-attachments.test.js +164 -0
  38. package/dist/esm/main/interaction-cost.test.js +107 -0
  39. package/dist/esm/main/main.js +193 -21
  40. package/dist/esm/main/main.template.js +1 -0
  41. package/dist/esm/state/debug-event-log.js +6 -0
  42. package/dist/react.cjs +6 -1
  43. package/dist/react.mjs +6 -1
  44. package/dist/tsconfig.tsbuildinfo +1 -1
  45. package/package.json +17 -17
  46. package/src/components/ai-driver/ai-driver.ts +11 -0
  47. package/src/components/chat-driver/chat-driver.test.ts +109 -0
  48. package/src/components/chat-driver/chat-driver.ts +78 -1
  49. package/src/components/chat-interaction-wrapper/chat-interaction-wrapper.ts +29 -0
  50. package/src/components/orchestrating-driver/orchestrating-driver.cost.test.ts +107 -0
  51. package/src/components/orchestrating-driver/orchestrating-driver.ts +17 -0
  52. package/src/index.ts +4 -1
  53. package/src/main/file-attachments.test.ts +215 -0
  54. package/src/main/interaction-cost.test.ts +140 -0
  55. package/src/main/main.template.ts +1 -0
  56. package/src/main/main.ts +204 -22
  57. package/src/state/debug-event-log.ts +8 -0
  58. package/src/types/ai-chat-widget.ts +8 -0
@@ -3518,6 +3518,12 @@ var META_EVENT_IMPORTANCE = {
3518
3518
  "provider.selected": "normal",
3519
3519
  "interaction.requested": "normal",
3520
3520
  "interaction.resolved": "normal",
3521
+ // Bookkeeping about an already-finished turn; interesting when reconciling a session total.
3522
+ "interaction.external-cost": "normal",
3523
+ // Spend that was billed but could NOT be recorded (the message was trimmed/condensed away, or
3524
+ // the value was not real spend). 'high': it is the one way the session total goes quietly
3525
+ // wrong, so it must stand out when reconciling.
3526
+ "interaction.external-cost-dropped": "high",
3521
3527
  "external-diagnostics.folded": "normal",
3522
3528
  "session.cleared": "normal",
3523
3529
  "session.switched": "low",
@@ -5003,6 +5009,62 @@ Output format (strict):
5003
5009
  });
5004
5010
  });
5005
5011
  }
5012
+ /**
5013
+ * Add external (non-LLM) spend to an interaction's message AFTER it has resolved.
5014
+ *
5015
+ * **Why this exists separately from `resolveInteraction`.** A widget's spend reaches the session
5016
+ * total only through `InteractionResult.costUsd`, which is read exactly once — `resolveInteraction`
5017
+ * does its whole job inside `if (interaction)` and then deletes the entry from
5018
+ * `pendingInteractions`. That is correct for the resolution itself, but it assumes a widget stops
5019
+ * costing money when it resolves, and several deliberately do not: a widget that resolves EARLY so
5020
+ * the assistant stops waiting (options shown, a preview rendered) may stay interactive for minutes
5021
+ * afterwards and do more paid work on the user's behalf. Re-emitting `interaction-completed` does
5022
+ * not help — with the interaction gone from the map the call is a silent no-op — so that spend had
5023
+ * nowhere to go and was simply missing from the figure shown to the user.
5024
+ *
5025
+ * Additive by design: the caller reports a DELTA, not a running total, so repeated calls sum. It
5026
+ * touches only `externalCostUsd`; the recorded `interaction.resolved` payload is left exactly as
5027
+ * the resolution wrote it, because this is not a second resolution and must not read like one.
5028
+ *
5029
+ * Deliberately does NOT require the interaction to be pending, does not resurrect it, and has no
5030
+ * loading/turn side effects — this is bookkeeping about a turn that already happened.
5031
+ *
5032
+ * @param interactionId the interaction whose message owns the spend.
5033
+ * @param costUsd a positive delta in USD. Non-finite, zero and negative values are ignored.
5034
+ * @returns `true` when the spend was recorded; `false` when it was not — either the value was
5035
+ * not a positive finite amount, or the message is no longer in history (trimmed or condensed
5036
+ * away). A real outcome a caller may want to log rather than a failure to throw on; every
5037
+ * `false` also records an `interaction.external-cost-dropped` meta event here, so money can
5038
+ * never disappear without a trace.
5039
+ * @beta
5040
+ */
5041
+ recordExternalCost(interactionId, costUsd) {
5042
+ const drop = (reason) => {
5043
+ recordMetaEvent(this.sessionKey, "interaction.external-cost-dropped", {
5044
+ interactionId,
5045
+ costUsd,
5046
+ reason
5047
+ });
5048
+ return false;
5049
+ };
5050
+ if (!interactionId) return drop("no interactionId");
5051
+ if (typeof costUsd !== "number" || !Number.isFinite(costUsd) || costUsd <= 0) {
5052
+ return drop("not a positive finite amount");
5053
+ }
5054
+ const idx = this.history.findIndex((m) => m.interaction?.interactionId === interactionId);
5055
+ if (idx === -1) return drop("interaction message no longer in history");
5056
+ this.history[idx] = {
5057
+ ...this.history[idx],
5058
+ externalCostUsd: (this.history[idx].externalCostUsd ?? 0) + costUsd
5059
+ };
5060
+ recordMetaEvent(this.sessionKey, "interaction.external-cost", { interactionId, costUsd });
5061
+ this.dispatchEvent(
5062
+ new CustomEvent("external-cost-recorded", {
5063
+ detail: { interactionId, costUsd }
5064
+ })
5065
+ );
5066
+ return true;
5067
+ }
5006
5068
  /**
5007
5069
  * Resolve a pending interaction. The wrapper component calls this on completion.
5008
5070
  * Marks the interaction message as resolved so it renders read-only on re-render.
@@ -6442,10 +6504,20 @@ var OrchestratingDriver = class extends EventTarget {
6442
6504
  new CustomEvent("provider-changed", { detail: e.detail })
6443
6505
  );
6444
6506
  });
6507
+ this.chatDriver.addEventListener("external-cost-recorded", (e) => {
6508
+ this.dispatchEvent(
6509
+ new CustomEvent("external-cost-recorded", { detail: e.detail })
6510
+ );
6511
+ });
6445
6512
  }
6446
6513
  resolveInteraction(interactionId, result) {
6447
6514
  this.chatDriver.resolveInteraction(interactionId, result);
6448
6515
  }
6516
+ /** Delegated for the same reason as `resolveInteraction`: the history that owns the
6517
+ * interaction — and therefore the cost — lives on the wrapped driver, not here. */
6518
+ recordExternalCost(interactionId, costUsd) {
6519
+ return this.chatDriver.recordExternalCost(interactionId, costUsd);
6520
+ }
6449
6521
  getInteractionContext(interactionId) {
6450
6522
  return this.chatDriver.getInteractionContext(interactionId);
6451
6523
  }