@genesislcap/ai-assistant 15.58.2 → 15.60.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.
Files changed (79) hide show
  1. package/dist/ai-assistant.api.json +10096 -6986
  2. package/dist/ai-assistant.d.ts +562 -101
  3. package/dist/chat-driver.cjs +624 -207
  4. package/dist/chat-driver.cjs.map +4 -4
  5. package/dist/chat-driver.mjs +624 -207
  6. package/dist/chat-driver.mjs.map +4 -4
  7. package/dist/custom-elements.json +5426 -3570
  8. package/dist/dts/components/agent-session/agent-session.d.ts +19 -3
  9. package/dist/dts/components/agent-session/agent-session.d.ts.map +1 -1
  10. package/dist/dts/components/ai-driver/ai-driver.d.ts +120 -10
  11. package/dist/dts/components/ai-driver/ai-driver.d.ts.map +1 -1
  12. package/dist/dts/components/ai-driver/base-driver-decorator.d.ts +103 -0
  13. package/dist/dts/components/ai-driver/base-driver-decorator.d.ts.map +1 -0
  14. package/dist/dts/components/ai-driver/index.d.ts +3 -1
  15. package/dist/dts/components/ai-driver/index.d.ts.map +1 -1
  16. package/dist/dts/components/chat-driver/chat-driver.d.ts +84 -8
  17. package/dist/dts/components/chat-driver/chat-driver.d.ts.map +1 -1
  18. package/dist/dts/components/chat-driver/interaction-controller.d.ts +37 -3
  19. package/dist/dts/components/chat-driver/interaction-controller.d.ts.map +1 -1
  20. package/dist/dts/components/message-feedback/index.d.ts +2 -0
  21. package/dist/dts/components/message-feedback/index.d.ts.map +1 -0
  22. package/dist/dts/components/message-feedback/message-feedback.d.ts +61 -0
  23. package/dist/dts/components/message-feedback/message-feedback.d.ts.map +1 -0
  24. package/dist/dts/components/message-feedback/message-feedback.styles.d.ts +2 -0
  25. package/dist/dts/components/message-feedback/message-feedback.styles.d.ts.map +1 -0
  26. package/dist/dts/components/message-feedback/message-feedback.template.d.ts +4 -0
  27. package/dist/dts/components/message-feedback/message-feedback.template.d.ts.map +1 -0
  28. package/dist/dts/components/orchestrating-driver/orchestrating-driver.d.ts +30 -93
  29. package/dist/dts/components/orchestrating-driver/orchestrating-driver.d.ts.map +1 -1
  30. package/dist/dts/index.d.ts +4 -1
  31. package/dist/dts/index.d.ts.map +1 -1
  32. package/dist/dts/main/main.d.ts +21 -5
  33. package/dist/dts/main/main.d.ts.map +1 -1
  34. package/dist/dts/main/main.styles.d.ts.map +1 -1
  35. package/dist/dts/main/main.template.d.ts.map +1 -1
  36. package/dist/dts/react.d.ts +10 -0
  37. package/dist/dts/state/debug-event-log.d.ts +1 -1
  38. package/dist/dts/state/debug-event-log.d.ts.map +1 -1
  39. package/dist/dts/state/interaction-context.d.ts +7 -1
  40. package/dist/dts/state/interaction-context.d.ts.map +1 -1
  41. package/dist/dts/state/persistence/session-persister.d.ts.map +1 -1
  42. package/dist/dts/suggestions/generate-suggestions.d.ts.map +1 -1
  43. package/dist/dts/types/handler-capability.d.ts +28 -0
  44. package/dist/dts/types/handler-capability.d.ts.map +1 -0
  45. package/dist/dts/types/interaction-context.d.ts +16 -0
  46. package/dist/dts/types/interaction-context.d.ts.map +1 -1
  47. package/dist/dts/types/interaction-interceptor.d.ts +109 -0
  48. package/dist/dts/types/interaction-interceptor.d.ts.map +1 -0
  49. package/dist/dts/utils/delegated-message.d.ts +52 -0
  50. package/dist/dts/utils/delegated-message.d.ts.map +1 -0
  51. package/dist/dts/utils/history-transform.d.ts.map +1 -1
  52. package/dist/esm/components/agent-session/agent-session.js +17 -0
  53. package/dist/esm/components/ai-driver/ai-driver.js +21 -1
  54. package/dist/esm/components/ai-driver/base-driver-decorator.js +211 -0
  55. package/dist/esm/components/ai-driver/index.js +2 -1
  56. package/dist/esm/components/chat-driver/chat-driver.js +195 -14
  57. package/dist/esm/components/chat-driver/interaction-controller.js +168 -14
  58. package/dist/esm/components/message-feedback/index.js +1 -0
  59. package/dist/esm/components/message-feedback/message-feedback.js +241 -0
  60. package/dist/esm/components/message-feedback/message-feedback.styles.js +94 -0
  61. package/dist/esm/components/message-feedback/message-feedback.template.js +80 -0
  62. package/dist/esm/components/orchestrating-driver/orchestrating-driver.js +72 -196
  63. package/dist/esm/index.js +1 -0
  64. package/dist/esm/main/main.js +123 -78
  65. package/dist/esm/main/main.styles.js +27 -0
  66. package/dist/esm/main/main.template.js +13 -0
  67. package/dist/esm/state/debug-event-log.js +7 -2
  68. package/dist/esm/state/interaction-context.js +11 -0
  69. package/dist/esm/state/persistence/session-persister.js +5 -6
  70. package/dist/esm/suggestions/generate-suggestions.js +8 -1
  71. package/dist/esm/types/handler-capability.js +1 -0
  72. package/dist/esm/types/interaction-interceptor.js +1 -0
  73. package/dist/esm/utils/delegated-message.js +25 -0
  74. package/dist/esm/utils/history-transform.js +12 -1
  75. package/dist/react.cjs +7 -0
  76. package/dist/react.mjs +6 -0
  77. package/package.json +17 -17
  78. package/sandbox/README.md +1 -1
  79. package/sandbox/sandbox.ts +35 -0
@@ -16,6 +16,7 @@ import { ChatDriverResult } from '@genesislcap/foundation-ai';
16
16
  import type { ChatFallback } from '@genesislcap/foundation-ai';
17
17
  import type { ChatInputDuringExecutionMode } from '@genesislcap/foundation-ai';
18
18
  import type { ChatMessage } from '@genesislcap/foundation-ai';
19
+ import type { ChatMessageFeedbackRating } from '@genesislcap/foundation-ai';
19
20
  import type { ChatThinkingPolicy } from '@genesislcap/foundation-ai';
20
21
  import type { ChatToolChoice } from '@genesislcap/foundation-ai';
21
22
  import type { ChatToolDefinition } from '@genesislcap/foundation-ai';
@@ -502,6 +503,12 @@ export declare class AgentSession {
502
503
  * Returns `undefined` when there was no active agent, so a caller can skip its events.
503
504
  */
504
505
  release(): Promise<AgentTransition | undefined>;
506
+ /**
507
+ * Hand a transition to the owner. A throwing listener is logged rather than propagated, for the
508
+ * same reason a throwing hook is: the transition has already happened, and failing the caller
509
+ * would leave it believing it had not.
510
+ */
511
+ private reportTransition;
505
512
  /**
506
513
  * Fire `onDeactivate` on the active agent and abort pending lifecycle work, for session
507
514
  * teardown, so machines release resources cleanly. The session is not reusable afterwards: the
@@ -533,14 +540,24 @@ export declare interface AgentSessionDeps {
533
540
  * after construction on some paths, so a value captured here would pin the wrong one.
534
541
  */
535
542
  sessionKey: () => string;
543
+ /**
544
+ * Called after every real transition (a swap to a different agent, or a release), once the
545
+ * session already reflects it. Not called for a re-activation of the same agent, for the direct
546
+ * {@link AgentSession.setFlowOwner} restore write, or on {@link AgentSession.dispose}.
547
+ *
548
+ * One place for the lifecycle events (GENC-1485): the session is shared between a `ChatDriver`
549
+ * and the `OrchestratingDriver` wrapping it, and either may move it, so the owner learns of a
550
+ * transition here rather than from whichever caller happened to make it.
551
+ */
552
+ onTransition?: (transition: AgentTransition) => void;
536
553
  }
537
554
 
538
555
  /**
539
556
  * What changed when an agent was activated or released.
540
557
  *
541
- * Returned rather than dispatched: the host listens on the `OrchestratingDriver`, not on the
542
- * `ChatDriver` that owns the session, so a self-dispatching session would need telling which
543
- * target to fire on.
558
+ * Returned to the caller, and also reported to the session's owner through
559
+ * {@link AgentSessionDeps.onTransition}, which is how the owning `ChatDriver` raises the lifecycle
560
+ * events whoever triggered the change (GENC-1485).
544
561
  *
545
562
  * @beta
546
563
  */
@@ -557,6 +574,14 @@ export declare interface AgentTransition {
557
574
  flowOwnerChangedTo?: string | null;
558
575
  }
559
576
 
577
+ /**
578
+ * The event types in {@link AiDriverEventMap}, as a runtime list. Built from a record keyed by the
579
+ * map, so adding an event to the map without adding it here is a compile error.
580
+ *
581
+ * @beta
582
+ */
583
+ export declare const AI_DRIVER_EVENT_TYPES: ReadonlyArray<keyof AiDriverEventMap>;
584
+
560
585
  /**
561
586
  * Union of all available animation names, derived from {@link ANIMATION_DEFS}.
562
587
  *
@@ -751,21 +776,22 @@ export declare interface AiDockProvider {
751
776
  }
752
777
 
753
778
  /**
754
- * Common interface implemented by both `ChatDriver` (single-agent) and
755
- * `OrchestratingDriver` (multi-agent). `FoundationAiAssistant` depends only
756
- * on this interface — the concrete class is chosen at startup based on how
757
- * many agents are configured.
779
+ * Common interface implemented by `ChatDriver` (single-agent), `OrchestratingDriver`
780
+ * (multi-agent) and any decorator built on {@link BaseDriverDecorator}. `FoundationAiAssistant`
781
+ * depends only on this interface — the concrete driver is chosen at startup based on how many
782
+ * agents are configured, and may be wrapped.
758
783
  *
759
- * Extends `EventTarget` so consumers can subscribe to `history-updated` events
784
+ * Extends `EventTarget` so consumers can subscribe to the events in {@link AiDriverEventMap}
760
785
  * without knowing the concrete implementation.
761
786
  *
762
787
  * @beta
763
788
  */
764
789
  export declare interface AiDriver extends EventTarget {
765
790
  /**
766
- * Send a user message and run the tool loop to completion.
791
+ * Send a user message and run the tool loop to completion. `options.delegate` sends it on the
792
+ * user's behalf instead (GENC-1660): see {@link SendMessageOptions}.
767
793
  */
768
- sendMessage(input: string, attachments?: ChatAttachment[]): Promise<ChatDriverResult>;
794
+ sendMessage(input: string, attachments?: ChatAttachment[], options?: SendMessageOptions): Promise<ChatDriverResult>;
769
795
  /**
770
796
  * Continue the tool loop from the current history without appending a new
771
797
  * user message. Used by `OrchestratingDriver` on agent handoffs — the
@@ -835,12 +861,17 @@ export declare interface AiDriver extends EventTarget {
835
861
  * than on the next message, then, when `resumeNote` is given and the agent has not opted out,
836
862
  * runs one turn from the restored history with the note in the tail of its first model call.
837
863
  *
864
+ * `agent` is the flow owner's config, for a driver that holds no list of agents to look it up
865
+ * in (GENC-1660): a config cannot be persisted, so after a reload only its name survives, and
866
+ * whoever runs a bare `ChatDriver` is the one that knows which agent it runs. A driver that does
867
+ * hold a list (the orchestrator) looks the owner up itself and ignores this.
868
+ *
838
869
  * Returns the turn's result when one ran, `undefined` otherwise (no flow owner, the owner is not
839
- * configured, or no note). Never throws for those cases.
870
+ * configured or not given, or no note). Never throws for those cases.
840
871
  *
841
872
  * @beta
842
873
  */
843
- resumeRestoredFlow?(resumeNote?: string): Promise<ChatDriverResult | undefined>;
874
+ resumeRestoredFlow?(resumeNote?: string, agent?: AgentConfig): Promise<ChatDriverResult | undefined>;
844
875
  /**
845
876
  * Return the full, unredacted conversation history.
846
877
  */
@@ -914,6 +945,54 @@ export declare interface AiDriver extends EventTarget {
914
945
  * since that ticket's breaking release.
915
946
  */
916
947
  setFlowOwner(name: string | null): void;
948
+ /**
949
+ * The transient flow lock: the name of the stateful agent that owns the current flow, or `null`
950
+ * (GENC-1660). The reading half of {@link AiDriver.setFlowOwner}; changes are announced on
951
+ * `flow-owner-changed`. Lets a decorator scope its behaviour to a flow without reaching for a
952
+ * concrete driver.
953
+ *
954
+ * Optional, so a third-party driver need not implement it; every shipped driver does.
955
+ *
956
+ * @beta
957
+ */
958
+ getFlowOwner?(): string | null;
959
+ /**
960
+ * Install an {@link InteractionInterceptor}: told about every interaction this driver opens,
961
+ * with its live context, and able to claim it and answer it instead of the person (GENC-1660).
962
+ * Interceptors are asked outermost first and the first claim wins. Returns a remover.
963
+ *
964
+ * Optional, so a third-party driver need not implement it; every shipped driver does.
965
+ *
966
+ * @beta
967
+ */
968
+ addInteractionInterceptor?(interceptor: InteractionInterceptor): () => void;
969
+ /**
970
+ * Show a widget in the transcript OUTSIDE any tool loop, and resolve with its result
971
+ * (GENC-1660): `requestInteraction` for something that is not a tool handler. How a decorator
972
+ * asks the person something of its own, such as what to do after a turn failed.
973
+ *
974
+ * It takes the one interaction slot like any other, so a turn that requests an interaction
975
+ * while it is open throws. Pass `options.signal` to close it — unanswered, like a timeout — when
976
+ * the moment passes. Interceptors are offered it like any other, with the active agent (if any)
977
+ * as its owner.
978
+ *
979
+ * Optional, so a third-party driver need not implement it; every shipped driver does.
980
+ *
981
+ * @beta
982
+ */
983
+ presentInteraction?<T = InteractionResult>(componentName: string, data: unknown, options?: InteractionRequestOptions): Promise<T>;
984
+ /**
985
+ * Add a named capability to every tool handler's context, under `context.capabilities[name]`
986
+ * (GENC-1660). How a decorator gives the working agent's handlers something to call — the
987
+ * autopilot's `mode` / `setMode`, say — without the agent knowing the decorator exists.
988
+ * `factory` builds the value per handler call, from who is calling; sub-agents' handlers see
989
+ * their root's capabilities. Returns a remover.
990
+ *
991
+ * Optional, so a third-party driver need not implement it; every shipped driver does.
992
+ *
993
+ * @beta
994
+ */
995
+ provideHandlerCapability?(name: string, factory: HandlerCapabilityFactory): () => void;
917
996
  /**
918
997
  * Headroom the next turn could need, and which agent set that requirement
919
998
  * (GENC-1582). `undefined` when no agent the turn could land on declares a
@@ -1031,6 +1110,53 @@ export declare interface AiDriver extends EventTarget {
1031
1110
  cancel?(): void;
1032
1111
  }
1033
1112
 
1113
+ /**
1114
+ * Every event an {@link AiDriver} can dispatch, by type (GENC-1660).
1115
+ *
1116
+ * The list a decorator forwards: {@link BaseDriverDecorator} re-dispatches each of these from its
1117
+ * inner driver, so an event missing here is an event a host behind a decorator never sees. That is
1118
+ * the failure the orchestrator's hand-written proxy list had twice (`external-cost-recorded`, then
1119
+ * the lifecycle events a bare `ChatDriver` never raised). Details typed `unknown` are forwarded
1120
+ * as-is and not yet described here.
1121
+ *
1122
+ * @beta
1123
+ */
1124
+ export declare interface AiDriverEventMap {
1125
+ /** The transcript changed. Detail: the full history. */
1126
+ 'history-updated': CustomEvent<ReadonlyArray<ChatMessage>>;
1127
+ /** A sub-agent's own transcript changed. */
1128
+ 'sub-agent-history-updated': CustomEvent<unknown>;
1129
+ /** A sub-agent run started. */
1130
+ 'sub-agent-start': CustomEvent<unknown>;
1131
+ /** A sub-agent run ended. */
1132
+ 'sub-agent-stop': CustomEvent<unknown>;
1133
+ /** A blocking interaction that overrides the chat input opened. */
1134
+ 'interaction-start': CustomEvent<unknown>;
1135
+ /** That interaction settled. */
1136
+ 'interaction-stop': CustomEvent<{
1137
+ interactionId: string;
1138
+ }>;
1139
+ /** The provider resolved for a turn changed. */
1140
+ 'provider-changed': CustomEvent<{
1141
+ name: string;
1142
+ }>;
1143
+ /** Spend was recorded against an already-resolved interaction. */
1144
+ 'external-cost-recorded': CustomEvent<{
1145
+ interactionId: string;
1146
+ costUsd: number;
1147
+ }>;
1148
+ /** The active agent changed. Detail: the new agent, or `undefined` after a release. */
1149
+ 'agent-changed': CustomEvent<AgentConfig | undefined>;
1150
+ /** A stateful agent released its flow. Detail: the released agent. */
1151
+ 'agent-released': CustomEvent<AgentConfig>;
1152
+ /** The flow-owner lock changed. Detail: the new owner's name, or `null` when cleared. */
1153
+ 'flow-owner-changed': CustomEvent<string | null>;
1154
+ /** Routing started (the classifier is about to run). Orchestrator only. */
1155
+ 'orchestrating-start': CustomEvent<undefined>;
1156
+ /** Routing finished and an agent is installed. Orchestrator only. */
1157
+ 'orchestrating-stop': CustomEvent<undefined>;
1158
+ }
1159
+
1034
1160
  /**
1035
1161
  * Optional app-registered policy for which cloud vendor backs the tier-shaped
1036
1162
  * provider registry slots (`low` / `high` / …). Apps inject a concrete
@@ -1525,6 +1651,97 @@ declare interface BaseAgentConfig {
1525
1651
  contextReserve?: ContextReserveInput;
1526
1652
  }
1527
1653
 
1654
+ /**
1655
+ * The base of every driver decorator (GENC-1660): an {@link AiDriver} that wraps another and
1656
+ * passes every member, and every event in {@link AiDriverEventMap}, through to it.
1657
+ *
1658
+ * A decorator extends this and overrides only what it changes, so decorators stack in any order
1659
+ * and a member or event added to `AiDriver` reaches the host through every layer by default.
1660
+ * `OrchestratingDriver` is one; it used to forward by hand, and twice a member it did not forward
1661
+ * silently did nothing for every multi-agent host (`recordExternalCost`, then
1662
+ * `getHistoryForPersistence`).
1663
+ *
1664
+ * Abstract with no abstract members, so it cannot be constructed on its own: a decorator that
1665
+ * changes nothing is not one.
1666
+ *
1667
+ * Optional `AiDriver` members are implemented here unconditionally, as a forward that falls back
1668
+ * to the "not supported" answer when the inner driver lacks them. A host that feature-detects with
1669
+ * `?.` therefore always finds them, and gets the same answer it would from the inner driver.
1670
+ *
1671
+ * @beta
1672
+ */
1673
+ export declare abstract class BaseDriverDecorator<TInner extends AiDriver = AiDriver> extends EventTarget implements AiDriver {
1674
+ protected readonly inner: TInner;
1675
+ /** Undoes this layer's hold on its inner driver; see {@link BaseDriverDecorator.detach}. */
1676
+ private readonly detachers;
1677
+ protected constructor(inner: TInner);
1678
+ /**
1679
+ * Let go of the inner driver WITHOUT disposing it: stop forwarding its events, and undo whatever
1680
+ * a subclass registered through {@link BaseDriverDecorator.onDetach} (its interceptors, its
1681
+ * capabilities, its own listeners). For dropping or replacing a decorator while the driver it
1682
+ * wrapped lives on — otherwise the old layer keeps re-dispatching every event and is never
1683
+ * collected. Idempotent. `dispose()` detaches too.
1684
+ */
1685
+ detach(): void;
1686
+ /** Register something {@link BaseDriverDecorator.detach} must undo. */
1687
+ protected onDetach(undo: () => void): void;
1688
+ sendMessage(input: string, attachments?: ChatAttachment[], options?: SendMessageOptions): Promise<ChatDriverResult>;
1689
+ continueFromHistory(transientPrimer?: ChatMessage[], options?: ContinueFromHistoryOptions): Promise<ChatDriverResult>;
1690
+ resolveInteraction(interactionId: string, result: unknown): void;
1691
+ recordExternalCost(interactionId: string, costUsd: number): boolean;
1692
+ getInteractionContext(interactionId: string): InteractionContext | undefined;
1693
+ loadHistory(messages: ChatMessage[]): void;
1694
+ primeRestoredAgentState(snapshots: Record<string, unknown>): void;
1695
+ canRestoreFlowOwner(agentName: string): boolean;
1696
+ canResumeRestoredFlow(agentName: string): boolean;
1697
+ resumeRestoredFlow(resumeNote?: string, agent?: AgentConfig): Promise<ChatDriverResult | undefined>;
1698
+ getRawHistory(): readonly ChatMessage[];
1699
+ getHistoryForPersistence(): ChatMessage[];
1700
+ getCondensePoliciesForPersistence(messages: readonly ChatMessage[]): PersistedCondensePolicy[];
1701
+ restoreCondensePolicies(entries: readonly unknown[] | undefined): {
1702
+ restored: number;
1703
+ awaitingReactivation: number;
1704
+ };
1705
+ getActiveAgent(): AgentConfig | undefined;
1706
+ setPinnedAgent(name: string | null): void;
1707
+ setFlowOwner(name: string | null): void;
1708
+ getFlowOwner(): string | null;
1709
+ /**
1710
+ * Forwarded, so an interceptor installed on any layer lands on the driver that opens the
1711
+ * interactions. A decorator that answers interactions installs its own on `this.inner`.
1712
+ */
1713
+ addInteractionInterceptor(interceptor: InteractionInterceptor): () => void;
1714
+ presentInteraction<T = InteractionResult>(componentName: string, data: unknown, options?: InteractionRequestOptions): Promise<T>;
1715
+ provideHandlerCapability(name: string, factory: HandlerCapabilityFactory): () => void;
1716
+ getContextReserve(): ContextReserveResolution | undefined;
1717
+ getPreambleTokens(): number | undefined;
1718
+ setContextGuard(policy?: ContextGuardPolicy): void;
1719
+ compact(options?: CompactionPlanOptions): Promise<ChatMessage | null>;
1720
+ getCompactionPlan(options?: CompactionPlanOptions): CompactionProjection | null;
1721
+ canCompact(options?: CompactionPlanOptions): boolean;
1722
+ isBusy(): boolean;
1723
+ getSuggestions(history: ChatMessage[], prompt: string, count: number, allAgentInfo?: AllAgentSummary[]): Promise<string[]>;
1724
+ getTurnSnapshots(): ReadonlyArray<TurnSnapshot>;
1725
+ /**
1726
+ * The inner driver's entries. Diagnostics compose down the stack: a decorator with entries of
1727
+ * its own overrides this and appends them to `super.getExternalDiagnostics()`.
1728
+ */
1729
+ getExternalDiagnostics(): ReadonlyArray<DiagnosticEntry>;
1730
+ getActiveProviderName(): string;
1731
+ dispose(): void | Promise<void>;
1732
+ cancel(): void;
1733
+ /**
1734
+ * Every driver in the stack, outermost first: `driver`, then each inner driver down to the one
1735
+ * that is not a decorator.
1736
+ *
1737
+ * For diagnostics and labelling only: behaviour must go through `AiDriver` members, which every
1738
+ * layer forwards, never through a concrete class found here.
1739
+ *
1740
+ * @internal
1741
+ */
1742
+ static layers(driver: AiDriver): AiDriver[];
1743
+ }
1744
+
1528
1745
  /**
1529
1746
  * Id of the blocked banner, referenced by the composer controls'
1530
1747
  * `aria-describedby`. Shadow-DOM-scoped, so a fixed string cannot collide with
@@ -1822,6 +2039,13 @@ export declare class ChatDriver extends EventTarget implements AiDriver {
1822
2039
  private unlinkLifecycleFromMessage?;
1823
2040
  /** A sub-agent runs inside its parent's message: the parent's `turnSignal`, handed down. */
1824
2041
  private inheritedTurnSignal?;
2042
+ /** Capabilities provided on this driver by decorators (GENC-1660). Only the root's are used. */
2043
+ private readonly handlerCapabilities;
2044
+ /**
2045
+ * For a sub-agent's driver, the driver that invoked it: its capabilities, flow owner and owner
2046
+ * path are the ones this driver's handlers see, so a capability reaches sub-agents unchanged.
2047
+ */
2048
+ private capabilityParent?;
1825
2049
  /**
1826
2050
  * Active agent's provider selector (static name or per-turn resolver).
1827
2051
  * `undefined` means "use the registry default".
@@ -1926,6 +2150,11 @@ export declare class ChatDriver extends EventTarget implements AiDriver {
1926
2150
  * the point: two would let `getActiveAgent()` disagree between the outer and inner driver.
1927
2151
  * `@internal` rather than private so that reach is legal without six delegating one-liners.
1928
2152
  *
2153
+ * **This driver raises the lifecycle events for every transition of the session**, whoever made
2154
+ * it: itself, through {@link ChatDriver.activateAgent} or a release, or the orchestrator reaching
2155
+ * through (GENC-1485). Before, only the orchestrator dispatched them, so a host on a bare
2156
+ * `ChatDriver` never learned its flow owner.
2157
+ *
1929
2158
  * @internal
1930
2159
  */
1931
2160
  readonly agentSession: AgentSession;
@@ -2199,6 +2428,30 @@ export declare class ChatDriver extends EventTarget implements AiDriver {
2199
2428
  * @beta
2200
2429
  */
2201
2430
  activateAgent(config: AgentConfig): Promise<void>;
2431
+ /**
2432
+ * {@inheritDoc AiDriver.resumeRestoredFlow}
2433
+ *
2434
+ * This driver holds no list of agents, so it resumes only the `agent` it is handed (GENC-1660):
2435
+ * whoever runs a bare `ChatDriver` knows which agent that is, and after a reload only the name
2436
+ * survived. Without one it does nothing, as a driver without this member did before; given one
2437
+ * that is not the restored flow owner, it refuses.
2438
+ *
2439
+ * For headless callers: the shipped host restores and resumes through `OrchestratingDriver`,
2440
+ * and a bare `ChatDriver` does not answer `canRestoreFlowOwner`, so the host never plans a resume
2441
+ * for one.
2442
+ *
2443
+ * The orchestrator does not delegate here, because it installs a decorated config of its own;
2444
+ * this is the bare-driver path.
2445
+ *
2446
+ * @beta
2447
+ */
2448
+ resumeRestoredFlow(resumeNote?: string, agent?: AgentConfig): Promise<ChatDriverResult | undefined>;
2449
+ /**
2450
+ * Raise the host-facing lifecycle events for one session transition (GENC-1485), in the order
2451
+ * the orchestrator raised them before it stopped doing so itself: the flow lock first, then the
2452
+ * release, then the active agent.
2453
+ */
2454
+ private dispatchAgentTransition;
2202
2455
  /**
2203
2456
  * {@inheritDoc AiDriver.getActiveAgent}
2204
2457
  *
@@ -2226,6 +2479,12 @@ export declare class ChatDriver extends EventTarget implements AiDriver {
2226
2479
  * @beta
2227
2480
  */
2228
2481
  setFlowOwner(name: string | null): void;
2482
+ /**
2483
+ * {@inheritDoc AiDriver.getFlowOwner}
2484
+ *
2485
+ * @beta
2486
+ */
2487
+ getFlowOwner(): string | null;
2229
2488
  /**
2230
2489
  * Install `config` as the active agent **without firing lifecycle hooks**.
2231
2490
  *
@@ -2528,7 +2787,38 @@ export declare class ChatDriver extends EventTarget implements AiDriver {
2528
2787
  * and `presentation` to control whether the host wraps the widget in a chat
2529
2788
  * bubble and/or shows the "Assistant" label.
2530
2789
  */
2531
- requestInteraction<T>(componentName: string, data: any, options?: InteractionRequestOptions, onOpened?: (interactionId: string) => void): Promise<T>;
2790
+ requestInteraction<T>(componentName: string, data: any, options?: InteractionRequestOptions, onOpened?: (interactionId: string) => void, innerPath?: readonly string[], onSettled?: (settled: InteractionSettled) => void): Promise<T>;
2791
+ /**
2792
+ * {@inheritDoc AiDriver.addInteractionInterceptor}
2793
+ *
2794
+ * Consulted only on the root driver, where every interaction opens: a sub-agent's request
2795
+ * travels up to its root, carrying its owner path, and is offered there once.
2796
+ *
2797
+ * @beta
2798
+ */
2799
+ addInteractionInterceptor(interceptor: InteractionInterceptor): () => void;
2800
+ /**
2801
+ * {@inheritDoc AiDriver.presentInteraction}
2802
+ *
2803
+ * @beta
2804
+ */
2805
+ presentInteraction<T = InteractionResult>(componentName: string, data: unknown, options?: InteractionRequestOptions): Promise<T>;
2806
+ /**
2807
+ * {@inheritDoc AiDriver.provideHandlerCapability}
2808
+ *
2809
+ * Throws if `name` is already provided: two decorators answering to one name would leave a
2810
+ * handler unable to tell which it is talking to.
2811
+ *
2812
+ * @beta
2813
+ */
2814
+ provideHandlerCapability(name: string, factory: HandlerCapabilityFactory): () => void;
2815
+ /**
2816
+ * The capabilities this driver's handlers see, and who they see them as: the root's factories,
2817
+ * the root's flow owner, and the owner path from the root down to this driver's agent.
2818
+ */
2819
+ private capabilityScope;
2820
+ /** Build `context.capabilities` for one handler call, or `undefined` when nothing is provided. */
2821
+ private buildCapabilities;
2532
2822
  /**
2533
2823
  * Record what came of an interaction, after it resolved, on its history message
2534
2824
  * (`interaction.outcome`): handed to its widget and persisted with the session, never sent to a
@@ -2583,7 +2873,7 @@ export declare class ChatDriver extends EventTarget implements AiDriver {
2583
2873
  * can continue an existing conversation. Call this before the first user message.
2584
2874
  */
2585
2875
  loadHistory(messages: ChatMessage[]): void;
2586
- sendMessage(userInput: string, attachments?: ChatAttachment[]): Promise<ChatDriverResult>;
2876
+ sendMessage(userInput: string, attachments?: ChatAttachment[], options?: SendMessageOptions): Promise<ChatDriverResult>;
2587
2877
  /**
2588
2878
  * Builds the context object passed to every tool handler call.
2589
2879
  * Centralised here so fold shortcut dispatch and the main tool loop use the
@@ -2714,10 +3004,10 @@ export declare interface ChatDriverConfig {
2714
3004
  * Leave acting on `releaseAgent` to the owner of this driver.
2715
3005
  *
2716
3006
  * Set by `OrchestratingDriver` for its inner driver, which performs the release itself after the
2717
- * turn so it can fire the host-facing `agent-released` / `agent-changed` / `flow-owner-changed`
2718
- * events. Both drivers share one `AgentSession`, so releasing here first would empty it and make
2719
- * the orchestrator's own release a silent no-op — leaving the host with a locked picker and a
2720
- * stale active agent.
3007
+ * turn, because a release ends its handoff loop and it reads the flag to know. Both drivers share
3008
+ * one `AgentSession`, and releasing here first would clear the flag before the orchestrator saw
3009
+ * it. The host-facing `agent-released` / `agent-changed` / `flow-owner-changed` events fire from
3010
+ * the session's transition either way (GENC-1485).
2721
3011
  *
2722
3012
  * Left unset, a driver releases its own agent, which is what a bare `ChatDriver` needs: nothing
2723
3013
  * else is watching the flag.
@@ -3112,6 +3402,14 @@ export declare interface DebugLog {
3112
3402
  */
3113
3403
  export declare const DEFAULT_ANIMATIONS: AiAssistantAnimation[];
3114
3404
 
3405
+ /**
3406
+ * How a delegated `user` message is framed for the model when its sender gives no phrase. Names no
3407
+ * decorator, so the model has none to repeat.
3408
+ *
3409
+ * @beta
3410
+ */
3411
+ export declare const DEFAULT_DELEGATE_FRAMING = "Sent on the user's behalf.";
3412
+
3115
3413
  /**
3116
3414
  * Identity helper that infers the narrowest possible type for an agent config,
3117
3415
  * preserving string literal types (including `name`) without requiring `as const`.
@@ -3156,6 +3454,36 @@ export declare function defineAgent<const T extends AgentConfig>(config: T): T;
3156
3454
  */
3157
3455
  export declare function defineStatefulAgent<S>(opts: StatefulAgentInit<S>): AgentConfig;
3158
3456
 
3457
+ /**
3458
+ * What the working agent is told about an interaction an interceptor answered (GENC-1660): added
3459
+ * to the result of the tool call that requested it, as `decidedOnUsersBehalf` on an object result
3460
+ * or as a line appended to a text one.
3461
+ *
3462
+ * Built only from what the platform already holds — the claimant's framing, and the choice and
3463
+ * narration it recorded — so the text the person saw and the text the agent is told about are the
3464
+ * same string. It never names the claimant, so the agent has nothing to repeat about one.
3465
+ *
3466
+ * @beta
3467
+ */
3468
+ export declare interface DelegatedDecision {
3469
+ /** The claimant's {@link InteractionInterceptor.decisionFraming}, e.g. "Decided on the user's behalf". */
3470
+ readonly framing: string;
3471
+ /** What was chosen, as recorded by the claimant. */
3472
+ readonly choice?: string;
3473
+ /** What the person was shown about it, verbatim, as the assistant's own words. */
3474
+ readonly shownToUser?: string;
3475
+ }
3476
+
3477
+ /**
3478
+ * A message written or sent on the user's behalf by a driver decorator (GENC-1660). See
3479
+ * `ChatMessage.delegate`.
3480
+ *
3481
+ * @beta
3482
+ */
3483
+ export declare type DelegatedMessage = ChatMessage & {
3484
+ delegate: string;
3485
+ };
3486
+
3159
3487
  /**
3160
3488
  * One entry in the diagnostics stream — the debug-log timeline-entry union
3161
3489
  * (`message` / `turn` / `event`, as `getDebugLog()` builds) plus a point-in-time
@@ -4162,11 +4490,11 @@ export declare class FoundationAiAssistant extends GenesisElement {
4162
4490
  showingSplash: boolean;
4163
4491
  private driver?;
4164
4492
  /**
4165
- * This element's driver as an orchestrator, or `undefined` when the session is running a bare
4166
- * `ChatDriver`. The only place in this element that narrows the type; the test itself lives in
4167
- * `asOrchestrator`, shared with the session persister.
4493
+ * Which kind of driver this element runs, for the `driver.created` / `assistant.connected` log
4494
+ * lines only. Looks through any decorators (GENC-1660): behaviour goes through `AiDriver`
4495
+ * members, which every layer forwards, so this is the one place the concrete class matters.
4168
4496
  */
4169
- private get orchestrator();
4497
+ private get driverKind();
4170
4498
  private driverCleanup?;
4171
4499
  private loadingTimer;
4172
4500
  private unsubBus?;
@@ -4872,6 +5200,22 @@ export declare class FoundationAiAssistant extends GenesisElement {
4872
5200
  * promise is enforced rather than relying on two copies agreeing.
4873
5201
  */
4874
5202
  private debugLogFilename;
5203
+ /**
5204
+ * The most recent rateable reply, whose thumbs stay visible without a hover.
5205
+ *
5206
+ * @internal
5207
+ */
5208
+ get latestReply(): ChatMessage | undefined;
5209
+ /** @internal */
5210
+ get messageFeedbackDescription(): string;
5211
+ /**
5212
+ * Hand a rated reply to the host's `ui.messageFeedback.send`, with a getter for the same
5213
+ * lifetime log the agent-log Send button submits — built only if the host asks for it.
5214
+ * Rejects when the host does, or does not settle in time.
5215
+ *
5216
+ * @internal
5217
+ */
5218
+ submitMessageFeedback(reply: ChatMessage, rating: ChatMessageFeedbackRating, note: string | undefined): Promise<void>;
4875
5219
  /**
4876
5220
  * Back to idle: nothing in flight, no flash, no open compose box, no note. Called on
4877
5221
  * disconnect and on a session switch / Clear (a note typed against one conversation
@@ -5249,6 +5593,35 @@ export declare type GenesisWriteReviewCompletedEventDetail = InteractionResult<G
5249
5593
  */
5250
5594
  export declare function getAiPopoutManager(): FoundationAiPopoutManager | undefined;
5251
5595
 
5596
+ /**
5597
+ * Builds a capability's value for one tool-handler call (GENC-1660). Called per call, so it can
5598
+ * reflect the moment; it should be cheap and must not throw (a throw is logged and the capability
5599
+ * left out of that call). Returning `undefined` leaves the capability out, which is how a decorator
5600
+ * says "not available here".
5601
+ *
5602
+ * @beta
5603
+ */
5604
+ export declare type HandlerCapabilityFactory = (scope: HandlerCapabilityScope) => unknown;
5605
+
5606
+ /**
5607
+ * Who a handler capability is being built for (GENC-1660): the tool handler about to run.
5608
+ *
5609
+ * @beta
5610
+ */
5611
+ export declare interface HandlerCapabilityScope {
5612
+ /**
5613
+ * The agents from the root down to the one whose handler is running, outermost first — e.g.
5614
+ * `['bootstrap', 'brief-critic']` for a sub-agent's handler. The same shape as
5615
+ * `InteractionOpened.ownerPath`, so a decorator scopes the two the same way.
5616
+ */
5617
+ readonly ownerPath: readonly string[];
5618
+ /**
5619
+ * The root driver's flow owner when the handler runs, or `null`. A sub-agent has no flow of its
5620
+ * own, so it sees its root's: a capability scoped to a flow applies to the flow's sub-agents.
5621
+ */
5622
+ readonly flowOwner: string | null;
5623
+ }
5624
+
5252
5625
  /**
5253
5626
  * A single in-flight per-call chat-input override pushed by a `requestSubAgent`
5254
5627
  * or `requestInteraction` call. Tracked as an array (not a counter) so the
@@ -5303,6 +5676,15 @@ export declare type InteractionCompletedEventDetail = ChatInteractionEventsMap['
5303
5676
  export declare interface InteractionContext<TState extends object = Record<string, unknown>> {
5304
5677
  /** Stable id of the interaction this context belongs to. */
5305
5678
  readonly interactionId: string;
5679
+ /**
5680
+ * Who holds this pending interaction right now: `'user'`, or the id of the interceptor that
5681
+ * claimed it, e.g. `'autopilot'` (GENC-1660). `'user'` unless something claimed it.
5682
+ *
5683
+ * Reactive through {@link InteractionContext.subscribe}: a change calls `notify()`, so a view
5684
+ * must re-read it on every notification rather than once on mount, or it would stay hidden after
5685
+ * a hand-back. Only the claimant changes it, through its `InteractionHold`.
5686
+ */
5687
+ readonly heldBy: InteractionHolder;
5306
5688
  /**
5307
5689
  * Durable, remount-surviving source of truth for the interaction — a socket
5308
5690
  * handle, the current phase, a half-typed draft. A plain object, deliberately
@@ -5355,11 +5737,120 @@ export declare interface InteractionContext<TState extends object = Record<strin
5355
5737
  */
5356
5738
  export declare type InteractionCostEventDetail = ChatInteractionEventsMap['interaction-cost'];
5357
5739
 
5740
+ /**
5741
+ * The handle an interceptor uses to move a pending interaction between the person and itself
5742
+ * (GENC-1660): to the person when it hands back or is paused, back to itself when resumed.
5743
+ *
5744
+ * Every interceptor is offered one, but only the claimant's works: on any other interceptor's
5745
+ * handle, and after the interaction ends, its members do nothing and return `false`. A claim is
5746
+ * granted only once `onInteractionOpened` has returned `'claim'` (it may yet be refused), so the
5747
+ * claimant's own handle does nothing until then either: act on it afterwards. Views read the
5748
+ * result as `ctx.heldBy`; they never change it.
5749
+ *
5750
+ * @beta
5751
+ */
5752
+ export declare interface InteractionHold {
5753
+ /**
5754
+ * Give the interaction to the person (`'user'`) or back to the claimant (`'claimant'`). Notifies
5755
+ * the context's subscribers and records `interaction.held`. Returns whether it applied.
5756
+ */
5757
+ set(holder: 'user' | 'claimant'): boolean;
5758
+ /**
5759
+ * Say what the claimant decided, before it settles the interaction, so the tool that asked is
5760
+ * told honestly (GENC-1660). When the interaction then resolves while the claimant holds it, the
5761
+ * driver adds a {@link DelegatedDecision} built from this to that tool's result, so the working
5762
+ * agent learns the choice was made on the user's behalf and what the user was shown about it.
5763
+ *
5764
+ * Optional to call: without it the record carries only the framing. Later calls replace earlier
5765
+ * ones. Returns `false`, recording nothing, unless this interceptor holds the interaction.
5766
+ */
5767
+ recordDecision(decision: {
5768
+ choice?: string;
5769
+ shownToUser?: string;
5770
+ }): boolean;
5771
+ /**
5772
+ * Settle the interaction AS the claimant (GENC-1660). The only route that stamps the claimant as
5773
+ * `answeredBy`: an answer through the host's `resolveInteraction` — a click — is the person's,
5774
+ * whoever held the interaction at the time, so attribution never depends on a view honouring
5775
+ * `heldBy`. Returns `false`, settling nothing, unless this interceptor holds it right now.
5776
+ */
5777
+ resolve(result: unknown): boolean;
5778
+ }
5779
+
5780
+ /**
5781
+ * Who holds a pending interaction: the person, or the id of the interceptor that claimed it
5782
+ * (GENC-1660). See {@link InteractionContext.heldBy}.
5783
+ *
5784
+ * @beta
5785
+ */
5786
+ export declare type InteractionHolder = 'user' | (string & {});
5787
+
5788
+ /**
5789
+ * Something that is told about every interaction a driver opens, and may answer it instead of the
5790
+ * person (GENC-1660). Installed with `AiDriver.addInteractionInterceptor`, typically by a driver
5791
+ * decorator such as an autopilot or a test harness.
5792
+ *
5793
+ * Interceptors are asked outermost first. The first to claim an interaction holds it; the rest
5794
+ * observe — they see the same context but their `hold` does nothing. Nobody can claim a `userOnly`
5795
+ * interaction. A throwing interceptor is logged and treated as abstaining.
5796
+ *
5797
+ * @beta
5798
+ */
5799
+ export declare interface InteractionInterceptor {
5800
+ /** The holder id this interceptor's claims are recorded under, e.g. `'autopilot'`. Not `'user'`. */
5801
+ readonly id: string;
5802
+ /**
5803
+ * How a {@link DelegatedDecision} it settled opens, as the working agent reads it. Must not name
5804
+ * the interceptor. Defaults to "Decided on the user's behalf"; an autopilot grounded in a brief
5805
+ * would say "Decided on the user's behalf, from their brief".
5806
+ */
5807
+ readonly decisionFraming?: string;
5808
+ /** Return `'claim'` to hold the interaction, or nothing to leave it with the person. */
5809
+ onInteractionOpened(opened: InteractionOpened): 'claim' | undefined | void;
5810
+ }
5811
+
5812
+ /**
5813
+ * A new interaction, as offered to each installed interceptor (GENC-1660).
5814
+ *
5815
+ * Offered once, at the root driver, after its context exists and before its message is appended,
5816
+ * so the first render of its widget already knows who holds it.
5817
+ *
5818
+ * @beta
5819
+ */
5820
+ export declare interface InteractionOpened {
5821
+ readonly interactionId: string;
5822
+ readonly componentName: string;
5823
+ /** The `data` the widget was requested with. */
5824
+ readonly data: unknown;
5825
+ /**
5826
+ * The agents that asked for it, outermost first: the root's active agent, then each sub-agent
5827
+ * the request travelled up through — e.g. `['bootstrap', 'brief-critic']`. The last entry is the
5828
+ * agent whose tool handler called `requestInteraction`.
5829
+ */
5830
+ readonly ownerPath: readonly string[];
5831
+ /** Set from `InteractionRequestOptions.userOnly`: nobody may claim it. */
5832
+ readonly userOnly: boolean;
5833
+ /** The interaction's live context, the same object its widget is handed. */
5834
+ readonly ctx: InteractionContext;
5835
+ /** See {@link InteractionHold}. Works only for the interceptor whose claim was granted. */
5836
+ readonly hold: InteractionHold;
5837
+ }
5838
+
5358
5839
  /**
5359
5840
  * Opens an interaction somewhere else — the parent driver, for a sub-agent's — and tells
5360
- * `onOpened` its id.
5841
+ * `onOpened` its id. `ownerPath` is the agents the request has already come up through, outermost
5842
+ * first, so the root can tell interceptors who asked (GENC-1660).
5361
5843
  */
5362
- declare type InteractionRequester = <T>(componentName: string, data: any, options?: InteractionRequestOptions, onOpened?: (interactionId: string) => void) => Promise<T>;
5844
+ declare type InteractionRequester = <T>(componentName: string, data: any, options?: InteractionRequestOptions, onOpened?: (interactionId: string) => void, ownerPath?: readonly string[], onSettled?: (settled: InteractionSettled) => void) => Promise<T>;
5845
+
5846
+ /**
5847
+ * Who answered an interaction, as its requester is told (GENC-1660). `answeredBy` is absent when it
5848
+ * closed unanswered (a timeout or a stop); `decision` is present when an interceptor answered.
5849
+ */
5850
+ declare interface InteractionSettled {
5851
+ readonly answeredBy?: string;
5852
+ readonly decision?: DelegatedDecision;
5853
+ }
5363
5854
 
5364
5855
  /**
5365
5856
  * A message's interaction widget, in the wrapper that mounts it. Everything the widget is shown
@@ -5373,6 +5864,14 @@ export declare const interactionWrapperTemplate: ViewTemplate<ChatMessage, Found
5373
5864
  /** True when the assistant is active in the layout panel (docked) rather than the bubble. */
5374
5865
  export declare function isAiAssistantDocked(): boolean;
5375
5866
 
5867
+ /**
5868
+ * Whether `message` was written or sent on the user's behalf. A delegated message renders as the
5869
+ * assistant, whatever its role.
5870
+ *
5871
+ * @beta
5872
+ */
5873
+ export declare const isDelegated: (message: ChatMessage) => message is DelegatedMessage;
5874
+
5376
5875
  /**
5377
5876
  * The interchangeable "assistant is working" loading-indicator styles. At most
5378
5877
  * one of these may be enabled at a time — enabling one disables the other.
@@ -5454,12 +5953,19 @@ export declare const NOOP_ACTIVITY_BUS: ActivityBus;
5454
5953
  * and `ChatDriver`, classifying each user message and routing it to the right
5455
5954
  * specialist — each with its own focused system prompt, tools, and primer.
5456
5955
  *
5956
+ * A {@link BaseDriverDecorator} over the `ChatDriver` it constructs (GENC-1485, GENC-1660): every
5957
+ * `AiDriver` member and event it does not override passes straight through. Its inner driver is
5958
+ * always one it built, never a composition choice, because routing reaches `ChatDriver`-only
5959
+ * members (`installAgent`, `agentSession`, `getHistory`, `setProviderHistoryTransform`, the
5960
+ * release flag and the `report…` exits). Other decorators go outside it.
5961
+ *
5457
5962
  * @beta
5458
5963
  */
5459
- export declare class OrchestratingDriver extends EventTarget implements AiDriver {
5964
+ export declare class OrchestratingDriver extends BaseDriverDecorator<ChatDriver> {
5460
5965
  private readonly providerRegistry;
5461
5966
  private readonly agents;
5462
- private readonly chatDriver;
5967
+ /** The inner driver this one built and routes onto. */
5968
+ private get chatDriver();
5463
5969
  private readonly specialists;
5464
5970
  private readonly fallback?;
5465
5971
  private readonly maxHandoffs;
@@ -5516,80 +6022,14 @@ export declare class OrchestratingDriver extends EventTarget implements AiDriver
5516
6022
  /** AI service error copy, passed through to the inner ChatDriver (GENC-1611). */
5517
6023
  aiServiceErrorMessages?: Partial<Record<AIServiceRefusal, string>>;
5518
6024
  });
5519
- resolveInteraction(interactionId: string, result: unknown): void;
5520
- /** Delegated for the same reason as `resolveInteraction`: the history that owns the
5521
- * interaction — and therefore the cost — lives on the wrapped driver, not here. */
5522
- recordExternalCost(interactionId: string, costUsd: number): boolean;
5523
- getInteractionContext(interactionId: string): InteractionContext | undefined;
5524
- isBusy(): boolean;
5525
- /** Currently active provider name from the underlying ChatDriver. */
5526
- getActiveProviderName(): string;
5527
- /**
5528
- * Pins routing to a specific agent by name. While pinned, the classifier is
5529
- * skipped and the continuation tool is hidden from the agent's tool list, so
5530
- * the agent cannot quietly hand back to the orchestrator. Pass `null` to
5531
- * return to automatic routing.
5532
- */
5533
- setPinnedAgent(name: string | null): void;
5534
- /**
5535
- * Set the flow-owner lock — used to restore state from Redux on driver
5536
- * reconstruction (agents-array changes, pop-in/pop-out). Not intended for
5537
- * external callers to manipulate routing; that's what `setPinnedAgent` is
5538
- * for.
5539
- */
5540
- setFlowOwner(name: string | null): void;
5541
- loadHistory(messages: ChatMessage[]): void;
5542
- getRawHistory(): readonly ChatMessage[];
5543
- /**
5544
- * Delegates to the inner {@link ChatDriver} — condensation policies are registered there, so it
5545
- * is the only object that knows which payloads the model has stopped seeing (GENC-1566).
5546
- *
5547
- * **This forward is the whole feature, for any multi-agent host.** `AiDriver` declares
5548
- * `getHistoryForPersistence` optional, and `SessionPersister` calls it through `?.`, falling back
5549
- * to {@link OrchestratingDriver.getRawHistory}. This class does NOT extend `ChatDriver` — it
5550
- * wraps one — so without an explicit forward the optional call resolves to `undefined` and every
5551
- * host on an orchestrating driver silently keeps persisting the full payloads. Measured exactly
5552
- * that way on a Create run: 10 `context.condensed` events fired, and the session still stored
5553
- * the two largest `read_context` results at 26,907 and 23,060 chars. The method existed, the
5554
- * tests passed, and the feature did nothing.
5555
- */
5556
- getHistoryForPersistence(): ChatMessage[];
5557
6025
  /**
5558
- * Delegates to the inner {@link ChatDriver}, which owns the condensation registry and clocks
5559
- * (GENC-1632). The forward matters for the same reason as `getHistoryForPersistence` above: the
5560
- * persister reaches it through `?.`, so a missing forward would compile, pass the ChatDriver
5561
- * tests, and do nothing for every orchestrated host — which is every host with an agents array.
6026
+ * Build the inner driver, after validating the agents' providers, so a bad config throws before
6027
+ * a driver exists to subscribe to the registry. Static because it runs before `super()`.
5562
6028
  */
5563
- getCondensePoliciesForPersistence(messages: readonly ChatMessage[]): PersistedCondensePolicy[];
5564
- /**
5565
- * Delegates to the inner {@link ChatDriver} (GENC-1632). The deferred activation stamp it
5566
- * performs is taken by the inner driver's `installAgent`, which this driver's own
5567
- * `installAgent` always reaches, so nothing extra is needed here.
5568
- */
5569
- restoreCondensePolicies(entries: readonly unknown[] | undefined): {
5570
- restored: number;
5571
- awaitingReactivation: number;
5572
- };
5573
- /** {@inheritDoc AiDriver.setContextGuard} */
5574
- setContextGuard(policy?: ContextGuardPolicy): void;
5575
- /** {@inheritDoc AiDriver.compact} */
5576
- compact(options?: CompactionPlanOptions): Promise<ChatMessage | null>;
5577
- /** {@inheritDoc AiDriver.canCompact} */
5578
- canCompact(options?: CompactionPlanOptions): boolean;
5579
- /** {@inheritDoc AiDriver.getPreambleTokens} */
5580
- getPreambleTokens(): number | undefined;
5581
- /** {@inheritDoc AiDriver.getCompactionPlan} */
5582
- getCompactionPlan(options?: CompactionPlanOptions): CompactionProjection | null;
5583
- /** Delegates to the inner {@link ChatDriver} — turns are captured there. */
5584
- getTurnSnapshots(): ReadonlyArray<TurnSnapshot>;
5585
- /** Delegates to the inner {@link ChatDriver} — interactions resolve there, so it holds the buffer. */
5586
- getExternalDiagnostics(): ReadonlyArray<DiagnosticEntry>;
6029
+ private static createInner;
5587
6030
  getSuggestions(history: ChatMessage[], prompt: string, count: number, allAgentInfo?: AllAgentSummary[]): Promise<string[]>;
5588
- sendMessage(input: string, attachments?: ChatAttachment[]): Promise<ChatDriverResult>;
6031
+ sendMessage(input: string, attachments?: ChatAttachment[], options?: SendMessageOptions): Promise<ChatDriverResult>;
5589
6032
  private runOrchestratedTurn;
5590
- continueFromHistory(transientPrimer?: ChatMessage[], options?: ContinueFromHistoryOptions): Promise<ChatDriverResult>;
5591
- /** {@inheritDoc AiDriver.primeRestoredAgentState} */
5592
- primeRestoredAgentState(snapshots: Record<string, unknown>): void;
5593
6033
  /** {@inheritDoc AiDriver.canRestoreFlowOwner} */
5594
6034
  canRestoreFlowOwner(agentName: string): boolean;
5595
6035
  /** {@inheritDoc AiDriver.canResumeRestoredFlow} */
@@ -5601,6 +6041,10 @@ export declare class OrchestratingDriver extends EventTarget implements AiDriver
5601
6041
  * to classify, and a restored lock already says which agent owns the flow. `continueFromHistory`
5602
6042
  * on its own would not do — it neither routes nor installs, so it would run on whatever agent
5603
6043
  * happened to be installed (none, straight after a reload).
6044
+ *
6045
+ * Looks the owner up in its own agents list, so the `agent` argument is not needed and is
6046
+ * ignored; and does not delegate to the inner driver's resume, which would install the agent
6047
+ * undecorated.
5604
6048
  */
5605
6049
  resumeRestoredFlow(resumeNote?: string): Promise<ChatDriverResult | undefined>;
5606
6050
  /**
@@ -5609,13 +6053,11 @@ export declare class OrchestratingDriver extends EventTarget implements AiDriver
5609
6053
  * Two cases, because routing has two modes and they need opposite answers.
5610
6054
  */
5611
6055
  getContextReserve(): ContextReserveResolution | undefined;
5612
- /** {@inheritDoc AiDriver.getActiveAgent} */
5613
- getActiveAgent(): AgentConfig | undefined;
5614
6056
  private installAgent;
5615
6057
  /**
5616
- * Release the current stateful agent: fire `onDeactivate`, clear the
5617
- * flow-owner lock, dispatch events so the host (and Redux) reflect the
5618
- * unlocked state. Called automatically when a tool handler invokes
6058
+ * Release the current stateful agent: fire `onDeactivate` and clear the flow-owner lock. The
6059
+ * inner driver raises the events from the session's transition, so the host (and Redux) reflect
6060
+ * the unlocked state (GENC-1485). Called automatically when a tool handler invokes
5619
6061
  * `context.releaseAgent`.
5620
6062
  *
5621
6063
  * The user-pin (`pinnedAgentName`) is intentionally *not* cleared — a user
@@ -6022,6 +6464,25 @@ export declare type RoutingDecision =
6022
6464
  /** A pin or an active flow owned the turn; the classifier was skipped. */
6023
6465
  | 'pinned';
6024
6466
 
6467
+ /**
6468
+ * Options for `AiDriver.sendMessage` (GENC-1660).
6469
+ *
6470
+ * @beta
6471
+ */
6472
+ export declare interface SendMessageOptions {
6473
+ /**
6474
+ * Send the message on the user's behalf, as this decorator (e.g. `'autopilot'`). The platform
6475
+ * stamps it on the stored message as `delegate`, so it renders as the assistant and the model
6476
+ * reads it framed.
6477
+ */
6478
+ delegate?: string;
6479
+ /**
6480
+ * The phrase the model reads in front of a delegated message. Defaults to
6481
+ * {@link DEFAULT_DELEGATE_FRAMING}. Ignored unless `delegate` is set.
6482
+ */
6483
+ delegateFraming?: string;
6484
+ }
6485
+
6025
6486
  /**
6026
6487
  * `detail` of the `AiAssistantEvent.SessionCleared` event. Captured *before*
6027
6488
  * teardown so a host can tidy up whatever the active agent was working on