@itookit/dsht 0.2.1 → 0.2.4

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.
package/dist/cli.js CHANGED
@@ -12,6 +12,7 @@ import { App } from "./app.js";
12
12
  import { sessionLabel } from "./navigation.js";
13
13
  import { CookieStore, login } from "./auth.js";
14
14
  import { Client } from "./client.js";
15
+ import { historyLimits } from "./memory.js";
15
16
  import { Controller } from "./controller.js";
16
17
  import { endpoint } from "./endpoint.js";
17
18
  import { errorText, safeText, string } from "./wire.js";
@@ -23,6 +24,8 @@ With no command, choose a workspace and session interactively.
23
24
  --workspace <id> Filter list sessions by workspace
24
25
  --session <id> Open a session directly
25
26
  --auth-dir <path> Private cookie directory (or DSHT_AUTH_DIR)
27
+ --history-records <n> Soft history record limit (default 2000)
28
+ --history-mb <n> Soft history payload budget in MiB (default 16)
26
29
  --json Print machine-readable list output
27
30
  --help Show this help
28
31
 
@@ -39,6 +42,7 @@ Examples:
39
42
  async function main() {
40
43
  const { values, positionals } = parseArgs({ allowPositionals: true, options: {
41
44
  url: { type: 'string', default: process.env.DSH_URL ?? 'http://127.0.0.1:3080' },
45
+ 'history-records': { type: 'string' }, 'history-mb': { type: 'string' },
42
46
  workspace: { type: 'string' }, session: { type: 'string' }, 'auth-dir': { type: 'string' }, json: { type: 'boolean' }, help: { type: 'boolean' },
43
47
  } });
44
48
  if (values.help) {
@@ -52,6 +56,7 @@ async function main() {
52
56
  throw new Error('--json and --workspace apply to list commands');
53
57
  if (list && values.session)
54
58
  throw new Error('--session applies to interactive mode');
59
+ const limits = historyLimits(values['history-records'], values['history-mb']);
55
60
  const { url, token } = endpoint(values.url, process.env.DSH_TOKEN);
56
61
  const store = new CookieStore(values['auth-dir']);
57
62
  if (list) {
@@ -91,7 +96,7 @@ async function main() {
91
96
  const costDirectory = join(process.env.DSHT_STATE_DIR ?? join(process.env.XDG_STATE_HOME ?? join(homedir(), '.local', 'state'), 'dsht'), 'cost', createHash('sha256').update(new URL(url).origin).digest('hex'));
92
97
  const costs = new CostLedger(prices, costDirectory);
93
98
  await costs.load();
94
- const controller = new Controller(url, token, values.session, undefined, client => login(client, token, store), costs);
99
+ const controller = new Controller(url, token, values.session, undefined, client => login(client, token, store), costs, limits);
95
100
  const app = render(_jsx(App, { controller: controller }), { exitOnCtrlC: false });
96
101
  const terminate = () => app.unmount();
97
102
  process.once('SIGTERM', terminate);
package/dist/client.d.ts CHANGED
@@ -48,6 +48,8 @@ export declare class Client {
48
48
  connect(): Promise<void>;
49
49
  /** Subscribe on the existing mux; each subscription has a fresh stream identity. */
50
50
  subscribe(endpoint: string, args: ObjectValue, listener: Listener): Subscription;
51
+ /** Archived session IDs from the latest authoritative workspace baseline. */
52
+ archivedSessionIds: ReadonlySet<string>;
51
53
  /** List workspaces by consuming and cancelling the authoritative opening baseline. */
52
54
  listWorkspaces(): Promise<ObjectValue[]>;
53
55
  /** List visible sessions, optionally filtering by the workspace's accounted IDs. */
package/dist/client.js CHANGED
@@ -160,6 +160,8 @@ export class Client {
160
160
  socket.send(JSON.stringify({ type: 'cancel', streamId }));
161
161
  } };
162
162
  }
163
+ /** Archived session IDs from the latest authoritative workspace baseline. */
164
+ archivedSessionIds = new Set();
163
165
  /** List workspaces by consuming and cancelling the authoritative opening baseline. */
164
166
  async listWorkspaces() {
165
167
  return new Promise((resolve, reject) => {
@@ -174,6 +176,7 @@ export class Client {
174
176
  const frame = object(value);
175
177
  if (frame.type !== 'baseline')
176
178
  throw new Error('Workspace stream omitted its baseline');
179
+ this.archivedSessionIds = new Set(array(object(frame.value).archivedSessionIds).map(string));
177
180
  resolve(array(object(frame.value).items).map(object));
178
181
  }
179
182
  catch (error) {
@@ -2,8 +2,17 @@ import { Client } from './client.ts';
2
2
  import { CostLedger } from './cost.ts';
3
3
  import { Telemetry } from './telemetry.ts';
4
4
  import { Transcript } from './transcript.ts';
5
+ import { type HistoryLimits } from './memory.ts';
5
6
  import { type FileReference } from './references.ts';
6
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
+ }
7
16
  /** State shared by the picker and conversation view. */
8
17
  export interface State {
9
18
  version: number;
@@ -20,9 +29,28 @@ export interface State {
20
29
  pending: ObjectValue[];
21
30
  controlError?: string;
22
31
  modelError?: string;
32
+ presetError?: string;
33
+ presets?: ObjectValue[];
23
34
  defaultModel?: ObjectValue;
24
35
  transcript: Transcript;
25
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[];
26
54
  /** Owns reconnects and subscriptions. User commands remain single-attempt operations. */
27
55
  export declare class Controller {
28
56
  readonly base: string;
@@ -30,8 +58,10 @@ export declare class Controller {
30
58
  private makeClient;
31
59
  private authenticate;
32
60
  readonly costs?: CostLedger | undefined;
61
+ readonly historyLimits: HistoryLimits;
33
62
  state: State;
34
63
  private observers;
64
+ private interactions;
35
65
  private abort;
36
66
  private client;
37
67
  private clientId;
@@ -39,8 +69,10 @@ export declare class Controller {
39
69
  private runTask;
40
70
  private generationFailed;
41
71
  private selection;
72
+ private historyPinned;
42
73
  telemetry: Telemetry;
43
74
  private observedRunningAt;
75
+ private presetClient?;
44
76
  private catalogRevision;
45
77
  private catalogTasks;
46
78
  private runningUpdates;
@@ -55,6 +87,20 @@ export declare class Controller {
55
87
  get running(): boolean;
56
88
  /** Current title projection, falling back to the list title and then the session ID. */
57
89
  get sessionName(): string | undefined;
90
+ /** Current agent-preset name, matching the web header's built-in labels and custom metadata. */
91
+ 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>;
58
104
  /** Epoch start from the retained turn log, or when this client first observed the run. */
59
105
  get workingSince(): number | undefined;
60
106
  /** Stop the selected turn, or allow exit only while idle. Repeated keys share one request.
@@ -62,7 +108,7 @@ export declare class Controller {
62
108
  * @returns True when the caller may exit; cancellation failures retain the client.
63
109
  */
64
110
  interrupt(force?: boolean): Promise<boolean>;
65
- constructor(base: string, token: string | undefined, initialSession?: string | undefined, makeClient?: () => Client, authenticate?: (client: Client) => Promise<void>, costs?: CostLedger | undefined);
111
+ constructor(base: string, token: string | undefined, initialSession?: string | undefined, makeClient?: () => Client, authenticate?: (client: Client) => Promise<void>, costs?: CostLedger | undefined, historyLimits?: HistoryLimits);
66
112
  /** React-compatible state subscription. */
67
113
  subscribe: (listener: () => void) => (() => void);
68
114
  /** Snapshot identity changes only when the controller publishes. */
@@ -71,6 +117,12 @@ export declare class Controller {
71
117
  start(): void;
72
118
  /** Cancel retries and HTTP, close the socket, and wait for the loop to settle. */
73
119
  stop(): Promise<void>;
120
+ /** Keep history stable while the user reads, searches, or expands it; trim again at the live tail.
121
+ * @param pinned - Whether the main transcript is actively being read away from its tail.
122
+ */
123
+ pinHistory(pinned: boolean): void;
124
+ private reclaimHistory;
125
+ private releaseTranscript;
74
126
  /** Stop the selected turn and then close, so quitting does not leave host work running.
75
127
  * An idle session stays untouched, and an in-flight cancellation is awaited rather than repeated.
76
128
  */
@@ -81,8 +133,22 @@ export declare class Controller {
81
133
  * @param signal - Optional cancellation for an explicit /cost refresh.
82
134
  */
83
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;
84
140
  /** Refresh both lists from the host, then show the requested picker. */
85
141
  showPicker(screen: 'workspaces' | 'sessions'): Promise<void>;
142
+ /** Resolve a removal command to one reviewable object without changing the selection.
143
+ * @param kind - Workspace registration removal or session archival.
144
+ * @param query - Exact name, ID, or unambiguous ID prefix.
145
+ * @returns The fixed identity and display details for confirmation.
146
+ */
147
+ removalTarget(kind: 'workspace' | 'session', query: string): Promise<RemovalTarget>;
148
+ /** Apply a confirmed removal or freshly verified empty-session archival; directories and logs are preserved.
149
+ * @param target - Exact workspace or session identity reviewed by the user.
150
+ */
151
+ removeTarget(target: RemovalTarget): Promise<void>;
86
152
  /** Pick a workspace, or use all sessions when the identity is omitted. */
87
153
  pickWorkspace(workspaceId?: string): void;
88
154
  /** Open a workspace picker, or resolve a workspace by ID, exact title/path, or unique ID prefix. */
@@ -122,7 +188,19 @@ export declare class Controller {
122
188
  /** Cancel the active turn; pending queue items remain host-owned. */
123
189
  cancelTurn(): Promise<void>;
124
190
  /** Add a page before the retained window using its fixed opening cut. */
125
- older(signal?: AbortSignal): Promise<void>;
191
+ older(signal?: AbortSignal, transcript?: Transcript): Promise<void>;
192
+ /** Search one page at a time, preserving only the first 200 matches and releasing temporary content.
193
+ * @param query - Literal, case-insensitive text including folded reasoning.
194
+ * @param signal - Cancels HTTP and processing without cancelling the agent.
195
+ * @returns Newest-first bounded summaries and an explicit truncation flag.
196
+ */
197
+ searchHistory(query: string, signal: AbortSignal): Promise<HistorySearch>;
198
+ /** Load a separate small window ending at a search target; the live transcript keeps following.
199
+ * @param target - Durable message sequence to display.
200
+ * @param signal - Cancels the target-page request.
201
+ * @returns A caller-owned historical window that must be disposed when closed.
202
+ */
203
+ historyAt(target: number, signal: AbortSignal): Promise<Transcript>;
126
204
  /** Load the prefix required for an explicit history jump; never loop on an unadvancing page.
127
205
  * @param target - Visible record sequence, or first for the oldest available history.
128
206
  * @param signal - Cancels local paging without interrupting the remote agent.
@@ -138,7 +216,6 @@ export declare class Controller {
138
216
  private get sessionId();
139
217
  private update;
140
218
  private reply;
141
- private releasePending;
142
219
  private refreshCatalog;
143
220
  private run;
144
221
  }