@genesislcap/ai-assistant 14.420.0 → 14.421.0
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
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { createStore } from '@genesislcap/foundation-redux';
|
|
2
|
+
import { aiAssistantSlice, defaultSessionState, } from './ai-assistant-slice';
|
|
3
|
+
const sessionStores = new Map();
|
|
4
|
+
function makeStore(devTools) {
|
|
5
|
+
return createStore([aiAssistantSlice], { aiAssistant: defaultSessionState }, devTools !== undefined ? { devTools } : undefined);
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Returns the session store for the given key, creating one if it does not
|
|
9
|
+
* already exist. Omit `devTools` (or pass `undefined`) to defer to `isDev()`.
|
|
10
|
+
* Pass `true` to force-enable or `false` to force-disable Redux DevTools.
|
|
11
|
+
*/
|
|
12
|
+
export function getSessionStore(key, devTools) {
|
|
13
|
+
const existing = sessionStores.get(key);
|
|
14
|
+
if (existing)
|
|
15
|
+
return existing;
|
|
16
|
+
const created = makeStore(devTools);
|
|
17
|
+
sessionStores.set(key, created);
|
|
18
|
+
return created;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Returns true if a session store already exists for the given key.
|
|
22
|
+
*/
|
|
23
|
+
export function hasSessionStore(key) {
|
|
24
|
+
return sessionStores.has(key);
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Deletes the session store for the given key.
|
|
28
|
+
*/
|
|
29
|
+
export function deleteSessionStore(key) {
|
|
30
|
+
sessionStores.delete(key);
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Removes all session stores. Exposed for test isolation only — not part of the public API.
|
|
34
|
+
*
|
|
35
|
+
* @internal
|
|
36
|
+
*/
|
|
37
|
+
export function clearAllSessionStores() {
|
|
38
|
+
sessionStores.clear();
|
|
39
|
+
}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { __decorate } from "tslib";
|
|
2
|
+
import { customElement, observable, html, css, repeat, when } from '@genesislcap/web-core';
|
|
3
|
+
import { GenesisElement } from '@genesislcap/web-core';
|
|
4
|
+
const PILL_ANIMATION_STAGGER_MS = 70;
|
|
5
|
+
const template = html `
|
|
6
|
+
${when((x) => x.state.status === 'loading', html `
|
|
7
|
+
<div class="suggestions-container">
|
|
8
|
+
${repeat(() => Array.from({ length: 3 }), html `
|
|
9
|
+
<div class="suggestion-placeholder"></div>
|
|
10
|
+
`)}
|
|
11
|
+
</div>
|
|
12
|
+
`)}
|
|
13
|
+
${when((x) => x.state.status === 'loaded', html `
|
|
14
|
+
<div class="suggestions-container">
|
|
15
|
+
${repeat((x) => x.state.suggestions, html `
|
|
16
|
+
<button
|
|
17
|
+
class="suggestion-pill"
|
|
18
|
+
style="animation-delay: ${(_, c) => c.index * PILL_ANIMATION_STAGGER_MS}ms"
|
|
19
|
+
@click="${(suggestion, c) => c.parent.handleSuggestionClick(suggestion)}"
|
|
20
|
+
>
|
|
21
|
+
${(suggestion) => suggestion}
|
|
22
|
+
</button>
|
|
23
|
+
`)}
|
|
24
|
+
</div>
|
|
25
|
+
`)}
|
|
26
|
+
`;
|
|
27
|
+
const styles = css `
|
|
28
|
+
:host {
|
|
29
|
+
display: block;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.suggestions-container {
|
|
33
|
+
display: flex;
|
|
34
|
+
flex-wrap: wrap;
|
|
35
|
+
gap: 6px;
|
|
36
|
+
padding: 10px calc(var(--design-unit) * 3px) 6px;
|
|
37
|
+
background-color: var(--neutral-layer-2);
|
|
38
|
+
animation: suggestions-appear 0.2s ease-out both;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
@keyframes suggestions-appear {
|
|
42
|
+
from {
|
|
43
|
+
opacity: 0;
|
|
44
|
+
transform: translateY(6px);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
to {
|
|
48
|
+
opacity: 1;
|
|
49
|
+
transform: translateY(0);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.suggestion-pill {
|
|
54
|
+
display: inline-flex;
|
|
55
|
+
align-items: center;
|
|
56
|
+
padding: 5px 14px;
|
|
57
|
+
background: color-mix(in srgb, var(--accent-fill-rest) 10%, var(--neutral-layer-3));
|
|
58
|
+
color: var(--neutral-foreground-rest);
|
|
59
|
+
border: 1px solid color-mix(in srgb, var(--accent-fill-rest) 25%, var(--neutral-stroke-rest));
|
|
60
|
+
border-radius: 20px;
|
|
61
|
+
font-family: var(--body-font);
|
|
62
|
+
font-size: 0.85em;
|
|
63
|
+
cursor: pointer;
|
|
64
|
+
transition:
|
|
65
|
+
background 0.15s ease,
|
|
66
|
+
border-color 0.15s ease,
|
|
67
|
+
transform 0.15s ease,
|
|
68
|
+
box-shadow 0.15s ease;
|
|
69
|
+
animation: pill-appear 0.3s ease-out both;
|
|
70
|
+
max-width: 100%;
|
|
71
|
+
white-space: normal;
|
|
72
|
+
text-align: left;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
.suggestion-pill:hover {
|
|
76
|
+
background: color-mix(in srgb, var(--accent-fill-rest) 20%, var(--neutral-layer-3));
|
|
77
|
+
border-color: color-mix(in srgb, var(--accent-fill-rest) 50%, var(--neutral-stroke-rest));
|
|
78
|
+
transform: translateY(-1px);
|
|
79
|
+
box-shadow: 0 2px 8px color-mix(in srgb, var(--accent-fill-rest) 20%, transparent);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.suggestion-pill:active {
|
|
83
|
+
transform: translateY(0);
|
|
84
|
+
box-shadow: none;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
@keyframes pill-appear {
|
|
88
|
+
from {
|
|
89
|
+
opacity: 0;
|
|
90
|
+
transform: scale(0.88) translateY(4px);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
to {
|
|
94
|
+
opacity: 1;
|
|
95
|
+
transform: scale(1) translateY(0);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.suggestion-placeholder {
|
|
100
|
+
height: 30px;
|
|
101
|
+
width: 110px;
|
|
102
|
+
background: var(--neutral-layer-3);
|
|
103
|
+
border-radius: 20px;
|
|
104
|
+
animation: placeholder-pulse 1.6s ease-in-out infinite;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
.suggestion-placeholder:nth-child(2) {
|
|
108
|
+
width: 150px;
|
|
109
|
+
animation-delay: 0.25s;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
.suggestion-placeholder:nth-child(3) {
|
|
113
|
+
width: 130px;
|
|
114
|
+
animation-delay: 0.5s;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
@keyframes placeholder-pulse {
|
|
118
|
+
0%,
|
|
119
|
+
100% {
|
|
120
|
+
opacity: 0.35;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
50% {
|
|
124
|
+
opacity: 0.65;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
`;
|
|
128
|
+
let ChatSuggestions = class ChatSuggestions extends GenesisElement {
|
|
129
|
+
constructor() {
|
|
130
|
+
super(...arguments);
|
|
131
|
+
this.state = { status: 'idle' };
|
|
132
|
+
}
|
|
133
|
+
handleSuggestionClick(suggestion) {
|
|
134
|
+
this.$emit('suggestion-clicked', suggestion);
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
__decorate([
|
|
138
|
+
observable
|
|
139
|
+
], ChatSuggestions.prototype, "state", void 0);
|
|
140
|
+
ChatSuggestions = __decorate([
|
|
141
|
+
customElement({
|
|
142
|
+
name: 'chat-suggestions',
|
|
143
|
+
template,
|
|
144
|
+
styles,
|
|
145
|
+
})
|
|
146
|
+
], ChatSuggestions);
|
|
147
|
+
export { ChatSuggestions };
|
package/dist/esm/utils/index.js
CHANGED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { __awaiter } from "tslib";
|
|
2
|
+
/**
|
|
3
|
+
* Symbol used to attach ToolFold metadata to a facade handler function.
|
|
4
|
+
* The ChatDriver inspects this to detect fold facades at runtime.
|
|
5
|
+
*
|
|
6
|
+
* @internal
|
|
7
|
+
*/
|
|
8
|
+
export const TOOL_FOLD_SYMBOL = Symbol('toolFold');
|
|
9
|
+
/**
|
|
10
|
+
* Creates a tool fold — a facade that hides a group of related tools behind a single
|
|
11
|
+
* named entry, revealing them progressively when the model invokes the facade.
|
|
12
|
+
*
|
|
13
|
+
* The `tools` and `handlers` parameters accept the exact same types as `AgentConfig.toolDefinitions`
|
|
14
|
+
* and `AgentConfig.toolHandlers`, so existing tool creation functions can be passed in unchanged.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```typescript
|
|
18
|
+
* const tradingTools = createToolFold({
|
|
19
|
+
* name: 'trading_tools',
|
|
20
|
+
* tools: createTradesToolDefinitions(),
|
|
21
|
+
* handlers: createTradesToolHandlers(connect),
|
|
22
|
+
* });
|
|
23
|
+
*
|
|
24
|
+
* const agent: AgentConfig = {
|
|
25
|
+
* name: 'Trades',
|
|
26
|
+
* systemPrompt: '...',
|
|
27
|
+
* toolDefinitions: [getCurrentDateDef, tradingTools.definition],
|
|
28
|
+
* toolHandlers: { get_current_date: handler, ...tradingTools.handler },
|
|
29
|
+
* };
|
|
30
|
+
* ```
|
|
31
|
+
*
|
|
32
|
+
* @example Nesting folds
|
|
33
|
+
* ```typescript
|
|
34
|
+
* const insertFold = createToolFold({
|
|
35
|
+
* name: 'trade_insertion',
|
|
36
|
+
* tools: [validateDef, insertDef],
|
|
37
|
+
* handlers: { validate_trade: vHandler, insert_trade: iHandler },
|
|
38
|
+
* });
|
|
39
|
+
*
|
|
40
|
+
* const tradingFold = createToolFold({
|
|
41
|
+
* name: 'trading_tools',
|
|
42
|
+
* tools: [searchDef, insertFold.definition],
|
|
43
|
+
* handlers: { search_trades: sHandler, ...insertFold.handler },
|
|
44
|
+
* });
|
|
45
|
+
* ```
|
|
46
|
+
*
|
|
47
|
+
* @beta
|
|
48
|
+
*/
|
|
49
|
+
export function createToolFold(config) {
|
|
50
|
+
var _a, _b;
|
|
51
|
+
const description = (_a = config.description) !== null && _a !== void 0 ? _a : `Contains: ${config.tools.map((t) => t.name).join(', ')}. Invoke to access these tools.`;
|
|
52
|
+
const fold = {
|
|
53
|
+
name: config.name,
|
|
54
|
+
description,
|
|
55
|
+
usageNotes: config.usageNotes,
|
|
56
|
+
tools: config.tools,
|
|
57
|
+
handlers: config.handlers,
|
|
58
|
+
exclusive: (_b = config.exclusive) !== null && _b !== void 0 ? _b : true,
|
|
59
|
+
};
|
|
60
|
+
const definition = {
|
|
61
|
+
name: config.name,
|
|
62
|
+
description,
|
|
63
|
+
parameters: { type: 'object', properties: {} },
|
|
64
|
+
};
|
|
65
|
+
// The facade handler body is never actually called — the driver intercepts it
|
|
66
|
+
// via TOOL_FOLD_SYMBOL before dispatch. The body is a no-op fallback.
|
|
67
|
+
const facadeHandler = () => __awaiter(this, void 0, void 0, function* () { return `Fold: ${config.name}`; });
|
|
68
|
+
facadeHandler[TOOL_FOLD_SYMBOL] = fold;
|
|
69
|
+
return {
|
|
70
|
+
definition,
|
|
71
|
+
handler: {
|
|
72
|
+
[config.name]: facadeHandler,
|
|
73
|
+
},
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Expands a flat list of tool definitions into a nested tree by resolving fold
|
|
78
|
+
* metadata from the corresponding handlers. Use this for debug output so the
|
|
79
|
+
* full tool hierarchy is visible rather than just the top-level facade names.
|
|
80
|
+
*
|
|
81
|
+
* @beta
|
|
82
|
+
*/
|
|
83
|
+
export function expandToolTree(definitions, handlers) {
|
|
84
|
+
return definitions.map((def) => {
|
|
85
|
+
const handler = handlers[def.name];
|
|
86
|
+
const fold = handler ? handler[TOOL_FOLD_SYMBOL] : undefined;
|
|
87
|
+
if (fold) {
|
|
88
|
+
return Object.assign(Object.assign({}, def), { tools: expandToolTree(fold.tools, fold.handlers) });
|
|
89
|
+
}
|
|
90
|
+
return Object.assign({}, def);
|
|
91
|
+
});
|
|
92
|
+
}
|
|
@@ -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/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"}
|
|
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/ai-driver/ai-driver.ts","../src/components/ai-driver/index.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/components/orchestrating-driver/index.ts","../src/components/orchestrating-driver/orchestrating-driver.ts","../src/components/popout-manager/index.ts","../src/components/popout-manager/popout-manager.ts","../src/config/config.ts","../src/config/fallback-agents.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/state/ai-assistant-slice.ts","../src/state/driver-registry.ts","../src/state/session-store.ts","../src/styles/ai-colours.ts","../src/styles/index.ts","../src/styles/styles.ts","../src/suggestions/chat-suggestions.ts","../src/tags/index.ts","../src/types/ai-chat-widget.ts","../src/utils/index.ts","../src/utils/logger.ts","../src/utils/tool-fold.ts"],"version":"5.9.2"}
|
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
# Migration Guide — FUI-2495 (AI Header & Orchestration)
|
|
2
|
+
|
|
3
|
+
This document lists every breaking change introduced by the `mw/FUI-2495-ai-header-and-orchestration` branch and shows exactly what to change in consumer code.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. `ChatConfig` restructured into sub-namespaces
|
|
8
|
+
|
|
9
|
+
`ChatConfig` (from `@genesislcap/foundation-ai`) was a flat interface. It is now a three-field wrapper. The old fields have been split across `ui`, `agent`, and `suggestions`.
|
|
10
|
+
|
|
11
|
+
The old `ChatConfig` interface is renamed `ChatUiConfig` and is still exported for typing the `ui` field.
|
|
12
|
+
|
|
13
|
+
**Before**
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
import type { ChatConfig } from '@genesislcap/foundation-ai';
|
|
17
|
+
|
|
18
|
+
const chatConfig: ChatConfig = {
|
|
19
|
+
showToolCalls: true,
|
|
20
|
+
showThinkingSteps: false,
|
|
21
|
+
allowDebugDownload: true,
|
|
22
|
+
acceptedFiles: '.txt,.md',
|
|
23
|
+
loadingDelay: 5,
|
|
24
|
+
animations: { enabledAnimations: ['halo'] },
|
|
25
|
+
maxToolIterations: 50,
|
|
26
|
+
};
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
**After**
|
|
30
|
+
|
|
31
|
+
```ts
|
|
32
|
+
import type { ChatConfig } from '@genesislcap/foundation-ai';
|
|
33
|
+
|
|
34
|
+
const chatConfig: ChatConfig = {
|
|
35
|
+
ui: {
|
|
36
|
+
showToolCalls: true,
|
|
37
|
+
showThinkingSteps: false,
|
|
38
|
+
allowDebugDownload: true,
|
|
39
|
+
acceptedFiles: '.txt,.md',
|
|
40
|
+
loadingDelay: 5,
|
|
41
|
+
animations: { enabledAnimations: ['halo'] },
|
|
42
|
+
},
|
|
43
|
+
agent: {
|
|
44
|
+
maxToolIterations: 50,
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
**New fields available** (all optional):
|
|
50
|
+
|
|
51
|
+
| Namespace | Field | Description |
|
|
52
|
+
|---|---|---|
|
|
53
|
+
| `ui` | `showSplash` | Show `slot="splash"` content when no messages exist |
|
|
54
|
+
| `ui` | `showAgentSwitchIndicator` | Show a divider when the active specialist changes |
|
|
55
|
+
| `ui` | `showContextUsage` | Show context window usage in the settings panel |
|
|
56
|
+
| `agent` | `maxHandoffs` | Max agent-to-agent handoffs per user turn (default: 3) |
|
|
57
|
+
| `agent` | `classifierHistoryLength` | Recent messages passed to the classifier (default: 4) |
|
|
58
|
+
| `agent` | `classifierRetries` | Retries on classifier failure (default: 2) |
|
|
59
|
+
| `agent` | `maxFoldOperations` | Max fold open/close cycles before a guidance message is injected (default: 5) |
|
|
60
|
+
| `suggestions` | `behavior` | `'never'` \| `'initial'` \| `'always'` |
|
|
61
|
+
| `suggestions` | `count` | Number of suggestions to generate (default: 3) |
|
|
62
|
+
| `suggestions` | `prompt` | Custom prompt to steer suggestion generation |
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## 2. `AgentConfig` is now a discriminated union
|
|
67
|
+
|
|
68
|
+
`AgentConfig` (from `@genesislcap/foundation-mf/ai-assistant`) was a single flat interface. It is now a union of `SpecialistAgentConfig` (requires `description`) and `FallbackAgentConfig` (requires `fallback: true`).
|
|
69
|
+
|
|
70
|
+
**Existing single-agent usage — no change required.** TypeScript will resolve the object as `SpecialistAgentConfig` automatically as long as `description` is present.
|
|
71
|
+
|
|
72
|
+
**Before (multi-agent)**
|
|
73
|
+
|
|
74
|
+
```ts
|
|
75
|
+
import type { AgentConfig } from '@genesislcap/foundation-mf/ai-assistant';
|
|
76
|
+
|
|
77
|
+
const agents: AgentConfig[] = [
|
|
78
|
+
{
|
|
79
|
+
name: 'Trades Agent',
|
|
80
|
+
description: 'Handles trade queries and execution.',
|
|
81
|
+
systemPrompt: '...',
|
|
82
|
+
toolHandlers: { ... },
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
name: 'General Agent',
|
|
86
|
+
description: 'Handles everything else.',
|
|
87
|
+
systemPrompt: '...',
|
|
88
|
+
},
|
|
89
|
+
];
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
**After** — if you want a dedicated fallback agent, mark it explicitly. Specialist agents are unchanged.
|
|
93
|
+
|
|
94
|
+
```ts
|
|
95
|
+
import type { AgentConfig } from '@genesislcap/foundation-mf/ai-assistant';
|
|
96
|
+
|
|
97
|
+
const agents: AgentConfig[] = [
|
|
98
|
+
{
|
|
99
|
+
name: 'Trades Agent',
|
|
100
|
+
description: 'Handles trade queries and execution.', // still required for specialists
|
|
101
|
+
systemPrompt: '...',
|
|
102
|
+
toolHandlers: { ... },
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
name: 'General Agent',
|
|
106
|
+
fallback: true, // replaces description for the catch-all agent
|
|
107
|
+
systemPrompt: '...',
|
|
108
|
+
},
|
|
109
|
+
];
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
**Rules:**
|
|
113
|
+
- A specialist must have `description` and must not have `fallback`.
|
|
114
|
+
- A fallback must have `fallback: true` and must not have `description`.
|
|
115
|
+
- Only one fallback is permitted per `agents` array.
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## 3. `chat-popout` and `chat-popin` bus events no longer carry a state payload
|
|
120
|
+
|
|
121
|
+
`AiAssistantSerializedState` has been deleted. The `chat-popout` and `chat-popin` bus events now carry `undefined`. State is managed automatically by the Redux session store shared between the bubble and layout instances — no manual transfer is required.
|
|
122
|
+
|
|
123
|
+
**Before**
|
|
124
|
+
|
|
125
|
+
```ts
|
|
126
|
+
import { agenticActivityBus } from '@genesislcap/foundation-mf/ai-assistant';
|
|
127
|
+
import type { AiAssistantSerializedState } from '@genesislcap/foundation-mf/ai-assistant';
|
|
128
|
+
|
|
129
|
+
agenticActivityBus.subscribe('chat-popin', ({ state }: { state: AiAssistantSerializedState }) => {
|
|
130
|
+
myAssistant.applyState(state);
|
|
131
|
+
});
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
**After**
|
|
135
|
+
|
|
136
|
+
```ts
|
|
137
|
+
import { agenticActivityBus } from '@genesislcap/foundation-mf/ai-assistant';
|
|
138
|
+
|
|
139
|
+
// No payload — state transfer is automatic.
|
|
140
|
+
agenticActivityBus.subscribe('chat-popin', () => {
|
|
141
|
+
// React to the event if needed, but state is already synced.
|
|
142
|
+
});
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Remove all imports of `AiAssistantSerializedState` — it no longer exists.
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## 4. `applyState()` and `serializeState()` removed from `FoundationAiAssistant`
|
|
150
|
+
|
|
151
|
+
These methods were used to manually transfer state between the bubble and layout instances. The session store makes them redundant.
|
|
152
|
+
|
|
153
|
+
**Before**
|
|
154
|
+
|
|
155
|
+
```ts
|
|
156
|
+
const state = bubbleAssistant.serializeState();
|
|
157
|
+
layoutAssistant.applyState(state);
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
**After** — delete these call sites. The session store handles state continuity automatically when the component is connected/disconnected.
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
## 5. `ChatInteraction.resolved` changed from `boolean` to `InteractionResult<unknown>`
|
|
165
|
+
|
|
166
|
+
**Before**
|
|
167
|
+
|
|
168
|
+
```ts
|
|
169
|
+
if (this.resolved === true) {
|
|
170
|
+
// show read-only state
|
|
171
|
+
}
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
**After** — use a truthy check. The value itself is now the result object, which widgets can also read.
|
|
175
|
+
|
|
176
|
+
```ts
|
|
177
|
+
if (this.resolved) {
|
|
178
|
+
// show read-only state
|
|
179
|
+
// optionally: use this.resolved.value for the result data
|
|
180
|
+
}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
If your interaction component explicitly typed this field:
|
|
184
|
+
|
|
185
|
+
```ts
|
|
186
|
+
// Before
|
|
187
|
+
resolved?: boolean;
|
|
188
|
+
|
|
189
|
+
// After
|
|
190
|
+
import type { InteractionResult } from '@genesislcap/foundation-ai';
|
|
191
|
+
resolved?: InteractionResult<unknown>;
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
## 6. `ChatToolCall` changed from an interface to a union type
|
|
197
|
+
|
|
198
|
+
`ChatToolCall` is now `ChatToolCallBase | ChatToolCallUnknown`. Code that was written against the original interface will still compile, but exhaustive handling should use the new type guard.
|
|
199
|
+
|
|
200
|
+
**Before**
|
|
201
|
+
|
|
202
|
+
```ts
|
|
203
|
+
import type { ChatToolCall } from '@genesislcap/foundation-ai';
|
|
204
|
+
|
|
205
|
+
function handleToolCall(tc: ChatToolCall) {
|
|
206
|
+
console.log(tc.name, tc.args);
|
|
207
|
+
}
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
**After** — use `isChatToolCallUnknown` before narrowing:
|
|
211
|
+
|
|
212
|
+
```ts
|
|
213
|
+
import { isChatToolCallUnknown } from '@genesislcap/foundation-ai';
|
|
214
|
+
import type { ChatToolCall } from '@genesislcap/foundation-ai';
|
|
215
|
+
|
|
216
|
+
function handleToolCall(tc: ChatToolCall) {
|
|
217
|
+
if (isChatToolCallUnknown(tc)) {
|
|
218
|
+
console.warn('Unknown tool call', tc.name, 'Available:', tc.availableTools);
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
console.log(tc.name, tc.args);
|
|
222
|
+
}
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
New optional fields on all `ChatToolCall` objects (not sent to the AI provider):
|
|
226
|
+
|
|
227
|
+
- `foldEvent?: 'open' | 'close'` — set when this call is a fold lifecycle event
|
|
228
|
+
- `foldPath?: string[]` — breadcrumb path of active folds when the call was made
|
|
229
|
+
|
|
230
|
+
---
|
|
231
|
+
|
|
232
|
+
## 7. `ChatRole` has a new `'system-event'` value
|
|
233
|
+
|
|
234
|
+
If you have an exhaustive `switch` or conditional chain on `ChatRole`, add a case for `'system-event'`.
|
|
235
|
+
|
|
236
|
+
**Before**
|
|
237
|
+
|
|
238
|
+
```ts
|
|
239
|
+
switch (message.role) {
|
|
240
|
+
case 'user': ...
|
|
241
|
+
case 'assistant': ...
|
|
242
|
+
case 'system': ...
|
|
243
|
+
case 'tool': ...
|
|
244
|
+
}
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
**After**
|
|
248
|
+
|
|
249
|
+
```ts
|
|
250
|
+
switch (message.role) {
|
|
251
|
+
case 'user': ...
|
|
252
|
+
case 'assistant': ...
|
|
253
|
+
case 'system': ...
|
|
254
|
+
case 'tool': ...
|
|
255
|
+
case 'system-event': ...
|
|
256
|
+
}
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
---
|
|
260
|
+
|
|
261
|
+
## 8. `GeminiAIConfig.model` is now typed as `GeminiModelId`
|
|
262
|
+
|
|
263
|
+
The `model` field no longer accepts arbitrary strings. Only the values in `SUPPORTED_GEMINI_MODEL_IDS` are accepted at runtime and at compile time.
|
|
264
|
+
|
|
265
|
+
**Before**
|
|
266
|
+
|
|
267
|
+
```ts
|
|
268
|
+
const config: GeminiAIConfig = {
|
|
269
|
+
providerType: 'gemini',
|
|
270
|
+
model: 'gemini-2.0-flash', // was accepted as string
|
|
271
|
+
};
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
**After**
|
|
275
|
+
|
|
276
|
+
```ts
|
|
277
|
+
import { SUPPORTED_GEMINI_MODEL_IDS } from '@genesislcap/foundation-ai';
|
|
278
|
+
import type { GeminiAIConfig } from '@genesislcap/foundation-ai';
|
|
279
|
+
|
|
280
|
+
const config: GeminiAIConfig = {
|
|
281
|
+
providerType: 'gemini',
|
|
282
|
+
model: 'gemini-2.5-flash', // must be a GeminiModelId
|
|
283
|
+
};
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
Supported values: `'gemini-2.5-flash'` | `'gemini-2.5-flash-lite'`
|
|
287
|
+
|
|
288
|
+
If you were using `'gemini-2.0-flash'` or another deprecated model, migrate to `'gemini-2.5-flash'`.
|
|
289
|
+
|
|
290
|
+
---
|
|
291
|
+
|
|
292
|
+
## 9. `downloadHistory()` renamed to `getDebugLog()`
|
|
293
|
+
|
|
294
|
+
**Before**
|
|
295
|
+
|
|
296
|
+
```ts
|
|
297
|
+
assistant.downloadHistory();
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
**After**
|
|
301
|
+
|
|
302
|
+
```ts
|
|
303
|
+
assistant.getDebugLog();
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
---
|
|
307
|
+
|
|
308
|
+
## 10. `headerTitle` now defaults to `'Genesis Assistant'`
|
|
309
|
+
|
|
310
|
+
Previously `headerTitle` was `undefined` by default, so the header title area was empty unless explicitly set. It now defaults to `'Genesis Assistant'`.
|
|
311
|
+
|
|
312
|
+
If you were relying on the absence of a title (e.g. to hide a title element via CSS `:empty` or conditional rendering), set the attribute explicitly to an empty string or adjust your CSS.
|
|
313
|
+
|
|
314
|
+
**Before** — no attribute set, title area was empty.
|
|
315
|
+
|
|
316
|
+
**After** — set explicitly if you want a different value or no value:
|
|
317
|
+
|
|
318
|
+
```html
|
|
319
|
+
<!-- Custom title -->
|
|
320
|
+
<foundation-ai-assistant header-title="My Assistant"></foundation-ai-assistant>
|
|
321
|
+
|
|
322
|
+
<!-- No title -->
|
|
323
|
+
<foundation-ai-assistant header-title=""></foundation-ai-assistant>
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
---
|
|
327
|
+
|
|
328
|
+
## Quick reference checklist
|
|
329
|
+
|
|
330
|
+
- [ ] Move `ChatConfig` fields into `ui`, `agent`, and `suggestions` sub-objects
|
|
331
|
+
- [ ] Remove all imports of `AiAssistantSerializedState`
|
|
332
|
+
- [ ] Remove `chat-popin`/`chat-popout` state payload destructuring
|
|
333
|
+
- [ ] Remove calls to `applyState()` and `serializeState()`
|
|
334
|
+
- [ ] Update `ChatInteraction.resolved` checks from `=== true` to truthy
|
|
335
|
+
- [ ] Update `AgentConfig` arrays — add `fallback: true` to catch-all agents (remove `description` from them)
|
|
336
|
+
- [ ] Add `'system-event'` case to any exhaustive `ChatRole` switches
|
|
337
|
+
- [ ] Update `GeminiAIConfig.model` from `'gemini-2.0-flash'` to a supported `GeminiModelId`
|
|
338
|
+
- [ ] Rename `downloadHistory()` calls to `getDebugLog()`
|
|
339
|
+
- [ ] Audit `header-title` attribute usage if you relied on an empty default
|