@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,79 +0,0 @@
|
|
|
1
|
-
import type { AiDriver } from '../components/ai-driver/ai-driver';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Module-level registry of AI drivers keyed by session identity string.
|
|
5
|
-
*
|
|
6
|
-
* Driver lifetime is tied to the conversation session, not the DOM.
|
|
7
|
-
* Components look up or create drivers on connect and only unwire
|
|
8
|
-
* event listeners on disconnect — the driver is never destroyed by
|
|
9
|
-
* a lifecycle event.
|
|
10
|
-
*
|
|
11
|
-
* @internal
|
|
12
|
-
*/
|
|
13
|
-
interface DriverRegistryEntry {
|
|
14
|
-
driver: AiDriver;
|
|
15
|
-
/**
|
|
16
|
-
* Fingerprint (see `FoundationAiAssistant.getAgentsKey`) of the agents array
|
|
17
|
-
* the driver was built for. Lets a second component sharing the same session
|
|
18
|
-
* key recognise that the registry driver already matches its desired agents
|
|
19
|
-
* and ADOPT it, instead of tearing it down and recreating — which would evict
|
|
20
|
-
* the sibling's driver and orphan whichever element is mid-turn on it
|
|
21
|
-
* (GENC-1388).
|
|
22
|
-
*/
|
|
23
|
-
agentsKey: string;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
const driverRegistry = new Map<string, DriverRegistryEntry>();
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Returns the existing driver for the given key, or calls the factory to create
|
|
30
|
-
* and register a new one. `agentsKey` is the fingerprint of the agents the
|
|
31
|
-
* driver is being built for; it is recorded only when a driver is created (a
|
|
32
|
-
* reused driver keeps the fingerprint it was originally built with).
|
|
33
|
-
*/
|
|
34
|
-
export function getOrCreateDriver(
|
|
35
|
-
key: string,
|
|
36
|
-
agentsKey: string,
|
|
37
|
-
factory: () => AiDriver,
|
|
38
|
-
): AiDriver {
|
|
39
|
-
const existing = driverRegistry.get(key);
|
|
40
|
-
if (existing) return existing.driver;
|
|
41
|
-
const driver = factory();
|
|
42
|
-
driverRegistry.set(key, { driver, agentsKey });
|
|
43
|
-
return driver;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Returns the existing driver for the given key, or `undefined`.
|
|
48
|
-
*/
|
|
49
|
-
export function getDriver(key: string): AiDriver | undefined {
|
|
50
|
-
return driverRegistry.get(key)?.driver;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* The agents fingerprint the registry driver for `key` was built with, or
|
|
55
|
-
* `undefined` if no driver is registered. Used by `agentsChanged` to decide
|
|
56
|
-
* whether a sibling has already rebuilt the shared driver to the desired agents.
|
|
57
|
-
*/
|
|
58
|
-
export function getDriverAgentsKey(key: string): string | undefined {
|
|
59
|
-
return driverRegistry.get(key)?.agentsKey;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Removes and returns the driver for the given key.
|
|
64
|
-
* Used when agents change (driver must be rebuilt) or on explicit session teardown.
|
|
65
|
-
*/
|
|
66
|
-
export function deleteDriver(key: string): AiDriver | undefined {
|
|
67
|
-
const entry = driverRegistry.get(key);
|
|
68
|
-
driverRegistry.delete(key);
|
|
69
|
-
return entry?.driver;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* Removes all entries. Exposed for test isolation only — not part of the public API.
|
|
74
|
-
*
|
|
75
|
-
* @internal
|
|
76
|
-
*/
|
|
77
|
-
export function clearDriverRegistry(): void {
|
|
78
|
-
driverRegistry.clear();
|
|
79
|
-
}
|
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
import { assert, createLogicSuite } from '@genesislcap/foundation-testing';
|
|
2
|
-
import { createInteractionContext } from './interaction-context';
|
|
3
|
-
|
|
4
|
-
const suite = createLogicSuite('interaction-context factory');
|
|
5
|
-
|
|
6
|
-
suite('once runs the factory a single time and memoises the result', () => {
|
|
7
|
-
const { context } = createInteractionContext('id-1');
|
|
8
|
-
let calls = 0;
|
|
9
|
-
const first = context.once('ws', () => {
|
|
10
|
-
calls += 1;
|
|
11
|
-
return { socket: true };
|
|
12
|
-
});
|
|
13
|
-
const second = context.once('ws', () => {
|
|
14
|
-
calls += 1;
|
|
15
|
-
return { socket: false };
|
|
16
|
-
});
|
|
17
|
-
assert.is(calls, 1, 'factory ran once');
|
|
18
|
-
assert.is(second, first, 'the memoised value is returned on the second call');
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
suite('subscribe/notify fans out to listeners; unsubscribe stops them', () => {
|
|
22
|
-
const { context } = createInteractionContext('id-2');
|
|
23
|
-
let a = 0;
|
|
24
|
-
let b = 0;
|
|
25
|
-
const unsubA = context.subscribe(() => (a += 1));
|
|
26
|
-
context.subscribe(() => (b += 1));
|
|
27
|
-
|
|
28
|
-
context.notify();
|
|
29
|
-
assert.is(a, 1);
|
|
30
|
-
assert.is(b, 1);
|
|
31
|
-
|
|
32
|
-
unsubA();
|
|
33
|
-
context.notify();
|
|
34
|
-
assert.is(a, 1, 'unsubscribed listener no longer fires');
|
|
35
|
-
assert.is(b, 2, 'remaining listener still fires');
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
suite('a throwing subscriber does not stop the others', () => {
|
|
39
|
-
const { context } = createInteractionContext('id-3');
|
|
40
|
-
let reached = false;
|
|
41
|
-
context.subscribe(() => {
|
|
42
|
-
throw new Error('boom');
|
|
43
|
-
});
|
|
44
|
-
context.subscribe(() => (reached = true));
|
|
45
|
-
context.notify();
|
|
46
|
-
assert.ok(reached, 'later subscriber still ran after an earlier one threw');
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
suite('dispose runs every onDispose callback once, then is idempotent', () => {
|
|
50
|
-
const { context, dispose } = createInteractionContext('id-4');
|
|
51
|
-
let count = 0;
|
|
52
|
-
context.onDispose(() => (count += 1));
|
|
53
|
-
context.onDispose(() => (count += 1));
|
|
54
|
-
|
|
55
|
-
dispose();
|
|
56
|
-
assert.is(count, 2, 'both disposers ran');
|
|
57
|
-
dispose();
|
|
58
|
-
assert.is(count, 2, 'a second dispose is a no-op');
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
suite('onDispose registered after dispose runs immediately', () => {
|
|
62
|
-
const { context, dispose } = createInteractionContext('id-5');
|
|
63
|
-
dispose();
|
|
64
|
-
let ran = false;
|
|
65
|
-
context.onDispose(() => (ran = true));
|
|
66
|
-
assert.ok(ran, 'late onDispose runs immediately so no resource leaks');
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
suite('notify after dispose is a no-op (listeners cleared)', () => {
|
|
70
|
-
const { context, dispose } = createInteractionContext('id-6');
|
|
71
|
-
let fired = 0;
|
|
72
|
-
context.subscribe(() => (fired += 1));
|
|
73
|
-
dispose();
|
|
74
|
-
context.notify();
|
|
75
|
-
assert.is(fired, 0, 'no listeners fire after dispose');
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
suite('once after dispose returns null without running the factory', () => {
|
|
79
|
-
const { context, dispose } = createInteractionContext('id-7');
|
|
80
|
-
dispose();
|
|
81
|
-
let calls = 0;
|
|
82
|
-
const result = context.once('late', () => {
|
|
83
|
-
calls += 1;
|
|
84
|
-
return { socket: true };
|
|
85
|
-
});
|
|
86
|
-
assert.is(calls, 0, 'the factory never ran on an ended interaction (no leaked resource)');
|
|
87
|
-
assert.is(result, null, 'once returns null after dispose');
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
suite.run();
|
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
import type { InteractionContext } from '../types/interaction-context';
|
|
2
|
-
import { logger } from '../utils/logger';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* A created {@link InteractionContext} plus the host-only `dispose` handle. The
|
|
6
|
-
* driver keeps the handle (so it can tear the context down on resolve/evict) and
|
|
7
|
-
* hands only `context` to the widget — widgets must not dispose their own context.
|
|
8
|
-
*
|
|
9
|
-
* @internal
|
|
10
|
-
*/
|
|
11
|
-
export interface InteractionContextHandle {
|
|
12
|
-
readonly context: InteractionContext;
|
|
13
|
-
/**
|
|
14
|
-
* Run every registered `onDispose` callback once (in registration order), then
|
|
15
|
-
* clear listeners. Idempotent. Called by the driver from `resolveInteraction`
|
|
16
|
-
* and on driver teardown — never on element unmount.
|
|
17
|
-
*/
|
|
18
|
-
dispose(): void;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Create a live, per-interaction context (GENC-1390). Framework-agnostic: the
|
|
23
|
-
* `subscribe`/`notify` pair is a plain observer set, not FAST reactivity. See
|
|
24
|
-
* {@link InteractionContext} for the lifetime/semantics contract.
|
|
25
|
-
*
|
|
26
|
-
* @internal
|
|
27
|
-
*/
|
|
28
|
-
export function createInteractionContext(interactionId: string): InteractionContextHandle {
|
|
29
|
-
const state: Record<string, unknown> = {};
|
|
30
|
-
const onceCache = new Map<string, unknown>();
|
|
31
|
-
const listeners = new Set<() => void>();
|
|
32
|
-
const disposers = new Set<() => void>();
|
|
33
|
-
let disposed = false;
|
|
34
|
-
|
|
35
|
-
const context: InteractionContext = {
|
|
36
|
-
interactionId,
|
|
37
|
-
state,
|
|
38
|
-
once<T>(key: string, factory: () => T): T | null {
|
|
39
|
-
if (onceCache.has(key)) return onceCache.get(key) as T;
|
|
40
|
-
// Interaction already ended (resolve/timeout/evict): refuse to run the factory.
|
|
41
|
-
// A resource created here would leak — dispose has already run every `onDispose`
|
|
42
|
-
// and won't run again. Return null so a stray late call (e.g. an async callback
|
|
43
|
-
// that lands after a `timeoutMs` timeout) degrades instead of crashing or leaking.
|
|
44
|
-
if (disposed) {
|
|
45
|
-
logger.warn(
|
|
46
|
-
`InteractionContext.once("${key}") called after dispose; not creating a resource on an ended interaction.`,
|
|
47
|
-
);
|
|
48
|
-
return null;
|
|
49
|
-
}
|
|
50
|
-
const value = factory();
|
|
51
|
-
onceCache.set(key, value);
|
|
52
|
-
return value;
|
|
53
|
-
},
|
|
54
|
-
notify(): void {
|
|
55
|
-
// A Set tolerates a listener unsubscribing mid-walk (matches
|
|
56
|
-
// interaction-panel-session's forEach); a throwing subscriber must not stop the rest.
|
|
57
|
-
for (const listener of listeners) {
|
|
58
|
-
try {
|
|
59
|
-
listener();
|
|
60
|
-
} catch (e) {
|
|
61
|
-
logger.error('InteractionContext subscriber threw during notify()', e);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
},
|
|
65
|
-
subscribe(listener: () => void): () => void {
|
|
66
|
-
listeners.add(listener);
|
|
67
|
-
return () => {
|
|
68
|
-
listeners.delete(listener);
|
|
69
|
-
};
|
|
70
|
-
},
|
|
71
|
-
onDispose(fn: () => void): void {
|
|
72
|
-
// Late registration after the interaction already ended: run immediately so
|
|
73
|
-
// callers never leak a resource by registering a beat too late.
|
|
74
|
-
if (disposed) {
|
|
75
|
-
fn();
|
|
76
|
-
return;
|
|
77
|
-
}
|
|
78
|
-
disposers.add(fn);
|
|
79
|
-
},
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
return {
|
|
83
|
-
context,
|
|
84
|
-
dispose(): void {
|
|
85
|
-
if (disposed) return;
|
|
86
|
-
disposed = true;
|
|
87
|
-
for (const fn of disposers) {
|
|
88
|
-
try {
|
|
89
|
-
fn();
|
|
90
|
-
} catch (e) {
|
|
91
|
-
logger.error('InteractionContext onDispose callback threw', e);
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
disposers.clear();
|
|
95
|
-
listeners.clear();
|
|
96
|
-
// Release memoised `once` values (sockets, timers, service handles) for GC — the resources
|
|
97
|
-
// themselves are closed via their `onDispose`, but drop the references too.
|
|
98
|
-
onceCache.clear();
|
|
99
|
-
},
|
|
100
|
-
};
|
|
101
|
-
}
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Shared, pure builder for the debug-log timeline entries (`message` / `turn` / `event`) — the
|
|
3
|
-
* common core of the host element's `buildDiagnosticEntries` and any HEADLESS consumer that drives
|
|
4
|
-
* a `ChatDriver` of its own (e.g. `ai-service` running the engine server-side) and needs to harvest
|
|
5
|
-
* that engine's debug log for the client to fold into its own download / persisted stream
|
|
6
|
-
* (GENC-1461 unified diagnostics). DOM-clean and dependency-light so it works in bare Node.
|
|
7
|
-
*
|
|
8
|
-
* It deliberately excludes the `meta-snapshot` entry: that block is host/DOM-specific (it reads
|
|
9
|
-
* `window.location.host`, the element's agent list, live context/cost), and a merged log keeps only
|
|
10
|
-
* the newest snapshot anyway — a headless source's agent/prompt/tools are already captured in its
|
|
11
|
-
* `turn` entries.
|
|
12
|
-
*
|
|
13
|
-
* @packageDocumentation
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
import type { ChatMessage } from '@genesislcap/foundation-ai';
|
|
17
|
-
import { flattenSubAgentMessages } from '../../utils/flatten-sub-agent-messages';
|
|
18
|
-
import type { MetaEvent } from '../debug-event-log';
|
|
19
|
-
import type { DiagnosticEntry } from './diagnostics';
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* The minimal shape this builder reads off a turn snapshot. The driver's full `TurnSnapshot` is a
|
|
23
|
-
* structural superset, so it assigns to this without the builder depending on the component layer.
|
|
24
|
-
*/
|
|
25
|
-
export interface TurnSnapshotLike {
|
|
26
|
-
turnIndex: string;
|
|
27
|
-
systemPrompt?: string;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Build the `message` / `turn` / `event` timeline entries from a driver's pull surfaces
|
|
32
|
-
* (`getRawHistory()` / `getTurnSnapshots()` / `getMetaEvents(sessionKey)`). Order within the array
|
|
33
|
-
* is message → turn → event; the caller (`assembleDebugLog`) sorts the whole timeline by timestamp,
|
|
34
|
-
* so this ordering only sets the co-timestamp tie-break. Pure.
|
|
35
|
-
*/
|
|
36
|
-
export function buildTimelineEntries(input: {
|
|
37
|
-
turnSnapshots: readonly TurnSnapshotLike[];
|
|
38
|
-
messages: readonly ChatMessage[];
|
|
39
|
-
metaEvents: readonly MetaEvent[];
|
|
40
|
-
}): DiagnosticEntry[] {
|
|
41
|
-
const { turnSnapshots, messages, metaEvents } = input;
|
|
42
|
-
|
|
43
|
-
// Collapse a turn's systemPrompt when byte-identical to the previous turn's — a stable agent
|
|
44
|
-
// repeats the same (often multi-KB) prompt every turn, while a stateful agent's changes. The
|
|
45
|
-
// prompt is shown in full whenever it changes, so prompt evolution stays visible.
|
|
46
|
-
let lastFullPrompt: string | undefined;
|
|
47
|
-
let lastFullIndex = '';
|
|
48
|
-
const turns = turnSnapshots.map((t) => {
|
|
49
|
-
let { systemPrompt } = t;
|
|
50
|
-
if (systemPrompt != null && systemPrompt === lastFullPrompt) {
|
|
51
|
-
systemPrompt = `<repeated — identical to turn ${lastFullIndex}>`;
|
|
52
|
-
} else if (systemPrompt != null) {
|
|
53
|
-
lastFullPrompt = systemPrompt;
|
|
54
|
-
lastFullIndex = t.turnIndex;
|
|
55
|
-
}
|
|
56
|
-
return { kind: 'turn' as const, ...t, systemPrompt };
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
// Sub-agent conversations are stored nested on the parent tool call's `subAgentTrace`;
|
|
60
|
-
// `flattenSubAgentMessages` hoists them to top-level `kind: 'message'` entries (breadcrumbed +
|
|
61
|
-
// correlated, the nested copy moved out — not duplicated) so the timeline reads chronologically.
|
|
62
|
-
const messageEntries = flattenSubAgentMessages(messages);
|
|
63
|
-
const eventEntries = metaEvents.map((e) => ({ kind: 'event' as const, ...e }));
|
|
64
|
-
|
|
65
|
-
return [...messageEntries, ...turns, ...eventEntries] as DiagnosticEntry[];
|
|
66
|
-
}
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import { assert, createLogicSuite } from '@genesislcap/foundation-testing';
|
|
2
|
-
import {
|
|
3
|
-
clearDiagnosticsCursorRegistry,
|
|
4
|
-
deleteDiagnosticsCursorsFor,
|
|
5
|
-
getDiagnosticsCursors,
|
|
6
|
-
resetDiagnosticsCursorsFor,
|
|
7
|
-
} from './diagnostics-cursors';
|
|
8
|
-
|
|
9
|
-
// GENC-1351 §5.8/§5.12 (#9): the forward-capture cursors, and the crucial difference
|
|
10
|
-
// between the Clear reset (keep the event high-water) and the in-place-switch delete
|
|
11
|
-
// (fresh cursors, because the meta-event buffer is torn down and its indices restart).
|
|
12
|
-
|
|
13
|
-
const KEY = 'session-1';
|
|
14
|
-
|
|
15
|
-
const Suite = createLogicSuite('diagnostics-cursors');
|
|
16
|
-
|
|
17
|
-
Suite.before.each(() => {
|
|
18
|
-
clearDiagnosticsCursorRegistry();
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
Suite('resetDiagnosticsCursorsFor KEEPS lastEventIndex (Clear: meta buffer keeps climbing)', () => {
|
|
22
|
-
const c = getDiagnosticsCursors(KEY);
|
|
23
|
-
c.lastEventIndex = 40;
|
|
24
|
-
c.emittedMsgKeys.add('m');
|
|
25
|
-
c.restoredMsgKeys.add('r');
|
|
26
|
-
resetDiagnosticsCursorsFor(KEY);
|
|
27
|
-
const after = getDiagnosticsCursors(KEY);
|
|
28
|
-
assert.is(
|
|
29
|
-
after.lastEventIndex,
|
|
30
|
-
40,
|
|
31
|
-
'event high-water kept — Clear does not reset the meta buffer',
|
|
32
|
-
);
|
|
33
|
-
assert.is(after.emittedMsgKeys.size, 0, 'per-conversation message cursors restarted');
|
|
34
|
-
assert.is(after.restoredMsgKeys.size, 0, 'restore watermark restarted');
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
Suite(
|
|
38
|
-
'deleteDiagnosticsCursorsFor RESETS lastEventIndex (switch: meta buffer restarts at 0)',
|
|
39
|
-
() => {
|
|
40
|
-
const c = getDiagnosticsCursors(KEY);
|
|
41
|
-
c.lastEventIndex = 40;
|
|
42
|
-
deleteDiagnosticsCursorsFor(KEY);
|
|
43
|
-
// A later return re-creates fresh cursors on first access.
|
|
44
|
-
const after = getDiagnosticsCursors(KEY);
|
|
45
|
-
assert.is(
|
|
46
|
-
after.lastEventIndex,
|
|
47
|
-
-1,
|
|
48
|
-
'fresh cursor — a returning session whose events restart at 0 is NOT skipped',
|
|
49
|
-
);
|
|
50
|
-
},
|
|
51
|
-
);
|
|
52
|
-
|
|
53
|
-
Suite.run();
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Per-session forward-capture cursors for the server-saved diagnostics stream
|
|
3
|
-
* (GENC-1351 §5.8). Module-level and keyed by the session `stateKey` — exactly like
|
|
4
|
-
* the meta-event buffer — so the (up to two) element instances that share one
|
|
5
|
-
* session (a collapsed bubble + a popped-out panel) share ONE set of cursors.
|
|
6
|
-
*
|
|
7
|
-
* Without this each instance keeps its own cursors and both independently append
|
|
8
|
-
* the shared driver's activity, double-writing the stream — and, worse, the second
|
|
9
|
-
* instance (which never runs restore, so its message watermark stays empty)
|
|
10
|
-
* re-appends the *entire* restored history on every reload. Module state dies with
|
|
11
|
-
* the JS realm, so these reset for free on a real page reload (like the meta
|
|
12
|
-
* buffer), which is exactly the "fresh capture per page load" behaviour we want.
|
|
13
|
-
*
|
|
14
|
-
* @internal
|
|
15
|
-
*/
|
|
16
|
-
export interface DiagnosticsCursors {
|
|
17
|
-
/** Message identities present at restore — never appended (they live in a prior load's stream). */
|
|
18
|
-
restoredMsgKeys: Set<string>;
|
|
19
|
-
/** Message identities already appended this load. */
|
|
20
|
-
emittedMsgKeys: Set<string>;
|
|
21
|
-
/** Turn indices already appended this load. */
|
|
22
|
-
emittedTurnKeys: Set<string>;
|
|
23
|
-
/** Highest meta-event index already appended. */
|
|
24
|
-
lastEventIndex: number;
|
|
25
|
-
/** JSON of the last meta-snapshot appended — skip re-appending an unchanged block. */
|
|
26
|
-
lastMetaJson: string;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const cursorsByKey = new Map<string, DiagnosticsCursors>();
|
|
30
|
-
|
|
31
|
-
const freshCursors = (): DiagnosticsCursors => ({
|
|
32
|
-
restoredMsgKeys: new Set(),
|
|
33
|
-
emittedMsgKeys: new Set(),
|
|
34
|
-
emittedTurnKeys: new Set(),
|
|
35
|
-
lastEventIndex: -1,
|
|
36
|
-
lastMetaJson: '',
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
/** The shared cursors for `key`, created (empty) on first access. @internal */
|
|
40
|
-
export function getDiagnosticsCursors(key: string): DiagnosticsCursors {
|
|
41
|
-
let cursors = cursorsByKey.get(key);
|
|
42
|
-
if (!cursors) {
|
|
43
|
-
cursors = freshCursors();
|
|
44
|
-
cursorsByKey.set(key, cursors);
|
|
45
|
-
}
|
|
46
|
-
return cursors;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Restart the per-conversation cursors for `key` on Clear — a new conversation in
|
|
51
|
-
* the same page load. `lastEventIndex` is intentionally kept: Clear does NOT reset
|
|
52
|
-
* the meta-event buffer, so its indices keep climbing and mustn't be re-emitted.
|
|
53
|
-
*
|
|
54
|
-
* @internal
|
|
55
|
-
*/
|
|
56
|
-
export function resetDiagnosticsCursorsFor(key: string): void {
|
|
57
|
-
const cursors = getDiagnosticsCursors(key);
|
|
58
|
-
cursors.restoredMsgKeys = new Set();
|
|
59
|
-
cursors.emittedMsgKeys = new Set();
|
|
60
|
-
cursors.emittedTurnKeys = new Set();
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Drop the cursors for `key` entirely — the in-place session switch teardown
|
|
65
|
-
* (GENC-1351 §5.12). Unlike {@link resetDiagnosticsCursorsFor}, this does NOT keep
|
|
66
|
-
* `lastEventIndex`: a switch also tears down the session's meta-event buffer (its
|
|
67
|
-
* indices restart at 0 on a later return), so a kept high-water index would skip
|
|
68
|
-
* every event of the resumed session. A return re-creates fresh cursors on first
|
|
69
|
-
* access.
|
|
70
|
-
*
|
|
71
|
-
* @internal
|
|
72
|
-
*/
|
|
73
|
-
export function deleteDiagnosticsCursorsFor(key: string): void {
|
|
74
|
-
cursorsByKey.delete(key);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
/** Drop all cursors — test isolation only. @internal */
|
|
78
|
-
export function clearDiagnosticsCursorRegistry(): void {
|
|
79
|
-
cursorsByKey.clear();
|
|
80
|
-
}
|