@thenewlabs/entangle-serve 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent.d.ts +10 -0
- package/dist/agent.d.ts.map +1 -0
- package/dist/agent.js +167 -0
- package/dist/agent.js.map +1 -0
- package/dist/capability.d.ts +21 -0
- package/dist/capability.d.ts.map +1 -0
- package/dist/capability.js +75 -0
- package/dist/capability.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +73 -0
- package/dist/index.js.map +1 -0
- package/dist/multi-session.d.ts +27 -0
- package/dist/multi-session.d.ts.map +1 -0
- package/dist/multi-session.js +362 -0
- package/dist/multi-session.js.map +1 -0
- package/dist/session.d.ts +26 -0
- package/dist/session.d.ts.map +1 -0
- package/dist/session.js +215 -0
- package/dist/session.js.map +1 -0
- package/dist/stream-manager.d.ts +122 -0
- package/dist/stream-manager.d.ts.map +1 -0
- package/dist/stream-manager.js +488 -0
- package/dist/stream-manager.js.map +1 -0
- package/package.json +33 -0
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { OutputHandler } from '@thenewlabs/entangle-utils';
|
|
2
|
+
import { ChildProcess } from 'child_process';
|
|
3
|
+
import { EventEmitter } from 'events';
|
|
4
|
+
import * as pty from '@homebridge/node-pty-prebuilt-multiarch';
|
|
5
|
+
import { StreamMode, StreamMetadata, StreamUsage, StreamPtyOptions, StreamExecOptions, Policy } from '@thenewlabs/entangle-protocol';
|
|
6
|
+
export interface Stream {
|
|
7
|
+
sid: string;
|
|
8
|
+
mode: StreamMode;
|
|
9
|
+
startedAt: number;
|
|
10
|
+
endedAt?: number;
|
|
11
|
+
process?: ChildProcess | pty.IPty;
|
|
12
|
+
usage: StreamUsage;
|
|
13
|
+
aborted: boolean;
|
|
14
|
+
limits: {
|
|
15
|
+
cpuMs?: number;
|
|
16
|
+
memMB?: number;
|
|
17
|
+
wallMs?: number;
|
|
18
|
+
maxOutBytes?: number;
|
|
19
|
+
};
|
|
20
|
+
wallTimer?: ReturnType<typeof setTimeout>;
|
|
21
|
+
idleTimer?: ReturnType<typeof setTimeout>;
|
|
22
|
+
resourceTimer?: ReturnType<typeof setInterval>;
|
|
23
|
+
}
|
|
24
|
+
interface StreamManagerOptions {
|
|
25
|
+
policy: Policy;
|
|
26
|
+
output: OutputHandler;
|
|
27
|
+
onStreamData?: (sid: string, data: Uint8Array, channel: 'stdout' | 'stderr') => void;
|
|
28
|
+
onStreamExit?: (sid: string, code: number | null, signal: string | null, usage?: StreamUsage) => void;
|
|
29
|
+
onStreamError?: (sid: string, error: string) => void;
|
|
30
|
+
}
|
|
31
|
+
export declare class StreamManager extends EventEmitter {
|
|
32
|
+
private options;
|
|
33
|
+
private streams;
|
|
34
|
+
private policy;
|
|
35
|
+
private output;
|
|
36
|
+
private aggregateUsage;
|
|
37
|
+
constructor(options: StreamManagerOptions);
|
|
38
|
+
/**
|
|
39
|
+
* Generate a unique stream ID
|
|
40
|
+
*/
|
|
41
|
+
private generateStreamId;
|
|
42
|
+
/**
|
|
43
|
+
* Resolve a requested cwd and confine it to AGENT_DEFAULT_CWD (the working
|
|
44
|
+
* directory doubles as the execution boundary). Symlinks are resolved
|
|
45
|
+
* (realpath) BEFORE the prefix check so a symlink inside the dir can't point
|
|
46
|
+
* the process outside it. Throws if the resolved path is outside the boundary.
|
|
47
|
+
* NOTE: this only constrains the initial cwd, not a full filesystem sandbox.
|
|
48
|
+
*/
|
|
49
|
+
private resolveCwd;
|
|
50
|
+
/**
|
|
51
|
+
* Check if we can open a new stream
|
|
52
|
+
*/
|
|
53
|
+
private canOpenStream;
|
|
54
|
+
/**
|
|
55
|
+
* Get stream-specific limits.
|
|
56
|
+
*
|
|
57
|
+
* Interactive PTYs are deliberately exempt from ALL command-oriented caps —
|
|
58
|
+
* wall-clock, cumulative output ceiling, and CPU/memory guards. A legitimate
|
|
59
|
+
* terminal session can stay open for hours, stream far more than
|
|
60
|
+
* MAX_OUT_BYTES, and burn CPU interactively, so any of these would force-close
|
|
61
|
+
* it mid-use. A PTY is bounded solely by the idle timeout (see
|
|
62
|
+
* armIdleTimeout). Command ('cmd') streams keep every limit.
|
|
63
|
+
*/
|
|
64
|
+
private getStreamLimits;
|
|
65
|
+
/**
|
|
66
|
+
* Arm a wall-clock deadline that force-closes the stream if it outlives its
|
|
67
|
+
* limit. Unref'd so the timer never keeps the process alive on its own.
|
|
68
|
+
*/
|
|
69
|
+
private armWallClock;
|
|
70
|
+
/**
|
|
71
|
+
* (Re)arm the PTY idle timeout. Called on every byte of PTY output so an
|
|
72
|
+
* interactive session is only reaped after genuine inactivity.
|
|
73
|
+
*/
|
|
74
|
+
private armIdleTimeout;
|
|
75
|
+
private clearTimers;
|
|
76
|
+
private readProcessUsage;
|
|
77
|
+
private armResourceMonitor;
|
|
78
|
+
/**
|
|
79
|
+
* Open a new PTY stream
|
|
80
|
+
*/
|
|
81
|
+
openPtyStream(options: StreamPtyOptions & {
|
|
82
|
+
cwd?: string;
|
|
83
|
+
}): Promise<string>;
|
|
84
|
+
/**
|
|
85
|
+
* Open a new command stream
|
|
86
|
+
*/
|
|
87
|
+
openCmdStream(options: StreamExecOptions): Promise<string>;
|
|
88
|
+
/**
|
|
89
|
+
* Write data to a stream (stdin)
|
|
90
|
+
*/
|
|
91
|
+
writeToStream(sid: string, data: Uint8Array): void;
|
|
92
|
+
/**
|
|
93
|
+
* Resize a PTY stream
|
|
94
|
+
*/
|
|
95
|
+
resizePtyStream(sid: string, cols: number, rows: number): void;
|
|
96
|
+
/**
|
|
97
|
+
* Send signal to a stream
|
|
98
|
+
*/
|
|
99
|
+
signalStream(sid: string, signal: NodeJS.Signals): void;
|
|
100
|
+
/**
|
|
101
|
+
* Close a stream
|
|
102
|
+
*/
|
|
103
|
+
closeStream(sid: string, reason?: string): void;
|
|
104
|
+
/**
|
|
105
|
+
* Close all streams
|
|
106
|
+
*/
|
|
107
|
+
closeAllStreams(reason?: string): void;
|
|
108
|
+
/**
|
|
109
|
+
* Get stream info
|
|
110
|
+
*/
|
|
111
|
+
getStream(sid: string): Stream | undefined;
|
|
112
|
+
/**
|
|
113
|
+
* Get all active streams
|
|
114
|
+
*/
|
|
115
|
+
getActiveStreams(): StreamMetadata[];
|
|
116
|
+
/**
|
|
117
|
+
* Get aggregate usage across all streams
|
|
118
|
+
*/
|
|
119
|
+
getAggregateUsage(): StreamUsage;
|
|
120
|
+
}
|
|
121
|
+
export {};
|
|
122
|
+
//# sourceMappingURL=stream-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stream-manager.d.ts","sourceRoot":"","sources":["../src/stream-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,488 @@
|
|
|
1
|
+
import { validateArguments, validateCwd, buildChildEnv, getConfig } from '@thenewlabs/entangle-utils';
|
|
2
|
+
import { spawn } from 'child_process';
|
|
3
|
+
import { EventEmitter } from 'events';
|
|
4
|
+
import { randomBytes } from 'crypto';
|
|
5
|
+
import { readFileSync, realpathSync } from 'fs';
|
|
6
|
+
import { resolve as resolvePath } from 'path';
|
|
7
|
+
import * as pty from '@homebridge/node-pty-prebuilt-multiarch';
|
|
8
|
+
import { DEFAULT_LIMITS } from '@thenewlabs/entangle-protocol';
|
|
9
|
+
export class StreamManager extends EventEmitter {
|
|
10
|
+
options;
|
|
11
|
+
streams = new Map();
|
|
12
|
+
policy;
|
|
13
|
+
output;
|
|
14
|
+
aggregateUsage = {
|
|
15
|
+
cpuMs: 0,
|
|
16
|
+
rssMaxBytes: 0,
|
|
17
|
+
wallMs: 0,
|
|
18
|
+
outBytes: 0,
|
|
19
|
+
};
|
|
20
|
+
constructor(options) {
|
|
21
|
+
super();
|
|
22
|
+
this.options = options;
|
|
23
|
+
this.policy = options.policy;
|
|
24
|
+
this.output = options.output;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Generate a unique stream ID
|
|
28
|
+
*/
|
|
29
|
+
generateStreamId() {
|
|
30
|
+
return randomBytes(8).toString('base64url');
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Resolve a requested cwd and confine it to AGENT_DEFAULT_CWD (the working
|
|
34
|
+
* directory doubles as the execution boundary). Symlinks are resolved
|
|
35
|
+
* (realpath) BEFORE the prefix check so a symlink inside the dir can't point
|
|
36
|
+
* the process outside it. Throws if the resolved path is outside the boundary.
|
|
37
|
+
* NOTE: this only constrains the initial cwd, not a full filesystem sandbox.
|
|
38
|
+
*/
|
|
39
|
+
resolveCwd(requestedCwd) {
|
|
40
|
+
const config = getConfig();
|
|
41
|
+
const base = requestedCwd
|
|
42
|
+
? resolvePath(config.agentDefaultCwd, requestedCwd)
|
|
43
|
+
: config.agentDefaultCwd;
|
|
44
|
+
let real = base;
|
|
45
|
+
try {
|
|
46
|
+
real = realpathSync(base);
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
// Path may not exist yet; validate the resolved (non-symlink) form.
|
|
50
|
+
}
|
|
51
|
+
// Boundary-aware prefix check (see utils validateCwd).
|
|
52
|
+
validateCwd(real, config.agentAllowedCwd);
|
|
53
|
+
return real;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Check if we can open a new stream
|
|
57
|
+
*/
|
|
58
|
+
canOpenStream() {
|
|
59
|
+
const maxStreams = this.policy.maxStreams || 1;
|
|
60
|
+
if (this.streams.size >= maxStreams) {
|
|
61
|
+
return { allowed: false, reason: `Maximum streams (${maxStreams}) reached` };
|
|
62
|
+
}
|
|
63
|
+
return { allowed: true };
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Get stream-specific limits.
|
|
67
|
+
*
|
|
68
|
+
* Interactive PTYs are deliberately exempt from ALL command-oriented caps —
|
|
69
|
+
* wall-clock, cumulative output ceiling, and CPU/memory guards. A legitimate
|
|
70
|
+
* terminal session can stay open for hours, stream far more than
|
|
71
|
+
* MAX_OUT_BYTES, and burn CPU interactively, so any of these would force-close
|
|
72
|
+
* it mid-use. A PTY is bounded solely by the idle timeout (see
|
|
73
|
+
* armIdleTimeout). Command ('cmd') streams keep every limit.
|
|
74
|
+
*/
|
|
75
|
+
getStreamLimits(mode) {
|
|
76
|
+
const limits = {};
|
|
77
|
+
if (mode === 'pty')
|
|
78
|
+
return limits;
|
|
79
|
+
const maxStreams = this.policy.maxStreams || 1;
|
|
80
|
+
const config = getConfig();
|
|
81
|
+
const perStream = this.policy.perStream;
|
|
82
|
+
// Apply defaults even when a partial per-stream policy is present.
|
|
83
|
+
const cpuMs = perStream?.maxCpuMs ?? this.policy.maxCpuMs ?? DEFAULT_LIMITS.MAX_CPU_MS;
|
|
84
|
+
const memMB = perStream?.maxMemMB ?? this.policy.maxMemMB ?? DEFAULT_LIMITS.MAX_MEM_MB;
|
|
85
|
+
limits.cpuMs = Math.max(1, Math.floor(cpuMs / maxStreams));
|
|
86
|
+
limits.memMB = Math.max(1, Math.floor(memMB / maxStreams));
|
|
87
|
+
const wallMs = perStream?.maxWallMs ?? this.policy.maxWallMs ?? config.cmdDefaultWallMs;
|
|
88
|
+
if (wallMs > 0)
|
|
89
|
+
limits.wallMs = Math.floor(wallMs / maxStreams);
|
|
90
|
+
const maxOutBytes = perStream?.maxOutBytes ?? this.policy.maxOutBytes ?? config.maxOutBytes;
|
|
91
|
+
if (maxOutBytes > 0)
|
|
92
|
+
limits.maxOutBytes = Math.floor(maxOutBytes / maxStreams);
|
|
93
|
+
return limits;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Arm a wall-clock deadline that force-closes the stream if it outlives its
|
|
97
|
+
* limit. Unref'd so the timer never keeps the process alive on its own.
|
|
98
|
+
*/
|
|
99
|
+
armWallClock(stream) {
|
|
100
|
+
const wallMs = stream.limits.wallMs;
|
|
101
|
+
if (!wallMs || wallMs <= 0)
|
|
102
|
+
return;
|
|
103
|
+
stream.wallTimer = setTimeout(() => {
|
|
104
|
+
const current = this.streams.get(stream.sid);
|
|
105
|
+
if (current && current.endedAt === undefined) {
|
|
106
|
+
this.output.warn(`Stream wall-clock limit exceeded for ${stream.sid}: limit=${wallMs}ms`);
|
|
107
|
+
this.closeStream(stream.sid, 'Wall-clock limit exceeded');
|
|
108
|
+
}
|
|
109
|
+
}, wallMs);
|
|
110
|
+
if (typeof stream.wallTimer.unref === 'function')
|
|
111
|
+
stream.wallTimer.unref();
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* (Re)arm the PTY idle timeout. Called on every byte of PTY output so an
|
|
115
|
+
* interactive session is only reaped after genuine inactivity.
|
|
116
|
+
*/
|
|
117
|
+
armIdleTimeout(stream, idleMs) {
|
|
118
|
+
if (!idleMs || idleMs <= 0)
|
|
119
|
+
return;
|
|
120
|
+
if (stream.idleTimer)
|
|
121
|
+
clearTimeout(stream.idleTimer);
|
|
122
|
+
stream.idleTimer = setTimeout(() => {
|
|
123
|
+
const current = this.streams.get(stream.sid);
|
|
124
|
+
if (current && current.endedAt === undefined) {
|
|
125
|
+
this.output.warn(`PTY idle timeout for ${stream.sid}: idle=${idleMs}ms`);
|
|
126
|
+
this.closeStream(stream.sid, 'Idle timeout');
|
|
127
|
+
}
|
|
128
|
+
}, idleMs);
|
|
129
|
+
if (typeof stream.idleTimer.unref === 'function')
|
|
130
|
+
stream.idleTimer.unref();
|
|
131
|
+
}
|
|
132
|
+
clearTimers(stream) {
|
|
133
|
+
if (stream.wallTimer) {
|
|
134
|
+
clearTimeout(stream.wallTimer);
|
|
135
|
+
delete stream.wallTimer;
|
|
136
|
+
}
|
|
137
|
+
if (stream.idleTimer) {
|
|
138
|
+
clearTimeout(stream.idleTimer);
|
|
139
|
+
delete stream.idleTimer;
|
|
140
|
+
}
|
|
141
|
+
if (stream.resourceTimer) {
|
|
142
|
+
clearInterval(stream.resourceTimer);
|
|
143
|
+
delete stream.resourceTimer;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
readProcessUsage(pid) {
|
|
147
|
+
if (process.platform !== 'linux')
|
|
148
|
+
return undefined;
|
|
149
|
+
try {
|
|
150
|
+
const stat = readFileSync(`/proc/${pid}/stat`, 'utf8');
|
|
151
|
+
const endComm = stat.lastIndexOf(')');
|
|
152
|
+
if (endComm < 0)
|
|
153
|
+
return undefined;
|
|
154
|
+
const fields = stat.slice(endComm + 2).trim().split(/\s+/);
|
|
155
|
+
const userTicks = Number(fields[11]);
|
|
156
|
+
const systemTicks = Number(fields[12]);
|
|
157
|
+
const rssPages = Number(fields[21]);
|
|
158
|
+
if (![userTicks, systemTicks, rssPages].every(Number.isFinite))
|
|
159
|
+
return undefined;
|
|
160
|
+
return { cpuMs: ((userTicks + systemTicks) * 1000) / 100, rssBytes: rssPages * 4096 };
|
|
161
|
+
}
|
|
162
|
+
catch {
|
|
163
|
+
return undefined;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
armResourceMonitor(stream) {
|
|
167
|
+
const pid = stream.process && 'pid' in stream.process ? stream.process.pid : undefined;
|
|
168
|
+
if (!pid || (!stream.limits.cpuMs && !stream.limits.memMB))
|
|
169
|
+
return;
|
|
170
|
+
stream.resourceTimer = setInterval(() => {
|
|
171
|
+
const usage = this.readProcessUsage(pid);
|
|
172
|
+
if (!usage)
|
|
173
|
+
return;
|
|
174
|
+
stream.usage.cpuMs = usage.cpuMs;
|
|
175
|
+
stream.usage.rssMaxBytes = Math.max(stream.usage.rssMaxBytes, usage.rssBytes);
|
|
176
|
+
if (stream.limits.cpuMs && usage.cpuMs > stream.limits.cpuMs) {
|
|
177
|
+
this.closeStream(stream.sid, 'CPU limit exceeded');
|
|
178
|
+
}
|
|
179
|
+
else if (stream.limits.memMB && usage.rssBytes > stream.limits.memMB * 1024 * 1024) {
|
|
180
|
+
this.closeStream(stream.sid, 'Memory limit exceeded');
|
|
181
|
+
}
|
|
182
|
+
}, 100);
|
|
183
|
+
if (typeof stream.resourceTimer.unref === 'function')
|
|
184
|
+
stream.resourceTimer.unref();
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Open a new PTY stream
|
|
188
|
+
*/
|
|
189
|
+
async openPtyStream(options) {
|
|
190
|
+
const check = this.canOpenStream();
|
|
191
|
+
if (!check.allowed) {
|
|
192
|
+
throw new Error(check.reason);
|
|
193
|
+
}
|
|
194
|
+
const sid = this.generateStreamId();
|
|
195
|
+
const limits = this.getStreamLimits('pty');
|
|
196
|
+
const config = getConfig();
|
|
197
|
+
const cwd = this.resolveCwd(options.cwd);
|
|
198
|
+
const env = buildChildEnv(config.agentEnvPassthrough, options.env);
|
|
199
|
+
env.TERM = 'xterm-256color';
|
|
200
|
+
// Create PTY
|
|
201
|
+
const ptyProcess = pty.spawn(config.agentShell, [], {
|
|
202
|
+
name: 'xterm-256color',
|
|
203
|
+
cols: options.cols,
|
|
204
|
+
rows: options.rows,
|
|
205
|
+
cwd,
|
|
206
|
+
env,
|
|
207
|
+
});
|
|
208
|
+
const stream = {
|
|
209
|
+
sid,
|
|
210
|
+
mode: 'pty',
|
|
211
|
+
startedAt: Date.now(),
|
|
212
|
+
process: ptyProcess,
|
|
213
|
+
usage: { cpuMs: 0, rssMaxBytes: 0, wallMs: 0, outBytes: 0 },
|
|
214
|
+
aborted: false,
|
|
215
|
+
limits,
|
|
216
|
+
};
|
|
217
|
+
const idleMs = config.ttyIdleTimeoutMs;
|
|
218
|
+
// Handle PTY data
|
|
219
|
+
ptyProcess.onData((data) => {
|
|
220
|
+
if (stream.aborted)
|
|
221
|
+
return;
|
|
222
|
+
const chunk = Buffer.from(data);
|
|
223
|
+
// Track bytes for usage reporting only; PTYs have no cumulative output
|
|
224
|
+
// ceiling (limits.maxOutBytes is unset for pty streams).
|
|
225
|
+
stream.usage.outBytes += chunk.length;
|
|
226
|
+
this.armIdleTimeout(stream, idleMs);
|
|
227
|
+
this.options.onStreamData?.(sid, chunk, 'stdout');
|
|
228
|
+
});
|
|
229
|
+
// Handle PTY exit
|
|
230
|
+
ptyProcess.onExit((exitCode) => {
|
|
231
|
+
stream.endedAt = Date.now();
|
|
232
|
+
stream.usage.wallMs = stream.endedAt - stream.startedAt;
|
|
233
|
+
this.clearTimers(stream);
|
|
234
|
+
this.output.info(`PTY stream exited for ${sid}: code=${exitCode.exitCode}, signal=${exitCode.signal}`);
|
|
235
|
+
this.options.onStreamExit?.(sid, exitCode.exitCode ?? null, exitCode.signal ? String(exitCode.signal) : null, stream.usage);
|
|
236
|
+
this.streams.delete(sid);
|
|
237
|
+
});
|
|
238
|
+
this.streams.set(sid, stream);
|
|
239
|
+
// No wall-clock or resource monitor for PTYs — only the idle timeout bounds
|
|
240
|
+
// an interactive session (see getStreamLimits).
|
|
241
|
+
this.armIdleTimeout(stream, idleMs);
|
|
242
|
+
this.output.info(`Opened PTY stream ${sid}: cols=${options.cols}, rows=${options.rows}`);
|
|
243
|
+
return sid;
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Open a new command stream
|
|
247
|
+
*/
|
|
248
|
+
async openCmdStream(options) {
|
|
249
|
+
const check = this.canOpenStream();
|
|
250
|
+
if (!check.allowed) {
|
|
251
|
+
throw new Error(check.reason);
|
|
252
|
+
}
|
|
253
|
+
// Validate arguments
|
|
254
|
+
try {
|
|
255
|
+
const config = getConfig();
|
|
256
|
+
validateArguments(options.argv, config.maxArgCount, config.maxArgLen);
|
|
257
|
+
}
|
|
258
|
+
catch (err) {
|
|
259
|
+
throw new Error(`Invalid arguments: ${err.message}`);
|
|
260
|
+
}
|
|
261
|
+
const sid = this.generateStreamId();
|
|
262
|
+
const limits = this.getStreamLimits('cmd');
|
|
263
|
+
const config = getConfig();
|
|
264
|
+
// Spawn process with a validated cwd and a minimal, curated environment.
|
|
265
|
+
const spawnOptions = {
|
|
266
|
+
shell: false,
|
|
267
|
+
detached: process.platform !== 'win32',
|
|
268
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
269
|
+
cwd: this.resolveCwd(options.cwd),
|
|
270
|
+
env: buildChildEnv(config.agentEnvPassthrough, options.env),
|
|
271
|
+
};
|
|
272
|
+
if (!options.argv || options.argv.length === 0) {
|
|
273
|
+
throw new Error('No command specified');
|
|
274
|
+
}
|
|
275
|
+
const [command, ...args] = options.argv;
|
|
276
|
+
if (!command) {
|
|
277
|
+
throw new Error('No command specified');
|
|
278
|
+
}
|
|
279
|
+
const childProcess = spawn(command, args, spawnOptions);
|
|
280
|
+
const stream = {
|
|
281
|
+
sid,
|
|
282
|
+
mode: 'cmd',
|
|
283
|
+
startedAt: Date.now(),
|
|
284
|
+
process: childProcess,
|
|
285
|
+
usage: { cpuMs: 0, rssMaxBytes: 0, wallMs: 0, outBytes: 0 },
|
|
286
|
+
aborted: false,
|
|
287
|
+
limits,
|
|
288
|
+
};
|
|
289
|
+
// Handle stdout / stderr (both count toward the output ceiling, but are
|
|
290
|
+
// tagged so the invoker can route them to the right fd).
|
|
291
|
+
const handleOutput = (channel) => (chunk) => {
|
|
292
|
+
if (stream.aborted)
|
|
293
|
+
return;
|
|
294
|
+
stream.usage.outBytes += chunk.length;
|
|
295
|
+
// Check output limit
|
|
296
|
+
if (limits.maxOutBytes && stream.usage.outBytes > limits.maxOutBytes) {
|
|
297
|
+
this.output.warn(`Stream output limit exceeded for ${sid}: limit=${limits.maxOutBytes}`);
|
|
298
|
+
this.closeStream(sid, 'Output limit exceeded');
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
this.options.onStreamData?.(sid, chunk, channel);
|
|
302
|
+
};
|
|
303
|
+
if (childProcess.stdout) {
|
|
304
|
+
childProcess.stdout.on('data', handleOutput('stdout'));
|
|
305
|
+
}
|
|
306
|
+
if (childProcess.stderr) {
|
|
307
|
+
childProcess.stderr.on('data', handleOutput('stderr'));
|
|
308
|
+
}
|
|
309
|
+
// Use 'close' (not 'exit') so all stdout/stderr 'data' events have been
|
|
310
|
+
// emitted before we report exit. Otherwise a fast command can emit EXIT
|
|
311
|
+
// ahead of its final output, and the client — which tears the stream down
|
|
312
|
+
// on exit — would drop that trailing data.
|
|
313
|
+
childProcess.on('close', (code, signal) => {
|
|
314
|
+
stream.endedAt = Date.now();
|
|
315
|
+
stream.usage.wallMs = stream.endedAt - stream.startedAt;
|
|
316
|
+
this.clearTimers(stream);
|
|
317
|
+
this.output.info(`Command stream exited for ${sid}: code=${code}, signal=${signal}`);
|
|
318
|
+
this.options.onStreamExit?.(sid, code, signal, stream.usage);
|
|
319
|
+
this.streams.delete(sid);
|
|
320
|
+
});
|
|
321
|
+
// Handle process errors
|
|
322
|
+
childProcess.on('error', (err) => {
|
|
323
|
+
this.clearTimers(stream);
|
|
324
|
+
this.output.error(`Command stream error for ${sid}`, err.message);
|
|
325
|
+
this.options.onStreamError?.(sid, err.message);
|
|
326
|
+
this.streams.delete(sid);
|
|
327
|
+
});
|
|
328
|
+
this.streams.set(sid, stream);
|
|
329
|
+
this.armWallClock(stream);
|
|
330
|
+
this.armResourceMonitor(stream);
|
|
331
|
+
// Log the command name and arg count only; full argv can carry secrets.
|
|
332
|
+
this.output.info(`Opened command stream ${sid}: ${command} (${args.length} args)`);
|
|
333
|
+
return sid;
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* Write data to a stream (stdin)
|
|
337
|
+
*/
|
|
338
|
+
writeToStream(sid, data) {
|
|
339
|
+
const stream = this.streams.get(sid);
|
|
340
|
+
if (!stream) {
|
|
341
|
+
throw new Error(`Unknown stream: ${sid}`);
|
|
342
|
+
}
|
|
343
|
+
if (stream.aborted) {
|
|
344
|
+
throw new Error(`Stream ${sid} is aborted`);
|
|
345
|
+
}
|
|
346
|
+
if (stream.mode === 'pty') {
|
|
347
|
+
const ptyProcess = stream.process;
|
|
348
|
+
ptyProcess.write(Buffer.from(data).toString());
|
|
349
|
+
}
|
|
350
|
+
else {
|
|
351
|
+
const childProcess = stream.process;
|
|
352
|
+
if (childProcess.stdin && !childProcess.stdin.destroyed) {
|
|
353
|
+
childProcess.stdin.write(data);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
/**
|
|
358
|
+
* Resize a PTY stream
|
|
359
|
+
*/
|
|
360
|
+
resizePtyStream(sid, cols, rows) {
|
|
361
|
+
const stream = this.streams.get(sid);
|
|
362
|
+
if (!stream) {
|
|
363
|
+
throw new Error(`Unknown stream: ${sid}`);
|
|
364
|
+
}
|
|
365
|
+
if (stream.mode !== 'pty') {
|
|
366
|
+
throw new Error(`Stream ${sid} is not a PTY`);
|
|
367
|
+
}
|
|
368
|
+
const ptyProcess = stream.process;
|
|
369
|
+
ptyProcess.resize(cols, rows);
|
|
370
|
+
this.output.debug(`Resized PTY stream ${sid}: cols=${cols}, rows=${rows}`);
|
|
371
|
+
}
|
|
372
|
+
/**
|
|
373
|
+
* Send signal to a stream
|
|
374
|
+
*/
|
|
375
|
+
signalStream(sid, signal) {
|
|
376
|
+
const stream = this.streams.get(sid);
|
|
377
|
+
if (!stream) {
|
|
378
|
+
throw new Error(`Unknown stream: ${sid}`);
|
|
379
|
+
}
|
|
380
|
+
if (stream.mode === 'pty') {
|
|
381
|
+
const ptyProcess = stream.process;
|
|
382
|
+
ptyProcess.kill(signal);
|
|
383
|
+
}
|
|
384
|
+
else {
|
|
385
|
+
const childProcess = stream.process;
|
|
386
|
+
childProcess.kill(signal);
|
|
387
|
+
}
|
|
388
|
+
this.output.info(`Sent signal ${signal} to stream ${sid}`);
|
|
389
|
+
}
|
|
390
|
+
/**
|
|
391
|
+
* Close a stream
|
|
392
|
+
*/
|
|
393
|
+
closeStream(sid, reason) {
|
|
394
|
+
const stream = this.streams.get(sid);
|
|
395
|
+
if (!stream) {
|
|
396
|
+
return; // Already closed
|
|
397
|
+
}
|
|
398
|
+
stream.aborted = true;
|
|
399
|
+
this.clearTimers(stream);
|
|
400
|
+
if (stream.mode === 'pty') {
|
|
401
|
+
const ptyProcess = stream.process;
|
|
402
|
+
try {
|
|
403
|
+
ptyProcess.kill();
|
|
404
|
+
}
|
|
405
|
+
catch (err) {
|
|
406
|
+
this.output.error(`Failed to kill PTY for stream ${sid}`, err instanceof Error ? err.message : String(err));
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
else {
|
|
410
|
+
const childProcess = stream.process;
|
|
411
|
+
try {
|
|
412
|
+
// Signal the whole process group (child was spawned detached) so shell
|
|
413
|
+
// pipelines and descendants are torn down, not just the direct child.
|
|
414
|
+
try {
|
|
415
|
+
if (process.platform !== 'win32' && childProcess.pid)
|
|
416
|
+
process.kill(-childProcess.pid, 'SIGTERM');
|
|
417
|
+
else
|
|
418
|
+
childProcess.kill('SIGTERM');
|
|
419
|
+
}
|
|
420
|
+
catch {
|
|
421
|
+
childProcess.kill('SIGTERM');
|
|
422
|
+
}
|
|
423
|
+
// Escalate to SIGKILL if the process has not actually exited. Note:
|
|
424
|
+
// childProcess.killed only means "a signal was delivered", so it is
|
|
425
|
+
// true right after SIGTERM and must NOT gate escalation. We key off the
|
|
426
|
+
// real exit state instead: the 'close' handler deletes the stream from
|
|
427
|
+
// the map and sets endedAt, so a still-present, not-yet-ended stream is
|
|
428
|
+
// one that ignored SIGTERM.
|
|
429
|
+
const timer = setTimeout(() => {
|
|
430
|
+
const current = this.streams.get(sid);
|
|
431
|
+
if (current && current.endedAt === undefined) {
|
|
432
|
+
try {
|
|
433
|
+
if (process.platform !== 'win32' && childProcess.pid)
|
|
434
|
+
process.kill(-childProcess.pid, 'SIGKILL');
|
|
435
|
+
else
|
|
436
|
+
childProcess.kill('SIGKILL');
|
|
437
|
+
}
|
|
438
|
+
catch { }
|
|
439
|
+
}
|
|
440
|
+
}, 5000);
|
|
441
|
+
// Don't keep the event loop alive just for the escalation timer.
|
|
442
|
+
if (typeof timer.unref === 'function')
|
|
443
|
+
timer.unref();
|
|
444
|
+
}
|
|
445
|
+
catch (err) {
|
|
446
|
+
this.output.error(`Failed to kill process for stream ${sid}`, err instanceof Error ? err.message : String(err));
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
this.output.info(`Closed stream ${sid}: reason=${reason}`);
|
|
450
|
+
}
|
|
451
|
+
/**
|
|
452
|
+
* Close all streams
|
|
453
|
+
*/
|
|
454
|
+
closeAllStreams(reason) {
|
|
455
|
+
for (const sid of this.streams.keys()) {
|
|
456
|
+
this.closeStream(sid, reason);
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
/**
|
|
460
|
+
* Get stream info
|
|
461
|
+
*/
|
|
462
|
+
getStream(sid) {
|
|
463
|
+
return this.streams.get(sid);
|
|
464
|
+
}
|
|
465
|
+
/**
|
|
466
|
+
* Get all active streams
|
|
467
|
+
*/
|
|
468
|
+
getActiveStreams() {
|
|
469
|
+
return Array.from(this.streams.values()).map(stream => {
|
|
470
|
+
const metadata = {
|
|
471
|
+
sid: stream.sid,
|
|
472
|
+
mode: stream.mode,
|
|
473
|
+
startedAt: stream.startedAt,
|
|
474
|
+
};
|
|
475
|
+
if (stream.endedAt !== undefined) {
|
|
476
|
+
metadata.endedAt = stream.endedAt;
|
|
477
|
+
}
|
|
478
|
+
return metadata;
|
|
479
|
+
});
|
|
480
|
+
}
|
|
481
|
+
/**
|
|
482
|
+
* Get aggregate usage across all streams
|
|
483
|
+
*/
|
|
484
|
+
getAggregateUsage() {
|
|
485
|
+
return this.aggregateUsage;
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
//# sourceMappingURL=stream-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stream-manager.js","sourceRoot":"","sources":["../src/stream-manager.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@thenewlabs/entangle-serve",
|
|
3
|
+
"version": "2.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"entangle-serve": "dist/index.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"dist"
|
|
11
|
+
],
|
|
12
|
+
"scripts": {
|
|
13
|
+
"build": "tsc",
|
|
14
|
+
"start": "node dist/index.js",
|
|
15
|
+
"dev": "tsx src/index.ts",
|
|
16
|
+
"clean": "rm -rf dist tsconfig.tsbuildinfo"
|
|
17
|
+
},
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"@homebridge/node-pty-prebuilt-multiarch": "^0.13.1",
|
|
20
|
+
"@thenewlabs/entangle-crypto": "^2.1.0",
|
|
21
|
+
"@thenewlabs/entangle-protocol": "^2.1.0",
|
|
22
|
+
"@thenewlabs/entangle-utils": "^2.1.0",
|
|
23
|
+
"cborg": "^4.5.8",
|
|
24
|
+
"commander": "^15.0.0",
|
|
25
|
+
"ws": "^8.21.0"
|
|
26
|
+
},
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"@types/node": "^20.19.43",
|
|
29
|
+
"@types/ws": "^8.18.1",
|
|
30
|
+
"tsx": "^4.23.0",
|
|
31
|
+
"typescript": "^5.9.3"
|
|
32
|
+
}
|
|
33
|
+
}
|