@genesislcap/ai-assistant 14.409.0-FUI-2495.2 → 14.409.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 +1110 -2791
- package/dist/ai-assistant.d.ts +45 -267
- package/dist/dts/channel/ai-activity-channel.d.ts +0 -1
- package/dist/dts/channel/ai-activity-channel.d.ts.map +1 -1
- package/dist/dts/components/chat-driver/chat-driver.d.ts +7 -25
- package/dist/dts/components/chat-driver/chat-driver.d.ts.map +1 -1
- package/dist/dts/components/halo-overlay.d.ts +1 -13
- package/dist/dts/components/halo-overlay.d.ts.map +1 -1
- package/dist/dts/config/config.d.ts +15 -43
- package/dist/dts/config/config.d.ts.map +1 -1
- package/dist/dts/config/index.d.ts +0 -1
- package/dist/dts/config/index.d.ts.map +1 -1
- package/dist/dts/index.d.ts +0 -4
- package/dist/dts/index.d.ts.map +1 -1
- package/dist/dts/main/main.d.ts +7 -16
- 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/esm/components/chat-driver/chat-driver.js +31 -86
- package/dist/esm/components/halo-overlay.js +7 -53
- package/dist/esm/config/index.js +0 -1
- package/dist/esm/index.js +0 -4
- package/dist/esm/main/main.js +45 -103
- package/dist/esm/main/main.styles.js +4 -145
- package/dist/esm/main/main.template.js +61 -97
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +15 -15
- package/src/channel/ai-activity-channel.ts +0 -1
- package/src/components/chat-driver/chat-driver.ts +35 -116
- package/src/components/halo-overlay.ts +7 -45
- package/src/config/config.ts +15 -45
- package/src/config/index.ts +0 -1
- package/src/index.ts +0 -4
- package/src/main/main.styles.ts +4 -145
- package/src/main/main.template.ts +78 -116
- package/src/main/main.ts +50 -105
- package/dist/dts/components/ai-driver/ai-driver.d.ts +0 -38
- package/dist/dts/components/ai-driver/ai-driver.d.ts.map +0 -1
- package/dist/dts/components/ai-driver/index.d.ts +0 -2
- package/dist/dts/components/ai-driver/index.d.ts.map +0 -1
- package/dist/dts/components/orchestrating-driver/index.d.ts +0 -2
- package/dist/dts/components/orchestrating-driver/index.d.ts.map +0 -1
- package/dist/dts/components/orchestrating-driver/orchestrating-driver.d.ts +0 -36
- package/dist/dts/components/orchestrating-driver/orchestrating-driver.d.ts.map +0 -1
- package/dist/dts/components/popout-manager/index.d.ts +0 -2
- package/dist/dts/components/popout-manager/index.d.ts.map +0 -1
- package/dist/dts/components/popout-manager/popout-manager.d.ts +0 -74
- package/dist/dts/components/popout-manager/popout-manager.d.ts.map +0 -1
- package/dist/dts/config/fallback-agents.d.ts +0 -20
- package/dist/dts/config/fallback-agents.d.ts.map +0 -1
- package/dist/esm/components/ai-driver/ai-driver.js +0 -1
- package/dist/esm/components/ai-driver/index.js +0 -1
- package/dist/esm/components/orchestrating-driver/index.js +0 -1
- package/dist/esm/components/orchestrating-driver/orchestrating-driver.js +0 -229
- package/dist/esm/components/popout-manager/index.js +0 -1
- package/dist/esm/components/popout-manager/popout-manager.js +0 -119
- package/dist/esm/config/fallback-agents.js +0 -26
- package/src/components/ai-driver/ai-driver.ts +0 -42
- package/src/components/ai-driver/index.ts +0 -1
- package/src/components/orchestrating-driver/index.ts +0 -1
- package/src/components/orchestrating-driver/orchestrating-driver.ts +0 -300
- package/src/components/popout-manager/index.ts +0 -1
- package/src/components/popout-manager/popout-manager.ts +0 -144
- package/src/config/fallback-agents.ts +0 -29
|
@@ -3,9 +3,6 @@ import { ANIMATION_DEFS } from './main.types';
|
|
|
3
3
|
const animationItemRenderer = (option) => html `
|
|
4
4
|
<span part="option-label" title="${() => option.tooltip}">${() => option.label}</span>
|
|
5
5
|
`;
|
|
6
|
-
const HALO_SPEED_DEFAULT = 1.5;
|
|
7
|
-
const HALO_SPEED_ORCHESTRATING = 0.4;
|
|
8
|
-
const HALO_BORDER_SIZE_DEFAULT = 3;
|
|
9
6
|
const animationOptions = Object.entries(ANIMATION_DEFS).map(([value, def]) => ({
|
|
10
7
|
value,
|
|
11
8
|
label: def.label,
|
|
@@ -31,8 +28,6 @@ const genesisIconTemplate = html `
|
|
|
31
28
|
*/
|
|
32
29
|
const messageType = (m) => {
|
|
33
30
|
switch (true) {
|
|
34
|
-
case m.role === 'system-event':
|
|
35
|
-
return 'agent-switch';
|
|
36
31
|
case m.role === 'user':
|
|
37
32
|
return 'user';
|
|
38
33
|
case !!m.thinking:
|
|
@@ -61,31 +56,30 @@ export const FoundationAiAssistantTemplate = (designSystemPrefix) => {
|
|
|
61
56
|
const iconTag = `${designSystemPrefix}-icon`;
|
|
62
57
|
return html `
|
|
63
58
|
<div class="chat-wrapper" part="chat-wrapper">
|
|
64
|
-
${when((x) =>
|
|
59
|
+
${when((x) => !!x.chatConfig.acceptedFiles, html `
|
|
65
60
|
<input
|
|
66
61
|
class="file-input"
|
|
67
62
|
type="file"
|
|
68
63
|
multiple
|
|
69
|
-
accept=${(x) =>
|
|
64
|
+
accept=${(x) => x.chatConfig.acceptedFiles}
|
|
70
65
|
@change=${(x, c) => x.handleFileSelect(c.event)}
|
|
71
66
|
/>
|
|
72
67
|
`)}
|
|
73
|
-
${when((x) =>
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
((_c = x.chatConfig.ui) === null || _c === void 0 ? void 0 : _c.showAgentSwitchIndicator) != null ||
|
|
79
|
-
((_d = x.chatConfig.ui) === null || _d === void 0 ? void 0 : _d.allowDebugDownload) === true ||
|
|
80
|
-
((_e = x.chatConfig.ui) === null || _e === void 0 ? void 0 : _e.animations) != null;
|
|
81
|
-
}, html `
|
|
68
|
+
${when((x) => !!x.popoutMode ||
|
|
69
|
+
x.chatConfig.showToolCalls != null ||
|
|
70
|
+
x.chatConfig.showThinkingSteps != null ||
|
|
71
|
+
x.chatConfig.allowDebugDownload === true ||
|
|
72
|
+
x.chatConfig.animations != null, html `
|
|
82
73
|
<div
|
|
83
|
-
class="chat-header ${(x) => (x.popoutMode
|
|
74
|
+
class="chat-header ${(x) => (x.popoutMode === 'expand' ? 'draggable' : '')}"
|
|
84
75
|
part="chat-header"
|
|
85
76
|
@mousedown="${(x, c) => x.onChatHeaderMouseDown(c.event)}"
|
|
86
77
|
>
|
|
87
|
-
${when((x) => !!x.headerTitle, html `
|
|
88
|
-
|
|
78
|
+
${when((x) => { var _a, _b, _c; return !!((_a = x.headerTitle) !== null && _a !== void 0 ? _a : (_c = (_b = x.agents) === null || _b === void 0 ? void 0 : _b[0]) === null || _c === void 0 ? void 0 : _c.name); }, html `
|
|
79
|
+
<!-- TODO: multi-agent orchestration — bind to active agent name rather than always agents[0] -->
|
|
80
|
+
<span class="chat-title" part="chat-title">
|
|
81
|
+
${(x) => { var _a, _b, _c; return (_a = x.headerTitle) !== null && _a !== void 0 ? _a : (_c = (_b = x.agents) === null || _b === void 0 ? void 0 : _b[0]) === null || _c === void 0 ? void 0 : _c.name; }}
|
|
82
|
+
</span>
|
|
89
83
|
`)}
|
|
90
84
|
<div class="header-actions" part="header-actions">
|
|
91
85
|
<slot name="header-actions-extra"></slot>
|
|
@@ -99,14 +93,10 @@ export const FoundationAiAssistantTemplate = (designSystemPrefix) => {
|
|
|
99
93
|
@click=${(x) => x.handlePopout()}
|
|
100
94
|
><${iconTag} name="${(x) => (x.popoutMode === 'expand' ? 'external-link-alt' : 'compress-alt')}"></${iconTag}></${buttonTag}>
|
|
101
95
|
`)}
|
|
102
|
-
${when((x) =>
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
((_c = x.chatConfig.ui) === null || _c === void 0 ? void 0 : _c.showAgentSwitchIndicator) != null ||
|
|
107
|
-
((_d = x.chatConfig.ui) === null || _d === void 0 ? void 0 : _d.allowDebugDownload) === true ||
|
|
108
|
-
((_e = x.chatConfig.ui) === null || _e === void 0 ? void 0 : _e.animations) != null;
|
|
109
|
-
}, html `
|
|
96
|
+
${when((x) => x.chatConfig.showToolCalls != null ||
|
|
97
|
+
x.chatConfig.showThinkingSteps != null ||
|
|
98
|
+
x.chatConfig.allowDebugDownload === true ||
|
|
99
|
+
x.chatConfig.animations != null, html `
|
|
110
100
|
<${buttonTag}
|
|
111
101
|
class="settings-button"
|
|
112
102
|
part="settings-button"
|
|
@@ -119,35 +109,28 @@ export const FoundationAiAssistantTemplate = (designSystemPrefix) => {
|
|
|
119
109
|
</div>
|
|
120
110
|
${when((x) => x.settingsOpen, html `
|
|
121
111
|
<div class="settings-panel" part="settings-panel">
|
|
122
|
-
${when((x) =>
|
|
112
|
+
${when((x) => x.chatConfig.showToolCalls != null, html `
|
|
123
113
|
<${switchTag}
|
|
124
114
|
part="toggle-tool-calls"
|
|
125
115
|
:checked=${(x) => x.showToolCalls}
|
|
126
116
|
@change=${(x) => x.toggleShowToolCalls()}
|
|
127
117
|
>Tool calls</${switchTag}>
|
|
128
118
|
`)}
|
|
129
|
-
${when((x) =>
|
|
119
|
+
${when((x) => x.chatConfig.showThinkingSteps != null, html `
|
|
130
120
|
<${switchTag}
|
|
131
121
|
part="toggle-thinking"
|
|
132
122
|
:checked=${(x) => x.showThinkingSteps}
|
|
133
123
|
@change=${(x) => x.toggleShowThinkingSteps()}
|
|
134
124
|
>Thinking</${switchTag}>
|
|
135
125
|
`)}
|
|
136
|
-
${when((x) =>
|
|
137
|
-
<${switchTag}
|
|
138
|
-
part="toggle-agent-switch"
|
|
139
|
-
:checked=${(x) => x.showAgentSwitchIndicator}
|
|
140
|
-
@change=${(x) => x.toggleShowAgentSwitchIndicator()}
|
|
141
|
-
>Agents</${switchTag}>
|
|
142
|
-
`)}
|
|
143
|
-
${when((x) => { var _a; return ((_a = x.chatConfig.ui) === null || _a === void 0 ? void 0 : _a.allowDebugDownload) === true; }, html `
|
|
126
|
+
${when((x) => x.chatConfig.allowDebugDownload === true, html `
|
|
144
127
|
<${buttonTag}
|
|
145
128
|
part="download-button"
|
|
146
129
|
appearance="stealth"
|
|
147
|
-
@click=${(x) => x.
|
|
148
|
-
>Download
|
|
130
|
+
@click=${(x) => x.downloadHistory()}
|
|
131
|
+
>Download debug state</${buttonTag}>
|
|
149
132
|
`)}
|
|
150
|
-
${when((x) => { var _a
|
|
133
|
+
${when((x) => { var _a; return ((_a = x.chatConfig.animations) === null || _a === void 0 ? void 0 : _a.userConfigurable) === true; }, html `
|
|
151
134
|
<div class="settings-animations">
|
|
152
135
|
<span class="settings-label">Animations</span>
|
|
153
136
|
<${multiselectTag}
|
|
@@ -168,61 +151,45 @@ export const FoundationAiAssistantTemplate = (designSystemPrefix) => {
|
|
|
168
151
|
<div class="messages" part="messages">
|
|
169
152
|
|
|
170
153
|
${repeat((x) => x.visibleMessages, html `
|
|
171
|
-
${
|
|
172
|
-
|
|
173
|
-
<
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
154
|
+
<div class="message-row ${(m) => messageType(m)}">
|
|
155
|
+
${when((m) => m.role !== 'user', html `
|
|
156
|
+
<div class="avatar ${(m) => messageType(m)}">
|
|
157
|
+
${when((m, c) => !!c.parent.imageSrc, html `
|
|
158
|
+
<img
|
|
159
|
+
src="${(m, c) => c.parent.imageSrc}"
|
|
160
|
+
alt="Assistant"
|
|
161
|
+
class="avatar-img"
|
|
162
|
+
/>
|
|
163
|
+
`)}
|
|
164
|
+
${when((m, c) => !c.parent.imageSrc, genesisIconTemplate)}
|
|
165
|
+
</div>
|
|
166
|
+
`)}
|
|
167
|
+
<div class="message ${(m) => messageType(m)}">
|
|
168
|
+
<div class="sender">${(m) => senderLabel[messageType(m)]}</div>
|
|
169
|
+
<div class="content">
|
|
170
|
+
${when((m) => m.content, html `
|
|
171
|
+
<ai-chat-markdown :content="${(m) => m.content}"></ai-chat-markdown>
|
|
189
172
|
`)}
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
m.agentName &&
|
|
194
|
-
c.parent.showAgentSwitchIndicator
|
|
195
|
-
? `Tool Call · ${m.agentName}`
|
|
196
|
-
: senderLabel[messageType(m)]}
|
|
197
|
-
</div>
|
|
198
|
-
<div class="content">
|
|
199
|
-
${when((m) => m.content, html `
|
|
200
|
-
<ai-chat-markdown :content="${(m) => m.content}"></ai-chat-markdown>
|
|
201
|
-
`)}
|
|
202
|
-
${when((m) => m.toolCalls, html `
|
|
203
|
-
${repeat((m) => { var _a; return (_a = m.toolCalls) !== null && _a !== void 0 ? _a : []; }, html `
|
|
204
|
-
<pre class="payload"><strong>${(tc) => tc.name}</strong>(${(tc) => JSON.stringify(tc.args, null, 2)})</pre>
|
|
205
|
-
`)}
|
|
173
|
+
${when((m) => m.toolCalls, html `
|
|
174
|
+
${repeat((m) => { var _a; return (_a = m.toolCalls) !== null && _a !== void 0 ? _a : []; }, html `
|
|
175
|
+
<pre class="payload"><strong>${(tc) => tc.name}</strong>(${(tc) => JSON.stringify(tc.args, null, 2)})</pre>
|
|
206
176
|
`)}
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
</div>
|
|
177
|
+
`)}
|
|
178
|
+
${when((m) => m.interaction, html `
|
|
179
|
+
<ai-chat-interaction-wrapper
|
|
180
|
+
:componentName=${(m) => m.interaction.componentName}
|
|
181
|
+
:data=${(m) => m.interaction.data}
|
|
182
|
+
:interactionId=${(m) => m.interaction.interactionId}
|
|
183
|
+
:resolved=${(m) => !!m.interaction.resolved}
|
|
184
|
+
@interaction-completed=${(m, c) => c.parent.handleInteractionCompleted(c.event)}
|
|
185
|
+
></ai-chat-interaction-wrapper>
|
|
186
|
+
`)}
|
|
218
187
|
</div>
|
|
219
|
-
|
|
188
|
+
</div>
|
|
189
|
+
</div>
|
|
220
190
|
`)}
|
|
221
|
-
${when((x) =>
|
|
222
|
-
|
|
223
|
-
return x.showLoadingIndicator &&
|
|
224
|
-
(((_a = x.chatConfig.ui) === null || _a === void 0 ? void 0 : _a.animations) == null || x.enabledAnimations.includes('loading'));
|
|
225
|
-
}, html `
|
|
191
|
+
${when((x) => x.showLoadingIndicator &&
|
|
192
|
+
(x.chatConfig.animations == null || x.enabledAnimations.includes('loading')), html `
|
|
226
193
|
<div class="message-row ai" part="thinking">
|
|
227
194
|
<div class="avatar">
|
|
228
195
|
${when((x) => !!x.imageSrc, html `
|
|
@@ -270,12 +237,12 @@ export const FoundationAiAssistantTemplate = (designSystemPrefix) => {
|
|
|
270
237
|
`)}
|
|
271
238
|
|
|
272
239
|
<div class="input-row" part="input-row">
|
|
273
|
-
${when((x) =>
|
|
240
|
+
${when((x) => !!x.chatConfig.acceptedFiles, html `
|
|
274
241
|
<${buttonTag}
|
|
275
242
|
class="attach-button"
|
|
276
243
|
part="attach-button"
|
|
277
244
|
appearance="stealth"
|
|
278
|
-
title=${(x) =>
|
|
245
|
+
title=${(x) => `Attach file (${x.chatConfig.acceptedFiles})`}
|
|
279
246
|
?disabled=${(x) => x.state === 'loading'}
|
|
280
247
|
@click=${(x) => x.triggerFileInput()}
|
|
281
248
|
><${iconTag} name="paperclip"></${iconTag}></${buttonTag}>
|
|
@@ -306,10 +273,7 @@ export const FoundationAiAssistantTemplate = (designSystemPrefix) => {
|
|
|
306
273
|
</div>
|
|
307
274
|
<ai-halo-overlay
|
|
308
275
|
part="halo-overlay"
|
|
309
|
-
?active=${(x) => x.showHalo
|
|
310
|
-
:speed="${(x) => (x.showHalo === 'orchestrating' ? HALO_SPEED_ORCHESTRATING : HALO_SPEED_DEFAULT)}"
|
|
311
|
-
direction="${(x) => (x.showHalo === 'orchestrating' ? 'ccw' : 'cw')}"
|
|
312
|
-
:borderSize="${(x) => (x.showHalo === 'orchestrating' ? 2 : HALO_BORDER_SIZE_DEFAULT)}"
|
|
276
|
+
?active=${(x) => x.showHalo && x.enabledAnimations.includes('halo')}
|
|
313
277
|
></ai-halo-overlay>
|
|
314
278
|
</div>
|
|
315
279
|
`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"root":["../src/index.ts","../src/channel/ai-activity-bus.ts","../src/channel/ai-activity-channel.ts","../src/components/halo-overlay.ts","../src/components/activity-halo/activity-halo.ts","../src/components/
|
|
1
|
+
{"root":["../src/index.ts","../src/channel/ai-activity-bus.ts","../src/channel/ai-activity-channel.ts","../src/components/halo-overlay.ts","../src/components/activity-halo/activity-halo.ts","../src/components/chat-bubble/chat-bubble.styles.ts","../src/components/chat-bubble/chat-bubble.template.ts","../src/components/chat-bubble/chat-bubble.ts","../src/components/chat-bubble/index.ts","../src/components/chat-driver/chat-driver.ts","../src/components/chat-driver/index.ts","../src/components/chat-interaction-wrapper/chat-interaction-wrapper.styles.ts","../src/components/chat-interaction-wrapper/chat-interaction-wrapper.template.ts","../src/components/chat-interaction-wrapper/chat-interaction-wrapper.ts","../src/components/chat-interaction-wrapper/index.ts","../src/components/chat-markdown/chat-markdown.ts","../src/components/chat-markdown/index.ts","../src/config/config.ts","../src/config/index.ts","../src/main/index.ts","../src/main/main.styles.ts","../src/main/main.template.ts","../src/main/main.ts","../src/main/main.types.ts","../src/styles/ai-colours.ts","../src/styles/index.ts","../src/styles/styles.ts","../src/tags/index.ts","../src/types/ai-chat-widget.ts","../src/utils/index.ts","../src/utils/logger.ts"],"version":"5.9.2"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@genesislcap/ai-assistant",
|
|
3
3
|
"description": "Genesis AI Assistant micro-frontend",
|
|
4
|
-
"version": "14.409.
|
|
4
|
+
"version": "14.409.1",
|
|
5
5
|
"license": "SEE LICENSE IN license.txt",
|
|
6
6
|
"main": "dist/esm/index.js",
|
|
7
7
|
"types": "dist/ai-assistant.d.ts",
|
|
@@ -59,23 +59,23 @@
|
|
|
59
59
|
}
|
|
60
60
|
},
|
|
61
61
|
"devDependencies": {
|
|
62
|
-
"@genesislcap/foundation-testing": "14.409.
|
|
63
|
-
"@genesislcap/genx": "14.409.
|
|
64
|
-
"@genesislcap/rollup-builder": "14.409.
|
|
65
|
-
"@genesislcap/ts-builder": "14.409.
|
|
66
|
-
"@genesislcap/uvu-playwright-builder": "14.409.
|
|
67
|
-
"@genesislcap/vite-builder": "14.409.
|
|
68
|
-
"@genesislcap/webpack-builder": "14.409.
|
|
62
|
+
"@genesislcap/foundation-testing": "14.409.1",
|
|
63
|
+
"@genesislcap/genx": "14.409.1",
|
|
64
|
+
"@genesislcap/rollup-builder": "14.409.1",
|
|
65
|
+
"@genesislcap/ts-builder": "14.409.1",
|
|
66
|
+
"@genesislcap/uvu-playwright-builder": "14.409.1",
|
|
67
|
+
"@genesislcap/vite-builder": "14.409.1",
|
|
68
|
+
"@genesislcap/webpack-builder": "14.409.1",
|
|
69
69
|
"@types/dompurify": "^3.0.5",
|
|
70
70
|
"@types/marked": "^5.0.2"
|
|
71
71
|
},
|
|
72
72
|
"dependencies": {
|
|
73
|
-
"@genesislcap/foundation-ai": "14.409.
|
|
74
|
-
"@genesislcap/foundation-logger": "14.409.
|
|
75
|
-
"@genesislcap/foundation-ui": "14.409.
|
|
76
|
-
"@genesislcap/foundation-utils": "14.409.
|
|
77
|
-
"@genesislcap/rapid-design-system": "14.409.
|
|
78
|
-
"@genesislcap/web-core": "14.409.
|
|
73
|
+
"@genesislcap/foundation-ai": "14.409.1",
|
|
74
|
+
"@genesislcap/foundation-logger": "14.409.1",
|
|
75
|
+
"@genesislcap/foundation-ui": "14.409.1",
|
|
76
|
+
"@genesislcap/foundation-utils": "14.409.1",
|
|
77
|
+
"@genesislcap/rapid-design-system": "14.409.1",
|
|
78
|
+
"@genesislcap/web-core": "14.409.1",
|
|
79
79
|
"dompurify": "^3.3.1",
|
|
80
80
|
"marked": "^17.0.3"
|
|
81
81
|
},
|
|
@@ -87,5 +87,5 @@
|
|
|
87
87
|
"publishConfig": {
|
|
88
88
|
"access": "public"
|
|
89
89
|
},
|
|
90
|
-
"gitHead": "
|
|
90
|
+
"gitHead": "a23531e1359a6381e7d4fd81e98bd8d2e9981560"
|
|
91
91
|
}
|
|
@@ -1,23 +1,17 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
AIProvider,
|
|
3
3
|
ChatAttachment,
|
|
4
|
-
ChatDriverResult,
|
|
5
4
|
ChatMessage,
|
|
6
5
|
ChatRequestOptions,
|
|
7
6
|
ChatToolDefinition,
|
|
8
7
|
ChatToolHandlers,
|
|
9
8
|
} from '@genesislcap/foundation-ai';
|
|
10
9
|
import { MalformedFunctionCallError } from '@genesislcap/foundation-ai';
|
|
11
|
-
import type { AgentConfig } from '../../config/config';
|
|
12
10
|
import { logger } from '../../utils/logger';
|
|
13
|
-
import type { AiDriver } from '../ai-driver/ai-driver';
|
|
14
11
|
|
|
15
12
|
const DEFAULT_MAX_TOOL_ITERATIONS = 50;
|
|
16
13
|
const MAX_MALFORMED_RETRIES = 2;
|
|
17
14
|
|
|
18
|
-
/** Name reserved for the cross-agent handoff tool — injected by OrchestratingDriver. */
|
|
19
|
-
export const REQUEST_CONTINUATION_TOOL = 'request_continuation';
|
|
20
|
-
|
|
21
15
|
/**
|
|
22
16
|
* Event emitted when the chat history is updated (new message appended).
|
|
23
17
|
*
|
|
@@ -33,7 +27,7 @@ export type ChatHistoryUpdatedEvent = CustomEvent<ReadonlyArray<ChatMessage>>;
|
|
|
33
27
|
*
|
|
34
28
|
* @beta
|
|
35
29
|
*/
|
|
36
|
-
export class ChatDriver extends EventTarget
|
|
30
|
+
export class ChatDriver extends EventTarget {
|
|
37
31
|
private history: ChatMessage[] = [];
|
|
38
32
|
private busy = false;
|
|
39
33
|
private pendingInteractions = new Map<
|
|
@@ -41,47 +35,26 @@ export class ChatDriver extends EventTarget implements AiDriver {
|
|
|
41
35
|
{ resolve: (value: any) => void; reject: (reason?: any) => void }
|
|
42
36
|
>();
|
|
43
37
|
|
|
44
|
-
private systemPrompt?: string;
|
|
45
|
-
private toolDefinitions: ChatToolDefinition[];
|
|
46
|
-
private toolHandlers: ChatToolHandlers;
|
|
47
|
-
private primerHistory?: ChatMessage[];
|
|
48
|
-
private activeAgentName?: string;
|
|
49
|
-
|
|
50
38
|
constructor(
|
|
51
39
|
private readonly aiProvider: AIProvider,
|
|
52
|
-
toolHandlers: ChatToolHandlers = {},
|
|
53
|
-
toolDefinitions: ChatToolDefinition[] = [],
|
|
54
|
-
systemPrompt?: string,
|
|
55
|
-
primerHistory?: ChatMessage[],
|
|
40
|
+
private readonly toolHandlers: ChatToolHandlers = {},
|
|
41
|
+
private readonly toolDefinitions: ChatToolDefinition[] = [],
|
|
42
|
+
private readonly systemPrompt?: string,
|
|
43
|
+
private readonly primerHistory?: ChatMessage[],
|
|
56
44
|
private readonly maxToolIterations: number = DEFAULT_MAX_TOOL_ITERATIONS,
|
|
57
45
|
) {
|
|
58
46
|
super();
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Swap in a new agent's configuration. Called by OrchestratingDriver before
|
|
67
|
-
* each specialist turn so the shared driver runs with the right tools and prompt.
|
|
68
|
-
*/
|
|
69
|
-
applyAgent(config: AgentConfig): void {
|
|
70
|
-
this.systemPrompt = config.systemPrompt;
|
|
71
|
-
this.toolDefinitions = config.toolDefinitions ?? [];
|
|
72
|
-
this.toolHandlers = config.toolHandlers ?? {};
|
|
73
|
-
this.primerHistory = config.primerHistory;
|
|
74
|
-
this.activeAgentName = config.name;
|
|
47
|
+
if (!systemPrompt) {
|
|
48
|
+
logger.error(
|
|
49
|
+
'ChatDriver: no systemPrompt provided. The assistant will have no instructions — set the systemPrompt property on foundation-ai-assistant.',
|
|
50
|
+
);
|
|
51
|
+
}
|
|
75
52
|
}
|
|
76
53
|
|
|
77
54
|
getHistory(): ReadonlyArray<ChatMessage> {
|
|
78
55
|
return this.history;
|
|
79
56
|
}
|
|
80
57
|
|
|
81
|
-
getRawHistory(): readonly ChatMessage[] {
|
|
82
|
-
return this.history;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
58
|
isBusy(): boolean {
|
|
86
59
|
return this.busy;
|
|
87
60
|
}
|
|
@@ -136,95 +109,55 @@ export class ChatDriver extends EventTarget implements AiDriver {
|
|
|
136
109
|
*/
|
|
137
110
|
public loadHistory(messages: ChatMessage[]): void {
|
|
138
111
|
this.history = [...messages];
|
|
139
|
-
this.dispatchEvent(
|
|
140
|
-
new CustomEvent<ReadonlyArray<ChatMessage>>('history-updated', {
|
|
141
|
-
detail: this.history,
|
|
142
|
-
}),
|
|
143
|
-
);
|
|
144
112
|
}
|
|
145
113
|
|
|
146
|
-
async sendMessage(userInput: string, attachments?: ChatAttachment[]): Promise<
|
|
147
|
-
if (this.busy || (!userInput.trim() && !attachments?.length)) return
|
|
114
|
+
async sendMessage(userInput: string, attachments?: ChatAttachment[]): Promise<void> {
|
|
115
|
+
if (this.busy || (!userInput.trim() && !attachments?.length)) return;
|
|
148
116
|
if (!this.aiProvider.chat) {
|
|
149
117
|
logger.warn('ChatDriver: AIProvider does not implement chat()');
|
|
150
|
-
return
|
|
118
|
+
return;
|
|
151
119
|
}
|
|
152
120
|
|
|
153
121
|
this.busy = true;
|
|
154
122
|
this.appendToHistory({ role: 'user', content: userInput, attachments });
|
|
155
123
|
|
|
156
124
|
try {
|
|
157
|
-
|
|
158
|
-
} catch (e) {
|
|
159
|
-
logger.error('ChatDriver error:', e);
|
|
160
|
-
this.appendToHistory({ role: 'assistant', content: 'Sorry, something went wrong.' });
|
|
161
|
-
return { reason: 'done' };
|
|
162
|
-
} finally {
|
|
163
|
-
this.busy = false;
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
/**
|
|
168
|
-
* Continue the tool loop from current history without appending a new user message.
|
|
169
|
-
* Used by OrchestratingDriver after an agent handoff — the handoff context is
|
|
170
|
-
* already in history; `transientPrimer` is injected as an invisible one-shot
|
|
171
|
-
* message for this call only.
|
|
172
|
-
*/
|
|
173
|
-
async continueFromHistory(transientPrimer?: ChatMessage[]): Promise<ChatDriverResult> {
|
|
174
|
-
if (this.busy) return { reason: 'done' };
|
|
175
|
-
if (!this.aiProvider.chat) {
|
|
176
|
-
logger.warn('ChatDriver: AIProvider does not implement chat()');
|
|
177
|
-
return { reason: 'done' };
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
this.busy = true;
|
|
181
|
-
try {
|
|
182
|
-
return await this.runToolLoop('', undefined, transientPrimer);
|
|
125
|
+
await this.runToolLoop(userInput, attachments);
|
|
183
126
|
} catch (e) {
|
|
184
127
|
logger.error('ChatDriver error:', e);
|
|
185
128
|
this.appendToHistory({ role: 'assistant', content: 'Sorry, something went wrong.' });
|
|
186
|
-
return { reason: 'done' };
|
|
187
129
|
} finally {
|
|
188
130
|
this.busy = false;
|
|
189
131
|
}
|
|
190
132
|
}
|
|
191
133
|
|
|
192
|
-
private async runToolLoop(
|
|
193
|
-
userInput: string,
|
|
194
|
-
attachments?: ChatAttachment[],
|
|
195
|
-
transientPrimer?: ChatMessage[],
|
|
196
|
-
): Promise<ChatDriverResult> {
|
|
197
|
-
if (!this.systemPrompt) {
|
|
198
|
-
logger.warn(
|
|
199
|
-
'ChatDriver: no systemPrompt set. The assistant will have no instructions — provide a systemPrompt via agents config or the foundation-ai-assistant property.',
|
|
200
|
-
);
|
|
201
|
-
}
|
|
134
|
+
private async runToolLoop(userInput: string, attachments?: ChatAttachment[]): Promise<void> {
|
|
202
135
|
const baseOptions: ChatRequestOptions = {
|
|
203
136
|
systemPrompt: this.systemPrompt,
|
|
204
137
|
tools: this.toolDefinitions.length ? this.toolDefinitions : undefined,
|
|
205
138
|
};
|
|
206
139
|
|
|
140
|
+
// History has the user message at the end — pass everything before it as history,
|
|
141
|
+
// and the user input as the userMessage argument.
|
|
207
142
|
let currentInput = userInput;
|
|
208
143
|
let currentAttachments: ChatAttachment[] | undefined = attachments;
|
|
209
144
|
let iterations = 0;
|
|
210
145
|
let malformedAttempts = 0;
|
|
211
|
-
// continueFromHistory callers pass empty input — start at iteration 1 so
|
|
212
|
-
// the first LLM call sees the full history (no slice-off-last logic).
|
|
213
|
-
const startIteration = currentInput ? 1 : 0;
|
|
214
146
|
|
|
215
147
|
while (iterations < this.maxToolIterations) {
|
|
216
148
|
iterations += 1;
|
|
217
149
|
|
|
218
|
-
// On the first iteration
|
|
219
|
-
//
|
|
220
|
-
//
|
|
221
|
-
//
|
|
222
|
-
|
|
150
|
+
// On the first iteration, the last item in history is the user message which is
|
|
151
|
+
// passed separately as currentInput — exclude it. On subsequent iterations, the
|
|
152
|
+
// full history (including tool results) should be sent and currentInput is empty.
|
|
153
|
+
// primerHistory (if provided) is prepended to every call but never stored in
|
|
154
|
+
// this.history and never shown in the UI.
|
|
155
|
+
const primer = this.primerHistory ?? [];
|
|
223
156
|
const historyForCall =
|
|
224
|
-
iterations ===
|
|
225
|
-
? [...primer, ...this.history.slice(0, -1)]
|
|
226
|
-
: [...primer, ...this.history];
|
|
157
|
+
iterations === 1 ? [...primer, ...this.history.slice(0, -1)] : [...primer, ...this.history];
|
|
227
158
|
|
|
159
|
+
// On malformed-call retries, augment the system prompt to steer the model
|
|
160
|
+
// away from generating Python-style batched function call syntax.
|
|
228
161
|
const systemPrompt =
|
|
229
162
|
malformedAttempts > 0
|
|
230
163
|
? `${baseOptions.systemPrompt ?? ''}\n\nIMPORTANT: Use only the structured function-call API to invoke tools. Do not write Python code or use Python-style syntax to call tools.`
|
|
@@ -247,7 +180,7 @@ export class ChatDriver extends EventTarget implements AiDriver {
|
|
|
247
180
|
logger.warn(
|
|
248
181
|
`ChatDriver: MALFORMED_FUNCTION_CALL, retrying (${malformedAttempts}/${MAX_MALFORMED_RETRIES})`,
|
|
249
182
|
);
|
|
250
|
-
iterations -= 1;
|
|
183
|
+
iterations -= 1; // don't consume an iteration budget slot for a failed attempt
|
|
251
184
|
continue;
|
|
252
185
|
}
|
|
253
186
|
logger.error('ChatDriver: MALFORMED_FUNCTION_CALL, max retries reached');
|
|
@@ -256,19 +189,20 @@ export class ChatDriver extends EventTarget implements AiDriver {
|
|
|
256
189
|
content:
|
|
257
190
|
"I'm sorry, I wasn't able to complete that request. Please try rephrasing or breaking it into smaller steps.",
|
|
258
191
|
});
|
|
259
|
-
return
|
|
192
|
+
return;
|
|
260
193
|
}
|
|
261
194
|
throw e;
|
|
262
195
|
}
|
|
263
196
|
|
|
264
|
-
currentAttachments = undefined;
|
|
197
|
+
currentAttachments = undefined; // attachments only sent on first call
|
|
265
198
|
|
|
266
199
|
const isThinkingStep = response.content && response.toolCalls?.length;
|
|
267
200
|
const isEmptyResponse = !response.content?.trim() && !response.toolCalls?.length;
|
|
268
201
|
|
|
269
202
|
if (isEmptyResponse) {
|
|
270
|
-
//
|
|
203
|
+
// Do nothing, discard empty/whitespace-only responses
|
|
271
204
|
} else if (isThinkingStep) {
|
|
205
|
+
// Separate thinking message and tool call message
|
|
272
206
|
this.appendToHistory({ ...response, toolCalls: undefined, thinking: true });
|
|
273
207
|
this.appendToHistory({ ...response, content: '' });
|
|
274
208
|
} else {
|
|
@@ -276,22 +210,11 @@ export class ChatDriver extends EventTarget implements AiDriver {
|
|
|
276
210
|
}
|
|
277
211
|
|
|
278
212
|
if (!response.toolCalls?.length) {
|
|
213
|
+
// Terminal text response — done
|
|
279
214
|
break;
|
|
280
215
|
}
|
|
281
216
|
|
|
282
|
-
//
|
|
283
|
-
// system tool intercepted by OrchestratingDriver, not a real handler.
|
|
284
|
-
const continuationCall = response.toolCalls.find(
|
|
285
|
-
(tc) => tc.name === REQUEST_CONTINUATION_TOOL,
|
|
286
|
-
);
|
|
287
|
-
if (continuationCall) {
|
|
288
|
-
const { summary, remaining_task: remainingTask } = continuationCall.args as {
|
|
289
|
-
summary: string;
|
|
290
|
-
remaining_task: string;
|
|
291
|
-
};
|
|
292
|
-
return { reason: 'agent-handoff', summary, remainingTask };
|
|
293
|
-
}
|
|
294
|
-
|
|
217
|
+
// Execute all tool calls for this iteration concurrently, then append results in order
|
|
295
218
|
// eslint-disable-next-line no-await-in-loop
|
|
296
219
|
const toolResults = await Promise.all(
|
|
297
220
|
response.toolCalls.map(async (tc) => {
|
|
@@ -322,21 +245,17 @@ export class ChatDriver extends EventTarget implements AiDriver {
|
|
|
322
245
|
});
|
|
323
246
|
}
|
|
324
247
|
|
|
248
|
+
// Next iteration sends an empty string — the tool results are in history
|
|
325
249
|
currentInput = '';
|
|
326
250
|
}
|
|
327
251
|
|
|
328
252
|
if (iterations >= this.maxToolIterations) {
|
|
329
253
|
logger.warn('ChatDriver: reached max tool iterations, stopping');
|
|
330
254
|
}
|
|
331
|
-
|
|
332
|
-
return { reason: 'done' };
|
|
333
255
|
}
|
|
334
256
|
|
|
335
257
|
private appendToHistory(message: ChatMessage): void {
|
|
336
|
-
|
|
337
|
-
? { ...message, agentName: this.activeAgentName }
|
|
338
|
-
: message;
|
|
339
|
-
this.history = [...this.history, tagged];
|
|
258
|
+
this.history = [...this.history, message];
|
|
340
259
|
this.dispatchEvent(
|
|
341
260
|
new CustomEvent<ReadonlyArray<ChatMessage>>('history-updated', {
|
|
342
261
|
detail: this.history,
|