@datnguyennnx/localterm-server 0.0.15 → 0.0.16
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/rpc.d.ts +22 -0
- package/dist/agent/rpc.d.ts.map +1 -0
- package/dist/agent/rpc.js +233 -0
- package/dist/agent/rpc.js.map +1 -0
- package/dist/agent/token.d.ts +21 -0
- package/dist/agent/token.d.ts.map +1 -0
- package/dist/agent/token.js +56 -0
- package/dist/agent/token.js.map +1 -0
- package/dist/agent-rpc.d.ts +0 -5
- package/dist/agent-rpc.d.ts.map +1 -1
- package/dist/agent-rpc.js +34 -14
- package/dist/agent-rpc.js.map +1 -1
- package/dist/agent-token.d.ts.map +1 -1
- package/dist/agent-token.js +10 -7
- package/dist/agent-token.js.map +1 -1
- package/dist/ensure-spawn-helper-executable.js +3 -3
- package/dist/ensure-spawn-helper-executable.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/osc-chunk-parser.d.ts +32 -0
- package/dist/osc-chunk-parser.d.ts.map +1 -0
- package/dist/osc-chunk-parser.js +56 -0
- package/dist/osc-chunk-parser.js.map +1 -0
- package/dist/osc133-chunk-parser.d.ts +9 -5
- package/dist/osc133-chunk-parser.d.ts.map +1 -1
- package/dist/osc133-chunk-parser.js +9 -25
- package/dist/osc133-chunk-parser.js.map +1 -1
- package/dist/osc7-chunk-parser.d.ts +8 -5
- package/dist/osc7-chunk-parser.d.ts.map +1 -1
- package/dist/osc7-chunk-parser.js +9 -25
- package/dist/osc7-chunk-parser.js.map +1 -1
- package/dist/output-batcher.d.ts +2 -1
- package/dist/output-batcher.d.ts.map +1 -1
- package/dist/output-batcher.js +3 -1
- package/dist/output-batcher.js.map +1 -1
- package/dist/parser/osc.d.ts +32 -0
- package/dist/parser/osc.d.ts.map +1 -0
- package/dist/parser/osc.js +56 -0
- package/dist/parser/osc.js.map +1 -0
- package/dist/parser/osc133-chunk-parser.d.ts +12 -0
- package/dist/parser/osc133-chunk-parser.d.ts.map +1 -0
- package/dist/parser/osc133-chunk-parser.js +13 -0
- package/dist/parser/osc133-chunk-parser.js.map +1 -0
- package/dist/parser/osc7-chunk-parser.d.ts +10 -0
- package/dist/parser/osc7-chunk-parser.d.ts.map +1 -0
- package/dist/parser/osc7-chunk-parser.js +13 -0
- package/dist/parser/osc7-chunk-parser.js.map +1 -0
- package/dist/parser/parse-osc133-from-chunk.d.ts +10 -0
- package/dist/parser/parse-osc133-from-chunk.d.ts.map +1 -0
- package/dist/parser/parse-osc133-from-chunk.js +49 -0
- package/dist/parser/parse-osc133-from-chunk.js.map +1 -0
- package/dist/parser/parse-osc7-from-chunk.d.ts +2 -0
- package/dist/parser/parse-osc7-from-chunk.d.ts.map +1 -0
- package/dist/parser/parse-osc7-from-chunk.js +33 -0
- package/dist/parser/parse-osc7-from-chunk.js.map +1 -0
- package/dist/parser/strip-ansi.d.ts +13 -0
- package/dist/parser/strip-ansi.d.ts.map +1 -0
- package/dist/parser/strip-ansi.js +26 -0
- package/dist/parser/strip-ansi.js.map +1 -0
- package/dist/schemas.js +1 -1
- package/dist/schemas.js.map +1 -1
- package/dist/server/index.d.ts +25 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +433 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/security.d.ts +5 -0
- package/dist/server/security.d.ts.map +1 -0
- package/dist/server/security.js +63 -0
- package/dist/server/security.js.map +1 -0
- package/dist/server/static-resolver.d.ts +7 -0
- package/dist/server/static-resolver.d.ts.map +1 -0
- package/dist/server/static-resolver.js +65 -0
- package/dist/server/static-resolver.js.map +1 -0
- package/dist/session/default-shell.d.ts +2 -0
- package/dist/session/default-shell.d.ts.map +1 -0
- package/dist/session/default-shell.js +44 -0
- package/dist/session/default-shell.js.map +1 -0
- package/dist/session/ensure-spawn-helper-executable.d.ts +2 -0
- package/dist/session/ensure-spawn-helper-executable.d.ts.map +1 -0
- package/dist/session/ensure-spawn-helper-executable.js +34 -0
- package/dist/session/ensure-spawn-helper-executable.js.map +1 -0
- package/dist/session/session-registry.d.ts +9 -0
- package/dist/session/session-registry.d.ts.map +1 -0
- package/dist/session/session-registry.js +19 -0
- package/dist/session/session-registry.js.map +1 -0
- package/dist/session/session.d.ts +62 -0
- package/dist/session/session.d.ts.map +1 -0
- package/dist/session/session.js +245 -0
- package/dist/session/session.js.map +1 -0
- package/dist/session.d.ts +1 -1
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +12 -5
- package/dist/session.js.map +1 -1
- package/dist/static-resolver.js +1 -1
- package/dist/static-resolver.js.map +1 -1
- package/dist/utils/parse-osc133-from-chunk.d.ts.map +1 -1
- package/dist/utils/parse-osc133-from-chunk.js +10 -5
- package/dist/utils/parse-osc133-from-chunk.js.map +1 -1
- package/dist/utils/parse-osc7-from-chunk.d.ts.map +1 -1
- package/dist/utils/parse-osc7-from-chunk.js +4 -3
- package/dist/utils/parse-osc7-from-chunk.js.map +1 -1
- package/dist/utils/strip-ansi.d.ts.map +1 -1
- package/dist/utils/strip-ansi.js +6 -8
- package/dist/utils/strip-ansi.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type CommandBoundary } from "../parser/parse-osc133-from-chunk.js";
|
|
2
|
+
import { Session } from "../session/session.js";
|
|
3
|
+
import { SessionRegistry } from "../session/session-registry.js";
|
|
4
|
+
export interface ManagedSession {
|
|
5
|
+
id: string;
|
|
6
|
+
session: Session;
|
|
7
|
+
outputBuffer: string[];
|
|
8
|
+
outputOffset: number;
|
|
9
|
+
lastBoundary: CommandBoundary | null;
|
|
10
|
+
}
|
|
11
|
+
export interface RpcContext {
|
|
12
|
+
registry: SessionRegistry;
|
|
13
|
+
allowDestructiveCommands: boolean;
|
|
14
|
+
sendResponse: (id: string, result?: unknown, error?: string) => void;
|
|
15
|
+
}
|
|
16
|
+
export interface RpcRequest {
|
|
17
|
+
id: string;
|
|
18
|
+
method: string;
|
|
19
|
+
params?: Record<string, unknown>;
|
|
20
|
+
}
|
|
21
|
+
export declare const handleRpcRequest: (ctx: RpcContext, request: RpcRequest) => void;
|
|
22
|
+
//# sourceMappingURL=rpc.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rpc.d.ts","sourceRoot":"","sources":["../../src/agent/rpc.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,sCAAsC,CAAC;AAE5E,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AAsCjE,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,eAAe,GAAG,IAAI,CAAC;CACtC;AASD,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,eAAe,CAAC;IAC1B,wBAAwB,EAAE,OAAO,CAAC;IAClC,YAAY,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;CACtE;AAED,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAED,eAAO,MAAM,gBAAgB,GAC3B,KAAK,UAAU,EACf,SAAS,UAAU,KAClB,IAuBF,CAAC"}
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { AGENT_COMMAND_DENYLIST } from "../constants.js";
|
|
4
|
+
import { stripAnsi } from "../parser/strip-ansi.js";
|
|
5
|
+
import {} from "../parser/parse-osc133-from-chunk.js";
|
|
6
|
+
import {} from "../types.js";
|
|
7
|
+
import { Session } from "../session/session.js";
|
|
8
|
+
import { SessionRegistry } from "../session/session-registry.js";
|
|
9
|
+
// ─── RPC parameter schemas ───────────────────────────────────────────────────
|
|
10
|
+
const SpawnSessionParamsSchema = z.object({
|
|
11
|
+
cwd: z.string().optional(),
|
|
12
|
+
shell: z.string().optional(),
|
|
13
|
+
}).strict();
|
|
14
|
+
const WriteInputParamsSchema = z.object({
|
|
15
|
+
sessionId: z.string().min(1),
|
|
16
|
+
data: z.string(),
|
|
17
|
+
}).strict();
|
|
18
|
+
const ReadOutputParamsSchema = z.object({
|
|
19
|
+
sessionId: z.string().min(1),
|
|
20
|
+
sinceOffset: z.number().optional(),
|
|
21
|
+
}).strict();
|
|
22
|
+
const WaitForBoundaryParamsSchema = z.object({
|
|
23
|
+
sessionId: z.string().min(1),
|
|
24
|
+
timeoutMs: z.number().optional(),
|
|
25
|
+
}).strict();
|
|
26
|
+
const ExecParamsSchema = z.object({
|
|
27
|
+
sessionId: z.string().min(1),
|
|
28
|
+
command: z.string().min(1),
|
|
29
|
+
timeoutMs: z.number().optional(),
|
|
30
|
+
}).strict();
|
|
31
|
+
const isCommandDenied = (command) => {
|
|
32
|
+
for (const pattern of AGENT_COMMAND_DENYLIST) {
|
|
33
|
+
if (command.includes(pattern))
|
|
34
|
+
return pattern;
|
|
35
|
+
}
|
|
36
|
+
return null;
|
|
37
|
+
};
|
|
38
|
+
export const handleRpcRequest = (ctx, request) => {
|
|
39
|
+
const { id, method, params } = request;
|
|
40
|
+
try {
|
|
41
|
+
switch (method) {
|
|
42
|
+
case "spawn_session":
|
|
43
|
+
return handleSpawnSession(ctx, id, params ?? {});
|
|
44
|
+
case "list_sessions":
|
|
45
|
+
return handleListSessions(ctx, id);
|
|
46
|
+
case "write_input":
|
|
47
|
+
return handleWriteInput(ctx, id, params ?? {});
|
|
48
|
+
case "read_output":
|
|
49
|
+
return handleReadOutput(ctx, id, params ?? {});
|
|
50
|
+
case "wait_for_boundary":
|
|
51
|
+
return handleWaitForBoundary(ctx, id, params ?? {});
|
|
52
|
+
case "exec":
|
|
53
|
+
return handleExec(ctx, id, params ?? {});
|
|
54
|
+
default:
|
|
55
|
+
ctx.sendResponse(id, undefined, `unknown method: ${method}`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
60
|
+
ctx.sendResponse(id, undefined, `internal error: ${message}`);
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
const handleSpawnSession = (ctx, id, params) => {
|
|
64
|
+
const { cwd, shell } = SpawnSessionParamsSchema.parse(params);
|
|
65
|
+
const sessionId = randomUUID();
|
|
66
|
+
const input = {
|
|
67
|
+
cwd,
|
|
68
|
+
shell,
|
|
69
|
+
mode: "agent",
|
|
70
|
+
env: { LOCALTERM_SHELL_INTEGRATION: "1" },
|
|
71
|
+
};
|
|
72
|
+
const session = new Session(input);
|
|
73
|
+
ctx.registry.register(session);
|
|
74
|
+
const managed = {
|
|
75
|
+
id: sessionId,
|
|
76
|
+
session,
|
|
77
|
+
outputBuffer: [],
|
|
78
|
+
outputOffset: 0,
|
|
79
|
+
lastBoundary: null,
|
|
80
|
+
};
|
|
81
|
+
activeSessions.set(sessionId, managed);
|
|
82
|
+
session.on("output", (data) => {
|
|
83
|
+
const text = stripAnsi(data);
|
|
84
|
+
if (text)
|
|
85
|
+
managed.outputBuffer.push(text);
|
|
86
|
+
});
|
|
87
|
+
session.on("commandBoundary", (boundary) => {
|
|
88
|
+
managed.lastBoundary = boundary;
|
|
89
|
+
});
|
|
90
|
+
session.on("exit", () => {
|
|
91
|
+
ctx.registry.unregister(session);
|
|
92
|
+
activeSessions.delete(sessionId);
|
|
93
|
+
});
|
|
94
|
+
ctx.sendResponse(id, {
|
|
95
|
+
sessionId,
|
|
96
|
+
shell: session.shell,
|
|
97
|
+
pid: session.pid,
|
|
98
|
+
cwd: session.cwd,
|
|
99
|
+
});
|
|
100
|
+
};
|
|
101
|
+
const handleListSessions = (ctx, id) => {
|
|
102
|
+
const sessions = Array.from(activeSessions.values()).map((m) => ({
|
|
103
|
+
id: m.id,
|
|
104
|
+
cwd: m.session.cwd,
|
|
105
|
+
pid: m.session.pid,
|
|
106
|
+
mode: "agent",
|
|
107
|
+
running: !m.session.isExited,
|
|
108
|
+
}));
|
|
109
|
+
ctx.sendResponse(id, { sessions });
|
|
110
|
+
};
|
|
111
|
+
const handleWriteInput = (ctx, id, params) => {
|
|
112
|
+
const { sessionId, data } = WriteInputParamsSchema.parse(params);
|
|
113
|
+
const managed = activeSessions.get(sessionId);
|
|
114
|
+
if (!managed) {
|
|
115
|
+
ctx.sendResponse(id, undefined, `session not found: ${sessionId}`);
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
if (managed.session.isExited) {
|
|
119
|
+
ctx.sendResponse(id, undefined, "session has exited");
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
managed.session.write(data);
|
|
123
|
+
ctx.sendResponse(id, { ok: true });
|
|
124
|
+
};
|
|
125
|
+
const handleReadOutput = (ctx, id, params) => {
|
|
126
|
+
const { sessionId, sinceOffset } = ReadOutputParamsSchema.parse(params);
|
|
127
|
+
const managed = activeSessions.get(sessionId);
|
|
128
|
+
if (!managed) {
|
|
129
|
+
ctx.sendResponse(id, undefined, `session not found: ${sessionId}`);
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
const offset = typeof sinceOffset === "number" ? sinceOffset : managed.outputOffset;
|
|
133
|
+
const buffer = managed.outputBuffer;
|
|
134
|
+
let charCount = 0;
|
|
135
|
+
let startIndex = -1;
|
|
136
|
+
for (let i = 0; i < buffer.length; i++) {
|
|
137
|
+
const entryLen = buffer[i].length;
|
|
138
|
+
if (charCount + entryLen > offset && startIndex === -1)
|
|
139
|
+
startIndex = i;
|
|
140
|
+
charCount += entryLen;
|
|
141
|
+
}
|
|
142
|
+
if (startIndex === -1) {
|
|
143
|
+
ctx.sendResponse(id, { text: "", offset: charCount });
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
const text = buffer.slice(startIndex).join("");
|
|
147
|
+
const newOffset = charCount;
|
|
148
|
+
managed.outputOffset = newOffset;
|
|
149
|
+
// Trim consumed entries to prevent unbounded memory growth in long sessions.
|
|
150
|
+
managed.outputBuffer.splice(0, startIndex);
|
|
151
|
+
ctx.sendResponse(id, { text, offset: newOffset });
|
|
152
|
+
};
|
|
153
|
+
const handleWaitForBoundary = (ctx, id, params) => {
|
|
154
|
+
const { sessionId, timeoutMs } = WaitForBoundaryParamsSchema.parse(params);
|
|
155
|
+
const managed = activeSessions.get(sessionId);
|
|
156
|
+
if (!managed) {
|
|
157
|
+
ctx.sendResponse(id, undefined, `session not found: ${sessionId}`);
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
const timeout = typeof timeoutMs === "number" ? timeoutMs : 30000;
|
|
161
|
+
if (managed.lastBoundary) {
|
|
162
|
+
const boundary = managed.lastBoundary;
|
|
163
|
+
managed.lastBoundary = null;
|
|
164
|
+
ctx.sendResponse(id, boundary);
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
const handler = (boundary) => {
|
|
168
|
+
managed.session.off("commandBoundary", handler);
|
|
169
|
+
clearTimeout(timer);
|
|
170
|
+
ctx.sendResponse(id, boundary);
|
|
171
|
+
};
|
|
172
|
+
const timer = setTimeout(() => {
|
|
173
|
+
managed.session.off("commandBoundary", handler);
|
|
174
|
+
ctx.sendResponse(id, undefined, "timeout");
|
|
175
|
+
}, timeout);
|
|
176
|
+
timer.unref();
|
|
177
|
+
managed.session.on("commandBoundary", handler);
|
|
178
|
+
};
|
|
179
|
+
const handleExec = (ctx, id, params) => {
|
|
180
|
+
const { sessionId, command, timeoutMs } = ExecParamsSchema.parse(params);
|
|
181
|
+
const managed = activeSessions.get(sessionId);
|
|
182
|
+
if (!managed) {
|
|
183
|
+
ctx.sendResponse(id, undefined, `session not found: ${sessionId}`);
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
if (!command || typeof command !== "string") {
|
|
187
|
+
ctx.sendResponse(id, undefined, "command must be a non-empty string");
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
if (!ctx.allowDestructiveCommands) {
|
|
191
|
+
const denied = isCommandDenied(command);
|
|
192
|
+
if (denied) {
|
|
193
|
+
ctx.sendResponse(id, undefined, `command denied by allowlist (matched pattern: "${denied}"). pass --yolo to localterm start to disable this check.`);
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
if (managed.session.isExited) {
|
|
198
|
+
ctx.sendResponse(id, undefined, "session has exited");
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
const timeout = typeof timeoutMs === "number" ? timeoutMs : 60000;
|
|
202
|
+
managed.session.write(command + "\n");
|
|
203
|
+
const handler = (boundary) => {
|
|
204
|
+
if (boundary.phase !== "command-end")
|
|
205
|
+
return;
|
|
206
|
+
managed.session.off("commandBoundary", handler);
|
|
207
|
+
clearTimeout(timer);
|
|
208
|
+
const text = managed.outputBuffer.join("");
|
|
209
|
+
managed.outputBuffer = [];
|
|
210
|
+
ctx.sendResponse(id, {
|
|
211
|
+
stdoutText: text,
|
|
212
|
+
exitCode: boundary.exitCode ?? 0,
|
|
213
|
+
});
|
|
214
|
+
};
|
|
215
|
+
const timer = setTimeout(() => {
|
|
216
|
+
managed.session.off("commandBoundary", handler);
|
|
217
|
+
const text = managed.outputBuffer.join("");
|
|
218
|
+
managed.outputBuffer = [];
|
|
219
|
+
ctx.sendResponse(id, {
|
|
220
|
+
stdoutText: text,
|
|
221
|
+
exitCode: null,
|
|
222
|
+
partial: true,
|
|
223
|
+
});
|
|
224
|
+
}, timeout);
|
|
225
|
+
timer.unref();
|
|
226
|
+
managed.session.on("commandBoundary", handler);
|
|
227
|
+
};
|
|
228
|
+
/**
|
|
229
|
+
* Map of session ID → ManagedSession for all sessions created via RPC.
|
|
230
|
+
* These are separate from the human-connection sessions managed by the registry.
|
|
231
|
+
*/
|
|
232
|
+
const activeSessions = new Map();
|
|
233
|
+
//# sourceMappingURL=rpc.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rpc.js","sourceRoot":"","sources":["../../src/agent/rpc.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Load the agent token from ~/.localterm/agent-token.
|
|
3
|
+
* If the file doesn't exist, generate a new token, write it with 0600 perms,
|
|
4
|
+
* and return it. This ensures every `localterm start` gets a fresh token
|
|
5
|
+
* and the file persists across the daemon's lifetime.
|
|
6
|
+
*
|
|
7
|
+
* Token is used for authenticating agent-mode WebSocket connections.
|
|
8
|
+
* Human-mode connections (default) do not require a token.
|
|
9
|
+
*/
|
|
10
|
+
export declare const loadOrCreateAgentToken: () => string;
|
|
11
|
+
/**
|
|
12
|
+
* Validate a candidate token against the stored agent token.
|
|
13
|
+
* Returns true if the token matches (constant-time comparison not required —
|
|
14
|
+
* this is a local-only security boundary; timing attacks assume network access).
|
|
15
|
+
*/
|
|
16
|
+
export declare const validateAgentToken: (candidate: string) => boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Get the path to the agent token file (for CLI display / docs).
|
|
19
|
+
*/
|
|
20
|
+
export declare const getAgentTokenPath: () => string;
|
|
21
|
+
//# sourceMappingURL=token.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token.d.ts","sourceRoot":"","sources":["../../src/agent/token.ts"],"names":[],"mappings":"AAkBA;;;;;;;;GAQG;AACH,eAAO,MAAM,sBAAsB,QAAO,MAgBzC,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,GAAI,WAAW,MAAM,KAAG,OAGtD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,iBAAiB,QAAO,MAAoB,CAAC"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { randomBytes } from "node:crypto";
|
|
2
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { homedir } from "node:os";
|
|
5
|
+
const LOCALTERM_DIR = join(homedir(), ".localterm");
|
|
6
|
+
const TOKEN_FILE = join(LOCALTERM_DIR, "agent-token");
|
|
7
|
+
const TOKEN_BYTES = 32; // 256-bit token
|
|
8
|
+
let cachedToken = null;
|
|
9
|
+
/**
|
|
10
|
+
* Generate a cryptographically random hex token.
|
|
11
|
+
*/
|
|
12
|
+
const generateToken = () => {
|
|
13
|
+
return randomBytes(TOKEN_BYTES).toString("hex");
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Load the agent token from ~/.localterm/agent-token.
|
|
17
|
+
* If the file doesn't exist, generate a new token, write it with 0600 perms,
|
|
18
|
+
* and return it. This ensures every `localterm start` gets a fresh token
|
|
19
|
+
* and the file persists across the daemon's lifetime.
|
|
20
|
+
*
|
|
21
|
+
* Token is used for authenticating agent-mode WebSocket connections.
|
|
22
|
+
* Human-mode connections (default) do not require a token.
|
|
23
|
+
*/
|
|
24
|
+
export const loadOrCreateAgentToken = () => {
|
|
25
|
+
if (cachedToken)
|
|
26
|
+
return cachedToken;
|
|
27
|
+
if (existsSync(TOKEN_FILE)) {
|
|
28
|
+
const raw = readFileSync(TOKEN_FILE, "utf-8").trim();
|
|
29
|
+
if (raw.length > 0) {
|
|
30
|
+
cachedToken = raw;
|
|
31
|
+
return cachedToken;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
const token = generateToken();
|
|
35
|
+
if (!existsSync(LOCALTERM_DIR)) {
|
|
36
|
+
mkdirSync(LOCALTERM_DIR, { recursive: true, mode: 0o755 });
|
|
37
|
+
}
|
|
38
|
+
writeFileSync(TOKEN_FILE, token + "\n", { mode: 0o600, encoding: "utf-8" });
|
|
39
|
+
cachedToken = token;
|
|
40
|
+
return token;
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* Validate a candidate token against the stored agent token.
|
|
44
|
+
* Returns true if the token matches (constant-time comparison not required —
|
|
45
|
+
* this is a local-only security boundary; timing attacks assume network access).
|
|
46
|
+
*/
|
|
47
|
+
export const validateAgentToken = (candidate) => {
|
|
48
|
+
if (!cachedToken)
|
|
49
|
+
return false;
|
|
50
|
+
return candidate === cachedToken;
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* Get the path to the agent token file (for CLI display / docs).
|
|
54
|
+
*/
|
|
55
|
+
export const getAgentTokenPath = () => TOKEN_FILE;
|
|
56
|
+
//# sourceMappingURL=token.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token.js","sourceRoot":"","sources":["../../src/agent/token.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAElC,MAAM,aAAa,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,YAAY,CAAC,CAAC;AACpD,MAAM,UAAU,GAAG,IAAI,CAAC,aAAa,EAAE,aAAa,CAAC,CAAC;AACtD,MAAM,WAAW,GAAG,EAAE,CAAC,CAAC,gBAAgB;AAExC,IAAI,WAAW,GAAkB,IAAI,CAAC;AAEtC;;GAEG;AACH,MAAM,aAAa,GAAG,GAAW,EAAE;IACjC,OAAO,WAAW,CAAC,WAAW,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AAClD,CAAC,CAAC;AAEF;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,GAAW,EAAE;IACjD,IAAI,WAAW;QAAE,OAAO,WAAW,CAAC;IACpC,IAAI,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC3B,MAAM,GAAG,GAAG,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;QACrD,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACnB,WAAW,GAAG,GAAG,CAAC;YAClB,OAAO,WAAW,CAAC;QACrB,CAAC;IACH,CAAC;IACD,MAAM,KAAK,GAAG,aAAa,EAAE,CAAC;IAC9B,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;QAC/B,SAAS,CAAC,aAAa,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAC7D,CAAC;IACD,aAAa,CAAC,UAAU,EAAE,KAAK,GAAG,IAAI,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;IAC5E,WAAW,GAAG,KAAK,CAAC;IACpB,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,SAAiB,EAAW,EAAE;IAC/D,IAAI,CAAC,WAAW;QAAE,OAAO,KAAK,CAAC;IAC/B,OAAO,SAAS,KAAK,WAAW,CAAC;AACnC,CAAC,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,GAAW,EAAE,CAAC,UAAU,CAAC"}
|
package/dist/agent-rpc.d.ts
CHANGED
|
@@ -19,9 +19,4 @@ export interface RpcRequest {
|
|
|
19
19
|
params?: Record<string, unknown>;
|
|
20
20
|
}
|
|
21
21
|
export declare const handleRpcRequest: (ctx: RpcContext, request: RpcRequest) => void;
|
|
22
|
-
/**
|
|
23
|
-
* Map of session ID → ManagedSession for all sessions created via RPC.
|
|
24
|
-
* These are separate from the human-connection sessions managed by the registry.
|
|
25
|
-
*/
|
|
26
|
-
export declare const activeSessions: Map<string, ManagedSession>;
|
|
27
22
|
//# sourceMappingURL=agent-rpc.d.ts.map
|
package/dist/agent-rpc.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-rpc.d.ts","sourceRoot":"","sources":["../src/agent-rpc.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"agent-rpc.d.ts","sourceRoot":"","sources":["../src/agent-rpc.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,oCAAoC,CAAC;AAE1E,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAsCxD,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,eAAe,GAAG,IAAI,CAAC;CACtC;AASD,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,eAAe,CAAC;IAC1B,wBAAwB,EAAE,OAAO,CAAC;IAClC,YAAY,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;CACtE;AAED,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAED,eAAO,MAAM,gBAAgB,GAC3B,KAAK,UAAU,EACf,SAAS,UAAU,KAClB,IAuBF,CAAC"}
|
package/dist/agent-rpc.js
CHANGED
|
@@ -1,17 +1,35 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { z } from "zod";
|
|
1
3
|
import { AGENT_COMMAND_DENYLIST } from "./constants.js";
|
|
2
4
|
import { stripAnsi } from "./utils/strip-ansi.js";
|
|
3
5
|
import {} from "./utils/parse-osc133-from-chunk.js";
|
|
4
6
|
import {} from "./types.js";
|
|
5
7
|
import { Session } from "./session.js";
|
|
6
8
|
import { SessionRegistry } from "./session-registry.js";
|
|
7
|
-
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
// ─── RPC parameter schemas ───────────────────────────────────────────────────
|
|
10
|
+
const SpawnSessionParamsSchema = z.object({
|
|
11
|
+
cwd: z.string().optional(),
|
|
12
|
+
shell: z.string().optional(),
|
|
13
|
+
}).strict();
|
|
14
|
+
const WriteInputParamsSchema = z.object({
|
|
15
|
+
sessionId: z.string().min(1),
|
|
16
|
+
data: z.string(),
|
|
17
|
+
}).strict();
|
|
18
|
+
const ReadOutputParamsSchema = z.object({
|
|
19
|
+
sessionId: z.string().min(1),
|
|
20
|
+
sinceOffset: z.number().optional(),
|
|
21
|
+
}).strict();
|
|
22
|
+
const WaitForBoundaryParamsSchema = z.object({
|
|
23
|
+
sessionId: z.string().min(1),
|
|
24
|
+
timeoutMs: z.number().optional(),
|
|
25
|
+
}).strict();
|
|
26
|
+
const ExecParamsSchema = z.object({
|
|
27
|
+
sessionId: z.string().min(1),
|
|
28
|
+
command: z.string().min(1),
|
|
29
|
+
timeoutMs: z.number().optional(),
|
|
30
|
+
}).strict();
|
|
13
31
|
const isCommandDenied = (command) => {
|
|
14
|
-
for (const
|
|
32
|
+
for (const pattern of AGENT_COMMAND_DENYLIST) {
|
|
15
33
|
if (command.includes(pattern))
|
|
16
34
|
return pattern;
|
|
17
35
|
}
|
|
@@ -43,8 +61,8 @@ export const handleRpcRequest = (ctx, request) => {
|
|
|
43
61
|
}
|
|
44
62
|
};
|
|
45
63
|
const handleSpawnSession = (ctx, id, params) => {
|
|
46
|
-
const { cwd, shell } = params;
|
|
47
|
-
const sessionId =
|
|
64
|
+
const { cwd, shell } = SpawnSessionParamsSchema.parse(params);
|
|
65
|
+
const sessionId = randomUUID();
|
|
48
66
|
const input = {
|
|
49
67
|
cwd,
|
|
50
68
|
shell,
|
|
@@ -91,7 +109,7 @@ const handleListSessions = (ctx, id) => {
|
|
|
91
109
|
ctx.sendResponse(id, { sessions });
|
|
92
110
|
};
|
|
93
111
|
const handleWriteInput = (ctx, id, params) => {
|
|
94
|
-
const { sessionId, data } = params;
|
|
112
|
+
const { sessionId, data } = WriteInputParamsSchema.parse(params);
|
|
95
113
|
const managed = activeSessions.get(sessionId);
|
|
96
114
|
if (!managed) {
|
|
97
115
|
ctx.sendResponse(id, undefined, `session not found: ${sessionId}`);
|
|
@@ -105,7 +123,7 @@ const handleWriteInput = (ctx, id, params) => {
|
|
|
105
123
|
ctx.sendResponse(id, { ok: true });
|
|
106
124
|
};
|
|
107
125
|
const handleReadOutput = (ctx, id, params) => {
|
|
108
|
-
const { sessionId, sinceOffset } = params;
|
|
126
|
+
const { sessionId, sinceOffset } = ReadOutputParamsSchema.parse(params);
|
|
109
127
|
const managed = activeSessions.get(sessionId);
|
|
110
128
|
if (!managed) {
|
|
111
129
|
ctx.sendResponse(id, undefined, `session not found: ${sessionId}`);
|
|
@@ -128,10 +146,12 @@ const handleReadOutput = (ctx, id, params) => {
|
|
|
128
146
|
const text = buffer.slice(startIndex).join("");
|
|
129
147
|
const newOffset = charCount;
|
|
130
148
|
managed.outputOffset = newOffset;
|
|
149
|
+
// Trim consumed entries to prevent unbounded memory growth in long sessions.
|
|
150
|
+
managed.outputBuffer.splice(0, startIndex);
|
|
131
151
|
ctx.sendResponse(id, { text, offset: newOffset });
|
|
132
152
|
};
|
|
133
153
|
const handleWaitForBoundary = (ctx, id, params) => {
|
|
134
|
-
const { sessionId, timeoutMs } = params;
|
|
154
|
+
const { sessionId, timeoutMs } = WaitForBoundaryParamsSchema.parse(params);
|
|
135
155
|
const managed = activeSessions.get(sessionId);
|
|
136
156
|
if (!managed) {
|
|
137
157
|
ctx.sendResponse(id, undefined, `session not found: ${sessionId}`);
|
|
@@ -157,7 +177,7 @@ const handleWaitForBoundary = (ctx, id, params) => {
|
|
|
157
177
|
managed.session.on("commandBoundary", handler);
|
|
158
178
|
};
|
|
159
179
|
const handleExec = (ctx, id, params) => {
|
|
160
|
-
const { sessionId, command, timeoutMs } = params;
|
|
180
|
+
const { sessionId, command, timeoutMs } = ExecParamsSchema.parse(params);
|
|
161
181
|
const managed = activeSessions.get(sessionId);
|
|
162
182
|
if (!managed) {
|
|
163
183
|
ctx.sendResponse(id, undefined, `session not found: ${sessionId}`);
|
|
@@ -209,5 +229,5 @@ const handleExec = (ctx, id, params) => {
|
|
|
209
229
|
* Map of session ID → ManagedSession for all sessions created via RPC.
|
|
210
230
|
* These are separate from the human-connection sessions managed by the registry.
|
|
211
231
|
*/
|
|
212
|
-
|
|
232
|
+
const activeSessions = new Map();
|
|
213
233
|
//# sourceMappingURL=agent-rpc.js.map
|
package/dist/agent-rpc.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-rpc.js","sourceRoot":"","sources":["../src/agent-rpc.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,EAAwB,MAAM,oCAAoC,CAAC;AAC1E,OAAO,EAAsB,MAAM,YAAY,CAAC;AAChD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"agent-rpc.js","sourceRoot":"","sources":["../src/agent-rpc.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-token.d.ts","sourceRoot":"","sources":["../src/agent-token.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"agent-token.d.ts","sourceRoot":"","sources":["../src/agent-token.ts"],"names":[],"mappings":"AAkBA;;;;;;;;GAQG;AACH,eAAO,MAAM,sBAAsB,QAAO,MAgBzC,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,GAAI,WAAW,MAAM,KAAG,OAGtD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,iBAAiB,QAAO,MAAoB,CAAC"}
|
package/dist/agent-token.js
CHANGED
|
@@ -5,6 +5,7 @@ import { homedir } from "node:os";
|
|
|
5
5
|
const LOCALTERM_DIR = join(homedir(), ".localterm");
|
|
6
6
|
const TOKEN_FILE = join(LOCALTERM_DIR, "agent-token");
|
|
7
7
|
const TOKEN_BYTES = 32; // 256-bit token
|
|
8
|
+
let cachedToken = null;
|
|
8
9
|
/**
|
|
9
10
|
* Generate a cryptographically random hex token.
|
|
10
11
|
*/
|
|
@@ -21,16 +22,21 @@ const generateToken = () => {
|
|
|
21
22
|
* Human-mode connections (default) do not require a token.
|
|
22
23
|
*/
|
|
23
24
|
export const loadOrCreateAgentToken = () => {
|
|
25
|
+
if (cachedToken)
|
|
26
|
+
return cachedToken;
|
|
24
27
|
if (existsSync(TOKEN_FILE)) {
|
|
25
28
|
const raw = readFileSync(TOKEN_FILE, "utf-8").trim();
|
|
26
|
-
if (raw.length > 0)
|
|
27
|
-
|
|
29
|
+
if (raw.length > 0) {
|
|
30
|
+
cachedToken = raw;
|
|
31
|
+
return cachedToken;
|
|
32
|
+
}
|
|
28
33
|
}
|
|
29
34
|
const token = generateToken();
|
|
30
35
|
if (!existsSync(LOCALTERM_DIR)) {
|
|
31
36
|
mkdirSync(LOCALTERM_DIR, { recursive: true, mode: 0o755 });
|
|
32
37
|
}
|
|
33
38
|
writeFileSync(TOKEN_FILE, token + "\n", { mode: 0o600, encoding: "utf-8" });
|
|
39
|
+
cachedToken = token;
|
|
34
40
|
return token;
|
|
35
41
|
};
|
|
36
42
|
/**
|
|
@@ -39,12 +45,9 @@ export const loadOrCreateAgentToken = () => {
|
|
|
39
45
|
* this is a local-only security boundary; timing attacks assume network access).
|
|
40
46
|
*/
|
|
41
47
|
export const validateAgentToken = (candidate) => {
|
|
42
|
-
if (!
|
|
48
|
+
if (!cachedToken)
|
|
43
49
|
return false;
|
|
44
|
-
|
|
45
|
-
if (!stored)
|
|
46
|
-
return false;
|
|
47
|
-
return candidate === stored;
|
|
50
|
+
return candidate === cachedToken;
|
|
48
51
|
};
|
|
49
52
|
/**
|
|
50
53
|
* Get the path to the agent token file (for CLI display / docs).
|
package/dist/agent-token.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-token.js","sourceRoot":"","sources":["../src/agent-token.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAElC,MAAM,aAAa,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,YAAY,CAAC,CAAC;AACpD,MAAM,UAAU,GAAG,IAAI,CAAC,aAAa,EAAE,aAAa,CAAC,CAAC;AACtD,MAAM,WAAW,GAAG,EAAE,CAAC,CAAC,gBAAgB;AAExC;;GAEG;AACH,MAAM,aAAa,GAAG,GAAW,EAAE;IACjC,OAAO,WAAW,CAAC,WAAW,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AAClD,CAAC,CAAC;AAEF;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,GAAW,EAAE;IACjD,IAAI,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC3B,MAAM,GAAG,GAAG,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;QACrD,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC;
|
|
1
|
+
{"version":3,"file":"agent-token.js","sourceRoot":"","sources":["../src/agent-token.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAElC,MAAM,aAAa,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,YAAY,CAAC,CAAC;AACpD,MAAM,UAAU,GAAG,IAAI,CAAC,aAAa,EAAE,aAAa,CAAC,CAAC;AACtD,MAAM,WAAW,GAAG,EAAE,CAAC,CAAC,gBAAgB;AAExC,IAAI,WAAW,GAAkB,IAAI,CAAC;AAEtC;;GAEG;AACH,MAAM,aAAa,GAAG,GAAW,EAAE;IACjC,OAAO,WAAW,CAAC,WAAW,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AAClD,CAAC,CAAC;AAEF;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,GAAW,EAAE;IACjD,IAAI,WAAW;QAAE,OAAO,WAAW,CAAC;IACpC,IAAI,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC3B,MAAM,GAAG,GAAG,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;QACrD,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACnB,WAAW,GAAG,GAAG,CAAC;YAClB,OAAO,WAAW,CAAC;QACrB,CAAC;IACH,CAAC;IACD,MAAM,KAAK,GAAG,aAAa,EAAE,CAAC;IAC9B,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;QAC/B,SAAS,CAAC,aAAa,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAC7D,CAAC;IACD,aAAa,CAAC,UAAU,EAAE,KAAK,GAAG,IAAI,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;IAC5E,WAAW,GAAG,KAAK,CAAC;IACpB,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,SAAiB,EAAW,EAAE;IAC/D,IAAI,CAAC,WAAW;QAAE,OAAO,KAAK,CAAC;IAC/B,OAAO,SAAS,KAAK,WAAW,CAAC;AACnC,CAAC,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,GAAW,EAAE,CAAC,UAAU,CAAC"}
|
|
@@ -3,15 +3,15 @@ import { createRequire } from "node:module";
|
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
const requireCjs = createRequire(import.meta.url);
|
|
5
5
|
const SPAWN_HELPER_MODE = 0o755;
|
|
6
|
-
let
|
|
6
|
+
let hasEnsuredSpawnHelper = false;
|
|
7
7
|
const candidateSpawnHelperPaths = (nodePtyDir) => [
|
|
8
8
|
path.join(nodePtyDir, "build", "Release", "spawn-helper"),
|
|
9
9
|
path.join(nodePtyDir, "prebuilds", `${process.platform}-${process.arch}`, "spawn-helper"),
|
|
10
10
|
];
|
|
11
11
|
export const ensureSpawnHelperExecutable = () => {
|
|
12
|
-
if (
|
|
12
|
+
if (hasEnsuredSpawnHelper)
|
|
13
13
|
return;
|
|
14
|
-
|
|
14
|
+
hasEnsuredSpawnHelper = true;
|
|
15
15
|
let nodePtyDir;
|
|
16
16
|
try {
|
|
17
17
|
const ptyEntry = requireCjs.resolve("node-pty");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ensure-spawn-helper-executable.js","sourceRoot":"","sources":["../src/ensure-spawn-helper-executable.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,iBAAiB,GAAG,KAAK,CAAC;AAEhC,IAAI,
|
|
1
|
+
{"version":3,"file":"ensure-spawn-helper-executable.js","sourceRoot":"","sources":["../src/ensure-spawn-helper-executable.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,iBAAiB,GAAG,KAAK,CAAC;AAEhC,IAAI,qBAAqB,GAAG,KAAK,CAAC;AAElC,MAAM,yBAAyB,GAAG,CAAC,UAAkB,EAAY,EAAE,CAAC;IAClE,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,OAAO,EAAE,SAAS,EAAE,cAAc,CAAC;IACzD,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,IAAI,EAAE,EAAE,cAAc,CAAC;CAC1F,CAAC;AAEF,MAAM,CAAC,MAAM,2BAA2B,GAAG,GAAS,EAAE;IACpD,IAAI,qBAAqB;QAAE,OAAO;IAClC,qBAAqB,GAAG,IAAI,CAAC;IAC7B,IAAI,UAAkB,CAAC;IACvB,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,UAAU,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QAChD,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC;IACpD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO;IACT,CAAC;IACD,KAAK,MAAM,SAAS,IAAI,yBAAyB,CAAC,UAAU,CAAC,EAAE,CAAC;QAC9D,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC;YAAE,SAAS;QACrC,IAAI,CAAC;YACH,SAAS,CAAC,SAAS,EAAE,iBAAiB,CAAC,CAAC;QAC1C,CAAC;QAAC,MAAM,CAAC;YACP,mFAAmF;QACrF,CAAC;IACH,CAAC;AACH,CAAC,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -210,7 +210,7 @@ export const createServer = async (options = {}) => {
|
|
|
210
210
|
// from Session (current or future) reaches the client. Today
|
|
211
211
|
// node-pty's data/exit are async, but this guards against drift.
|
|
212
212
|
outputBatcher = new OutputBatcher((output) => {
|
|
213
|
-
safeSendRaw(ws, output.buffer);
|
|
213
|
+
safeSendRaw(ws, output.buffer.slice(output.byteOffset, output.byteOffset + output.byteLength));
|
|
214
214
|
if (!newSession.isPaused &&
|
|
215
215
|
getRawBufferedAmount(ws.raw) >= WS_OUTBOUND_PAUSE_HIGH_WATER_BYTES) {
|
|
216
216
|
newSession.pause();
|