@itookit/dsht 0.3.0 → 0.3.3

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 (134) hide show
  1. package/README.i18n.yaml +2 -2
  2. package/README.md +39 -23
  3. package/README.zh.md +40 -24
  4. package/dist/catalog/controller.d.ts +32 -0
  5. package/dist/catalog/controller.js +88 -0
  6. package/dist/catalog/index.d.ts +2 -0
  7. package/dist/catalog/index.js +2 -0
  8. package/dist/{cli.js → cli/index.js} +42 -29
  9. package/dist/controller/connection.d.ts +80 -0
  10. package/dist/controller/connection.js +190 -0
  11. package/dist/controller/controller.d.ts +269 -0
  12. package/dist/controller/controller.js +372 -0
  13. package/dist/controller/index.d.ts +5 -0
  14. package/dist/controller/index.js +3 -0
  15. package/dist/controller/memory-log.d.ts +35 -0
  16. package/dist/controller/memory-log.js +95 -0
  17. package/dist/cost/config.d.ts +17 -0
  18. package/dist/cost/config.js +68 -0
  19. package/dist/cost/controller.d.ts +41 -0
  20. package/dist/cost/controller.js +115 -0
  21. package/dist/cost/index.d.ts +10 -0
  22. package/dist/cost/index.js +8 -0
  23. package/dist/cost/ledger-files.d.ts +16 -0
  24. package/dist/cost/ledger-files.js +103 -0
  25. package/dist/cost/ledger.d.ts +78 -0
  26. package/dist/cost/ledger.js +146 -0
  27. package/dist/cost/pricing.d.ts +86 -0
  28. package/dist/cost/pricing.js +223 -0
  29. package/dist/cost/records.d.ts +17 -0
  30. package/dist/cost/records.js +79 -0
  31. package/dist/cost/scanner.d.ts +22 -0
  32. package/dist/cost/scanner.js +95 -0
  33. package/dist/cost/types.d.ts +85 -0
  34. package/dist/cost/types.js +7 -0
  35. package/dist/index.d.ts +3 -0
  36. package/dist/index.js +2 -0
  37. package/dist/session/connection-view.d.ts +18 -0
  38. package/dist/session/connection-view.js +1 -0
  39. package/dist/{controller.d.ts → session/controller.d.ts} +102 -136
  40. package/dist/session/controller.js +616 -0
  41. package/dist/session/export-html.d.ts +9 -0
  42. package/dist/session/export-html.js +39 -0
  43. package/dist/{export.d.ts → session/export.d.ts} +1 -1
  44. package/dist/{export.js → session/export.js} +6 -20
  45. package/dist/{history.d.ts → session/history.d.ts} +17 -0
  46. package/dist/{history.js → session/history.js} +163 -2
  47. package/dist/session/index.d.ts +17 -0
  48. package/dist/session/index.js +10 -0
  49. package/dist/session/markdown.d.ts +39 -0
  50. package/dist/session/markdown.js +255 -0
  51. package/dist/session/math.d.ts +11 -0
  52. package/dist/session/math.js +82 -0
  53. package/dist/session/navigation.d.ts +37 -0
  54. package/dist/session/navigation.js +84 -0
  55. package/dist/{references.js → session/references.js} +1 -1
  56. package/dist/{telemetry.d.ts → session/telemetry.d.ts} +1 -1
  57. package/dist/{telemetry.js → session/telemetry.js} +1 -1
  58. package/dist/{transcript.d.ts → session/transcript.d.ts} +65 -1
  59. package/dist/{transcript.js → session/transcript.js} +141 -20
  60. package/dist/session/types.d.ts +18 -0
  61. package/dist/session/types.js +2 -0
  62. package/dist/state.d.ts +41 -0
  63. package/dist/state.js +9 -0
  64. package/dist/storage/directories.d.ts +14 -0
  65. package/dist/storage/directories.js +24 -0
  66. package/dist/storage/files.d.ts +51 -0
  67. package/dist/storage/files.js +152 -0
  68. package/dist/storage/heap-snapshot.d.ts +19 -0
  69. package/dist/storage/heap-snapshot.js +29 -0
  70. package/dist/storage/index.d.ts +4 -0
  71. package/dist/storage/index.js +4 -0
  72. package/dist/transport/auth.js +65 -0
  73. package/dist/transport/host.d.ts +13 -0
  74. package/dist/transport/host.js +1 -0
  75. package/dist/ui/app.d.ts +11 -0
  76. package/dist/ui/app.js +790 -0
  77. package/dist/ui/chat/header.d.ts +11 -0
  78. package/dist/ui/chat/header.js +14 -0
  79. package/dist/ui/chat/history-view.d.ts +12 -0
  80. package/dist/ui/chat/history-view.js +17 -0
  81. package/dist/ui/chat/status.d.ts +91 -0
  82. package/dist/ui/chat/status.js +386 -0
  83. package/dist/ui/chat/viewport.d.ts +17 -0
  84. package/dist/ui/chat/viewport.js +14 -0
  85. package/dist/ui/commands/parse.d.ts +99 -0
  86. package/dist/ui/commands/parse.js +126 -0
  87. package/dist/ui/commands/registry.d.ts +33 -0
  88. package/dist/ui/commands/registry.js +73 -0
  89. package/dist/ui/copy-mode.d.ts +4 -0
  90. package/dist/ui/copy-mode.js +6 -0
  91. package/dist/{cost-view.d.ts → ui/dialogs/cost.d.ts} +1 -1
  92. package/dist/{cost-view.js → ui/dialogs/cost.js} +6 -6
  93. package/dist/ui/dialogs/index.d.ts +120 -0
  94. package/dist/ui/dialogs/index.js +113 -0
  95. package/dist/ui/dialogs/picker.d.ts +18 -0
  96. package/dist/ui/dialogs/picker.js +38 -0
  97. package/dist/ui/frozen.d.ts +8 -0
  98. package/dist/ui/frozen.js +7 -0
  99. package/dist/ui/input/references.d.ts +12 -0
  100. package/dist/ui/input/references.js +15 -0
  101. package/dist/ui/mount.d.ts +6 -0
  102. package/dist/ui/mount.js +11 -0
  103. package/dist/{theme.d.ts → ui/theme/index.d.ts} +1 -1
  104. package/package.json +19 -13
  105. package/dist/app.d.ts +0 -21
  106. package/dist/app.js +0 -805
  107. package/dist/auth.js +0 -108
  108. package/dist/controller.js +0 -961
  109. package/dist/cost.d.ts +0 -119
  110. package/dist/cost.js +0 -313
  111. package/dist/history-view.d.ts +0 -8
  112. package/dist/history-view.js +0 -12
  113. package/dist/navigation.d.ts +0 -11
  114. package/dist/navigation.js +0 -36
  115. package/dist/status.d.ts +0 -28
  116. package/dist/status.js +0 -157
  117. /package/dist/{cli.d.ts → cli/index.d.ts} +0 -0
  118. /package/dist/{memory.d.ts → session/memory.d.ts} +0 -0
  119. /package/dist/{memory.js → session/memory.js} +0 -0
  120. /package/dist/{references.d.ts → session/references.d.ts} +0 -0
  121. /package/dist/{auth.d.ts → transport/auth.d.ts} +0 -0
  122. /package/dist/{client.d.ts → transport/client.d.ts} +0 -0
  123. /package/dist/{client.js → transport/client.js} +0 -0
  124. /package/dist/{endpoint.d.ts → transport/endpoint.d.ts} +0 -0
  125. /package/dist/{endpoint.js → transport/endpoint.js} +0 -0
  126. /package/dist/{wire.d.ts → transport/wire.d.ts} +0 -0
  127. /package/dist/{wire.js → transport/wire.js} +0 -0
  128. /package/dist/{input-history.d.ts → ui/input/history.d.ts} +0 -0
  129. /package/dist/{input-history.js → ui/input/history.js} +0 -0
  130. /package/dist/{input.d.ts → ui/input/input.d.ts} +0 -0
  131. /package/dist/{input.js → ui/input/input.js} +0 -0
  132. /package/dist/{mouse.d.ts → ui/input/mouse.d.ts} +0 -0
  133. /package/dist/{mouse.js → ui/input/mouse.js} +0 -0
  134. /package/dist/{theme.js → ui/theme/index.js} +0 -0
@@ -0,0 +1,95 @@
1
+ /** Address and page one session's complete billing history over the host connection. */
2
+ import { RemoteError } from "../transport/client.js";
3
+ import { array, errorText, object, string } from "../transport/wire.js";
4
+ import { costRecords } from "./records.js";
5
+ /** Wire addresses for one `session/list` row, in the order the cost scan should try them.
6
+ *
7
+ * A subagent child is reachable only under its durable parent, and the list row omits the delivery
8
+ * mode, so both modes are offered with the continuable form first.
9
+ * @param session - One row from the host session list.
10
+ * @returns One plain-session address, or both subagent forms when the row is a child.
11
+ */
12
+ export function costAddresses(session) {
13
+ const sessionId = string(session.sessionId);
14
+ const parentSessionId = typeof session.parentSessionId === 'string' ? session.parentSessionId : '';
15
+ if (session.origin !== 'subagent' || parentSessionId === '')
16
+ return [{ kind: 'session', sessionId }];
17
+ return [
18
+ { kind: 'subagent', parentSessionId, childSessionId: sessionId, mode: 'continuable' },
19
+ { kind: 'subagent', parentSessionId, childSessionId: sessionId, mode: 'one-shot' },
20
+ ];
21
+ }
22
+ /** Read one session's complete cost history, retrying a subagent child with its other delivery mode.
23
+ * @param client - Authenticated host transport.
24
+ * @param session - One row from the host session list.
25
+ * @param signal - Cancels paging without cancelling any agent work.
26
+ * @param onPage - Counts each history request, so a scan can report how much it re-read.
27
+ * @returns Opening cursor and the minimal billing events behind it.
28
+ */
29
+ export async function sessionCostHistory(client, session, signal, onPage) {
30
+ let lastError;
31
+ for (const address of costAddresses(session)) {
32
+ try {
33
+ return await readCostHistory(client, address, signal, onPage);
34
+ }
35
+ catch (error) {
36
+ lastError = error;
37
+ // Only a delivery-mode mismatch justifies the other form; every other failure is final here.
38
+ if (!(error instanceof RemoteError && error.code === 'subagent/unauthorized'))
39
+ throw error;
40
+ }
41
+ }
42
+ throw lastError;
43
+ }
44
+ /** Page one addressed session's history into the billing events the ledger folds. */
45
+ async function readCostHistory(client, address, signal, onPage) {
46
+ onPage?.();
47
+ const snapshot = await new Promise((resolve, reject) => {
48
+ let sub;
49
+ const timeout = setTimeout(() => finish(new Error('Cost history snapshot timed out')), client.timeoutMs);
50
+ const onAbort = () => finish(new Error('Cost refresh cancelled'));
51
+ const finish = (error, frame) => {
52
+ clearTimeout(timeout);
53
+ signal.removeEventListener('abort', onAbort);
54
+ sub?.cancel();
55
+ if (error)
56
+ reject(error);
57
+ else
58
+ resolve(frame);
59
+ };
60
+ signal.addEventListener('abort', onAbort, { once: true });
61
+ try {
62
+ sub = client.subscribe('session/follow', { request: { address, maxMessages: 80, assistantStream: true } }, {
63
+ item: value => { const frame = object(value); if (frame.type === 'snapshot')
64
+ finish(undefined, frame); },
65
+ end: error => finish(error ?? new Error('Cost history stream ended')),
66
+ });
67
+ }
68
+ catch (error) {
69
+ finish(error instanceof Error ? error : new Error(errorText(error)));
70
+ }
71
+ });
72
+ const cursor = snapshot.cursor;
73
+ if (typeof cursor !== 'number' || !Number.isSafeInteger(cursor))
74
+ throw new Error('Invalid cost history cursor');
75
+ let page = snapshot;
76
+ const events = [];
77
+ while (true) {
78
+ signal.throwIfAborted();
79
+ const records = array(page.records);
80
+ events.push(...costRecords(records));
81
+ if (!page.hasMore)
82
+ break;
83
+ const seqs = records.map(r => object(object(r).event).seq);
84
+ if (!seqs.length || seqs.some(n => typeof n !== 'number' || !Number.isSafeInteger(n)))
85
+ throw new Error('Invalid cost history page');
86
+ const beforeSeq = Math.min(...seqs);
87
+ onPage?.();
88
+ page = object(await client.call('session/page', { request: { address, throughSeq: cursor, beforeSeq, maxMessages: 80 } }, signal));
89
+ if (page.hasMore && array(page.records).every(r => Number(object(object(r).event).seq) >= beforeSeq))
90
+ throw new Error('Cost history page did not advance');
91
+ }
92
+ if (object(snapshot.header).isSeeded === true && !events.some(e => e.type === 'session/end-seed' && object(e.data).inherited === true))
93
+ throw new Error('Cannot attribute inherited session usage');
94
+ return { cursor, events };
95
+ }
@@ -0,0 +1,85 @@
1
+ /** Cost-domain types shared by pricing, record folding, storage and the in-memory ledger. */
2
+ /** Per-million-token rates for one peak or off-peak bucket. */
3
+ export interface Rates {
4
+ input: number;
5
+ cacheRead: number;
6
+ cacheWrite: number;
7
+ output: number;
8
+ }
9
+ /** An explicit validity interval and weekday peak windows in the named time zone. */
10
+ export interface PriceVersion {
11
+ id: string;
12
+ provider: string;
13
+ model: string;
14
+ /** Further model names this version prices; a trailing `*` matches a prefix. Never a guess. */
15
+ aliases?: string[];
16
+ from: string;
17
+ until?: string;
18
+ currency: 'CNY';
19
+ source: string;
20
+ timezone: string;
21
+ peak: Rates;
22
+ offPeak: Rates;
23
+ weekdays: number[];
24
+ windows: [number, number][];
25
+ }
26
+ /** Disjoint token buckets reported for one model request. */
27
+ export interface Usage {
28
+ input: number;
29
+ output: number;
30
+ cacheRead: number;
31
+ cacheWrite: number;
32
+ }
33
+ /** One folded request sample: the attempt identity and the facts a price decision needs. */
34
+ export interface ChargeSample {
35
+ key: string;
36
+ time?: number;
37
+ provider: string;
38
+ model: string;
39
+ usage?: Usage;
40
+ }
41
+ /** What the table decides for one request sample: an amount, or the reason it has none. */
42
+ export interface PriceDecision {
43
+ amount?: number;
44
+ reason?: string;
45
+ }
46
+ /** Summary retains the known subtotal and the records it could not price.
47
+ * `unknown` counts records with no amount; `records` counts every request the range covers, so a
48
+ * subtotal is never read as complete without them.
49
+ */
50
+ export interface CostTotal {
51
+ amount: number;
52
+ unknown: number;
53
+ records: number;
54
+ }
55
+ /** One Beijing calendar day's requests, kept only for the day a scan ran on. */
56
+ export interface DayTotal extends CostTotal {
57
+ day: string;
58
+ }
59
+ /** One session's persisted ledger slice.
60
+ *
61
+ * The host log and the loaded price table are the only inputs, so the slice stores the totals one
62
+ * scan folded them into and no per-request detail: the next scan reads the session's history again
63
+ * and decides every sample with the table loaded then. `engine` and `catalog` name the decision
64
+ * rules and the table behind these totals, so a process holding an older one cannot overwrite them.
65
+ */
66
+ export interface SavedCost {
67
+ version: 3;
68
+ sessionId: string;
69
+ /** Durable sequence the fold reached; a scan that opened an older cut may not replace this slice. */
70
+ cut: number;
71
+ engine: number;
72
+ catalog: string;
73
+ total: CostTotal;
74
+ day: DayTotal;
75
+ /** Distinct reasons an amount is missing, bounded, so a panel can say what makes a total inexact. */
76
+ unpriced: string[];
77
+ }
78
+ /** How much of the visible history the cached ledger currently covers. */
79
+ export type Coverage = 'complete' | 'scanning' | 'partial';
80
+ /** Reason recorded when a sample carries no usable token counts. */
81
+ export declare const MISSING_USAGE = "missing usage";
82
+ /** Reason recorded when the host reported a cache-write bucket the published table does not price. */
83
+ export declare const UNSUPPORTED_USAGE = "unsupported usage";
84
+ /** Reason recorded when the request has no settlement time to place it in a peak band or a day. */
85
+ export declare const MISSING_TIME = "missing time";
@@ -0,0 +1,7 @@
1
+ /** Cost-domain types shared by pricing, record folding, storage and the in-memory ledger. */
2
+ /** Reason recorded when a sample carries no usable token counts. */
3
+ export const MISSING_USAGE = 'missing usage';
4
+ /** Reason recorded when the host reported a cache-write bucket the published table does not price. */
5
+ export const UNSUPPORTED_USAGE = 'unsupported usage';
6
+ /** Reason recorded when the request has no settlement time to place it in a peak band or a day. */
7
+ export const MISSING_TIME = 'missing time';
@@ -0,0 +1,3 @@
1
+ /** Published library entry: the reusable host client and its error types. */
2
+ export { Client, HttpError, RemoteError } from './transport/client.ts';
3
+ export type { Subscription } from './transport/client.ts';
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ /** Published library entry: the reusable host client and its error types. */
2
+ export { Client, HttpError, RemoteError } from "./transport/client.js";
@@ -0,0 +1,18 @@
1
+ /** What the session domain reads from the connection the controller owns. */
2
+ import type { Telemetry } from './telemetry.ts';
3
+ import type { ObjectValue } from '../transport/wire.ts';
4
+ /** Read-only connection facts and actions the session controller needs. */
5
+ export interface ConnectionView {
6
+ /** Projection store of the current generation. */
7
+ telemetryView(): Telemetry;
8
+ /** Cached host running flag for one session, or undefined when never reported. */
9
+ runningFor(sessionId: string): boolean | undefined;
10
+ /** When this client first observed the session, for the elapsed-time fallback. */
11
+ observedAt(sessionId: string): number | undefined;
12
+ /** Record an observation start for a session this client just opened. */
13
+ observe(sessionId: string): void;
14
+ /** Fail the current generation, so the controller reopens a snapshot. */
15
+ fail(error: Error): void;
16
+ /** Answer one retained host waterfall through the event-result endpoint. */
17
+ reply(frame: ObjectValue, outcome: ObjectValue): Promise<void>;
18
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -1,143 +1,84 @@
1
- import { Client } from './client.ts';
2
- import { CostLedger } from './cost.ts';
3
- import { Telemetry } from './telemetry.ts';
4
- import { Transcript } from './transcript.ts';
5
- import { type HistoryLimits } from './memory.ts';
1
+ import type { HostAccess } from '../transport/host.ts';
2
+ import { type Json, type ObjectValue } from '../transport/wire.ts';
3
+ import type { ControllerStore, State } from '../state.ts';
4
+ import type { HistoryLimits } from './memory.ts';
6
5
  import { type FileReference } from './references.ts';
7
- import { type Json, type ObjectValue } from './wire.ts';
8
- /** Resolved navigation-removal identity; empty marks a fresh blank, idle session eligible for immediate archival. */
9
- export interface RemovalTarget {
10
- kind: 'workspace' | 'session';
11
- id: string;
12
- name: string;
13
- path?: string;
14
- empty?: boolean;
15
- }
16
- /** State shared by the picker and conversation view. */
17
- export interface State {
18
- version: number;
19
- online: boolean;
20
- busy: boolean;
21
- screen: 'workspaces' | 'sessions' | 'chat' | 'path';
22
- status: string;
23
- error: string;
24
- workspaces: ObjectValue[];
25
- sessions: ObjectValue[];
26
- showAllSessions: boolean;
27
- workspaceId?: string;
28
- sessionId?: string;
29
- pending: ObjectValue[];
30
- controlError?: string;
31
- modelError?: string;
32
- presetError?: string;
33
- presets?: ObjectValue[];
34
- defaultModel?: ObjectValue;
35
- transcript: Transcript;
36
- }
37
- /** Bounded search results contain navigation summaries, never complete message bodies. */
38
- export interface HistorySearch {
39
- items: {
40
- seq: number;
41
- role: string;
42
- preview: string;
43
- }[];
44
- truncated: boolean;
45
- }
46
- /** Wire addresses for one `session/list` row, in the order the cost scan should try them.
47
- *
48
- * A subagent child is reachable only under its durable parent, and the list row omits the delivery
49
- * mode, so both modes are offered with the continuable form first.
50
- * @param session - One row from the host session list.
51
- * @returns One plain-session address, or both subagent forms when the row is a child.
52
- */
53
- export declare function costAddresses(session: ObjectValue): ObjectValue[];
54
- /** Owns reconnects and subscriptions. User commands remain single-attempt operations. */
55
- export declare class Controller {
56
- readonly base: string;
57
- readonly initialSession?: string | undefined;
58
- private makeClient;
59
- private authenticate;
60
- readonly costs?: CostLedger | undefined;
61
- readonly historyLimits: HistoryLimits;
62
- state: State;
63
- private observers;
64
- private interactions;
65
- private abort;
66
- private client;
67
- private clientId;
6
+ import { Transcript } from './transcript.ts';
7
+ import type { ConnectionView } from './connection-view.ts';
8
+ import type { HistorySearch, RemovalTarget } from './types.ts';
9
+ /** Owns the selected session: its follow stream, transcript, history window and interactions. */
10
+ export declare class SessionController {
11
+ private readonly store;
12
+ private readonly host;
13
+ private readonly connection;
14
+ private readonly historyLimits;
68
15
  private follow;
69
- private runTask;
70
- private generationFailed;
71
- private selection;
16
+ private interactions;
72
17
  private historyPinned;
73
- telemetry: Telemetry;
74
- private observedRunningAt;
75
- private presetClient?;
76
- private catalogRevision;
77
- private catalogTasks;
78
- private runningUpdates;
79
18
  private stoppingSession?;
80
19
  private interruptTask;
81
20
  private admission;
82
- private costUpdates;
83
- private costAbort?;
84
- private costTask;
85
- private costTimer;
21
+ constructor(store: ControllerStore, host: HostAccess, connection: ConnectionView, historyLimits: HistoryLimits);
86
22
  /** Host running state covers model generation, tools, and waits between assistant attempts. */
87
23
  get running(): boolean;
88
24
  /** Current title projection, falling back to the list title and then the session ID. */
89
25
  get sessionName(): string | undefined;
90
26
  /** Current agent-preset name, matching the web header's built-in labels and custom metadata. */
91
27
  get sessionMode(): string | undefined;
92
- /** Load the optional preset roster once per connection, only when a session names a preset. */
93
- loadPresetNames(): void;
94
- /** Fetch current model routes and adapter-owned reasoning choices for the selected session.
95
- * @returns Host catalog; provider failures remain available to the selector.
96
- */
97
- modelCatalog(): Promise<ObjectValue>;
98
- /** Select the next request's model; the host also attempts to save its deployment default.
99
- * @param provider - Host provider route ID.
100
- * @param model - Exact model ID.
101
- * @param reasoningEffort - Optional adapter-owned effort ID; omission uses its default.
102
- */
103
- selectModel(provider: string, model: string, reasoningEffort?: string): Promise<void>;
104
28
  /** Epoch start from the retained turn log, or when this client first observed the run. */
105
29
  get workingSince(): number | undefined;
30
+ /** Present only sessions explicitly accounted to the selected workspace. */
31
+ get visibleSessions(): ObjectValue[];
32
+ /** Whether a turn, cancellation or prompt admission is still in flight. */
33
+ get active(): boolean;
34
+ /** Whether reading protects the loaded window, suspending history reclamation. */
35
+ get pinned(): boolean;
36
+ /** Drop generation-scoped state before a new connection generation begins. */
37
+ beginGeneration(): void;
38
+ /** Invalidate in-flight work and drop transient interactions when a generation ends. */
39
+ endGeneration(): void;
40
+ /** Wait for an in-flight cancellation so shutdown leaves nothing running. */
41
+ settle(): Promise<void>;
42
+ /** Release the selected transcript and its layout caches. */
43
+ release(): void;
44
+ /** Pending interactions for the selected chat session, derived independently of frame order.
45
+ * @param state - State being published.
46
+ * @returns Retained question and approval frames for that session.
47
+ */
48
+ pendingFor(state: State): ObjectValue[];
49
+ /** Retain a recognized host waterfall; unknown events stay with the connection to delegate.
50
+ * @param frame - One decoded waterfall frame.
51
+ * @returns Whether this domain retained the frame for an answer.
52
+ */
53
+ waterfall(frame: ObjectValue): boolean;
54
+ /** Drop a waterfall the host cancelled.
55
+ * @param eventId - Correlation id previously retained.
56
+ */
57
+ cancelled(eventId: string): void;
58
+ /** Apply one host running-state notification to the session list and status line.
59
+ * @param sessionId - Session whose state changed.
60
+ * @param running - Whether the host still runs that session.
61
+ */
62
+ status(sessionId: string, running: boolean): void;
63
+ /** Surface a host-reported error for the selected session.
64
+ * @param sessionId - Session the host reported on.
65
+ * @param error - Error payload as delivered by the host.
66
+ */
67
+ reportError(sessionId: unknown, error: unknown): void;
106
68
  /** Stop the selected turn, or allow exit only while idle. Repeated keys share one request.
107
69
  * @param force - Send an explicit cancellation even when the cached running flag is idle.
108
70
  * @returns True when the caller may exit; cancellation failures retain the client.
109
71
  */
110
72
  interrupt(force?: boolean): Promise<boolean>;
111
- constructor(base: string, token: string | undefined, initialSession?: string | undefined, makeClient?: () => Client, authenticate?: (client: Client) => Promise<void>, costs?: CostLedger | undefined, historyLimits?: HistoryLimits);
112
- /** React-compatible state subscription. */
113
- subscribe: (listener: () => void) => (() => void);
114
- /** Snapshot identity changes only when the controller publishes. */
115
- snapshot: () => State;
116
- /** Start one retry loop, with a fresh snapshot generation after every disconnect. */
117
- start(): void;
118
- /** Cancel retries and HTTP, close the socket, and wait for the loop to settle. */
119
- stop(): Promise<void>;
120
73
  /** Keep history stable while the user reads, searches, or expands it; trim again at the live tail.
121
74
  * @param pinned - Whether the main transcript is actively being read away from its tail.
122
75
  */
123
76
  pinHistory(pinned: boolean): void;
124
- private reclaimHistory;
125
- private releaseTranscript;
126
- /** Stop the selected turn and then close, so quitting does not leave host work running.
127
- * An idle session stays untouched, and an in-flight cancellation is awaited rather than repeated.
128
- */
129
- shutdown(): Promise<void>;
130
- /** Run a UI operation and expose errors without destroying the current input. */
131
- perform(operation: () => Promise<void>): Promise<boolean>;
132
- /** Refresh all HTTP-visible sessions without changing the selected conversation.
133
- * @param signal - Optional cancellation for an explicit /cost refresh.
134
- */
135
- refreshCosts(signal?: AbortSignal): Promise<void>;
136
- /** Read one session's complete cost history, retrying a subagent child with its other delivery mode. */
137
- private sessionCostHistory;
138
- /** Page one addressed session's history into the billing events the ledger folds. */
139
- private readCostHistory;
140
- /** Refresh both lists from the host, then show the requested picker. */
77
+ /** Cancel the active turn; pending queue items remain host-owned. */
78
+ cancelTurn(): Promise<void>;
79
+ /** Refresh both lists from the host, then show the requested picker.
80
+ * @param screen - Picker to display after the refresh.
81
+ */
141
82
  showPicker(screen: 'workspaces' | 'sessions'): Promise<void>;
142
83
  /** Resolve a removal command to one reviewable object without changing the selection.
143
84
  * @param kind - Workspace registration removal or session archival.
@@ -149,19 +90,29 @@ export declare class Controller {
149
90
  * @param target - Exact workspace or session identity reviewed by the user.
150
91
  */
151
92
  removeTarget(target: RemovalTarget): Promise<void>;
152
- /** Pick a workspace, or use all sessions when the identity is omitted. */
93
+ /** Pick a workspace, or use all sessions when the identity is omitted.
94
+ * @param workspaceId - Workspace to select, if any.
95
+ */
153
96
  pickWorkspace(workspaceId?: string): void;
154
- /** Open a workspace picker, or resolve a workspace by ID, exact title/path, or unique ID prefix. */
97
+ /** Open a workspace picker, or resolve a workspace by ID, exact title/path, or unique ID prefix.
98
+ * @param query - Workspace target, if any.
99
+ */
155
100
  switchWorkspace(query?: string): Promise<void>;
156
- /** Guide workspace selection, list all sessions with `all`, or resolve an exact session target. */
101
+ /** Guide workspace selection, list all sessions with `all`, or resolve an exact session target.
102
+ * @param query - Session target, `all`, or nothing for the guided picker.
103
+ */
157
104
  switchSession(query?: string): Promise<void>;
158
105
  /** Prompt for a host path without starting a local agent. */
159
106
  enterPath(): void;
160
- /** Register a host directory and move to its session picker. */
107
+ /** Register a host directory and move to its session picker.
108
+ * @param path - Absolute directory path on the host.
109
+ */
161
110
  createWorkspace(path: string): Promise<void>;
162
111
  /** Create a session only after the user explicitly selects New session. */
163
112
  createSession(): Promise<void>;
164
- /** Replace the selected transcript and cancel its preceding follow stream. */
113
+ /** Replace the selected transcript and cancel its preceding follow stream.
114
+ * @param sessionId - Session to follow.
115
+ */
165
116
  selectSession(sessionId: string): Promise<void>;
166
117
  /** Wait for the selected follow snapshot, failing on disconnect or cancellation.
167
118
  * @param signal - Cancels waiting without closing the session.
@@ -199,11 +150,28 @@ export declare class Controller {
199
150
  * @returns Absolute saved filename.
200
151
  */
201
152
  exportLog(path: string | undefined, signal: AbortSignal): Promise<string>;
202
- /** Admit text once as steering while running, or a new turn while idle; a lost response can leave delivery uncertain. */
153
+ /** Save the retained conversation with offline Markdown, diagrams and math.
154
+ * @param path - Optional destination; existing files are never overwritten.
155
+ * @param signal - Cancels the write.
156
+ * @returns Absolute saved filename.
157
+ */
158
+ exportHtml(path: string | undefined, signal: AbortSignal): Promise<string>;
159
+ /** Admit text once as steering while running, or a new turn while idle; a lost response can leave delivery uncertain.
160
+ * @param text - Composed prompt text.
161
+ */
203
162
  prompt(text: string): Promise<void>;
204
- /** Cancel the active turn; pending queue items remain host-owned. */
205
- cancelTurn(): Promise<void>;
206
- /** Add a page before the retained window using its fixed opening cut. */
163
+ /** Answer the oldest selected-session interaction, after explicit user action.
164
+ * @param value - Structured answer value or approval outcome.
165
+ */
166
+ answer(value: Json): Promise<void>;
167
+ /** Restrict an approval command to an approval request.
168
+ * @param allowed - Whether the request is approved once.
169
+ */
170
+ approve(allowed: boolean): Promise<void>;
171
+ /** Add a page before the retained window using its fixed opening cut.
172
+ * @param signal - Cancels local paging without interrupting the remote agent.
173
+ * @param transcript - Transcript to extend; defaults to the live one.
174
+ */
207
175
  older(signal?: AbortSignal, transcript?: Transcript): Promise<void>;
208
176
  /** Search one page at a time, preserving only the first 200 matches and releasing temporary content.
209
177
  * @param query - Literal, case-insensitive text including folded reasoning.
@@ -222,16 +190,14 @@ export declare class Controller {
222
190
  * @param signal - Cancels local paging without interrupting the remote agent.
223
191
  */
224
192
  historyThrough(target: number | 'first', signal: AbortSignal): Promise<void>;
225
- /** Answer the oldest selected-session interaction, after explicit user action. */
226
- answer(value: Json): Promise<void>;
227
- /** Restrict an approval command to an approval request. */
228
- approve(allowed: boolean): Promise<void>;
229
- /** Present only sessions explicitly accounted to the selected workspace. */
230
- get visibleSessions(): ObjectValue[];
231
- private get host();
193
+ /** Reclaim reloadable history unless the user is reading away from the tail.
194
+ * @returns Number of removed records.
195
+ */
196
+ private reclaimHistory;
197
+ /** Release the selected transcript and its layout caches. */
198
+ private releaseTranscript;
199
+ /** @returns The selected session identity, or a `Select a session first` failure. */
232
200
  private get sessionId();
233
- private update;
201
+ /** Answer one retained waterfall through the connection's event-result endpoint. */
234
202
  private reply;
235
- private refreshCatalog;
236
- private run;
237
203
  }