@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.
Files changed (105) hide show
  1. package/dist/ai-assistant.api.json +4061 -1416
  2. package/dist/ai-assistant.d.ts +594 -81
  3. package/dist/dts/channel/ai-activity-channel.d.ts +4 -22
  4. package/dist/dts/channel/ai-activity-channel.d.ts.map +1 -1
  5. package/dist/dts/components/ai-driver/ai-driver.d.ts +52 -0
  6. package/dist/dts/components/ai-driver/ai-driver.d.ts.map +1 -0
  7. package/dist/dts/components/ai-driver/index.d.ts +2 -0
  8. package/dist/dts/components/ai-driver/index.d.ts.map +1 -0
  9. package/dist/dts/components/chat-driver/chat-driver.d.ts +63 -8
  10. package/dist/dts/components/chat-driver/chat-driver.d.ts.map +1 -1
  11. package/dist/dts/components/chat-interaction-wrapper/chat-interaction-wrapper.d.ts +3 -3
  12. package/dist/dts/components/chat-interaction-wrapper/chat-interaction-wrapper.d.ts.map +1 -1
  13. package/dist/dts/components/chat-markdown/chat-markdown.d.ts +1 -1
  14. package/dist/dts/components/chat-markdown/chat-markdown.d.ts.map +1 -1
  15. package/dist/dts/components/halo-overlay.d.ts +13 -1
  16. package/dist/dts/components/halo-overlay.d.ts.map +1 -1
  17. package/dist/dts/components/orchestrating-driver/index.d.ts +2 -0
  18. package/dist/dts/components/orchestrating-driver/index.d.ts.map +1 -0
  19. package/dist/dts/components/orchestrating-driver/orchestrating-driver.d.ts +39 -0
  20. package/dist/dts/components/orchestrating-driver/orchestrating-driver.d.ts.map +1 -0
  21. package/dist/dts/components/popout-manager/index.d.ts +2 -0
  22. package/dist/dts/components/popout-manager/index.d.ts.map +1 -0
  23. package/dist/dts/components/popout-manager/popout-manager.d.ts +72 -0
  24. package/dist/dts/components/popout-manager/popout-manager.d.ts.map +1 -0
  25. package/dist/dts/config/config.d.ts +43 -15
  26. package/dist/dts/config/config.d.ts.map +1 -1
  27. package/dist/dts/config/fallback-agents.d.ts +20 -0
  28. package/dist/dts/config/fallback-agents.d.ts.map +1 -0
  29. package/dist/dts/config/index.d.ts +1 -0
  30. package/dist/dts/config/index.d.ts.map +1 -1
  31. package/dist/dts/index.d.ts +6 -0
  32. package/dist/dts/index.d.ts.map +1 -1
  33. package/dist/dts/main/main.d.ts +122 -21
  34. package/dist/dts/main/main.d.ts.map +1 -1
  35. package/dist/dts/main/main.styles.d.ts.map +1 -1
  36. package/dist/dts/main/main.template.d.ts.map +1 -1
  37. package/dist/dts/main/main.types.d.ts +16 -0
  38. package/dist/dts/main/main.types.d.ts.map +1 -1
  39. package/dist/dts/state/ai-assistant-slice.d.ts +38 -0
  40. package/dist/dts/state/ai-assistant-slice.d.ts.map +1 -0
  41. package/dist/dts/state/driver-registry.d.ts +22 -0
  42. package/dist/dts/state/driver-registry.d.ts.map +1 -0
  43. package/dist/dts/state/session-store.d.ts +37 -0
  44. package/dist/dts/state/session-store.d.ts.map +1 -0
  45. package/dist/dts/suggestions/chat-suggestions.d.ts +7 -0
  46. package/dist/dts/suggestions/chat-suggestions.d.ts.map +1 -0
  47. package/dist/dts/types/ai-chat-widget.d.ts +3 -2
  48. package/dist/dts/types/ai-chat-widget.d.ts.map +1 -1
  49. package/dist/dts/utils/index.d.ts +1 -0
  50. package/dist/dts/utils/index.d.ts.map +1 -1
  51. package/dist/dts/utils/tool-fold.d.ts +133 -0
  52. package/dist/dts/utils/tool-fold.d.ts.map +1 -0
  53. package/dist/esm/components/ai-driver/ai-driver.js +1 -0
  54. package/dist/esm/components/ai-driver/index.js +1 -0
  55. package/dist/esm/components/chat-driver/chat-driver.js +499 -67
  56. package/dist/esm/components/chat-interaction-wrapper/chat-interaction-wrapper.js +2 -2
  57. package/dist/esm/components/chat-markdown/chat-markdown.js +1 -1
  58. package/dist/esm/components/halo-overlay.js +53 -7
  59. package/dist/esm/components/orchestrating-driver/index.js +1 -0
  60. package/dist/esm/components/orchestrating-driver/orchestrating-driver.js +247 -0
  61. package/dist/esm/components/popout-manager/index.js +1 -0
  62. package/dist/esm/components/popout-manager/popout-manager.js +126 -0
  63. package/dist/esm/config/fallback-agents.js +26 -0
  64. package/dist/esm/config/index.js +1 -0
  65. package/dist/esm/index.js +6 -0
  66. package/dist/esm/main/main.js +546 -112
  67. package/dist/esm/main/main.styles.js +200 -4
  68. package/dist/esm/main/main.template.js +163 -63
  69. package/dist/esm/state/ai-assistant-slice.js +54 -0
  70. package/dist/esm/state/driver-registry.js +46 -0
  71. package/dist/esm/state/session-store.js +39 -0
  72. package/dist/esm/suggestions/chat-suggestions.js +147 -0
  73. package/dist/esm/utils/index.js +1 -0
  74. package/dist/esm/utils/tool-fold.js +92 -0
  75. package/dist/tsconfig.tsbuildinfo +1 -1
  76. package/docs/migration-FUI-2495.md +339 -0
  77. package/docs/sub_agent.md +310 -0
  78. package/package.json +16 -15
  79. package/src/channel/ai-activity-channel.ts +4 -20
  80. package/src/components/ai-driver/ai-driver.ts +69 -0
  81. package/src/components/ai-driver/index.ts +1 -0
  82. package/src/components/chat-driver/chat-driver.ts +600 -73
  83. package/src/components/chat-interaction-wrapper/chat-interaction-wrapper.ts +3 -3
  84. package/src/components/chat-markdown/chat-markdown.ts +1 -1
  85. package/src/components/halo-overlay.ts +45 -7
  86. package/src/components/orchestrating-driver/index.ts +1 -0
  87. package/src/components/orchestrating-driver/orchestrating-driver.ts +328 -0
  88. package/src/components/popout-manager/index.ts +1 -0
  89. package/src/components/popout-manager/popout-manager.ts +147 -0
  90. package/src/config/config.ts +45 -15
  91. package/src/config/fallback-agents.ts +29 -0
  92. package/src/config/index.ts +1 -0
  93. package/src/index.ts +6 -0
  94. package/src/main/main.styles.ts +200 -4
  95. package/src/main/main.template.ts +200 -80
  96. package/src/main/main.ts +567 -94
  97. package/src/main/main.types.ts +11 -0
  98. package/src/state/ai-assistant-slice.ts +80 -0
  99. package/src/state/driver-registry.ts +51 -0
  100. package/src/state/session-store.ts +56 -0
  101. package/src/suggestions/chat-suggestions.ts +158 -0
  102. package/src/types/ai-chat-widget.ts +4 -2
  103. package/src/utils/index.ts +1 -0
  104. package/src/utils/tool-fold.ts +181 -0
  105. package/docs/multi-agent-architecture.md +0 -198
@@ -1,49 +1,23 @@
1
1
  import { AIProvider } from '@genesislcap/foundation-ai';
2
2
  import type { ChatAttachment } from '@genesislcap/foundation-ai';
3
3
  import type { ChatConfig } from '@genesislcap/foundation-ai';
4
+ import type { ChatDriverResult } from '@genesislcap/foundation-ai';
4
5
  import type { ChatMessage } from '@genesislcap/foundation-ai';
5
6
  import type { ChatToolDefinition } from '@genesislcap/foundation-ai';
6
7
  import type { ChatToolHandlers } from '@genesislcap/foundation-ai';
7
8
  import { GenesisElement } from '@genesislcap/web-core';
9
+ import type { InteractionResult } from '@genesislcap/foundation-ai';
8
10
  import { ViewTemplate } from '@genesislcap/web-core';
9
11
 
10
12
  /**
11
- * Configuration for a single specialist agent.
13
+ * Configuration for an agent passed to `FoundationAiAssistant`.
12
14
  *
13
- * When multiple agents are provided to `FoundationAiAssistant`, an orchestrating layer
14
- * will route each user message to the appropriate specialist based on intent. When only
15
- * one agent is configured, routing is skipped.
15
+ * Either a specialist (requires `description`) or a fallback (requires
16
+ * `fallback: true`). Passing both or neither is a compile error.
16
17
  *
17
18
  * @beta
18
19
  */
19
- export declare interface AgentConfig {
20
- /**
21
- * Display name shown in the chat header when this agent is active.
22
- */
23
- name: string;
24
- /**
25
- * Plain-language description of what this agent handles.
26
- * Used by the classifier to auto-generate its routing prompt.
27
- */
28
- description: string;
29
- /**
30
- * System prompt injected into every conversation turn for this agent.
31
- */
32
- systemPrompt?: string;
33
- /**
34
- * Tool definitions (JSON Schema) passed to the AI provider for this agent.
35
- */
36
- toolDefinitions?: ChatToolDefinition[];
37
- /**
38
- * Tool handler implementations for this agent.
39
- */
40
- toolHandlers?: ChatToolHandlers;
41
- /**
42
- * Optional primer history prepended to every call (not visible to the user).
43
- * Used to establish agent identity and behavioural rules.
44
- */
45
- primerHistory?: ChatMessage[];
46
- }
20
+ export declare type AgentConfig = SpecialistAgentConfig | FallbackAgentConfig;
47
21
 
48
22
  /**
49
23
  * Typed in-process event bus for AI assistant activity events.
@@ -144,14 +118,10 @@ export declare interface AgenticActivityEvents {
144
118
  };
145
119
  /** Fired when the assistant finishes all tool processing and returns to idle. */
146
120
  'halo-stop': undefined;
147
- /** Fired when the user clicks the expand button — moves assistant from bubble into layout. */
148
- 'chat-popout': {
149
- state: AiAssistantSerializedState;
150
- };
151
- /** Fired when the user clicks the collapse button — moves assistant from layout back to bubble. */
152
- 'chat-popin': {
153
- state: AiAssistantSerializedState;
154
- };
121
+ /** Fired when the user clicks the expand button — moves assistant from bubble into layout. State lives in the session store, not in this event. */
122
+ 'chat-popout': undefined;
123
+ /** Fired when the user clicks the collapse button — moves assistant from layout back to bubble. State lives in the session store, not in this event. */
124
+ 'chat-popin': undefined;
155
125
  }
156
126
 
157
127
  /**
@@ -173,19 +143,6 @@ export declare interface AiAssistantAnimationDef {
173
143
  tooltip: string;
174
144
  }
175
145
 
176
- /**
177
- * Serialized state of a `FoundationAiAssistant` instance.
178
- * All fields are JSON-serializable.
179
- *
180
- * @beta
181
- */
182
- export declare interface AiAssistantSerializedState {
183
- messages: ChatMessage[];
184
- showToolCalls: boolean;
185
- showThinkingSteps: boolean;
186
- enabledAnimations: AiAssistantAnimation[];
187
- }
188
-
189
146
  /**
190
147
  * State of the AI assistant component.
191
148
  *
@@ -193,6 +150,13 @@ export declare interface AiAssistantSerializedState {
193
150
  */
194
151
  export declare type AiAssistantState = 'idle' | 'loading' | 'error';
195
152
 
153
+ export declare class AiChatMarkdown extends GenesisElement {
154
+ /** The markdown string to render. */
155
+ content: string;
156
+ /** @internal */
157
+ renderMarkdown(): string;
158
+ }
159
+
196
160
  /**
197
161
  * Interface that AI inline interaction components can implement.
198
162
  * The `AiChatInteractionWrapper` always sets `data` and `resolved` on the rendered element.
@@ -201,8 +165,76 @@ export declare type AiAssistantState = 'idle' | 'loading' | 'error';
201
165
  */
202
166
  export declare interface AiChatWidget {
203
167
  data: unknown;
204
- /** When true, the interaction has already been resolved. Components should render read-only. */
205
- resolved?: boolean;
168
+ /** The result when the interaction has been resolved. Truthy = resolved; value contains status/payload for display. */
169
+ resolved?: InteractionResult<unknown>;
170
+ }
171
+
172
+ /**
173
+ * Contract for pages that support docking the AI assistant.
174
+ * Register an implementation with {@link getAiPopoutManager} on mount and deregister on unmount.
175
+ *
176
+ * @beta
177
+ */
178
+ export declare interface AiDockProvider {
179
+ /**
180
+ * Called when the user expands the bubble. The provider is responsible for inserting
181
+ * the element into its layout. State is held in the session store and restored
182
+ * automatically when the element connects.
183
+ */
184
+ onDock(element: HTMLElement): Promise<void>;
185
+ /** Called when the user collapses the panel or before navigation. */
186
+ onUndock(): Promise<void>;
187
+ /**
188
+ * Called by `collapseIfDocked` before navigation. The provider is responsible for
189
+ * finding the docked assistant element and calling `handlePopout()` on it, which
190
+ * publishes `chat-popin` and returns the assistant to the bubble.
191
+ */
192
+ initiateCollapse(): void;
193
+ }
194
+
195
+ /**
196
+ * Common interface implemented by both `ChatDriver` (single-agent) and
197
+ * `OrchestratingDriver` (multi-agent). `FoundationAiAssistant` depends only
198
+ * on this interface — the concrete class is chosen at startup based on how
199
+ * many agents are configured.
200
+ *
201
+ * Extends `EventTarget` so consumers can subscribe to `history-updated` events
202
+ * without knowing the concrete implementation.
203
+ *
204
+ * @beta
205
+ */
206
+ export declare interface AiDriver extends EventTarget {
207
+ /**
208
+ * Send a user message and run the tool loop to completion.
209
+ */
210
+ sendMessage(input: string, attachments?: ChatAttachment[]): Promise<ChatDriverResult>;
211
+ /**
212
+ * Continue the tool loop from the current history without appending a new
213
+ * user message. Used by `OrchestratingDriver` on agent handoffs — the
214
+ * handoff context is already in history; `transientPrimer` is injected as
215
+ * an invisible one-shot message for this call only.
216
+ */
217
+ continueFromHistory(transientPrimer?: ChatMessage[]): Promise<ChatDriverResult>;
218
+ /**
219
+ * Resolve a pending blocking interaction with the given result.
220
+ */
221
+ resolveInteraction(interactionId: string, result: unknown): void;
222
+ /**
223
+ * Seed the driver's message history (called on state restore / pop-in).
224
+ */
225
+ loadHistory(messages: ChatMessage[]): void;
226
+ /**
227
+ * Return the full, unredacted conversation history.
228
+ */
229
+ getRawHistory?(): readonly ChatMessage[];
230
+ /**
231
+ * Returns true if the driver is currently processing a request.
232
+ */
233
+ isBusy(): boolean;
234
+ /**
235
+ * Get query suggestions from the AI.
236
+ */
237
+ getSuggestions(history: ChatMessage[], prompt: string, count: number, allAgentInfo?: AllAgentSummary[]): Promise<string[]>;
206
238
  }
207
239
 
208
240
  /**
@@ -212,6 +244,13 @@ export declare interface AiChatWidget {
212
244
  */
213
245
  export declare const ALL_ANIMATIONS: AiAssistantAnimation[];
214
246
 
247
+ /** @internal */
248
+ declare interface AllAgentSummary {
249
+ name: string;
250
+ description: string;
251
+ tools: ChatToolDefinition[];
252
+ }
253
+
215
254
  /**
216
255
  * Registry of all available animations with their display metadata.
217
256
  * Adding an entry here automatically extends the {@link AiAssistantAnimation} type.
@@ -229,6 +268,30 @@ export declare const ANIMATION_DEFS: {
229
268
  };
230
269
  };
231
270
 
271
+ declare interface BaseAgentConfig {
272
+ /**
273
+ * Display name shown in the chat header when this agent is active.
274
+ */
275
+ name: string;
276
+ /**
277
+ * System prompt injected into every conversation turn for this agent.
278
+ */
279
+ systemPrompt?: string;
280
+ /**
281
+ * Tool definitions (JSON Schema) passed to the AI provider for this agent.
282
+ */
283
+ toolDefinitions?: ChatToolDefinition[];
284
+ /**
285
+ * Tool handler implementations for this agent.
286
+ */
287
+ toolHandlers?: ChatToolHandlers;
288
+ /**
289
+ * Optional primer history prepended to every call (not visible to the user).
290
+ * Used to establish agent identity and behavioural rules.
291
+ */
292
+ primerHistory?: ChatMessage[];
293
+ }
294
+
232
295
  /**
233
296
  * Plain TS class that drives a multi-turn chat conversation, including the tool-call loop.
234
297
  * Owned by `FoundationAiAssistant` — created in `connectedCallback`, torn down in `disconnectedCallback`.
@@ -239,18 +302,45 @@ export declare const ANIMATION_DEFS: {
239
302
  *
240
303
  * @beta
241
304
  */
242
- export declare class ChatDriver extends EventTarget {
305
+ export declare class ChatDriver extends EventTarget implements AiDriver {
243
306
  private readonly aiProvider;
244
- private readonly toolHandlers;
245
- private readonly toolDefinitions;
246
- private readonly systemPrompt?;
247
- private readonly primerHistory?;
248
307
  private readonly maxToolIterations;
249
308
  private history;
250
309
  private busy;
251
310
  private pendingInteractions;
252
- constructor(aiProvider: AIProvider, toolHandlers?: ChatToolHandlers, toolDefinitions?: ChatToolDefinition[], systemPrompt?: string, primerHistory?: ChatMessage[], maxToolIterations?: number);
311
+ private systemPrompt?;
312
+ private toolDefinitions;
313
+ private toolHandlers;
314
+ private primerHistory?;
315
+ private activeAgentName?;
316
+ /**
317
+ * When set (e.g. by OrchestratingDriver), applied only to the conversation slice
318
+ * sent to the model — stored `history` stays unchanged for UI and logging.
319
+ */
320
+ private providerHistoryTransform?;
321
+ /** Stack of fold frames — grows when a fold opens, shrinks when it closes. */
322
+ private foldStack;
323
+ /** Consecutive fold open/close ops without a real tool call. Reset on real tool execution. */
324
+ private consecutiveFoldOps;
325
+ /** Consecutive unknown-tool calls without a real tool call. Reset on real tool execution. */
326
+ private consecutiveUnknownToolCalls;
327
+ private readonly maxFoldOperations;
328
+ constructor(aiProvider: AIProvider, toolHandlers?: ChatToolHandlers, toolDefinitions?: ChatToolDefinition[], systemPrompt?: string, primerHistory?: ChatMessage[], maxToolIterations?: number, maxFoldOperations?: number);
329
+ /**
330
+ * Swap in a new agent's configuration. Called by OrchestratingDriver before
331
+ * each specialist turn so the shared driver runs with the right tools and prompt.
332
+ */
333
+ applyAgent(config: AgentConfig): void;
334
+ /**
335
+ * Optional transform applied to conversation history immediately before each LLM request.
336
+ * Cleared when `undefined`. Does not alter stored history.
337
+ */
338
+ setProviderHistoryTransform(transform?: (history: ChatMessage[]) => ChatMessage[]): void;
253
339
  getHistory(): ReadonlyArray<ChatMessage>;
340
+ getRawHistory(): readonly ChatMessage[];
341
+ /** Returns the current fold stack names for debugging. */
342
+ getActiveFoldNames(): string[];
343
+ getSuggestions(history: ChatMessage[], prompt: string, count: number, allAgentInfo?: AllAgentSummary[]): Promise<string[]>;
254
344
  isBusy(): boolean;
255
345
  /**
256
346
  * Request a custom UI interaction. Emits a new message with the interaction.
@@ -270,7 +360,31 @@ export declare class ChatDriver extends EventTarget {
270
360
  * can continue an existing conversation. Call this before the first user message.
271
361
  */
272
362
  loadHistory(messages: ChatMessage[]): void;
273
- sendMessage(userInput: string, attachments?: ChatAttachment[]): Promise<void>;
363
+ sendMessage(userInput: string, attachments?: ChatAttachment[]): Promise<ChatDriverResult>;
364
+ /**
365
+ * Continue the tool loop from current history without appending a new user message.
366
+ * Used by OrchestratingDriver after an agent handoff.
367
+ */
368
+ continueFromHistory(transientPrimer?: ChatMessage[]): Promise<ChatDriverResult>;
369
+ /** Extract ToolFold metadata from a handler, or undefined if it isn't a fold facade. */
370
+ private getFold;
371
+ /**
372
+ * Search all currently registered fold facades (and their nested folds recursively)
373
+ * to find which fold contains a given tool name. Returns the immediate parent fold name.
374
+ */
375
+ private findFoldContaining;
376
+ /**
377
+ * Install the fold's inner tool set, replacing (exclusive) or extending (non-exclusive)
378
+ * the current tool set. Also injects the close tool. Does NOT touch the fold stack.
379
+ */
380
+ private applyFoldToolSet;
381
+ /** Open a fold: push a stack frame, swap the tool set, return the response message. */
382
+ private openFold;
383
+ private pushFoldFrame;
384
+ /** Close the top fold: pop the stack frame, restore the previous tool set. */
385
+ private closeFold;
386
+ /** Build the fold-awareness suffix appended to the system prompt each LLM call. */
387
+ private buildFoldSystemPromptSuffix;
274
388
  private runToolLoop;
275
389
  private appendToHistory;
276
390
  }
@@ -282,12 +396,103 @@ export declare class ChatDriver extends EventTarget {
282
396
  */
283
397
  export declare type ChatHistoryUpdatedEvent = CustomEvent<ReadonlyArray<ChatMessage>>;
284
398
 
399
+ /**
400
+ * Creates a tool fold — a facade that hides a group of related tools behind a single
401
+ * named entry, revealing them progressively when the model invokes the facade.
402
+ *
403
+ * The `tools` and `handlers` parameters accept the exact same types as `AgentConfig.toolDefinitions`
404
+ * and `AgentConfig.toolHandlers`, so existing tool creation functions can be passed in unchanged.
405
+ *
406
+ * @example
407
+ * ```typescript
408
+ * const tradingTools = createToolFold({
409
+ * name: 'trading_tools',
410
+ * tools: createTradesToolDefinitions(),
411
+ * handlers: createTradesToolHandlers(connect),
412
+ * });
413
+ *
414
+ * const agent: AgentConfig = {
415
+ * name: 'Trades',
416
+ * systemPrompt: '...',
417
+ * toolDefinitions: [getCurrentDateDef, tradingTools.definition],
418
+ * toolHandlers: { get_current_date: handler, ...tradingTools.handler },
419
+ * };
420
+ * ```
421
+ *
422
+ * @example Nesting folds
423
+ * ```typescript
424
+ * const insertFold = createToolFold({
425
+ * name: 'trade_insertion',
426
+ * tools: [validateDef, insertDef],
427
+ * handlers: { validate_trade: vHandler, insert_trade: iHandler },
428
+ * });
429
+ *
430
+ * const tradingFold = createToolFold({
431
+ * name: 'trading_tools',
432
+ * tools: [searchDef, insertFold.definition],
433
+ * handlers: { search_trades: sHandler, ...insertFold.handler },
434
+ * });
435
+ * ```
436
+ *
437
+ * @beta
438
+ */
439
+ export declare function createToolFold(config: {
440
+ /** Facade tool name — used as the tool name the model calls to open this fold. */
441
+ name: string;
442
+ /**
443
+ * Description shown to the model for the facade tool.
444
+ * If omitted, auto-generated from the inner tool names:
445
+ * "Contains: tool_a, tool_b. Invoke to access these tools."
446
+ */
447
+ description?: string;
448
+ /**
449
+ * Optional usage guidance injected into the fold-open response message.
450
+ * Not included in the facade description — only visible once the fold is open.
451
+ */
452
+ usageNotes?: string;
453
+ /** Inner tool definitions. Same type as `AgentConfig.toolDefinitions`. */
454
+ tools: ChatToolDefinition[];
455
+ /** Inner tool handlers. Same type as `AgentConfig.toolHandlers`. */
456
+ handlers: ChatToolHandlers;
457
+ /**
458
+ * When true (default), all other tools are removed when this fold opens.
459
+ * When false, sibling tools remain available alongside the inner tools.
460
+ */
461
+ exclusive?: boolean;
462
+ }): ToolFoldResult;
463
+
464
+ /**
465
+ * Expands a flat list of tool definitions into a nested tree by resolving fold
466
+ * metadata from the corresponding handlers. Use this for debug output so the
467
+ * full tool hierarchy is visible rather than just the top-level facade names.
468
+ *
469
+ * @beta
470
+ */
471
+ export declare function expandToolTree(definitions: ChatToolDefinition[], handlers: ChatToolHandlers): ToolTreeNode[];
472
+
473
+ /**
474
+ * Configuration for a fallback agent.
475
+ *
476
+ * Invoked when the classifier returns no match. Excluded from the classifier
477
+ * prompt. Only one fallback is permitted per agents array.
478
+ *
479
+ * @beta
480
+ */
481
+ export declare interface FallbackAgentConfig extends BaseAgentConfig {
482
+ /**
483
+ * Marks this agent as the fallback for unrecognised requests.
484
+ */
485
+ fallback: true;
486
+ description?: never;
487
+ }
488
+
285
489
  /**
286
490
  * Foundation AI Assistant component.
287
491
  *
288
492
  * @remarks
289
493
  * Inject an `AIProvider` through the DI container. Pass agent configuration via the `agents`
290
- * property. The component creates a `ChatDriver` to manage the conversation loop.
494
+ * property. The component creates a `ChatDriver` (single agent) or `OrchestratingDriver`
495
+ * (multiple agents) to manage the conversation loop.
291
496
  *
292
497
  * Popout/collapse coordination uses `agenticActivityBus` topics `chat-popout` and `chat-popin` — not DOM `CustomEvent`s on this element.
293
498
  *
@@ -298,7 +503,7 @@ export declare type ChatHistoryUpdatedEvent = CustomEvent<ReadonlyArray<ChatMess
298
503
  export declare class FoundationAiAssistant extends GenesisElement {
299
504
  aiProvider: AIProvider;
300
505
  designSystemPrefix: string;
301
- headerTitle?: string;
506
+ headerTitle: string;
302
507
  imageSrc?: string;
303
508
  placeholder: string;
304
509
  /**
@@ -315,30 +520,67 @@ export declare class FoundationAiAssistant extends GenesisElement {
315
520
  agents?: AgentConfig[];
316
521
  chatConfig: ChatConfig;
317
522
  debugStateFactory?: () => unknown;
318
- messages: ChatMessage[];
319
- state: AiAssistantState;
320
- inputValue: string;
321
- attachments: ChatAttachment[];
322
- attachmentErrors: string[];
523
+ /** When set, enables Redux DevTools for this instance's session store. */
524
+ debugRedux: boolean;
525
+ private _sessionRef?;
526
+ get messages(): ChatMessage[];
527
+ set messages(value: ChatMessage[]);
528
+ get state(): AiAssistantState;
529
+ set state(value: AiAssistantState);
530
+ get activeAgent(): Omit<AgentConfig, 'toolHandlers'> | undefined;
531
+ set activeAgent(value: AgentConfig | undefined);
532
+ get suggestionsState(): SuggestionsState;
533
+ set suggestionsState(value: SuggestionsState);
323
534
  /** Current user-facing toggle state for tool call visibility. */
324
- showToolCalls: boolean;
535
+ get showToolCalls(): boolean;
536
+ set showToolCalls(value: boolean);
325
537
  /** Current user-facing toggle state for thinking step visibility. */
326
- showThinkingSteps: boolean;
538
+ get showThinkingSteps(): boolean;
539
+ set showThinkingSteps(value: boolean);
540
+ /** Current user-facing toggle state for agent switch indicator visibility. */
541
+ get showAgentSwitchIndicator(): boolean;
542
+ set showAgentSwitchIndicator(value: boolean);
327
543
  /** Currently enabled animations. */
328
- enabledAnimations: AiAssistantAnimation[];
544
+ get enabledAnimations(): AiAssistantAnimation[];
545
+ set enabledAnimations(value: AiAssistantAnimation[]);
546
+ /** Most recent prompt token count from the AI provider, if available. */
547
+ get contextTokens(): number | undefined;
548
+ set contextTokens(value: number | undefined);
549
+ /** Context window size for the active model, if known. */
550
+ get contextLimit(): number | undefined;
551
+ set contextLimit(value: number | undefined);
552
+ private _suggestionsGeneration;
553
+ get inputValue(): string;
554
+ set inputValue(value: string);
555
+ attachments: ChatAttachment[];
556
+ attachmentErrors: string[];
329
557
  /** Whether the loading spinner is currently visible. Controlled by the loading delay timer. */
330
558
  showLoadingIndicator: boolean;
331
559
  /** Whether the settings panel is open. */
332
560
  settingsOpen: boolean;
561
+ /** Whether the splash overlay is currently showing (no messages and showSplash is enabled). Reflected as a boolean attribute on the host. */
562
+ showingSplash: boolean;
333
563
  private driver?;
564
+ private driverCleanup?;
334
565
  private loadingTimer;
335
566
  private unsubBus?;
336
567
  private haloStartPublished;
568
+ /** Fingerprint of the agents array used to build the current driver. Used by agentsChanged to skip spurious rebuilds. */
569
+ private _driverAgentsKey?;
570
+ /** Bound to the messages container via the template ref — assigned by FAST before connectedCallback logic runs. */
571
+ messagesEl?: HTMLElement;
572
+ /** True when the user has intentionally scrolled away from the bottom — suppresses auto-scroll. */
573
+ private _userScrolledAway;
574
+ private _scrollListener?;
575
+ private static readonly SCROLL_BOTTOM_THRESHOLD_PX;
337
576
  /**
338
- * Whether the halo animation should be shown.
339
- * True when the AI is actively computing (loading state, no pending interaction).
577
+ * Unsubscribes a one-shot state subscription created when this element connects
578
+ * mid-execution. The subscription watches for `state` becoming 'idle' so that
579
+ * this element can stop its loading timer and sync the halo even when the
580
+ * originating `send()` ran on a different element instance.
340
581
  */
341
- showHalo: boolean;
582
+ private _executionCompletionUnsub?;
583
+ showHalo: 'no' | 'orchestrating' | 'agent';
342
584
  private syncShowHalo;
343
585
  /** True when there is a pending (unresolved) interaction — disables the popout button. */
344
586
  get hasActivePendingInteraction(): boolean;
@@ -348,29 +590,91 @@ export declare class FoundationAiAssistant extends GenesisElement {
348
590
  * Messages filtered by the current toggle state.
349
591
  * Tool-related messages (those with toolCalls or toolResult) are hidden when
350
592
  * `showToolCalls` is false.
593
+ *
594
+ * Marked `@volatile` because the filter branches conditionally access
595
+ * `showToolCalls`, `showThinkingSteps`, and `showAgentSwitchIndicator`
596
+ * depending on message content. Without it, FAST would only track the
597
+ * observables accessed on the last evaluation and miss toggle changes that
598
+ * happen to hit an untracked branch.
351
599
  */
352
600
  get visibleMessages(): ChatMessage[];
601
+ agentsChanged(): void;
602
+ /** Returns a stable fingerprint for an agents array based on agent names and tool handler keys. */
603
+ private getAgentsKey;
604
+ /**
605
+ * Pure factory — creates a ChatDriver or OrchestratingDriver based on the
606
+ * current agent configuration. Does not wire event listeners or register in
607
+ * the driver registry.
608
+ */
609
+ private createDriver;
610
+ /**
611
+ * Attaches event listeners to the current driver. Stores a cleanup function
612
+ * so `unwireDriver` can remove them precisely. Safe to call multiple
613
+ * times — unwires any existing listeners first.
614
+ */
615
+ private wireDriver;
616
+ /**
617
+ * Removes event listeners attached by `wireDriver`. Does not destroy
618
+ * the driver or remove it from the registry.
619
+ */
620
+ private unwireDriver;
353
621
  connectedCallback(): void;
354
622
  disconnectedCallback(): void;
355
- stateChanged(): void;
356
- messagesChanged(): void;
623
+ private resolveContextLimit;
624
+ chatConfigChanged(): void;
625
+ showingSplashChanged(): void;
626
+ private syncShowingSplash;
627
+ /**
628
+ * Runs side effects that were previously in `messagesChanged()`.
629
+ * Called from the `messages` setter after dispatching to the store.
630
+ */
631
+ private handleMessagesUpdate;
357
632
  showLoadingIndicatorChanged(): void;
358
633
  private scrollToBottom;
359
634
  private static readonly DEFAULT_LOADING_DELAY_S;
635
+ private static readonly DEFAULT_SUGGESTION_COUNT;
360
636
  private static readonly MS_PER_SECOND;
361
637
  private startLoadingTimer;
362
638
  private clearLoadingTimer;
363
639
  private stopLoadingTimer;
364
640
  /** Called when the user clicks the popout button. */
365
641
  handlePopout(): void;
366
- /** Applies a serialized state snapshot to this live instance (used on collapse path). */
367
- applyState(state: AiAssistantSerializedState): void;
368
- private serializeState;
642
+ /** Returns a cache key for this instance, or undefined if the component has no identity. */
643
+ private getStateKey;
369
644
  toggleSettings(): void;
370
645
  toggleShowToolCalls(): void;
371
646
  toggleShowThinkingSteps(): void;
647
+ toggleShowAgentSwitchIndicator(): void;
372
648
  setEnabledAnimations(animations: AiAssistantAnimation[]): void;
373
- downloadHistory(): void;
649
+ getDebugLog(): {
650
+ messages: readonly ChatMessage[];
651
+ meta: {
652
+ timestamp: string;
653
+ host: string;
654
+ agentSummary: ({
655
+ toolDefinitions: ToolTreeNode[];
656
+ toolHandlers: any;
657
+ description: string;
658
+ fallback?: never;
659
+ name: string;
660
+ systemPrompt?: string;
661
+ primerHistory?: ChatMessage[];
662
+ } | {
663
+ toolDefinitions: ToolTreeNode[];
664
+ toolHandlers: any;
665
+ fallback: true;
666
+ description?: never;
667
+ name: string;
668
+ systemPrompt?: string;
669
+ primerHistory?: ChatMessage[];
670
+ })[];
671
+ activeSystemPrompt: string;
672
+ activePrimerHistory: ChatMessage[];
673
+ activeFoldStack: string[];
674
+ debug: unknown;
675
+ };
676
+ };
677
+ downloadDebugLog(): void;
374
678
  triggerFileInput(): void;
375
679
  handleFileSelect(e: Event): void;
376
680
  removeAttachment(attachment: ChatAttachment): void;
@@ -379,6 +683,8 @@ export declare class FoundationAiAssistant extends GenesisElement {
379
683
  private readFileAsText;
380
684
  private loadSelectedFiles;
381
685
  handleSendClick(): void;
686
+ handleSuggestionClick(suggestion: string): void;
687
+ private fetchSuggestions;
382
688
  private send;
383
689
  private restoreFocusIfAppropriate;
384
690
  onChatHeaderMouseDown(e: MouseEvent): void;
@@ -388,6 +694,103 @@ export declare class FoundationAiAssistant extends GenesisElement {
388
694
  /** @internal */
389
695
  export declare const FoundationAiAssistantTemplate: (designSystemPrefix: string) => ViewTemplate<FoundationAiAssistant>;
390
696
 
697
+ /**
698
+ * App-shell component that owns the pop-out/pop-in lifecycle for the AI assistant bubble.
699
+ *
700
+ * @remarks
701
+ * Place this in the persistent app shell, wrapping a `foundation-ai-chat-bubble` that
702
+ * contains an AI assistant element in the `dialog-content` slot. The component will
703
+ * auto-create a matching collapse-mode element for docking into pages, and will
704
+ * control the expand button visibility based on whether a dock provider is registered.
705
+ *
706
+ * Pages that support docking call `aiPopoutManager.registerDockProvider()` on mount
707
+ * and `aiPopoutManager.deregisterDockProvider()` on unmount.
708
+ *
709
+ * @example
710
+ * ```html
711
+ * <foundation-ai-popout-manager>
712
+ * <foundation-ai-chat-bubble title="My Assistant">
713
+ * <my-assistant slot="dialog-content"></my-assistant>
714
+ * </foundation-ai-chat-bubble>
715
+ * </foundation-ai-popout-manager>
716
+ * ```
717
+ *
718
+ * @beta
719
+ */
720
+ export declare class FoundationAiPopoutManager extends GenesisElement {
721
+ /** True when a dock provider is registered — controls expand button visibility. */
722
+ canDock: boolean;
723
+ private collapseEl;
724
+ private dockProvider;
725
+ private isDocked;
726
+ private unsubBus?;
727
+ connectedCallback(): void;
728
+ disconnectedCallback(): void;
729
+ canDockChanged(): void;
730
+ registerDockProvider(provider: AiDockProvider): void;
731
+ deregisterDockProvider(): void;
732
+ /**
733
+ * If the assistant is currently docked, collapses it back into the bubble.
734
+ * Await this in `onBeforeNavButtonClick` to ensure cleanup before navigation.
735
+ */
736
+ collapseIfDocked(): Promise<void>;
737
+ }
738
+
739
+ /**
740
+ * A warm, conversational fallback agent. Acknowledges it can't help directly,
741
+ * explains what the available specialists can do, and invites the user to retry.
742
+ *
743
+ * The system prompt is generated at runtime by `OrchestratingDriver` from the
744
+ * specialist list — no manual authoring required.
745
+ *
746
+ * @beta
747
+ */
748
+ export declare const friendlyFallbackAgent: FallbackAgentConfig;
749
+
750
+ /**
751
+ * Returns the active `FoundationAiPopoutManager` instance, or `undefined` if none is mounted.
752
+ * Import this in pages to call `registerDockProvider` / `deregisterDockProvider`.
753
+ *
754
+ * @beta
755
+ */
756
+ export declare function getAiPopoutManager(): FoundationAiPopoutManager | undefined;
757
+
758
+ /**
759
+ * Orchestrates multiple specialist agents. Sits between `FoundationAiAssistant`
760
+ * and `ChatDriver`, classifying each user message and routing it to the right
761
+ * specialist — each with its own focused system prompt, tools, and primer.
762
+ *
763
+ * @beta
764
+ */
765
+ export declare class OrchestratingDriver extends EventTarget implements AiDriver {
766
+ private readonly aiProvider;
767
+ private readonly agents;
768
+ private readonly chatDriver;
769
+ private readonly specialists;
770
+ private readonly fallback?;
771
+ private readonly maxHandoffs;
772
+ private readonly classifierHistoryLength;
773
+ private readonly classifierRetries;
774
+ activeAgent?: AgentConfig;
775
+ constructor(aiProvider: AIProvider, agents: AgentConfig[], options?: {
776
+ maxHandoffs?: number;
777
+ classifierHistoryLength?: number;
778
+ classifierRetries?: number;
779
+ maxToolIterations?: number;
780
+ maxFoldOperations?: number;
781
+ });
782
+ resolveInteraction(interactionId: string, result: unknown): void;
783
+ isBusy(): boolean;
784
+ loadHistory(messages: ChatMessage[]): void;
785
+ getRawHistory(): readonly ChatMessage[];
786
+ getSuggestions(history: ChatMessage[], prompt: string, count: number, allAgentInfo?: AllAgentSummary[]): Promise<string[]>;
787
+ sendMessage(input: string, attachments?: ChatAttachment[]): Promise<ChatDriverResult>;
788
+ continueFromHistory(transientPrimer?: ChatMessage[]): Promise<ChatDriverResult>;
789
+ private applyAgent;
790
+ private classify;
791
+ private appendInlineMessage;
792
+ }
793
+
391
794
  /**
392
795
  * Controls the pop-out button shown in the assistant header.
393
796
  * - `"expand"` — assistant is embedded in the bubble dialog; button expands it to a layout panel.
@@ -397,4 +800,114 @@ export declare const FoundationAiAssistantTemplate: (designSystemPrefix: string)
397
800
  */
398
801
  export declare type PopoutMode = 'expand' | 'collapse';
399
802
 
803
+ /** Name reserved for the cross-agent handoff tool — injected by OrchestratingDriver. */
804
+ export declare const REQUEST_CONTINUATION_TOOL = "request_continuation";
805
+
806
+ /**
807
+ * Configuration for a specialist agent.
808
+ *
809
+ * Specialist agents are offered to the classifier for intent routing. The
810
+ * `description` is used to auto-generate the classifier prompt — no manual
811
+ * routing prompt authoring required.
812
+ *
813
+ * @beta
814
+ */
815
+ export declare interface SpecialistAgentConfig extends BaseAgentConfig {
816
+ /**
817
+ * Plain-language description of what this agent handles.
818
+ * Used by the classifier to auto-generate its routing prompt.
819
+ */
820
+ description: string;
821
+ fallback?: never;
822
+ }
823
+
824
+ /**
825
+ * A brief, professional fallback agent. States what is available without
826
+ * elaboration. The `{{agents}}` placeholder is replaced at runtime by
827
+ * `OrchestratingDriver` with the generated specialist list.
828
+ *
829
+ * @beta
830
+ */
831
+ export declare const strictFallbackAgent: FallbackAgentConfig;
832
+
833
+ /**
834
+ * State of the chat suggestions feature.
835
+ *
836
+ * @beta
837
+ */
838
+ export declare type SuggestionsState = {
839
+ status: 'idle';
840
+ } | {
841
+ status: 'loading';
842
+ } | {
843
+ status: 'loaded';
844
+ suggestions: string[];
845
+ } | {
846
+ status: 'error';
847
+ message: string;
848
+ };
849
+
850
+ /**
851
+ * Symbol used to attach ToolFold metadata to a facade handler function.
852
+ * The ChatDriver inspects this to detect fold facades at runtime.
853
+ *
854
+ * @internal
855
+ */
856
+ export declare const TOOL_FOLD_SYMBOL: unique symbol;
857
+
858
+ /**
859
+ * Internal metadata for a tool fold. Attached to the facade handler via TOOL_FOLD_SYMBOL.
860
+ *
861
+ * @internal
862
+ */
863
+ export declare interface ToolFold {
864
+ /** Facade tool name. */
865
+ name: string;
866
+ /** Description shown to the model. */
867
+ description: string;
868
+ /** Optional guidance injected in the fold-open response. */
869
+ usageNotes?: string;
870
+ /** Tool definitions inside this fold. */
871
+ tools: ChatToolDefinition[];
872
+ /** Handlers for the inner tools (keyed by tool name). */
873
+ handlers: ChatToolHandlers;
874
+ /**
875
+ * When true (default), all other tools are removed when this fold opens —
876
+ * the model can only see this fold's tools until it closes.
877
+ * When false, sibling tools remain alongside the inner tools.
878
+ */
879
+ exclusive: boolean;
880
+ }
881
+
882
+ /**
883
+ * The value returned by `createToolFold`.
884
+ *
885
+ * @beta
886
+ */
887
+ export declare interface ToolFoldResult {
888
+ /**
889
+ * The facade tool definition. Add this to your agent's `toolDefinitions`.
890
+ * It is a regular `ChatToolDefinition` with an empty parameter schema.
891
+ */
892
+ definition: ChatToolDefinition;
893
+ /**
894
+ * The facade handler — a single-entry map keyed by the fold name.
895
+ * Spread this into your agent's `toolHandlers`.
896
+ * Inner tool handlers are NOT included here — they are encapsulated inside
897
+ * the fold metadata and installed by the driver only when the fold opens.
898
+ */
899
+ handler: ChatToolHandlers;
900
+ }
901
+
902
+ /**
903
+ * A tool entry in the expanded debug tree.
904
+ * Folds are represented as nodes with a `tools` array; regular tools have none.
905
+ *
906
+ * @beta
907
+ */
908
+ export declare interface ToolTreeNode extends ChatToolDefinition {
909
+ /** Present when this tool is a fold — contains its inner tools recursively expanded. */
910
+ tools?: ToolTreeNode[];
911
+ }
912
+
400
913
  export { }