@genesislcap/ai-assistant 15.86.1 → 15.87.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 (84) hide show
  1. package/dist/ai-assistant.api.json +5026 -645
  2. package/dist/ai-assistant.d.ts +802 -0
  3. package/dist/chat-driver.cjs +1487 -132
  4. package/dist/chat-driver.cjs.map +4 -4
  5. package/dist/chat-driver.mjs +1480 -132
  6. package/dist/chat-driver.mjs.map +4 -4
  7. package/dist/custom-elements.json +2779 -657
  8. package/dist/dts/autopilot/autopilot-session.d.ts +25 -0
  9. package/dist/dts/autopilot/autopilot-session.d.ts.map +1 -1
  10. package/dist/dts/chat-driver-node.d.ts +2 -0
  11. package/dist/dts/chat-driver-node.d.ts.map +1 -1
  12. package/dist/dts/components/ai-driver/ai-driver.d.ts +15 -0
  13. package/dist/dts/components/ai-driver/ai-driver.d.ts.map +1 -1
  14. package/dist/dts/components/ai-driver/base-driver-decorator.d.ts +6 -0
  15. package/dist/dts/components/ai-driver/base-driver-decorator.d.ts.map +1 -1
  16. package/dist/dts/components/chat-driver/chat-driver.d.ts +7 -0
  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 +12 -0
  19. package/dist/dts/components/chat-driver/interaction-controller.d.ts.map +1 -1
  20. package/dist/dts/headless/describe-interaction.d.ts +17 -0
  21. package/dist/dts/headless/describe-interaction.d.ts.map +1 -0
  22. package/dist/dts/headless/headless-debug.d.ts +28 -0
  23. package/dist/dts/headless/headless-debug.d.ts.map +1 -0
  24. package/dist/dts/headless/headless-persistence.d.ts +35 -0
  25. package/dist/dts/headless/headless-persistence.d.ts.map +1 -0
  26. package/dist/dts/headless/headless-session.d.ts +180 -0
  27. package/dist/dts/headless/headless-session.d.ts.map +1 -0
  28. package/dist/dts/headless/headless.types.d.ts +435 -0
  29. package/dist/dts/headless/headless.types.d.ts.map +1 -0
  30. package/dist/dts/headless/index.d.ts +5 -0
  31. package/dist/dts/headless/index.d.ts.map +1 -0
  32. package/dist/dts/headless-server/compact.d.ts +52 -0
  33. package/dist/dts/headless-server/compact.d.ts.map +1 -0
  34. package/dist/dts/headless-server/index.d.ts +23 -0
  35. package/dist/dts/headless-server/index.d.ts.map +1 -0
  36. package/dist/dts/headless-server/server.d.ts +13 -0
  37. package/dist/dts/headless-server/server.d.ts.map +1 -0
  38. package/dist/dts/headless-server/types.d.ts +210 -0
  39. package/dist/dts/headless-server/types.d.ts.map +1 -0
  40. package/dist/dts/index.d.ts +2 -0
  41. package/dist/dts/index.d.ts.map +1 -1
  42. package/dist/dts/main/main.d.ts.map +1 -1
  43. package/dist/dts/state/debug-event-log.d.ts +1 -1
  44. package/dist/dts/state/debug-event-log.d.ts.map +1 -1
  45. package/dist/dts/state/decision-surface.d.ts +5 -4
  46. package/dist/dts/state/decision-surface.d.ts.map +1 -1
  47. package/dist/dts/state/persistence/debug-log-assembly.d.ts +49 -0
  48. package/dist/dts/state/persistence/debug-log-assembly.d.ts.map +1 -0
  49. package/dist/dts/state/persistence/index.d.ts +1 -0
  50. package/dist/dts/state/persistence/index.d.ts.map +1 -1
  51. package/dist/dts/state/persistence/session-persister.d.ts +7 -0
  52. package/dist/dts/state/persistence/session-persister.d.ts.map +1 -1
  53. package/dist/dts/types/interaction-surface.d.ts +30 -0
  54. package/dist/dts/types/interaction-surface.d.ts.map +1 -1
  55. package/dist/esm/autopilot/autopilot-session.js +31 -16
  56. package/dist/esm/chat-driver-node.js +8 -0
  57. package/dist/esm/components/ai-driver/base-driver-decorator.js +12 -0
  58. package/dist/esm/components/chat-driver/chat-driver.js +8 -0
  59. package/dist/esm/components/chat-driver/interaction-controller.js +66 -0
  60. package/dist/esm/headless/describe-interaction.js +55 -0
  61. package/dist/esm/headless/headless-debug.js +62 -0
  62. package/dist/esm/headless/headless-persistence.js +192 -0
  63. package/dist/esm/headless/headless-session.js +808 -0
  64. package/dist/esm/headless/headless.types.js +1 -0
  65. package/dist/esm/headless/index.js +3 -0
  66. package/dist/esm/headless-server/compact.js +160 -0
  67. package/dist/esm/headless-server/index.js +21 -0
  68. package/dist/esm/headless-server/server.js +746 -0
  69. package/dist/esm/headless-server/types.js +3 -0
  70. package/dist/esm/index.js +3 -0
  71. package/dist/esm/main/main.js +18 -37
  72. package/dist/esm/state/debug-event-log.js +6 -1
  73. package/dist/esm/state/decision-surface.js +75 -48
  74. package/dist/esm/state/persistence/debug-log-assembly.js +69 -0
  75. package/dist/esm/state/persistence/index.js +1 -0
  76. package/dist/esm/state/persistence/session-persister.js +16 -0
  77. package/dist/headless-server.cjs +853 -0
  78. package/dist/headless-server.cjs.map +7 -0
  79. package/dist/headless-server.mjs +819 -0
  80. package/dist/headless-server.mjs.map +7 -0
  81. package/package.json +28 -18
  82. package/scripts/build-headless-server-node.mjs +42 -0
  83. package/scripts/smoke-chat-driver-node.mjs +3 -0
  84. package/scripts/smoke-headless-server-node.mjs +112 -0
@@ -1231,6 +1231,20 @@ export declare interface AiDriver extends EventTarget {
1231
1231
  * @beta
1232
1232
  */
1233
1233
  addInteractionInterceptor?(interceptor: InteractionInterceptor): () => void;
1234
+ /**
1235
+ * Run one of a pending interaction's surface actions as the person: the programmatic equivalent
1236
+ * of clicking the widget, for a host with no DOM to click (GENC-1660). The interaction is
1237
+ * credited to the person (`answeredBy: 'user'`), never to a claimant, and an action that finishes
1238
+ * it settles it.
1239
+ *
1240
+ * Refused as `not-held` when the interaction has ended, or when a claimant holds it — one is not
1241
+ * pushed aside; the person takes it back first, for example by pausing the autopilot. Any other
1242
+ * refusal is as for `hold.invoke`, and nothing runs. Optional, so a third-party
1243
+ * driver need not implement it; every shipped driver does.
1244
+ *
1245
+ * @beta
1246
+ */
1247
+ invokeAsUser?(interactionId: string, action: string, args?: unknown): Promise<InvokeResult>;
1234
1248
  /**
1235
1249
  * Show a widget in the transcript OUTSIDE any tool loop, and resolve with its result
1236
1250
  * (GENC-1660): `requestInteraction` for something that is not a tool handler. How a decorator
@@ -2328,6 +2342,14 @@ export declare interface AutopilotHostState {
2328
2342
  readonly working: boolean;
2329
2343
  }
2330
2344
 
2345
+ /**
2346
+ * The part of an `AutopilotHost` a session uses. `keepPaused` is optional, so a host built before it
2347
+ * still fits; `autopilot('keepPaused')` says so when it is missing.
2348
+ *
2349
+ * @beta
2350
+ */
2351
+ export declare type AutopilotLike = Pick<AutopilotHost, 'state' | 'subscribe' | 'pause' | 'resume' | 'stop'> & Partial<Pick<AutopilotHost, 'keepPaused'>>;
2352
+
2331
2353
  /**
2332
2354
  * The autopilot's mode for the current flow (GENC-1660 §4.10). `'unavailable'`: no autopilot for
2333
2355
  * this flow, or not yet (e.g. no approved brief). `'paused'`: available but not answering.
@@ -2741,6 +2763,11 @@ export declare abstract class BaseDriverDecorator<TInner extends AiDriver = AiDr
2741
2763
  * interactions. A decorator that answers interactions installs its own on `this.inner`.
2742
2764
  */
2743
2765
  addInteractionInterceptor(interceptor: InteractionInterceptor): () => void;
2766
+ /**
2767
+ * Forwarded: the interaction belongs to the driver that opened it. An inner driver that cannot
2768
+ * run actions answers as if the interaction had ended.
2769
+ */
2770
+ invokeAsUser(interactionId: string, action: string, args?: unknown): Promise<InvokeResult>;
2744
2771
  presentInteraction<T = InteractionResult>(componentName: string, data: unknown, options?: InteractionRequestOptions): Promise<T>;
2745
2772
  provideHandlerCapability(name: string, factory: HandlerCapabilityFactory): () => void;
2746
2773
  getContextReserve(): ContextReserveResolution | undefined;
@@ -2833,6 +2860,28 @@ declare type BudgetDetail = NonNullable<Extract<ChatDriverResult, {
2833
2860
  */
2834
2861
  export declare function budgetPercentOf(figures: VendorBudgetFigures): number;
2835
2862
 
2863
+ /**
2864
+ * The current page's diagnostic entries (GENC-1351 §5.8): the debug-log timeline entries
2865
+ * (`message`/`turn`/`event`), the driver's external diagnostics, and one `meta-snapshot` carrying
2866
+ * the export-time `meta` block. The assistant element reassembles these into the live log, and the
2867
+ * persister's forward-capture path diffs them against what has already been appended to the stored
2868
+ * stream. Extracted from the element so a host with no element (the headless session) derives its
2869
+ * log from the same code, not a second copy that could drift.
2870
+ *
2871
+ * DOM-free and framework-free.
2872
+ *
2873
+ * @beta
2874
+ */
2875
+ export declare function buildDiagnosticEntries(input: {
2876
+ driver: AiDriver | undefined;
2877
+ /** The debug-log key the meta events are kept under; none, no events. */
2878
+ stateKey: string | undefined;
2879
+ /** The `meta-snapshot` entry for right now (see `buildMetaSnapshot`). */
2880
+ metaSnapshot: () => DiagnosticEntry;
2881
+ /** The transcript to use when the driver has no raw history: the host's own copy. */
2882
+ messages?: readonly ChatMessage[];
2883
+ }): DiagnosticEntry[];
2884
+
2836
2885
  export { CachePolicy }
2837
2886
 
2838
2887
  /**
@@ -3886,6 +3935,12 @@ export declare class ChatDriver extends EventTarget implements AiDriver {
3886
3935
  * @beta
3887
3936
  */
3888
3937
  addInteractionInterceptor(interceptor: InteractionInterceptor): () => void;
3938
+ /**
3939
+ * {@inheritDoc AiDriver.invokeAsUser}
3940
+ *
3941
+ * @beta
3942
+ */
3943
+ invokeAsUser(interactionId: string, action: string, args?: unknown): Promise<InvokeResult>;
3889
3944
  /**
3890
3945
  * {@inheritDoc AiDriver.presentInteraction}
3891
3946
  *
@@ -4639,6 +4694,36 @@ export declare interface DecisionSpec {
4639
4694
  * handing back is left). Ignored without `freeText`.
4640
4695
  */
4641
4696
  readonly freeTextUnavailable?: () => string | undefined;
4697
+ /**
4698
+ * Extra actions beside the options, for a control the person can use before choosing: a "plan
4699
+ * first" checkbox next to "Business" and "Technical", say. They are the full form's actions
4700
+ * ({@link SurfaceActionSpec}), with the same rules: `description` for the model, `finishes`
4701
+ * (default `false`, so they edit), `unavailable`, `text` or `argsSchema` for what they take, and
4702
+ * `run`, the SAME code the control calls.
4703
+ *
4704
+ * Listed after the options and `select` / `reply`, and run as a full-form action is. An editing
4705
+ * action does not settle the decision, so an option still has to be chosen. They never make a
4706
+ * decision ready on their own: readiness stays the options' rule.
4707
+ *
4708
+ * Names must not collide with an option id or the reserved `select` / `reply` (it throws, as a
4709
+ * duplicate option id does), and one action cannot take both `text` and `argsSchema`.
4710
+ *
4711
+ * @example
4712
+ * ```ts
4713
+ * ctx.exposeDecision({
4714
+ * options: ['Business', 'Technical'],
4715
+ * choose,
4716
+ * actions: {
4717
+ * set_plan_first: {
4718
+ * description: 'Tick or untick "plan first" before choosing.',
4719
+ * argsSchema: { type: 'object', properties: { value: { type: 'boolean' } }, required: ['value'] },
4720
+ * run: (args) => setPlanFirst((args as { value: boolean }).value),
4721
+ * },
4722
+ * },
4723
+ * });
4724
+ * ```
4725
+ */
4726
+ readonly actions?: Readonly<Record<string, SurfaceActionSpec>>;
4642
4727
  /**
4643
4728
  * What a decision needs that the person sees on screen in some other form — e.g.
4644
4729
  * `{ validated: true }`. A getter, so it is read fresh whenever the decision is described.
@@ -4833,6 +4918,69 @@ export declare type DelegatedMessage = ChatMessage & {
4833
4918
  delegate: string;
4834
4919
  };
4835
4920
 
4921
+ /**
4922
+ * One action of a pending interaction, as a model reads it: a SurfaceAction cut to what is
4923
+ * useful to choose by, with the number {@link describeInteraction} gave it. Plain data.
4924
+ *
4925
+ * @beta
4926
+ */
4927
+ export declare interface DescribedAction {
4928
+ /**
4929
+ * The number the action is chosen by, when it is a numbered option: the same number the
4930
+ * autopilot's list gives it, so "1" means the same option to both. Absent on a platform-owned
4931
+ * action (`select`, `reply`) or a named, full-form one, which are chosen by `name`.
4932
+ */
4933
+ readonly n?: number;
4934
+ /** The action's name: what `act` runs when it is not chosen by number. */
4935
+ readonly name: string;
4936
+ /** What the person would read on the button, when it differs from the name. */
4937
+ readonly label?: string;
4938
+ /** What a full-form action does, as its widget wrote it. */
4939
+ readonly description?: string;
4940
+ /** Whether it can be taken now. */
4941
+ readonly enabled: boolean;
4942
+ /** Why it cannot be, when it is not enabled and the widget said. */
4943
+ readonly unavailable?: string;
4944
+ /**
4945
+ * What it takes: `'options'` (`select`: several, by number or label), `'text'` (written words)
4946
+ * or `'fields'` (a JSON object fitting `argsSchema`). Absent: nothing.
4947
+ */
4948
+ readonly args?: 'options' | 'text' | 'fields';
4949
+ /** The shape `fields` must fit, for an action that takes them. */
4950
+ readonly argsSchema?: Readonly<Record<string, unknown>>;
4951
+ /** Whether running it settles the interaction. */
4952
+ readonly finishes: boolean;
4953
+ /** Whether it is a written refinement: one that counts against a step's limit. */
4954
+ readonly refines?: boolean;
4955
+ }
4956
+
4957
+ /**
4958
+ * What the person is being asked, as a compact JSON-serialisable record a model can read and
4959
+ * answer (GENC-1660): the same text the autopilot is sent for the decision (`renderDecision`,
4960
+ * so there is one rendering of a decision, not two), and its actions as data, numbered as that text
4961
+ * numbers them, so "1" means the same option here and there.
4962
+ *
4963
+ * With no surface — a widget with no controller, or one that has not exposed anything yet — there
4964
+ * is nothing to act on: `controller` is `false` (or `true` and not `ready`, while a controller that
4965
+ * will expose a surface has not yet), `actions` is empty, and `text` is the widget as text alone.
4966
+ *
4967
+ * Reads the surface fresh each time, so it describes the widget as it is now.
4968
+ *
4969
+ * @beta
4970
+ */
4971
+ export declare function describeInteraction(input: DescribeInteractionInput): InteractionDescription;
4972
+
4973
+ /**
4974
+ * The input of {@link describeInteraction}: a pending interaction as the driver knows it.
4975
+ *
4976
+ * @beta
4977
+ */
4978
+ export declare interface DescribeInteractionInput {
4979
+ readonly ctx: InteractionContext;
4980
+ readonly componentName: string;
4981
+ readonly data: unknown;
4982
+ }
4983
+
4836
4984
  /**
4837
4985
  * One entry in the diagnostics stream — the debug-log timeline-entry union
4838
4986
  * (`message` / `turn` / `event`, as `getDebugLog()` builds) plus a point-in-time
@@ -7329,6 +7477,588 @@ export declare interface HandOffOutcome {
7329
7477
  */
7330
7478
  export declare type HandOffOutcomeKind = 'completed' | 'released' | 'cleared' | 'agent-removed' | 'state-lost';
7331
7479
 
7480
+ /**
7481
+ * What `act` is given besides the action: the arguments a person would fill in.
7482
+ *
7483
+ * @beta
7484
+ */
7485
+ export declare interface HeadlessActArgs {
7486
+ /** Written words, for an action that takes `text`, such as `reply`. */
7487
+ readonly text?: string;
7488
+ /** Options for `select`, by number or label. */
7489
+ readonly options?: readonly string[];
7490
+ /** A form's fields: an object, or JSON text of one. */
7491
+ readonly fields?: unknown;
7492
+ }
7493
+
7494
+ /**
7495
+ * The result of `act`: the driver's, plus the interaction as it stands when it is still open.
7496
+ *
7497
+ * @beta
7498
+ */
7499
+ export declare type HeadlessActResult = InvokeResult & {
7500
+ /** The interaction after the action, when it is still pending. */
7501
+ readonly description?: InteractionDescription;
7502
+ };
7503
+
7504
+ /**
7505
+ * The current page's debug log: what `HeadlessSession.debugLog()` returns when nothing is
7506
+ * persisted, and the fallback when the stored stream cannot be read.
7507
+ *
7508
+ * @beta
7509
+ */
7510
+ export declare function headlessCurrentDebugLog(driver: AiDriver, stateKey: string, options?: HeadlessDebugOptions): DebugLog;
7511
+
7512
+ /**
7513
+ * What a debug log reports of the host that built it: the `meta` block's agents, state and host.
7514
+ *
7515
+ * @beta
7516
+ */
7517
+ export declare interface HeadlessDebugOptions {
7518
+ /** The configured agents, as the element's `agents` are. */
7519
+ readonly agents?: () => readonly AgentConfig[];
7520
+ /** The host's own debug state, shown as `meta.debug`. */
7521
+ readonly debugState?: () => unknown;
7522
+ /** The host name `meta.host` carries. The element's is `window.location.host`. Default `'headless'`. */
7523
+ readonly host?: string;
7524
+ /**
7525
+ * The active model and its context window, which the element learns from the provider registry's
7526
+ * status; the session has no registry, so the host says. Read each time they are needed.
7527
+ */
7528
+ readonly context?: () => {
7529
+ model?: string;
7530
+ contextLimit?: number;
7531
+ } | undefined;
7532
+ }
7533
+
7534
+ /**
7535
+ * The diagnostic entries for the session so far, from the same `buildDiagnosticEntries` the
7536
+ * browser's element and its persister use.
7537
+ *
7538
+ * @beta
7539
+ */
7540
+ export declare function headlessDiagnosticEntries(driver: AiDriver, stateKey: string, options?: HeadlessDebugOptions): DiagnosticEntry[];
7541
+
7542
+ /**
7543
+ * What a headless session logs, one entry per thing that happened. Every entry has a `seq` (from
7544
+ * 1, rising by one) and an `at` (an ISO time); `wait` is cursored by `seq`.
7545
+ *
7546
+ * @beta
7547
+ */
7548
+ export declare type HeadlessEvent = HeadlessEventBase & (({
7549
+ readonly type: 'decision';
7550
+ } & InteractionDescription & {
7551
+ /** The agents that asked for it, outermost first. */
7552
+ readonly ownerPath?: readonly string[];
7553
+ }) | {
7554
+ readonly type: 'working';
7555
+ readonly interactionId: string;
7556
+ readonly component: string;
7557
+ /** Who holds it; `'user'` when it is the person's but not ready yet. */
7558
+ readonly heldBy: string;
7559
+ } | {
7560
+ readonly type: 'settled';
7561
+ readonly interactionId: string;
7562
+ readonly component: string;
7563
+ /** Who answered it; absent for a timeout, a stop, or one that settled by itself. */
7564
+ readonly answeredBy?: string;
7565
+ /** Set when the widget settled by itself and nobody answered. */
7566
+ readonly resolvedItself?: boolean;
7567
+ /** Set when the session settled it for a widget that settles itself in a browser. */
7568
+ readonly auto?: boolean;
7569
+ /** Set when the host settled it raw, bypassing the widget's actions. */
7570
+ readonly raw?: boolean;
7571
+ } | {
7572
+ readonly type: 'message';
7573
+ /** One line of what the person would see, as the autopilot reads it ("Assistant: ..."). */
7574
+ readonly text: string;
7575
+ /** The line's full length, in characters, when `text` was cut. */
7576
+ readonly chars?: number;
7577
+ } | {
7578
+ readonly type: 'turn';
7579
+ /** The driver's reason, `'done'` for a finished turn; `'error'` when it threw. */
7580
+ readonly reason: string;
7581
+ /** Set when the turn ended in a typed failure rather than completing. */
7582
+ readonly failureReason?: string;
7583
+ /** The assistant's final text for the turn, when it said any. */
7584
+ readonly text?: string;
7585
+ /** The text's full length, in characters, when `text` was cut. */
7586
+ readonly chars?: number;
7587
+ } | {
7588
+ readonly type: 'autopilot';
7589
+ readonly mode: string;
7590
+ readonly status: string;
7591
+ readonly needsUser: boolean;
7592
+ readonly working: boolean;
7593
+ /** Why it is paused, when it said. */
7594
+ readonly reason?: string;
7595
+ } | {
7596
+ readonly type: 'probe';
7597
+ /** What the host's probe reads now. */
7598
+ readonly probe: Readonly<Record<string, unknown>>;
7599
+ /** The keys whose values changed since the last entry. */
7600
+ readonly changed: readonly string[];
7601
+ } | {
7602
+ readonly type: 'error';
7603
+ /** What failed: `'turn'`, `'auto-settle'`, `'probe'`, … */
7604
+ readonly where: string;
7605
+ readonly message: string;
7606
+ });
7607
+
7608
+ /**
7609
+ * The fields every {@link HeadlessEvent} has.
7610
+ *
7611
+ * @beta
7612
+ */
7613
+ export declare interface HeadlessEventBase {
7614
+ readonly seq: number;
7615
+ /** When it was logged, as an ISO time. */
7616
+ readonly at: string;
7617
+ }
7618
+
7619
+ /**
7620
+ * The type of a {@link HeadlessEvent}.
7621
+ *
7622
+ * @beta
7623
+ */
7624
+ export declare type HeadlessEventType = HeadlessEvent['type'];
7625
+
7626
+ /**
7627
+ * The `meta-snapshot` entry for right now, gathered the way the assistant element gathers it
7628
+ * (`buildMetaSnapshot` does the assembly; this reads what it reports): the live agent comes from
7629
+ * the DRIVER, the transcript from its raw history, and the figures from the transcript, so what a
7630
+ * headless host logs is what the browser would. The context window and model, which the element
7631
+ * learns from its provider registry, are the host's to say.
7632
+ *
7633
+ * @beta
7634
+ */
7635
+ export declare function headlessMetaSnapshot(driver: AiDriver, options?: HeadlessDebugOptions): DiagnosticEntry;
7636
+
7637
+ /**
7638
+ * Persistence for a {@link HeadlessSession}, as `headlessPersistence(...)` builds it. Lives apart
7639
+ * from the session so that the session itself, and the Node entry that exports it, never reach the
7640
+ * store, the persister or the framework they use.
7641
+ *
7642
+ * @beta
7643
+ */
7644
+ export declare interface HeadlessPersistence {
7645
+ /** The session key: the file under `sessions/` and the stream under `diag/`. */
7646
+ readonly stateKey: string;
7647
+ attach(host: HeadlessPersistenceHost): HeadlessPersistenceBinding;
7648
+ }
7649
+
7650
+ /**
7651
+ * Persistence for a `HeadlessSession`: it writes exactly what the browser writes — the
7652
+ * `sessions/<key>` snapshot and the `diag/<key>` stream — through the platform's
7653
+ * `SessionPersister` and the host's `SessionPersistenceProvider`, and builds the lifetime debug log
7654
+ * from the same code as the browser's Download.
7655
+ *
7656
+ * Exported from the package's main entry only, NOT from the Node entry (`./chat-driver`): it
7657
+ * reaches the session store, and through it `@genesislcap/foundation-redux`, which are not
7658
+ * Node-clean. The `persister` it makes is the registry's, so a host can restore through
7659
+ * `getPersister(stateKey)`.
7660
+ *
7661
+ * @example
7662
+ * ```ts
7663
+ * const session = new HeadlessSession(driver, {
7664
+ * persistence: headlessPersistence({ provider, stateKey: 'project-1', agents: () => agents }),
7665
+ * });
7666
+ * ```
7667
+ *
7668
+ * @beta
7669
+ */
7670
+ export declare function headlessPersistence(options: HeadlessPersistenceOptions): HeadlessPersistence;
7671
+
7672
+ /**
7673
+ * A session's saving, attached to a driver: it keeps what the persister reads current and asks it
7674
+ * to save when the browser's element would. Built by `HeadlessPersistence.attach`.
7675
+ *
7676
+ * @beta
7677
+ */
7678
+ export declare interface HeadlessPersistenceBinding {
7679
+ /** Note the prompt a person is about to send, for the flow it may start (`flowActivationPrompt`). */
7680
+ notePrompt(text: string): void;
7681
+ /** Save the snapshot and append the diagnostics now, rather than at the next throttled flush. */
7682
+ flush(): Promise<void>;
7683
+ /** The debug log for the whole session, stitched from the stored stream (see `lifetimeDebugLog`). */
7684
+ debugLog(): Promise<DebugLog>;
7685
+ /** Stop watching the driver and cancel pending saves. The saved session is left as it is. */
7686
+ dispose(): void;
7687
+ }
7688
+
7689
+ /**
7690
+ * What a persistence binding is built from: the session's driver, and its debug-log key.
7691
+ *
7692
+ * @beta
7693
+ */
7694
+ export declare interface HeadlessPersistenceHost {
7695
+ readonly driver: AiDriver;
7696
+ readonly sessionKey: string;
7697
+ }
7698
+
7699
+ /**
7700
+ * Options for {@link headlessPersistence}: where to save, and what the debug log says of the host.
7701
+ *
7702
+ * @beta
7703
+ */
7704
+ export declare interface HeadlessPersistenceOptions extends HeadlessDebugOptions {
7705
+ /** The storage backend, as a browser host supplies it. */
7706
+ readonly provider: SessionPersistenceProvider;
7707
+ /** The session key: the file under `sessions/` and the stream under `diag/`. */
7708
+ readonly stateKey: string;
7709
+ }
7710
+
7711
+ /**
7712
+ * What `read` asks for: a view of the widget, or one of the widget's tools (not both).
7713
+ *
7714
+ * @beta
7715
+ */
7716
+ export declare interface HeadlessReadRequest {
7717
+ /** A view's name, from the description's `views`. Absent (with no `tool`): the default read. */
7718
+ readonly view?: string;
7719
+ /** A widget tool's name, from `HeadlessSessionOptions.widgetTools`. */
7720
+ readonly tool?: string;
7721
+ /** The tool's arguments. */
7722
+ readonly args?: Record<string, unknown>;
7723
+ }
7724
+
7725
+ /**
7726
+ * The result of `read`: what was read as text (capped), or why it was refused.
7727
+ *
7728
+ * @beta
7729
+ */
7730
+ export declare type HeadlessReadResult = {
7731
+ readonly ok: true;
7732
+ readonly content: string;
7733
+ readonly error?: never;
7734
+ } | {
7735
+ readonly ok: false;
7736
+ readonly content?: never;
7737
+ readonly error: string;
7738
+ };
7739
+
7740
+ /**
7741
+ * The result of a call that may be refused: the reason, as words, in `error`.
7742
+ *
7743
+ * @beta
7744
+ */
7745
+ export declare type HeadlessResult = {
7746
+ readonly ok: true;
7747
+ readonly error?: never;
7748
+ } | {
7749
+ readonly ok: false;
7750
+ readonly error: string;
7751
+ };
7752
+
7753
+ /**
7754
+ * What `send` may carry besides the words.
7755
+ *
7756
+ * @beta
7757
+ */
7758
+ export declare interface HeadlessSendOptions {
7759
+ readonly attachments?: ChatAttachment[];
7760
+ /** Route the turn to this agent, as `SendMessageOptions.agent` does. */
7761
+ readonly agent?: string;
7762
+ }
7763
+
7764
+ /**
7765
+ * A driver with no screen: a way for a host with no browser (a coding agent behind a small HTTP
7766
+ * server, a test) to run a whole assistant journey as the person (GENC-1660).
7767
+ *
7768
+ * It watches the driver for interactions and turns the conversation into an append-only log of
7769
+ * plain-data events (see {@link HeadlessEvent}): `decision` when the person has something to
7770
+ * answer, `working` when someone else has it, `settled`, the visible `message`s, the end of each
7771
+ * `turn`, the autopilot's state, and the host's own `probe`. The caller reads the log with
7772
+ * {@link HeadlessSession.wait}, a long poll cursored by `seq`, so nothing is lost between calls.
7773
+ * It answers with {@link HeadlessSession.act}, which runs a widget's action as a click would, with
7774
+ * the same numbered options the autopilot is shown.
7775
+ *
7776
+ * It only observes: its interceptor never claims an interaction, so an autopilot on the same
7777
+ * driver works as it always does, and what the session reports as a `decision` is what the autopilot
7778
+ * has handed to the person. Plain classes only: no DOM, no FAST.
7779
+ *
7780
+ * @beta
7781
+ */
7782
+ export declare class HeadlessSession {
7783
+ private readonly driver;
7784
+ private readonly options;
7785
+ private readonly sessionKey;
7786
+ private readonly allowRaw;
7787
+ private readonly clock;
7788
+ private readonly autopilotHost;
7789
+ private readonly events;
7790
+ private seq;
7791
+ private readonly tracked;
7792
+ /** What the session did to an interaction itself, for `settled` to say when the driver reports it. */
7793
+ private readonly origin;
7794
+ private readonly waiters;
7795
+ private readonly teardown;
7796
+ /** How much of the driver's history has been reported as messages. */
7797
+ private seen;
7798
+ /** The `send` in flight, if any. */
7799
+ private turn;
7800
+ /**
7801
+ * The turn that is running, whoever started it, until the driver has been idle for a beat:
7802
+ * `start` is where its messages begin in the history. Its `reason` and `failureReason` are what
7803
+ * ended it, when something said.
7804
+ */
7805
+ private open;
7806
+ /** History length when the last turn closed: where a turn the session did not start begins. */
7807
+ private base;
7808
+ private quiesceTimer;
7809
+ private poller;
7810
+ private readonly persistence;
7811
+ private lastProbe;
7812
+ private lastAutopilot;
7813
+ private disposed;
7814
+ constructor(driver: AiDriver, options?: HeadlessSessionOptions);
7815
+ /**
7816
+ * Send the person's message, and start the turn. Returns as soon as the turn has started, not
7817
+ * when it ends: a turn includes every interaction parked on the person, so it can run as long as
7818
+ * the journey. Its end is the `turn` event.
7819
+ *
7820
+ * Refused, never thrown, when the message is empty, or a turn is already running.
7821
+ */
7822
+ send(text: string, options?: HeadlessSendOptions): HeadlessResult;
7823
+ /**
7824
+ * Run one of a pending interaction's actions as the person, as a click would (the answer is
7825
+ * credited `answeredBy: 'user'`). `action` is a number from the description's actions, or an
7826
+ * action's name; `args` carry the text, the options (numbers or labels) or the form's fields it
7827
+ * takes. Refused, with the reason and what is enabled, when a claimant holds the interaction,
7828
+ * the action is unknown or disabled, or its arguments do not fit: nothing runs then.
7829
+ *
7830
+ * The result is the driver's `InvokeResult`, plus `description` of the interaction when it is
7831
+ * still open.
7832
+ */
7833
+ act(interactionId: string, action: string | number, args?: HeadlessActArgs): Promise<HeadlessActResult>;
7834
+ /**
7835
+ * Settle a pending interaction raw, with `result` as the widget would have resolved it,
7836
+ * bypassing its actions and everything they check: an escape hatch for a widget with no
7837
+ * controller, or one that cannot be acted on. Logs `settled` with `raw: true` and records
7838
+ * `headless.raw-resolved`. Refused when `allowRaw` is `false`, when the interaction is not
7839
+ * pending, or when a claimant holds it: as for `act`, the person takes it back first.
7840
+ */
7841
+ resolve(interactionId: string, result: unknown): HeadlessResult;
7842
+ /**
7843
+ * Read from a pending interaction without changing it: one of its views, or (with `tool`) one of
7844
+ * the widget tools given to the session. The text is capped. A view the surface does not list is
7845
+ * refused, naming those it does, as the autopilot's `widget_read` does.
7846
+ */
7847
+ read(interactionId: string, request?: HeadlessReadRequest): Promise<HeadlessReadResult>;
7848
+ /**
7849
+ * Wait for the log to say something, then return what it said. Resolves as soon as an event in
7850
+ * `until` is in the log after `since` (immediately, when one already is), or at `maxWaitMs` with
7851
+ * status `'working'`. Either way it returns every event after `since`, and `nextSeq`, the cursor
7852
+ * for the next call: poll with it and nothing is lost.
7853
+ */
7854
+ wait(request: HeadlessWaitRequest): Promise<HeadlessWaitResult>;
7855
+ /** Every event logged after `since` (default: all the log keeps), without waiting. */
7856
+ eventsSince(since?: number): readonly HeadlessEvent[];
7857
+ /**
7858
+ * What is going on now: whether a turn runs, the interaction the person should answer first (and
7859
+ * the others open behind it), the autopilot, what it has cost, and the host's probe.
7860
+ */
7861
+ state(): HeadlessState;
7862
+ /**
7863
+ * Save the session now: the snapshot, and the diagnostics appended since the last flush, rather
7864
+ * than at the next throttled save. A no-op without `persistence`.
7865
+ */
7866
+ flush(): Promise<void>;
7867
+ /**
7868
+ * The debug log, the document the browser's Download gives. With `persistence`, the log of the
7869
+ * whole session stitched from the stored stream with a fresh `meta-snapshot` (`lifetimeDebugLog`,
7870
+ * the same code); without, the current page's, from `buildDiagnosticEntries`. Never throws.
7871
+ */
7872
+ debugLog(): Promise<DebugLog>;
7873
+ /** Stop the running turn, when the driver can. */
7874
+ stop(): HeadlessResult;
7875
+ /**
7876
+ * Pause, resume or stop the autopilot, when there is one. Pausing hands what it holds to the
7877
+ * person, which then appears as a `decision`.
7878
+ *
7879
+ * `'keepPaused'` is the hand-back banner's "Keep paused": it turns the autopilot's own hand-back
7880
+ * of one interaction into an ordinary pause, so it does not take the question back once it is
7881
+ * answered. `interactionId` names the interaction handed back; omitted, it is the one the
7882
+ * autopilot's own pause is waiting on (`state().autopilot`'s hand-back, the `decision` it left
7883
+ * with the person). Refused, with why, when the autopilot has handed nothing back, when
7884
+ * `interactionId` is not the one it handed back, or when the host cannot keep paused; the host's
7885
+ * own `keepPaused` would do nothing in those cases without saying so.
7886
+ */
7887
+ autopilot(mode: 'pause' | 'resume' | 'stop' | 'keepPaused', interactionId?: string): HeadlessResult;
7888
+ private keepPaused;
7889
+ /** Detach: remove the interceptor and every subscription, and release anyone waiting. */
7890
+ dispose(): void;
7891
+ private listen;
7892
+ private history;
7893
+ /** An interaction opened: watch it. Who holds it is not decided yet, so it is reported later. */
7894
+ private onOpened;
7895
+ /** The driver says an interaction settled, by whatever route. */
7896
+ private onSettled;
7897
+ /** The interaction's context was disposed: if nothing said it settled, say it did. */
7898
+ private onEnded;
7899
+ private settle;
7900
+ private release;
7901
+ /** New messages in the driver's history: report what the person would see of them. */
7902
+ private onHistory;
7903
+ private reportMessages;
7904
+ private onAutopilot;
7905
+ private autopilotSignature;
7906
+ private describe;
7907
+ /**
7908
+ * Report where an interaction stands, when that has changed. A `decision` when the person holds
7909
+ * it and can act; `working` when a claimant holds it or it is not ready yet. A `decision` is
7910
+ * logged again only when its description changed materially: who holds it, whether it is ready
7911
+ * or has a controller, or which actions are enabled. The text and facts alone do not count.
7912
+ */
7913
+ private evaluate;
7914
+ /**
7915
+ * Settle a widget that settles itself in a browser, as it would on mounting. Once, and only when
7916
+ * the person holds it. Returns whether it settled it.
7917
+ */
7918
+ private autoSettle;
7919
+ private readTool;
7920
+ /**
7921
+ * Notice a turn begin or end, whoever started it. The driver being busy (or a `send` in flight)
7922
+ * is a turn; once it has been idle for a beat the turn is over and is reported, once. The beat
7923
+ * covers the gaps inside one turn, such as a hand-off continuing it, which are a microtask long.
7924
+ * A turn that begins the instant another ends, with no idle between, is reported as one.
7925
+ */
7926
+ private observe;
7927
+ /** Report the open turn as ended, unless the driver is busy again. */
7928
+ private closeTurn;
7929
+ /** Without a shared bus nothing says a turn ended, so while one is open the driver is asked. */
7930
+ private startPolling;
7931
+ private stopPolling;
7932
+ private logTurn;
7933
+ private log;
7934
+ private append;
7935
+ private readProbe;
7936
+ /** Read the probe again; a change in any top-level value is a `probe` event. */
7937
+ private checkProbe;
7938
+ private waited;
7939
+ }
7940
+
7941
+ /**
7942
+ * Options for a {@link HeadlessSession}.
7943
+ *
7944
+ * @beta
7945
+ */
7946
+ export declare interface HeadlessSessionOptions {
7947
+ /** The debug-log key its meta events go under: the driver's own. Defaults to `''`. */
7948
+ readonly sessionKey?: string;
7949
+ /** What the host calls itself, recorded with `headless.attached`, e.g. `'cli'`. */
7950
+ readonly label?: string;
7951
+ /**
7952
+ * Widgets that settle themselves in a browser when their element mounts, with no controller
7953
+ * to act on, by widget type: each maps the widget's `data` to the result to settle it with.
7954
+ * When one opens the session settles it with that result (once the open has completed), logs
7955
+ * `settled` with `auto: true`, and never reports it as a `decision`.
7956
+ */
7957
+ readonly autoSettle?: Readonly<Record<string, (data: unknown) => unknown>>;
7958
+ /** The widget tools `read({ tool })` may run, as for the autopilot. */
7959
+ readonly widgetTools?: readonly WidgetTools[];
7960
+ /**
7961
+ * Host state shown in `state()` as `probe`, e.g. its app phase. Read again at every event; a
7962
+ * change in any top-level value is logged as a `probe` event.
7963
+ */
7964
+ readonly probe?: () => Record<string, unknown>;
7965
+ /** Whether `resolve` (settling an interaction raw) is allowed. Default `true`. */
7966
+ readonly allowRaw?: boolean;
7967
+ /**
7968
+ * The autopilot, when the driver handed to the session is not itself one (a decorator wrapped
7969
+ * over it hides it). Default: the driver, when it has the shape of an `AutopilotHost`.
7970
+ */
7971
+ readonly autopilot?: AutopilotLike;
7972
+ /** The time source for `at`, in milliseconds. Default `Date.now`. */
7973
+ readonly clock?: () => number;
7974
+ /**
7975
+ * Where the session is saved, as `headlessPersistence(...)` builds it: the same
7976
+ * `sessions/<key>` snapshot and `diag/<key>` stream the browser writes. Absent: nothing is
7977
+ * saved, and `debugLog()` is the current page's.
7978
+ */
7979
+ readonly persistence?: HeadlessPersistence;
7980
+ /**
7981
+ * What `debugLog()` reports of the host when nothing is persisted (with `persistence` its own
7982
+ * options are used instead).
7983
+ */
7984
+ readonly debug?: HeadlessDebugOptions;
7985
+ /**
7986
+ * The bus the driver was built with (`ChatDriver`'s `activityBus` option), to hear turns end the
7987
+ * moment they do, whoever started them. Without it a turn the session did not start is noticed
7988
+ * by watching the driver's history and polling `isBusy()`, which is the slower route.
7989
+ */
7990
+ readonly activityBus?: Pick<AgenticActivityBus, 'subscribe'>;
7991
+ }
7992
+
7993
+ /**
7994
+ * What a headless session is doing now.
7995
+ *
7996
+ * @beta
7997
+ */
7998
+ export declare interface HeadlessState {
7999
+ /** Whether the driver is running a turn. */
8000
+ readonly busy: boolean;
8001
+ /** The oldest interaction the person holds and can act on, or `null`. */
8002
+ readonly pending: InteractionDescription | null;
8003
+ /** The other open interactions: a claimant's, or not ready yet, or behind the first. */
8004
+ readonly others: readonly PendingSummary[];
8005
+ /** The autopilot's state, when there is one. */
8006
+ readonly autopilot?: {
8007
+ readonly mode: string;
8008
+ readonly status: string;
8009
+ readonly needsUser: boolean;
8010
+ readonly working: boolean;
8011
+ };
8012
+ /** What the conversation has cost so far, in `sumUsage`'s four buckets. */
8013
+ readonly cost: AggregateUsage;
8014
+ /** The host's probe, read now. */
8015
+ readonly probe: Readonly<Record<string, unknown>>;
8016
+ /** The `seq` of the last event logged: `wait`'s cursor. */
8017
+ readonly lastSeq: number;
8018
+ }
8019
+
8020
+ /**
8021
+ * What `wait` takes.
8022
+ *
8023
+ * @beta
8024
+ */
8025
+ export declare interface HeadlessWaitRequest {
8026
+ /**
8027
+ * The cursor: the `seq` of the last event already seen. Events after it are returned. Absent:
8028
+ * from the start of the log.
8029
+ */
8030
+ readonly since?: number;
8031
+ /**
8032
+ * The event types that end the wait. Default: `decision`, `turn`, `error`, and an `autopilot`
8033
+ * entry that `needsUser`. One naming `autopilot` ends it on any autopilot entry.
8034
+ */
8035
+ readonly until?: readonly HeadlessEventType[];
8036
+ /**
8037
+ * The longest to wait, in milliseconds. Cut to what a timer can hold (about 24 days); a value that is
8038
+ * not a number is no wait at all.
8039
+ */
8040
+ readonly maxWaitMs: number;
8041
+ /** Ends the wait early, with status `'working'`, when it aborts: a caller that has gone away. */
8042
+ readonly signal?: AbortSignal;
8043
+ }
8044
+
8045
+ /**
8046
+ * What `wait` returns.
8047
+ *
8048
+ * @beta
8049
+ */
8050
+ export declare interface HeadlessWaitResult {
8051
+ /** Every event after `since`, up to now. */
8052
+ readonly events: readonly HeadlessEvent[];
8053
+ /**
8054
+ * `'ready'`: an event the caller was waiting for is among them. `'working'`: none came in
8055
+ * time. `'closed'`: the session was disposed.
8056
+ */
8057
+ readonly status: 'ready' | 'working' | 'closed';
8058
+ /** The cursor to pass as `since` next time: the `seq` of the last event logged. */
8059
+ readonly nextSeq: number;
8060
+ }
8061
+
7332
8062
  /**
7333
8063
  * A single in-flight per-call chat-input override pushed by a `requestSubAgent`
7334
8064
  * or `requestInteraction` call. Tracked as an array (not a counter) so the
@@ -7577,6 +8307,42 @@ export declare type InteractionControllerFactory<TController = unknown> = (data:
7577
8307
  */
7578
8308
  export declare type InteractionCostEventDetail = ChatInteractionEventsMap['interaction-cost'];
7579
8309
 
8310
+ /**
8311
+ * What a pending interaction needs from the person, as a compact, JSON-serialisable view a model
8312
+ * can read and answer.
8313
+ *
8314
+ * @beta
8315
+ */
8316
+ export declare interface InteractionDescription {
8317
+ readonly interactionId: string;
8318
+ /** The widget type. */
8319
+ readonly component: string;
8320
+ /** Who holds it: `'user'`, or a claimant such as `'autopilot'`. */
8321
+ readonly heldBy: string;
8322
+ /**
8323
+ * Whether the widget has a controller and so a surface to act on. `false`: nothing here can be
8324
+ * run with `act`; `text` is all the widget says, and only a raw `resolve` can settle it.
8325
+ */
8326
+ readonly controller: boolean;
8327
+ /**
8328
+ * Whether the person can act now. A widget with no controller is ready; one with a surface is
8329
+ * ready when it has an enabled finishing action and is not busy working.
8330
+ */
8331
+ readonly ready: boolean;
8332
+ /**
8333
+ * What the autopilot would be sent for it: the same `renderDecision` text (the widget as text,
8334
+ * its views and facts, the numbered actions), or the widget as text alone where there is no
8335
+ * surface.
8336
+ */
8337
+ readonly text: string;
8338
+ /** Every action, in the order the list shows them. Empty with no surface. */
8339
+ readonly actions: readonly DescribedAction[];
8340
+ /** The views `read` takes, each with what it holds. */
8341
+ readonly views?: Readonly<Record<string, string>>;
8342
+ /** The surface's facts, as they stand now. */
8343
+ readonly facts?: Readonly<Record<string, unknown>>;
8344
+ }
8345
+
7580
8346
  export { InteractionEdit }
7581
8347
 
7582
8348
  /**
@@ -7951,6 +8717,30 @@ export declare function isAiAssistantDocked(): boolean;
7951
8717
  */
7952
8718
  export declare const isDelegated: (message: ChatMessage) => message is DelegatedMessage;
7953
8719
 
8720
+ /**
8721
+ * The debug log for the WHOLE session (GENC-1351 §5.8 / §5.10), not just this page's activity:
8722
+ * the persisted diagnostics stream with its stored `meta-snapshot`s replaced by a fresh one
8723
+ * (`withFreshMetaSnapshot`), so its context and cost figures are current. When the provider
8724
+ * stores no diagnostics, there is no key, the stream is empty or loading it fails, it is
8725
+ * `fallback()` — the current-page log. Never throws.
8726
+ *
8727
+ * The one derivation of the lifetime log: the assistant element's `getLifetimeDebugLog` and the
8728
+ * headless session both call it, because a second one drifts, and for this log that means silently
8729
+ * understating spend.
8730
+ *
8731
+ * @beta
8732
+ */
8733
+ export declare function lifetimeDebugLog(input: {
8734
+ provider: SessionPersistenceProvider | undefined;
8735
+ stateKey: string | undefined;
8736
+ /** Land the current page's unflushed diagnostics delta, so the log includes it. */
8737
+ flush: () => Promise<void> | void;
8738
+ /** The `meta-snapshot` entry for right now. */
8739
+ metaSnapshot: () => DiagnosticEntry;
8740
+ /** The current-page log, for when there is no stored stream to stitch. */
8741
+ fallback: () => DebugLog;
8742
+ }): Promise<DebugLog>;
8743
+
7954
8744
  /**
7955
8745
  * The interchangeable "assistant is working" loading-indicator styles. At most
7956
8746
  * one of these may be enabled at a time — enabling one disables the other.
@@ -8342,6 +9132,18 @@ export declare class OrchestratingDriver extends BaseDriverDecorator<ChatDriver>
8342
9132
  private appendInlineMessage;
8343
9133
  }
8344
9134
 
9135
+ /**
9136
+ * Something else pending, besides the one `state().pending` describes.
9137
+ *
9138
+ * @beta
9139
+ */
9140
+ export declare interface PendingSummary {
9141
+ readonly interactionId: string;
9142
+ readonly component: string;
9143
+ readonly heldBy: string;
9144
+ readonly ready: boolean;
9145
+ }
9146
+
8345
9147
  /**
8346
9148
  * Schema version of the persisted session shape. Bump on an incompatible
8347
9149
  * change; a snapshot whose `version` doesn't match is discarded on load rather