@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.
- package/package.json +17 -18
- package/api-extractor.json +0 -11
- package/dist/dts/components/chat-driver/chat-driver.compact.test.d.ts +0 -2
- package/dist/dts/components/chat-driver/chat-driver.compact.test.d.ts.map +0 -1
- package/dist/dts/components/chat-driver/chat-driver.invocation-scope.test.d.ts +0 -2
- package/dist/dts/components/chat-driver/chat-driver.invocation-scope.test.d.ts.map +0 -1
- package/dist/dts/components/chat-driver/chat-driver.test.d.ts +0 -2
- package/dist/dts/components/chat-driver/chat-driver.test.d.ts.map +0 -1
- package/dist/dts/components/chat-driver/chat-driver.thinking-policy.test.d.ts +0 -2
- package/dist/dts/components/chat-driver/chat-driver.thinking-policy.test.d.ts.map +0 -1
- package/dist/dts/components/chat-driver/chat-driver.trace-capture.test.d.ts +0 -2
- package/dist/dts/components/chat-driver/chat-driver.trace-capture.test.d.ts.map +0 -1
- package/dist/dts/components/chat-driver/chat-driver.turn-usage.test.d.ts +0 -2
- package/dist/dts/components/chat-driver/chat-driver.turn-usage.test.d.ts.map +0 -1
- package/dist/dts/components/chat-interaction-wrapper/chat-interaction-wrapper.test.d.ts +0 -2
- package/dist/dts/components/chat-interaction-wrapper/chat-interaction-wrapper.test.d.ts.map +0 -1
- package/dist/dts/components/orchestrating-driver/orchestrating-driver.budget.test.d.ts +0 -2
- package/dist/dts/components/orchestrating-driver/orchestrating-driver.budget.test.d.ts.map +0 -1
- package/dist/dts/components/orchestrating-driver/orchestrating-driver.cost.test.d.ts +0 -2
- package/dist/dts/components/orchestrating-driver/orchestrating-driver.cost.test.d.ts.map +0 -1
- package/dist/dts/components/orchestrating-driver/orchestrating-driver.pin.test.d.ts +0 -2
- package/dist/dts/components/orchestrating-driver/orchestrating-driver.pin.test.d.ts.map +0 -1
- package/dist/dts/components/settings-modal/settings-modal.styles.test.d.ts +0 -2
- package/dist/dts/components/settings-modal/settings-modal.styles.test.d.ts.map +0 -1
- package/dist/dts/components/settings-modal/settings-modal.template.test.d.ts +0 -2
- package/dist/dts/components/settings-modal/settings-modal.template.test.d.ts.map +0 -1
- package/dist/dts/config/define-stateful-agent.test.d.ts +0 -2
- package/dist/dts/config/define-stateful-agent.test.d.ts.map +0 -1
- package/dist/dts/config/validate-providers.test.d.ts +0 -2
- package/dist/dts/config/validate-providers.test.d.ts.map +0 -1
- package/dist/dts/main/blocked-state.test.d.ts +0 -2
- package/dist/dts/main/blocked-state.test.d.ts.map +0 -1
- package/dist/dts/main/budget-meter.test.d.ts +0 -2
- package/dist/dts/main/budget-meter.test.d.ts.map +0 -1
- package/dist/dts/main/cost-session-banking.test.d.ts +0 -2
- package/dist/dts/main/cost-session-banking.test.d.ts.map +0 -1
- package/dist/dts/main/file-attachments.test.d.ts +0 -2
- package/dist/dts/main/file-attachments.test.d.ts.map +0 -1
- package/dist/dts/main/interaction-cost.test.d.ts +0 -2
- package/dist/dts/main/interaction-cost.test.d.ts.map +0 -1
- package/dist/dts/main/main.styles.test.d.ts +0 -2
- package/dist/dts/main/main.styles.test.d.ts.map +0 -1
- package/dist/dts/main/persistence-broken-sources.test.d.ts +0 -2
- package/dist/dts/main/persistence-broken-sources.test.d.ts.map +0 -1
- package/dist/dts/main/popout-interaction-gate.test.d.ts +0 -2
- package/dist/dts/main/popout-interaction-gate.test.d.ts.map +0 -1
- package/dist/dts/state/ai-assistant-slice.test.d.ts +0 -2
- package/dist/dts/state/ai-assistant-slice.test.d.ts.map +0 -1
- package/dist/dts/state/debug-event-log.test.d.ts +0 -2
- package/dist/dts/state/debug-event-log.test.d.ts.map +0 -1
- package/dist/dts/state/driver-registry.test.d.ts +0 -2
- package/dist/dts/state/driver-registry.test.d.ts.map +0 -1
- package/dist/dts/state/interaction-context.test.d.ts +0 -2
- package/dist/dts/state/interaction-context.test.d.ts.map +0 -1
- package/dist/dts/state/persistence/diagnostics-cursors.test.d.ts +0 -2
- package/dist/dts/state/persistence/diagnostics-cursors.test.d.ts.map +0 -1
- package/dist/dts/state/persistence/diagnostics.test.d.ts +0 -2
- package/dist/dts/state/persistence/diagnostics.test.d.ts.map +0 -1
- package/dist/dts/state/persistence/session-persistence-provider.test.d.ts +0 -2
- package/dist/dts/state/persistence/session-persistence-provider.test.d.ts.map +0 -1
- package/dist/dts/state/persistence/session-persistence.integration.test.d.ts +0 -2
- package/dist/dts/state/persistence/session-persistence.integration.test.d.ts.map +0 -1
- package/dist/dts/state/persistence/session-persister.test.d.ts +0 -2
- package/dist/dts/state/persistence/session-persister.test.d.ts.map +0 -1
- package/dist/dts/state/persistence/session-snapshot.test.d.ts +0 -2
- package/dist/dts/state/persistence/session-snapshot.test.d.ts.map +0 -1
- package/dist/dts/state/persistence/stateful-restore.e2e.test.d.ts +0 -2
- package/dist/dts/state/persistence/stateful-restore.e2e.test.d.ts.map +0 -1
- package/dist/dts/utils/animation-exclusivity.test.d.ts +0 -2
- package/dist/dts/utils/animation-exclusivity.test.d.ts.map +0 -1
- package/dist/dts/utils/collect-session-models.test.d.ts +0 -2
- package/dist/dts/utils/collect-session-models.test.d.ts.map +0 -1
- package/dist/dts/utils/condense-history.test.d.ts +0 -2
- package/dist/dts/utils/condense-history.test.d.ts.map +0 -1
- package/dist/dts/utils/cost-session-history.test.d.ts +0 -2
- package/dist/dts/utils/cost-session-history.test.d.ts.map +0 -1
- package/dist/dts/utils/derive-cost-session-title.test.d.ts +0 -2
- package/dist/dts/utils/derive-cost-session-title.test.d.ts.map +0 -1
- package/dist/dts/utils/flatten-sub-agent-messages.test.d.ts +0 -2
- package/dist/dts/utils/flatten-sub-agent-messages.test.d.ts.map +0 -1
- package/dist/dts/utils/history-transform.test.d.ts +0 -2
- package/dist/dts/utils/history-transform.test.d.ts.map +0 -1
- package/dist/dts/utils/message-partition.test.d.ts +0 -2
- package/dist/dts/utils/message-partition.test.d.ts.map +0 -1
- package/dist/dts/utils/resolve-cost-history-config.test.d.ts +0 -2
- package/dist/dts/utils/resolve-cost-history-config.test.d.ts.map +0 -1
- package/dist/dts/utils/resolve-preference-baseline.test.d.ts +0 -2
- package/dist/dts/utils/resolve-preference-baseline.test.d.ts.map +0 -1
- package/dist/dts/utils/strip-agent-handlers.test.d.ts +0 -2
- package/dist/dts/utils/strip-agent-handlers.test.d.ts.map +0 -1
- package/dist/dts/utils/sum-costs.test.d.ts +0 -2
- package/dist/dts/utils/sum-costs.test.d.ts.map +0 -1
- package/dist/dts/utils/sum-tokens.test.d.ts +0 -2
- package/dist/dts/utils/sum-tokens.test.d.ts.map +0 -1
- package/dist/dts/utils/sum-usage.test.d.ts +0 -2
- package/dist/dts/utils/sum-usage.test.d.ts.map +0 -1
- package/dist/dts/utils/usage-rows.test.d.ts +0 -2
- package/dist/dts/utils/usage-rows.test.d.ts.map +0 -1
- package/dist/esm/components/chat-driver/chat-driver.compact.test.js +0 -93
- package/dist/esm/components/chat-driver/chat-driver.invocation-scope.test.js +0 -238
- package/dist/esm/components/chat-driver/chat-driver.test.js +0 -2770
- package/dist/esm/components/chat-driver/chat-driver.thinking-policy.test.js +0 -137
- package/dist/esm/components/chat-driver/chat-driver.trace-capture.test.js +0 -200
- package/dist/esm/components/chat-driver/chat-driver.turn-usage.test.js +0 -268
- package/dist/esm/components/chat-interaction-wrapper/chat-interaction-wrapper.test.js +0 -104
- package/dist/esm/components/orchestrating-driver/orchestrating-driver.budget.test.js +0 -312
- package/dist/esm/components/orchestrating-driver/orchestrating-driver.cost.test.js +0 -76
- package/dist/esm/components/orchestrating-driver/orchestrating-driver.pin.test.js +0 -61
- package/dist/esm/components/settings-modal/settings-modal.styles.test.js +0 -80
- package/dist/esm/components/settings-modal/settings-modal.template.test.js +0 -91
- package/dist/esm/config/define-stateful-agent.test.js +0 -53
- package/dist/esm/config/validate-providers.test.js +0 -100
- package/dist/esm/main/blocked-state.test.js +0 -1065
- package/dist/esm/main/budget-meter.test.js +0 -359
- package/dist/esm/main/cost-session-banking.test.js +0 -538
- package/dist/esm/main/file-attachments.test.js +0 -164
- package/dist/esm/main/interaction-cost.test.js +0 -107
- package/dist/esm/main/main.styles.test.js +0 -161
- package/dist/esm/main/persistence-broken-sources.test.js +0 -180
- package/dist/esm/main/popout-interaction-gate.test.js +0 -54
- package/dist/esm/state/ai-assistant-slice.test.js +0 -229
- package/dist/esm/state/debug-event-log.test.js +0 -117
- package/dist/esm/state/driver-registry.test.js +0 -55
- package/dist/esm/state/interaction-context.test.js +0 -78
- package/dist/esm/state/persistence/diagnostics-cursors.test.js +0 -30
- package/dist/esm/state/persistence/diagnostics.test.js +0 -280
- package/dist/esm/state/persistence/session-persistence-provider.test.js +0 -110
- package/dist/esm/state/persistence/session-persistence.integration.test.js +0 -113
- package/dist/esm/state/persistence/session-persister.test.js +0 -613
- package/dist/esm/state/persistence/session-snapshot.test.js +0 -256
- package/dist/esm/state/persistence/stateful-restore.e2e.test.js +0 -158
- package/dist/esm/utils/animation-exclusivity.test.js +0 -52
- package/dist/esm/utils/collect-session-models.test.js +0 -53
- package/dist/esm/utils/condense-history.test.js +0 -547
- package/dist/esm/utils/cost-session-history.test.js +0 -174
- package/dist/esm/utils/derive-cost-session-title.test.js +0 -37
- package/dist/esm/utils/flatten-sub-agent-messages.test.js +0 -139
- package/dist/esm/utils/history-transform.test.js +0 -158
- package/dist/esm/utils/message-partition.test.js +0 -90
- package/dist/esm/utils/resolve-cost-history-config.test.js +0 -32
- package/dist/esm/utils/resolve-preference-baseline.test.js +0 -69
- package/dist/esm/utils/strip-agent-handlers.test.js +0 -81
- package/dist/esm/utils/sum-costs.test.js +0 -114
- package/dist/esm/utils/sum-tokens.test.js +0 -51
- package/dist/esm/utils/sum-usage.test.js +0 -164
- package/dist/esm/utils/usage-rows.test.js +0 -189
- package/dist/tsconfig.tsbuildinfo +0 -1
- package/license.txt +0 -46
- package/sandbox/tsconfig.json +0 -8
- package/src/channel/ai-activity-bus.ts +0 -209
- package/src/channel/ai-activity-channel.ts +0 -146
- package/src/chat-driver-node.ts +0 -159
- package/src/components/activity-halo/activity-halo.ts +0 -106
- package/src/components/agent-picker/agent-picker.constants.ts +0 -2
- package/src/components/agent-picker/agent-picker.styles.ts +0 -24
- package/src/components/agent-picker/agent-picker.template.ts +0 -54
- package/src/components/agent-picker/agent-picker.ts +0 -99
- package/src/components/agent-picker/index.ts +0 -1
- package/src/components/ai-driver/ai-driver.ts +0 -166
- package/src/components/ai-driver/index.ts +0 -1
- package/src/components/chat-bubble/chat-bubble.styles.ts +0 -194
- package/src/components/chat-bubble/chat-bubble.template.ts +0 -67
- package/src/components/chat-bubble/chat-bubble.ts +0 -436
- package/src/components/chat-bubble/index.ts +0 -1
- package/src/components/chat-driver/align-event-globals.ts +0 -23
- package/src/components/chat-driver/chat-driver.compact.test.ts +0 -131
- package/src/components/chat-driver/chat-driver.invocation-scope.test.ts +0 -285
- package/src/components/chat-driver/chat-driver.test.ts +0 -3679
- package/src/components/chat-driver/chat-driver.thinking-policy.test.ts +0 -185
- package/src/components/chat-driver/chat-driver.trace-capture.test.ts +0 -251
- package/src/components/chat-driver/chat-driver.ts +0 -3925
- package/src/components/chat-driver/chat-driver.turn-usage.test.ts +0 -362
- package/src/components/chat-driver/index.ts +0 -1
- package/src/components/chat-interaction-wrapper/chat-interaction-wrapper.styles.ts +0 -7
- package/src/components/chat-interaction-wrapper/chat-interaction-wrapper.template.ts +0 -6
- package/src/components/chat-interaction-wrapper/chat-interaction-wrapper.test.ts +0 -144
- package/src/components/chat-interaction-wrapper/chat-interaction-wrapper.ts +0 -243
- package/src/components/chat-interaction-wrapper/index.ts +0 -3
- package/src/components/chat-markdown/chat-markdown.ts +0 -89
- package/src/components/chat-markdown/index.ts +0 -1
- package/src/components/flowing-waves-indicator.ts +0 -286
- package/src/components/halo-overlay.ts +0 -184
- package/src/components/orchestrating-driver/index.ts +0 -1
- package/src/components/orchestrating-driver/orchestrating-driver.budget.test.ts +0 -438
- package/src/components/orchestrating-driver/orchestrating-driver.cost.test.ts +0 -107
- package/src/components/orchestrating-driver/orchestrating-driver.pin.test.ts +0 -96
- package/src/components/orchestrating-driver/orchestrating-driver.ts +0 -813
- package/src/components/plasma-orb-indicator.ts +0 -281
- package/src/components/popout-manager/index.ts +0 -1
- package/src/components/popout-manager/popout-manager.ts +0 -212
- package/src/components/settings-modal/index.ts +0 -2
- package/src/components/settings-modal/settings-modal.styles.test.ts +0 -94
- package/src/components/settings-modal/settings-modal.styles.ts +0 -853
- package/src/components/settings-modal/settings-modal.template.test.ts +0 -124
- package/src/components/settings-modal/settings-modal.template.ts +0 -943
- package/src/components/waves-indicator.ts +0 -241
- package/src/config/config.ts +0 -608
- package/src/config/define-stateful-agent.test.ts +0 -64
- package/src/config/define-stateful-agent.ts +0 -642
- package/src/config/fallback-agents.ts +0 -29
- package/src/config/index.ts +0 -2
- package/src/config/validate-providers.test.ts +0 -148
- package/src/config/validate-providers.ts +0 -58
- package/src/index.ts +0 -29
- package/src/main/blocked-state.test.ts +0 -1444
- package/src/main/budget-meter.test.ts +0 -477
- package/src/main/cost-session-banking.test.ts +0 -679
- package/src/main/file-attachments.test.ts +0 -215
- package/src/main/index.ts +0 -3
- package/src/main/interaction-cost.test.ts +0 -140
- package/src/main/main.styles.test.ts +0 -216
- package/src/main/main.styles.ts +0 -995
- package/src/main/main.template.ts +0 -1119
- package/src/main/main.ts +0 -5432
- package/src/main/main.types.ts +0 -225
- package/src/main/persistence-broken-sources.test.ts +0 -219
- package/src/main/popout-interaction-gate.test.ts +0 -87
- package/src/provider/ai-provider-switcher.ts +0 -40
- package/src/provider/assistant-app-settings.ts +0 -84
- package/src/state/ai-assistant-slice.test.ts +0 -336
- package/src/state/ai-assistant-slice.ts +0 -604
- package/src/state/debug-event-log.test.ts +0 -154
- package/src/state/debug-event-log.ts +0 -358
- package/src/state/driver-registry.test.ts +0 -70
- package/src/state/driver-registry.ts +0 -79
- package/src/state/interaction-context.test.ts +0 -90
- package/src/state/interaction-context.ts +0 -101
- package/src/state/persistence/build-timeline-entries.ts +0 -66
- package/src/state/persistence/diagnostics-cursors.test.ts +0 -53
- package/src/state/persistence/diagnostics-cursors.ts +0 -80
- package/src/state/persistence/diagnostics.test.ts +0 -346
- package/src/state/persistence/diagnostics.ts +0 -220
- package/src/state/persistence/index.ts +0 -10
- package/src/state/persistence/persister-registry.ts +0 -55
- package/src/state/persistence/session-persistence-provider.test.ts +0 -136
- package/src/state/persistence/session-persistence-provider.ts +0 -226
- package/src/state/persistence/session-persistence.integration.test.ts +0 -141
- package/src/state/persistence/session-persister.test.ts +0 -787
- package/src/state/persistence/session-persister.ts +0 -917
- package/src/state/persistence/session-snapshot.test.ts +0 -352
- package/src/state/persistence/session-snapshot.ts +0 -344
- package/src/state/persistence/stateful-restore.e2e.test.ts +0 -229
- package/src/state/session-store.ts +0 -56
- package/src/styles/ai-colours.ts +0 -30
- package/src/styles/menu.ts +0 -187
- package/src/styles/settings-section.ts +0 -40
- package/src/suggestions/chat-suggestions.ts +0 -186
- package/src/tags/index.ts +0 -1
- package/src/types/ai-chat-widget.ts +0 -67
- package/src/types/interaction-context.ts +0 -82
- package/src/utils/animated-panel-toggle.ts +0 -62
- package/src/utils/animation-exclusivity.test.ts +0 -72
- package/src/utils/animation-exclusivity.ts +0 -40
- package/src/utils/banked-usage-baselines.ts +0 -90
- package/src/utils/collect-session-models.test.ts +0 -82
- package/src/utils/collect-session-models.ts +0 -65
- package/src/utils/condense-history.test.ts +0 -746
- package/src/utils/condense-history.ts +0 -448
- package/src/utils/cost-session-history.test.ts +0 -226
- package/src/utils/cost-session-history.ts +0 -218
- package/src/utils/derive-cost-session-title.test.ts +0 -63
- package/src/utils/derive-cost-session-title.ts +0 -76
- package/src/utils/flatten-sub-agent-messages.test.ts +0 -163
- package/src/utils/flatten-sub-agent-messages.ts +0 -88
- package/src/utils/format-usd.ts +0 -26
- package/src/utils/history-transform.test.ts +0 -228
- package/src/utils/history-transform.ts +0 -163
- package/src/utils/index.ts +0 -3
- package/src/utils/logger.ts +0 -3
- package/src/utils/message-partition.test.ts +0 -129
- package/src/utils/message-partition.ts +0 -115
- package/src/utils/resolve-cost-history-config.test.ts +0 -38
- package/src/utils/resolve-cost-history-config.ts +0 -38
- package/src/utils/resolve-preference-baseline.test.ts +0 -84
- package/src/utils/resolve-preference-baseline.ts +0 -80
- package/src/utils/strip-agent-handlers.test.ts +0 -99
- package/src/utils/strip-agent-handlers.ts +0 -53
- package/src/utils/sum-costs.test.ts +0 -136
- package/src/utils/sum-costs.ts +0 -18
- package/src/utils/sum-tokens.test.ts +0 -93
- package/src/utils/sum-tokens.ts +0 -68
- package/src/utils/sum-usage.test.ts +0 -191
- package/src/utils/sum-usage.ts +0 -208
- package/src/utils/tool-fold.ts +0 -181
- package/src/utils/usage-rows.test.ts +0 -237
- package/src/utils/usage-rows.ts +0 -187
- package/src/utils/with-timeout.ts +0 -24
- 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();
|