@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/README.i18n.yaml +2 -2
- package/README.md +47 -26
- package/README.zh.md +47 -26
- package/dist/app.d.ts +16 -1
- package/dist/app.js +450 -73
- package/dist/cli.js +6 -1
- package/dist/client.d.ts +2 -0
- package/dist/client.js +3 -0
- package/dist/controller.d.ts +80 -3
- package/dist/controller.js +350 -75
- package/dist/cost-view.js +3 -1
- package/dist/history-view.d.ts +8 -0
- package/dist/history-view.js +12 -0
- package/dist/history.d.ts +29 -12
- package/dist/history.js +172 -27
- package/dist/input-history.d.ts +19 -0
- package/dist/input-history.js +43 -0
- package/dist/input.d.ts +3 -1
- package/dist/input.js +3 -1
- package/dist/memory.d.ts +13 -0
- package/dist/memory.js +22 -0
- package/dist/mouse.d.ts +3 -1
- package/dist/mouse.js +15 -4
- package/dist/navigation.d.ts +1 -1
- package/dist/navigation.js +2 -2
- package/dist/status.d.ts +3 -1
- package/dist/status.js +63 -42
- package/dist/telemetry.d.ts +3 -0
- package/dist/telemetry.js +9 -0
- package/dist/theme.d.ts +15 -0
- package/dist/theme.js +15 -0
- package/dist/transcript.d.ts +91 -6
- package/dist/transcript.js +393 -49
- package/dsht.png +0 -0
- package/package.json +4 -2
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) {
|
package/dist/controller.d.ts
CHANGED
|
@@ -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
|
}
|