@fishwithcat/dsh-tui-app 0.0.0-stage → 0.2.2-alpha.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.
@@ -0,0 +1,146 @@
1
+ /**
2
+ * The local subagent-watch wire protocol shared by the publishing TUI and the
3
+ * read-only viewer. Frames are NDJSON; a connection opens with exactly one
4
+ * snapshot and then carries ordered events, assistant frames, status, and
5
+ * heartbeats.
6
+ * @module @deepseek-ai/dsh-tui-app/watch/protocol
7
+ */
8
+ import type { AssistantStreamFrame, AssistantStreamBaseline } from '@deepseek-ai/dsh-agent';
9
+ import type { SessionEvent, SessionHeader, SessionId } from '@deepseek-ai/dsh-session';
10
+ import type { LlmAttemptId, StreamChunk } from '@deepseek-ai/dsh-llm';
11
+ /** Wire version a publisher and viewer must share. */
12
+ export declare const WATCH_PROTOCOL_VERSION = 1;
13
+ /** Request header carrying the random access token. */
14
+ export declare const WATCH_TOKEN_HEADER = "x-dsh-watch-token";
15
+ /** Request header carrying the wire version. */
16
+ export declare const WATCH_PROTOCOL_HEADER = "x-dsh-watch-protocol";
17
+ /** Stream path, always queried with `?session=<id>`. */
18
+ export declare const WATCH_STREAM_PATH = "/v1/stream";
19
+ /** Execution state the publisher reports in the footer. */
20
+ export type WatchExecutionState = 'running' | 'idle';
21
+ /** How the viewer obtained the transcript. */
22
+ export type WatchConnectionState = 'online' | 'history' | 'disconnected';
23
+ /** One published connection record under the runtime directory. */
24
+ export interface WatchConnectionRecord {
25
+ /** Wire version this record was written for. */
26
+ readonly protocol: typeof WATCH_PROTOCOL_VERSION;
27
+ /** Process-local service identity; records from another instance are not ours to delete. */
28
+ readonly serviceInstanceId: string;
29
+ /** Child session this record addresses. */
30
+ readonly sessionId: SessionId;
31
+ /** Root session whose tree the service serves. */
32
+ readonly rootSessionId: SessionId;
33
+ /** Loopback HTTP origin, for example `http://127.0.0.1:43121`. */
34
+ readonly address: string;
35
+ /** Random bearer token; never placed in a command, URL, or log. */
36
+ readonly token: string;
37
+ }
38
+ /** One assistant frame on the watch wire; `start` carries the durable cursor. */
39
+ export type WatchAssistantFrame = {
40
+ readonly type: 'start';
41
+ readonly attemptId: LlmAttemptId;
42
+ readonly revision: number;
43
+ readonly startedAfterSeq: number;
44
+ readonly turn: number;
45
+ readonly step: number;
46
+ } | {
47
+ readonly type: 'chunk';
48
+ readonly attemptId: LlmAttemptId;
49
+ readonly revision: number;
50
+ readonly index: number;
51
+ readonly time: number;
52
+ readonly chunk: StreamChunk;
53
+ } | {
54
+ readonly type: 'end';
55
+ readonly attemptId: LlmAttemptId;
56
+ readonly revision: number;
57
+ readonly index: number;
58
+ readonly outcome: {
59
+ readonly kind: 'committed';
60
+ readonly eventType: 'assistant/message' | 'assistant/attempt';
61
+ readonly seq: number;
62
+ } | {
63
+ readonly kind: 'abandoned';
64
+ };
65
+ };
66
+ /** Opening snapshot: a complete cut plus the live assistant baseline. */
67
+ export interface WatchSnapshotFrame {
68
+ readonly type: 'snapshot';
69
+ /** Service identity the viewer compares with its record. */
70
+ readonly serviceInstanceId: string;
71
+ /** Session header the viewer shows and validates. */
72
+ readonly header: SessionHeader;
73
+ /** Last event seq included in `events`, or -1 for an empty log. */
74
+ readonly cursor: number;
75
+ /** Committed events in sequence order. */
76
+ readonly events: readonly SessionEvent[];
77
+ /** Current Agent lifecycle state. */
78
+ readonly status: WatchExecutionState;
79
+ /** Process-local assistant state at this revision. */
80
+ readonly assistantStream: AssistantStreamBaseline;
81
+ }
82
+ /** One frame the publisher sends after the opening snapshot. */
83
+ export type WatchServerFrame = WatchSnapshotFrame | {
84
+ readonly type: 'event';
85
+ readonly event: SessionEvent;
86
+ } | {
87
+ readonly type: 'assistant';
88
+ readonly frame: WatchAssistantFrame;
89
+ } | {
90
+ readonly type: 'status';
91
+ readonly status: WatchExecutionState;
92
+ }
93
+ /** Keeps an otherwise idle stream inside transport body timeouts. */
94
+ | {
95
+ readonly type: 'heartbeat';
96
+ } | {
97
+ readonly type: 'execution-end';
98
+ readonly stopReason: string;
99
+ } | {
100
+ readonly type: 'service-closed';
101
+ } | {
102
+ readonly type: 'error';
103
+ readonly message: string;
104
+ };
105
+ /**
106
+ * Encode a session id as a filesystem-safe record name.
107
+ * @param sessionId - the child session id.
108
+ * @returns URL-safe base64 of the UTF-8 id.
109
+ */
110
+ export declare function encodeSessionRecordName(sessionId: string): string;
111
+ /**
112
+ * Convert one process-local frame to its wire form.
113
+ * @param frame - the Agent frame.
114
+ * @param durableCursor - last committed seq observed when the frame arrived.
115
+ * @returns the wire frame; `start` carries the cursor.
116
+ */
117
+ export declare function wireAssistantFrame(frame: AssistantStreamFrame, durableCursor: number): WatchAssistantFrame;
118
+ /**
119
+ * Convert one wire frame back to the Agent shape the transcript folds.
120
+ * @param frame - the wire frame.
121
+ * @returns the Agent frame, with the wire-only cursor dropped from `start`.
122
+ */
123
+ export declare function agentAssistantFrame(frame: WatchAssistantFrame): AssistantStreamFrame;
124
+ /**
125
+ * Whether a string names a loopback HTTP origin this viewer may connect to.
126
+ * @param address - candidate origin from a record.
127
+ * @returns true only for a bare `http://127.0.0.1:<port>` origin.
128
+ */
129
+ export declare function isLoopbackWatchAddress(address: string): boolean;
130
+ /**
131
+ * Parse one JSON value from a record or wire frame.
132
+ *
133
+ * Both are file/wire boundaries, so object and field checks live here rather
134
+ * than in the consumers that trust the parsed value.
135
+ * @param value - decoded JSON.
136
+ * @returns the value when it is a non-null, non-array object.
137
+ */
138
+ export declare function asRecord(value: unknown): Record<string, unknown> | undefined;
139
+ /**
140
+ * Parse a connection record read from disk.
141
+ * @param value - decoded JSON.
142
+ * @returns the validated record.
143
+ * @throws when the record is corrupt, for another protocol, or not loopback.
144
+ */
145
+ export declare function parseWatchConnectionRecord(value: unknown): WatchConnectionRecord;
146
+ //# sourceMappingURL=protocol.d.ts.map
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Runtime connection records for local subagent watching.
3
+ *
4
+ * A record is disposable runtime data: it names the loopback origin, a random
5
+ * token, and the service instance that wrote it. Records live in a private
6
+ * directory under `$DSH_HOME/runtime/subagent-watch`, one file per child
7
+ * session, and are never part of the Session format.
8
+ * @module @deepseek-ai/dsh-tui-app/watch/record
9
+ */
10
+ import type { SessionId } from '@deepseek-ai/dsh-session';
11
+ import type { WatchConnectionRecord } from './protocol.ts';
12
+ /**
13
+ * Directory holding published connection records.
14
+ * @returns the absolute runtime directory; it is resolved on every call so tests can change `$DSH_HOME`.
15
+ */
16
+ export declare function watchRecordDirectory(): string;
17
+ /**
18
+ * Path of one session's record.
19
+ * @param sessionId - the child session id.
20
+ * @returns the absolute record path.
21
+ */
22
+ export declare function watchRecordPath(sessionId: string): string;
23
+ /**
24
+ * Publish one record atomically with owner-only permissions.
25
+ *
26
+ * A temporary file in the same directory is written and renamed into place, so
27
+ * a reader never observes a partial record.
28
+ * @param record - the validated connection record.
29
+ */
30
+ export declare function publishWatchRecord(record: WatchConnectionRecord): Promise<void>;
31
+ /**
32
+ * Read one published record.
33
+ * @param sessionId - the child session id.
34
+ * @returns the validated record, or undefined when no record was published.
35
+ * @throws when the file exists but is unreadable, malformed, or for another protocol.
36
+ */
37
+ export declare function readWatchRecord(sessionId: string): Promise<WatchConnectionRecord | undefined>;
38
+ /**
39
+ * Remove one record only when this service instance wrote it.
40
+ * @param sessionId - the child session id.
41
+ * @param serviceInstanceId - this service's identity.
42
+ */
43
+ export declare function removeOwnedWatchRecord(sessionId: SessionId, serviceInstanceId: string): Promise<void>;
44
+ /**
45
+ * Remove every record this service instance published.
46
+ * @param sessionIds - sessions this service published.
47
+ * @param serviceInstanceId - this service's identity.
48
+ */
49
+ export declare function removeOwnedWatchRecords(sessionIds: Iterable<SessionId>, serviceInstanceId: string): Promise<void>;
50
+ //# sourceMappingURL=record.d.ts.map
@@ -0,0 +1,172 @@
1
+ /**
2
+ * The publishing side of cross-terminal subagent watching.
3
+ *
4
+ * One hub serves every local subagent in the TUI's session tree from a single
5
+ * loopback HTTP listener. It owns the HTTP service, the lifecycle/event
6
+ * subscriptions, the shared assistant-stream state, per-client bounded write
7
+ * queues, and the runtime connection records. It never changes agent-loop.
8
+ * @module @deepseek-ai/dsh-tui-app/watch/server
9
+ */
10
+ import type { ServerResponse } from 'node:http';
11
+ import type { Context } from '@deepseek-ai/cordis';
12
+ import type { SessionId } from '@deepseek-ai/dsh-session';
13
+ import type { WatchAssistantFrame, WatchServerFrame, WatchSnapshotFrame } from './protocol.ts';
14
+ /** Largest number of bytes a single viewer may fall behind before it is disconnected. */
15
+ export declare const WATCH_CLIENT_MAX_QUEUED_BYTES = 1000000;
16
+ /** Largest number of frames a single viewer may fall behind before it is disconnected. */
17
+ export declare const WATCH_CLIENT_MAX_QUEUED_FRAMES = 4096;
18
+ /**
19
+ * Interval between empty-stream heartbeats. Node's fetch body timeout is five
20
+ * minutes, so a quiet child stream needs traffic well inside that window.
21
+ */
22
+ export declare const WATCH_HEARTBEAT_MS = 20000;
23
+ /** Callbacks the owning TUI registers to report publication outcomes. */
24
+ export interface SubagentWatchHooks {
25
+ /**
26
+ * A child's watch record is published; the command is safe to show.
27
+ * @param sessionId - the viewable child session.
28
+ * @param command - shell command naming only the session id.
29
+ */
30
+ published(sessionId: SessionId, command: string): void;
31
+ /**
32
+ * A child could not be made viewable.
33
+ * @param sessionId - the child session.
34
+ * @param error - the publication or listener failure.
35
+ */
36
+ failed(sessionId: SessionId, error: unknown): void;
37
+ }
38
+ /**
39
+ * One viewer's NDJSON response with an independent bounded queue.
40
+ *
41
+ * A viewer that stops reading falls behind in this queue rather than in the
42
+ * Agent's event loop. Exceeding either bound destroys that response and leaves
43
+ * every other viewer and the Agent untouched.
44
+ */
45
+ export declare class WatchConnection {
46
+ private readonly response;
47
+ private readonly onClose;
48
+ private readonly queue;
49
+ private queuedBytes;
50
+ private closed;
51
+ private ending;
52
+ private notified;
53
+ private paused;
54
+ private blocked;
55
+ private readonly held;
56
+ private heldBytes;
57
+ private readonly heartbeat;
58
+ /**
59
+ * @param response - the HTTP response this connection owns.
60
+ * @param onClose - called exactly once when the response ends or is destroyed.
61
+ */
62
+ constructor(response: ServerResponse, onClose: () => void);
63
+ /** Whether this connection can still accept frames. */
64
+ get writable(): boolean;
65
+ /**
66
+ * Queue one frame for the viewer.
67
+ * @param frame - the frame to serialize.
68
+ * @returns false when the frame was dropped because the queue is full.
69
+ */
70
+ send(frame: WatchServerFrame): boolean;
71
+ /**
72
+ * Queue one assistant frame tagged with its arrival position.
73
+ *
74
+ * Revision restarts when the Agent lifecycle is replaced, so the opening
75
+ * snapshot cuts held assistant frames by arrival position rather than
76
+ * revision.
77
+ * @param frame - the assistant wire frame.
78
+ * @param ordinal - monotonic per-child arrival position.
79
+ * @returns false when the frame was dropped because the queue is full.
80
+ */
81
+ sendAssistant(frame: WatchAssistantFrame, ordinal: number): boolean;
82
+ private enqueue;
83
+ /** Hold live frames while an opening snapshot is read. */
84
+ pause(): void;
85
+ /**
86
+ * Write the one opening snapshot outside the incremental queue bound.
87
+ *
88
+ * A complete history line can exceed the per-increment budget; it is written
89
+ * once, before any held increment, and is the only frame allowed to do so.
90
+ * @param frame - the opening snapshot.
91
+ */
92
+ sendSnapshot(frame: WatchSnapshotFrame): void;
93
+ /**
94
+ * Release held frames, dropping the ones the snapshot already represents.
95
+ * @param cursor - last durable seq in the snapshot.
96
+ * @param assistantOrdinal - last assistant arrival position in the snapshot.
97
+ */
98
+ resume(cursor: number, assistantOrdinal: number): void;
99
+ /**
100
+ * Queue free-form NDJSON text.
101
+ * @param payload - one complete line, including its newline.
102
+ * @returns false when the payload was dropped because the queue is full.
103
+ */
104
+ write(payload: string): boolean;
105
+ /** Flush queued frames, then end the response. */
106
+ end(): void;
107
+ /** Drop the connection immediately, discarding queued frames. */
108
+ abort(): void;
109
+ private notifyClose;
110
+ private pump;
111
+ }
112
+ /**
113
+ * Owns the loopback service, the tracked child states, and the published
114
+ * records for one TUI process.
115
+ */
116
+ export declare class SubagentWatchHub {
117
+ private readonly ctx;
118
+ private readonly serviceInstanceId;
119
+ private readonly token;
120
+ private rootSessionId;
121
+ private hooks;
122
+ private server;
123
+ private starting;
124
+ private readonly children;
125
+ private readonly published;
126
+ private readonly disposers;
127
+ private closed;
128
+ private closing;
129
+ /** Whether close() has started; a getter avoids narrowing across awaits. */
130
+ private get isClosed();
131
+ /**
132
+ * @param ctx - the TUI plugin context carrying the Agent registry.
133
+ */
134
+ constructor(ctx: Context);
135
+ /**
136
+ * Begin tracking one root session's local subagent tree.
137
+ * @param rootSessionId - the TUI's own session.
138
+ * @param hooks - publication outcomes to report to the surface.
139
+ */
140
+ activate(rootSessionId: SessionId, hooks: SubagentWatchHooks): void;
141
+ /**
142
+ * Move the tracked root to a replaced TUI session.
143
+ * @param rootSessionId - the replacement root.
144
+ */
145
+ rebind(rootSessionId: SessionId): Promise<void>;
146
+ /**
147
+ * Close the service, settle every viewer, and remove this instance's records.
148
+ * Repeat calls await the same completion.
149
+ * @returns completion after the listener and every record are gone.
150
+ */
151
+ close(): Promise<void>;
152
+ private closeOnce;
153
+ /** Track one published local child synchronously, before its first model frame. */
154
+ private onStart;
155
+ /** Report one settled execution without closing its viewer. */
156
+ private onEnd;
157
+ private onSessionEvent;
158
+ private onAssistantFrame;
159
+ private onAgentStatus;
160
+ private onAgentDisposed;
161
+ /** Start the loopback listener once, then publish one child's record. */
162
+ private publish;
163
+ private ensureServer;
164
+ private handle;
165
+ private tokenMatches;
166
+ /**
167
+ * Subscribe first, read the opening cut, send it, then release only the
168
+ * increments after that cut.
169
+ */
170
+ private openStream;
171
+ }
172
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1,128 @@
1
+ /**
2
+ * The read-only terminal viewer for one local subagent session.
3
+ *
4
+ * It reuses the transcript model, message rendering, and scrolling components,
5
+ * but creates no Agent, installs no answerer, and starts no stream service. Esc,
6
+ * Ctrl+C, and Ctrl+D leave; a lost connection keeps the trusted screen and
7
+ * reports the disconnect without reconnecting.
8
+ * @module @deepseek-ai/dsh-tui-app/watch/viewer
9
+ */
10
+ import type { Context } from '@deepseek-ai/cordis';
11
+ import type { Component } from '@earendil-works/pi-tui';
12
+ import type { TuiTheme } from '../ansi.ts';
13
+ import type { Config } from '../config.ts';
14
+ import type { TuiMeasurement } from '../measurement.ts';
15
+ import type { WatchExecutionState } from './protocol.ts';
16
+ /** Everything one watch invocation needs from its launcher. */
17
+ export interface WatchAppOptions {
18
+ /** The plugin context the tree mounted. */
19
+ ctx: Context;
20
+ /** Validated app settings. */
21
+ config: Config;
22
+ /** Child session id to view. */
23
+ watch: string;
24
+ /** Request bounded process exit with `code`. */
25
+ exit(code: number): void;
26
+ }
27
+ /**
28
+ * The pinned watch footer: child identity, execution and connection state,
29
+ * followed by usage measured from the child's committed events.
30
+ */
31
+ export declare class WatchStatusBar implements Component {
32
+ private readonly theme;
33
+ private sessionId;
34
+ private connection;
35
+ private execution;
36
+ private readonly usage;
37
+ /**
38
+ * @param theme - the surface theme.
39
+ */
40
+ constructor(theme: TuiTheme);
41
+ /**
42
+ * Replace the rendered facts.
43
+ * @param facts - child identity, execution and connection state, and available usage.
44
+ */
45
+ set(facts: {
46
+ sessionId: string;
47
+ connection: 'online' | 'history' | 'disconnected';
48
+ execution?: WatchExecutionState | undefined;
49
+ measurement?: TuiMeasurement | undefined;
50
+ }): void;
51
+ /** Drop cached render state. */
52
+ invalidate(): void;
53
+ /**
54
+ * Render the footer.
55
+ * @param width - the viewport width in columns.
56
+ * @returns a blank margin, separator, identity, and usage lines within `width`.
57
+ */
58
+ render(width: number): string[];
59
+ private connectionText;
60
+ private executionText;
61
+ /** Place the right group against the left at the footer's edges. */
62
+ private pairLine;
63
+ }
64
+ /** The read-only viewer application. */
65
+ export declare class WatchApp {
66
+ private readonly options;
67
+ private readonly theme;
68
+ private readonly transcript;
69
+ private readonly transcriptView;
70
+ private readonly statusBar;
71
+ private readonly tui;
72
+ private readonly viewport;
73
+ private readonly copySelection;
74
+ private readonly disposers;
75
+ private stream;
76
+ private connection;
77
+ private execution;
78
+ private cursor;
79
+ private streamRevision;
80
+ private expectedChunk;
81
+ private attemptId;
82
+ private failed;
83
+ private leaving;
84
+ private stopped;
85
+ private header;
86
+ private inheritedEventCount;
87
+ private checkpoint;
88
+ private measurement;
89
+ private constructor();
90
+ /**
91
+ * Open the viewer for one child session.
92
+ * @param options - launcher context, settings, target, and exit request.
93
+ * @returns the mounted viewer.
94
+ * @throws when no interactive terminal exists, or the record, service, or history read fails.
95
+ */
96
+ static boot(options: WatchAppOptions): Promise<WatchApp>;
97
+ /** Resolve online versus history, apply the opening cut, and mount the surface. */
98
+ private open;
99
+ /** Build the surface, subscribe to exit keys, and start rendering. */
100
+ private mount;
101
+ /**
102
+ * Leave the viewer.
103
+ * @param code - process exit code.
104
+ */
105
+ stop(code: number): void;
106
+ /** Apply the complete opening cut and replay any active assistant attempt. */
107
+ private applySnapshot;
108
+ /** Replay the compact active attempt so a mid-response join shows its prefix. */
109
+ private replayAttempt;
110
+ /** Fold stored history with sequence continuity checks. */
111
+ private applyHistory;
112
+ private applyEvents;
113
+ private onEvent;
114
+ private onAssistant;
115
+ private onStatus;
116
+ private onExecutionEnd;
117
+ /** Stop applying updates, keep the trusted screen, and report the disconnect. */
118
+ private disconnect;
119
+ private protocolFailure;
120
+ private refresh;
121
+ /** Initialize projection state from the complete opening cut, including inherited history. */
122
+ private resetMeasurement;
123
+ /** Advance cached projection state only when committed events arrive. */
124
+ private measureEvents;
125
+ /** Restore the terminal exactly once. */
126
+ private teardown;
127
+ }
128
+ //# sourceMappingURL=viewer.d.ts.map
package/locale/de.json ADDED
@@ -0,0 +1,6 @@
1
+ {
2
+ "meta": {
3
+ "title": "Terminal-Oberfläche",
4
+ "description": "Interaktive Vollbild-Terminaloberfläche, die einen Agent und eine Session über dsh-base steuert."
5
+ }
6
+ }
package/locale/en.json ADDED
@@ -0,0 +1,6 @@
1
+ {
2
+ "meta": {
3
+ "title": "Terminal UI",
4
+ "description": "The interactive full-screen terminal surface that drives one Agent and Session over dsh-base."
5
+ }
6
+ }
package/locale/es.json ADDED
@@ -0,0 +1,6 @@
1
+ {
2
+ "meta": {
3
+ "title": "Interfaz de terminal",
4
+ "description": "Superficie de terminal interactiva a pantalla completa que controla un Agent y una Session sobre dsh-base."
5
+ }
6
+ }
package/locale/fr.json ADDED
@@ -0,0 +1,6 @@
1
+ {
2
+ "meta": {
3
+ "title": "Interface de terminal",
4
+ "description": "Surface de terminal interactive en plein écran qui pilote un Agent et une Session sur dsh-base."
5
+ }
6
+ }
package/locale/ja.json ADDED
@@ -0,0 +1,6 @@
1
+ {
2
+ "meta": {
3
+ "title": "ターミナル UI",
4
+ "description": "dsh-base 上で単一の Agent と Session を操作する全画面対話型ターミナル。"
5
+ }
6
+ }
package/locale/pt.json ADDED
@@ -0,0 +1,6 @@
1
+ {
2
+ "meta": {
3
+ "title": "Interface de terminal",
4
+ "description": "Superfície de terminal interativa em tela cheia que controla um Agent e uma Session sobre o dsh-base."
5
+ }
6
+ }
package/locale/ru.json ADDED
@@ -0,0 +1,6 @@
1
+ {
2
+ "meta": {
3
+ "title": "Терминальный интерфейс",
4
+ "description": "Интерактивный полноэкранный терминальный интерфейс для одного Agent и Session на dsh-base."
5
+ }
6
+ }
package/locale/zh.json ADDED
@@ -0,0 +1,6 @@
1
+ {
2
+ "meta": {
3
+ "title": "终端界面",
4
+ "description": "基于 dsh-base 驱动单个 Agent 与会话的全屏交互式终端界面。"
5
+ }
6
+ }
package/package.json CHANGED
@@ -1,6 +1,112 @@
1
1
  {
2
2
  "name": "@fishwithcat/dsh-tui-app",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "description": "The dsh terminal application: an interactive full-screen TUI that drives one in-process Agent over dsh-base",
4
+ "version": "0.2.2-alpha.2",
5
+ "publishConfig": {
6
+ "access": "public"
7
+ },
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "https://github.com/FishwithCat/deepseek-harness-tui",
11
+ "directory": "packages/bundle/tui-app"
12
+ },
13
+ "type": "module",
14
+ "main": "lib/index.js",
15
+ "types": "lib/types/index.d.ts",
16
+ "exports": {
17
+ ".": {
18
+ "types": "./lib/types/index.d.ts",
19
+ "default": "./lib/index.js"
20
+ },
21
+ "./startup": {
22
+ "types": "./lib/types/startup.d.ts",
23
+ "default": "./lib/startup.js"
24
+ },
25
+ "./cordis.patch.yml": "./cordis.patch.yml",
26
+ "./src/*": "./src/*",
27
+ "./package.json": "./package.json",
28
+ "./locale/*.json": "./locale/*.json"
29
+ },
30
+ "files": [
31
+ "locale/*.json",
32
+ "lib/index.js",
33
+ "lib/startup.js",
34
+ "cordis.patch.yml",
35
+ "lib/types/**/*.d.ts"
36
+ ],
37
+ "license": "MIT",
38
+ "dsh": {
39
+ "bundle": {
40
+ "patch": "./cordis.patch.yml"
41
+ }
42
+ },
43
+ "dependencies": {
44
+ "@deepseek-ai/dsh-brand": "0.2.2-alpha.2",
45
+ "@deepseek-ai/dsh-cmdline": "0.2.2-alpha.2",
46
+ "@deepseek-ai/dsh-home-paths": "0.2.2-alpha.2",
47
+ "@deepseek-ai/dsh-session-stats": "0.2.2-alpha.2",
48
+ "@deepseek-ai/dsh-tool-ask-user": "npm:@fishwithcat/dsh-tool-ask-user@0.2.2-alpha.2",
49
+ "@deepseek-ai/dsh-util-values": "0.2.2-alpha.2",
50
+ "@deepseek-ai/schemastery": "~3.18.6-alpha.1",
51
+ "@earendil-works/pi-tui": "^0.85.1",
52
+ "commander": "^15.0.0",
53
+ "diff": "^9.0.0"
54
+ },
55
+ "peerDependencies": {
56
+ "@deepseek-ai/cordis": "~4.0.6-alpha.1",
57
+ "@deepseek-ai/cordis-plugin-loader": "~1.0.7-alpha.1",
58
+ "@deepseek-ai/dsh-agent": "0.2.2-alpha.2",
59
+ "@deepseek-ai/dsh-agent-default-model": "0.2.2-alpha.2",
60
+ "@deepseek-ai/dsh-attachment": "0.2.2-alpha.2",
61
+ "@deepseek-ai/dsh-commands": "0.2.2-alpha.2",
62
+ "@deepseek-ai/dsh-compaction": "0.2.2-alpha.2",
63
+ "@deepseek-ai/dsh-llm": "0.2.2-alpha.2",
64
+ "@deepseek-ai/dsh-plan-mode": "0.2.2-alpha.2",
65
+ "@deepseek-ai/dsh-sandbox-policy": "0.2.2-alpha.2",
66
+ "@deepseek-ai/dsh-session": "0.2.2-alpha.2",
67
+ "@deepseek-ai/dsh-session-persistence": "0.2.2-alpha.2",
68
+ "@deepseek-ai/dsh-session-projection": "0.2.2-alpha.2",
69
+ "@deepseek-ai/dsh-session-query": "0.2.2-alpha.2",
70
+ "@deepseek-ai/dsh-shell": "0.2.2-alpha.2",
71
+ "@deepseek-ai/dsh-skill": "0.2.2-alpha.2",
72
+ "@deepseek-ai/dsh-subagent": "0.2.2-alpha.2",
73
+ "@deepseek-ai/dsh-token-meter": "0.2.2-alpha.2",
74
+ "@deepseek-ai/dsh-tool-ask-user": "0.2.2-alpha.2",
75
+ "@deepseek-ai/dsh-tools": "0.2.2-alpha.2",
76
+ "@deepseek-ai/dsh-user-approval": "0.2.2-alpha.2",
77
+ "@deepseek-ai/dsh-user-questions": "0.2.2-alpha.2",
78
+ "@deepseek-ai/dsh-working-directory": "0.2.2-alpha.2"
79
+ },
80
+ "devDependencies": {
81
+ "@deepseek-ai/cordis": "~4.0.6-alpha.1",
82
+ "@deepseek-ai/cordis-plugin-include": "~1.0.11-alpha.1",
83
+ "@deepseek-ai/cordis-plugin-loader": "~1.0.7-alpha.1",
84
+ "@deepseek-ai/dsh-agent": "0.2.2-alpha.2",
85
+ "@deepseek-ai/dsh-agent-default-model": "0.2.2-alpha.2",
86
+ "@deepseek-ai/dsh-agent-loop": "0.2.2-alpha.2",
87
+ "@deepseek-ai/dsh-agent-loop-testkit": "0.2.2-alpha.2",
88
+ "@deepseek-ai/dsh-attachment": "0.2.2-alpha.2",
89
+ "@deepseek-ai/dsh-attachment-local": "0.2.2-alpha.2",
90
+ "@deepseek-ai/dsh-bash-local": "0.2.2-alpha.2",
91
+ "@deepseek-ai/dsh-commands": "0.2.2-alpha.2",
92
+ "@deepseek-ai/dsh-compaction": "0.2.2-alpha.2",
93
+ "@deepseek-ai/dsh-llm": "0.2.2-alpha.2",
94
+ "@deepseek-ai/dsh-plan-mode": "0.2.2-alpha.2",
95
+ "@deepseek-ai/dsh-sandbox-policy": "0.2.2-alpha.2",
96
+ "@deepseek-ai/dsh-session": "0.2.2-alpha.2",
97
+ "@deepseek-ai/dsh-session-persistence": "0.2.2-alpha.2",
98
+ "@deepseek-ai/dsh-session-projection": "0.2.2-alpha.2",
99
+ "@deepseek-ai/dsh-session-query": "0.2.2-alpha.2",
100
+ "@deepseek-ai/dsh-shell": "0.2.2-alpha.2",
101
+ "@deepseek-ai/dsh-skill": "0.2.2-alpha.2",
102
+ "@deepseek-ai/dsh-subagent": "0.2.2-alpha.2",
103
+ "@deepseek-ai/dsh-subprocess-local": "0.2.2-alpha.2",
104
+ "@deepseek-ai/dsh-system-prompt": "0.2.2-alpha.2",
105
+ "@deepseek-ai/dsh-token-meter": "0.2.2-alpha.2",
106
+ "@deepseek-ai/dsh-tool-executor-native": "0.2.2-alpha.2",
107
+ "@deepseek-ai/dsh-tools": "0.2.2-alpha.2",
108
+ "@deepseek-ai/dsh-user-approval": "0.2.2-alpha.2",
109
+ "@deepseek-ai/dsh-user-questions": "0.2.2-alpha.2",
110
+ "@deepseek-ai/dsh-working-directory": "0.2.2-alpha.2"
111
+ }
112
+ }