@genesislcap/ai-assistant 14.420.0 → 14.421.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/dist/ai-assistant.api.json +4061 -1416
- package/dist/ai-assistant.d.ts +594 -81
- package/dist/dts/channel/ai-activity-channel.d.ts +4 -22
- package/dist/dts/channel/ai-activity-channel.d.ts.map +1 -1
- package/dist/dts/components/ai-driver/ai-driver.d.ts +52 -0
- package/dist/dts/components/ai-driver/ai-driver.d.ts.map +1 -0
- package/dist/dts/components/ai-driver/index.d.ts +2 -0
- package/dist/dts/components/ai-driver/index.d.ts.map +1 -0
- package/dist/dts/components/chat-driver/chat-driver.d.ts +63 -8
- package/dist/dts/components/chat-driver/chat-driver.d.ts.map +1 -1
- package/dist/dts/components/chat-interaction-wrapper/chat-interaction-wrapper.d.ts +3 -3
- package/dist/dts/components/chat-interaction-wrapper/chat-interaction-wrapper.d.ts.map +1 -1
- package/dist/dts/components/chat-markdown/chat-markdown.d.ts +1 -1
- package/dist/dts/components/chat-markdown/chat-markdown.d.ts.map +1 -1
- package/dist/dts/components/halo-overlay.d.ts +13 -1
- package/dist/dts/components/halo-overlay.d.ts.map +1 -1
- package/dist/dts/components/orchestrating-driver/index.d.ts +2 -0
- package/dist/dts/components/orchestrating-driver/index.d.ts.map +1 -0
- package/dist/dts/components/orchestrating-driver/orchestrating-driver.d.ts +39 -0
- package/dist/dts/components/orchestrating-driver/orchestrating-driver.d.ts.map +1 -0
- package/dist/dts/components/popout-manager/index.d.ts +2 -0
- package/dist/dts/components/popout-manager/index.d.ts.map +1 -0
- package/dist/dts/components/popout-manager/popout-manager.d.ts +72 -0
- package/dist/dts/components/popout-manager/popout-manager.d.ts.map +1 -0
- package/dist/dts/config/config.d.ts +43 -15
- package/dist/dts/config/config.d.ts.map +1 -1
- package/dist/dts/config/fallback-agents.d.ts +20 -0
- package/dist/dts/config/fallback-agents.d.ts.map +1 -0
- package/dist/dts/config/index.d.ts +1 -0
- package/dist/dts/config/index.d.ts.map +1 -1
- package/dist/dts/index.d.ts +6 -0
- package/dist/dts/index.d.ts.map +1 -1
- package/dist/dts/main/main.d.ts +122 -21
- package/dist/dts/main/main.d.ts.map +1 -1
- package/dist/dts/main/main.styles.d.ts.map +1 -1
- package/dist/dts/main/main.template.d.ts.map +1 -1
- package/dist/dts/main/main.types.d.ts +16 -0
- package/dist/dts/main/main.types.d.ts.map +1 -1
- package/dist/dts/state/ai-assistant-slice.d.ts +38 -0
- package/dist/dts/state/ai-assistant-slice.d.ts.map +1 -0
- package/dist/dts/state/driver-registry.d.ts +22 -0
- package/dist/dts/state/driver-registry.d.ts.map +1 -0
- package/dist/dts/state/session-store.d.ts +37 -0
- package/dist/dts/state/session-store.d.ts.map +1 -0
- package/dist/dts/suggestions/chat-suggestions.d.ts +7 -0
- package/dist/dts/suggestions/chat-suggestions.d.ts.map +1 -0
- package/dist/dts/types/ai-chat-widget.d.ts +3 -2
- package/dist/dts/types/ai-chat-widget.d.ts.map +1 -1
- package/dist/dts/utils/index.d.ts +1 -0
- package/dist/dts/utils/index.d.ts.map +1 -1
- package/dist/dts/utils/tool-fold.d.ts +133 -0
- package/dist/dts/utils/tool-fold.d.ts.map +1 -0
- package/dist/esm/components/ai-driver/ai-driver.js +1 -0
- package/dist/esm/components/ai-driver/index.js +1 -0
- package/dist/esm/components/chat-driver/chat-driver.js +499 -67
- package/dist/esm/components/chat-interaction-wrapper/chat-interaction-wrapper.js +2 -2
- package/dist/esm/components/chat-markdown/chat-markdown.js +1 -1
- package/dist/esm/components/halo-overlay.js +53 -7
- package/dist/esm/components/orchestrating-driver/index.js +1 -0
- package/dist/esm/components/orchestrating-driver/orchestrating-driver.js +247 -0
- package/dist/esm/components/popout-manager/index.js +1 -0
- package/dist/esm/components/popout-manager/popout-manager.js +126 -0
- package/dist/esm/config/fallback-agents.js +26 -0
- package/dist/esm/config/index.js +1 -0
- package/dist/esm/index.js +6 -0
- package/dist/esm/main/main.js +546 -112
- package/dist/esm/main/main.styles.js +200 -4
- package/dist/esm/main/main.template.js +163 -63
- package/dist/esm/state/ai-assistant-slice.js +54 -0
- package/dist/esm/state/driver-registry.js +46 -0
- package/dist/esm/state/session-store.js +39 -0
- package/dist/esm/suggestions/chat-suggestions.js +147 -0
- package/dist/esm/utils/index.js +1 -0
- package/dist/esm/utils/tool-fold.js +92 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/docs/migration-FUI-2495.md +339 -0
- package/docs/sub_agent.md +310 -0
- package/package.json +16 -15
- package/src/channel/ai-activity-channel.ts +4 -20
- package/src/components/ai-driver/ai-driver.ts +69 -0
- package/src/components/ai-driver/index.ts +1 -0
- package/src/components/chat-driver/chat-driver.ts +600 -73
- package/src/components/chat-interaction-wrapper/chat-interaction-wrapper.ts +3 -3
- package/src/components/chat-markdown/chat-markdown.ts +1 -1
- package/src/components/halo-overlay.ts +45 -7
- package/src/components/orchestrating-driver/index.ts +1 -0
- package/src/components/orchestrating-driver/orchestrating-driver.ts +328 -0
- package/src/components/popout-manager/index.ts +1 -0
- package/src/components/popout-manager/popout-manager.ts +147 -0
- package/src/config/config.ts +45 -15
- package/src/config/fallback-agents.ts +29 -0
- package/src/config/index.ts +1 -0
- package/src/index.ts +6 -0
- package/src/main/main.styles.ts +200 -4
- package/src/main/main.template.ts +200 -80
- package/src/main/main.ts +567 -94
- package/src/main/main.types.ts +11 -0
- package/src/state/ai-assistant-slice.ts +80 -0
- package/src/state/driver-registry.ts +51 -0
- package/src/state/session-store.ts +56 -0
- package/src/suggestions/chat-suggestions.ts +158 -0
- package/src/types/ai-chat-widget.ts +4 -2
- package/src/utils/index.ts +1 -0
- package/src/utils/tool-fold.ts +181 -0
- package/docs/multi-agent-architecture.md +0 -198
package/dist/esm/main/main.js
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
|
+
// =============================================================================
|
|
2
|
+
// ARCHITECTURAL RULES — read before modifying this file
|
|
3
|
+
// =============================================================================
|
|
4
|
+
//
|
|
5
|
+
// 1. STORE INIT MUST PRECEDE super.connectedCallback()
|
|
6
|
+
// `_sessionRef` must be assigned before calling `super.connectedCallback()`.
|
|
7
|
+
// FAST triggers its first render inside `super.connectedCallback()`. The store
|
|
8
|
+
// Proxy calls Observable.track() when a slice is read, which wires up FAST's
|
|
9
|
+
// reactivity. If `_sessionRef` is null during that first render, no tracking
|
|
10
|
+
// is registered and subsequent Redux dispatches will not trigger re-renders.
|
|
11
|
+
// Do not reorder these lines.
|
|
12
|
+
//
|
|
13
|
+
// 2. MARK @volatile ON GETTERS WITH CONDITIONAL OBSERVABLE ACCESS
|
|
14
|
+
// FAST only tracks observables that are actually accessed during a getter's
|
|
15
|
+
// last evaluation. If a getter has branches that access different observables
|
|
16
|
+
// depending on runtime state (e.g. filtering over messages of varying types,
|
|
17
|
+
// or a ternary that reads one observable OR another), FAST may not know to
|
|
18
|
+
// re-evaluate when an unvisited branch's observable changes. Mark such
|
|
19
|
+
// getters @volatile so FAST always re-evaluates them when any dependency
|
|
20
|
+
// changes, rather than relying on cached dependency tracking.
|
|
21
|
+
//
|
|
22
|
+
// =============================================================================
|
|
1
23
|
var FoundationAiAssistant_1;
|
|
2
|
-
import { __awaiter, __decorate } from "tslib";
|
|
24
|
+
import { __awaiter, __decorate, __rest } from "tslib";
|
|
3
25
|
import { AIProvider } from '@genesislcap/foundation-ai';
|
|
4
26
|
import { avoidTreeShaking } from '@genesislcap/foundation-utils';
|
|
5
27
|
import { customElement, html, GenesisElement, observable, volatile, attr, } from '@genesislcap/web-core';
|
|
@@ -10,18 +32,32 @@ import { ChatDriver } from '../components/chat-driver/chat-driver';
|
|
|
10
32
|
import { AiChatInteractionWrapper } from '../components/chat-interaction-wrapper/chat-interaction-wrapper';
|
|
11
33
|
import { AiChatMarkdown } from '../components/chat-markdown/chat-markdown';
|
|
12
34
|
import { AiHaloOverlay } from '../components/halo-overlay';
|
|
35
|
+
import { OrchestratingDriver } from '../components/orchestrating-driver/orchestrating-driver';
|
|
36
|
+
import { getOrCreateDriver, deleteDriver } from '../state/driver-registry';
|
|
37
|
+
import { getSessionStore, hasSessionStore } from '../state/session-store';
|
|
38
|
+
import { ChatSuggestions } from '../suggestions/chat-suggestions';
|
|
13
39
|
import { logger } from '../utils/logger';
|
|
40
|
+
import { expandToolTree } from '../utils/tool-fold';
|
|
14
41
|
import { styles } from './main.styles';
|
|
15
42
|
import { FoundationAiAssistantTemplate } from './main.template';
|
|
16
43
|
import { ALL_ANIMATIONS } from './main.types';
|
|
44
|
+
/** Context window sizes (in tokens) for known models. */
|
|
45
|
+
const MODEL_CONTEXT_LIMITS = {
|
|
46
|
+
'gemini-2.5-flash': 1048576,
|
|
47
|
+
'gemini-2.5-flash-lite': 1048576,
|
|
48
|
+
'gpt-4o': 128000,
|
|
49
|
+
'gpt-4o-mini': 128000,
|
|
50
|
+
'gpt-4-turbo': 128000,
|
|
51
|
+
};
|
|
17
52
|
// Register supporting components when the main component module is imported.
|
|
18
|
-
avoidTreeShaking(AiChatMarkdown, AiChatInteractionWrapper, AiHaloOverlay, AiChatBubble, AiActivityHalo);
|
|
53
|
+
avoidTreeShaking(AiChatMarkdown, AiChatInteractionWrapper, AiHaloOverlay, AiChatBubble, AiActivityHalo, ChatSuggestions);
|
|
19
54
|
/**
|
|
20
55
|
* Foundation AI Assistant component.
|
|
21
56
|
*
|
|
22
57
|
* @remarks
|
|
23
58
|
* Inject an `AIProvider` through the DI container. Pass agent configuration via the `agents`
|
|
24
|
-
* property. The component creates a `ChatDriver`
|
|
59
|
+
* property. The component creates a `ChatDriver` (single agent) or `OrchestratingDriver`
|
|
60
|
+
* (multiple agents) to manage the conversation loop.
|
|
25
61
|
*
|
|
26
62
|
* Popout/collapse coordination uses `agenticActivityBus` topics `chat-popout` and `chat-popin` — not DOM `CustomEvent`s on this element.
|
|
27
63
|
*
|
|
@@ -33,37 +69,143 @@ let FoundationAiAssistant = FoundationAiAssistant_1 = class FoundationAiAssistan
|
|
|
33
69
|
constructor() {
|
|
34
70
|
super(...arguments);
|
|
35
71
|
this.designSystemPrefix = 'rapid';
|
|
72
|
+
this.headerTitle = 'Genesis Assistant';
|
|
36
73
|
this.placeholder = 'Message assistant...';
|
|
37
74
|
this.chatConfig = {};
|
|
38
|
-
this.
|
|
39
|
-
this.
|
|
40
|
-
|
|
75
|
+
/** When set, enables Redux DevTools for this instance's session store. */
|
|
76
|
+
this.debugRedux = false;
|
|
77
|
+
// ---- Transient UI state (stays as @observable on the component) ----
|
|
78
|
+
this._suggestionsGeneration = 0;
|
|
41
79
|
this.attachments = [];
|
|
42
80
|
this.attachmentErrors = [];
|
|
43
|
-
/** Current user-facing toggle state for tool call visibility. */
|
|
44
|
-
this.showToolCalls = false;
|
|
45
|
-
/** Current user-facing toggle state for thinking step visibility. */
|
|
46
|
-
this.showThinkingSteps = false;
|
|
47
|
-
/** Currently enabled animations. */
|
|
48
|
-
this.enabledAnimations = [];
|
|
49
81
|
/** Whether the loading spinner is currently visible. Controlled by the loading delay timer. */
|
|
50
82
|
this.showLoadingIndicator = false;
|
|
51
83
|
/** Whether the settings panel is open. */
|
|
52
84
|
this.settingsOpen = false;
|
|
85
|
+
/** Whether the splash overlay is currently showing (no messages and showSplash is enabled). Reflected as a boolean attribute on the host. */
|
|
86
|
+
this.showingSplash = false;
|
|
53
87
|
this.haloStartPublished = false;
|
|
54
|
-
/**
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
88
|
+
/** True when the user has intentionally scrolled away from the bottom — suppresses auto-scroll. */
|
|
89
|
+
this._userScrolledAway = false;
|
|
90
|
+
this.showHalo = 'no';
|
|
91
|
+
}
|
|
92
|
+
get messages() {
|
|
93
|
+
var _a, _b;
|
|
94
|
+
return (_b = (_a = this._sessionRef) === null || _a === void 0 ? void 0 : _a.store.aiAssistant.messages) !== null && _b !== void 0 ? _b : [];
|
|
95
|
+
}
|
|
96
|
+
set messages(value) {
|
|
97
|
+
var _a;
|
|
98
|
+
(_a = this._sessionRef) === null || _a === void 0 ? void 0 : _a.actions.aiAssistant.setMessages(value);
|
|
99
|
+
this.handleMessagesUpdate();
|
|
100
|
+
}
|
|
101
|
+
get state() {
|
|
102
|
+
var _a, _b;
|
|
103
|
+
return (_b = (_a = this._sessionRef) === null || _a === void 0 ? void 0 : _a.store.aiAssistant.state) !== null && _b !== void 0 ? _b : 'idle';
|
|
104
|
+
}
|
|
105
|
+
set state(value) {
|
|
106
|
+
var _a;
|
|
107
|
+
(_a = this._sessionRef) === null || _a === void 0 ? void 0 : _a.actions.aiAssistant.setState(value);
|
|
108
|
+
this.syncShowHalo();
|
|
109
|
+
}
|
|
110
|
+
get activeAgent() {
|
|
111
|
+
var _a;
|
|
112
|
+
return (_a = this._sessionRef) === null || _a === void 0 ? void 0 : _a.store.aiAssistant.activeAgent;
|
|
113
|
+
}
|
|
114
|
+
set activeAgent(value) {
|
|
115
|
+
var _a, _b;
|
|
116
|
+
// Strip toolHandlers before storing — functions are non-serializable and Redux
|
|
117
|
+
// serializable-state middleware will warn. toolHandlers are never read back from
|
|
118
|
+
// the store; they are always sourced from this.agents when the driver is built.
|
|
119
|
+
if (value) {
|
|
120
|
+
const { toolHandlers: _ } = value, serializable = __rest(value, ["toolHandlers"]);
|
|
121
|
+
(_a = this._sessionRef) === null || _a === void 0 ? void 0 : _a.actions.aiAssistant.setActiveAgent(serializable);
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
(_b = this._sessionRef) === null || _b === void 0 ? void 0 : _b.actions.aiAssistant.setActiveAgent(undefined);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
get suggestionsState() {
|
|
128
|
+
var _a, _b;
|
|
129
|
+
return (_b = (_a = this._sessionRef) === null || _a === void 0 ? void 0 : _a.store.aiAssistant.suggestionsState) !== null && _b !== void 0 ? _b : { status: 'idle' };
|
|
130
|
+
}
|
|
131
|
+
set suggestionsState(value) {
|
|
132
|
+
var _a;
|
|
133
|
+
(_a = this._sessionRef) === null || _a === void 0 ? void 0 : _a.actions.aiAssistant.setSuggestionsState(value);
|
|
134
|
+
}
|
|
135
|
+
/** Current user-facing toggle state for tool call visibility. */
|
|
136
|
+
get showToolCalls() {
|
|
137
|
+
var _a, _b;
|
|
138
|
+
return (_b = (_a = this._sessionRef) === null || _a === void 0 ? void 0 : _a.store.aiAssistant.showToolCalls) !== null && _b !== void 0 ? _b : false;
|
|
139
|
+
}
|
|
140
|
+
set showToolCalls(value) {
|
|
141
|
+
var _a;
|
|
142
|
+
(_a = this._sessionRef) === null || _a === void 0 ? void 0 : _a.actions.aiAssistant.setShowToolCalls(value);
|
|
143
|
+
}
|
|
144
|
+
/** Current user-facing toggle state for thinking step visibility. */
|
|
145
|
+
get showThinkingSteps() {
|
|
146
|
+
var _a, _b;
|
|
147
|
+
return (_b = (_a = this._sessionRef) === null || _a === void 0 ? void 0 : _a.store.aiAssistant.showThinkingSteps) !== null && _b !== void 0 ? _b : false;
|
|
148
|
+
}
|
|
149
|
+
set showThinkingSteps(value) {
|
|
150
|
+
var _a;
|
|
151
|
+
(_a = this._sessionRef) === null || _a === void 0 ? void 0 : _a.actions.aiAssistant.setShowThinkingSteps(value);
|
|
152
|
+
}
|
|
153
|
+
/** Current user-facing toggle state for agent switch indicator visibility. */
|
|
154
|
+
get showAgentSwitchIndicator() {
|
|
155
|
+
var _a, _b;
|
|
156
|
+
return (_b = (_a = this._sessionRef) === null || _a === void 0 ? void 0 : _a.store.aiAssistant.showAgentSwitchIndicator) !== null && _b !== void 0 ? _b : false;
|
|
157
|
+
}
|
|
158
|
+
set showAgentSwitchIndicator(value) {
|
|
159
|
+
var _a;
|
|
160
|
+
(_a = this._sessionRef) === null || _a === void 0 ? void 0 : _a.actions.aiAssistant.setShowAgentSwitchIndicator(value);
|
|
161
|
+
}
|
|
162
|
+
/** Currently enabled animations. */
|
|
163
|
+
get enabledAnimations() {
|
|
164
|
+
var _a, _b;
|
|
165
|
+
return (_b = (_a = this._sessionRef) === null || _a === void 0 ? void 0 : _a.store.aiAssistant.enabledAnimations) !== null && _b !== void 0 ? _b : [];
|
|
166
|
+
}
|
|
167
|
+
set enabledAnimations(value) {
|
|
168
|
+
var _a;
|
|
169
|
+
(_a = this._sessionRef) === null || _a === void 0 ? void 0 : _a.actions.aiAssistant.setEnabledAnimations(value);
|
|
170
|
+
}
|
|
171
|
+
/** Most recent prompt token count from the AI provider, if available. */
|
|
172
|
+
get contextTokens() {
|
|
173
|
+
var _a;
|
|
174
|
+
return (_a = this._sessionRef) === null || _a === void 0 ? void 0 : _a.store.aiAssistant.contextTokens;
|
|
175
|
+
}
|
|
176
|
+
set contextTokens(value) {
|
|
177
|
+
var _a;
|
|
178
|
+
(_a = this._sessionRef) === null || _a === void 0 ? void 0 : _a.actions.aiAssistant.setContextTokens(value);
|
|
179
|
+
}
|
|
180
|
+
/** Context window size for the active model, if known. */
|
|
181
|
+
get contextLimit() {
|
|
182
|
+
var _a;
|
|
183
|
+
return (_a = this._sessionRef) === null || _a === void 0 ? void 0 : _a.store.aiAssistant.contextLimit;
|
|
184
|
+
}
|
|
185
|
+
set contextLimit(value) {
|
|
186
|
+
var _a;
|
|
187
|
+
(_a = this._sessionRef) === null || _a === void 0 ? void 0 : _a.actions.aiAssistant.setContextLimit(value);
|
|
188
|
+
}
|
|
189
|
+
get inputValue() {
|
|
190
|
+
var _a, _b;
|
|
191
|
+
return (_b = (_a = this._sessionRef) === null || _a === void 0 ? void 0 : _a.store.aiAssistant.inputValue) !== null && _b !== void 0 ? _b : '';
|
|
192
|
+
}
|
|
193
|
+
set inputValue(value) {
|
|
194
|
+
var _a;
|
|
195
|
+
(_a = this._sessionRef) === null || _a === void 0 ? void 0 : _a.actions.aiAssistant.setInputValue(value);
|
|
59
196
|
}
|
|
60
197
|
syncShowHalo() {
|
|
61
198
|
if (this.state !== 'loading') {
|
|
62
|
-
this.showHalo =
|
|
199
|
+
this.showHalo = 'no';
|
|
63
200
|
return;
|
|
64
201
|
}
|
|
65
202
|
const last = this.messages[this.messages.length - 1];
|
|
66
|
-
|
|
203
|
+
if (last === null || last === void 0 ? void 0 : last.interaction) {
|
|
204
|
+
this.showHalo = 'no';
|
|
205
|
+
}
|
|
206
|
+
else if (this.showHalo !== 'orchestrating') {
|
|
207
|
+
this.showHalo = 'agent';
|
|
208
|
+
}
|
|
67
209
|
}
|
|
68
210
|
/** True when there is a pending (unresolved) interaction — disables the popout button. */
|
|
69
211
|
get hasActivePendingInteraction() {
|
|
@@ -76,7 +218,7 @@ let FoundationAiAssistant = FoundationAiAssistant_1 = class FoundationAiAssistan
|
|
|
76
218
|
var _a;
|
|
77
219
|
if (!((_a = this.enabledAnimations) === null || _a === void 0 ? void 0 : _a.includes('halo')))
|
|
78
220
|
return;
|
|
79
|
-
if (
|
|
221
|
+
if (this.showHalo === 'no') {
|
|
80
222
|
agenticActivityBus.publish('halo-stop', undefined);
|
|
81
223
|
this.haloStartPublished = false;
|
|
82
224
|
}
|
|
@@ -98,10 +240,24 @@ let FoundationAiAssistant = FoundationAiAssistant_1 = class FoundationAiAssistan
|
|
|
98
240
|
* Messages filtered by the current toggle state.
|
|
99
241
|
* Tool-related messages (those with toolCalls or toolResult) are hidden when
|
|
100
242
|
* `showToolCalls` is false.
|
|
243
|
+
*
|
|
244
|
+
* Marked `@volatile` because the filter branches conditionally access
|
|
245
|
+
* `showToolCalls`, `showThinkingSteps`, and `showAgentSwitchIndicator`
|
|
246
|
+
* depending on message content. Without it, FAST would only track the
|
|
247
|
+
* observables accessed on the last evaluation and miss toggle changes that
|
|
248
|
+
* happen to hit an untracked branch.
|
|
101
249
|
*/
|
|
102
250
|
get visibleMessages() {
|
|
251
|
+
var _a;
|
|
252
|
+
const showAgentSwitchIndicator = ((_a = this.chatConfig.ui) === null || _a === void 0 ? void 0 : _a.showAgentSwitchIndicator) != null
|
|
253
|
+
? this.showAgentSwitchIndicator
|
|
254
|
+
: this.showToolCalls;
|
|
103
255
|
return this.messages.filter((m) => {
|
|
104
256
|
var _a, _b, _c;
|
|
257
|
+
// Agent switch indicators are shown when the toggle is on (or showToolCalls implies it)
|
|
258
|
+
if (m.role === 'system-event') {
|
|
259
|
+
return showAgentSwitchIndicator;
|
|
260
|
+
}
|
|
105
261
|
// Never show tool messages to the user
|
|
106
262
|
if (m.role === 'tool') {
|
|
107
263
|
return false;
|
|
@@ -118,45 +274,247 @@ let FoundationAiAssistant = FoundationAiAssistant_1 = class FoundationAiAssistan
|
|
|
118
274
|
return !isToolRelated || this.showToolCalls;
|
|
119
275
|
});
|
|
120
276
|
}
|
|
277
|
+
agentsChanged() {
|
|
278
|
+
var _a, _b, _c;
|
|
279
|
+
// Guard: driver doesn't exist yet during connectedCallback — createDriver/wireDriver handle that.
|
|
280
|
+
if (!this.driver)
|
|
281
|
+
return;
|
|
282
|
+
const key = this.getStateKey();
|
|
283
|
+
if (!key)
|
|
284
|
+
return;
|
|
285
|
+
// Skip rebuild if the agent configuration hasn't meaningfully changed.
|
|
286
|
+
// This prevents spurious driver teardowns when the collapse-mode element
|
|
287
|
+
// connects and its parent re-assigns the same agents array, which would
|
|
288
|
+
// destroy pending interactions in the existing driver.
|
|
289
|
+
const newKey = this.getAgentsKey(this.agents);
|
|
290
|
+
if (newKey === this._driverAgentsKey)
|
|
291
|
+
return;
|
|
292
|
+
this._driverAgentsKey = newKey;
|
|
293
|
+
// Don't rebuild while the driver is busy — it was created with the correct agents
|
|
294
|
+
// and has live pending interactions. This prevents the collapse element (which
|
|
295
|
+
// initially has no agents, then gets them assigned by its wrapper) from tearing
|
|
296
|
+
// down a mid-flight driver and creating a fresh idle one.
|
|
297
|
+
if (this.driver.isBusy())
|
|
298
|
+
return;
|
|
299
|
+
const history = (_c = (_b = (_a = this.driver).getRawHistory) === null || _b === void 0 ? void 0 : _b.call(_a)) !== null && _c !== void 0 ? _c : [];
|
|
300
|
+
this.unwireDriver();
|
|
301
|
+
deleteDriver(key);
|
|
302
|
+
this.driver = getOrCreateDriver(key, () => this.createDriver());
|
|
303
|
+
this.wireDriver();
|
|
304
|
+
if (history.length)
|
|
305
|
+
this.driver.loadHistory([...history]);
|
|
306
|
+
}
|
|
307
|
+
/** Returns a stable fingerprint for an agents array based on agent names and tool handler keys. */
|
|
308
|
+
getAgentsKey(agents) {
|
|
309
|
+
if (!(agents === null || agents === void 0 ? void 0 : agents.length))
|
|
310
|
+
return '';
|
|
311
|
+
return agents
|
|
312
|
+
.map((a) => {
|
|
313
|
+
var _a;
|
|
314
|
+
const toolNames = Object.keys((_a = a.toolHandlers) !== null && _a !== void 0 ? _a : {})
|
|
315
|
+
.sort()
|
|
316
|
+
.join('+');
|
|
317
|
+
return `${a.name}[${toolNames}]`;
|
|
318
|
+
})
|
|
319
|
+
.join(',');
|
|
320
|
+
}
|
|
321
|
+
/**
|
|
322
|
+
* Pure factory — creates a ChatDriver or OrchestratingDriver based on the
|
|
323
|
+
* current agent configuration. Does not wire event listeners or register in
|
|
324
|
+
* the driver registry.
|
|
325
|
+
*/
|
|
326
|
+
createDriver() {
|
|
327
|
+
var _a, _b, _c;
|
|
328
|
+
const agent = (_a = this.chatConfig.agent) !== null && _a !== void 0 ? _a : {};
|
|
329
|
+
const { agents } = this;
|
|
330
|
+
if (agents && agents.length > 1) {
|
|
331
|
+
return new OrchestratingDriver(this.aiProvider, agents, {
|
|
332
|
+
maxHandoffs: agent.maxHandoffs,
|
|
333
|
+
classifierHistoryLength: agent.classifierHistoryLength,
|
|
334
|
+
classifierRetries: agent.classifierRetries,
|
|
335
|
+
maxToolIterations: agent.maxToolIterations,
|
|
336
|
+
maxFoldOperations: agent.maxFoldOperations,
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
const singleAgent = agents === null || agents === void 0 ? void 0 : agents[0];
|
|
340
|
+
this.activeAgent = singleAgent;
|
|
341
|
+
return new ChatDriver(this.aiProvider, (_b = singleAgent === null || singleAgent === void 0 ? void 0 : singleAgent.toolHandlers) !== null && _b !== void 0 ? _b : {}, (_c = singleAgent === null || singleAgent === void 0 ? void 0 : singleAgent.toolDefinitions) !== null && _c !== void 0 ? _c : [], singleAgent === null || singleAgent === void 0 ? void 0 : singleAgent.systemPrompt, singleAgent === null || singleAgent === void 0 ? void 0 : singleAgent.primerHistory, agent.maxToolIterations, agent.maxFoldOperations);
|
|
342
|
+
}
|
|
343
|
+
/**
|
|
344
|
+
* Attaches event listeners to the current driver. Stores a cleanup function
|
|
345
|
+
* so `unwireDriver` can remove them precisely. Safe to call multiple
|
|
346
|
+
* times — unwires any existing listeners first.
|
|
347
|
+
*/
|
|
348
|
+
wireDriver() {
|
|
349
|
+
const { driver } = this;
|
|
350
|
+
if (!driver)
|
|
351
|
+
return;
|
|
352
|
+
// Idempotent — unwire previous listeners on this component before re-wiring.
|
|
353
|
+
this.unwireDriver();
|
|
354
|
+
const onHistoryUpdated = (e) => {
|
|
355
|
+
this.messages = [...e.detail];
|
|
356
|
+
};
|
|
357
|
+
driver.addEventListener('history-updated', onHistoryUpdated);
|
|
358
|
+
const cleanups = [
|
|
359
|
+
() => driver.removeEventListener('history-updated', onHistoryUpdated),
|
|
360
|
+
];
|
|
361
|
+
if (driver instanceof OrchestratingDriver) {
|
|
362
|
+
const onOrchStart = () => {
|
|
363
|
+
this.showHalo = 'orchestrating';
|
|
364
|
+
};
|
|
365
|
+
const onOrchStop = () => {
|
|
366
|
+
if (this.showHalo === 'orchestrating')
|
|
367
|
+
this.showHalo = 'agent';
|
|
368
|
+
};
|
|
369
|
+
const onAgentChanged = (e) => {
|
|
370
|
+
this.activeAgent = e.detail;
|
|
371
|
+
};
|
|
372
|
+
driver.addEventListener('orchestrating-start', onOrchStart);
|
|
373
|
+
driver.addEventListener('orchestrating-stop', onOrchStop);
|
|
374
|
+
driver.addEventListener('agent-changed', onAgentChanged);
|
|
375
|
+
cleanups.push(() => driver.removeEventListener('orchestrating-start', onOrchStart), () => driver.removeEventListener('orchestrating-stop', onOrchStop), () => driver.removeEventListener('agent-changed', onAgentChanged));
|
|
376
|
+
}
|
|
377
|
+
this.driverCleanup = () => {
|
|
378
|
+
for (const fn of cleanups)
|
|
379
|
+
fn();
|
|
380
|
+
};
|
|
381
|
+
}
|
|
382
|
+
/**
|
|
383
|
+
* Removes event listeners attached by `wireDriver`. Does not destroy
|
|
384
|
+
* the driver or remove it from the registry.
|
|
385
|
+
*/
|
|
386
|
+
unwireDriver() {
|
|
387
|
+
var _a;
|
|
388
|
+
(_a = this.driverCleanup) === null || _a === void 0 ? void 0 : _a.call(this);
|
|
389
|
+
this.driverCleanup = undefined;
|
|
390
|
+
}
|
|
121
391
|
connectedCallback() {
|
|
122
|
-
var _a, _b, _c, _d;
|
|
392
|
+
var _a, _b, _c, _d, _e;
|
|
393
|
+
// Initialise the store reference BEFORE super.connectedCallback() so that
|
|
394
|
+
// the first FAST render has access to the store. The store Proxy calls
|
|
395
|
+
// Observable.track(observableStore, sliceName) whenever a slice is read,
|
|
396
|
+
// and actions call Observable.notify — so FAST's reactivity wires up
|
|
397
|
+
// correctly only if _sessionRef is set during that first render pass.
|
|
398
|
+
const key = this.getStateKey();
|
|
399
|
+
const isNewStore = !hasSessionStore(key);
|
|
400
|
+
this._sessionRef = getSessionStore(key, this.debugRedux || undefined);
|
|
123
401
|
super.connectedCallback();
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
402
|
+
// Only apply chatConfig UI defaults to a freshly created store.
|
|
403
|
+
// Existing stores already hold the correct state from a prior session.
|
|
404
|
+
if (isNewStore) {
|
|
405
|
+
const ui = (_a = this.chatConfig.ui) !== null && _a !== void 0 ? _a : {};
|
|
406
|
+
this.showToolCalls = ui.showToolCalls === true;
|
|
407
|
+
this.showThinkingSteps = ui.showThinkingSteps === true;
|
|
408
|
+
this.showAgentSwitchIndicator = ui.showAgentSwitchIndicator === true;
|
|
409
|
+
this.enabledAnimations =
|
|
410
|
+
(_c = (_b = ui.animations) === null || _b === void 0 ? void 0 : _b.enabled) !== null && _c !== void 0 ? _c : (ui.animations ? [...ALL_ANIMATIONS] : []);
|
|
132
411
|
}
|
|
133
|
-
|
|
134
|
-
this.
|
|
135
|
-
this.
|
|
136
|
-
this.messages = [...e.detail];
|
|
137
|
-
});
|
|
138
|
-
// When embedded in a bubble (expand mode), listen for chat-popin to restore state
|
|
139
|
-
// when the layout panel collapses back.
|
|
412
|
+
this.driver = getOrCreateDriver(key, () => this.createDriver());
|
|
413
|
+
this._driverAgentsKey = this.getAgentsKey(this.agents);
|
|
414
|
+
this.wireDriver();
|
|
140
415
|
if (this.popoutMode === 'expand') {
|
|
141
|
-
|
|
142
|
-
|
|
416
|
+
// Dual-listener guard: when the assistant is popped out into the layout
|
|
417
|
+
// panel, a collapse-mode element connects and wires to the same shared
|
|
418
|
+
// driver. Unwire this (hidden) instance on popout; re-wire on popin.
|
|
419
|
+
const unsubPopout = agenticActivityBus.subscribe('chat-popout', () => {
|
|
420
|
+
this.unwireDriver();
|
|
143
421
|
});
|
|
422
|
+
const unsubPopin = agenticActivityBus.subscribe('chat-popin', () => {
|
|
423
|
+
this.wireDriver();
|
|
424
|
+
});
|
|
425
|
+
this.unsubBus = () => {
|
|
426
|
+
unsubPopout();
|
|
427
|
+
unsubPopin();
|
|
428
|
+
};
|
|
429
|
+
}
|
|
430
|
+
this.syncShowingSplash();
|
|
431
|
+
// Restore loading state if the driver is still executing mid-lifecycle.
|
|
432
|
+
// disconnectedCallback resets state to 'idle', so we must check real driver state here.
|
|
433
|
+
if ((_d = this.driver) === null || _d === void 0 ? void 0 : _d.isBusy()) {
|
|
434
|
+
this.state = 'loading';
|
|
435
|
+
this.startLoadingTimer();
|
|
436
|
+
// Subscribe once so that when the originating send() completes (possibly on a
|
|
437
|
+
// different element instance that has since disconnected), this element cleans up
|
|
438
|
+
// its own timer, syncs the halo, and triggers the post-response suggestion fetch.
|
|
439
|
+
this._executionCompletionUnsub = (_e = this._sessionRef) === null || _e === void 0 ? void 0 : _e.subscribeKey((s) => s.aiAssistant.state, () => {
|
|
440
|
+
var _a, _b;
|
|
441
|
+
if (((_a = this._sessionRef) === null || _a === void 0 ? void 0 : _a.store.aiAssistant.state) === 'idle') {
|
|
442
|
+
this.stopLoadingTimer();
|
|
443
|
+
this.syncShowHalo();
|
|
444
|
+
this.fetchSuggestions();
|
|
445
|
+
(_b = this._executionCompletionUnsub) === null || _b === void 0 ? void 0 : _b.call(this);
|
|
446
|
+
this._executionCompletionUnsub = undefined;
|
|
447
|
+
}
|
|
448
|
+
});
|
|
449
|
+
}
|
|
450
|
+
this.fetchSuggestions();
|
|
451
|
+
void this.resolveContextLimit();
|
|
452
|
+
if (this.messagesEl) {
|
|
453
|
+
this._scrollListener = () => {
|
|
454
|
+
this._userScrolledAway =
|
|
455
|
+
this.messagesEl.scrollTop + this.messagesEl.clientHeight <
|
|
456
|
+
this.messagesEl.scrollHeight - FoundationAiAssistant_1.SCROLL_BOTTOM_THRESHOLD_PX;
|
|
457
|
+
};
|
|
458
|
+
this.messagesEl.addEventListener('scroll', this._scrollListener);
|
|
144
459
|
}
|
|
145
460
|
logger.debug('FoundationAiAssistant connected');
|
|
146
461
|
}
|
|
147
462
|
disconnectedCallback() {
|
|
148
|
-
var _a;
|
|
463
|
+
var _a, _b;
|
|
149
464
|
super.disconnectedCallback();
|
|
150
465
|
this.stopLoadingTimer();
|
|
151
466
|
this.state = 'idle';
|
|
467
|
+
this.unwireDriver();
|
|
152
468
|
(_a = this.unsubBus) === null || _a === void 0 ? void 0 : _a.call(this);
|
|
153
469
|
this.unsubBus = undefined;
|
|
470
|
+
(_b = this._executionCompletionUnsub) === null || _b === void 0 ? void 0 : _b.call(this);
|
|
471
|
+
this._executionCompletionUnsub = undefined;
|
|
472
|
+
if (this.messagesEl && this._scrollListener) {
|
|
473
|
+
this.messagesEl.removeEventListener('scroll', this._scrollListener);
|
|
474
|
+
}
|
|
475
|
+
this._scrollListener = undefined;
|
|
476
|
+
this._userScrolledAway = false;
|
|
477
|
+
// Clear local references only — driver and store stay in their registries.
|
|
154
478
|
this.driver = undefined;
|
|
479
|
+
this._sessionRef = undefined;
|
|
155
480
|
}
|
|
156
|
-
|
|
157
|
-
this
|
|
481
|
+
resolveContextLimit() {
|
|
482
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
483
|
+
var _a, _b;
|
|
484
|
+
try {
|
|
485
|
+
const status = yield ((_b = (_a = this.aiProvider).getStatus) === null || _b === void 0 ? void 0 : _b.call(_a));
|
|
486
|
+
if (status === null || status === void 0 ? void 0 : status.model) {
|
|
487
|
+
this.contextLimit = MODEL_CONTEXT_LIMITS[status.model];
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
catch (_c) {
|
|
491
|
+
// Non-fatal — context limit display simply won't show
|
|
492
|
+
}
|
|
493
|
+
});
|
|
494
|
+
}
|
|
495
|
+
chatConfigChanged() {
|
|
496
|
+
this.syncShowingSplash();
|
|
497
|
+
}
|
|
498
|
+
showingSplashChanged() {
|
|
499
|
+
if (this.showingSplash) {
|
|
500
|
+
this.setAttribute('showing-splash', '');
|
|
501
|
+
}
|
|
502
|
+
else {
|
|
503
|
+
this.removeAttribute('showing-splash');
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
// Sets the observable which reflects as a boolean attribute on the host via showingSplashChanged.
|
|
507
|
+
// Must be an attribute on the host (not a shadow DOM class) so consumer CSS can target slotted
|
|
508
|
+
// light DOM content — shadow DOM classes are not visible to external stylesheets.
|
|
509
|
+
syncShowingSplash() {
|
|
510
|
+
var _a;
|
|
511
|
+
this.showingSplash = !!((_a = this.chatConfig.ui) === null || _a === void 0 ? void 0 : _a.showSplash) && this.messages.length === 0;
|
|
158
512
|
}
|
|
159
|
-
|
|
513
|
+
/**
|
|
514
|
+
* Runs side effects that were previously in `messagesChanged()`.
|
|
515
|
+
* Called from the `messages` setter after dispatching to the store.
|
|
516
|
+
*/
|
|
517
|
+
handleMessagesUpdate() {
|
|
160
518
|
var _a, _b;
|
|
161
519
|
// Reset the loading timer when an assistant message arrives mid-loop so each
|
|
162
520
|
// individual step gets a fresh window before the spinner appears.
|
|
@@ -172,11 +530,16 @@ let FoundationAiAssistant = FoundationAiAssistant_1 = class FoundationAiAssistan
|
|
|
172
530
|
}
|
|
173
531
|
}
|
|
174
532
|
this.syncShowHalo();
|
|
533
|
+
this.syncShowingSplash();
|
|
534
|
+
// Update context token count from the most recent message that carries usage data.
|
|
535
|
+
for (let i = this.messages.length - 1; i >= 0; i -= 1) {
|
|
536
|
+
if (this.messages[i].inputTokens != null) {
|
|
537
|
+
this.contextTokens = this.messages[i].inputTokens;
|
|
538
|
+
break;
|
|
539
|
+
}
|
|
540
|
+
}
|
|
175
541
|
// Publish halo-start whenever a new toolCalls message arrives.
|
|
176
|
-
|
|
177
|
-
// not relevant to the new tools begin deactivating (fix #2).
|
|
178
|
-
// Never publish with empty toolNames (fix #3).
|
|
179
|
-
if (this.showHalo && ((_a = this.enabledAnimations) === null || _a === void 0 ? void 0 : _a.includes('halo'))) {
|
|
542
|
+
if (this.showHalo !== 'no' && ((_a = this.enabledAnimations) === null || _a === void 0 ? void 0 : _a.includes('halo'))) {
|
|
180
543
|
const last = this.messages[this.messages.length - 1];
|
|
181
544
|
if ((_b = last === null || last === void 0 ? void 0 : last.toolCalls) === null || _b === void 0 ? void 0 : _b.length) {
|
|
182
545
|
const toolNames = this.getActiveToolNames();
|
|
@@ -192,7 +555,6 @@ let FoundationAiAssistant = FoundationAiAssistant_1 = class FoundationAiAssistan
|
|
|
192
555
|
this.scrollToBottom();
|
|
193
556
|
}
|
|
194
557
|
showLoadingIndicatorChanged() {
|
|
195
|
-
// Scroll to bottom when the spinner appears so it is visible.
|
|
196
558
|
if (this.showLoadingIndicator) {
|
|
197
559
|
this.scrollToBottom();
|
|
198
560
|
}
|
|
@@ -200,19 +562,19 @@ let FoundationAiAssistant = FoundationAiAssistant_1 = class FoundationAiAssistan
|
|
|
200
562
|
// Double rAF: first frame lets the framework flush the DOM update,
|
|
201
563
|
// second frame reads the correct scrollHeight after layout.
|
|
202
564
|
scrollToBottom() {
|
|
565
|
+
if (this._userScrolledAway)
|
|
566
|
+
return;
|
|
203
567
|
requestAnimationFrame(() => {
|
|
204
568
|
requestAnimationFrame(() => {
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
if (el)
|
|
208
|
-
el.scrollTop = el.scrollHeight;
|
|
569
|
+
if (this.messagesEl)
|
|
570
|
+
this.messagesEl.scrollTop = this.messagesEl.scrollHeight;
|
|
209
571
|
});
|
|
210
572
|
});
|
|
211
573
|
}
|
|
212
574
|
startLoadingTimer() {
|
|
213
|
-
var _a;
|
|
575
|
+
var _a, _b;
|
|
214
576
|
this.clearLoadingTimer();
|
|
215
|
-
const delay = (_a = this.chatConfig.loadingDelay) !== null &&
|
|
577
|
+
const delay = (_b = (_a = this.chatConfig.ui) === null || _a === void 0 ? void 0 : _a.loadingDelay) !== null && _b !== void 0 ? _b : FoundationAiAssistant_1.DEFAULT_LOADING_DELAY_S;
|
|
216
578
|
if (delay === 0) {
|
|
217
579
|
this.showLoadingIndicator = true;
|
|
218
580
|
}
|
|
@@ -235,31 +597,35 @@ let FoundationAiAssistant = FoundationAiAssistant_1 = class FoundationAiAssistan
|
|
|
235
597
|
/** Called when the user clicks the popout button. */
|
|
236
598
|
handlePopout() {
|
|
237
599
|
if (this.popoutMode === 'expand') {
|
|
238
|
-
agenticActivityBus.publish('chat-popout',
|
|
600
|
+
agenticActivityBus.publish('chat-popout', undefined);
|
|
239
601
|
}
|
|
240
602
|
else if (this.popoutMode === 'collapse') {
|
|
241
|
-
agenticActivityBus.publish('chat-popin',
|
|
603
|
+
agenticActivityBus.publish('chat-popin', undefined);
|
|
242
604
|
}
|
|
243
605
|
}
|
|
244
|
-
/**
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
this.showToolCalls = state.showToolCalls;
|
|
249
|
-
this.showThinkingSteps = state.showThinkingSteps;
|
|
250
|
-
this.enabledAnimations = [...state.enabledAnimations];
|
|
251
|
-
(_a = this.driver) === null || _a === void 0 ? void 0 : _a.loadHistory(state.messages);
|
|
252
|
-
}
|
|
253
|
-
serializeState() {
|
|
254
|
-
return {
|
|
255
|
-
messages: [...this.messages],
|
|
256
|
-
showToolCalls: this.showToolCalls,
|
|
257
|
-
showThinkingSteps: this.showThinkingSteps,
|
|
258
|
-
enabledAnimations: [...this.enabledAnimations],
|
|
259
|
-
};
|
|
606
|
+
/** Returns a cache key for this instance, or undefined if the component has no identity. */
|
|
607
|
+
getStateKey() {
|
|
608
|
+
const parts = [this.id, this.headerTitle].filter(Boolean);
|
|
609
|
+
return parts.length ? parts.join('::') : undefined;
|
|
260
610
|
}
|
|
261
611
|
toggleSettings() {
|
|
262
|
-
|
|
612
|
+
var _a;
|
|
613
|
+
if (this.settingsOpen) {
|
|
614
|
+
const panel = (_a = this.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('.settings-panel');
|
|
615
|
+
if (panel) {
|
|
616
|
+
panel.classList.add('closing');
|
|
617
|
+
panel.addEventListener('animationend', () => {
|
|
618
|
+
panel.classList.remove('closing');
|
|
619
|
+
this.settingsOpen = false;
|
|
620
|
+
}, { once: true });
|
|
621
|
+
}
|
|
622
|
+
else {
|
|
623
|
+
this.settingsOpen = false;
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
else {
|
|
627
|
+
this.settingsOpen = true;
|
|
628
|
+
}
|
|
263
629
|
}
|
|
264
630
|
toggleShowToolCalls() {
|
|
265
631
|
this.showToolCalls = !this.showToolCalls;
|
|
@@ -267,23 +633,38 @@ let FoundationAiAssistant = FoundationAiAssistant_1 = class FoundationAiAssistan
|
|
|
267
633
|
toggleShowThinkingSteps() {
|
|
268
634
|
this.showThinkingSteps = !this.showThinkingSteps;
|
|
269
635
|
}
|
|
636
|
+
toggleShowAgentSwitchIndicator() {
|
|
637
|
+
this.showAgentSwitchIndicator = !this.showAgentSwitchIndicator;
|
|
638
|
+
}
|
|
270
639
|
setEnabledAnimations(animations) {
|
|
271
640
|
this.enabledAnimations = animations;
|
|
272
641
|
}
|
|
273
|
-
|
|
274
|
-
var _a, _b, _c, _d;
|
|
642
|
+
getDebugLog() {
|
|
643
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
644
|
+
const timestamp = new Date().toISOString().replace(/:/g, '-');
|
|
645
|
+
return {
|
|
646
|
+
messages: (_c = (_b = (_a = this.driver) === null || _a === void 0 ? void 0 : _a.getRawHistory) === null || _b === void 0 ? void 0 : _b.call(_a)) !== null && _c !== void 0 ? _c : this.messages,
|
|
647
|
+
meta: {
|
|
648
|
+
timestamp,
|
|
649
|
+
host: window.location.host,
|
|
650
|
+
agentSummary: (_d = this.agents) === null || _d === void 0 ? void 0 : _d.map((a) => {
|
|
651
|
+
var _a, _b;
|
|
652
|
+
return (Object.assign(Object.assign({}, a), { toolDefinitions: expandToolTree((_a = a.toolDefinitions) !== null && _a !== void 0 ? _a : [], (_b = a.toolHandlers) !== null && _b !== void 0 ? _b : {}), toolHandlers: undefined }));
|
|
653
|
+
}),
|
|
654
|
+
activeSystemPrompt: (_e = this.activeAgent) === null || _e === void 0 ? void 0 : _e.systemPrompt,
|
|
655
|
+
activePrimerHistory: (_f = this.activeAgent) === null || _f === void 0 ? void 0 : _f.primerHistory,
|
|
656
|
+
activeFoldStack: this.driver instanceof ChatDriver ? this.driver.getActiveFoldNames() : undefined,
|
|
657
|
+
debug: (_g = this.debugStateFactory) === null || _g === void 0 ? void 0 : _g.call(this),
|
|
658
|
+
},
|
|
659
|
+
};
|
|
660
|
+
}
|
|
661
|
+
downloadDebugLog() {
|
|
662
|
+
var _a, _b, _c;
|
|
275
663
|
const timestamp = new Date().toISOString().replace(/:/g, '-');
|
|
276
|
-
|
|
277
|
-
const agent = (_a = this.agents) === null || _a === void 0 ? void 0 : _a[0];
|
|
278
|
-
const agentName = ((_c = (_b = agent === null || agent === void 0 ? void 0 : agent.name) !== null && _b !== void 0 ? _b : this.headerTitle) !== null && _c !== void 0 ? _c : 'chat')
|
|
664
|
+
const agentName = ((_c = (_b = (_a = this.activeAgent) === null || _a === void 0 ? void 0 : _a.name) !== null && _b !== void 0 ? _b : this.headerTitle) !== null && _c !== void 0 ? _c : 'chat')
|
|
279
665
|
.toLowerCase()
|
|
280
666
|
.replace(/\s+/g, '-');
|
|
281
|
-
const payload =
|
|
282
|
-
messages: this.messages,
|
|
283
|
-
systemPrompt: agent === null || agent === void 0 ? void 0 : agent.systemPrompt,
|
|
284
|
-
primerHistory: agent === null || agent === void 0 ? void 0 : agent.primerHistory,
|
|
285
|
-
debug: (_d = this.debugStateFactory) === null || _d === void 0 ? void 0 : _d.call(this),
|
|
286
|
-
};
|
|
667
|
+
const payload = this.getDebugLog();
|
|
287
668
|
const blob = new Blob([JSON.stringify(payload, null, 2)], { type: 'application/json' });
|
|
288
669
|
const url = URL.createObjectURL(blob);
|
|
289
670
|
const a = document.createElement('a');
|
|
@@ -312,12 +693,12 @@ let FoundationAiAssistant = FoundationAiAssistant_1 = class FoundationAiAssistan
|
|
|
312
693
|
}
|
|
313
694
|
}
|
|
314
695
|
isAcceptedFile(file) {
|
|
315
|
-
var _a, _b;
|
|
316
|
-
const accepted = this.chatConfig.acceptedFiles;
|
|
696
|
+
var _a, _b, _c;
|
|
697
|
+
const accepted = (_a = this.chatConfig.ui) === null || _a === void 0 ? void 0 : _a.acceptedFiles;
|
|
317
698
|
if (!accepted)
|
|
318
699
|
return false;
|
|
319
700
|
const acceptedList = accepted.split(',').map((s) => s.trim().toLowerCase());
|
|
320
|
-
const ext = `.${(
|
|
701
|
+
const ext = `.${(_c = (_b = file.name.split('.').pop()) === null || _b === void 0 ? void 0 : _b.toLowerCase()) !== null && _c !== void 0 ? _c : ''}`;
|
|
321
702
|
return acceptedList.some((a) => a === ext ||
|
|
322
703
|
a === file.type ||
|
|
323
704
|
(a.endsWith('/*') && file.type.startsWith(a.replace('/*', '/'))));
|
|
@@ -367,16 +748,79 @@ let FoundationAiAssistant = FoundationAiAssistant_1 = class FoundationAiAssistan
|
|
|
367
748
|
handleSendClick() {
|
|
368
749
|
this.send();
|
|
369
750
|
}
|
|
751
|
+
handleSuggestionClick(suggestion) {
|
|
752
|
+
this.inputValue = suggestion;
|
|
753
|
+
this.send();
|
|
754
|
+
}
|
|
755
|
+
fetchSuggestions() {
|
|
756
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
757
|
+
var _a, _b;
|
|
758
|
+
const suggestionsConfig = this.chatConfig.suggestions;
|
|
759
|
+
if (!this.driver || !suggestionsConfig || suggestionsConfig.behavior === 'never') {
|
|
760
|
+
return;
|
|
761
|
+
}
|
|
762
|
+
if (suggestionsConfig.behavior === 'initial' && this.messages.length > 0) {
|
|
763
|
+
return;
|
|
764
|
+
}
|
|
765
|
+
// Skip if a tool flow is currently executing — suggestions would be generated
|
|
766
|
+
// from partial history and would be replaced by the post-response fetch anyway.
|
|
767
|
+
if ((_a = this.driver) === null || _a === void 0 ? void 0 : _a.isBusy()) {
|
|
768
|
+
return;
|
|
769
|
+
}
|
|
770
|
+
// Skip if suggestions were already fetched or are in-flight — avoids redundant
|
|
771
|
+
// AI calls when the component reconnects during lifecycle events (pop-out/pop-in,
|
|
772
|
+
// docking) since suggestionsState is persisted in the store.
|
|
773
|
+
if (this.suggestionsState.status === 'loaded' || this.suggestionsState.status === 'loading') {
|
|
774
|
+
return;
|
|
775
|
+
}
|
|
776
|
+
this._suggestionsGeneration += 1;
|
|
777
|
+
const generation = this._suggestionsGeneration;
|
|
778
|
+
this.suggestionsState = { status: 'loading' };
|
|
779
|
+
// For single-agent (ChatDriver used directly), activeAgent is set but its name is never
|
|
780
|
+
// passed to the driver — build agentInfo here so getSuggestions has context.
|
|
781
|
+
// OrchestratingDriver ignores this parameter and builds its own from specialists.
|
|
782
|
+
const agentInfo = this.activeAgent
|
|
783
|
+
? [
|
|
784
|
+
{
|
|
785
|
+
name: this.activeAgent.name,
|
|
786
|
+
description: 'description' in this.activeAgent ? this.activeAgent.description : '',
|
|
787
|
+
tools: (_b = this.activeAgent.toolDefinitions) !== null && _b !== void 0 ? _b : [],
|
|
788
|
+
},
|
|
789
|
+
]
|
|
790
|
+
: undefined;
|
|
791
|
+
try {
|
|
792
|
+
const suggestions = yield this.driver.getSuggestions(this.messages, suggestionsConfig.prompt || '', suggestionsConfig.count || FoundationAiAssistant_1.DEFAULT_SUGGESTION_COUNT, agentInfo);
|
|
793
|
+
if (generation !== this._suggestionsGeneration)
|
|
794
|
+
return;
|
|
795
|
+
this.suggestionsState = { status: 'loaded', suggestions };
|
|
796
|
+
this.scrollToBottom();
|
|
797
|
+
}
|
|
798
|
+
catch (e) {
|
|
799
|
+
if (generation !== this._suggestionsGeneration)
|
|
800
|
+
return;
|
|
801
|
+
this.suggestionsState = { status: 'error', message: e.message };
|
|
802
|
+
logger.error('Failed to fetch suggestions:', e);
|
|
803
|
+
}
|
|
804
|
+
});
|
|
805
|
+
}
|
|
370
806
|
send() {
|
|
371
807
|
return __awaiter(this, void 0, void 0, function* () {
|
|
372
808
|
var _a;
|
|
373
809
|
const input = this.inputValue.trim();
|
|
374
810
|
if ((!input && !this.attachments.length) || this.state === 'loading')
|
|
375
811
|
return;
|
|
812
|
+
// Capture the session ref before any await. If a lifecycle event occurs during
|
|
813
|
+
// execution, disconnectedCallback clears this._sessionRef — but the captured
|
|
814
|
+
// reference lets the finally block still write 'idle' back to the shared store,
|
|
815
|
+
// which in turn triggers the _executionCompletionUnsub subscription on whichever
|
|
816
|
+
// element is currently active (e.g. the collapse-mode element after docking).
|
|
817
|
+
const capturedSessionRef = this._sessionRef;
|
|
376
818
|
const pendingAttachments = this.attachments.length ? [...this.attachments] : undefined;
|
|
377
819
|
this.inputValue = '';
|
|
378
820
|
this.attachments = [];
|
|
379
821
|
this.attachmentErrors = [];
|
|
822
|
+
this.suggestionsState = { status: 'idle' };
|
|
823
|
+
this._userScrolledAway = false;
|
|
380
824
|
this.state = 'loading';
|
|
381
825
|
this.startLoadingTimer();
|
|
382
826
|
const displayInput = (pendingAttachments === null || pendingAttachments === void 0 ? void 0 : pendingAttachments.length)
|
|
@@ -387,15 +831,17 @@ let FoundationAiAssistant = FoundationAiAssistant_1 = class FoundationAiAssistan
|
|
|
387
831
|
}
|
|
388
832
|
finally {
|
|
389
833
|
this.stopLoadingTimer();
|
|
390
|
-
this.
|
|
834
|
+
// Write directly via captured ref — this._sessionRef may be null if the element
|
|
835
|
+
// disconnected mid-execution. The state setter also calls syncShowHalo(); replicate
|
|
836
|
+
// that here for the case where this element is still connected.
|
|
837
|
+
capturedSessionRef === null || capturedSessionRef === void 0 ? void 0 : capturedSessionRef.actions.aiAssistant.setState('idle');
|
|
838
|
+
this.syncShowHalo();
|
|
839
|
+
this.fetchSuggestions();
|
|
391
840
|
this.restoreFocusIfAppropriate();
|
|
392
841
|
}
|
|
393
842
|
});
|
|
394
843
|
}
|
|
395
844
|
restoreFocusIfAppropriate() {
|
|
396
|
-
// If focus is still within this component (document.activeElement === this, since shadow DOM
|
|
397
|
-
// reports the host) or nothing specific has focus (body), return focus to the input.
|
|
398
|
-
// If the user has navigated to another element in the app, leave them there.
|
|
399
845
|
const active = document.activeElement;
|
|
400
846
|
if (active !== document.body && active !== this)
|
|
401
847
|
return;
|
|
@@ -405,7 +851,7 @@ let FoundationAiAssistant = FoundationAiAssistant_1 = class FoundationAiAssistan
|
|
|
405
851
|
});
|
|
406
852
|
}
|
|
407
853
|
onChatHeaderMouseDown(e) {
|
|
408
|
-
if (this.popoutMode
|
|
854
|
+
if (this.popoutMode === 'collapse')
|
|
409
855
|
return;
|
|
410
856
|
e.preventDefault();
|
|
411
857
|
this.dispatchEvent(new CustomEvent('chat-header-mousedown', {
|
|
@@ -419,11 +865,14 @@ let FoundationAiAssistant = FoundationAiAssistant_1 = class FoundationAiAssistan
|
|
|
419
865
|
const detail = e.detail;
|
|
420
866
|
if (detail && detail.interactionId) {
|
|
421
867
|
this.startLoadingTimer();
|
|
422
|
-
|
|
868
|
+
const { interactionId } = detail, result = __rest(detail, ["interactionId"]);
|
|
869
|
+
(_a = this.driver) === null || _a === void 0 ? void 0 : _a.resolveInteraction(interactionId, result);
|
|
423
870
|
}
|
|
424
871
|
}
|
|
425
872
|
};
|
|
873
|
+
FoundationAiAssistant.SCROLL_BOTTOM_THRESHOLD_PX = 50;
|
|
426
874
|
FoundationAiAssistant.DEFAULT_LOADING_DELAY_S = 5;
|
|
875
|
+
FoundationAiAssistant.DEFAULT_SUGGESTION_COUNT = 3;
|
|
427
876
|
FoundationAiAssistant.MS_PER_SECOND = 1000;
|
|
428
877
|
__decorate([
|
|
429
878
|
AIProvider
|
|
@@ -453,29 +902,14 @@ __decorate([
|
|
|
453
902
|
observable
|
|
454
903
|
], FoundationAiAssistant.prototype, "debugStateFactory", void 0);
|
|
455
904
|
__decorate([
|
|
456
|
-
|
|
457
|
-
], FoundationAiAssistant.prototype, "
|
|
458
|
-
__decorate([
|
|
459
|
-
observable
|
|
460
|
-
], FoundationAiAssistant.prototype, "state", void 0);
|
|
461
|
-
__decorate([
|
|
462
|
-
observable
|
|
463
|
-
], FoundationAiAssistant.prototype, "inputValue", void 0);
|
|
905
|
+
attr({ attribute: 'debug-redux', mode: 'boolean' })
|
|
906
|
+
], FoundationAiAssistant.prototype, "debugRedux", void 0);
|
|
464
907
|
__decorate([
|
|
465
908
|
observable
|
|
466
909
|
], FoundationAiAssistant.prototype, "attachments", void 0);
|
|
467
910
|
__decorate([
|
|
468
911
|
observable
|
|
469
912
|
], FoundationAiAssistant.prototype, "attachmentErrors", void 0);
|
|
470
|
-
__decorate([
|
|
471
|
-
observable
|
|
472
|
-
], FoundationAiAssistant.prototype, "showToolCalls", void 0);
|
|
473
|
-
__decorate([
|
|
474
|
-
observable
|
|
475
|
-
], FoundationAiAssistant.prototype, "showThinkingSteps", void 0);
|
|
476
|
-
__decorate([
|
|
477
|
-
observable
|
|
478
|
-
], FoundationAiAssistant.prototype, "enabledAnimations", void 0);
|
|
479
913
|
__decorate([
|
|
480
914
|
observable
|
|
481
915
|
], FoundationAiAssistant.prototype, "showLoadingIndicator", void 0);
|
|
@@ -484,10 +918,10 @@ __decorate([
|
|
|
484
918
|
], FoundationAiAssistant.prototype, "settingsOpen", void 0);
|
|
485
919
|
__decorate([
|
|
486
920
|
observable
|
|
487
|
-
], FoundationAiAssistant.prototype, "
|
|
921
|
+
], FoundationAiAssistant.prototype, "showingSplash", void 0);
|
|
488
922
|
__decorate([
|
|
489
|
-
|
|
490
|
-
], FoundationAiAssistant.prototype, "
|
|
923
|
+
observable
|
|
924
|
+
], FoundationAiAssistant.prototype, "showHalo", void 0);
|
|
491
925
|
__decorate([
|
|
492
926
|
volatile
|
|
493
927
|
], FoundationAiAssistant.prototype, "visibleMessages", null);
|