@lemoncat7/dsh-ssh 0.1.0-alpha.16 → 1.0.6
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.md +12 -1
- package/lib/activity-events.d.ts +26 -0
- package/lib/activity-events.d.ts.map +1 -0
- package/lib/activity-events.js +81 -0
- package/lib/activity-events.js.map +1 -0
- package/lib/api.d.ts +2 -0
- package/lib/api.d.ts.map +1 -1
- package/lib/api.js +29 -2
- package/lib/api.js.map +1 -1
- package/lib/client-api.d.ts +14 -3
- package/lib/client-api.d.ts.map +1 -1
- package/lib/client-api.js +13 -2
- package/lib/client-api.js.map +1 -1
- package/lib/client.d.ts.map +1 -1
- package/lib/client.js +228 -83
- package/lib/client.js.map +3 -3
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +4 -2
- package/lib/index.js.map +1 -1
- package/lib/terminal-io.d.ts +38 -0
- package/lib/terminal-io.d.ts.map +1 -0
- package/lib/terminal-io.js +83 -0
- package/lib/terminal-io.js.map +1 -0
- package/lib/terminal-stream.d.ts +9 -0
- package/lib/terminal-stream.d.ts.map +1 -0
- package/lib/terminal-stream.js +50 -0
- package/lib/terminal-stream.js.map +1 -0
- package/lib/terminal-transport.d.ts +29 -0
- package/lib/terminal-transport.d.ts.map +1 -0
- package/lib/terminal-transport.js +147 -0
- package/lib/terminal-transport.js.map +1 -0
- package/lib/terminal.d.ts +14 -11
- package/lib/terminal.d.ts.map +1 -1
- package/lib/terminal.js +42 -33
- package/lib/terminal.js.map +1 -1
- package/package.json +1 -1
package/lib/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAElD,OAAO,EAAE,MAAM,IAAI,YAAY,EAAiB,KAAK,MAAM,IAAI,SAAS,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAElD,OAAO,EAAE,MAAM,IAAI,YAAY,EAAiB,KAAK,MAAM,IAAI,SAAS,EAAE,MAAM,aAAa,CAAA;AAU7F,eAAO,MAAM,MAAM,0DAAe,CAAA;AAClC,MAAM,MAAM,MAAM,GAAG,SAAS,CAAA;AAC9B,cAAc,aAAa,CAAA;AAC3B,eAAO,MAAM,IAAI,YAAY,CAAA;AAC7B,eAAO,MAAM,MAAM,UAAqD,CAAA;AAQxE,wBAAgB,KAAK,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,GAAG,IAAI,CAoC/D"}
|
package/lib/index.js
CHANGED
|
@@ -6,6 +6,7 @@ import { ForwardManager } from './forwards.js';
|
|
|
6
6
|
import { SshStore } from './store.js';
|
|
7
7
|
import { AiTerminalManager, BrowserTerminalManager } from './terminal.js';
|
|
8
8
|
import { registerSshTools } from './tools.js';
|
|
9
|
+
import { ActivityEventBus } from './activity-events.js';
|
|
9
10
|
export const Config = ConfigSchema;
|
|
10
11
|
export * from './domain.js';
|
|
11
12
|
export const name = 'dsh-ssh';
|
|
@@ -23,7 +24,8 @@ export function apply(context, config) {
|
|
|
23
24
|
const connector = new SshConnector(store, credentials);
|
|
24
25
|
const forwards = new ForwardManager(connector, store);
|
|
25
26
|
const terminals = new BrowserTerminalManager(connector);
|
|
26
|
-
const
|
|
27
|
+
const activityEvents = new ActivityEventBus();
|
|
28
|
+
const aiTerminals = new AiTerminalManager(connector, event => { activityEvents.publish(event); });
|
|
27
29
|
const disposeTools = registerSshTools(context, store, connector, forwards, aiTerminals);
|
|
28
30
|
let disposeApi;
|
|
29
31
|
const mountApi = (runtime) => {
|
|
@@ -32,7 +34,7 @@ export function apply(context, config) {
|
|
|
32
34
|
const webServer = runtime.webServer ?? runtime.get('webServer');
|
|
33
35
|
if (webServer === undefined)
|
|
34
36
|
throw new Error('dsh-ssh exposeWeb requires webServer');
|
|
35
|
-
disposeApi = registerSshApi(webServer, resolved.apiPrefix, { store, credentials, connector, forwards, terminals, aiTerminals });
|
|
37
|
+
disposeApi = registerSshApi(webServer, resolved.apiPrefix, { store, credentials, connector, forwards, terminals, aiTerminals, activityEvents });
|
|
36
38
|
};
|
|
37
39
|
if (ctx.inject !== undefined)
|
|
38
40
|
ctx.inject(['webServer'], mountApi);
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,IAAI,YAAY,EAAE,aAAa,EAA4B,MAAM,aAAa,CAAA;AAC7F,OAAO,EAAE,cAAc,EAAsB,MAAM,UAAU,CAAA;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAC7C,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAA;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AACrC,OAAO,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAA;AACzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export interface TerminalOutputDelta {
|
|
2
|
+
data: string;
|
|
3
|
+
cursor: number;
|
|
4
|
+
truncated: boolean;
|
|
5
|
+
closed: boolean;
|
|
6
|
+
}
|
|
7
|
+
export type TerminalOutputListener = (output: TerminalOutputDelta) => void;
|
|
8
|
+
/**
|
|
9
|
+
* Cursor-addressable terminal scrollback with synchronous fan-out for live transports.
|
|
10
|
+
* A subscriber can attach and immediately call read() without an output race because
|
|
11
|
+
* both operations complete in the same JavaScript turn.
|
|
12
|
+
*/
|
|
13
|
+
export declare class TerminalOutputBuffer {
|
|
14
|
+
private readonly trimThreshold;
|
|
15
|
+
private readonly retainChars;
|
|
16
|
+
private value;
|
|
17
|
+
private baseCursor;
|
|
18
|
+
private closed;
|
|
19
|
+
private readonly listeners;
|
|
20
|
+
constructor(trimThreshold: number, retainChars: number);
|
|
21
|
+
append(text: string): void;
|
|
22
|
+
read(cursor: number): TerminalOutputDelta;
|
|
23
|
+
text(): string;
|
|
24
|
+
isTruncated(): boolean;
|
|
25
|
+
subscribe(listener: TerminalOutputListener): () => void;
|
|
26
|
+
close(): void;
|
|
27
|
+
private cursor;
|
|
28
|
+
private emit;
|
|
29
|
+
}
|
|
30
|
+
/** Preserves keystroke order while allowing browser requests to travel concurrently. */
|
|
31
|
+
export declare class OrderedTerminalInput {
|
|
32
|
+
private readonly write;
|
|
33
|
+
private nextSequence;
|
|
34
|
+
private readonly pending;
|
|
35
|
+
constructor(write: (text: string) => void);
|
|
36
|
+
push(sequence: number | undefined, text: string): void;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=terminal-io.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal-io.d.ts","sourceRoot":"","sources":["../src/terminal-io.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,OAAO,CAAA;IAClB,MAAM,EAAE,OAAO,CAAA;CAChB;AAED,MAAM,MAAM,sBAAsB,GAAG,CAAC,MAAM,EAAE,mBAAmB,KAAK,IAAI,CAAA;AAE1E;;;;GAIG;AACH,qBAAa,oBAAoB;IAO7B,OAAO,CAAC,QAAQ,CAAC,aAAa;IAC9B,OAAO,CAAC,QAAQ,CAAC,WAAW;IAP9B,OAAO,CAAC,KAAK,CAAK;IAClB,OAAO,CAAC,UAAU,CAAI;IACtB,OAAO,CAAC,MAAM,CAAQ;IACtB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAoC;gBAG3C,aAAa,EAAE,MAAM,EACrB,WAAW,EAAE,MAAM;IAGtC,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAW1B,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,mBAAmB;IAUzC,IAAI,IAAI,MAAM;IAEd,WAAW,IAAI,OAAO;IAEtB,SAAS,CAAC,QAAQ,EAAE,sBAAsB,GAAG,MAAM,IAAI;IAKvD,KAAK,IAAI,IAAI;IAMb,OAAO,CAAC,MAAM;IAEd,OAAO,CAAC,IAAI;CAGb;AAED,wFAAwF;AACxF,qBAAa,oBAAoB;IAInB,OAAO,CAAC,QAAQ,CAAC,KAAK;IAHlC,OAAO,CAAC,YAAY,CAAI;IACxB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA4B;gBAEvB,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI;IAE1D,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;CAiBvD"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
const MAX_PENDING_INPUTS = 256;
|
|
2
|
+
/**
|
|
3
|
+
* Cursor-addressable terminal scrollback with synchronous fan-out for live transports.
|
|
4
|
+
* A subscriber can attach and immediately call read() without an output race because
|
|
5
|
+
* both operations complete in the same JavaScript turn.
|
|
6
|
+
*/
|
|
7
|
+
export class TerminalOutputBuffer {
|
|
8
|
+
trimThreshold;
|
|
9
|
+
retainChars;
|
|
10
|
+
value = '';
|
|
11
|
+
baseCursor = 0;
|
|
12
|
+
closed = false;
|
|
13
|
+
listeners = new Set();
|
|
14
|
+
constructor(trimThreshold, retainChars) {
|
|
15
|
+
this.trimThreshold = trimThreshold;
|
|
16
|
+
this.retainChars = retainChars;
|
|
17
|
+
}
|
|
18
|
+
append(text) {
|
|
19
|
+
if (!text)
|
|
20
|
+
return;
|
|
21
|
+
this.value += text;
|
|
22
|
+
if (this.value.length > this.trimThreshold) {
|
|
23
|
+
const removed = this.value.length - this.retainChars;
|
|
24
|
+
this.value = this.value.slice(removed);
|
|
25
|
+
this.baseCursor += removed;
|
|
26
|
+
}
|
|
27
|
+
this.emit({ data: text, cursor: this.cursor(), truncated: false, closed: false });
|
|
28
|
+
}
|
|
29
|
+
read(cursor) {
|
|
30
|
+
const safeCursor = Math.max(cursor, this.baseCursor);
|
|
31
|
+
return {
|
|
32
|
+
data: this.value.slice(safeCursor - this.baseCursor),
|
|
33
|
+
cursor: this.cursor(),
|
|
34
|
+
truncated: cursor < this.baseCursor,
|
|
35
|
+
closed: this.closed,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
text() { return this.value; }
|
|
39
|
+
isTruncated() { return this.baseCursor > 0; }
|
|
40
|
+
subscribe(listener) {
|
|
41
|
+
this.listeners.add(listener);
|
|
42
|
+
return () => { this.listeners.delete(listener); };
|
|
43
|
+
}
|
|
44
|
+
close() {
|
|
45
|
+
if (this.closed)
|
|
46
|
+
return;
|
|
47
|
+
this.closed = true;
|
|
48
|
+
this.emit({ data: '', cursor: this.cursor(), truncated: false, closed: true });
|
|
49
|
+
}
|
|
50
|
+
cursor() { return this.baseCursor + this.value.length; }
|
|
51
|
+
emit(output) {
|
|
52
|
+
for (const listener of this.listeners)
|
|
53
|
+
listener(output);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/** Preserves keystroke order while allowing browser requests to travel concurrently. */
|
|
57
|
+
export class OrderedTerminalInput {
|
|
58
|
+
write;
|
|
59
|
+
nextSequence = 0;
|
|
60
|
+
pending = new Map();
|
|
61
|
+
constructor(write) {
|
|
62
|
+
this.write = write;
|
|
63
|
+
}
|
|
64
|
+
push(sequence, text) {
|
|
65
|
+
if (sequence === undefined) {
|
|
66
|
+
this.write(text);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
if (!Number.isSafeInteger(sequence) || sequence < 0 || sequence > this.nextSequence + MAX_PENDING_INPUTS) {
|
|
70
|
+
throw Object.assign(new Error('terminal input sequence is invalid'), { status: 400 });
|
|
71
|
+
}
|
|
72
|
+
if (sequence < this.nextSequence || this.pending.has(sequence))
|
|
73
|
+
return;
|
|
74
|
+
this.pending.set(sequence, text);
|
|
75
|
+
while (this.pending.has(this.nextSequence)) {
|
|
76
|
+
const next = this.pending.get(this.nextSequence);
|
|
77
|
+
this.pending.delete(this.nextSequence);
|
|
78
|
+
this.nextSequence += 1;
|
|
79
|
+
this.write(next);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=terminal-io.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal-io.js","sourceRoot":"","sources":["../src/terminal-io.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { IncomingMessage, ServerResponse } from 'node:http';
|
|
2
|
+
import type { TerminalOutputDelta, TerminalOutputListener } from './terminal-io.js';
|
|
3
|
+
export interface TerminalOutputSource {
|
|
4
|
+
read(cursor: number): TerminalOutputDelta;
|
|
5
|
+
subscribe(listener: TerminalOutputListener): () => void;
|
|
6
|
+
}
|
|
7
|
+
/** Streams terminal output as resumable SSE and disables reverse-proxy buffering. */
|
|
8
|
+
export declare function streamTerminalOutput(req: IncomingMessage, res: ServerResponse, url: URL, source: TerminalOutputSource): Promise<void>;
|
|
9
|
+
//# sourceMappingURL=terminal-stream.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal-stream.d.ts","sourceRoot":"","sources":["../src/terminal-stream.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAChE,OAAO,KAAK,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAA;AAEnF,MAAM,WAAW,oBAAoB;IACnC,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,mBAAmB,CAAA;IACzC,SAAS,CAAC,QAAQ,EAAE,sBAAsB,GAAG,MAAM,IAAI,CAAA;CACxD;AAED,qFAAqF;AACrF,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,GAAG,EAAE,GAAG,EACR,MAAM,EAAE,oBAAoB,GAC3B,OAAO,CAAC,IAAI,CAAC,CAsCf"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/** Streams terminal output as resumable SSE and disables reverse-proxy buffering. */
|
|
2
|
+
export function streamTerminalOutput(req, res, url, source) {
|
|
3
|
+
const cursor = parseCursor(req, url);
|
|
4
|
+
res.statusCode = 200;
|
|
5
|
+
res.setHeader('Cache-Control', 'no-cache, no-store, no-transform');
|
|
6
|
+
res.setHeader('Content-Type', 'text/event-stream; charset=utf-8');
|
|
7
|
+
res.setHeader('Connection', 'keep-alive');
|
|
8
|
+
res.setHeader('X-Accel-Buffering', 'no');
|
|
9
|
+
res.setHeader('X-Content-Type-Options', 'nosniff');
|
|
10
|
+
res.flushHeaders();
|
|
11
|
+
return new Promise(resolve => {
|
|
12
|
+
let finished = false;
|
|
13
|
+
let heartbeat;
|
|
14
|
+
let unsubscribe = () => { };
|
|
15
|
+
const cleanup = () => {
|
|
16
|
+
if (finished)
|
|
17
|
+
return;
|
|
18
|
+
finished = true;
|
|
19
|
+
if (heartbeat !== undefined)
|
|
20
|
+
clearInterval(heartbeat);
|
|
21
|
+
unsubscribe();
|
|
22
|
+
resolve();
|
|
23
|
+
};
|
|
24
|
+
const send = (output) => {
|
|
25
|
+
if (finished || res.destroyed || res.writableEnded)
|
|
26
|
+
return cleanup();
|
|
27
|
+
res.write(`id: ${output.cursor}\ndata: ${JSON.stringify(output)}\n\n`);
|
|
28
|
+
if (output.closed) {
|
|
29
|
+
res.end();
|
|
30
|
+
cleanup();
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
res.once('close', cleanup);
|
|
34
|
+
res.once('finish', cleanup);
|
|
35
|
+
unsubscribe = source.subscribe(send);
|
|
36
|
+
heartbeat = setInterval(() => {
|
|
37
|
+
if (!finished && !res.destroyed && !res.writableEnded)
|
|
38
|
+
res.write(': keepalive\n\n');
|
|
39
|
+
}, 15_000);
|
|
40
|
+
send(source.read(cursor));
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
function parseCursor(req, url) {
|
|
44
|
+
const header = Array.isArray(req.headers['last-event-id']) ? req.headers['last-event-id'][0] : req.headers['last-event-id'];
|
|
45
|
+
const value = Number(header ?? url.searchParams.get('cursor') ?? 0);
|
|
46
|
+
if (!Number.isSafeInteger(value) || value < 0)
|
|
47
|
+
throw Object.assign(new Error('terminal cursor is invalid'), { status: 400 });
|
|
48
|
+
return value;
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=terminal-stream.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal-stream.js","sourceRoot":"","sources":["../src/terminal-stream.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { TerminalOutputDelta } from './client-api.js';
|
|
2
|
+
interface TerminalTransportEndpoints {
|
|
3
|
+
streamUrl: string;
|
|
4
|
+
read(cursor: number): Promise<TerminalOutputDelta>;
|
|
5
|
+
send(text: string, sequence: number): Promise<void>;
|
|
6
|
+
}
|
|
7
|
+
interface TerminalOutputObserver {
|
|
8
|
+
output(value: TerminalOutputDelta): void;
|
|
9
|
+
error(reason: unknown): void;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Low-latency browser transport shared by the SSH panel and conversation activity.
|
|
13
|
+
* SSE is the primary output path; cursor polling only starts when the stream cannot
|
|
14
|
+
* pass through the current browser or reverse proxy.
|
|
15
|
+
*/
|
|
16
|
+
export declare class TerminalTransport {
|
|
17
|
+
private readonly endpoints;
|
|
18
|
+
private input;
|
|
19
|
+
private inputSequence;
|
|
20
|
+
private inputScheduled;
|
|
21
|
+
private disposed;
|
|
22
|
+
constructor(endpoints: TerminalTransportEndpoints);
|
|
23
|
+
sendInput(text: string, onError: (reason: unknown) => void): void;
|
|
24
|
+
observe(observer: TerminalOutputObserver): () => void;
|
|
25
|
+
dispose(): void;
|
|
26
|
+
private deliverInput;
|
|
27
|
+
}
|
|
28
|
+
export {};
|
|
29
|
+
//# sourceMappingURL=terminal-transport.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal-transport.d.ts","sourceRoot":"","sources":["../src/terminal-transport.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAA;AAE1D,UAAU,0BAA0B;IAClC,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAA;IAClD,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CACpD;AAED,UAAU,sBAAsB;IAC9B,MAAM,CAAC,KAAK,EAAE,mBAAmB,GAAG,IAAI,CAAA;IACxC,KAAK,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAAA;CAC7B;AAED;;;;GAIG;AACH,qBAAa,iBAAiB;IAMhB,OAAO,CAAC,QAAQ,CAAC,SAAS;IALtC,OAAO,CAAC,KAAK,CAAK;IAClB,OAAO,CAAC,aAAa,CAAI;IACzB,OAAO,CAAC,cAAc,CAAQ;IAC9B,OAAO,CAAC,QAAQ,CAAQ;gBAEK,SAAS,EAAE,0BAA0B;IAElE,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,GAAG,IAAI;IAgBjE,OAAO,CAAC,QAAQ,EAAE,sBAAsB,GAAG,MAAM,IAAI;IAuErD,OAAO,IAAI,IAAI;IAKf,OAAO,CAAC,YAAY;CAUrB"}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Low-latency browser transport shared by the SSH panel and conversation activity.
|
|
3
|
+
* SSE is the primary output path; cursor polling only starts when the stream cannot
|
|
4
|
+
* pass through the current browser or reverse proxy.
|
|
5
|
+
*/
|
|
6
|
+
export class TerminalTransport {
|
|
7
|
+
endpoints;
|
|
8
|
+
input = '';
|
|
9
|
+
inputSequence = 0;
|
|
10
|
+
inputScheduled = false;
|
|
11
|
+
disposed = false;
|
|
12
|
+
constructor(endpoints) {
|
|
13
|
+
this.endpoints = endpoints;
|
|
14
|
+
}
|
|
15
|
+
sendInput(text, onError) {
|
|
16
|
+
if (this.disposed || !text)
|
|
17
|
+
return;
|
|
18
|
+
this.input += text;
|
|
19
|
+
if (this.inputScheduled)
|
|
20
|
+
return;
|
|
21
|
+
this.inputScheduled = true;
|
|
22
|
+
queueMicrotask(() => {
|
|
23
|
+
this.inputScheduled = false;
|
|
24
|
+
if (this.disposed)
|
|
25
|
+
return;
|
|
26
|
+
const pending = this.input;
|
|
27
|
+
this.input = '';
|
|
28
|
+
if (!pending)
|
|
29
|
+
return;
|
|
30
|
+
const sequence = this.inputSequence++;
|
|
31
|
+
this.deliverInput(pending, sequence, onError);
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
observe(observer) {
|
|
35
|
+
let stopped = false;
|
|
36
|
+
let cursor = 0;
|
|
37
|
+
let source;
|
|
38
|
+
let streamWatchdog;
|
|
39
|
+
let pollTimer;
|
|
40
|
+
let streamConfirmed = false;
|
|
41
|
+
const stop = () => {
|
|
42
|
+
if (stopped)
|
|
43
|
+
return;
|
|
44
|
+
stopped = true;
|
|
45
|
+
source?.close();
|
|
46
|
+
if (streamWatchdog !== undefined)
|
|
47
|
+
clearTimeout(streamWatchdog);
|
|
48
|
+
if (pollTimer !== undefined)
|
|
49
|
+
clearTimeout(pollTimer);
|
|
50
|
+
};
|
|
51
|
+
const accept = (value) => {
|
|
52
|
+
if (stopped)
|
|
53
|
+
return;
|
|
54
|
+
cursor = value.cursor;
|
|
55
|
+
observer.output(value);
|
|
56
|
+
if (value.closed)
|
|
57
|
+
stop();
|
|
58
|
+
};
|
|
59
|
+
const poll = async () => {
|
|
60
|
+
if (stopped)
|
|
61
|
+
return;
|
|
62
|
+
try {
|
|
63
|
+
const value = await this.endpoints.read(cursor);
|
|
64
|
+
accept(value);
|
|
65
|
+
if (!stopped)
|
|
66
|
+
pollTimer = window.setTimeout(() => { void poll(); }, document.hidden ? 500 : value.data ? 16 : 64);
|
|
67
|
+
}
|
|
68
|
+
catch (reason) {
|
|
69
|
+
if (stopped)
|
|
70
|
+
return;
|
|
71
|
+
observer.error(reason);
|
|
72
|
+
pollTimer = window.setTimeout(() => { void poll(); }, 500);
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
const startPolling = () => {
|
|
76
|
+
if (stopped || pollTimer !== undefined)
|
|
77
|
+
return;
|
|
78
|
+
source?.close();
|
|
79
|
+
source = undefined;
|
|
80
|
+
void poll();
|
|
81
|
+
};
|
|
82
|
+
if (typeof EventSource === 'undefined') {
|
|
83
|
+
startPolling();
|
|
84
|
+
return stop;
|
|
85
|
+
}
|
|
86
|
+
source = new EventSource(this.endpoints.streamUrl);
|
|
87
|
+
source.onmessage = event => {
|
|
88
|
+
try {
|
|
89
|
+
const value = parseOutput(event.data);
|
|
90
|
+
streamConfirmed = true;
|
|
91
|
+
if (streamWatchdog !== undefined) {
|
|
92
|
+
clearTimeout(streamWatchdog);
|
|
93
|
+
streamWatchdog = undefined;
|
|
94
|
+
}
|
|
95
|
+
accept(value);
|
|
96
|
+
}
|
|
97
|
+
catch (reason) {
|
|
98
|
+
observer.error(reason);
|
|
99
|
+
startPolling();
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
source.onerror = () => {
|
|
103
|
+
// A confirmed EventSource reconnects with Last-Event-ID and does not need a
|
|
104
|
+
// competing poller. Before the first event, fall back if the proxy buffers SSE.
|
|
105
|
+
if (!streamConfirmed && source?.readyState === EventSource.CLOSED)
|
|
106
|
+
startPolling();
|
|
107
|
+
};
|
|
108
|
+
streamWatchdog = window.setTimeout(() => {
|
|
109
|
+
if (!streamConfirmed)
|
|
110
|
+
startPolling();
|
|
111
|
+
}, 1_500);
|
|
112
|
+
return stop;
|
|
113
|
+
}
|
|
114
|
+
dispose() {
|
|
115
|
+
this.disposed = true;
|
|
116
|
+
this.input = '';
|
|
117
|
+
}
|
|
118
|
+
deliverInput(text, sequence, onError, attempt = 0) {
|
|
119
|
+
void this.endpoints.send(text, sequence).catch(reason => {
|
|
120
|
+
if (this.disposed)
|
|
121
|
+
return;
|
|
122
|
+
if (attempt < 2 && isRetryable(reason)) {
|
|
123
|
+
window.setTimeout(() => this.deliverInput(text, sequence, onError, attempt + 1), 60 * (attempt + 1));
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
onError(reason);
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
function parseOutput(value) {
|
|
131
|
+
const parsed = JSON.parse(value);
|
|
132
|
+
if (typeof parsed.data !== 'string' ||
|
|
133
|
+
typeof parsed.cursor !== 'number' ||
|
|
134
|
+
!Number.isSafeInteger(parsed.cursor) ||
|
|
135
|
+
parsed.cursor < 0 ||
|
|
136
|
+
typeof parsed.truncated !== 'boolean' ||
|
|
137
|
+
typeof parsed.closed !== 'boolean')
|
|
138
|
+
throw new Error('SSH terminal stream returned an invalid event');
|
|
139
|
+
return parsed;
|
|
140
|
+
}
|
|
141
|
+
function isRetryable(reason) {
|
|
142
|
+
if (typeof reason !== 'object' || reason === null || !('status' in reason))
|
|
143
|
+
return true;
|
|
144
|
+
const status = Number(reason.status);
|
|
145
|
+
return !Number.isFinite(status) || status >= 500;
|
|
146
|
+
}
|
|
147
|
+
//# sourceMappingURL=terminal-transport.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal-transport.js","sourceRoot":"","sources":["../src/terminal-transport.ts"],"names":[],"mappings":"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"}
|
package/lib/terminal.d.ts
CHANGED
|
@@ -2,6 +2,8 @@ import type { ClientChannel } from 'ssh2';
|
|
|
2
2
|
import type { TerminalBackend, TerminalBackendSession, TerminalBackendSpawnSpec, TerminalReadRequest, TerminalReadResult, TerminalSendOperation, TerminalSendRequest, TerminalSendResult, TerminalSessionStatus, TerminalSignal, TerminalSignalResult } from '@deepseek-ai/dsh-terminal';
|
|
3
3
|
import { SshConnector, type ManagedSshConnection } from './connector.js';
|
|
4
4
|
import { SshStore } from './store.js';
|
|
5
|
+
import { TerminalOutputBuffer, type TerminalOutputListener } from './terminal-io.js';
|
|
6
|
+
import type { TerminalOpenedEvent } from './activity-events.js';
|
|
5
7
|
export declare class SshTerminalBackend implements TerminalBackend {
|
|
6
8
|
private readonly connector;
|
|
7
9
|
private readonly store;
|
|
@@ -13,21 +15,18 @@ export declare class SshTerminalSession implements TerminalBackendSession {
|
|
|
13
15
|
private readonly connection;
|
|
14
16
|
readonly channel: ClientChannel;
|
|
15
17
|
readonly motd: string;
|
|
16
|
-
private
|
|
17
|
-
private scrollbackCursor;
|
|
18
|
+
private readonly output;
|
|
18
19
|
private terminalStatus;
|
|
19
20
|
private active;
|
|
20
21
|
private closing?;
|
|
22
|
+
private readonly orderedInput;
|
|
21
23
|
constructor(connection: ManagedSshConnection, channel: ClientChannel, motd: string);
|
|
22
24
|
startSend(request: TerminalSendRequest): TerminalSendOperation;
|
|
23
25
|
read(request: TerminalReadRequest): TerminalReadResult;
|
|
24
|
-
readOutput(cursor: number):
|
|
25
|
-
data: string;
|
|
26
|
-
cursor: number;
|
|
27
|
-
truncated: boolean;
|
|
28
|
-
closed: boolean;
|
|
29
|
-
};
|
|
26
|
+
readOutput(cursor: number): ReturnType<TerminalOutputBuffer['read']>;
|
|
30
27
|
write(text: string): void;
|
|
28
|
+
writeOrdered(sequence: number | undefined, text: string): void;
|
|
29
|
+
subscribeOutput(listener: TerminalOutputListener): () => void;
|
|
31
30
|
resize(cols: number, rows: number): void;
|
|
32
31
|
signal(signal: TerminalSignal): Promise<TerminalSignalResult>;
|
|
33
32
|
status(): TerminalSessionStatus;
|
|
@@ -49,8 +48,9 @@ export declare class BrowserTerminalManager {
|
|
|
49
48
|
/** Owner-scoped AI terminals for Web profiles, whose official Terminal service lives inside each Agent preset realm. */
|
|
50
49
|
export declare class AiTerminalManager {
|
|
51
50
|
private readonly connector;
|
|
51
|
+
private readonly onTerminalOpened?;
|
|
52
52
|
private readonly sessions;
|
|
53
|
-
constructor(connector: SshConnector);
|
|
53
|
+
constructor(connector: SshConnector, onTerminalOpened?: ((event: TerminalOpenedEvent) => void) | undefined);
|
|
54
54
|
create(ownerId: string, profileId: string, cwd: string, name?: string, signal?: AbortSignal): Promise<{
|
|
55
55
|
terminalId: string;
|
|
56
56
|
profileId: string;
|
|
@@ -64,6 +64,7 @@ export declare class AiTerminalManager {
|
|
|
64
64
|
}>;
|
|
65
65
|
send(ownerId: string, terminalId: string, request: TerminalSendRequest): Promise<TerminalSendResult>;
|
|
66
66
|
write(ownerId: string, terminalId: string, text: string): void;
|
|
67
|
+
writeOrdered(ownerId: string, terminalId: string, sequence: number | undefined, text: string): void;
|
|
67
68
|
resize(ownerId: string, terminalId: string, cols: number, rows: number): void;
|
|
68
69
|
readOutput(ownerId: string, terminalId: string, cursor: number): {
|
|
69
70
|
data: string;
|
|
@@ -101,12 +102,13 @@ export declare class BrowserTerminal {
|
|
|
101
102
|
private readonly connection;
|
|
102
103
|
private readonly channel;
|
|
103
104
|
private readonly onClose;
|
|
104
|
-
private output;
|
|
105
|
-
private baseCursor;
|
|
105
|
+
private readonly output;
|
|
106
106
|
private closed;
|
|
107
107
|
private idleTimer;
|
|
108
|
+
private readonly orderedInput;
|
|
108
109
|
constructor(id: string, profileId: string, connection: ManagedSshConnection, channel: ClientChannel, onClose: () => void);
|
|
109
110
|
write(text: string): void;
|
|
111
|
+
writeOrdered(sequence: number | undefined, text: string): void;
|
|
110
112
|
resize(cols: number, rows: number): void;
|
|
111
113
|
read(cursor: number): {
|
|
112
114
|
data: string;
|
|
@@ -114,6 +116,7 @@ export declare class BrowserTerminal {
|
|
|
114
116
|
truncated: boolean;
|
|
115
117
|
closed: boolean;
|
|
116
118
|
};
|
|
119
|
+
subscribeOutput(listener: TerminalOutputListener): () => void;
|
|
117
120
|
close(): Promise<void>;
|
|
118
121
|
private append;
|
|
119
122
|
private touch;
|
package/lib/terminal.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"terminal.d.ts","sourceRoot":"","sources":["../src/terminal.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,MAAM,CAAA;AACzC,OAAO,KAAK,EACV,eAAe,EAAE,sBAAsB,EAAE,wBAAwB,EAAE,mBAAmB,EACtF,kBAAkB,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,kBAAkB,EAClF,qBAAqB,EAAE,cAAc,EAAE,oBAAoB,EAC5D,MAAM,2BAA2B,CAAA;AAClC,OAAO,EAAE,YAAY,EAAE,KAAK,oBAAoB,EAAE,MAAM,gBAAgB,CAAA;AACxE,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"terminal.d.ts","sourceRoot":"","sources":["../src/terminal.ts"],"names":[],"mappings":"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"}
|