@itookit/dsht 0.3.8 → 0.5.2

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 (166) hide show
  1. package/README.i18n.yaml +2 -2
  2. package/README.md +33 -12
  3. package/README.zh.md +35 -14
  4. package/dist/catalog/controller.d.ts +26 -6
  5. package/dist/catalog/controller.js +73 -45
  6. package/dist/catalog/index.d.ts +1 -0
  7. package/dist/cli/dsht.js +206 -18
  8. package/dist/cli/startup.d.ts +40 -0
  9. package/dist/cli/startup.js +314 -0
  10. package/dist/cli/trace-summary.d.ts +78 -0
  11. package/dist/cli/trace-summary.js +241 -0
  12. package/dist/cli/verifier.d.ts +64 -0
  13. package/dist/cli/verifier.js +265 -0
  14. package/dist/contracts.d.ts +359 -0
  15. package/dist/contracts.js +1 -0
  16. package/dist/controller/commands.d.ts +47 -0
  17. package/dist/controller/commands.js +322 -0
  18. package/dist/controller/connection-streams.d.ts +22 -0
  19. package/dist/controller/connection-streams.js +105 -0
  20. package/dist/controller/connection.d.ts +24 -31
  21. package/dist/controller/connection.js +48 -111
  22. package/dist/controller/controller.d.ts +412 -178
  23. package/dist/controller/controller.js +713 -167
  24. package/dist/controller/foreground.d.ts +44 -0
  25. package/dist/controller/foreground.js +79 -0
  26. package/dist/controller/index.d.ts +8 -1
  27. package/dist/controller/index.js +5 -0
  28. package/dist/controller/loop-contract.d.ts +136 -0
  29. package/dist/controller/loop-contract.js +308 -0
  30. package/dist/controller/loop-coordinator.d.ts +48 -0
  31. package/dist/controller/loop-coordinator.js +647 -0
  32. package/dist/controller/loop-prompts-schema.d.ts +56 -0
  33. package/dist/controller/loop-prompts-schema.js +144 -0
  34. package/dist/controller/loop-prompts.d.ts +55 -0
  35. package/dist/controller/loop-prompts.generated.d.ts +104 -0
  36. package/dist/controller/loop-prompts.generated.js +185 -0
  37. package/dist/controller/loop-prompts.js +104 -0
  38. package/dist/controller/loop-protocols.d.ts +39 -0
  39. package/dist/controller/loop-protocols.js +115 -0
  40. package/dist/controller/loop.d.ts +275 -0
  41. package/dist/controller/loop.js +378 -0
  42. package/dist/controller/prompts.d.ts +54 -0
  43. package/dist/controller/prompts.js +162 -0
  44. package/dist/controller/trace-log.d.ts +45 -0
  45. package/dist/controller/trace-log.js +144 -0
  46. package/dist/controller/verifier.d.ts +130 -0
  47. package/dist/controller/verifier.js +75 -0
  48. package/dist/cost/controller.d.ts +1 -1
  49. package/dist/cost/controller.js +12 -5
  50. package/dist/cost/index.d.ts +1 -1
  51. package/dist/cost/index.js +1 -1
  52. package/dist/cost/ledger.d.ts +0 -1
  53. package/dist/cost/ledger.js +0 -1
  54. package/dist/cost/scanner.js +1 -0
  55. package/dist/json.d.ts +18 -0
  56. package/dist/json.js +19 -0
  57. package/dist/references.d.ts +25 -0
  58. package/dist/references.js +26 -0
  59. package/dist/session/connection-view.d.ts +2 -11
  60. package/dist/session/controller.d.ts +94 -105
  61. package/dist/session/controller.js +262 -536
  62. package/dist/session/history-reader.d.ts +32 -0
  63. package/dist/session/history-reader.js +170 -0
  64. package/dist/session/history.d.ts +6 -18
  65. package/dist/session/history.js +1 -24
  66. package/dist/session/index.d.ts +9 -4
  67. package/dist/session/index.js +7 -3
  68. package/dist/session/info.d.ts +20 -82
  69. package/dist/session/info.js +52 -25
  70. package/dist/session/interactions.d.ts +26 -0
  71. package/dist/session/interactions.js +75 -0
  72. package/dist/session/markdown.js +1 -1
  73. package/dist/session/math.js +1 -1
  74. package/dist/session/mutation-gate.d.ts +51 -0
  75. package/dist/session/mutation-gate.js +73 -0
  76. package/dist/session/navigation.d.ts +2 -89
  77. package/dist/session/navigation.js +2 -129
  78. package/dist/session/navigator.d.ts +47 -0
  79. package/dist/session/navigator.js +158 -0
  80. package/dist/session/peek.d.ts +38 -0
  81. package/dist/session/peek.js +103 -0
  82. package/dist/session/prompt-backfill.d.ts +23 -0
  83. package/dist/session/prompt-backfill.js +88 -0
  84. package/dist/session/references.d.ts +2 -20
  85. package/dist/session/references.js +1 -26
  86. package/dist/session/runtime.d.ts +26 -0
  87. package/dist/session/runtime.js +28 -0
  88. package/dist/session/state.d.ts +20 -0
  89. package/dist/session/state.js +1 -0
  90. package/dist/session/telemetry.d.ts +25 -17
  91. package/dist/session/telemetry.js +66 -60
  92. package/dist/session/transcript.d.ts +5 -7
  93. package/dist/session/transcript.js +2 -15
  94. package/dist/session/types.d.ts +25 -0
  95. package/dist/session/types.js +0 -1
  96. package/dist/session-title.d.ts +9 -0
  97. package/dist/session-title.js +21 -0
  98. package/dist/shell/controller.d.ts +31 -1
  99. package/dist/shell/controller.js +34 -2
  100. package/dist/shell/index.d.ts +3 -3
  101. package/dist/shell/index.js +2 -2
  102. package/dist/shell/runner.d.ts +10 -0
  103. package/dist/shell/runner.js +48 -9
  104. package/dist/slash/index.d.ts +10 -0
  105. package/dist/slash/index.js +7 -0
  106. package/dist/slash/parse.d.ts +42 -0
  107. package/dist/slash/parse.js +259 -0
  108. package/dist/slash/pipeline.d.ts +140 -0
  109. package/dist/slash/pipeline.js +115 -0
  110. package/dist/slash/registry.d.ts +88 -0
  111. package/dist/slash/registry.js +177 -0
  112. package/dist/slash/types.d.ts +126 -0
  113. package/dist/slash/types.js +1 -0
  114. package/dist/state.d.ts +16 -18
  115. package/dist/state.js +4 -3
  116. package/dist/text.d.ts +28 -0
  117. package/dist/text.js +55 -0
  118. package/dist/transport/client.d.ts +4 -3
  119. package/dist/transport/client.js +71 -25
  120. package/dist/transport/events.d.ts +104 -0
  121. package/dist/transport/events.js +149 -0
  122. package/dist/transport/wire.d.ts +9 -17
  123. package/dist/transport/wire.js +2 -27
  124. package/dist/ui/app.js +750 -550
  125. package/dist/ui/chat/header.js +1 -1
  126. package/dist/ui/chat/history-view.d.ts +1 -1
  127. package/dist/ui/chat/loop-status.d.ts +11 -0
  128. package/dist/ui/chat/loop-status.js +28 -0
  129. package/dist/ui/chat/navigation-model.d.ts +86 -0
  130. package/dist/ui/chat/navigation-model.js +107 -0
  131. package/dist/ui/chat/shell-view.d.ts +17 -2
  132. package/dist/ui/chat/shell-view.js +45 -3
  133. package/dist/ui/chat/status.d.ts +47 -3
  134. package/dist/ui/chat/status.js +65 -50
  135. package/dist/ui/chat/use-history-view.d.ts +69 -0
  136. package/dist/ui/chat/use-history-view.js +123 -0
  137. package/dist/ui/chat/viewport.d.ts +1 -1
  138. package/dist/ui/dialogs/cost.d.ts +21 -4
  139. package/dist/ui/dialogs/cost.js +7 -12
  140. package/dist/ui/dialogs/index.d.ts +22 -5
  141. package/dist/ui/dialogs/index.js +19 -3
  142. package/dist/ui/dialogs/loop.d.ts +43 -0
  143. package/dist/ui/dialogs/loop.js +224 -0
  144. package/dist/ui/dialogs/peek.d.ts +25 -0
  145. package/dist/ui/dialogs/peek.js +35 -0
  146. package/dist/ui/dialogs/picker.d.ts +2 -0
  147. package/dist/ui/dialogs/picker.js +4 -2
  148. package/dist/ui/dialogs/use-panels.d.ts +53 -0
  149. package/dist/ui/dialogs/use-panels.js +51 -0
  150. package/dist/ui/input/mouse.d.ts +12 -2
  151. package/dist/ui/input/mouse.js +20 -7
  152. package/dist/ui/input/references.d.ts +1 -1
  153. package/dist/ui/input/use-composer.d.ts +35 -0
  154. package/dist/ui/input/use-composer.js +109 -0
  155. package/dist/ui/input/use-deferred-lines.d.ts +16 -0
  156. package/dist/ui/input/use-deferred-lines.js +54 -0
  157. package/dist/ui/input/use-history-recall.d.ts +20 -0
  158. package/dist/ui/input/use-history-recall.js +47 -0
  159. package/dist/ui/status/model.d.ts +7 -0
  160. package/dist/ui/status/model.js +5 -0
  161. package/dist/ui/theme/index.d.ts +1 -1
  162. package/package.json +6 -4
  163. package/dist/ui/commands/parse.d.ts +0 -104
  164. package/dist/ui/commands/parse.js +0 -135
  165. package/dist/ui/commands/registry.d.ts +0 -33
  166. package/dist/ui/commands/registry.js +0 -73
@@ -1,33 +1,211 @@
1
- /** Application facade: composes the connection, session, catalog and cost domains. */
2
1
  import { Client } from '../transport/client.ts';
3
- import { type Json, type ObjectValue } from '../transport/wire.ts';
2
+ import { type ObjectValue } from '../transport/wire.ts';
3
+ import type { HostEvent } from '../transport/events.ts';
4
4
  import { type HistoryLimits } from '../session/memory.ts';
5
+ import { type SessionRender } from '../session/history.ts';
5
6
  import { SessionController } from '../session/controller.ts';
6
7
  import { CatalogController } from '../catalog/controller.ts';
7
- import type { Telemetry } from '../session/telemetry.ts';
8
+ import type { TelemetryReader } from '../session/telemetry.ts';
8
9
  import type { Transcript } from '../session/transcript.ts';
9
10
  import type { CostLedger } from '../cost/ledger.ts';
10
11
  import { CostController } from '../cost/controller.ts';
11
12
  import { ConnectionController, type ConnectionListener } from './connection.ts';
12
13
  import { MemoryLog } from './memory-log.ts';
14
+ import { TraceLog } from './trace-log.ts';
15
+ import { PromptStore } from './prompts.ts';
16
+ import { type LoopLimits, type LoopProtocol } from './loop.ts';
17
+ import type { VerifierPort } from './verifier.ts';
18
+ import type { ClientActivity, ForegroundKind, ForegroundSnapshot, LoopProgress, LoopRecord, OutputSource, PeekSnapshot } from '../contracts.ts';
19
+ import { SessionPeek } from '../session/peek.ts';
13
20
  import { type ControllerStore, type State } from '../state.ts';
14
21
  import { ShellController } from '../shell/index.ts';
15
- import type { HistorySearch, RemovalTarget } from '../session/types.ts';
16
- import type { ComposerState, InteractionState, ModelState, OptionState, PanelState, ReferenceState, ViewState } from '../session/info.ts';
22
+ import type { HistorySearch, AnswerValue, RemovalTarget } from '../session/types.ts';
23
+ import type { SavedPrompt } from '../contracts.ts';
24
+ import type { FileReference } from '../session/references.ts';
25
+ import type { InteractionState, OptionState } from '../session/info.ts';
17
26
  import type { Reasoning } from '../session/history.ts';
27
+ /** Mutating operations: foreground work, local edits, and control cancellation with its own admission. */
28
+ export interface Actions {
29
+ /** Claim the single foreground slot for work the front end orchestrates itself (paging, loading).
30
+ *
31
+ * The controller owns the slot, the abort controller and the identity; the front end only supplies
32
+ * the work and renders `queries.foreground`. Returns undefined when the client is busy with another
33
+ * operation or the client has stopped. Admitted work keeps its result/error on cancellation.
34
+ */
35
+ foreground<T>(kind: ForegroundKind, label: string, work: (signal: AbortSignal) => Promise<T>, wait?: boolean): Promise<T | undefined>;
36
+ /** Cancel the operation that owns the slot; false when none is running. */
37
+ cancelForeground(): boolean;
38
+ /** Open one output source read-only, at full screen; unknown ids are ignored. */
39
+ openPeek(id: string): void;
40
+ /** Close the read-only view and release whatever it was following. */
41
+ closePeek(): void;
42
+ switchWorkspace(workspaceId?: string): Promise<boolean>;
43
+ switchSession(query?: string): Promise<boolean>;
44
+ selectSession(sessionId: string): Promise<boolean>;
45
+ createWorkspace(path: string): Promise<boolean>;
46
+ createSession(): Promise<boolean>;
47
+ /** Create a named session without selecting it; used by a forked verifier. */
48
+ createVerifierSession(title: string): Promise<string | undefined>;
49
+ /** Stop a verifier session's turn on the host without selecting it. */
50
+ cancelVerifierSession(sessionId: string): Promise<boolean>;
51
+ showPicker(screen: 'workspaces' | 'sessions'): Promise<boolean>;
52
+ removeTarget(target: RemovalTarget): Promise<boolean>;
53
+ removalTarget(kind: 'workspace' | 'session', query: string): Promise<RemovalTarget | undefined>;
54
+ waitForHistory(signal: AbortSignal): Promise<boolean>;
55
+ searchSessions(query: string, workspaceOnly: boolean, signal: AbortSignal): Promise<{
56
+ items: ObjectValue[];
57
+ hasMore: boolean;
58
+ } | undefined>;
59
+ searchHistory(query: string, signal: AbortSignal): Promise<HistorySearch | undefined>;
60
+ prompt(text: string): Promise<boolean>;
61
+ /** Clear this client's HANDOFF.md, then ask the agent to write a fresh handoff there. */
62
+ handoff(): Promise<boolean>;
63
+ /** Start any client-driven scored loop and send its first step. */
64
+ startLoop(protocol: LoopProtocol, limits: LoopLimits): Promise<boolean>;
65
+ /** Stop a running loop; the terminal progress stays visible for the reader. */
66
+ stopLoop(): void;
67
+ /** Drop a finished run's progress line; a run that is still active is left alone. */
68
+ clearLoopResult(): void;
69
+ /** Answer a paused run: re-judge the current artifact with what the operator supplied. */
70
+ answerLoop(text: string): Promise<boolean>;
71
+ cancelTurn(): Promise<boolean>;
72
+ answer(value: AnswerValue): Promise<boolean>;
73
+ /** Answer the current sub-question of the pending set, advancing the waterfall or sending it. */
74
+ answerQuestion(input?: {
75
+ selected?: readonly string[];
76
+ custom?: string;
77
+ }): Promise<boolean>;
78
+ approve(allowed: boolean): Promise<boolean>;
79
+ dismissQuestion(): Promise<boolean>;
80
+ /** Repeated keys share one cancellation; it reports exit eligibility itself. */
81
+ interrupt(force?: boolean): Promise<boolean>;
82
+ older(signal?: AbortSignal, transcript?: Transcript): Promise<boolean>;
83
+ openHistory(target: number, signal: AbortSignal): Promise<boolean>;
84
+ historyThrough(target: number | 'first', signal: AbortSignal): Promise<boolean>;
85
+ removeQueued(itemId: string): Promise<boolean>;
86
+ /** Local shortcut prompts: no connection and no busy envelope, since they never reach the host. */
87
+ savePrompt(text: string): Promise<boolean>;
88
+ updatePrompt(id: string, text: string): Promise<boolean>;
89
+ deletePrompt(id: string): Promise<boolean>;
90
+ command(line: string, signal: AbortSignal): Promise<string | undefined>;
91
+ exportLog(path: string | undefined, signal: AbortSignal): Promise<string | undefined>;
92
+ exportHtml(path: string | undefined, signal: AbortSignal): Promise<string | undefined>;
93
+ selectModel(provider: string, model: string, reasoningEffort?: string): Promise<boolean>;
94
+ modelCatalog(): Promise<ObjectValue | undefined>;
95
+ refreshCosts(signal?: AbortSignal): Promise<boolean>;
96
+ /** Local, immediate setters: no request, so they keep the synchronous contract. */
97
+ loadPresetNames(): void;
98
+ /** Drop the internal last failure, once the fact has been reported elsewhere. */
99
+ clearFailure(): void;
100
+ enterPath(): void;
101
+ pickWorkspace(workspaceId?: string): void;
102
+ /** Leave a picker and return to the selected conversation; false when none is selected. */
103
+ showChat(): boolean;
104
+ showLatest(): void;
105
+ pinHistory(pinned: boolean): void;
106
+ setAnswers(answers: Record<string, AnswerValue['answers']>): void;
107
+ setOption(option?: OptionState): void;
108
+ setApproval(approval?: InteractionState['approval']): void;
109
+ recordRecall(value: string): void;
110
+ resetRecall(): void;
111
+ refillRecall(): boolean;
112
+ heapSnapshot(tag?: string): string;
113
+ }
114
+ /** Read-only operations the UI drives; none of them changes observable state. */
115
+ export interface Queries {
116
+ readonly running: boolean;
117
+ /** Turns the selected session has finished since this client connected. */
118
+ readonly turnsCompleted: number;
119
+ /** Whether a forked verifier is available to score rounds. */
120
+ readonly forkedVerification: boolean;
121
+ /** Whether this client's own reply block may decide an attempt: no verifier, or the fallback is on. */
122
+ readonly selfScoring: boolean;
123
+ /** Whether this connection generation finished its startup work and is safe to drive. */
124
+ readonly connectionSettled: boolean;
125
+ readonly sessionName: string | undefined;
126
+ readonly sessionMode: string | undefined;
127
+ readonly workingSince: number | undefined;
128
+ readonly visibleSessions: ObjectValue[];
129
+ readonly record: Transcript;
130
+ readonly window: Transcript | undefined;
131
+ readonly interaction: InteractionState;
132
+ readonly telemetry: TelemetryReader;
133
+ readonly recallAtOldest: boolean;
134
+ readonly recallLength: number;
135
+ readonly recallHasOlder: boolean;
136
+ /** Shortcut prompts the operator saved, oldest first. */
137
+ readonly prompts: readonly SavedPrompt[];
138
+ /** Live progress of the selected session's design review, when one has run. */
139
+ readonly loop: LoopProgress | undefined;
140
+ /** What the client is working on now, already merged across the host turn and any running loop. */
141
+ readonly activity: ClientActivity | undefined;
142
+ /** The one operation that owns the client, when one does; the view renders its label and clock. */
143
+ readonly foreground: ForegroundSnapshot | undefined;
144
+ /** Every readable output source this client knows: verifier sessions, `!` runs, host children. */
145
+ readonly sources: readonly OutputSource[];
146
+ /** The read-only view's content, when one is open; undefined while it is closed. */
147
+ readonly peek: PeekSnapshot | undefined;
148
+ /** Every `loop.yaml` record, so the picker can offer names and their defaults without a lookup. */
149
+ readonly loopRecords: readonly LoopRecord[];
150
+ /** Why the saved prompts could not be read, when the file was malformed. */
151
+ readonly promptsError: string | undefined;
152
+ pendingCounts(): ReadonlyMap<string, number>;
153
+ recall(direction: -1 | 1, current: string): string;
154
+ references(query: string, signal: AbortSignal): Promise<FileReference[]>;
155
+ /** Plain rows and offsets for one laid-out record. */
156
+ render(input: {
157
+ transcript: Transcript;
158
+ width: number;
159
+ folds: ReadonlySet<number>;
160
+ liveReasoning: Reasoning;
161
+ }): SessionRender;
162
+ }
163
+ /** Everything one `Controller` needs, named so a new capability never shifts an argument position.
164
+ *
165
+ * `base` is the only required field: a local or offline client still has an address to show, while
166
+ * every other capability — authentication, billing, budgets, local shell, shortcut prompts — is
167
+ * opted into by supplying its own field.
168
+ */
169
+ export interface ControllerOptions {
170
+ /** Host base URL. */
171
+ base: string;
172
+ /** Token for the first authentication; absent when a saved cookie already authenticates. */
173
+ token?: string;
174
+ /** Session to open once connected, instead of starting on the picker. */
175
+ initialSession?: string;
176
+ /** Builds one connection client; defaults to a plain `Client` for `base`. */
177
+ makeClient?: () => Client;
178
+ /** Authenticates one connection client; defaults to the supplied token. */
179
+ authenticate?: (client: Client) => Promise<void>;
180
+ /** Billing ledger; absent disables every cost feature. */
181
+ costs?: CostLedger;
182
+ /** History retention budgets. */
183
+ historyLimits?: HistoryLimits;
184
+ /** Runtime memory log path; absent disables the log. */
185
+ memoryLogPath?: string;
186
+ /** Connection, screen and selection trace path; absent disables the log. */
187
+ tracePath?: string;
188
+ /** Directory this client runs in, offered as a workspace the host has not registered. */
189
+ localDirectory?: string;
190
+ /** Whether `!` may run local commands; the CLI disables it with `--no-shell`. */
191
+ shellEnabled?: boolean;
192
+ /** File holding the operator's shortcut prompts; absent keeps them in memory for this run. */
193
+ promptsPath?: string;
194
+ /** Independent verifier for scored rounds; absent keeps verification inside the reviewed session. */
195
+ verifier?: VerifierPort;
196
+ /** Allow a reply block to decide when the verifier is unavailable; the progress line says so. */
197
+ allowSelfFallback?: boolean;
198
+ /** Client-side root for verdict files; defaults to the workspace this client runs in. */
199
+ verdictRoot?: string;
200
+ /** Whole-run budget in milliseconds; when it expires the run stops as `deadline`. */
201
+ deadlineMs?: number;
202
+ }
18
203
  /** Application facade over the domain controllers; the UI owns only this object.
19
204
  *
20
205
  * State lives here, connection generations live in `connection`, the selected session and its
21
206
  * history live in `session`, model metadata lives in `catalog`, and billing lives in `cost`.
22
207
  */
23
208
  export declare class Controller implements ControllerStore, ConnectionListener {
24
- readonly base: string;
25
- private readonly initialSession?;
26
- readonly costs?: CostLedger | undefined;
27
- readonly historyLimits: HistoryLimits;
28
- readonly memoryLogPath?: string | undefined;
29
- /** Directory this client runs in, offered as a workspace when the host has not registered it. */
30
- readonly localDirectory: string;
31
209
  state: State;
32
210
  /** Physical connection, retry loop and projection store. */
33
211
  readonly connection: ConnectionController;
@@ -39,23 +217,58 @@ export declare class Controller implements ControllerStore, ConnectionListener {
39
217
  readonly cost: CostController | undefined;
40
218
  /** Bounded runtime memory samples; present only when a log path was supplied. */
41
219
  readonly memoryLog: MemoryLog | undefined;
220
+ /** Bounded connection, screen and selection trace; present only when a path was supplied. */
221
+ readonly trace: TraceLog | undefined;
222
+ /** Shortcut prompts the operator saved; in memory for this run when no path was supplied. */
223
+ readonly promptStore: PromptStore;
224
+ /** Finished turns of the selected session, so a waiter never has to sample a cached flag. */
225
+ private completedTurns;
226
+ /** Sessions the host reported busy, so a lone idle frame cannot claim a finished turn. */
227
+ private readonly busySessions;
228
+ /** Loop execution owns all verifier, settling and deadline state. */
229
+ private readonly loops;
42
230
  /** Local `!` commands, run on this machine and shown inline in the transcript. */
43
231
  readonly shell: ShellController;
232
+ /** Mutating surface the UI drives. */
233
+ readonly actions: Actions;
234
+ /** Read-only surface the UI drives. */
235
+ readonly queries: Queries;
236
+ /** Host base URL this client talks to. */
237
+ readonly base: string;
238
+ /** Billing ledger supplied at construction, when any. */
239
+ readonly costs: CostLedger | undefined;
240
+ /** History retention budgets in force. */
241
+ readonly historyLimits: HistoryLimits;
242
+ /** Runtime memory log path, when one was configured. */
243
+ readonly memoryLogPath: string | undefined;
244
+ /** Directory this client runs in. */
245
+ readonly localDirectory: string;
246
+ /** Session opened at startup, when one was named. */
247
+ private readonly initialSession;
44
248
  private readonly observers;
45
249
  private selector;
46
- constructor(base: string, token: string | undefined, initialSession?: string | undefined, makeClient?: () => Client, authenticate?: (client: Client) => Promise<void>, costs?: CostLedger | undefined, historyLimits?: HistoryLimits, memoryLogPath?: string | undefined,
47
- /** Directory this client runs in, offered as a workspace when the host has not registered it. */
48
- localDirectory?: string,
49
- /** Whether `!` may run local commands; the CLI disables it with `--no-shell`. */
50
- shellEnabled?: boolean);
250
+ private connectionSettled;
251
+ /** Startup defaults apply once; subsequent generations restore the operator's selection. */
252
+ private initialized;
253
+ /** Counter behind `commandId`, so every executed line has one identifier in begin and end. */
254
+ private commandSeq;
255
+ /** Scheduling and cancellation are owned independently of domain operations. */
256
+ private readonly foregroundSlot;
257
+ /** Read-only follower for the full-screen view; it borrows the connection and never selects. */
258
+ readonly peek: SessionPeek;
259
+ /** Sources this client created, keyed by session id; the host cannot record that lineage itself. */
260
+ private readonly createdSources;
261
+ /** The source the read-only view is showing, when one is open. */
262
+ private peekId;
263
+ constructor(options: ControllerOptions);
51
264
  /** React-compatible state subscription. */
52
265
  subscribe: (listener: () => void) => (() => void);
53
266
  /** Snapshot identity changes only when the controller publishes. */
54
267
  snapshot: () => State;
55
268
  /** Current projection store; replaced at each connection generation. */
56
- get telemetry(): Telemetry;
269
+ private get telemetry();
57
270
  /** Record of the selected session; the one strong owner lives in `State.session`. */
58
- get record(): Transcript;
271
+ private get record();
59
272
  /** @returns The current selector generation. */
60
273
  selection(): number;
61
274
  /** Advance the selector generation when the selected workspace or session changes. */
@@ -63,7 +276,46 @@ export declare class Controller implements ControllerStore, ConnectionListener {
63
276
  /** Publish a state patch, re-deriving the visible pending interactions.
64
277
  * @param patch - Fields to replace on the current state.
65
278
  */
279
+ /** Whether an operation owns the client's foreground slot right now.
280
+ * @returns True while an operation is running.
281
+ */
282
+ busy(): boolean;
66
283
  update(patch: Partial<State>): void;
284
+ /** Record one diagnostic event; a no-op when no trace path was configured. */
285
+ private traceEvent;
286
+ /** Record one diagnostic event from outside the controller, such as a UI-only decision.
287
+ *
288
+ * The composition root knows things this class cannot see — which record the operator highlighted,
289
+ * that a form was refused a name — and a start that never reaches `startLoop` is otherwise invisible
290
+ * in every log. Same no-op contract as the internal call.
291
+ * @param event - Event name, e.g. `loop-ui`.
292
+ * @param detail - Identifiers only; never prompt or session text.
293
+ */
294
+ traceNote(event: string, detail?: ObjectValue): void;
295
+ /** Mint the identifier one executed line carries through its `begin` and `end` events.
296
+ *
297
+ * Short and process-local on purpose: it exists to pair two lines of one file, not to identify a
298
+ * line across runs, so a monotonic counter beats a random id a reader would have to match by eye.
299
+ * @returns The next command id, such as `C17`.
300
+ */
301
+ nextCommandId(): string;
302
+ /** Record the state fields that decide which screen the reader is looking at.
303
+ *
304
+ * Every non-user transition is written here as well as at its cause, so a screen that moved
305
+ * without an expected reason is still visible in the trace rather than silently skipped.
306
+ * @param previous - State before the patch.
307
+ * @param next - State after the patch.
308
+ */
309
+ private traceTransition;
310
+ /** Bind every mutating entry point to its private implementation.
311
+ *
312
+ * Each one names the kind and label of the operation it performs, because that is now the single
313
+ * answer to "what owns the client right now" (§6.2): the front end renders it and cancels it, and
314
+ * nothing else has to know which layer started the work.
315
+ */
316
+ private buildActions;
317
+ /** Bind every read-only entry point; getters stay live because the values move between renders. */
318
+ private buildQueries;
67
319
  /** Start one retry loop, with a fresh snapshot generation after every disconnect. */
68
320
  start(): void;
69
321
  /** Cancel retries and HTTP, close the socket, and release session and catalog work. */
@@ -72,11 +324,24 @@ export declare class Controller implements ControllerStore, ConnectionListener {
72
324
  * An idle session stays untouched, and an in-flight cancellation is awaited rather than repeated.
73
325
  */
74
326
  shutdown(): Promise<void>;
75
- /** Run a UI operation and expose errors without destroying the current input.
327
+ /** Run one mutating operation inside the client's single foreground slot.
328
+ *
329
+ * Private on purpose: the application owns the slot, so a caller never hands the controller a
330
+ * closure to orchestrate. Every entry of `actions` uses it, and `actions.foreground` is the one
331
+ * door left open for work the front end orchestrates itself.
332
+ * @param kind - What the operation is, for the label and the trace.
333
+ * @param label - Human label shown while it runs.
76
334
  * @param operation - Operation to run while the client is busy.
77
- * @returns Whether the operation completed.
335
+ * @returns Whether the operation ran to completion.
78
336
  */
79
- perform(operation: () => Promise<void>): Promise<boolean>;
337
+ private runAction;
338
+ /** Same slot, for an operation that produces a value the caller needs. */
339
+ private runActionValue;
340
+ /** Run outside the foreground slot, with the same application failure reporting.
341
+ * Local prompt edits need no connection; verifier cancellation uses the session control lane and
342
+ * must reach the host even while the foreground is busy or closed for shutdown.
343
+ */
344
+ private runImmediateAction;
80
345
  /** Read the counters one memory sample records; content never leaves as text.
81
346
  *
82
347
  * The retained transcript and the ledger are small in practice, so a sample also reads the two
@@ -98,292 +363,261 @@ export declare class Controller implements ControllerStore, ConnectionListener {
98
363
  begin(): void;
99
364
  /** The event stream is ready and the control baseline is applied. */
100
365
  ready(): Promise<void>;
101
- /** The generation ended; invalidate session work and stop the scan. */
366
+ /** The generation ended; invalidate session work and stop the scan.
367
+ *
368
+ * A running loop is deliberately left alone: the host keeps running the review, and the client
369
+ * re-selects the same session after reconnecting, so only a switch to another session ends it.
370
+ */
102
371
  ended(): Promise<void>;
103
- /** Deliver a host waterfall to the session domain.
104
- * @param frame - One decoded waterfall frame.
105
- * @returns Whether the session domain retained it.
106
- */
107
- waterfall(frame: ObjectValue): boolean;
108
- /** Drop a waterfall the host cancelled.
109
- * @param eventId - Correlation id previously retained.
110
- */
111
- cancelled(eventId: string): void;
112
- /** Apply one host running-state notification.
113
- * @param sessionId - Session whose state changed.
114
- * @param running - Whether the host still runs that session.
115
- */
116
- status(sessionId: string, running: boolean): void;
117
- /** Surface a host-reported session error.
118
- * @param sessionId - Session the host reported on.
119
- * @param error - Error payload as delivered by the host.
120
- */
121
- error(sessionId: unknown, error: unknown): void;
122
- /** Reload the model catalog after a host settings, credential or adapter change. */
123
- invalidated(): void;
124
- /** Refresh billing after a turn finished. */
125
- idle(): void;
372
+ /** Route one normalized host event to the domain that owns it.
373
+ *
374
+ * This is the composition point: the connection knows only that an event arrived, so a feature
375
+ * never has to hold another feature. `false` means the host's waterfall is still unsettled.
376
+ * @param event - Normalized host event.
377
+ * @returns Whether a retained waterfall was consumed.
378
+ */
379
+ event(event: HostEvent): boolean;
126
380
  /** @returns Host running state of the selected session. */
127
- get running(): boolean;
381
+ private get running();
128
382
  /** @returns Current session title, falling back to the list title and then the ID. */
129
- get sessionName(): string | undefined;
383
+ private get sessionName();
130
384
  /** @returns Current agent-preset label. */
131
- get sessionMode(): string | undefined;
385
+ private get sessionMode();
132
386
  /** @returns Epoch start of the active turn, when known. */
133
- get workingSince(): number | undefined;
387
+ private get workingSince();
388
+ /** What the client is doing right now, merged across the host turn and any running loop.
389
+ *
390
+ * This is the controller's answer, not a view's guess: a turn speaks for the session while it runs,
391
+ * otherwise a live loop speaks for itself with its own sub-state and clock, and neither means idle.
392
+ * @returns The activity, or undefined when nothing is in flight.
393
+ */
394
+ private get activity();
134
395
  /** @returns Sessions accounted to the selected workspace, minus archived identities. */
135
- get visibleSessions(): ObjectValue[];
396
+ private get visibleSessions();
397
+ /** Every readable output source, newest activity first.
398
+ *
399
+ * Three origins feed one list, because a reader asking "what is that session" does not care which
400
+ * layer knows about it: sessions this client created (the host cannot record that link), local `!`
401
+ * runs it already holds, and host-created subagent children, whose only lineage is their list row.
402
+ * A client-created source wins over the list row for the same session, since it says more.
403
+ * @returns Sources to offer, running ones first.
404
+ */
405
+ private outputSources;
406
+ /** Register a session this client created for a verifier, so the list can explain it. */
407
+ private createVerifierSession;
408
+ /** Mark a source this client created as finished, keeping it readable. */
409
+ private endSource;
410
+ /** Open one source read-only at full screen; a session source starts following it. */
411
+ private openPeek;
412
+ /** Close the read-only view and release whatever it followed. */
413
+ private closePeek;
414
+ /** Release the view without publishing; the caller is already inside an update. */
415
+ private dropPeek;
416
+ /** What the read-only view renders, or undefined while it is closed. */
417
+ private peekSnapshot;
136
418
  /** @returns Unanswered interactions by session, for the state each list row reports. */
137
- pendingCounts(): ReadonlyMap<string, number>;
419
+ private pendingCounts;
138
420
  /** Load the optional preset roster once per connection. */
139
- loadPresetNames(): void;
140
- /** @returns Host model routes and adapter-owned reasoning choices. */
141
- modelCatalog(): Promise<ObjectValue>;
142
- /** Select the next request's model.
143
- * @param provider - Host provider route ID.
144
- * @param model - Exact model ID.
145
- * @param reasoningEffort - Optional adapter-owned effort ID.
146
- */
147
- selectModel(provider: string, model: string, reasoningEffort?: string): Promise<void>;
421
+ private loadPresetNames;
148
422
  /** Stop the selected turn, or allow exit only while idle.
149
423
  * @param force - Send an explicit cancellation even when the cached running flag is idle.
150
424
  * @returns True when the caller may exit.
151
425
  */
152
- interrupt(force?: boolean): Promise<boolean>;
426
+ private interrupt;
153
427
  /** One-line estimate of the selected session's cost, or `?` while the ledger has no entry for it. */
154
- get sessionCostText(): string;
155
428
  /** Keep history stable while the user reads, searches, or expands it.
156
429
  * @param pinned - Whether the main transcript is being read away from its tail.
157
430
  */
158
- pinHistory(pinned: boolean): void;
431
+ private pinHistory;
432
+ /** @returns The detached history window the reader opened, if any. */
433
+ private get window();
434
+ /** Show a detached history window, releasing the one it replaces.
435
+ * @param window - Record to display, or undefined to return to the live transcript.
436
+ */
159
437
  /** Recall one step through the selected session's prompt index; never touches the network.
160
438
  * @param direction - Negative for older input, positive for newer input.
161
439
  * @param current - Composer content before recall began, restored at the newest position.
162
440
  * @returns The recalled prompt, or the unsent draft.
163
441
  */
164
- recall(direction: -1 | 1, current: string): string;
442
+ private recall;
165
443
  /** Remember a locally submitted command, which never becomes a durable session record.
166
444
  * @param value - Submitted command text.
167
445
  */
168
- recordRecall(value: string): void;
446
+ private recordRecall;
169
447
  /** Leave recall navigation because the composer was edited or replaced. */
170
- resetRecall(): void;
448
+ private resetRecall;
171
449
  /** Whether recall is parked on the oldest prompt the session retains. */
172
- get recallAtOldest(): boolean;
450
+ private get recallAtOldest();
173
451
  /** How many prompts the selected session retains for recall. */
174
- get recallLength(): number;
452
+ private get recallLength();
175
453
  /** Whether an older prompt is reachable, in the loaded window or on the host. */
176
- get recallHasOlder(): boolean;
454
+ private get recallHasOlder();
177
455
  /** Recover older prompts from the loaded window before spending a page request.
178
456
  * @returns Whether any older prompt was recovered.
179
457
  */
180
- refillRecall(): boolean;
181
- /** Composer draft, caret and parked draft of the selected session. */
182
- get composer(): ComposerState;
183
- /** Replace the composer text and caret.
184
- * @param draft - New text.
185
- * @param cursor - Caret column; defaults to the end of the text.
186
- */
187
- setComposer(draft: string, cursor?: number): void;
188
- /** Move the caret without changing the text.
189
- * @param cursor - Caret column.
190
- */
191
- setComposerCursor(cursor: number): void;
192
- /** Move a non-empty draft aside while a dialog owns the keyboard. */
193
- parkComposer(): void;
194
- /** Give a parked draft back once no dialog needs the keyboard. */
195
- restoreComposer(): void;
196
- /** How the selected session's record is being read right now. */
197
- get view(): ViewState;
198
- /** Show a detached history window, releasing the one it replaces.
199
- * @param window - Record to display, or undefined to return to the live transcript.
200
- */
201
- setViewWindow(window?: Transcript): void;
202
- /** Move the reader's position inside the displayed record.
203
- * @param scroll - Rows scrolled back from the live end.
204
- */
205
- setScroll(scroll: number): void;
206
- /** Replace the set of expanded reasoning blocks.
207
- * @param folds - Sequences to expand beyond the default fold.
208
- */
209
- setFolds(folds: ReadonlySet<number>): void;
210
- /** Set the fold mode of the live attempt's completed reasoning.
211
- * @param reasoning - `row` to fold, `full` to keep the streamed text.
212
- */
213
- setLiveReasoning(reasoning: Reasoning): void;
458
+ private refillRecall;
214
459
  /** Local answer state for the selected session's pending waterfalls. */
215
- get interaction(): InteractionState;
460
+ private get interaction();
216
461
  /** Replace the partly collected answers, keyed by waterfall event id.
217
462
  * @param answers - Answers collected so far, by event id.
218
463
  */
219
- setAnswers(answers: Record<string, ObjectValue[]>): void;
464
+ private setAnswers;
465
+ /** Clear the internal last failure; a no-op when there is none. */
466
+ private clearFailure;
220
467
  /** Replace the pending question's option keyboard state.
221
468
  * @param option - Highlighted option, toggled labels and free-text mode; undefined clears it.
222
469
  */
223
- setOption(option?: OptionState): void;
470
+ private setOption;
224
471
  /** Replace the pending approval's selected row.
225
472
  * @param approval - Selected approval row; undefined clears the highlight.
226
473
  */
227
- setApproval(approval?: InteractionState['approval']): void;
228
- /** Composer-adjacent `@` reference menu state. */
229
- get reference(): ReferenceState;
230
- /** Highlight one row of the open reference menu.
231
- * @param index - Row index into the current matches.
232
- */
233
- setReferenceIndex(index: number): void;
234
- /** Remember the draft that dismissed the reference menu.
235
- * @param draft - Composer text at dismissal, or undefined to allow the menu again.
236
- */
237
- setReferenceDismissed(draft?: string): void;
238
- /** Panels the selected session has open. */
239
- get panels(): PanelState;
240
- /** Show or hide the reasoning panel.
241
- * @param open - Whether `/think` is open.
242
- */
243
- openThoughts(open: boolean): void;
244
- /** Show or hide the pending-input panel.
245
- * @param open - Whether `/queue` is open.
246
- */
247
- openQueue(open: boolean): void;
248
- /** Show the model dialog at one step, or close it.
249
- * @param model - Catalog plus the provider or model being inspected; undefined closes the dialog.
250
- */
251
- setModelPanel(model?: ModelState): void;
252
- /** Show the history or content-search dialog, or close it.
253
- * @param history - Query, content-search mode and matches; undefined closes the dialog.
254
- */
255
- setHistoryPanel(history?: PanelState['history']): void;
256
- /** Show the host session-search results, or close them.
257
- * @param search - Query, results and truncation flag; undefined closes the dialog.
258
- */
259
- setSearchPanel(search?: PanelState['search']): void;
474
+ private setApproval;
260
475
  /** Refresh all HTTP-visible sessions without changing the selected conversation.
261
476
  * @param signal - Optional cancellation for an explicit /cost refresh.
262
477
  */
263
- refreshCosts(signal?: AbortSignal): Promise<void>;
478
+ private refreshCosts;
264
479
  /** Refresh both lists from the host, then show the requested picker.
265
480
  * @param screen - Picker to display after the refresh.
266
481
  */
267
- showPicker(screen: 'workspaces' | 'sessions'): Promise<void>;
482
+ private showPicker;
268
483
  /** Resolve a removal command to one reviewable object.
269
484
  * @param kind - Workspace registration removal or session archival.
270
485
  * @param query - Exact name, ID, or unambiguous ID prefix.
271
486
  * @returns The fixed identity and display details for confirmation.
272
487
  */
273
- removalTarget(kind: 'workspace' | 'session', query: string): Promise<RemovalTarget>;
488
+ private removalTarget;
274
489
  /** Apply a confirmed removal or verified empty-session archival.
275
490
  * @param target - Exact workspace or session identity reviewed by the user.
276
491
  */
277
- removeTarget(target: RemovalTarget): Promise<void>;
492
+ private removeTarget;
278
493
  /** Pick a workspace, or use all sessions when the identity is omitted.
279
494
  * @param workspaceId - Workspace to select, if any.
280
495
  */
281
- pickWorkspace(workspaceId?: string): void;
496
+ private pickWorkspace;
497
+ /** Leave a picker and return to the selected conversation, without reloading it.
498
+ * @returns Whether there was a selected conversation to return to.
499
+ */
500
+ private showChat;
282
501
  /** Open a workspace picker, or resolve a workspace target.
283
502
  * @param query - Workspace target, if any.
284
503
  */
285
- switchWorkspace(query?: string): Promise<void>;
504
+ private switchWorkspace;
286
505
  /** Guide session selection, list all sessions with `all`, or resolve a target.
287
506
  * @param query - Session target, `all`, or nothing for the guided picker.
288
507
  */
289
- switchSession(query?: string): Promise<void>;
508
+ private switchSession;
290
509
  /** Prompt for a host path without starting a local agent. */
291
- enterPath(): void;
510
+ private enterPath;
292
511
  /** Register a host directory and move to its session picker.
293
512
  * @param path - Absolute directory path on the host.
294
513
  */
295
- createWorkspace(path: string): Promise<void>;
514
+ private createWorkspace;
296
515
  /** Create a session in the selected workspace. */
297
- createSession(): Promise<void>;
516
+ private createSession;
298
517
  /** Replace the selected transcript and follow the session.
299
518
  * @param sessionId - Session to follow.
300
519
  */
301
- selectSession(sessionId: string): Promise<void>;
520
+ private selectSession;
302
521
  /** Wait for the selected follow snapshot.
303
522
  * @param signal - Cancels waiting without closing the session.
304
523
  */
305
- waitForHistory(signal: AbortSignal): Promise<void>;
524
+ private waitForHistory;
306
525
  /** Search host session results.
307
526
  * @param query - Literal message text.
308
527
  * @param workspaceOnly - Restrict hits to the selected workspace.
309
528
  * @param signal - Cancels the HTTP search.
310
529
  * @returns Session snippets and the global truncation flag.
311
530
  */
312
- searchSessions(query: string, workspaceOnly: boolean, signal: AbortSignal): Promise<{
313
- items: ObjectValue[];
314
- hasMore: boolean;
315
- }>;
531
+ private searchSessions;
316
532
  /** Search host paths for the composer's `@` completion.
317
533
  * @param query - Path text after @.
318
534
  * @param signal - Cancels an obsolete lookup.
319
535
  * @returns Validated candidates in host order.
320
536
  */
321
- references(query: string, signal: AbortSignal): Promise<import("../session/references.ts").FileReference[]>;
537
+ private references;
322
538
  /** Execute a human command directly, outside the model prompt queue.
323
539
  * @param line - Complete slash command, including arguments.
324
540
  * @param signal - Cancels the request while the host performs compaction.
325
541
  * @returns The host's successful command result text.
326
542
  */
327
- command(line: string, signal: AbortSignal): Promise<string>;
543
+ private command;
328
544
  /** Remove one host-owned pending input.
329
545
  * @param itemId - Queue occurrence identity from session/control.
330
546
  */
331
- removeQueued(itemId: string): Promise<void>;
547
+ private removeQueued;
332
548
  /** Export the selected host log to a new local ZIP file.
333
549
  * @param path - Optional local destination; existing files are never overwritten.
334
550
  * @param signal - Cancels the download and removes an incomplete file.
335
551
  * @returns Absolute saved filename.
336
552
  */
337
- exportLog(path: string | undefined, signal: AbortSignal): Promise<string>;
553
+ private exportLog;
338
554
  /** Save loaded Markdown, diagrams and math as offline HTML.
339
555
  * @param path - Optional filename; existing files are not replaced.
340
556
  * @param signal - Cancels the write.
341
557
  * @returns Absolute saved filename.
342
558
  */
343
- exportHtml(path: string | undefined, signal: AbortSignal): Promise<string>;
559
+ private exportHtml;
344
560
  /** Write a V8 heap snapshot into this client's working directory; the write pauses the client.
345
561
  * @param tag - Sampling-point label naming the file, such as `after-stress`.
346
562
  * @returns Absolute path of the written snapshot.
347
563
  */
348
- heapSnapshot(tag?: string): string;
564
+ private heapSnapshot;
349
565
  /** Admit text once as steering while running, or a new turn while idle.
566
+ *
567
+ * Text the operator typed ends an automated review: the loop must not race a human for the turn,
568
+ * and the reply it would parse is no longer the reply to its own prompt.
350
569
  * @param text - Composed prompt text.
351
570
  */
352
- prompt(text: string): Promise<void>;
571
+ private prompt;
572
+ /** Clear this client's stale handoff file, then ask the agent to write a new one.
573
+ *
574
+ * The deletion happens first and on this machine, so a handoff that never gets written cannot be
575
+ * mistaken for the previous one. The request itself is an ordinary turn: it steers a running
576
+ * agent and starts an idle one, exactly like submitted text.
577
+ */
578
+ private handoff;
353
579
  /** Cancel the active turn; pending queue items remain host-owned. */
354
- cancelTurn(): Promise<void>;
580
+ private cancelTurn;
355
581
  /** Add a page before the retained window.
356
582
  * @param signal - Cancels local paging without interrupting the remote agent.
357
583
  * @param transcript - Transcript to extend; defaults to the live one.
358
584
  */
359
- older(signal?: AbortSignal, transcript?: Transcript): Promise<void>;
585
+ private older;
360
586
  /** Search the loaded history page by page.
361
587
  * @param query - Literal, case-insensitive text including folded reasoning.
362
588
  * @param signal - Cancels HTTP and processing without cancelling the agent.
363
589
  * @returns Newest-first bounded summaries and an explicit truncation flag.
364
590
  */
365
- searchHistory(query: string, signal: AbortSignal): Promise<HistorySearch>;
366
- /** Load a separate small window ending at a search target.
367
- * @param target - Durable message sequence to display.
368
- * @param signal - Cancels the target-page request.
369
- * @returns A caller-owned historical window that must be disposed when closed.
370
- */
371
- historyAt(target: number, signal: AbortSignal): Promise<Transcript>;
591
+ private searchHistory;
592
+ /** Plain rows and offsets for one laid-out record; the projection stays in the session domain. */
593
+ private render;
372
594
  /** Load the prefix required for an explicit history jump.
373
595
  * @param target - Visible record sequence, or first for the oldest available history.
374
596
  * @param signal - Cancels local paging without interrupting the remote agent.
375
597
  */
376
- historyThrough(target: number | 'first', signal: AbortSignal): Promise<void>;
598
+ private historyThrough;
377
599
  /** Answer the oldest selected-session interaction, after explicit user action.
378
- * @param value - Structured answer value or approval outcome.
600
+ * @param value - Structured answer collected by the UI.
379
601
  */
380
- answer(value: Json): Promise<void>;
602
+ private answer;
603
+ /** Answer the current sub-question of the pending set, advancing the waterfall or sending it.
604
+ *
605
+ * The waterfall is interaction state of the session — which sub-question is current follows from the
606
+ * answers collected so far, and the ticked labels live in the option state — so it belongs here
607
+ * rather than in a front end. Both entry points then complete a question the same way: a line the
608
+ * operator typed as an answer, and the option keys.
609
+ * @param input - Labels chosen for this sub-question, or free text the operator typed.
610
+ * @returns True once the answer was recorded or sent; a host refusal throws, leaving the collected
611
+ * answers in place so the same submission can be retried.
612
+ */
613
+ private answerQuestion;
381
614
  /** Approve or reject the pending approval request.
382
615
  * @param allowed - Whether the request is approved once.
383
616
  */
384
- approve(allowed: boolean): Promise<void>;
617
+ private approve;
385
618
  /** Dismiss the whole pending question set without answering it, as the Web close button does. */
386
- dismissQuestion(): Promise<void>;
619
+ private dismissQuestion;
387
620
  }
388
- export type { HistorySearch, RemovalTarget } from '../session/types.ts';
621
+ export type { HistorySearch, RemovalTarget, AnswerValue, PendingInteraction } from '../session/types.ts';
622
+ export type { SavedPrompt } from '../contracts.ts';
389
623
  export type { State } from '../state.ts';