@genesislcap/ai-assistant 15.19.0 → 15.19.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 (288) hide show
  1. package/package.json +17 -18
  2. package/api-extractor.json +0 -11
  3. package/dist/dts/components/chat-driver/chat-driver.compact.test.d.ts +0 -2
  4. package/dist/dts/components/chat-driver/chat-driver.compact.test.d.ts.map +0 -1
  5. package/dist/dts/components/chat-driver/chat-driver.invocation-scope.test.d.ts +0 -2
  6. package/dist/dts/components/chat-driver/chat-driver.invocation-scope.test.d.ts.map +0 -1
  7. package/dist/dts/components/chat-driver/chat-driver.test.d.ts +0 -2
  8. package/dist/dts/components/chat-driver/chat-driver.test.d.ts.map +0 -1
  9. package/dist/dts/components/chat-driver/chat-driver.thinking-policy.test.d.ts +0 -2
  10. package/dist/dts/components/chat-driver/chat-driver.thinking-policy.test.d.ts.map +0 -1
  11. package/dist/dts/components/chat-driver/chat-driver.trace-capture.test.d.ts +0 -2
  12. package/dist/dts/components/chat-driver/chat-driver.trace-capture.test.d.ts.map +0 -1
  13. package/dist/dts/components/chat-driver/chat-driver.turn-usage.test.d.ts +0 -2
  14. package/dist/dts/components/chat-driver/chat-driver.turn-usage.test.d.ts.map +0 -1
  15. package/dist/dts/components/chat-interaction-wrapper/chat-interaction-wrapper.test.d.ts +0 -2
  16. package/dist/dts/components/chat-interaction-wrapper/chat-interaction-wrapper.test.d.ts.map +0 -1
  17. package/dist/dts/components/orchestrating-driver/orchestrating-driver.budget.test.d.ts +0 -2
  18. package/dist/dts/components/orchestrating-driver/orchestrating-driver.budget.test.d.ts.map +0 -1
  19. package/dist/dts/components/orchestrating-driver/orchestrating-driver.cost.test.d.ts +0 -2
  20. package/dist/dts/components/orchestrating-driver/orchestrating-driver.cost.test.d.ts.map +0 -1
  21. package/dist/dts/components/orchestrating-driver/orchestrating-driver.pin.test.d.ts +0 -2
  22. package/dist/dts/components/orchestrating-driver/orchestrating-driver.pin.test.d.ts.map +0 -1
  23. package/dist/dts/components/settings-modal/settings-modal.styles.test.d.ts +0 -2
  24. package/dist/dts/components/settings-modal/settings-modal.styles.test.d.ts.map +0 -1
  25. package/dist/dts/components/settings-modal/settings-modal.template.test.d.ts +0 -2
  26. package/dist/dts/components/settings-modal/settings-modal.template.test.d.ts.map +0 -1
  27. package/dist/dts/config/define-stateful-agent.test.d.ts +0 -2
  28. package/dist/dts/config/define-stateful-agent.test.d.ts.map +0 -1
  29. package/dist/dts/config/validate-providers.test.d.ts +0 -2
  30. package/dist/dts/config/validate-providers.test.d.ts.map +0 -1
  31. package/dist/dts/main/blocked-state.test.d.ts +0 -2
  32. package/dist/dts/main/blocked-state.test.d.ts.map +0 -1
  33. package/dist/dts/main/budget-meter.test.d.ts +0 -2
  34. package/dist/dts/main/budget-meter.test.d.ts.map +0 -1
  35. package/dist/dts/main/cost-session-banking.test.d.ts +0 -2
  36. package/dist/dts/main/cost-session-banking.test.d.ts.map +0 -1
  37. package/dist/dts/main/file-attachments.test.d.ts +0 -2
  38. package/dist/dts/main/file-attachments.test.d.ts.map +0 -1
  39. package/dist/dts/main/interaction-cost.test.d.ts +0 -2
  40. package/dist/dts/main/interaction-cost.test.d.ts.map +0 -1
  41. package/dist/dts/main/main.styles.test.d.ts +0 -2
  42. package/dist/dts/main/main.styles.test.d.ts.map +0 -1
  43. package/dist/dts/main/persistence-broken-sources.test.d.ts +0 -2
  44. package/dist/dts/main/persistence-broken-sources.test.d.ts.map +0 -1
  45. package/dist/dts/main/popout-interaction-gate.test.d.ts +0 -2
  46. package/dist/dts/main/popout-interaction-gate.test.d.ts.map +0 -1
  47. package/dist/dts/state/ai-assistant-slice.test.d.ts +0 -2
  48. package/dist/dts/state/ai-assistant-slice.test.d.ts.map +0 -1
  49. package/dist/dts/state/debug-event-log.test.d.ts +0 -2
  50. package/dist/dts/state/debug-event-log.test.d.ts.map +0 -1
  51. package/dist/dts/state/driver-registry.test.d.ts +0 -2
  52. package/dist/dts/state/driver-registry.test.d.ts.map +0 -1
  53. package/dist/dts/state/interaction-context.test.d.ts +0 -2
  54. package/dist/dts/state/interaction-context.test.d.ts.map +0 -1
  55. package/dist/dts/state/persistence/diagnostics-cursors.test.d.ts +0 -2
  56. package/dist/dts/state/persistence/diagnostics-cursors.test.d.ts.map +0 -1
  57. package/dist/dts/state/persistence/diagnostics.test.d.ts +0 -2
  58. package/dist/dts/state/persistence/diagnostics.test.d.ts.map +0 -1
  59. package/dist/dts/state/persistence/session-persistence-provider.test.d.ts +0 -2
  60. package/dist/dts/state/persistence/session-persistence-provider.test.d.ts.map +0 -1
  61. package/dist/dts/state/persistence/session-persistence.integration.test.d.ts +0 -2
  62. package/dist/dts/state/persistence/session-persistence.integration.test.d.ts.map +0 -1
  63. package/dist/dts/state/persistence/session-persister.test.d.ts +0 -2
  64. package/dist/dts/state/persistence/session-persister.test.d.ts.map +0 -1
  65. package/dist/dts/state/persistence/session-snapshot.test.d.ts +0 -2
  66. package/dist/dts/state/persistence/session-snapshot.test.d.ts.map +0 -1
  67. package/dist/dts/state/persistence/stateful-restore.e2e.test.d.ts +0 -2
  68. package/dist/dts/state/persistence/stateful-restore.e2e.test.d.ts.map +0 -1
  69. package/dist/dts/utils/animation-exclusivity.test.d.ts +0 -2
  70. package/dist/dts/utils/animation-exclusivity.test.d.ts.map +0 -1
  71. package/dist/dts/utils/collect-session-models.test.d.ts +0 -2
  72. package/dist/dts/utils/collect-session-models.test.d.ts.map +0 -1
  73. package/dist/dts/utils/condense-history.test.d.ts +0 -2
  74. package/dist/dts/utils/condense-history.test.d.ts.map +0 -1
  75. package/dist/dts/utils/cost-session-history.test.d.ts +0 -2
  76. package/dist/dts/utils/cost-session-history.test.d.ts.map +0 -1
  77. package/dist/dts/utils/derive-cost-session-title.test.d.ts +0 -2
  78. package/dist/dts/utils/derive-cost-session-title.test.d.ts.map +0 -1
  79. package/dist/dts/utils/flatten-sub-agent-messages.test.d.ts +0 -2
  80. package/dist/dts/utils/flatten-sub-agent-messages.test.d.ts.map +0 -1
  81. package/dist/dts/utils/history-transform.test.d.ts +0 -2
  82. package/dist/dts/utils/history-transform.test.d.ts.map +0 -1
  83. package/dist/dts/utils/message-partition.test.d.ts +0 -2
  84. package/dist/dts/utils/message-partition.test.d.ts.map +0 -1
  85. package/dist/dts/utils/resolve-cost-history-config.test.d.ts +0 -2
  86. package/dist/dts/utils/resolve-cost-history-config.test.d.ts.map +0 -1
  87. package/dist/dts/utils/resolve-preference-baseline.test.d.ts +0 -2
  88. package/dist/dts/utils/resolve-preference-baseline.test.d.ts.map +0 -1
  89. package/dist/dts/utils/strip-agent-handlers.test.d.ts +0 -2
  90. package/dist/dts/utils/strip-agent-handlers.test.d.ts.map +0 -1
  91. package/dist/dts/utils/sum-costs.test.d.ts +0 -2
  92. package/dist/dts/utils/sum-costs.test.d.ts.map +0 -1
  93. package/dist/dts/utils/sum-tokens.test.d.ts +0 -2
  94. package/dist/dts/utils/sum-tokens.test.d.ts.map +0 -1
  95. package/dist/dts/utils/sum-usage.test.d.ts +0 -2
  96. package/dist/dts/utils/sum-usage.test.d.ts.map +0 -1
  97. package/dist/dts/utils/usage-rows.test.d.ts +0 -2
  98. package/dist/dts/utils/usage-rows.test.d.ts.map +0 -1
  99. package/dist/esm/components/chat-driver/chat-driver.compact.test.js +0 -93
  100. package/dist/esm/components/chat-driver/chat-driver.invocation-scope.test.js +0 -238
  101. package/dist/esm/components/chat-driver/chat-driver.test.js +0 -2770
  102. package/dist/esm/components/chat-driver/chat-driver.thinking-policy.test.js +0 -137
  103. package/dist/esm/components/chat-driver/chat-driver.trace-capture.test.js +0 -200
  104. package/dist/esm/components/chat-driver/chat-driver.turn-usage.test.js +0 -268
  105. package/dist/esm/components/chat-interaction-wrapper/chat-interaction-wrapper.test.js +0 -104
  106. package/dist/esm/components/orchestrating-driver/orchestrating-driver.budget.test.js +0 -312
  107. package/dist/esm/components/orchestrating-driver/orchestrating-driver.cost.test.js +0 -76
  108. package/dist/esm/components/orchestrating-driver/orchestrating-driver.pin.test.js +0 -61
  109. package/dist/esm/components/settings-modal/settings-modal.styles.test.js +0 -80
  110. package/dist/esm/components/settings-modal/settings-modal.template.test.js +0 -91
  111. package/dist/esm/config/define-stateful-agent.test.js +0 -53
  112. package/dist/esm/config/validate-providers.test.js +0 -100
  113. package/dist/esm/main/blocked-state.test.js +0 -1065
  114. package/dist/esm/main/budget-meter.test.js +0 -359
  115. package/dist/esm/main/cost-session-banking.test.js +0 -538
  116. package/dist/esm/main/file-attachments.test.js +0 -164
  117. package/dist/esm/main/interaction-cost.test.js +0 -107
  118. package/dist/esm/main/main.styles.test.js +0 -161
  119. package/dist/esm/main/persistence-broken-sources.test.js +0 -180
  120. package/dist/esm/main/popout-interaction-gate.test.js +0 -54
  121. package/dist/esm/state/ai-assistant-slice.test.js +0 -229
  122. package/dist/esm/state/debug-event-log.test.js +0 -117
  123. package/dist/esm/state/driver-registry.test.js +0 -55
  124. package/dist/esm/state/interaction-context.test.js +0 -78
  125. package/dist/esm/state/persistence/diagnostics-cursors.test.js +0 -30
  126. package/dist/esm/state/persistence/diagnostics.test.js +0 -280
  127. package/dist/esm/state/persistence/session-persistence-provider.test.js +0 -110
  128. package/dist/esm/state/persistence/session-persistence.integration.test.js +0 -113
  129. package/dist/esm/state/persistence/session-persister.test.js +0 -613
  130. package/dist/esm/state/persistence/session-snapshot.test.js +0 -256
  131. package/dist/esm/state/persistence/stateful-restore.e2e.test.js +0 -158
  132. package/dist/esm/utils/animation-exclusivity.test.js +0 -52
  133. package/dist/esm/utils/collect-session-models.test.js +0 -53
  134. package/dist/esm/utils/condense-history.test.js +0 -547
  135. package/dist/esm/utils/cost-session-history.test.js +0 -174
  136. package/dist/esm/utils/derive-cost-session-title.test.js +0 -37
  137. package/dist/esm/utils/flatten-sub-agent-messages.test.js +0 -139
  138. package/dist/esm/utils/history-transform.test.js +0 -158
  139. package/dist/esm/utils/message-partition.test.js +0 -90
  140. package/dist/esm/utils/resolve-cost-history-config.test.js +0 -32
  141. package/dist/esm/utils/resolve-preference-baseline.test.js +0 -69
  142. package/dist/esm/utils/strip-agent-handlers.test.js +0 -81
  143. package/dist/esm/utils/sum-costs.test.js +0 -114
  144. package/dist/esm/utils/sum-tokens.test.js +0 -51
  145. package/dist/esm/utils/sum-usage.test.js +0 -164
  146. package/dist/esm/utils/usage-rows.test.js +0 -189
  147. package/dist/tsconfig.tsbuildinfo +0 -1
  148. package/license.txt +0 -46
  149. package/sandbox/tsconfig.json +0 -8
  150. package/src/channel/ai-activity-bus.ts +0 -209
  151. package/src/channel/ai-activity-channel.ts +0 -146
  152. package/src/chat-driver-node.ts +0 -159
  153. package/src/components/activity-halo/activity-halo.ts +0 -106
  154. package/src/components/agent-picker/agent-picker.constants.ts +0 -2
  155. package/src/components/agent-picker/agent-picker.styles.ts +0 -24
  156. package/src/components/agent-picker/agent-picker.template.ts +0 -54
  157. package/src/components/agent-picker/agent-picker.ts +0 -99
  158. package/src/components/agent-picker/index.ts +0 -1
  159. package/src/components/ai-driver/ai-driver.ts +0 -166
  160. package/src/components/ai-driver/index.ts +0 -1
  161. package/src/components/chat-bubble/chat-bubble.styles.ts +0 -194
  162. package/src/components/chat-bubble/chat-bubble.template.ts +0 -67
  163. package/src/components/chat-bubble/chat-bubble.ts +0 -436
  164. package/src/components/chat-bubble/index.ts +0 -1
  165. package/src/components/chat-driver/align-event-globals.ts +0 -23
  166. package/src/components/chat-driver/chat-driver.compact.test.ts +0 -131
  167. package/src/components/chat-driver/chat-driver.invocation-scope.test.ts +0 -285
  168. package/src/components/chat-driver/chat-driver.test.ts +0 -3679
  169. package/src/components/chat-driver/chat-driver.thinking-policy.test.ts +0 -185
  170. package/src/components/chat-driver/chat-driver.trace-capture.test.ts +0 -251
  171. package/src/components/chat-driver/chat-driver.ts +0 -3925
  172. package/src/components/chat-driver/chat-driver.turn-usage.test.ts +0 -362
  173. package/src/components/chat-driver/index.ts +0 -1
  174. package/src/components/chat-interaction-wrapper/chat-interaction-wrapper.styles.ts +0 -7
  175. package/src/components/chat-interaction-wrapper/chat-interaction-wrapper.template.ts +0 -6
  176. package/src/components/chat-interaction-wrapper/chat-interaction-wrapper.test.ts +0 -144
  177. package/src/components/chat-interaction-wrapper/chat-interaction-wrapper.ts +0 -243
  178. package/src/components/chat-interaction-wrapper/index.ts +0 -3
  179. package/src/components/chat-markdown/chat-markdown.ts +0 -89
  180. package/src/components/chat-markdown/index.ts +0 -1
  181. package/src/components/flowing-waves-indicator.ts +0 -286
  182. package/src/components/halo-overlay.ts +0 -184
  183. package/src/components/orchestrating-driver/index.ts +0 -1
  184. package/src/components/orchestrating-driver/orchestrating-driver.budget.test.ts +0 -438
  185. package/src/components/orchestrating-driver/orchestrating-driver.cost.test.ts +0 -107
  186. package/src/components/orchestrating-driver/orchestrating-driver.pin.test.ts +0 -96
  187. package/src/components/orchestrating-driver/orchestrating-driver.ts +0 -813
  188. package/src/components/plasma-orb-indicator.ts +0 -281
  189. package/src/components/popout-manager/index.ts +0 -1
  190. package/src/components/popout-manager/popout-manager.ts +0 -212
  191. package/src/components/settings-modal/index.ts +0 -2
  192. package/src/components/settings-modal/settings-modal.styles.test.ts +0 -94
  193. package/src/components/settings-modal/settings-modal.styles.ts +0 -853
  194. package/src/components/settings-modal/settings-modal.template.test.ts +0 -124
  195. package/src/components/settings-modal/settings-modal.template.ts +0 -943
  196. package/src/components/waves-indicator.ts +0 -241
  197. package/src/config/config.ts +0 -608
  198. package/src/config/define-stateful-agent.test.ts +0 -64
  199. package/src/config/define-stateful-agent.ts +0 -642
  200. package/src/config/fallback-agents.ts +0 -29
  201. package/src/config/index.ts +0 -2
  202. package/src/config/validate-providers.test.ts +0 -148
  203. package/src/config/validate-providers.ts +0 -58
  204. package/src/index.ts +0 -29
  205. package/src/main/blocked-state.test.ts +0 -1444
  206. package/src/main/budget-meter.test.ts +0 -477
  207. package/src/main/cost-session-banking.test.ts +0 -679
  208. package/src/main/file-attachments.test.ts +0 -215
  209. package/src/main/index.ts +0 -3
  210. package/src/main/interaction-cost.test.ts +0 -140
  211. package/src/main/main.styles.test.ts +0 -216
  212. package/src/main/main.styles.ts +0 -995
  213. package/src/main/main.template.ts +0 -1119
  214. package/src/main/main.ts +0 -5432
  215. package/src/main/main.types.ts +0 -225
  216. package/src/main/persistence-broken-sources.test.ts +0 -219
  217. package/src/main/popout-interaction-gate.test.ts +0 -87
  218. package/src/provider/ai-provider-switcher.ts +0 -40
  219. package/src/provider/assistant-app-settings.ts +0 -84
  220. package/src/state/ai-assistant-slice.test.ts +0 -336
  221. package/src/state/ai-assistant-slice.ts +0 -604
  222. package/src/state/debug-event-log.test.ts +0 -154
  223. package/src/state/debug-event-log.ts +0 -358
  224. package/src/state/driver-registry.test.ts +0 -70
  225. package/src/state/driver-registry.ts +0 -79
  226. package/src/state/interaction-context.test.ts +0 -90
  227. package/src/state/interaction-context.ts +0 -101
  228. package/src/state/persistence/build-timeline-entries.ts +0 -66
  229. package/src/state/persistence/diagnostics-cursors.test.ts +0 -53
  230. package/src/state/persistence/diagnostics-cursors.ts +0 -80
  231. package/src/state/persistence/diagnostics.test.ts +0 -346
  232. package/src/state/persistence/diagnostics.ts +0 -220
  233. package/src/state/persistence/index.ts +0 -10
  234. package/src/state/persistence/persister-registry.ts +0 -55
  235. package/src/state/persistence/session-persistence-provider.test.ts +0 -136
  236. package/src/state/persistence/session-persistence-provider.ts +0 -226
  237. package/src/state/persistence/session-persistence.integration.test.ts +0 -141
  238. package/src/state/persistence/session-persister.test.ts +0 -787
  239. package/src/state/persistence/session-persister.ts +0 -917
  240. package/src/state/persistence/session-snapshot.test.ts +0 -352
  241. package/src/state/persistence/session-snapshot.ts +0 -344
  242. package/src/state/persistence/stateful-restore.e2e.test.ts +0 -229
  243. package/src/state/session-store.ts +0 -56
  244. package/src/styles/ai-colours.ts +0 -30
  245. package/src/styles/menu.ts +0 -187
  246. package/src/styles/settings-section.ts +0 -40
  247. package/src/suggestions/chat-suggestions.ts +0 -186
  248. package/src/tags/index.ts +0 -1
  249. package/src/types/ai-chat-widget.ts +0 -67
  250. package/src/types/interaction-context.ts +0 -82
  251. package/src/utils/animated-panel-toggle.ts +0 -62
  252. package/src/utils/animation-exclusivity.test.ts +0 -72
  253. package/src/utils/animation-exclusivity.ts +0 -40
  254. package/src/utils/banked-usage-baselines.ts +0 -90
  255. package/src/utils/collect-session-models.test.ts +0 -82
  256. package/src/utils/collect-session-models.ts +0 -65
  257. package/src/utils/condense-history.test.ts +0 -746
  258. package/src/utils/condense-history.ts +0 -448
  259. package/src/utils/cost-session-history.test.ts +0 -226
  260. package/src/utils/cost-session-history.ts +0 -218
  261. package/src/utils/derive-cost-session-title.test.ts +0 -63
  262. package/src/utils/derive-cost-session-title.ts +0 -76
  263. package/src/utils/flatten-sub-agent-messages.test.ts +0 -163
  264. package/src/utils/flatten-sub-agent-messages.ts +0 -88
  265. package/src/utils/format-usd.ts +0 -26
  266. package/src/utils/history-transform.test.ts +0 -228
  267. package/src/utils/history-transform.ts +0 -163
  268. package/src/utils/index.ts +0 -3
  269. package/src/utils/logger.ts +0 -3
  270. package/src/utils/message-partition.test.ts +0 -129
  271. package/src/utils/message-partition.ts +0 -115
  272. package/src/utils/resolve-cost-history-config.test.ts +0 -38
  273. package/src/utils/resolve-cost-history-config.ts +0 -38
  274. package/src/utils/resolve-preference-baseline.test.ts +0 -84
  275. package/src/utils/resolve-preference-baseline.ts +0 -80
  276. package/src/utils/strip-agent-handlers.test.ts +0 -99
  277. package/src/utils/strip-agent-handlers.ts +0 -53
  278. package/src/utils/sum-costs.test.ts +0 -136
  279. package/src/utils/sum-costs.ts +0 -18
  280. package/src/utils/sum-tokens.test.ts +0 -93
  281. package/src/utils/sum-tokens.ts +0 -68
  282. package/src/utils/sum-usage.test.ts +0 -191
  283. package/src/utils/sum-usage.ts +0 -208
  284. package/src/utils/tool-fold.ts +0 -181
  285. package/src/utils/usage-rows.test.ts +0 -237
  286. package/src/utils/usage-rows.ts +0 -187
  287. package/src/utils/with-timeout.ts +0 -24
  288. package/tsconfig.json +0 -9
@@ -1,280 +0,0 @@
1
- import { assert, createLogicSuite } from '@genesislcap/foundation-testing';
2
- import { assembleDebugLog, diagnosticsMessageKey, withFreshMetaSnapshot, } from './diagnostics';
3
- // GENC-1351 §5.8: `assembleDebugLog` reassembles the forward-only diagnostics
4
- // stream back into the `{ readme, timeline, meta }` debug-log shape — timeline
5
- // sorted by timestamp, meta-snapshots pulled out with the latest winning.
6
- const README = ['read me'];
7
- const Suite = createLogicSuite('assembleDebugLog');
8
- Suite('sorts the timeline by timestamp, tie-breaking event → turn → message', () => {
9
- const entries = [
10
- { kind: 'message', timestamp: '2026-01-01T00:00:02.000Z', content: 'later msg' },
11
- { kind: 'turn', timestamp: '2026-01-01T00:00:01.000Z', turnIndex: '0' },
12
- { kind: 'event', timestamp: '2026-01-01T00:00:01.000Z', type: 'turn.start' },
13
- { kind: 'message', timestamp: '2026-01-01T00:00:01.000Z', content: 'first msg' },
14
- ];
15
- const { timeline } = assembleDebugLog(entries, README);
16
- // Co-timestamped @ …01: event, then turn, then message; the …02 message last.
17
- assert.equal(timeline.map((e) => e.kind), ['event', 'turn', 'message', 'message']);
18
- assert.is(timeline[3].content, 'later msg');
19
- });
20
- Suite('pulls meta-snapshots out of the timeline and surfaces the latest as `meta`', () => {
21
- const entries = [
22
- { kind: 'meta-snapshot', timestamp: '2026-01-01T00:00:01.000Z', meta: { model: 'old' } },
23
- { kind: 'message', timestamp: '2026-01-01T00:00:02.000Z', content: 'hi' },
24
- { kind: 'meta-snapshot', timestamp: '2026-01-01T00:00:03.000Z', meta: { model: 'new' } },
25
- ];
26
- const { timeline, meta } = assembleDebugLog(entries, README);
27
- assert.equal(timeline.map((e) => e.kind), ['message'], 'meta-snapshots do not leak into the timeline');
28
- assert.equal(meta, { model: 'new' }, 'the newest meta-snapshot surfaces as top-level meta');
29
- });
30
- Suite('re-prepends the passed readme and tolerates an empty stream', () => {
31
- const empty = assembleDebugLog([], README);
32
- assert.is(empty.readme, README);
33
- assert.equal(empty.timeline, []);
34
- assert.is(empty.meta, undefined, 'no meta-snapshot → undefined meta');
35
- });
36
- Suite('reassembles two loads into one lifetime timeline (the stitch)', () => {
37
- // Load 1's appended entries + load 2's — as loadDiagnostics would return them,
38
- // in arbitrary order — stitch back chronologically.
39
- const load2 = [
40
- { kind: 'message', timestamp: '2026-01-01T00:10:00.000Z', content: 'reload msg' },
41
- { kind: 'meta-snapshot', timestamp: '2026-01-01T00:10:00.000Z', meta: { load: 2 } },
42
- ];
43
- const load1 = [
44
- { kind: 'message', timestamp: '2026-01-01T00:00:00.000Z', content: 'first msg' },
45
- { kind: 'meta-snapshot', timestamp: '2026-01-01T00:00:00.000Z', meta: { load: 1 } },
46
- ];
47
- const { timeline, meta } = assembleDebugLog([...load2, ...load1], README);
48
- assert.equal(timeline.filter((e) => e.kind === 'message').map((e) => e.content), ['first msg', 'reload msg'], 'messages ordered across loads regardless of input order');
49
- assert.equal(meta, { load: 2 }, 'newest load’s meta-snapshot surfaces');
50
- });
51
- Suite('collapses exact-duplicate entries but keeps genuinely-distinct ones', () => {
52
- // Two element instances (bubble + panel) can each append the same message, and a
53
- // reload's second instance can re-append it — byte-identical copies. Two real
54
- // `assistant.connected` (from two instances) differ by `index` and must be kept.
55
- const msg = {
56
- kind: 'message',
57
- timestamp: '2026-01-01T00:00:01.000Z',
58
- role: 'user',
59
- content: 'hi',
60
- };
61
- const connA = {
62
- kind: 'event',
63
- timestamp: '2026-01-01T00:00:00.000Z',
64
- type: 'assistant.connected',
65
- index: 0,
66
- };
67
- const connB = Object.assign(Object.assign({}, connA), { index: 1 });
68
- const { timeline } = assembleDebugLog([msg, connA, Object.assign({}, msg), connB, connA], README);
69
- assert.is(timeline.filter((e) => e.kind === 'message').length, 1, 'identical message collapsed');
70
- assert.is(timeline.filter((e) => e.type === 'assistant.connected').length, 2, 'two distinct connects (different index) kept; the repeated connA collapsed');
71
- });
72
- Suite('lifts the newest snapshot’s session usage to the top of the log', () => {
73
- // The four buckets + USD are the headline of a cost investigation, and `meta` is a
74
- // large block to go digging in — so they surface at the top level. Same object, not a
75
- // second derivation, and taken from the SAME snapshot that becomes `meta`.
76
- const usage = {
77
- costUsd: 1.25,
78
- uncachedInputTokens: 1000,
79
- cacheReadTokens: 9000,
80
- cacheWriteTokens: 500,
81
- outputTokens: 300,
82
- };
83
- const entries = [
84
- {
85
- kind: 'meta-snapshot',
86
- timestamp: '2026-01-01T00:00:01.000Z',
87
- meta: { context: { sessionUsage: Object.assign(Object.assign({}, usage), { costUsd: 0.01 }) } },
88
- },
89
- {
90
- kind: 'meta-snapshot',
91
- timestamp: '2026-01-01T00:00:09.000Z',
92
- meta: { context: { sessionUsage: usage } },
93
- },
94
- ];
95
- assert.equal(assembleDebugLog(entries, README).sessionUsage, usage);
96
- });
97
- Suite('leaves session usage undefined when no snapshot carries it', () => {
98
- // A stream with no meta-snapshot, or one written before the field existed. Absent
99
- // rather than zeroed: "not recorded" must not read as "this session spent nothing".
100
- assert.is(assembleDebugLog([], README).sessionUsage, undefined);
101
- const noContext = [
102
- { kind: 'meta-snapshot', timestamp: '2026-01-01T00:00:01.000Z', meta: { host: 'localhost' } },
103
- ];
104
- assert.is(assembleDebugLog(noContext, README).sessionUsage, undefined);
105
- });
106
- Suite('collapses the turn pair even when its rendered systemPrompt differs', () => {
107
- // The pair is produced by two separate flushes, and `buildTimelineEntries` renders
108
- // `systemPrompt` relative to the preceding snapshots — so if the snapshot holding the
109
- // full prompt is evicted from the ring buffer between the two, the surviving turn
110
- // renders its prompt in full where the earlier copy had the '<repeated>' marker. Any
111
- // identity derived from the serialized entry breaks here and the log shows one model
112
- // call as two turns, one unpriced. Identity is turnIndex + timestamp + agentName.
113
- const unpriced = {
114
- kind: 'turn',
115
- turnIndex: '7',
116
- timestamp: '2026-01-01T00:00:01.000Z',
117
- agentName: 'Trade Operations',
118
- systemPrompt: '<repeated — identical to turn 0>',
119
- toolNames: [],
120
- };
121
- const priced = Object.assign(Object.assign({}, unpriced), { systemPrompt: 'the full prompt, now that turn 0 has been evicted', usage: {
122
- costUsd: 0.5,
123
- uncachedInputTokens: 100,
124
- cacheReadTokens: 0,
125
- cacheWriteTokens: 0,
126
- outputTokens: 20,
127
- } });
128
- const turns = assembleDebugLog([unpriced, priced], README).timeline.filter((e) => e.kind === 'turn');
129
- assert.is(turns.length, 1, 'still one model call');
130
- assert.equal(turns[0].usage, priced.usage, 'and it is the priced copy');
131
- });
132
- Suite('keeps same-index turns from different loads and different sub-agents apart', () => {
133
- // `turnIndex` restarts at '0' on every page load, so a lifetime log holds one turn '0'
134
- // per load; two sub-agents invoked in one parent turn share the index prefix and are
135
- // separated by `agentName` (see `forwardSubAgentSnapshots`).
136
- const load1 = {
137
- kind: 'turn',
138
- turnIndex: '0',
139
- timestamp: '2026-01-01T00:00:01.000Z',
140
- agentName: 'Booker',
141
- toolNames: [],
142
- };
143
- const load2 = Object.assign(Object.assign({}, load1), { timestamp: '2026-01-02T09:00:00.000Z' });
144
- const sibling = Object.assign(Object.assign({}, load1), { turnIndex: '3-1', agentName: 'Planner' });
145
- const cousin = Object.assign(Object.assign({}, sibling), { agentName: 'Grounding' });
146
- const turns = assembleDebugLog([load1, load2, sibling, cousin], README).timeline.filter((e) => e.kind === 'turn');
147
- assert.is(turns.length, 4, 'four distinct calls, none collapsed');
148
- });
149
- Suite('collapses the unpriced and priced copies of one turn onto the priced one', () => {
150
- // A turn entry is persisted when it is created (before its model call) and again once
151
- // `usage` is back-filled, so a stitched stream carries both. They are ONE model call
152
- // and must read as one — with the cost, or the re-emit gained nothing.
153
- const unpriced = {
154
- kind: 'turn',
155
- turnIndex: '0',
156
- timestamp: '2026-01-01T00:00:01.000Z',
157
- toolNames: [],
158
- };
159
- const priced = Object.assign(Object.assign({}, unpriced), { usage: {
160
- costUsd: 0.5,
161
- uncachedInputTokens: 100,
162
- cacheReadTokens: 0,
163
- cacheWriteTokens: 0,
164
- outputTokens: 20,
165
- } });
166
- for (const order of [
167
- [unpriced, priced],
168
- [priced, unpriced],
169
- ]) {
170
- const turns = assembleDebugLog(order, README).timeline.filter((e) => e.kind === 'turn');
171
- assert.is(turns.length, 1, 'one turn, not two');
172
- assert.equal(turns[0].usage, priced.usage, 'the priced copy wins regardless of stream order');
173
- }
174
- });
175
- Suite('keeps two genuinely-different turns that differ only in usage', () => {
176
- // The collapse keys on everything EXCEPT usage, so distinct calls stay distinct — they
177
- // differ in timestamp (and turnIndex) whatever else they share.
178
- const a = {
179
- kind: 'turn',
180
- turnIndex: '0',
181
- timestamp: '2026-01-01T00:00:01.000Z',
182
- toolNames: [],
183
- };
184
- const b = Object.assign(Object.assign({}, a), { turnIndex: '1', timestamp: '2026-01-01T00:00:02.000Z' });
185
- const turns = assembleDebugLog([a, b], README).timeline.filter((e) => e.kind === 'turn');
186
- assert.is(turns.length, 2);
187
- });
188
- Suite.run();
189
- // The download path's swap: a stored stream's `meta-snapshot`s replaced by an export-time
190
- // one. This is the fix for a SILENT bug — the persisted stream only re-appends that block
191
- // when the config signature changes, so a stitched lifetime log reported the totals frozen
192
- // at the session's first flush (near-zero spend against a transcript full of priced
193
- // messages) and nothing about it looked wrong.
194
- const FreshSuite = createLogicSuite('withFreshMetaSnapshot');
195
- const storedStream = [
196
- {
197
- kind: 'meta-snapshot',
198
- timestamp: '2026-01-01T00:00:00.000Z',
199
- meta: { context: { sessionUsage: { costUsd: 0.01 } } },
200
- dedupSignature: 'cfg-1',
201
- },
202
- { kind: 'message', timestamp: '2026-01-01T00:00:01.000Z', role: 'user', content: 'hi' },
203
- { kind: 'turn', turnIndex: '0', timestamp: '2026-01-01T00:00:02.000Z', toolNames: [] },
204
- { kind: 'event', index: 0, timestamp: '2026-01-01T00:00:03.000Z', type: 'turn.end' },
205
- ];
206
- const freshSnapshot = {
207
- kind: 'meta-snapshot',
208
- timestamp: '2026-01-01T02:00:00.000Z',
209
- meta: {
210
- context: {
211
- sessionUsage: {
212
- costUsd: 1.25,
213
- uncachedInputTokens: 1000,
214
- cacheReadTokens: 9000,
215
- cacheWriteTokens: 500,
216
- outputTokens: 300,
217
- },
218
- },
219
- },
220
- dedupSignature: 'cfg-1',
221
- };
222
- FreshSuite('reports the export-time totals, not the frozen stored ones', () => {
223
- var _a, _b;
224
- const log = assembleDebugLog(withFreshMetaSnapshot(storedStream, freshSnapshot), README);
225
- assert.is((_a = log.sessionUsage) === null || _a === void 0 ? void 0 : _a.costUsd, 1.25, 'the fresh snapshot supplies the totals');
226
- assert.is((_b = log.sessionUsage) === null || _b === void 0 ? void 0 : _b.cacheReadTokens, 9000);
227
- assert.equal(log.meta, freshSnapshot.meta, 'and the whole meta block is the fresh one');
228
- });
229
- FreshSuite('keeps every non-snapshot entry', () => {
230
- const timeline = assembleDebugLog(withFreshMetaSnapshot(storedStream, freshSnapshot), README).timeline;
231
- assert.equal(timeline.map((e) => e.kind), ['message', 'turn', 'event'], 'the conversation is untouched — only the snapshots are swapped');
232
- });
233
- FreshSuite('wins even when the stored snapshot claims a later time', () => {
234
- var _a;
235
- // A stream written on another machine can carry a skewed clock, and reassembly keeps
236
- // whichever snapshot claims the later timestamp — so the stale one must be REMOVED
237
- // rather than out-timestamped.
238
- const skewed = [
239
- Object.assign(Object.assign({}, storedStream[0]), { timestamp: '2099-01-01T00:00:00.000Z' }),
240
- ...storedStream.slice(1),
241
- ];
242
- const log = assembleDebugLog(withFreshMetaSnapshot(skewed, freshSnapshot), README);
243
- assert.is((_a = log.sessionUsage) === null || _a === void 0 ? void 0 : _a.costUsd, 1.25);
244
- });
245
- FreshSuite.run();
246
- // GENC-1461: the reasoning/narration/answer split (GENC-1411) emits several messages from ONE model
247
- // response, so they share `timestamp` + `role` + `subAgentOf`. The message identity key must still
248
- // tell them apart — otherwise the forward-capture dedup treats them as one and drops all but the
249
- // first (a server generation's answer message vanished from the persisted download while its
250
- // reasoning survived).
251
- const KeySuite = createLogicSuite('diagnosticsMessageKey');
252
- KeySuite('gives co-timestamped split messages (reasoning vs answer) distinct keys', () => {
253
- const base = {
254
- kind: 'message',
255
- role: 'assistant',
256
- timestamp: '2026-01-01T00:00:05.000Z',
257
- };
258
- const reasoning = Object.assign(Object.assign({}, base), { category: 'reasoning', content: 'thinking…' });
259
- const answer = Object.assign(Object.assign({}, base), { content: 'the generated code' }); // no category = the answer
260
- const kReasoning = diagnosticsMessageKey(reasoning);
261
- const kAnswer = diagnosticsMessageKey(answer);
262
- assert.ok(kReasoning, 'reasoning message has a key');
263
- assert.ok(kAnswer, 'answer message has a key');
264
- assert.not.equal(kReasoning, kAnswer, 'a reasoning and an answer split from one response must not collide');
265
- });
266
- KeySuite('still collapses a genuine re-append of the same message (same key)', () => {
267
- const m = {
268
- kind: 'message',
269
- role: 'assistant',
270
- timestamp: '2026-01-01T00:00:05.000Z',
271
- category: 'reasoning',
272
- content: 'thinking…',
273
- };
274
- // Two instances / a reload re-appending the SAME message must still share one key.
275
- assert.equal(diagnosticsMessageKey(m), diagnosticsMessageKey(Object.assign({}, m)));
276
- });
277
- KeySuite('returns null when the entry has no timestamp (treated as always-new)', () => {
278
- assert.is(diagnosticsMessageKey({ kind: 'message', role: 'assistant' }), null);
279
- });
280
- KeySuite.run();
@@ -1,110 +0,0 @@
1
- import { __awaiter } from "tslib";
2
- import { assert, createLogicSuite } from '@genesislcap/foundation-testing';
3
- import { WebStorageSessionProvider } from './session-persistence-provider';
4
- import { createPersistedSession } from './session-snapshot';
5
- // GENC-1351 §5.2: the WebStorageSessionProvider against a fake Storage (no real
6
- // sessionStorage in Node). Covers round-trip, absent/corrupt entries, clear,
7
- // and keyPrefix isolation.
8
- /** Minimal in-memory Storage matching the DOM `Storage` shape the provider uses. */
9
- function fakeStorage() {
10
- const m = new Map();
11
- return {
12
- get length() {
13
- return m.size;
14
- },
15
- clear: () => m.clear(),
16
- getItem: (k) => (m.has(k) ? m.get(k) : null),
17
- key: (i) => { var _a; return (_a = [...m.keys()][i]) !== null && _a !== void 0 ? _a : null; },
18
- removeItem: (k) => {
19
- m.delete(k);
20
- },
21
- setItem: (k, v) => {
22
- m.set(k, v);
23
- },
24
- };
25
- }
26
- const snap = (sessionKey) => createPersistedSession({
27
- sessionKey,
28
- host: 'app.example',
29
- messages: [],
30
- pinnedAgentName: null,
31
- flowOwnerAgentName: null,
32
- sessionCostUsd: 0,
33
- });
34
- const Suite = createLogicSuite('web-storage-session-provider');
35
- Suite('save → load round-trips a snapshot', () => __awaiter(void 0, void 0, void 0, function* () {
36
- const provider = new WebStorageSessionProvider(fakeStorage());
37
- const s = snap('s1');
38
- yield provider.save('s1', s);
39
- const loaded = yield provider.load('s1');
40
- // Compare through JSON: createPersistedSession leaves optional keys undefined,
41
- // which JSON drops — so normalise both sides the same way.
42
- assert.equal(loaded, JSON.parse(JSON.stringify(s)));
43
- }));
44
- Suite('load returns null for an unknown key', () => __awaiter(void 0, void 0, void 0, function* () {
45
- const provider = new WebStorageSessionProvider(fakeStorage());
46
- assert.is(yield provider.load('missing'), null);
47
- }));
48
- Suite('load returns null (not throw) on a corrupt entry', () => __awaiter(void 0, void 0, void 0, function* () {
49
- const storage = fakeStorage();
50
- storage.setItem('genesis-ai-session:s1', '{ not valid json');
51
- const provider = new WebStorageSessionProvider(storage);
52
- assert.is(yield provider.load('s1'), null);
53
- }));
54
- Suite('clear removes the snapshot', () => __awaiter(void 0, void 0, void 0, function* () {
55
- const provider = new WebStorageSessionProvider(fakeStorage());
56
- yield provider.save('s1', snap('s1'));
57
- yield provider.clear('s1');
58
- assert.is(yield provider.load('s1'), null);
59
- }));
60
- Suite('keyPrefix isolates snapshots stored in the same Storage', () => __awaiter(void 0, void 0, void 0, function* () {
61
- const storage = fakeStorage();
62
- const a = new WebStorageSessionProvider(storage, { keyPrefix: 'appA' });
63
- const b = new WebStorageSessionProvider(storage, { keyPrefix: 'appB' });
64
- yield a.save('k', snap('k'));
65
- assert.is(yield b.load('k'), null);
66
- assert.ok(yield a.load('k'));
67
- }));
68
- Suite('saveDebounceMs defaults to 0 (web storage is sync) and is overridable', () => {
69
- assert.is(new WebStorageSessionProvider(fakeStorage()).saveDebounceMs, 0);
70
- assert.is(new WebStorageSessionProvider(fakeStorage(), { saveDebounceMs: 1500 }).saveDebounceMs, 1500);
71
- });
72
- // GENC-1351: user preferences (remember-chat + display toggles) — persisted
73
- // independently of the snapshot and of the enabled toggle.
74
- Suite('loadPreferences is undefined until set, then round-trips a blob', () => __awaiter(void 0, void 0, void 0, function* () {
75
- const provider = new WebStorageSessionProvider(fakeStorage());
76
- assert.is(yield provider.loadPreferences('s1'), undefined, 'never saved → undefined (use defaults)');
77
- const prefs = {
78
- enabled: false,
79
- showToolCalls: true,
80
- showThinkingSteps: true,
81
- showNarration: false,
82
- showAgentSwitchIndicator: true,
83
- animations: ['dots'],
84
- };
85
- yield provider.savePreferences('s1', prefs);
86
- assert.equal(yield provider.loadPreferences('s1'), prefs);
87
- }));
88
- Suite('loadPreferences returns undefined (not throw) on a corrupt entry', () => __awaiter(void 0, void 0, void 0, function* () {
89
- const storage = fakeStorage();
90
- storage.setItem('genesis-ai-session:prefs:s1', '{ not valid json');
91
- const provider = new WebStorageSessionProvider(storage);
92
- assert.is(yield provider.loadPreferences('s1'), undefined);
93
- }));
94
- Suite('clear wipes the snapshot but keeps the preferences', () => __awaiter(void 0, void 0, void 0, function* () {
95
- const provider = new WebStorageSessionProvider(fakeStorage());
96
- yield provider.save('s1', snap('s1'));
97
- yield provider.savePreferences('s1', { enabled: false, showToolCalls: true });
98
- yield provider.clear('s1');
99
- assert.is(yield provider.load('s1'), null, 'snapshot cleared');
100
- assert.equal(yield provider.loadPreferences('s1'), { enabled: false, showToolCalls: true }, 'preferences survive clear');
101
- }));
102
- Suite('preferences are keyPrefix-isolated too', () => __awaiter(void 0, void 0, void 0, function* () {
103
- const storage = fakeStorage();
104
- const a = new WebStorageSessionProvider(storage, { keyPrefix: 'appA' });
105
- const b = new WebStorageSessionProvider(storage, { keyPrefix: 'appB' });
106
- yield a.savePreferences('k', { enabled: true });
107
- assert.is(yield b.loadPreferences('k'), undefined);
108
- assert.equal(yield a.loadPreferences('k'), { enabled: true });
109
- }));
110
- Suite.run();
@@ -1,113 +0,0 @@
1
- import { __awaiter } from "tslib";
2
- import { assert, createLogicSuite } from '@genesislcap/foundation-testing';
3
- import { aiAssistantSlice, createDefaultSessionState } from '../ai-assistant-slice';
4
- import { WebStorageSessionProvider } from './session-persistence-provider';
5
- import { createPersistedSession, isRestorableSession, toLoadSessionPayload, trimToRestorableBoundary, } from './session-snapshot';
6
- // GENC-1351 Phase 1 integration: the page-reload cycle the element wires —
7
- // save on idle → reload drops the in-memory store + provider → restore hydrates
8
- // a fresh store. Exercises the REAL provider + schema + reducer composed; the
9
- // custom-element glue (connectedCallback → maybeRestoreSession) is covered by a
10
- // manual app test.
11
- /** In-memory Storage that survives the simulated reload (like sessionStorage does). */
12
- function fakeStorage() {
13
- const m = new Map();
14
- return {
15
- get length() {
16
- return m.size;
17
- },
18
- clear: () => m.clear(),
19
- getItem: (k) => (m.has(k) ? m.get(k) : null),
20
- key: (i) => { var _a; return (_a = [...m.keys()][i]) !== null && _a !== void 0 ? _a : null; },
21
- removeItem: (k) => {
22
- m.delete(k);
23
- },
24
- setItem: (k, v) => {
25
- m.set(k, v);
26
- },
27
- };
28
- }
29
- const asMsg = (o) => o;
30
- const reduce = aiAssistantSlice.reducer;
31
- const { loadSession } = aiAssistantSlice.actions;
32
- const Suite = createLogicSuite('session-persistence-integration');
33
- Suite('save → reload → restore brings back messages, selection, counters', () => __awaiter(void 0, void 0, void 0, function* () {
34
- const storage = fakeStorage(); // persists across the simulated reload
35
- const host = 'app.example';
36
- const key = 'assistant::Title';
37
- // 1. A live session reaches idle with history + a pinned agent.
38
- const messages = [
39
- asMsg({ role: 'user', content: 'book a trade' }),
40
- asMsg({ role: 'assistant', content: 'sure' }),
41
- ];
42
- yield new WebStorageSessionProvider(storage).save(key, createPersistedSession({
43
- sessionKey: key,
44
- host,
45
- messages,
46
- activeAgentName: 'Guided Booking',
47
- pinnedAgentName: 'Guided Booking',
48
- flowOwnerAgentName: null,
49
- sessionCostUsd: 0.5,
50
- contextTokens: 800,
51
- contextLimit: 200000,
52
- activeModel: 'claude-sonnet-4-6',
53
- activeProviderName: 'anthropic',
54
- }));
55
- // 2. "Reload": the in-memory store + provider instance are gone; storage remains.
56
- const freshStore = createDefaultSessionState();
57
- const snapshot = yield new WebStorageSessionProvider(storage).load(key);
58
- assert.ok(snapshot, 'snapshot survives the reload');
59
- assert.ok(isRestorableSession(snapshot, { host }), 'snapshot is restorable for this host');
60
- // 3. Restore into the fresh store (what maybeRestoreSession does).
61
- const restored = reduce(freshStore, loadSession(toLoadSessionPayload(snapshot)));
62
- assert.is(restored.messages.length, 2);
63
- assert.is(restored.pinnedAgentName, 'Guided Booking');
64
- // Cost comes from the restored transcript, NOT the snapshot's stored counter — so it
65
- // is whatever the messages actually carry. Computed independently here rather than
66
- // by calling the summing helper under test.
67
- const expectedCost = restored.messages.reduce((sum, m) => { var _a, _b; return sum + ((_a = m.cost) !== null && _a !== void 0 ? _a : 0) + ((_b = m.externalCostUsd) !== null && _b !== void 0 ? _b : 0); }, 0);
68
- assert.is(restored.sessionUsage.costUsd, expectedCost);
69
- assert.is(restored.contextTokens, 800);
70
- assert.is(restored.contextLimit, 200000);
71
- assert.is(restored.activeModel, 'claude-sonnet-4-6');
72
- assert.is(restored.activeProviderName, 'anthropic');
73
- assert.is(restored.state, 'idle');
74
- }));
75
- Suite('a cross-host snapshot is rejected on restore', () => __awaiter(void 0, void 0, void 0, function* () {
76
- const storage = fakeStorage();
77
- const provider = new WebStorageSessionProvider(storage);
78
- yield provider.save('k', createPersistedSession({
79
- sessionKey: 'k',
80
- host: 'app.example',
81
- messages: [asMsg({ role: 'user', content: 'x' })],
82
- pinnedAgentName: null,
83
- flowOwnerAgentName: null,
84
- sessionCostUsd: 0,
85
- }));
86
- const snapshot = yield provider.load('k');
87
- assert.ok(snapshot);
88
- assert.ok(!isRestorableSession(snapshot, { host: 'evil.example' }));
89
- }));
90
- Suite('a dangling interaction tail is scrubbed before restore', () => __awaiter(void 0, void 0, void 0, function* () {
91
- const storage = fakeStorage();
92
- const provider = new WebStorageSessionProvider(storage);
93
- const messages = [
94
- asMsg({ role: 'user', content: 'hi' }),
95
- asMsg({
96
- role: 'assistant',
97
- content: '',
98
- interaction: { interactionId: '1', componentName: 'x', data: {} },
99
- }),
100
- ];
101
- yield provider.save('k', createPersistedSession({
102
- sessionKey: 'k',
103
- host: 'h',
104
- messages,
105
- pinnedAgentName: null,
106
- flowOwnerAgentName: null,
107
- sessionCostUsd: 0,
108
- }));
109
- const snapshot = yield provider.load('k');
110
- const scrubbed = trimToRestorableBoundary(snapshot.messages);
111
- assert.is(scrubbed.length, 1, 'the unresolved interaction message is dropped');
112
- }));
113
- Suite.run();