@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
package/src/main/main.types.ts
DELETED
|
@@ -1,225 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* State of the AI assistant component.
|
|
3
|
-
*
|
|
4
|
-
* `cancelling` is a refinement of `loading`: a stop was requested but the turn
|
|
5
|
-
* is still winding down (e.g. a tool mid-execution finishing). It is "busy"
|
|
6
|
-
* like `loading` — use the host's `busy` getter for "is a turn active" gates.
|
|
7
|
-
*
|
|
8
|
-
* @beta
|
|
9
|
-
*/
|
|
10
|
-
export type AiAssistantState = 'idle' | 'loading' | 'cancelling' | 'error';
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Controls the pop-out button shown in the assistant header.
|
|
14
|
-
* - `"expand"` — assistant is embedded in the bubble dialog; button expands it to a layout panel.
|
|
15
|
-
* - `"collapse"` — assistant is in a layout panel; button collapses it back to the bubble.
|
|
16
|
-
*
|
|
17
|
-
* @beta
|
|
18
|
-
*/
|
|
19
|
-
export type PopoutMode = 'expand' | 'collapse';
|
|
20
|
-
|
|
21
|
-
export type { AgentPickerMode } from '@genesislcap/foundation-ai';
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Result returned by {@link FoundationAiAssistant.submitMessage}.
|
|
25
|
-
*
|
|
26
|
-
* `ok` is `false` when the assistant is busy, the message is empty, or any
|
|
27
|
-
* supplied file failed validation — in which case no send was dispatched and
|
|
28
|
-
* `errors` lists the reasons.
|
|
29
|
-
*
|
|
30
|
-
* @beta
|
|
31
|
-
*/
|
|
32
|
-
export interface SubmitMessageResult {
|
|
33
|
-
ok: boolean;
|
|
34
|
-
errors: string[];
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* `detail` of the `AiAssistantEvent.SessionCleared` event. Captured *before*
|
|
39
|
-
* teardown so a host can tidy up whatever the active agent was working on
|
|
40
|
-
* (generated files, server-side scratch, …). `agentSnapshot` is the agent's
|
|
41
|
-
* `serialize()` output (a state-machine image for machine-backed agents).
|
|
42
|
-
*
|
|
43
|
-
* @beta
|
|
44
|
-
*/
|
|
45
|
-
export interface SessionClearedDetail {
|
|
46
|
-
sessionKey: string | undefined;
|
|
47
|
-
agentName: string | undefined;
|
|
48
|
-
agentSnapshot: unknown;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* `detail` of the `AiAssistantEvent.ChatHeaderMouseDown` event.
|
|
53
|
-
*
|
|
54
|
-
* @beta
|
|
55
|
-
*/
|
|
56
|
-
export interface ChatHeaderMouseDownDetail {
|
|
57
|
-
clientX: number;
|
|
58
|
-
clientY: number;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* DOM events the `<foundation-ai-assistant>` element dispatches to its host.
|
|
63
|
-
* All bubble and are `composed` (they cross the shadow boundary), so a host can
|
|
64
|
-
* listen on the element — or any ancestor — to react. Use these constants to
|
|
65
|
-
* wire listeners instead of hand-typing event-name strings.
|
|
66
|
-
*
|
|
67
|
-
* An `as const` map (not a TS `enum` — this package ships none), so it serves as
|
|
68
|
-
* both the listener-name value and, via the same-named type below, a union.
|
|
69
|
-
*
|
|
70
|
-
* @example
|
|
71
|
-
* ```ts
|
|
72
|
-
* import { AiAssistantEvent, type SessionClearedDetail } from '@genesislcap/ai-assistant';
|
|
73
|
-
*
|
|
74
|
-
* el.addEventListener(AiAssistantEvent.SessionCleared, (e) => {
|
|
75
|
-
* const { agentName, agentSnapshot } = (e as CustomEvent<SessionClearedDetail>).detail;
|
|
76
|
-
* // …clean up external state the agent was working on…
|
|
77
|
-
* });
|
|
78
|
-
* ```
|
|
79
|
-
*
|
|
80
|
-
* @beta
|
|
81
|
-
*/
|
|
82
|
-
export const AiAssistantEvent = {
|
|
83
|
-
/** Session wiped via the lifecycle menu's Clear. `detail`: `SessionClearedDetail`. */
|
|
84
|
-
SessionCleared: 'session-cleared',
|
|
85
|
-
/** Header pressed in `popout-mode="expand"` (drag-to-popout hosts). `detail`: `ChatHeaderMouseDownDetail`. */
|
|
86
|
-
ChatHeaderMouseDown: 'chat-header-mousedown',
|
|
87
|
-
} as const;
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* One of the `AiAssistantEvent` event-name values.
|
|
91
|
-
*
|
|
92
|
-
* @beta
|
|
93
|
-
*/
|
|
94
|
-
export type AiAssistantEvent = (typeof AiAssistantEvent)[keyof typeof AiAssistantEvent];
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* One rendered row of the settings-modal budget meter (GENC-1464) — a vendor
|
|
98
|
-
* that currently has budget figures, pre-formatted so the template stays a pure
|
|
99
|
-
* binding layer (and so tests can pin the exact text a user reads).
|
|
100
|
-
*
|
|
101
|
-
* @beta
|
|
102
|
-
*/
|
|
103
|
-
export interface SettingsBudgetRow {
|
|
104
|
-
/** The vendor the row describes (an `AIProviderType` member). */
|
|
105
|
-
vendor: string;
|
|
106
|
-
/** Display name from `VENDOR_LABELS`, e.g. `Anthropic`. */
|
|
107
|
-
label: string;
|
|
108
|
-
/**
|
|
109
|
-
* The real figures — `$45.00 / $50.00 (90%)`. The percentage is NOT clamped:
|
|
110
|
-
* spend can genuinely overshoot the cap (the last allowed call may cross it),
|
|
111
|
-
* and the text tells the truth about it.
|
|
112
|
-
*/
|
|
113
|
-
figures: string;
|
|
114
|
-
/**
|
|
115
|
-
* The bar's value, clamped to `0..100` — a progress bar past its end renders
|
|
116
|
-
* nonsense, so only the bar clamps (mirroring the context-usage indicator's
|
|
117
|
-
* `Math.min(100, …)`).
|
|
118
|
-
*/
|
|
119
|
-
barValue: number;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* State of the chat suggestions feature.
|
|
124
|
-
*
|
|
125
|
-
* @beta
|
|
126
|
-
*/
|
|
127
|
-
export type SuggestionsState =
|
|
128
|
-
| { status: 'idle' }
|
|
129
|
-
| { status: 'loading' }
|
|
130
|
-
| { status: 'loaded'; suggestions: string[] }
|
|
131
|
-
| { status: 'error'; message: string };
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
* Metadata describing a UI animation in the assistant.
|
|
135
|
-
*
|
|
136
|
-
* @beta
|
|
137
|
-
*/
|
|
138
|
-
export interface AiAssistantAnimationDef {
|
|
139
|
-
/** Display label shown in the settings multiselect. */
|
|
140
|
-
label: string;
|
|
141
|
-
/** Short description shown beneath the label in the categorized multiselect. */
|
|
142
|
-
description: string;
|
|
143
|
-
/** Group heading the option is listed under in the settings multiselect. */
|
|
144
|
-
category: string;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
/**
|
|
148
|
-
* Registry of all available animations with their display metadata.
|
|
149
|
-
* Adding an entry here automatically extends the {@link AiAssistantAnimation} type.
|
|
150
|
-
*
|
|
151
|
-
* @remarks
|
|
152
|
-
* `loading` (dots), `waves`, `flowingWaves` and `plasma` are interchangeable
|
|
153
|
-
* styles of the same "is the assistant working" indicator and are therefore
|
|
154
|
-
* grouped under the same {@link AiAssistantAnimationDef.category}. They are
|
|
155
|
-
* mutually exclusive — see `LOADING_STYLE_ANIMATIONS`.
|
|
156
|
-
*
|
|
157
|
-
* @beta
|
|
158
|
-
*/
|
|
159
|
-
export const ANIMATION_DEFS = {
|
|
160
|
-
loading: {
|
|
161
|
-
label: 'Dots',
|
|
162
|
-
description: 'Shows pulsing dots while the assistant is generating a response.',
|
|
163
|
-
category: 'Loading style',
|
|
164
|
-
},
|
|
165
|
-
waves: {
|
|
166
|
-
label: 'Waves',
|
|
167
|
-
description:
|
|
168
|
-
'Shows glowing sine waves inside a circle while the assistant is generating a response.',
|
|
169
|
-
category: 'Loading style',
|
|
170
|
-
},
|
|
171
|
-
flowingWaves: {
|
|
172
|
-
label: 'Flowing waves',
|
|
173
|
-
description:
|
|
174
|
-
'Shows coloured waves rising and settling from a line while the assistant is generating a response.',
|
|
175
|
-
category: 'Loading style',
|
|
176
|
-
},
|
|
177
|
-
plasma: {
|
|
178
|
-
label: 'Plasma orb',
|
|
179
|
-
description:
|
|
180
|
-
'Shows a glowing plasma sphere with drifting energy while the assistant is generating a response.',
|
|
181
|
-
category: 'Loading style',
|
|
182
|
-
},
|
|
183
|
-
halo: {
|
|
184
|
-
label: 'Halo',
|
|
185
|
-
description:
|
|
186
|
-
'Displays a glowing halo around the assistant avatar while a response is streaming.',
|
|
187
|
-
category: 'Effects',
|
|
188
|
-
},
|
|
189
|
-
} satisfies Record<string, AiAssistantAnimationDef>;
|
|
190
|
-
|
|
191
|
-
/**
|
|
192
|
-
* Union of all available animation names, derived from {@link ANIMATION_DEFS}.
|
|
193
|
-
*
|
|
194
|
-
* @beta
|
|
195
|
-
*/
|
|
196
|
-
export type AiAssistantAnimation = keyof typeof ANIMATION_DEFS;
|
|
197
|
-
|
|
198
|
-
/**
|
|
199
|
-
* All available animation names, derived from the registry.
|
|
200
|
-
*
|
|
201
|
-
* @internal
|
|
202
|
-
*/
|
|
203
|
-
export const ALL_ANIMATIONS = Object.keys(ANIMATION_DEFS) as AiAssistantAnimation[];
|
|
204
|
-
|
|
205
|
-
/**
|
|
206
|
-
* The interchangeable "assistant is working" loading-indicator styles. At most
|
|
207
|
-
* one of these may be enabled at a time — enabling one disables the other.
|
|
208
|
-
*
|
|
209
|
-
* @internal
|
|
210
|
-
*/
|
|
211
|
-
export const LOADING_STYLE_ANIMATIONS = [
|
|
212
|
-
'loading',
|
|
213
|
-
'waves',
|
|
214
|
-
'flowingWaves',
|
|
215
|
-
'plasma',
|
|
216
|
-
] as const satisfies readonly AiAssistantAnimation[];
|
|
217
|
-
|
|
218
|
-
/**
|
|
219
|
-
* Animations enabled by default when a consumer opts into the animations
|
|
220
|
-
* feature without specifying an explicit `enabled` list. Keeps the dots loading
|
|
221
|
-
* style (the long-standing default); the waves style is opt-in.
|
|
222
|
-
*
|
|
223
|
-
* @internal
|
|
224
|
-
*/
|
|
225
|
-
export const DEFAULT_ANIMATIONS: AiAssistantAnimation[] = ['loading', 'halo'];
|
|
@@ -1,219 +0,0 @@
|
|
|
1
|
-
import { assert, createLogicSuite } from '@genesislcap/foundation-testing';
|
|
2
|
-
import { DOM } from '@genesislcap/web-core';
|
|
3
|
-
import { FoundationAiAssistant } from './main';
|
|
4
|
-
|
|
5
|
-
// Hold a reference so the custom-element registration isn't tree-shaken.
|
|
6
|
-
FoundationAiAssistant;
|
|
7
|
-
|
|
8
|
-
// GENC-1511 — the blocking "not saving" modal has MORE THAN ONE reporter: this element's own
|
|
9
|
-
// session persister (`sessions/<key>`), and a host reporting its own keyspaces through the public
|
|
10
|
-
// API (Create's `projects/<id>.json`, which holds the app rather than the transcript).
|
|
11
|
-
//
|
|
12
|
-
// It was first built on a single `persistenceBroken` boolean, and review caught what that costs:
|
|
13
|
-
// whichever reporter recovered FIRST closed the modal for both, and the host's own re-entry guard
|
|
14
|
-
// then kept it from ever being raised again. This suite pins the per-source behaviour so that
|
|
15
|
-
// collision cannot come back.
|
|
16
|
-
//
|
|
17
|
-
// Like `blocked-state.test.ts`, this exercises the METHODS the template bindings read rather than
|
|
18
|
-
// the rendered DOM: `document.createElement` upgrades the element (constructor) without connecting
|
|
19
|
-
// it, so `connectedCallback` never runs and nothing subscribes to `agenticActivityBus` — which
|
|
20
|
-
// would otherwise hold the test runner's event loop open.
|
|
21
|
-
const Suite = createLogicSuite('FoundationAiAssistant persistence-broken sources');
|
|
22
|
-
|
|
23
|
-
/** A fresh, unconnected element. Nothing here needs a session store. */
|
|
24
|
-
const element = (): FoundationAiAssistant =>
|
|
25
|
-
document.createElement('foundation-ai-assistant') as FoundationAiAssistant;
|
|
26
|
-
|
|
27
|
-
/** The modal's visible copy, as the template bindings read it. */
|
|
28
|
-
const copy = (el: FoundationAiAssistant) => ({
|
|
29
|
-
broken: el.persistenceBroken,
|
|
30
|
-
message: el.persistenceBrokenMessage,
|
|
31
|
-
detail: el.persistenceBrokenDetail,
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
const SESSION = 'session';
|
|
35
|
-
const PROJECT = 'project';
|
|
36
|
-
|
|
37
|
-
Suite('a single reporter raises and withdraws its own warning', () => {
|
|
38
|
-
const el = element();
|
|
39
|
-
assert.is(el.persistenceBroken, false);
|
|
40
|
-
|
|
41
|
-
el.reportPersistenceBroken({ detail: '2 messages have not been saved.', source: SESSION });
|
|
42
|
-
assert.is(el.persistenceBroken, true);
|
|
43
|
-
assert.is(el.persistenceBrokenDetail, '2 messages have not been saved.');
|
|
44
|
-
|
|
45
|
-
el.reportPersistenceRecovered(SESSION);
|
|
46
|
-
assert.is(el.persistenceBroken, false);
|
|
47
|
-
assert.is(el.persistenceBrokenMessage, undefined);
|
|
48
|
-
assert.is(el.persistenceBrokenDetail, undefined);
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
Suite('one source recovering does NOT withdraw another still-broken source', () => {
|
|
52
|
-
const el = element();
|
|
53
|
-
el.reportPersistenceBroken({ detail: 'session detail', source: SESSION });
|
|
54
|
-
el.reportPersistenceBroken({ message: 'project copy', source: PROJECT });
|
|
55
|
-
|
|
56
|
-
// The session's own save lands. Its warning goes; the project's must not.
|
|
57
|
-
el.reportPersistenceRecovered(SESSION);
|
|
58
|
-
|
|
59
|
-
assert.is(el.persistenceBroken, true, 'modal must stay up while the project store is failing');
|
|
60
|
-
assert.is(el.persistenceBrokenMessage, 'project copy', 'and must still describe THAT failure');
|
|
61
|
-
|
|
62
|
-
el.reportPersistenceRecovered(PROJECT);
|
|
63
|
-
assert.is(el.persistenceBroken, false, 'only once nothing is broken');
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
Suite('a later report does not overwrite an earlier source with its own copy', () => {
|
|
67
|
-
const el = element();
|
|
68
|
-
el.reportPersistenceBroken({
|
|
69
|
-
message: 'project copy',
|
|
70
|
-
detail: 'project detail',
|
|
71
|
-
source: PROJECT,
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
// The session reports with NO message override — it wants the template's session default.
|
|
75
|
-
// Before per-source tracking this assigned `undefined` over the project wording, so the modal
|
|
76
|
-
// claimed "this session has stopped saving" about a failed PROJECT write.
|
|
77
|
-
el.reportPersistenceBroken({ detail: 'session detail', source: SESSION });
|
|
78
|
-
assert.is(el.persistenceBrokenMessage, undefined, 'newest source wins while it is broken');
|
|
79
|
-
assert.is(el.persistenceBrokenDetail, 'session detail');
|
|
80
|
-
|
|
81
|
-
// ...and when the newest recovers, the copy falls BACK to the survivor rather than staying
|
|
82
|
-
// on the recovered source's wording (or reverting to the default).
|
|
83
|
-
el.reportPersistenceRecovered(SESSION);
|
|
84
|
-
assert.is(el.persistenceBrokenMessage, 'project copy');
|
|
85
|
-
assert.is(el.persistenceBrokenDetail, 'project detail');
|
|
86
|
-
assert.is(el.persistenceBroken, true);
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
Suite('recovering an unknown or already-recovered source is a no-op', () => {
|
|
90
|
-
const el = element();
|
|
91
|
-
el.reportPersistenceBroken({ message: 'project copy', source: PROJECT });
|
|
92
|
-
|
|
93
|
-
el.reportPersistenceRecovered(SESSION); // never reported
|
|
94
|
-
assert.equal(copy(el), { broken: true, message: 'project copy', detail: undefined });
|
|
95
|
-
|
|
96
|
-
el.reportPersistenceRecovered(PROJECT);
|
|
97
|
-
el.reportPersistenceRecovered(PROJECT); // twice
|
|
98
|
-
assert.equal(copy(el), { broken: false, message: undefined, detail: undefined });
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
Suite('re-reporting the same source refreshes its copy without duplicating it', () => {
|
|
102
|
-
const el = element();
|
|
103
|
-
el.reportPersistenceBroken({ detail: '2 messages have not been saved.', source: SESSION });
|
|
104
|
-
el.reportPersistenceBroken({ detail: '5 messages have not been saved.', source: SESSION });
|
|
105
|
-
assert.is(el.persistenceBrokenDetail, '5 messages have not been saved.');
|
|
106
|
-
|
|
107
|
-
// One recovery must clear it — a second entry for the same source would leave it stuck on.
|
|
108
|
-
el.reportPersistenceRecovered(SESSION);
|
|
109
|
-
assert.is(el.persistenceBroken, false);
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
Suite('a host that omits the source gets a default it can still recover', () => {
|
|
113
|
-
const el = element();
|
|
114
|
-
el.reportPersistenceBroken({ message: 'host copy' });
|
|
115
|
-
assert.is(el.persistenceBroken, true);
|
|
116
|
-
|
|
117
|
-
el.reportPersistenceRecovered();
|
|
118
|
-
assert.is(el.persistenceBroken, false);
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
Suite("a host's default source is independent of the session's", () => {
|
|
122
|
-
const el = element();
|
|
123
|
-
el.reportPersistenceBroken({ detail: 'session detail', source: SESSION });
|
|
124
|
-
el.reportPersistenceBroken({ message: 'host copy' });
|
|
125
|
-
|
|
126
|
-
el.reportPersistenceRecovered(); // the host's
|
|
127
|
-
assert.is(el.persistenceBroken, true, 'the session failure is still live');
|
|
128
|
-
assert.is(el.persistenceBrokenDetail, 'session detail');
|
|
129
|
-
});
|
|
130
|
-
|
|
131
|
-
// GENC-1511 (PR #2472 review) — the deferred show is a separate race from the source tracking.
|
|
132
|
-
// `persistenceBrokenChanged` queues the show via `DOM.queueUpdate`, and the queued callback used
|
|
133
|
-
// not to re-read the flag. A `true → false` inside the same batch runs the `!broken` branch against
|
|
134
|
-
// a modal that was never shown (both statements no-op), and the callback then raised a blocking,
|
|
135
|
-
// NON-DISMISSIBLE modal for a problem that had already fixed itself — with no further change event
|
|
136
|
-
// left to close it, so the only way out was a reload nobody needed.
|
|
137
|
-
//
|
|
138
|
-
// Reachable because `maybeReportBroken` fires before `provider.save` in `persistSession`, so a
|
|
139
|
-
// report and the write that withdraws it can share a tick.
|
|
140
|
-
|
|
141
|
-
/** Minimal stand-in for the design-system modal, recording what the callback did to it. */
|
|
142
|
-
function modalStub() {
|
|
143
|
-
const calls = { show: 0, close: 0 };
|
|
144
|
-
const dialog = document.createElement('dialog');
|
|
145
|
-
return {
|
|
146
|
-
calls,
|
|
147
|
-
modal: {
|
|
148
|
-
open: false,
|
|
149
|
-
mainElement: dialog,
|
|
150
|
-
show() {
|
|
151
|
-
calls.show += 1;
|
|
152
|
-
this.open = true;
|
|
153
|
-
},
|
|
154
|
-
close() {
|
|
155
|
-
calls.close += 1;
|
|
156
|
-
this.open = false;
|
|
157
|
-
},
|
|
158
|
-
},
|
|
159
|
-
};
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
/**
|
|
163
|
-
* Drain the FAST update queue SYNCHRONOUSLY.
|
|
164
|
-
*
|
|
165
|
-
* `DOM.processUpdates()` and not an `await setTimeout(0)`: the queue lands on
|
|
166
|
-
* `requestAnimationFrame`, which a zero-delay timer does not reliably cover. A timer-based flush
|
|
167
|
-
* made these tests pass or fail on scheduling luck — the "does not show" assertion passed for the
|
|
168
|
-
* wrong reason, and its positive control passed only because earlier tests had pumped the queue.
|
|
169
|
-
*/
|
|
170
|
-
const flush = () => DOM.processUpdates();
|
|
171
|
-
|
|
172
|
-
const withModal = (el: FoundationAiAssistant, modal: unknown) => {
|
|
173
|
-
(el as unknown as { persistenceModal: unknown }).persistenceModal = modal;
|
|
174
|
-
};
|
|
175
|
-
|
|
176
|
-
// POSITIVE CONTROL for the test below. Without it, a queue that never drains in this environment
|
|
177
|
-
// would make the "does not show" assertion pass for entirely the wrong reason.
|
|
178
|
-
Suite('the deferred show DOES raise the modal when the failure is still live', () => {
|
|
179
|
-
const el = element();
|
|
180
|
-
const { calls, modal } = modalStub();
|
|
181
|
-
withModal(el, modal);
|
|
182
|
-
|
|
183
|
-
el.reportPersistenceBroken({ detail: 'session detail', source: SESSION });
|
|
184
|
-
flush();
|
|
185
|
-
|
|
186
|
-
assert.is(calls.show, 1, 'precondition: the queued callback runs in this environment');
|
|
187
|
-
assert.is(modal.open, true);
|
|
188
|
-
});
|
|
189
|
-
|
|
190
|
-
Suite('a recovery inside the same batch cancels the deferred show', () => {
|
|
191
|
-
const el = element();
|
|
192
|
-
const { calls, modal } = modalStub();
|
|
193
|
-
withModal(el, modal);
|
|
194
|
-
|
|
195
|
-
el.reportPersistenceBroken({ detail: 'session detail', source: SESSION });
|
|
196
|
-
el.reportPersistenceRecovered(SESSION); // lands before the queue flushes
|
|
197
|
-
flush();
|
|
198
|
-
|
|
199
|
-
assert.is(el.persistenceBroken, false);
|
|
200
|
-
assert.is(calls.show, 0, 'must not raise a blocking modal for a resolved failure');
|
|
201
|
-
assert.is(modal.open, false);
|
|
202
|
-
});
|
|
203
|
-
|
|
204
|
-
Suite('a recovery of ONE source still shows for the source left broken', () => {
|
|
205
|
-
const el = element();
|
|
206
|
-
const { calls, modal } = modalStub();
|
|
207
|
-
withModal(el, modal);
|
|
208
|
-
|
|
209
|
-
el.reportPersistenceBroken({ detail: 'session detail', source: SESSION });
|
|
210
|
-
el.reportPersistenceBroken({ message: 'project copy', source: PROJECT });
|
|
211
|
-
el.reportPersistenceRecovered(SESSION);
|
|
212
|
-
flush();
|
|
213
|
-
|
|
214
|
-
assert.is(el.persistenceBroken, true);
|
|
215
|
-
assert.is(calls.show, 1, 'the project failure still warrants the modal');
|
|
216
|
-
assert.is(el.persistenceBrokenMessage, 'project copy');
|
|
217
|
-
});
|
|
218
|
-
|
|
219
|
-
Suite.run();
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
import type { ChatMessage } from '@genesislcap/foundation-ai';
|
|
2
|
-
import { assert, createLogicSuite } from '@genesislcap/foundation-testing';
|
|
3
|
-
import { FoundationAiAssistant } from './main';
|
|
4
|
-
|
|
5
|
-
// Hold a reference so the custom-element registration isn't tree-shaken.
|
|
6
|
-
FoundationAiAssistant;
|
|
7
|
-
|
|
8
|
-
// GENC-1351 §5.11 (PR review): the single-element popout refactor removed the
|
|
9
|
-
// `claimSideEffect` first-writer latch, so the only thing preventing a pending
|
|
10
|
-
// interaction widget from being re-instantiated (and re-firing its side effect) on a
|
|
11
|
-
// dock/undock move is that the popout control is disabled while an interaction is
|
|
12
|
-
// pending — the template binds `?disabled=${x.hasActivePendingInteraction}`
|
|
13
|
-
// (`main.template.ts`). This suite pins the GATE LOGIC (`hasActivePendingInteraction`)
|
|
14
|
-
// that binding depends on, so a change to when the gate opens/closes is caught.
|
|
15
|
-
//
|
|
16
|
-
// Note: this deliberately does NOT mount the assistant. Mounting runs `connectedCallback`,
|
|
17
|
-
// which subscribes to `agenticActivityBus` — opening a cross-tab `BroadcastChannel` in a browser
|
|
18
|
-
// env and leaving the runner's event loop open. A getter-level test needs no mount and stays fast
|
|
19
|
-
// + reliable. `document.createElement` only upgrades the element (constructor) — it does not
|
|
20
|
-
// connect — so nothing subscribes, and the bus opens its channel lazily on first use, so none is
|
|
21
|
-
// ever created here (no teardown needed).
|
|
22
|
-
|
|
23
|
-
const Suite = createLogicSuite('FoundationAiAssistant popout interaction gate');
|
|
24
|
-
|
|
25
|
-
/** A fresh (unconnected) element with a fake session store wired in. */
|
|
26
|
-
function elementWith(state: string, messages: ChatMessage[]): FoundationAiAssistant {
|
|
27
|
-
const el = document.createElement('foundation-ai-assistant') as FoundationAiAssistant;
|
|
28
|
-
(el as unknown as { _sessionRef: unknown })._sessionRef = {
|
|
29
|
-
store: { aiAssistant: { state, messages } },
|
|
30
|
-
};
|
|
31
|
-
return el;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
const withInteraction = (resolved: boolean | { value: string }): ChatMessage[] => [
|
|
35
|
-
{ role: 'user', content: 'hi' } as ChatMessage,
|
|
36
|
-
{
|
|
37
|
-
role: 'assistant',
|
|
38
|
-
content: resolved ? 'done' : '',
|
|
39
|
-
interaction: { interactionId: '1', componentName: 'x', data: {}, resolved },
|
|
40
|
-
} as unknown as ChatMessage,
|
|
41
|
-
];
|
|
42
|
-
|
|
43
|
-
Suite('is true only while a turn is running AND a pending interaction is the last message', () => {
|
|
44
|
-
// Gated: a turn is running and the last message is an unresolved interaction. This is
|
|
45
|
-
// the state during which the popout/dock control MUST be disabled.
|
|
46
|
-
assert.is(
|
|
47
|
-
elementWith('loading', withInteraction(false)).hasActivePendingInteraction,
|
|
48
|
-
true,
|
|
49
|
-
'busy + unresolved interaction → gated',
|
|
50
|
-
);
|
|
51
|
-
// `cancelling` counts as busy too (a stop was requested but the turn is winding down).
|
|
52
|
-
assert.is(
|
|
53
|
-
elementWith('cancelling', withInteraction(false)).hasActivePendingInteraction,
|
|
54
|
-
true,
|
|
55
|
-
'cancelling + unresolved interaction → gated',
|
|
56
|
-
);
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
Suite('is false when idle, when the interaction is resolved, or when there is none', () => {
|
|
60
|
-
// Not busy → never gated, even with an unresolved interaction present.
|
|
61
|
-
assert.is(
|
|
62
|
-
elementWith('idle', withInteraction(false)).hasActivePendingInteraction,
|
|
63
|
-
false,
|
|
64
|
-
'idle → not gated',
|
|
65
|
-
);
|
|
66
|
-
// Busy but the interaction has resolved → the widget is answered, nothing to strand.
|
|
67
|
-
assert.is(
|
|
68
|
-
elementWith('loading', withInteraction({ value: 'ok' })).hasActivePendingInteraction,
|
|
69
|
-
false,
|
|
70
|
-
'resolved interaction → not gated',
|
|
71
|
-
);
|
|
72
|
-
// Busy but the last message is not an interaction at all.
|
|
73
|
-
assert.is(
|
|
74
|
-
elementWith('loading', [{ role: 'assistant', content: 'thinking' } as ChatMessage])
|
|
75
|
-
.hasActivePendingInteraction,
|
|
76
|
-
false,
|
|
77
|
-
'no interaction → not gated',
|
|
78
|
-
);
|
|
79
|
-
// No session / empty transcript.
|
|
80
|
-
assert.is(
|
|
81
|
-
elementWith('loading', []).hasActivePendingInteraction,
|
|
82
|
-
false,
|
|
83
|
-
'empty transcript → not gated',
|
|
84
|
-
);
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
Suite.run();
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import { DI } from '@genesislcap/web-core';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Optional app-registered policy for which cloud vendor backs the tier-shaped
|
|
5
|
-
* provider registry slots (`low` / `high` / …). Apps inject a concrete
|
|
6
|
-
* implementation on this DI token at bootstrap; consumers include the
|
|
7
|
-
* slotted `settings-model` component or a header vendor control.
|
|
8
|
-
* The platform settings modal does not render vendor UI itself.
|
|
9
|
-
*
|
|
10
|
-
* @beta
|
|
11
|
-
*/
|
|
12
|
-
export interface AIProviderSwitcher {
|
|
13
|
-
readonly vendor: string;
|
|
14
|
-
readonly vendors: readonly string[];
|
|
15
|
-
switchTo(vendor: string): void;
|
|
16
|
-
subscribe(listener: (vendor: string) => void): () => void;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
class NoopAIProviderSwitcher implements AIProviderSwitcher {
|
|
20
|
-
readonly vendor = '';
|
|
21
|
-
readonly vendors: readonly string[] = [];
|
|
22
|
-
switchTo(): void {
|
|
23
|
-
/* no-op */
|
|
24
|
-
}
|
|
25
|
-
subscribe(): () => void {
|
|
26
|
-
return () => {
|
|
27
|
-
/* no-op */
|
|
28
|
-
};
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* The DI token for the {@link (AIProviderSwitcher:interface)}. Resolves a noop until the app
|
|
34
|
-
* registers one.
|
|
35
|
-
*
|
|
36
|
-
* @beta
|
|
37
|
-
*/
|
|
38
|
-
export const AIProviderSwitcher = DI.createInterface<AIProviderSwitcher>((x) =>
|
|
39
|
-
x.singleton(NoopAIProviderSwitcher),
|
|
40
|
-
);
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
import { DI } from '@genesislcap/web-core';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* One boolean toggle rendered in the platform settings modal app section.
|
|
5
|
-
*
|
|
6
|
-
* @beta
|
|
7
|
-
*/
|
|
8
|
-
export interface AssistantAppSettingsToggle {
|
|
9
|
-
/** Stable id passed to {@link (AssistantAppSettingsProvider:interface).getValue} / `setValue`. */
|
|
10
|
-
id: string;
|
|
11
|
-
title: string;
|
|
12
|
-
description: string;
|
|
13
|
-
/** Optional `part` name for the toggle row (defaults to `app-toggle-${id}`). */
|
|
14
|
-
part?: string;
|
|
15
|
-
/** When provided and returns false, the toggle is hidden. */
|
|
16
|
-
visible?: () => boolean;
|
|
17
|
-
/** When provided and returns true, the switch is disabled. */
|
|
18
|
-
disabled?: () => boolean;
|
|
19
|
-
/** Optional footnote rendered below the row when the string is non-empty. */
|
|
20
|
-
hint?: () => string | undefined;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Optional heading above a provider's toggle group.
|
|
25
|
-
*
|
|
26
|
-
* Entirely host-supplied — the assistant has no default title and no default icon, because the
|
|
27
|
-
* section belongs to the host. Omit it and the toggles render bare, which is right when the
|
|
28
|
-
* host's slotted content already titles them.
|
|
29
|
-
*
|
|
30
|
-
* @beta
|
|
31
|
-
*/
|
|
32
|
-
export interface AssistantAppSettingsHeading {
|
|
33
|
-
readonly title: string;
|
|
34
|
-
/**
|
|
35
|
-
* Icon name for the design system's icon element (a Font Awesome free name, e.g.
|
|
36
|
-
* `'object-group'`). Omitted renders text only; an unknown name renders nothing at all, so
|
|
37
|
-
* check it against the installed Font Awesome set.
|
|
38
|
-
*/
|
|
39
|
-
readonly icon?: string;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* App-supplied settings for the host's own section of the settings modal. Register a concrete
|
|
44
|
-
* implementation on the DI token at app bootstrap; the assistant renders the toggles with the
|
|
45
|
-
* same row layout as AI Chat Bot settings.
|
|
46
|
-
*
|
|
47
|
-
* The section itself is untitled by the assistant — no heading text and no icon — because only
|
|
48
|
-
* the host knows what it is. Title it from the `settings-app` slot, which renders above these
|
|
49
|
-
* toggles, and apply `assistantSettingsSectionTitleStyles` to match the built-in headings.
|
|
50
|
-
*
|
|
51
|
-
* @beta
|
|
52
|
-
*/
|
|
53
|
-
export interface AssistantAppSettingsProvider {
|
|
54
|
-
readonly toggles: readonly AssistantAppSettingsToggle[];
|
|
55
|
-
/**
|
|
56
|
-
* Heading for the toggle group, for hosts that put other controls in the `settings-app` slot
|
|
57
|
-
* and need these distinguished from them. No default: absent means no heading.
|
|
58
|
-
*/
|
|
59
|
-
readonly togglesHeading?: AssistantAppSettingsHeading;
|
|
60
|
-
getValue(id: string): boolean;
|
|
61
|
-
setValue(id: string, value: boolean): void;
|
|
62
|
-
/** Notify the assistant to re-read toggle values / visibility. */
|
|
63
|
-
subscribe?(listener: () => void): () => void;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
class NoopAssistantAppSettingsProvider implements AssistantAppSettingsProvider {
|
|
67
|
-
readonly toggles: readonly AssistantAppSettingsToggle[] = [];
|
|
68
|
-
getValue(): boolean {
|
|
69
|
-
return false;
|
|
70
|
-
}
|
|
71
|
-
setValue(): void {
|
|
72
|
-
/* no-op */
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* The DI token for the {@link (AssistantAppSettingsProvider:interface)}. Resolves a noop
|
|
78
|
-
* until the host registers one.
|
|
79
|
-
*
|
|
80
|
-
* @beta
|
|
81
|
-
*/
|
|
82
|
-
export const AssistantAppSettingsProvider = DI.createInterface<AssistantAppSettingsProvider>((x) =>
|
|
83
|
-
x.singleton(NoopAssistantAppSettingsProvider),
|
|
84
|
-
);
|