@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,336 +0,0 @@
1
- import type { ChatMessage } from '@genesislcap/foundation-ai';
2
- import { assert, createLogicSuite } from '@genesislcap/foundation-testing';
3
- import {
4
- aiAssistantSlice,
5
- type AiAssistantSessionState,
6
- createDefaultSessionState,
7
- type LoadSessionPayload,
8
- } from './ai-assistant-slice';
9
-
10
- // GENC-1351 §5.6 / Phase 1: the new bulk loadSession + resetSession reducers.
11
-
12
- const {
13
- loadSession,
14
- resetSession,
15
- setBlocked,
16
- setBlockedReason,
17
- setVendorBlocked,
18
- setInputValue,
19
- setMessages,
20
- setState,
21
- setSessionMenuOpen,
22
- setShowToolCalls,
23
- setShowThinkingSteps,
24
- setShowNarration,
25
- setShowAgentSwitchIndicator,
26
- setEnabledAnimations,
27
- } = aiAssistantSlice.actions;
28
- const reduce = aiAssistantSlice.reducer;
29
-
30
- const Suite = createLogicSuite('ai-assistant-slice-persistence');
31
-
32
- Suite('loadSession hydrates the restorable fields and forces idle', () => {
33
- let start = createDefaultSessionState();
34
- start = reduce(start, setState('loading')); // prove it overrides any prior state
35
- const payload: LoadSessionPayload = {
36
- // Usage rides on the message: `loadSession` derives the session totals from the
37
- // restored transcript rather than from a stored counter, so the cost has to be in
38
- // the messages for the assertion below to see it.
39
- messages: [
40
- { role: 'user', content: 'hi', cost: 1.25, inputTokens: 100, outputTokens: 20 },
41
- ] as ChatMessage[],
42
- pinnedAgentName: 'Guided Booking',
43
- flowOwnerAgentName: 'Guided Booking',
44
- contextTokens: 1200,
45
- contextLimit: 200000,
46
- activeModel: 'claude-sonnet-4-6',
47
- activeProviderName: 'anthropic',
48
- };
49
- const next = reduce(start, loadSession(payload));
50
- assert.is(next.messages.length, 1);
51
- assert.is(next.pinnedAgentName, 'Guided Booking');
52
- assert.is(next.flowOwnerAgentName, 'Guided Booking');
53
- assert.is(next.sessionUsage.costUsd, 1.25);
54
- // Derived from the same walk: 100 prompt tokens with no cache split reported, so all
55
- // of it is uncached input, plus the 20 generated.
56
- assert.is(next.sessionUsage.uncachedInputTokens, 100);
57
- assert.is(next.sessionUsage.outputTokens, 20);
58
- assert.is(next.contextTokens, 1200);
59
- assert.is(next.contextLimit, 200000);
60
- assert.is(next.activeModel, 'claude-sonnet-4-6');
61
- assert.is(next.activeProviderName, 'anthropic');
62
- assert.is(next.state, 'idle');
63
- });
64
-
65
- Suite('resetSession wipes back to a fresh default', () => {
66
- let state = createDefaultSessionState();
67
- state = reduce(state, setMessages([{ role: 'user', content: 'x' }] as ChatMessage[]));
68
- state = reduce(
69
- state,
70
- loadSession({
71
- messages: [],
72
- pinnedAgentName: 'A',
73
- flowOwnerAgentName: 'A',
74
- contextTokens: 5,
75
- contextLimit: 10,
76
- activeModel: 'm',
77
- activeProviderName: 'p',
78
- }),
79
- );
80
- const cleared = reduce(state, resetSession());
81
- assert.is(cleared.messages.length, 0);
82
- assert.is(cleared.sessionUsage.costUsd, 0);
83
- assert.is(cleared.pinnedAgentName, null);
84
- assert.is(cleared.flowOwnerAgentName, null);
85
- assert.is(cleared.contextTokens, undefined);
86
- assert.is(cleared.state, 'idle');
87
- });
88
-
89
- Suite('resetSession preserves the user display preferences (they survive Clear)', () => {
90
- // Display prefs are settings, not conversation state — Clear/New-chat must keep them
91
- // (GENC-1351 #10). Turn several on, plus an animation, then reset.
92
- let state = createDefaultSessionState();
93
- state = reduce(state, setShowToolCalls(true));
94
- state = reduce(state, setShowThinkingSteps(true));
95
- state = reduce(state, setShowNarration(true));
96
- state = reduce(state, setShowAgentSwitchIndicator(true));
97
- state = reduce(state, setEnabledAnimations(['halo']));
98
- state = reduce(state, setMessages([{ role: 'user', content: 'x' }] as ChatMessage[]));
99
-
100
- const cleared = reduce(state, resetSession());
101
- // Conversation wiped…
102
- assert.is(cleared.messages.length, 0, 'conversation cleared');
103
- // …but the display prefs kept.
104
- assert.is(cleared.showToolCalls, true);
105
- assert.is(cleared.showThinkingSteps, true);
106
- assert.is(cleared.showNarration, true);
107
- assert.is(cleared.showAgentSwitchIndicator, true);
108
- assert.equal(cleared.enabledAnimations, ['halo']);
109
- });
110
-
111
- Suite('createDefaultSessionState returns independent collections', () => {
112
- // No aliasing between instances — resetSession must hand back a clean slate.
113
- assert.ok(createDefaultSessionState().messages !== createDefaultSessionState().messages);
114
- });
115
-
116
- // GENC-1351 Phase 3: the lifecycle (session) menu open/close flag.
117
- Suite('setSessionMenuOpen toggles the lifecycle-menu flag; resetSession clears it', () => {
118
- let state = createDefaultSessionState();
119
- assert.is(state.sessionMenuOpen, false);
120
- state = reduce(state, setSessionMenuOpen(true));
121
- assert.is(state.sessionMenuOpen, true);
122
- const cleared = reduce(state, resetSession());
123
- assert.is(cleared.sessionMenuOpen, false);
124
- });
125
-
126
- // GENC-1464: the backend-blocked latch (exhausted AI budget).
127
- Suite('setBlocked latches the flag and its reason', () => {
128
- let state = createDefaultSessionState();
129
- assert.is(state.blocked, false);
130
- assert.is(state.blockedReason, null);
131
-
132
- state = reduce(state, setBlocked({ blocked: true }));
133
- assert.is(state.blocked, true);
134
- assert.is(state.blockedReason, null, 'no reason given → null, so the element uses its default');
135
-
136
- state = reduce(
137
- state,
138
- setBlocked({ blocked: true, reason: 'Budget exhausted — contact billing' }),
139
- );
140
- assert.is(state.blockedReason, 'Budget exhausted — contact billing');
141
- });
142
-
143
- Suite('unblocking always clears the reason', () => {
144
- // A stale explanation must never outlive the condition it described.
145
- let state = reduce(createDefaultSessionState(), setBlocked({ blocked: true, reason: 'gone' }));
146
- state = reduce(state, setBlocked({ blocked: false }));
147
- assert.is(state.blocked, false);
148
- assert.is(state.blockedReason, null);
149
- });
150
-
151
- Suite('resetSession preserves the block — "New chat" does not refill the budget', () => {
152
- // Deliberately unlike sessionMenuOpen/compacting above: this is a backend
153
- // condition, not conversation state, so Clear must not hand the user a
154
- // working-looking composer that fails on the next send.
155
- let state = reduce(
156
- createDefaultSessionState(),
157
- setBlocked({ blocked: true, reason: 'no funds' }),
158
- );
159
- state = reduce(state, setMessages([{ role: 'user', content: 'x' }] as ChatMessage[]));
160
-
161
- const cleared = reduce(state, resetSession());
162
-
163
- assert.is(cleared.messages.length, 0, 'the transcript is still cleared');
164
- assert.is(cleared.blocked, true, 'the block survives Clear');
165
- assert.is(cleared.blockedReason, 'no funds', 'and so does its reason');
166
- });
167
-
168
- Suite('re-latching without a reason preserves the host explanation', () => {
169
- // The race this fixes is deterministic, not theoretical: `tool-loop-end` is
170
- // published from the driver's `finally`, i.e. BEFORE `sendMessage()` resolves.
171
- // So a bus-subscribed host (what the migration guide's Option C recommends)
172
- // writes its detailed copy first, and the element's own latch — which may have
173
- // no figures to offer — lands a moment later. Treating an OMITTED reason as
174
- // "clear it" replaced the host's copy with generic copy every single time.
175
- let state = reduce(
176
- createDefaultSessionState(),
177
- setBlocked({ blocked: true, reason: 'contact ops@acme.com' }),
178
- );
179
-
180
- state = reduce(state, setBlocked({ blocked: true }));
181
-
182
- assert.is(state.blocked, true);
183
- assert.is(state.blockedReason, 'contact ops@acme.com', 'the host copy survives the re-latch');
184
- });
185
-
186
- Suite('reason:null clears the explanation while staying blocked', () => {
187
- // The explicit escape hatch the omitted case gives up: `null` still clears.
188
- let state = reduce(
189
- createDefaultSessionState(),
190
- setBlocked({ blocked: true, reason: 'stale copy' }),
191
- );
192
-
193
- state = reduce(state, setBlocked({ blocked: true, reason: null }));
194
-
195
- assert.is(state.blocked, true);
196
- assert.is(state.blockedReason, null, 'the banner falls back to the default copy');
197
- });
198
-
199
- Suite('resetSession still resets everything NOT on the preserved list', () => {
200
- // Pins the boundary from the other side, so the preserved list cannot quietly
201
- // grow: these are conversation/UI state and Clear must wipe them.
202
- let state = reduce(createDefaultSessionState(), setBlocked({ blocked: true, reason: 'r' }));
203
- state = reduce(state, setSessionMenuOpen(true));
204
- state = reduce(state, setInputValue('half-typed message'));
205
-
206
- const cleared = reduce(state, resetSession());
207
-
208
- assert.is(cleared.inputValue, '', 'the composer draft is reset');
209
- assert.is(cleared.sessionMenuOpen, false, 'the panel flag is reset');
210
- assert.is(cleared.blocked, true, '…while the block is still preserved');
211
- });
212
-
213
- // ── Per-vendor latches (GENC-1464 per-vendor budgets) ──────────────────────────
214
-
215
- Suite('setVendorBlocked walls one vendor and keeps the wall order', () => {
216
- let state = reduce(
217
- createDefaultSessionState(),
218
- setVendorBlocked({ vendor: 'anthropic', blocked: true, reason: 'anthropic copy' }),
219
- );
220
- assert.equal(state.blockedVendors, ['anthropic']);
221
- assert.equal(state.blockedVendorReasons, { anthropic: 'anthropic copy' });
222
- assert.is(state.blocked, false, 'the vendor-agnostic flag is untouched');
223
-
224
- state = reduce(state, setVendorBlocked({ vendor: 'gemini', blocked: true }));
225
- assert.equal(
226
- state.blockedVendors,
227
- ['anthropic', 'gemini'],
228
- 'order is the order they were walled',
229
- );
230
- });
231
-
232
- Suite('walling an already-walled vendor is idempotent', () => {
233
- let state = reduce(
234
- createDefaultSessionState(),
235
- setVendorBlocked({ vendor: 'gemini', blocked: true, reason: 'first' }),
236
- );
237
- state = reduce(state, setVendorBlocked({ vendor: 'gemini', blocked: true, reason: 'second' }));
238
- assert.equal(state.blockedVendors, ['gemini'], 'no duplicate entry');
239
- assert.is(state.blockedVendorReasons.gemini, 'second');
240
- });
241
-
242
- Suite('the per-vendor reason honours the same three cases as setBlocked', () => {
243
- // The same two-writer race (driver latch landing after a bus-subscribed host)
244
- // applies per vendor, so "omitted keeps" has to hold here too.
245
- let state = reduce(
246
- createDefaultSessionState(),
247
- setVendorBlocked({ vendor: 'anthropic', blocked: true, reason: 'host copy' }),
248
- );
249
-
250
- state = reduce(state, setVendorBlocked({ vendor: 'anthropic', blocked: true }));
251
- assert.is(state.blockedVendorReasons.anthropic, 'host copy', 'omitted keeps');
252
-
253
- state = reduce(state, setVendorBlocked({ vendor: 'anthropic', blocked: true, reason: null }));
254
- assert.is(state.blockedVendorReasons.anthropic, undefined, 'null clears');
255
- });
256
-
257
- Suite('releasing a vendor drops it and its copy', () => {
258
- let state = reduce(
259
- createDefaultSessionState(),
260
- setVendorBlocked({ vendor: 'anthropic', blocked: true, reason: 'r' }),
261
- );
262
- state = reduce(state, setVendorBlocked({ vendor: 'gemini', blocked: true }));
263
-
264
- state = reduce(state, setVendorBlocked({ vendor: 'anthropic', blocked: false }));
265
-
266
- assert.equal(state.blockedVendors, ['gemini']);
267
- assert.is(state.blockedVendorReasons.anthropic, undefined);
268
- });
269
-
270
- Suite('setBlocked(false) also clears every per-vendor latch', () => {
271
- // THE back-compat rule. A host asserting "the wall is gone" after its own
272
- // pre-flight (migration-GENC-1464 Option B) must not be overruled by a driver
273
- // latch it cannot see — without this, per-vendor would silently make the
274
- // documented unblock stop working.
275
- let state = reduce(
276
- createDefaultSessionState(),
277
- setVendorBlocked({ vendor: 'anthropic', blocked: true, reason: 'r' }),
278
- );
279
- state = reduce(state, setBlocked({ blocked: true, reason: 'global' }));
280
-
281
- state = reduce(state, setBlocked({ blocked: false }));
282
-
283
- assert.is(state.blocked, false);
284
- assert.is(state.blockedReason, null);
285
- assert.equal(state.blockedVendors, []);
286
- assert.equal(state.blockedVendorReasons, {});
287
- });
288
-
289
- Suite('setBlockedReason writes the copy without disturbing any latch', () => {
290
- // It exists precisely so the element's `blockedReason` setter cannot route
291
- // through `setBlocked(false, …)` — which would now clear the vendor latches.
292
- let state = reduce(
293
- createDefaultSessionState(),
294
- setVendorBlocked({ vendor: 'gemini', blocked: true }),
295
- );
296
-
297
- state = reduce(state, setBlockedReason('host copy'));
298
-
299
- assert.is(state.blockedReason, 'host copy');
300
- assert.is(state.blocked, false, 'the vendor-agnostic flag is untouched');
301
- assert.equal(state.blockedVendors, ['gemini'], 'and so are the per-vendor latches');
302
- });
303
-
304
- Suite('resetSession preserves the per-vendor latches too', () => {
305
- let state = reduce(
306
- createDefaultSessionState(),
307
- setVendorBlocked({ vendor: 'anthropic', blocked: true, reason: 'no funds' }),
308
- );
309
- state = reduce(state, setMessages([{ role: 'user', content: 'hi' }] as ChatMessage[]));
310
-
311
- const cleared = reduce(state, resetSession());
312
-
313
- assert.equal(cleared.messages, [], 'the conversation is wiped');
314
- assert.equal(cleared.blockedVendors, ['anthropic'], 'Clear does not refill a vendor budget');
315
- assert.equal(cleared.blockedVendorReasons, { anthropic: 'no funds' });
316
- });
317
-
318
- // `resetSession` preserves its keys through `Object.assign`, whose source parameter
319
- // is structurally permissive: a typo like `blockedResaon` would compile clean,
320
- // silently stop preserving the real key, AND leak a junk key into serialised state.
321
- // The reducer therefore annotates its literal `satisfies
322
- // Partial<AiAssistantSessionState>`, which is a COMPILE-time guarantee — so the
323
- // durable proof is a type fixture, not a runtime assertion.
324
- //
325
- // This mirrors the reducer's clause on the same typo. If `satisfies` ever stopped
326
- // rejecting excess properties (a TS behaviour change, or someone widening the
327
- // annotated type), the `@ts-expect-error` below becomes unused and the BUILD fails
328
- // — which is exactly the signal wanted. The runtime suites above are its
329
- // behavioural companions: they pin the preserved list from both sides.
330
- const _typoIsRejectedAtCompileTime = {
331
- // @ts-expect-error — an excess/misspelled key must be rejected by `satisfies`
332
- blockedResaon: null,
333
- } satisfies Partial<AiAssistantSessionState>;
334
- void _typoIsRejectedAtCompileTime;
335
-
336
- Suite.run();