@pasko70/pibo 1.14.0 → 1.15.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/apps/chat-ui/assets/{dist-DmqwP_tM.js → dist-BFwSuVfD.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-ur4yXrlj.js → dist-BYTi90un.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-hoDORUlL.js → dist-Bi74WdBU.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-BIwXuAMQ.js → dist-CYMM1_bS.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-BG1J2hGI.js → dist-CuIwfDgF.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-LWXXqiGT.js → dist-DS1ScAMf.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-1eQpSfYj.js → dist-DUgrMhHX.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-CtsdsIpj.js → dist-Dq3i1LVZ.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-DfdQQObC.js → dist-Dy5L1xOD.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-BeCHnL7P.js → dist-Zy3KnDp7.js} +1 -1
- package/dist/apps/chat-ui/assets/index-BZO4zpMi.js +237 -0
- package/dist/apps/chat-ui/index.html +1 -1
- package/dist/apps/chat-vscode-web/assets/{index-R_7kgvvD.js → index-V_pKPVAm.js} +3 -3
- package/dist/apps/chat-vscode-web/index.html +1 -1
- package/dist/apps/vscode-artifacts/latest.vsix +0 -0
- package/dist/apps/vscode-artifacts/{pibo-vscode-ext-1.14.0.vsix → pibo-vscode-ext-1.15.0.vsix} +0 -0
- package/dist/core/runtime.js +27 -5
- package/dist/plugins/builtin.js +7 -0
- package/dist/session-ui/terminalRows.js +12 -2
- package/dist/tools/browser-use-leases.js +16 -0
- package/dist/tools/codex-browser-node-repl.js +224 -0
- package/dist/tools/codex-browser-node-worker-source.js +403 -0
- package/dist/tools/codex-browser.js +461 -0
- package/package.json +3 -1
- package/dist/apps/chat-ui/assets/index-DLNTzhdh.js +0 -237
|
@@ -0,0 +1,403 @@
|
|
|
1
|
+
export const CODEX_BROWSER_NODE_WORKER_SOURCE = String.raw `
|
|
2
|
+
const vm = require("node:vm");
|
|
3
|
+
const util = require("node:util");
|
|
4
|
+
const { Parser } = require(process.argv[1]);
|
|
5
|
+
const walk = require(process.argv[2]);
|
|
6
|
+
|
|
7
|
+
let context;
|
|
8
|
+
let currentOutput = null;
|
|
9
|
+
let browserRequestCounter = 0;
|
|
10
|
+
let timerCounter = 0;
|
|
11
|
+
const pendingBrowserRequests = new Map();
|
|
12
|
+
const timers = new Map();
|
|
13
|
+
|
|
14
|
+
function hardenFunction(fn) {
|
|
15
|
+
Object.setPrototypeOf(fn, null);
|
|
16
|
+
return Object.freeze(fn);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function nullObject(properties) {
|
|
20
|
+
return Object.freeze(Object.assign(Object.create(null), properties));
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function bounded(value, maxBytes = 8192) {
|
|
24
|
+
const text = String(value);
|
|
25
|
+
const bytes = Buffer.byteLength(text, "utf8");
|
|
26
|
+
if (bytes <= maxBytes) return text;
|
|
27
|
+
return Buffer.from(text, "utf8").subarray(0, maxBytes).toString("utf8") + "\n...<truncated>";
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function safeInspect(value, maxBytes = 4096) {
|
|
31
|
+
try {
|
|
32
|
+
return bounded(util.inspect(value, { depth: 4, maxArrayLength: 100, breakLength: 120 }), maxBytes);
|
|
33
|
+
} catch (error) {
|
|
34
|
+
return "<inspect failed: " + (error?.name || "Error") + ": " + (error?.message || String(error)) + ">";
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function summarize(value, maxBytes = 4096) {
|
|
39
|
+
const type = value === null ? "null" : Array.isArray(value) ? "array" : typeof value;
|
|
40
|
+
const result = { type, repr: safeInspect(value, maxBytes) };
|
|
41
|
+
try {
|
|
42
|
+
if (value != null && typeof value.length === "number") result.length = value.length;
|
|
43
|
+
if (value && typeof value === "object") {
|
|
44
|
+
const keys = Object.keys(value).slice(0, 100);
|
|
45
|
+
if (keys.length > 0) result.keys = keys;
|
|
46
|
+
}
|
|
47
|
+
} catch {}
|
|
48
|
+
return result;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function errorSummary(error) {
|
|
52
|
+
const stack = error && error.stack ? String(error.stack) : String(error);
|
|
53
|
+
const out = {
|
|
54
|
+
name: error && error.name ? String(error.name) : "Error",
|
|
55
|
+
message: error && error.message ? String(error.message) : String(error),
|
|
56
|
+
stack,
|
|
57
|
+
};
|
|
58
|
+
const match = stack.match(/<node_repl>:(\d+):(\d+)/) || stack.match(/evalmachine\.<anonymous>:(\d+):(\d+)/);
|
|
59
|
+
if (match) {
|
|
60
|
+
out.line = Number(match[1]);
|
|
61
|
+
out.column = Number(match[2]);
|
|
62
|
+
}
|
|
63
|
+
return out;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function appendStdout(chunk) {
|
|
67
|
+
if (currentOutput) currentOutput.stdout += String(chunk);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function appendStderr(chunk) {
|
|
71
|
+
if (currentOutput) currentOutput.stderr += String(chunk);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function requestBrowser(operation, input = {}) {
|
|
75
|
+
const id = "browser_" + (++browserRequestCounter);
|
|
76
|
+
const promise = new Promise((resolve, reject) => {
|
|
77
|
+
pendingBrowserRequests.set(id, { resolve, reject });
|
|
78
|
+
writeMessage({ type: "browser_request", id, operation, input });
|
|
79
|
+
});
|
|
80
|
+
return nullObject({
|
|
81
|
+
then: hardenFunction((resolve, reject) => promise.then(resolve, reject)),
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function createTimer(repeat, callback, delay, args) {
|
|
86
|
+
if (typeof callback !== "function") throw new TypeError("Timer callback must be a function");
|
|
87
|
+
const id = ++timerCounter;
|
|
88
|
+
const invoke = () => callback(...args);
|
|
89
|
+
const timer = repeat ? setInterval(invoke, delay) : setTimeout(() => {
|
|
90
|
+
timers.delete(id);
|
|
91
|
+
invoke();
|
|
92
|
+
}, delay);
|
|
93
|
+
timers.set(id, { repeat, timer });
|
|
94
|
+
return id;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function clearTimer(id) {
|
|
98
|
+
const entry = timers.get(id);
|
|
99
|
+
if (!entry) return;
|
|
100
|
+
timers.delete(id);
|
|
101
|
+
if (entry.repeat) clearInterval(entry.timer);
|
|
102
|
+
else clearTimeout(entry.timer);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function clearAllTimers() {
|
|
106
|
+
for (const id of [...timers.keys()]) clearTimer(id);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function createContext() {
|
|
110
|
+
clearAllTimers();
|
|
111
|
+
const consoleProxy = nullObject({
|
|
112
|
+
log: hardenFunction((...args) => appendStdout(util.format(...args) + "\n")),
|
|
113
|
+
info: hardenFunction((...args) => appendStdout(util.format(...args) + "\n")),
|
|
114
|
+
debug: hardenFunction((...args) => appendStdout(util.format(...args) + "\n")),
|
|
115
|
+
warn: hardenFunction((...args) => appendStderr(util.format(...args) + "\n")),
|
|
116
|
+
error: hardenFunction((...args) => appendStderr(util.format(...args) + "\n")),
|
|
117
|
+
dir: hardenFunction((value, options) => appendStdout(util.inspect(value, options) + "\n")),
|
|
118
|
+
});
|
|
119
|
+
const browser = nullObject({
|
|
120
|
+
openTabs: hardenFunction(() => requestBrowser("open_tabs")),
|
|
121
|
+
use: hardenFunction((action, params = {}) => {
|
|
122
|
+
const input = action && typeof action === "object" ? action : { ...params, action };
|
|
123
|
+
return requestBrowser("use", input);
|
|
124
|
+
}),
|
|
125
|
+
});
|
|
126
|
+
const sandbox = Object.assign(Object.create(null), {
|
|
127
|
+
console: consoleProxy,
|
|
128
|
+
browser,
|
|
129
|
+
setTimeout: hardenFunction((callback, delay = 0, ...args) => createTimer(false, callback, delay, args)),
|
|
130
|
+
clearTimeout: hardenFunction((id) => clearTimer(id)),
|
|
131
|
+
setInterval: hardenFunction((callback, delay = 0, ...args) => createTimer(true, callback, delay, args)),
|
|
132
|
+
clearInterval: hardenFunction((id) => clearTimer(id)),
|
|
133
|
+
setImmediate: hardenFunction((callback, ...args) => createTimer(false, callback, 0, args)),
|
|
134
|
+
clearImmediate: hardenFunction((id) => clearTimer(id)),
|
|
135
|
+
queueMicrotask: hardenFunction((callback) => { Promise.resolve().then(callback); }),
|
|
136
|
+
});
|
|
137
|
+
context = vm.createContext(sandbox, {
|
|
138
|
+
name: "node_repl",
|
|
139
|
+
codeGeneration: { strings: false, wasm: false },
|
|
140
|
+
});
|
|
141
|
+
context.global = context;
|
|
142
|
+
context.globalThis = context;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
async function withTimeout(value, timeoutMs) {
|
|
146
|
+
if (!value || typeof value.then !== "function") return value;
|
|
147
|
+
let timer;
|
|
148
|
+
try {
|
|
149
|
+
return await Promise.race([
|
|
150
|
+
value,
|
|
151
|
+
new Promise((_, reject) => {
|
|
152
|
+
timer = setTimeout(() => reject(new Error("JavaScript execution timed out after " + timeoutMs + "ms")), timeoutMs);
|
|
153
|
+
}),
|
|
154
|
+
]);
|
|
155
|
+
} finally {
|
|
156
|
+
clearTimeout(timer);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Adapt Node REPL's top-level-await rewrite to the restricted vm context.
|
|
161
|
+
function isTopLevelDeclaration(state) {
|
|
162
|
+
return state.ancestors[state.ancestors.length - 2] === state.body;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
const noopVisitor = () => {};
|
|
166
|
+
const topLevelAwaitVisitorsWithoutAncestors = {
|
|
167
|
+
ClassDeclaration(node, state, c) {
|
|
168
|
+
if (isTopLevelDeclaration(state)) {
|
|
169
|
+
state.prepend(node, node.id.name + "=");
|
|
170
|
+
state.hoistedDeclarationStatements.push("let " + node.id.name + "; ");
|
|
171
|
+
}
|
|
172
|
+
walk.base.ClassDeclaration(node, state, c);
|
|
173
|
+
},
|
|
174
|
+
ForOfStatement(node, state, c) {
|
|
175
|
+
if (node.await === true) state.containsAwait = true;
|
|
176
|
+
walk.base.ForOfStatement(node, state, c);
|
|
177
|
+
},
|
|
178
|
+
FunctionDeclaration(node, state) {
|
|
179
|
+
state.prepend(node, "this." + node.id.name + " = " + node.id.name + "; ");
|
|
180
|
+
state.hoistedDeclarationStatements.push("var " + node.id.name + "; ");
|
|
181
|
+
},
|
|
182
|
+
FunctionExpression: noopVisitor,
|
|
183
|
+
ArrowFunctionExpression: noopVisitor,
|
|
184
|
+
MethodDefinition: noopVisitor,
|
|
185
|
+
AwaitExpression(node, state, c) {
|
|
186
|
+
state.containsAwait = true;
|
|
187
|
+
walk.base.AwaitExpression(node, state, c);
|
|
188
|
+
},
|
|
189
|
+
ReturnStatement(node, state, c) {
|
|
190
|
+
state.containsReturn = true;
|
|
191
|
+
walk.base.ReturnStatement(node, state, c);
|
|
192
|
+
},
|
|
193
|
+
VariableDeclaration(node, state, c) {
|
|
194
|
+
const variableKind = node.kind;
|
|
195
|
+
const parent = state.ancestors[state.ancestors.length - 2];
|
|
196
|
+
const isIterableForDeclaration = parent.type === "ForOfStatement" || parent.type === "ForInStatement";
|
|
197
|
+
if (variableKind === "var" || isTopLevelDeclaration(state)) {
|
|
198
|
+
state.replace(
|
|
199
|
+
node.start,
|
|
200
|
+
node.start + variableKind.length + (isIterableForDeclaration ? 1 : 0),
|
|
201
|
+
variableKind === "var" && isIterableForDeclaration ? "" : "void" + (node.declarations.length === 1 ? "" : " ("),
|
|
202
|
+
);
|
|
203
|
+
if (!isIterableForDeclaration) {
|
|
204
|
+
for (const declaration of node.declarations) {
|
|
205
|
+
state.prepend(declaration, "(");
|
|
206
|
+
state.append(declaration, declaration.init ? ")" : "=undefined)");
|
|
207
|
+
}
|
|
208
|
+
if (node.declarations.length !== 1) state.append(node.declarations[node.declarations.length - 1], ")");
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
const variableIdentifiersToHoist = { var: [], let: [] };
|
|
212
|
+
function registerVariableDeclarationIdentifiers(pattern) {
|
|
213
|
+
if (!pattern) return;
|
|
214
|
+
if (pattern.type === "Identifier") {
|
|
215
|
+
variableIdentifiersToHoist[variableKind === "var" ? "var" : "let"].push(pattern.name);
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
if (pattern.type === "ObjectPattern") {
|
|
219
|
+
for (const property of pattern.properties) registerVariableDeclarationIdentifiers(property.value || property.argument);
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
if (pattern.type === "ArrayPattern") {
|
|
223
|
+
for (const element of pattern.elements) registerVariableDeclarationIdentifiers(element);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
for (const declaration of node.declarations) registerVariableDeclarationIdentifiers(declaration.id);
|
|
227
|
+
for (const kind of ["var", "let"]) {
|
|
228
|
+
const identifiers = variableIdentifiersToHoist[kind];
|
|
229
|
+
if (identifiers.length > 0) state.hoistedDeclarationStatements.push(kind + " " + identifiers.join(", ") + "; ");
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
walk.base.VariableDeclaration(node, state, c);
|
|
233
|
+
},
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
const topLevelAwaitVisitors = {};
|
|
237
|
+
for (const nodeType of Object.keys(walk.base)) {
|
|
238
|
+
const callback = topLevelAwaitVisitorsWithoutAncestors[nodeType] || walk.base[nodeType];
|
|
239
|
+
topLevelAwaitVisitors[nodeType] = (node, state, c) => {
|
|
240
|
+
const isNew = node !== state.ancestors[state.ancestors.length - 1];
|
|
241
|
+
if (isNew) state.ancestors.push(node);
|
|
242
|
+
callback(node, state, c);
|
|
243
|
+
if (isNew) state.ancestors.pop();
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
function processTopLevelAwait(source) {
|
|
248
|
+
const wrapPrefix = "(async () => { ";
|
|
249
|
+
const wrapped = wrapPrefix + source + " })()";
|
|
250
|
+
const chars = wrapped.split("");
|
|
251
|
+
let root;
|
|
252
|
+
try {
|
|
253
|
+
root = Parser.parse(wrapped, { ecmaVersion: "latest" });
|
|
254
|
+
} catch {
|
|
255
|
+
return null;
|
|
256
|
+
}
|
|
257
|
+
const body = root.body[0].expression.callee.body;
|
|
258
|
+
const state = {
|
|
259
|
+
body,
|
|
260
|
+
ancestors: [],
|
|
261
|
+
hoistedDeclarationStatements: [],
|
|
262
|
+
containsAwait: false,
|
|
263
|
+
containsReturn: false,
|
|
264
|
+
replace(from, to, text) {
|
|
265
|
+
for (let index = from; index < to; index += 1) chars[index] = "";
|
|
266
|
+
if (from === to) text += chars[from];
|
|
267
|
+
chars[from] = text;
|
|
268
|
+
},
|
|
269
|
+
prepend(node, text) {
|
|
270
|
+
chars[node.start] = text + chars[node.start];
|
|
271
|
+
},
|
|
272
|
+
append(node, text) {
|
|
273
|
+
chars[node.end - 1] += text;
|
|
274
|
+
},
|
|
275
|
+
};
|
|
276
|
+
walk.recursive(body, state, topLevelAwaitVisitors);
|
|
277
|
+
if (!state.containsAwait || state.containsReturn) return null;
|
|
278
|
+
|
|
279
|
+
for (let index = body.body.length - 1; index >= 0; index -= 1) {
|
|
280
|
+
const node = body.body[index];
|
|
281
|
+
if (node.type === "EmptyStatement") continue;
|
|
282
|
+
if (node.type === "ExpressionStatement") {
|
|
283
|
+
state.prepend(node.expression, "{ value: (");
|
|
284
|
+
state.prepend(node, "return ");
|
|
285
|
+
state.append(node.expression, ") }");
|
|
286
|
+
}
|
|
287
|
+
break;
|
|
288
|
+
}
|
|
289
|
+
return state.hoistedDeclarationStatements.join("") + chars.join("");
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
async function execute(req) {
|
|
293
|
+
const output = { stdout: "", stderr: "" };
|
|
294
|
+
currentOutput = output;
|
|
295
|
+
try {
|
|
296
|
+
const timeoutMs = Number(req.timeoutMs || 30000);
|
|
297
|
+
const code = req.code || "";
|
|
298
|
+
let transformedTopLevelAwait = false;
|
|
299
|
+
let value;
|
|
300
|
+
try {
|
|
301
|
+
value = vm.runInContext(code, context, {
|
|
302
|
+
filename: "<node_repl>",
|
|
303
|
+
timeout: timeoutMs,
|
|
304
|
+
});
|
|
305
|
+
} catch (error) {
|
|
306
|
+
const transformed = error && error.name === "SyntaxError" ? processTopLevelAwait(code) : null;
|
|
307
|
+
if (!transformed) throw error;
|
|
308
|
+
transformedTopLevelAwait = true;
|
|
309
|
+
value = vm.runInContext(transformed, context, {
|
|
310
|
+
filename: "<node_repl>",
|
|
311
|
+
timeout: timeoutMs,
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
const settled = await withTimeout(value, timeoutMs);
|
|
315
|
+
const result = transformedTopLevelAwait && settled && Object.prototype.hasOwnProperty.call(settled, "value")
|
|
316
|
+
? settled.value
|
|
317
|
+
: settled;
|
|
318
|
+
return {
|
|
319
|
+
type: "response",
|
|
320
|
+
id: req.id,
|
|
321
|
+
status: "ok",
|
|
322
|
+
stdout: output.stdout,
|
|
323
|
+
stderr: output.stderr,
|
|
324
|
+
result: result === undefined ? null : summarize(result),
|
|
325
|
+
};
|
|
326
|
+
} catch (error) {
|
|
327
|
+
return {
|
|
328
|
+
type: "response",
|
|
329
|
+
id: req.id,
|
|
330
|
+
status: "error",
|
|
331
|
+
stdout: output.stdout,
|
|
332
|
+
stderr: output.stderr,
|
|
333
|
+
error: errorSummary(error),
|
|
334
|
+
};
|
|
335
|
+
} finally {
|
|
336
|
+
currentOutput = null;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
function reset(req) {
|
|
341
|
+
createContext();
|
|
342
|
+
return { type: "response", id: req.id, status: "ok", reset: true };
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
function handleBrowserResponse(req) {
|
|
346
|
+
const pending = pendingBrowserRequests.get(req.id);
|
|
347
|
+
if (!pending) return;
|
|
348
|
+
pendingBrowserRequests.delete(req.id);
|
|
349
|
+
if (req.error) {
|
|
350
|
+
const error = new Error(req.error.message || String(req.error));
|
|
351
|
+
error.name = req.error.name || "BrowserUseError";
|
|
352
|
+
pending.reject(error);
|
|
353
|
+
return;
|
|
354
|
+
}
|
|
355
|
+
const json = JSON.stringify(req.result === undefined ? null : req.result);
|
|
356
|
+
const contextValue = vm.runInContext("JSON.parse(" + JSON.stringify(json) + ")", context);
|
|
357
|
+
pending.resolve(contextValue);
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
function writeMessage(message) {
|
|
361
|
+
process.stdout.write(JSON.stringify(message) + "\n");
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
function handleRequest(req) {
|
|
365
|
+
if (req.type === "browser_response") {
|
|
366
|
+
handleBrowserResponse(req);
|
|
367
|
+
return;
|
|
368
|
+
}
|
|
369
|
+
if (req.type === "exec") {
|
|
370
|
+
void execute(req).then(writeMessage);
|
|
371
|
+
return;
|
|
372
|
+
}
|
|
373
|
+
if (req.type === "reset") {
|
|
374
|
+
writeMessage(reset(req));
|
|
375
|
+
return;
|
|
376
|
+
}
|
|
377
|
+
if (req.type === "shutdown") {
|
|
378
|
+
writeMessage({ type: "response", id: req.id, status: "ok", shutdown: true });
|
|
379
|
+
process.exit(0);
|
|
380
|
+
return;
|
|
381
|
+
}
|
|
382
|
+
writeMessage({ type: "response", id: req.id, status: "error", error: { name: "NodeReplProtocolError", message: "Unknown request type " + req.type } });
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
createContext();
|
|
386
|
+
writeMessage({ type: "ready", id: "ready", status: "ready" });
|
|
387
|
+
let buffer = "";
|
|
388
|
+
process.stdin.setEncoding("utf8");
|
|
389
|
+
process.stdin.on("data", (chunk) => {
|
|
390
|
+
buffer += chunk;
|
|
391
|
+
let index;
|
|
392
|
+
while ((index = buffer.indexOf("\n")) >= 0) {
|
|
393
|
+
const line = buffer.slice(0, index);
|
|
394
|
+
buffer = buffer.slice(index + 1);
|
|
395
|
+
if (!line.trim()) continue;
|
|
396
|
+
try {
|
|
397
|
+
handleRequest(JSON.parse(line));
|
|
398
|
+
} catch (error) {
|
|
399
|
+
writeMessage({ type: "response", status: "error", error: errorSummary(error) });
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
});
|
|
403
|
+
`;
|