@deepseek-ai/dsh-api-terminal-controller 0.1.6-alpha.1
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/LICENSE +21 -0
- package/README.i18n.yaml +6 -0
- package/README.md +93 -0
- package/README.zh.md +93 -0
- package/lib/client.js +677 -0
- package/lib/index.js +844 -0
- package/lib/typert.host.d.ts +3 -0
- package/lib/typert.host.js +1131 -0
- package/lib/typert.remote-client.d.ts +49 -0
- package/lib/typert.remote-client.js +529 -0
- package/lib/types/client/close-requests.d.ts +31 -0
- package/lib/types/client/close-requests.js +75 -0
- package/lib/types/client/index.d.ts +88 -0
- package/lib/types/client/index.js +157 -0
- package/lib/types/client/model.d.ts +119 -0
- package/lib/types/client/model.js +323 -0
- package/lib/types/client/shell-preference.d.ts +11 -0
- package/lib/types/client/shell-preference.js +26 -0
- package/lib/types/index.d.ts +135 -0
- package/lib/types/index.js +371 -0
- package/lib/types/shells.d.ts +21 -0
- package/lib/types/shells.js +54 -0
- package/lib/types/stream.d.ts +29 -0
- package/lib/types/stream.js +78 -0
- package/lib/types/terminal.d.ts +61 -0
- package/lib/types/terminal.js +168 -0
- package/lib/types/types.d.ts +69 -0
- package/lib/types/types.js +2 -0
- package/package.json +93 -0
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/** A bounded output queue for one Remote stream generation. */
|
|
2
|
+
import { Deque } from '@deepseek-ai/dsh-deque';
|
|
3
|
+
/** Slow followers fail explicitly; a later attachment recovers from the screen. */
|
|
4
|
+
export class TerminalFollower {
|
|
5
|
+
maxBytes;
|
|
6
|
+
queue = new Deque();
|
|
7
|
+
bytes = 0;
|
|
8
|
+
wake;
|
|
9
|
+
closed = false;
|
|
10
|
+
finished = false;
|
|
11
|
+
failure;
|
|
12
|
+
/** @param maxBytes - maximum queued UTF-8 bytes for this follower. */
|
|
13
|
+
constructor(maxBytes) {
|
|
14
|
+
this.maxBytes = maxBytes;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Queue a frame or fail this follower when its byte limit is exceeded.
|
|
18
|
+
* @param frame - next ordered frame.
|
|
19
|
+
*/
|
|
20
|
+
push(frame) {
|
|
21
|
+
if (this.closed || this.finished)
|
|
22
|
+
return;
|
|
23
|
+
const bytes = Buffer.byteLength(JSON.stringify(frame), 'utf8');
|
|
24
|
+
if (this.bytes + bytes > this.maxBytes) {
|
|
25
|
+
this.failure = new Error('Terminal output consumer exceeded its buffer; reconnect to recover the current screen');
|
|
26
|
+
this.close();
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
this.queue.pushBack({ frame, bytes });
|
|
30
|
+
this.bytes += bytes;
|
|
31
|
+
this.wake?.();
|
|
32
|
+
}
|
|
33
|
+
/** Finish after delivering every queued frame, including the final exit state. */
|
|
34
|
+
finish() {
|
|
35
|
+
this.finished = true;
|
|
36
|
+
this.wake?.();
|
|
37
|
+
}
|
|
38
|
+
/** Stop this follower without stopping its terminal. */
|
|
39
|
+
close() {
|
|
40
|
+
this.closed = true;
|
|
41
|
+
this.queue.clear();
|
|
42
|
+
this.bytes = 0;
|
|
43
|
+
this.wake?.();
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Drain until detached or failed.
|
|
47
|
+
* @param signal - Remote generation cancellation.
|
|
48
|
+
* @returns ordered terminal frames.
|
|
49
|
+
*/
|
|
50
|
+
async *read(signal) {
|
|
51
|
+
const abort = () => { this.close(); };
|
|
52
|
+
signal.addEventListener('abort', abort, { once: true });
|
|
53
|
+
if (signal.aborted)
|
|
54
|
+
abort();
|
|
55
|
+
try {
|
|
56
|
+
while (!this.closed) {
|
|
57
|
+
const next = this.queue.popFront();
|
|
58
|
+
if (next !== undefined) {
|
|
59
|
+
this.bytes -= next.bytes;
|
|
60
|
+
yield next.frame;
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
if (this.finished)
|
|
64
|
+
break;
|
|
65
|
+
await new Promise((resolve) => { this.wake = resolve; });
|
|
66
|
+
this.wake = undefined;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
if (this.failure !== undefined)
|
|
70
|
+
throw this.failure;
|
|
71
|
+
}
|
|
72
|
+
finally {
|
|
73
|
+
signal.removeEventListener('abort', abort);
|
|
74
|
+
this.close();
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=stream.js.map
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { SubprocessTerminalHandle } from '@deepseek-ai/dsh-subprocess';
|
|
2
|
+
import type { TerminalAttachmentId, TerminalFrame, WebTerminalInfo } from './types.ts';
|
|
3
|
+
/** Process lifetime is independent of follower and component lifetimes. */
|
|
4
|
+
export declare class BrowserTerminal {
|
|
5
|
+
private readonly handle;
|
|
6
|
+
info: WebTerminalInfo;
|
|
7
|
+
private readonly maxBufferedBytes;
|
|
8
|
+
private readonly screen;
|
|
9
|
+
private readonly serializer;
|
|
10
|
+
private readonly followers;
|
|
11
|
+
private sequence;
|
|
12
|
+
private operations;
|
|
13
|
+
private readonly drained;
|
|
14
|
+
private closing;
|
|
15
|
+
private controller;
|
|
16
|
+
/**
|
|
17
|
+
* @param handle - allocated terminal process range.
|
|
18
|
+
* @param info - initial metadata.
|
|
19
|
+
* @param scrollback - maximum retained scrollback rows.
|
|
20
|
+
* @param maxBufferedBytes - per-follower queue cap.
|
|
21
|
+
*/
|
|
22
|
+
constructor(handle: SubprocessTerminalHandle, info: WebTerminalInfo, scrollback: number, maxBufferedBytes: number);
|
|
23
|
+
/**
|
|
24
|
+
* Attach with exclusive input control; an older attachment becomes read-only.
|
|
25
|
+
* @param id - browser attachment identity.
|
|
26
|
+
* @param signal - attachment cancellation; never terminates the process.
|
|
27
|
+
* @returns a consistent screen followed by ordered output and state changes.
|
|
28
|
+
*/
|
|
29
|
+
follow(id: TerminalAttachmentId, signal: AbortSignal): AsyncIterable<TerminalFrame>;
|
|
30
|
+
/**
|
|
31
|
+
* Send raw terminal input without command interpretation.
|
|
32
|
+
* @param id - current writable attachment.
|
|
33
|
+
* @param data - UTF-8 input, including shell completion/control keys.
|
|
34
|
+
* @returns when the provider accepts the input.
|
|
35
|
+
*/
|
|
36
|
+
write(id: TerminalAttachmentId, data: string): Promise<void>;
|
|
37
|
+
/**
|
|
38
|
+
* Resize the PTY and recovery screen in the same operation order as output.
|
|
39
|
+
* @param id - current writable attachment.
|
|
40
|
+
* @param cols - validated column count.
|
|
41
|
+
* @param rows - validated row count.
|
|
42
|
+
* @returns when the provider and emulator use the new dimensions.
|
|
43
|
+
*/
|
|
44
|
+
resize(id: TerminalAttachmentId, cols: number, rows: number): Promise<void>;
|
|
45
|
+
/**
|
|
46
|
+
* Publish a display name to every attached view.
|
|
47
|
+
* @param title - validated user title.
|
|
48
|
+
*/
|
|
49
|
+
rename(title: string): void;
|
|
50
|
+
/**
|
|
51
|
+
* Terminate the complete provider-owned process range before releasing its screen.
|
|
52
|
+
* @returns after process cleanup and final output drainage; failures remain retryable.
|
|
53
|
+
*/
|
|
54
|
+
close(): Promise<void>;
|
|
55
|
+
private requireController;
|
|
56
|
+
private broadcast;
|
|
57
|
+
private enqueue;
|
|
58
|
+
private consume;
|
|
59
|
+
private output;
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=terminal.d.ts.map
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
/** One PTY, a bounded terminal emulator and its detachable browser followers. */
|
|
2
|
+
import { createRequire } from 'node:module';
|
|
3
|
+
import { RemoteError } from '@deepseek-ai/dsh-typert-protocol';
|
|
4
|
+
import { TerminalFollower } from "./stream.js";
|
|
5
|
+
const { Terminal, SerializeAddon } = loadXterm();
|
|
6
|
+
function loadXterm() {
|
|
7
|
+
// The Preview's CommonJS wrapper owns its outer require binding; these literal calls also retain the CJS entries.
|
|
8
|
+
const require = createRequire(import.meta.url);
|
|
9
|
+
const { Terminal } = require('@xterm/headless');
|
|
10
|
+
const { SerializeAddon } = require('@xterm/addon-serialize');
|
|
11
|
+
return { Terminal, SerializeAddon };
|
|
12
|
+
}
|
|
13
|
+
/** Process lifetime is independent of follower and component lifetimes. */
|
|
14
|
+
export class BrowserTerminal {
|
|
15
|
+
handle;
|
|
16
|
+
info;
|
|
17
|
+
maxBufferedBytes;
|
|
18
|
+
screen;
|
|
19
|
+
serializer;
|
|
20
|
+
followers = new Set();
|
|
21
|
+
sequence = 0;
|
|
22
|
+
operations = Promise.resolve();
|
|
23
|
+
drained;
|
|
24
|
+
closing;
|
|
25
|
+
controller;
|
|
26
|
+
/**
|
|
27
|
+
* @param handle - allocated terminal process range.
|
|
28
|
+
* @param info - initial metadata.
|
|
29
|
+
* @param scrollback - maximum retained scrollback rows.
|
|
30
|
+
* @param maxBufferedBytes - per-follower queue cap.
|
|
31
|
+
*/
|
|
32
|
+
constructor(handle, info, scrollback, maxBufferedBytes) {
|
|
33
|
+
this.handle = handle;
|
|
34
|
+
this.info = info;
|
|
35
|
+
this.maxBufferedBytes = maxBufferedBytes;
|
|
36
|
+
this.screen = new Terminal({ cols: info.cols, rows: info.rows, scrollback, allowProposedApi: true });
|
|
37
|
+
this.serializer = new SerializeAddon();
|
|
38
|
+
this.screen.loadAddon(this.serializer);
|
|
39
|
+
this.drained = this.consume();
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Attach with exclusive input control; an older attachment becomes read-only.
|
|
43
|
+
* @param id - browser attachment identity.
|
|
44
|
+
* @param signal - attachment cancellation; never terminates the process.
|
|
45
|
+
* @returns a consistent screen followed by ordered output and state changes.
|
|
46
|
+
*/
|
|
47
|
+
async *follow(id, signal) {
|
|
48
|
+
signal.throwIfAborted();
|
|
49
|
+
const follower = new TerminalFollower(this.maxBufferedBytes);
|
|
50
|
+
const baseline = await this.enqueue(() => {
|
|
51
|
+
signal.throwIfAborted();
|
|
52
|
+
this.controller = { id, follower };
|
|
53
|
+
this.info = { ...this.info, controllerId: id };
|
|
54
|
+
this.broadcast({ type: 'state', info: this.info });
|
|
55
|
+
const snapshot = { type: 'snapshot', sequence: this.sequence, screen: this.serializer.serialize(), info: this.info };
|
|
56
|
+
this.followers.add(follower);
|
|
57
|
+
return snapshot;
|
|
58
|
+
});
|
|
59
|
+
try {
|
|
60
|
+
yield baseline;
|
|
61
|
+
yield* follower.read(signal);
|
|
62
|
+
}
|
|
63
|
+
finally {
|
|
64
|
+
this.followers.delete(follower);
|
|
65
|
+
follower.close();
|
|
66
|
+
if (this.controller?.follower === follower) {
|
|
67
|
+
this.controller = undefined;
|
|
68
|
+
const { controllerId: _controllerId, ...info } = this.info;
|
|
69
|
+
this.info = info;
|
|
70
|
+
this.broadcast({ type: 'state', info });
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Send raw terminal input without command interpretation.
|
|
76
|
+
* @param id - current writable attachment.
|
|
77
|
+
* @param data - UTF-8 input, including shell completion/control keys.
|
|
78
|
+
* @returns when the provider accepts the input.
|
|
79
|
+
*/
|
|
80
|
+
write(id, data) {
|
|
81
|
+
return this.enqueue(async () => { this.requireController(id); await this.handle.write(data); });
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Resize the PTY and recovery screen in the same operation order as output.
|
|
85
|
+
* @param id - current writable attachment.
|
|
86
|
+
* @param cols - validated column count.
|
|
87
|
+
* @param rows - validated row count.
|
|
88
|
+
* @returns when the provider and emulator use the new dimensions.
|
|
89
|
+
*/
|
|
90
|
+
resize(id, cols, rows) {
|
|
91
|
+
return this.enqueue(async () => {
|
|
92
|
+
this.requireController(id);
|
|
93
|
+
await this.handle.resize(cols, rows);
|
|
94
|
+
this.screen.resize(cols, rows);
|
|
95
|
+
this.info = { ...this.info, cols, rows };
|
|
96
|
+
this.broadcast({ type: 'state', info: this.info });
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Publish a display name to every attached view.
|
|
101
|
+
* @param title - validated user title.
|
|
102
|
+
*/
|
|
103
|
+
rename(title) {
|
|
104
|
+
this.info = { ...this.info, title };
|
|
105
|
+
this.broadcast({ type: 'state', info: this.info });
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Terminate the complete provider-owned process range before releasing its screen.
|
|
109
|
+
* @returns after process cleanup and final output drainage; failures remain retryable.
|
|
110
|
+
*/
|
|
111
|
+
close() {
|
|
112
|
+
if (this.closing !== undefined)
|
|
113
|
+
return this.closing;
|
|
114
|
+
this.closing = (async () => {
|
|
115
|
+
await this.handle.terminate();
|
|
116
|
+
await this.drained;
|
|
117
|
+
for (const follower of this.followers)
|
|
118
|
+
follower.finish();
|
|
119
|
+
this.followers.clear();
|
|
120
|
+
this.screen.dispose();
|
|
121
|
+
})().catch((error) => { this.closing = undefined; throw error; });
|
|
122
|
+
return this.closing;
|
|
123
|
+
}
|
|
124
|
+
requireController(id) {
|
|
125
|
+
if (this.closing !== undefined || this.info.state !== 'running')
|
|
126
|
+
throw new RemoteError('terminal/control-unavailable', 'Terminal is not running', { reason: 'not-running' });
|
|
127
|
+
if (this.controller?.id !== id)
|
|
128
|
+
throw new RemoteError('terminal/control-unavailable', 'Terminal input is controlled by another attachment', { reason: 'read-only' });
|
|
129
|
+
}
|
|
130
|
+
broadcast(frame) {
|
|
131
|
+
for (const follower of this.followers)
|
|
132
|
+
follower.push(frame);
|
|
133
|
+
}
|
|
134
|
+
enqueue(operation) {
|
|
135
|
+
const pending = this.operations.then(operation);
|
|
136
|
+
this.operations = pending.catch(() => { });
|
|
137
|
+
return pending;
|
|
138
|
+
}
|
|
139
|
+
async consume() {
|
|
140
|
+
const decoder = new TextDecoder('utf-8', { ignoreBOM: true });
|
|
141
|
+
const outcome = this.handle.done.then(value => ({ value }), (error) => ({ error }));
|
|
142
|
+
try {
|
|
143
|
+
for await (const chunk of this.handle.output) {
|
|
144
|
+
// Node Readable's iterator is untyped; this provider explicitly emits Buffer chunks.
|
|
145
|
+
const data = decoder.decode(chunk, { stream: true });
|
|
146
|
+
await this.output(data);
|
|
147
|
+
}
|
|
148
|
+
await this.output(decoder.decode());
|
|
149
|
+
const result = await outcome;
|
|
150
|
+
if ('error' in result)
|
|
151
|
+
throw result.error;
|
|
152
|
+
this.info = { ...this.info, state: 'exited', exitCode: result.value.exitCode };
|
|
153
|
+
}
|
|
154
|
+
catch (error) {
|
|
155
|
+
this.info = { ...this.info, state: 'failed', error: error instanceof Error ? error.message : String(error) };
|
|
156
|
+
}
|
|
157
|
+
this.broadcast({ type: 'state', info: this.info });
|
|
158
|
+
}
|
|
159
|
+
async output(data) {
|
|
160
|
+
if (data.length === 0)
|
|
161
|
+
return;
|
|
162
|
+
await this.enqueue(async () => {
|
|
163
|
+
await new Promise((resolve) => { this.screen.write(data, resolve); });
|
|
164
|
+
this.broadcast({ type: 'output', sequence: ++this.sequence, data });
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
//# sourceMappingURL=terminal.js.map
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/** Browser terminal identities, metadata and screen-stream frames. */
|
|
2
|
+
import type { Branded } from '@deepseek-ai/dsh-brand';
|
|
3
|
+
declare module '@deepseek-ai/dsh-typert-protocol' {
|
|
4
|
+
interface RemoteErrorDetailsMap {
|
|
5
|
+
/** Input or resize was refused without invalidating the output attachment. */
|
|
6
|
+
'terminal/control-unavailable': {
|
|
7
|
+
readonly reason: 'read-only' | 'not-running';
|
|
8
|
+
};
|
|
9
|
+
/** Retained screens and pending allocations consume the Session's terminal quota. */
|
|
10
|
+
'terminal/limit-reached': {
|
|
11
|
+
readonly limit: number;
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
/** A terminal identity scoped to one Session and one Host lifetime. */
|
|
16
|
+
export type WebTerminalId = Branded<'WebTerminalId'>;
|
|
17
|
+
/** An attachment allowed to write and resize one terminal. */
|
|
18
|
+
export type TerminalAttachmentId = Branded<'TerminalAttachmentId'>;
|
|
19
|
+
/** An executable shell verified in the subprocess provider's execution environment. */
|
|
20
|
+
export interface TerminalShell {
|
|
21
|
+
readonly path: string;
|
|
22
|
+
readonly args: readonly string[];
|
|
23
|
+
readonly name: string;
|
|
24
|
+
}
|
|
25
|
+
/** Working directory and limits shared by new and restored terminals. */
|
|
26
|
+
export interface TerminalEnvironment {
|
|
27
|
+
readonly cwd: string;
|
|
28
|
+
readonly maxInputBytes: number;
|
|
29
|
+
readonly maxCols: number;
|
|
30
|
+
readonly maxRows: number;
|
|
31
|
+
readonly scrollback: number;
|
|
32
|
+
}
|
|
33
|
+
/** Host-owned terminal state; process exit never creates a replacement shell. */
|
|
34
|
+
export interface WebTerminalInfo {
|
|
35
|
+
readonly id: WebTerminalId;
|
|
36
|
+
readonly title: string;
|
|
37
|
+
readonly shell: TerminalShell;
|
|
38
|
+
/** Initial working directory; shell directory changes do not update this field. */
|
|
39
|
+
readonly cwd: string;
|
|
40
|
+
readonly cols: number;
|
|
41
|
+
readonly rows: number;
|
|
42
|
+
readonly state: 'running' | 'exited' | 'failed';
|
|
43
|
+
readonly exitCode: number | null;
|
|
44
|
+
readonly error?: string;
|
|
45
|
+
readonly controllerId?: TerminalAttachmentId;
|
|
46
|
+
}
|
|
47
|
+
/** Create is idempotent for an open identity; closed identities cannot be recreated. */
|
|
48
|
+
export interface TerminalCreateRequest {
|
|
49
|
+
/** A path returned by shell discovery; absent selects the execution default. */
|
|
50
|
+
readonly shellPath?: string;
|
|
51
|
+
readonly id: WebTerminalId;
|
|
52
|
+
readonly cols: number;
|
|
53
|
+
readonly rows: number;
|
|
54
|
+
}
|
|
55
|
+
/** Every attachment begins with a complete bounded screen, then ordered output. */
|
|
56
|
+
export type TerminalFrame = {
|
|
57
|
+
readonly type: 'snapshot';
|
|
58
|
+
readonly sequence: number;
|
|
59
|
+
readonly screen: string;
|
|
60
|
+
readonly info: WebTerminalInfo;
|
|
61
|
+
} | {
|
|
62
|
+
readonly type: 'output';
|
|
63
|
+
readonly sequence: number;
|
|
64
|
+
readonly data: string;
|
|
65
|
+
} | {
|
|
66
|
+
readonly type: 'state';
|
|
67
|
+
readonly info: WebTerminalInfo;
|
|
68
|
+
};
|
|
69
|
+
//# sourceMappingURL=types.d.ts.map
|
package/package.json
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@deepseek-ai/dsh-api-terminal-controller",
|
|
3
|
+
"description": "Session-owned interactive terminals with shell discovery, screen recovery and typed Remote control",
|
|
4
|
+
"version": "0.1.6-alpha.1",
|
|
5
|
+
"publishConfig": {
|
|
6
|
+
"access": "public"
|
|
7
|
+
},
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/deepseek-ai/deepseek-harness.git",
|
|
11
|
+
"directory": "packages/api/terminal-controller"
|
|
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
|
+
"./types": {
|
|
22
|
+
"types": "./lib/types/types.d.ts",
|
|
23
|
+
"default": "./lib/types/types.js"
|
|
24
|
+
},
|
|
25
|
+
"./client": {
|
|
26
|
+
"types": "./lib/types/client/index.d.ts",
|
|
27
|
+
"default": "./lib/client.js"
|
|
28
|
+
},
|
|
29
|
+
"./typert": {
|
|
30
|
+
"types": "./lib/typert.host.d.ts",
|
|
31
|
+
"default": "./lib/typert.host.js"
|
|
32
|
+
},
|
|
33
|
+
"./remote": {
|
|
34
|
+
"types": "./lib/typert.remote-client.d.ts",
|
|
35
|
+
"default": "./lib/typert.remote-client.js"
|
|
36
|
+
},
|
|
37
|
+
"./src/*": "./src/*",
|
|
38
|
+
"./package.json": "./package.json"
|
|
39
|
+
},
|
|
40
|
+
"dsh": {
|
|
41
|
+
"client": {
|
|
42
|
+
"inject": [
|
|
43
|
+
"@deepseek-ai/dsh-api-gateway"
|
|
44
|
+
],
|
|
45
|
+
"external": [
|
|
46
|
+
"@deepseek-ai/dsh-api-gateway/client"
|
|
47
|
+
],
|
|
48
|
+
"platform": "web"
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
"license": "MIT",
|
|
52
|
+
"dependencies": {
|
|
53
|
+
"@xterm/headless": "^6.0.0",
|
|
54
|
+
"@xterm/addon-serialize": "^0.14.0",
|
|
55
|
+
"zod": "^4.4.3",
|
|
56
|
+
"@deepseek-ai/dsh-deque": "^0.1.6-alpha.1",
|
|
57
|
+
"@deepseek-ai/dsh-typert-protocol": "^0.1.6-alpha.1",
|
|
58
|
+
"@deepseek-ai/schemastery": "^3.18.2"
|
|
59
|
+
},
|
|
60
|
+
"peerDependencies": {
|
|
61
|
+
"@deepseek-ai/dsh-subprocess": "^0.1.6-alpha.1",
|
|
62
|
+
"@deepseek-ai/cordis": "^4.0.2"
|
|
63
|
+
},
|
|
64
|
+
"devDependencies": {
|
|
65
|
+
"@deepseek-ai/cordis": "^4.0.2",
|
|
66
|
+
"@deepseek-ai/dsh-agent": "^0.1.6-alpha.1",
|
|
67
|
+
"@deepseek-ai/dsh-api-gateway": "^0.1.6-alpha.1",
|
|
68
|
+
"@deepseek-ai/dsh-brand": "^0.1.6-alpha.1",
|
|
69
|
+
"@deepseek-ai/dsh-client-store": "^0.1.6-alpha.1",
|
|
70
|
+
"@deepseek-ai/dsh-fs": "^0.1.6-alpha.1",
|
|
71
|
+
"@deepseek-ai/dsh-sandbox": "^0.1.6-alpha.1",
|
|
72
|
+
"@deepseek-ai/dsh-sandbox-policy": "^0.1.6-alpha.1",
|
|
73
|
+
"@deepseek-ai/dsh-session": "^0.1.6-alpha.1",
|
|
74
|
+
"@deepseek-ai/dsh-session-projection": "^0.1.6-alpha.1",
|
|
75
|
+
"@deepseek-ai/dsh-subprocess-local": "^0.1.6-alpha.1",
|
|
76
|
+
"@deepseek-ai/dsh-util-crypto": "^0.1.6-alpha.1",
|
|
77
|
+
"@deepseek-ai/dsh-subprocess": "^0.1.6-alpha.1"
|
|
78
|
+
},
|
|
79
|
+
"files": [
|
|
80
|
+
"lib/index.js",
|
|
81
|
+
"lib/client.js",
|
|
82
|
+
"lib/types/**/*.js",
|
|
83
|
+
"lib/types/**/*.d.ts",
|
|
84
|
+
"lib/typert.host.js",
|
|
85
|
+
"lib/typert.host.d.ts",
|
|
86
|
+
"lib/typert.remote-client.js",
|
|
87
|
+
"lib/typert.remote-client.d.ts"
|
|
88
|
+
],
|
|
89
|
+
"scripts": {
|
|
90
|
+
"bundle": "tsdown",
|
|
91
|
+
"watch": "tsdown --watch"
|
|
92
|
+
}
|
|
93
|
+
}
|