@agimon-ai/doompi-computer-use 0.0.1-alpha.26 → 0.0.1-alpha.28

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.
Files changed (49) hide show
  1. package/README.md +9 -10
  2. package/dist/{computerUseMode-BgtaVx_z.cjs → computerUseMode-CHpbP7yo.cjs} +81 -2
  3. package/dist/computerUseMode-CHpbP7yo.cjs.map +1 -0
  4. package/dist/{computerUseMode-nb6yoF4Y.mjs → computerUseMode-DTXNRobA.mjs} +64 -3
  5. package/dist/computerUseMode-DTXNRobA.mjs.map +1 -0
  6. package/dist/{dependencies-CuOzd5Pm.cjs → dependencies-Dub2ybTN.cjs} +15 -3
  7. package/dist/dependencies-Dub2ybTN.cjs.map +1 -0
  8. package/dist/{dependencies-gtxIMe7d.mjs → dependencies-Y1TS7gGv.mjs} +9 -3
  9. package/dist/dependencies-Y1TS7gGv.mjs.map +1 -0
  10. package/dist/extensionService-BJXeNc4R.mjs +434 -0
  11. package/dist/extensionService-BJXeNc4R.mjs.map +1 -0
  12. package/dist/extensionService-CZS-zDP0.cjs +504 -0
  13. package/dist/extensionService-CZS-zDP0.cjs.map +1 -0
  14. package/dist/extensions/mcp.cjs +11 -8
  15. package/dist/extensions/mcp.cjs.map +1 -1
  16. package/dist/extensions/mcp.d.mts.map +1 -1
  17. package/dist/extensions/mcp.mjs +12 -9
  18. package/dist/extensions/mcp.mjs.map +1 -1
  19. package/dist/extensions/pi.cjs +23 -26
  20. package/dist/extensions/pi.cjs.map +1 -1
  21. package/dist/extensions/pi.d.mts +1 -1
  22. package/dist/extensions/pi.d.mts.map +1 -1
  23. package/dist/extensions/pi.mjs +23 -26
  24. package/dist/extensions/pi.mjs.map +1 -1
  25. package/dist/extensions/server.cjs +246 -82
  26. package/dist/extensions/server.cjs.map +1 -1
  27. package/dist/extensions/server.d.mts.map +1 -1
  28. package/dist/extensions/server.mjs +247 -83
  29. package/dist/extensions/server.mjs.map +1 -1
  30. package/dist/extensions/web.mjs +5 -2
  31. package/dist/extensions/web.mjs.map +1 -1
  32. package/dist/{index-CazCNSuR.d.mts → index-0S6V4EU9.d.mts} +116 -98
  33. package/dist/index-0S6V4EU9.d.mts.map +1 -0
  34. package/dist/index.cjs +3 -3
  35. package/dist/index.d.mts +2 -2
  36. package/dist/index.mjs +2 -2
  37. package/docs/computer-scripts.md +58 -23
  38. package/package.json +9 -8
  39. package/src/prompts/doompi-use-computer-use/SKILL.md +25 -11
  40. package/src/types/computerUse.ts +15 -1
  41. package/dist/computerUseMode-BgtaVx_z.cjs.map +0 -1
  42. package/dist/computerUseMode-nb6yoF4Y.mjs.map +0 -1
  43. package/dist/dependencies-CuOzd5Pm.cjs.map +0 -1
  44. package/dist/dependencies-gtxIMe7d.mjs.map +0 -1
  45. package/dist/extensionService-44mLS5b_.cjs +0 -275
  46. package/dist/extensionService-44mLS5b_.cjs.map +0 -1
  47. package/dist/extensionService-nFT_46iM.mjs +0 -206
  48. package/dist/extensionService-nFT_46iM.mjs.map +0 -1
  49. package/dist/index-CazCNSuR.d.mts.map +0 -1
@@ -0,0 +1,434 @@
1
+ import { createRequire } from "node:module";
2
+ import path from "node:path";
3
+ import { spawn } from "node:child_process";
4
+ import { realpath } from "node:fs/promises";
5
+ //#region src/constants/computerUse.ts
6
+ const COMPUTER_USE_GUIDANCE = `[COMPUTER USE ACTIVE]
7
+ Use computer_state before acting and after any action that may change the interface. Use only element refs and snapshot ids returned by computer_state. Use computer_action for one semantic press, focus, set_value, or scroll at a time. Use computer_exec only for a trusted, explicitly allowed local TypeScript script. Never infer coordinates, inspect another application, bypass secure elements, or retry an uncertain outcome. Stop computer use when the task is complete.`;
8
+ const COMMAND_NAME = "computer-use";
9
+ const COMMAND_DESCRIPTION = "Inspect or manage the session computer use mode";
10
+ const COMPUTER_USE_TOOL_NAMES = [
11
+ "computer_state",
12
+ "computer_action",
13
+ "computer_exec"
14
+ ];
15
+ //#endregion
16
+ //#region src/services/computerScriptWorker/index.ts
17
+ /** Source for an isolated child process. Restricted modules execute in QuickJS, not in Node's realm. */
18
+ const COMPUTER_SCRIPT_WORKER_SOURCE = String.raw`
19
+ import { readFileSync, realpathSync, statSync } from 'node:fs';
20
+ import path from 'node:path';
21
+ import { stripTypeScriptTypes } from 'node:module';
22
+ import { pathToFileURL } from 'node:url';
23
+
24
+ let nextRequestId = 0;
25
+ let started = false;
26
+ const pending = new Map();
27
+ const controller = new AbortController();
28
+ process.once('SIGTERM', () => controller.abort());
29
+ const send = (message) => {
30
+ if (process.connected) process.send(message, () => {});
31
+ };
32
+ const call = (operation, payload) => new Promise((resolve, reject) => {
33
+ if (controller.signal.aborted) return reject(new Error('Computer script was cancelled.'));
34
+ if (pending.size >= 64) return reject(new Error('Too many outstanding program operations.'));
35
+ const id = String(++nextRequestId);
36
+ pending.set(id, { resolve, reject });
37
+ send({ type: 'program', id, operation, payload });
38
+ });
39
+
40
+ async function restricted(message) {
41
+ const { getQuickJS } = await import(pathToFileURL(message.quickjsPath).href);
42
+ const QuickJS = await getQuickJS();
43
+ const runtime = QuickJS.newRuntime();
44
+ runtime.setMemoryLimit(32 * 1024 * 1024);
45
+ runtime.setMaxStackSize(512 * 1024);
46
+ const deadline = Date.now() + message.timeoutMs;
47
+ runtime.setInterruptHandler(() => controller.signal.aborted || Date.now() >= deadline);
48
+ const root = realpathSync(message.scriptRoot);
49
+ const sources = new Map();
50
+ let sourceBytes = 0;
51
+ let moduleFailure;
52
+ const modulePath = (candidate) => {
53
+ const filename = realpathSync(candidate);
54
+ const relative = path.relative(root, filename);
55
+ if (relative === '..' || relative.startsWith('..' + path.sep) || path.isAbsolute(relative)) {
56
+ throw new Error('Computer helper escapes the admitted script root.');
57
+ }
58
+ if (!/\.(ts|js|mjs)$/.test(filename)) throw new Error('Computer helpers must be JavaScript or erasable TypeScript.');
59
+ return filename;
60
+ };
61
+ const entry = modulePath(message.scriptPath);
62
+ runtime.setModuleLoader((filename) => {
63
+ // Preserve a rejected normalization even if the engine subsequently asks to load an empty name.
64
+ if (moduleFailure) throw moduleFailure;
65
+ if (sources.has(filename)) return sources.get(filename);
66
+ if (sources.size >= 32 || statSync(filename).size > 256 * 1024) throw new Error('Computer script module limit exceeded.');
67
+ const source = readFileSync(filename, 'utf8');
68
+ sourceBytes += Buffer.byteLength(source);
69
+ if (sourceBytes > 512 * 1024) throw new Error('Computer script source limit exceeded.');
70
+ const compiled = filename.endsWith('.ts') ? stripTypeScriptTypes(source, { mode: 'strip' }) : source;
71
+ sources.set(filename, compiled);
72
+ return compiled;
73
+ }, (base, name) => {
74
+ try {
75
+ if (name === '__entry__') return entry;
76
+ if (!name.startsWith('./') && !name.startsWith('../')) {
77
+ throw new Error('Restricted computer functions cannot import host or package modules.');
78
+ }
79
+ return modulePath(path.resolve(path.dirname(base), name));
80
+ } catch (error) {
81
+ moduleFailure = error;
82
+ throw error;
83
+ }
84
+ });
85
+ const vm = runtime.newContext();
86
+ let disposed = false;
87
+ const deferreds = new Set();
88
+ const pump = () => {
89
+ if (disposed) return;
90
+ const jobs = runtime.executePendingJobs();
91
+ if (jobs.error) {
92
+ const detail = vm.dump(jobs.error);
93
+ jobs.error.dispose();
94
+ throw new Error(detail?.message ?? String(detail));
95
+ }
96
+ };
97
+ const set = (name, value) => {
98
+ vm.setProp(vm.global, name, value);
99
+ value.dispose();
100
+ };
101
+ set('__input', vm.newString(JSON.stringify(message.input)));
102
+ set('__aborted', vm.newFunction('__aborted', () => controller.signal.aborted ? vm.true : vm.false));
103
+ set('__log', vm.newFunction('__log', (level, text) => {
104
+ send({ type: 'log', level: vm.getString(level), message: vm.getString(text) });
105
+ }));
106
+ set('__call', vm.newFunction('__call', (operationHandle, payloadHandle) => {
107
+ const operation = vm.getString(operationHandle);
108
+ const serialized = vm.getString(payloadHandle);
109
+ if (serialized.length > message.maxOutputBytes) throw new Error('Computer action exceeds the size limit.');
110
+ if (operation !== 'observe' && operation !== 'act') throw new Error('Unsupported program operation.');
111
+ const deferred = vm.newPromise();
112
+ deferreds.add(deferred);
113
+ call(operation, JSON.parse(serialized)).then((value) => {
114
+ if (disposed) return;
115
+ const handle = vm.newString(JSON.stringify(value));
116
+ deferred.resolve(handle);
117
+ handle.dispose();
118
+ }, (error) => {
119
+ if (disposed) return;
120
+ const handle = vm.newError(error.message);
121
+ deferred.reject(handle);
122
+ handle.dispose();
123
+ }).then(() => {
124
+ if (disposed) return;
125
+ deferred.dispose();
126
+ deferreds.delete(deferred);
127
+ pump();
128
+ }).catch((error) => send({ type: 'failed', error: error.message }));
129
+ return deferred.handle.dup();
130
+ }));
131
+ let evaluation;
132
+ try {
133
+ evaluation = vm.unwrapResult(vm.evalCode(
134
+ 'import { run } from "__entry__";\n' +
135
+ 'const invoke = __call; const log = __log; const isAborted = __aborted;\n' +
136
+ 'const program = Object.freeze({\n' +
137
+ ' observe: async (options = {}) => JSON.parse(await invoke("observe", JSON.stringify(options))),\n' +
138
+ ' act: async (action) => JSON.parse(await invoke("act", JSON.stringify(action)))\n' +
139
+ '});\n' +
140
+ 'const logger = Object.freeze(Object.fromEntries(["debug","info","warn","error"].map(level => [level, value => log(level, String(value))])));\n' +
141
+ 'const signal = Object.freeze({ get aborted() { return isAborted(); }, throwIfAborted() { if (isAborted()) throw new Error("Computer script was cancelled."); } });\n' +
142
+ 'const result = await run({ context: { program }, input: JSON.parse(__input), logger, signal });\n' +
143
+ 'globalThis.__result = result === undefined ? undefined : JSON.stringify(result);',
144
+ path.join(root, '__computer_entry__.mjs'), { type: 'module' },
145
+ ));
146
+ const completion = vm.resolvePromise(evaluation);
147
+ pump();
148
+ const completed = vm.unwrapResult(await completion);
149
+ completed.dispose();
150
+ const result = vm.getProp(vm.global, '__result');
151
+ const resultJson = vm.dump(result);
152
+ result.dispose();
153
+ return resultJson;
154
+ } finally {
155
+ disposed = true;
156
+ for (const deferred of deferreds) deferred.dispose();
157
+ evaluation?.dispose();
158
+ vm.dispose();
159
+ runtime.dispose();
160
+ }
161
+ }
162
+
163
+ process.on('message', async (message) => {
164
+ if (message?.type === 'response') {
165
+ const request = pending.get(message.id);
166
+ if (!request) return;
167
+ pending.delete(message.id);
168
+ if (message.error) request.reject(new Error(message.error));
169
+ else request.resolve(message.value);
170
+ return;
171
+ }
172
+ if (message?.type !== 'start' || started) return;
173
+ started = true;
174
+ try {
175
+ let resultJson;
176
+ if (message.trusted) {
177
+ const loaded = await import(pathToFileURL(message.scriptPath).href);
178
+ if (typeof loaded.run !== 'function') throw new Error('Computer script must export a named run function.');
179
+ const program = {
180
+ observe: (options = {}) => call('observe', options),
181
+ act: (action) => call('act', action),
182
+ };
183
+ const logger = Object.fromEntries(['debug','info','warn','error'].map(level => [level, value => {
184
+ send({ type: 'log', level, message: String(value) });
185
+ }]));
186
+ const result = await loaded.run({ context: { program }, input: message.input, logger, signal: controller.signal });
187
+ resultJson = result === undefined ? undefined : JSON.stringify(result);
188
+ } else {
189
+ resultJson = await restricted(message);
190
+ }
191
+ if (typeof resultJson === 'string' && Buffer.byteLength(resultJson) > message.maxOutputBytes) {
192
+ throw new Error('Computer script result exceeded the size limit.');
193
+ }
194
+ send({ type: 'complete', resultJson });
195
+ } catch (error) {
196
+ send({ type: 'failed', error: String(error?.message ?? error).slice(0, 1024) });
197
+ }
198
+ });
199
+ `;
200
+ //#endregion
201
+ //#region src/services/computerScriptRunner/index.ts
202
+ const DEFAULT_TIMEOUT_MS = 3e4;
203
+ const DEFAULT_MAX_OUTPUT_BYTES = 262144;
204
+ const MAX_IMAGE_BYTES = 6291456;
205
+ const MAX_PENDING_OPERATIONS = 64;
206
+ var ComputerScriptExecutionError = class extends Error {
207
+ completedActions;
208
+ outcomeUncertain;
209
+ constructor(message, completedActions, outcomeUncertain) {
210
+ super(message);
211
+ this.completedActions = completedActions;
212
+ this.outcomeUncertain = outcomeUncertain;
213
+ this.name = "ComputerScriptExecutionError";
214
+ }
215
+ };
216
+ var ComputerScriptRunner = class {
217
+ client;
218
+ allowedScriptPaths;
219
+ scriptRoot;
220
+ timeoutMs;
221
+ maxOutputBytes;
222
+ constructor(options) {
223
+ this.client = options.client;
224
+ this.allowedScriptPaths = options.allowedScriptPaths;
225
+ this.scriptRoot = options.scriptRoot;
226
+ this.timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
227
+ this.maxOutputBytes = options.maxOutputBytes ?? DEFAULT_MAX_OUTPUT_BYTES;
228
+ }
229
+ async execute(scriptPath, input, signal, options = {}) {
230
+ signal?.throwIfAborted();
231
+ const resolvedPath = await realpath(path.resolve(this.scriptRoot ?? process.cwd(), scriptPath));
232
+ const allowedPaths = await Promise.all(this.allowedScriptPaths.map(async (candidate) => realpath(candidate).catch(() => "")));
233
+ const trusted = options.trusted === true;
234
+ if ((trusted || this.scriptRoot === void 0) && !allowedPaths.includes(resolvedPath)) throw new Error("Computer script path is not explicitly allowed.");
235
+ if (!/\.(ts|js|mjs)$/u.test(resolvedPath)) throw new Error("Computer scripts must be JavaScript or erasable TypeScript files.");
236
+ const root = await realpath(this.scriptRoot ?? path.dirname(resolvedPath));
237
+ const relative = path.relative(root, resolvedPath);
238
+ if (!trusted && (relative === ".." || relative.startsWith(`..${path.sep}`) || path.isAbsolute(relative))) throw new Error("Computer script escapes the admitted script root.");
239
+ const serializedInput = JSON.stringify(input);
240
+ if (serializedInput === void 0) throw new Error("Computer script input must be JSON serializable.");
241
+ if (Buffer.byteLength(serializedInput) > this.maxOutputBytes) throw new Error("Computer script input exceeds the size limit.");
242
+ const quickjsPath = trusted ? void 0 : createRequire(import.meta.url).resolve("quickjs-emscripten");
243
+ signal?.throwIfAborted();
244
+ const started = performance.now();
245
+ return new Promise((resolve, reject) => {
246
+ const child = spawn(process.execPath, [
247
+ "--input-type=module",
248
+ "--eval",
249
+ COMPUTER_SCRIPT_WORKER_SOURCE
250
+ ], {
251
+ stdio: [
252
+ "ignore",
253
+ "pipe",
254
+ "pipe",
255
+ "ipc"
256
+ ],
257
+ env: trusted ? process.env : { ELECTRON_RUN_AS_NODE: "1" }
258
+ });
259
+ const controller = new AbortController();
260
+ const logs = [];
261
+ let outputBytes = 0;
262
+ let completedActions = 0;
263
+ let observations = 0;
264
+ let actionInFlight = false;
265
+ let settled = false;
266
+ let completing = false;
267
+ let outstanding = 0;
268
+ let operation = Promise.resolve();
269
+ const finish = (error, value) => {
270
+ if (settled) return;
271
+ settled = true;
272
+ clearTimeout(timeout);
273
+ signal?.removeEventListener("abort", onAbort);
274
+ controller.abort();
275
+ child.kill("SIGTERM");
276
+ setTimeout(() => child.kill("SIGKILL"), 250).unref();
277
+ if (error) reject(new ComputerScriptExecutionError(error.message, completedActions, actionInFlight));
278
+ else resolve(value);
279
+ };
280
+ const addOutput = (value) => {
281
+ outputBytes += Buffer.byteLength(value);
282
+ if (outputBytes <= this.maxOutputBytes) return true;
283
+ finish(/* @__PURE__ */ new Error("Computer script output exceeded the size limit."));
284
+ return false;
285
+ };
286
+ const send = (value) => {
287
+ if (settled || !child.connected) return;
288
+ child.send(value, (error) => {
289
+ if (error && !settled) finish(error);
290
+ });
291
+ };
292
+ const onAbort = () => finish(/* @__PURE__ */ new Error("Computer script execution was cancelled."));
293
+ const timeout = setTimeout(() => finish(/* @__PURE__ */ new Error("Computer script execution timed out.")), this.timeoutMs);
294
+ timeout.unref();
295
+ signal?.addEventListener("abort", onAbort, { once: true });
296
+ if (signal?.aborted) return onAbort();
297
+ child.stdout?.on("data", (chunk) => addOutput(chunk.toString("utf8")));
298
+ child.stderr?.on("data", (chunk) => addOutput(chunk.toString("utf8")));
299
+ child.on("error", (error) => finish(error));
300
+ child.on("exit", (code, exitSignal) => {
301
+ if (!settled) finish(/* @__PURE__ */ new Error(`Computer script worker exited before completion (${exitSignal ?? code ?? "unknown"}).`));
302
+ });
303
+ const observe = async (includeScreenshot) => {
304
+ const value = await this.client.observe(controller.signal, { includeScreenshot });
305
+ observations += 1;
306
+ const { screenshot, ...semantic } = value;
307
+ if (Buffer.byteLength(JSON.stringify(semantic)) > this.maxOutputBytes) throw new Error("Computer observation exceeds the size limit.");
308
+ if (includeScreenshot && screenshot) {
309
+ if (screenshot.mimeType !== "image/png" || screenshot.data.length > Math.ceil(MAX_IMAGE_BYTES / 3) * 4) throw new Error("Computer screenshot exceeds the image limit.");
310
+ return {
311
+ ...semantic,
312
+ screenshot
313
+ };
314
+ }
315
+ return semantic;
316
+ };
317
+ child.on("message", (raw) => {
318
+ if (settled) return;
319
+ if (!raw || typeof raw !== "object" || Buffer.byteLength(JSON.stringify(raw)) > this.maxOutputBytes + 4096) {
320
+ finish(/* @__PURE__ */ new Error("Computer worker message exceeds the size limit."));
321
+ return;
322
+ }
323
+ if (raw.type === "log" && typeof raw.message === "string") {
324
+ const line = `[${String(raw.level)}] ${raw.message}`;
325
+ if (addOutput(line)) logs.push(line);
326
+ return;
327
+ }
328
+ if (raw.type === "program") {
329
+ if (completing || typeof raw.id !== "string" || raw.id.length > 128 || raw.operation !== "observe" && raw.operation !== "act" || outstanding >= MAX_PENDING_OPERATIONS) {
330
+ finish(/* @__PURE__ */ new Error("Invalid or excessive computer program operations."));
331
+ return;
332
+ }
333
+ outstanding += 1;
334
+ operation = operation.then(async () => {
335
+ if (settled || controller.signal.aborted) return;
336
+ try {
337
+ let value;
338
+ if (raw.operation === "observe") {
339
+ const settings = raw.payload;
340
+ if (!settings || typeof settings !== "object" || Array.isArray(settings) || Object.keys(settings).some((key) => key !== "includeScreenshot") || "includeScreenshot" in settings && typeof settings.includeScreenshot !== "boolean") throw new Error("Invalid observation options.");
341
+ value = await observe("includeScreenshot" in settings && settings.includeScreenshot === true);
342
+ } else {
343
+ actionInFlight = true;
344
+ value = await this.client.act(raw.payload, controller.signal);
345
+ completedActions += 1;
346
+ actionInFlight = false;
347
+ }
348
+ send({
349
+ type: "response",
350
+ id: raw.id,
351
+ value
352
+ });
353
+ } catch (error) {
354
+ if (actionInFlight) finish(error instanceof Error ? error : new Error(String(error)));
355
+ else send({
356
+ type: "response",
357
+ id: raw.id,
358
+ error: error instanceof Error ? error.message : String(error)
359
+ });
360
+ } finally {
361
+ outstanding -= 1;
362
+ }
363
+ }).catch((error) => finish(error instanceof Error ? error : new Error(String(error))));
364
+ return;
365
+ }
366
+ if (raw.type === "failed" && typeof raw.error === "string") {
367
+ finish(new Error(raw.error));
368
+ return;
369
+ }
370
+ if (raw.type === "complete") {
371
+ if (completing) {
372
+ finish(/* @__PURE__ */ new Error("Computer worker completed twice."));
373
+ return;
374
+ }
375
+ completing = true;
376
+ operation = operation.then(async () => {
377
+ if (settled) return;
378
+ const resultJson = raw.resultJson;
379
+ if (resultJson !== void 0 && typeof resultJson !== "string") throw new Error("Computer script returned an invalid result.");
380
+ if (typeof resultJson === "string" && !addOutput(resultJson)) return;
381
+ const observation = await observe(options.includeScreenshot === true);
382
+ if (settled || !addOutput(JSON.stringify({
383
+ ...observation,
384
+ screenshot: void 0
385
+ }))) return;
386
+ finish(void 0, {
387
+ ...typeof resultJson === "string" ? { result: JSON.parse(resultJson) } : {},
388
+ observation,
389
+ logs,
390
+ metrics: {
391
+ actions: completedActions,
392
+ observations,
393
+ durationMs: Math.round(performance.now() - started),
394
+ outputBytes
395
+ }
396
+ });
397
+ }).catch((error) => finish(error instanceof Error ? error : new Error(String(error))));
398
+ }
399
+ });
400
+ send({
401
+ type: "start",
402
+ scriptPath: resolvedPath,
403
+ scriptRoot: root,
404
+ input: JSON.parse(serializedInput),
405
+ trusted,
406
+ quickjsPath,
407
+ timeoutMs: this.timeoutMs,
408
+ maxOutputBytes: this.maxOutputBytes
409
+ });
410
+ });
411
+ }
412
+ };
413
+ //#endregion
414
+ //#region src/services/extensionService/index.ts
415
+ var DefaultComputerUseExtensionService = class {
416
+ client;
417
+ constructor(client) {
418
+ this.client = client;
419
+ }
420
+ async execute() {
421
+ if (this.client === void 0) return {
422
+ message: "Computer use requires a DoomPi Desktop session.",
423
+ level: "error"
424
+ };
425
+ return {
426
+ message: `Computer use is ${(await this.client.state()).phase.replaceAll("_", " ")}.`,
427
+ level: "info"
428
+ };
429
+ }
430
+ };
431
+ //#endregion
432
+ export { COMMAND_NAME as a, COMMAND_DESCRIPTION as i, ComputerScriptExecutionError as n, COMPUTER_USE_GUIDANCE as o, ComputerScriptRunner as r, COMPUTER_USE_TOOL_NAMES as s, DefaultComputerUseExtensionService as t };
433
+
434
+ //# sourceMappingURL=extensionService-BJXeNc4R.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extensionService-BJXeNc4R.mjs","names":[],"sources":["../src/constants/computerUse.ts","../src/services/computerScriptWorker/index.ts","../src/services/computerScriptRunner/index.ts","../src/services/extensionService/index.ts"],"sourcesContent":["export const COMPUTER_USE_GUIDANCE = `[COMPUTER USE ACTIVE]\nUse computer_state before acting and after any action that may change the interface. Use only element refs and snapshot ids returned by computer_state. Use computer_action for one semantic press, focus, set_value, or scroll at a time. Use computer_exec only for a trusted, explicitly allowed local TypeScript script. Never infer coordinates, inspect another application, bypass secure elements, or retry an uncertain outcome. Stop computer use when the task is complete.`;\nexport const COMMAND_NAME = 'computer-use';\nexport const COMMAND_DESCRIPTION = 'Inspect or manage the session computer use mode';\n\nexport const COMPUTER_USE_TOOL_NAMES = ['computer_state', 'computer_action', 'computer_exec'] as const;\n","/** Source for an isolated child process. Restricted modules execute in QuickJS, not in Node's realm. */\nexport const COMPUTER_SCRIPT_WORKER_SOURCE = String.raw`\nimport { readFileSync, realpathSync, statSync } from 'node:fs';\nimport path from 'node:path';\nimport { stripTypeScriptTypes } from 'node:module';\nimport { pathToFileURL } from 'node:url';\n\nlet nextRequestId = 0;\nlet started = false;\nconst pending = new Map();\nconst controller = new AbortController();\nprocess.once('SIGTERM', () => controller.abort());\nconst send = (message) => {\n if (process.connected) process.send(message, () => {});\n};\nconst call = (operation, payload) => new Promise((resolve, reject) => {\n if (controller.signal.aborted) return reject(new Error('Computer script was cancelled.'));\n if (pending.size >= 64) return reject(new Error('Too many outstanding program operations.'));\n const id = String(++nextRequestId);\n pending.set(id, { resolve, reject });\n send({ type: 'program', id, operation, payload });\n});\n\nasync function restricted(message) {\n const { getQuickJS } = await import(pathToFileURL(message.quickjsPath).href);\n const QuickJS = await getQuickJS();\n const runtime = QuickJS.newRuntime();\n runtime.setMemoryLimit(32 * 1024 * 1024);\n runtime.setMaxStackSize(512 * 1024);\n const deadline = Date.now() + message.timeoutMs;\n runtime.setInterruptHandler(() => controller.signal.aborted || Date.now() >= deadline);\n const root = realpathSync(message.scriptRoot);\n const sources = new Map();\n let sourceBytes = 0;\n let moduleFailure;\n const modulePath = (candidate) => {\n const filename = realpathSync(candidate);\n const relative = path.relative(root, filename);\n if (relative === '..' || relative.startsWith('..' + path.sep) || path.isAbsolute(relative)) {\n throw new Error('Computer helper escapes the admitted script root.');\n }\n if (!/\\.(ts|js|mjs)$/.test(filename)) throw new Error('Computer helpers must be JavaScript or erasable TypeScript.');\n return filename;\n };\n const entry = modulePath(message.scriptPath);\n runtime.setModuleLoader((filename) => {\n // Preserve a rejected normalization even if the engine subsequently asks to load an empty name.\n if (moduleFailure) throw moduleFailure;\n if (sources.has(filename)) return sources.get(filename);\n if (sources.size >= 32 || statSync(filename).size > 256 * 1024) throw new Error('Computer script module limit exceeded.');\n const source = readFileSync(filename, 'utf8');\n sourceBytes += Buffer.byteLength(source);\n if (sourceBytes > 512 * 1024) throw new Error('Computer script source limit exceeded.');\n const compiled = filename.endsWith('.ts') ? stripTypeScriptTypes(source, { mode: 'strip' }) : source;\n sources.set(filename, compiled);\n return compiled;\n }, (base, name) => {\n try {\n if (name === '__entry__') return entry;\n if (!name.startsWith('./') && !name.startsWith('../')) {\n throw new Error('Restricted computer functions cannot import host or package modules.');\n }\n return modulePath(path.resolve(path.dirname(base), name));\n } catch (error) {\n moduleFailure = error;\n throw error;\n }\n });\n const vm = runtime.newContext();\n let disposed = false;\n const deferreds = new Set();\n const pump = () => {\n if (disposed) return;\n const jobs = runtime.executePendingJobs();\n if (jobs.error) {\n const detail = vm.dump(jobs.error);\n jobs.error.dispose();\n throw new Error(detail?.message ?? String(detail));\n }\n };\n const set = (name, value) => {\n vm.setProp(vm.global, name, value);\n value.dispose();\n };\n set('__input', vm.newString(JSON.stringify(message.input)));\n set('__aborted', vm.newFunction('__aborted', () => controller.signal.aborted ? vm.true : vm.false));\n set('__log', vm.newFunction('__log', (level, text) => {\n send({ type: 'log', level: vm.getString(level), message: vm.getString(text) });\n }));\n set('__call', vm.newFunction('__call', (operationHandle, payloadHandle) => {\n const operation = vm.getString(operationHandle);\n const serialized = vm.getString(payloadHandle);\n if (serialized.length > message.maxOutputBytes) throw new Error('Computer action exceeds the size limit.');\n if (operation !== 'observe' && operation !== 'act') throw new Error('Unsupported program operation.');\n const deferred = vm.newPromise();\n deferreds.add(deferred);\n call(operation, JSON.parse(serialized)).then((value) => {\n if (disposed) return;\n const handle = vm.newString(JSON.stringify(value));\n deferred.resolve(handle);\n handle.dispose();\n }, (error) => {\n if (disposed) return;\n const handle = vm.newError(error.message);\n deferred.reject(handle);\n handle.dispose();\n }).then(() => {\n if (disposed) return;\n deferred.dispose();\n deferreds.delete(deferred);\n pump();\n }).catch((error) => send({ type: 'failed', error: error.message }));\n return deferred.handle.dup();\n }));\n let evaluation;\n try {\n evaluation = vm.unwrapResult(vm.evalCode(\n 'import { run } from \"__entry__\";\\n' +\n 'const invoke = __call; const log = __log; const isAborted = __aborted;\\n' +\n 'const program = Object.freeze({\\n' +\n ' observe: async (options = {}) => JSON.parse(await invoke(\"observe\", JSON.stringify(options))),\\n' +\n ' act: async (action) => JSON.parse(await invoke(\"act\", JSON.stringify(action)))\\n' +\n '});\\n' +\n 'const logger = Object.freeze(Object.fromEntries([\"debug\",\"info\",\"warn\",\"error\"].map(level => [level, value => log(level, String(value))])));\\n' +\n 'const signal = Object.freeze({ get aborted() { return isAborted(); }, throwIfAborted() { if (isAborted()) throw new Error(\"Computer script was cancelled.\"); } });\\n' +\n 'const result = await run({ context: { program }, input: JSON.parse(__input), logger, signal });\\n' +\n 'globalThis.__result = result === undefined ? undefined : JSON.stringify(result);',\n path.join(root, '__computer_entry__.mjs'), { type: 'module' },\n ));\n const completion = vm.resolvePromise(evaluation);\n pump();\n const completed = vm.unwrapResult(await completion);\n completed.dispose();\n const result = vm.getProp(vm.global, '__result');\n const resultJson = vm.dump(result);\n result.dispose();\n return resultJson;\n } finally {\n disposed = true;\n for (const deferred of deferreds) deferred.dispose();\n evaluation?.dispose();\n vm.dispose();\n runtime.dispose();\n }\n}\n\nprocess.on('message', async (message) => {\n if (message?.type === 'response') {\n const request = pending.get(message.id);\n if (!request) return;\n pending.delete(message.id);\n if (message.error) request.reject(new Error(message.error));\n else request.resolve(message.value);\n return;\n }\n if (message?.type !== 'start' || started) return;\n started = true;\n try {\n let resultJson;\n if (message.trusted) {\n const loaded = await import(pathToFileURL(message.scriptPath).href);\n if (typeof loaded.run !== 'function') throw new Error('Computer script must export a named run function.');\n const program = {\n observe: (options = {}) => call('observe', options),\n act: (action) => call('act', action),\n };\n const logger = Object.fromEntries(['debug','info','warn','error'].map(level => [level, value => {\n send({ type: 'log', level, message: String(value) });\n }]));\n const result = await loaded.run({ context: { program }, input: message.input, logger, signal: controller.signal });\n resultJson = result === undefined ? undefined : JSON.stringify(result);\n } else {\n resultJson = await restricted(message);\n }\n if (typeof resultJson === 'string' && Buffer.byteLength(resultJson) > message.maxOutputBytes) {\n throw new Error('Computer script result exceeded the size limit.');\n }\n send({ type: 'complete', resultJson });\n } catch (error) {\n send({ type: 'failed', error: String(error?.message ?? error).slice(0, 1024) });\n }\n});\n`;\n","import { spawn } from 'node:child_process';\nimport { realpath } from 'node:fs/promises';\nimport { createRequire } from 'node:module';\nimport path from 'node:path';\n\nimport type {\n ComputerScriptExecutionOptions,\n ComputerScriptExecutionResult,\n ComputerScriptRunnerOptions,\n} from '../../types/computerScript';\nimport type { ComputerUseAction, ComputerUseObservation, ComputerUseSessionClient } from '../../types/computerUse';\nimport { COMPUTER_SCRIPT_WORKER_SOURCE } from '../computerScriptWorker';\n\nconst DEFAULT_TIMEOUT_MS = 30_000;\nconst DEFAULT_MAX_OUTPUT_BYTES = 256 * 1024;\nconst MAX_IMAGE_BYTES = 6 * 1024 * 1024;\nconst MAX_PENDING_OPERATIONS = 64;\n\nexport class ComputerScriptExecutionError extends Error {\n constructor(\n message: string,\n readonly completedActions: number,\n readonly outcomeUncertain: boolean,\n ) {\n super(message);\n this.name = 'ComputerScriptExecutionError';\n }\n}\n\ninterface WorkerMessage {\n readonly type?: unknown;\n readonly id?: unknown;\n readonly operation?: unknown;\n readonly payload?: unknown;\n readonly level?: unknown;\n readonly message?: unknown;\n readonly resultJson?: unknown;\n readonly error?: unknown;\n}\n\nexport class ComputerScriptRunner {\n private readonly client: ComputerUseSessionClient;\n private readonly allowedScriptPaths: readonly string[];\n private readonly scriptRoot?: string;\n private readonly timeoutMs: number;\n private readonly maxOutputBytes: number;\n\n constructor(options: ComputerScriptRunnerOptions) {\n this.client = options.client;\n this.allowedScriptPaths = options.allowedScriptPaths;\n this.scriptRoot = options.scriptRoot;\n this.timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n this.maxOutputBytes = options.maxOutputBytes ?? DEFAULT_MAX_OUTPUT_BYTES;\n }\n\n async execute(\n scriptPath: string,\n input: unknown,\n signal?: AbortSignal,\n options: ComputerScriptExecutionOptions = {},\n ): Promise<ComputerScriptExecutionResult> {\n signal?.throwIfAborted();\n const resolvedPath = await realpath(path.resolve(this.scriptRoot ?? process.cwd(), scriptPath));\n const allowedPaths = await Promise.all(\n this.allowedScriptPaths.map(async (candidate) => realpath(candidate).catch(() => '')),\n );\n const trusted = options.trusted === true;\n if ((trusted || this.scriptRoot === undefined) && !allowedPaths.includes(resolvedPath)) {\n throw new Error('Computer script path is not explicitly allowed.');\n }\n if (!/\\.(ts|js|mjs)$/u.test(resolvedPath))\n throw new Error('Computer scripts must be JavaScript or erasable TypeScript files.');\n const root = await realpath(this.scriptRoot ?? path.dirname(resolvedPath));\n const relative = path.relative(root, resolvedPath);\n if (!trusted && (relative === '..' || relative.startsWith(`..${path.sep}`) || path.isAbsolute(relative))) {\n throw new Error('Computer script escapes the admitted script root.');\n }\n const serializedInput = JSON.stringify(input);\n if (serializedInput === undefined) throw new Error('Computer script input must be JSON serializable.');\n if (Buffer.byteLength(serializedInput) > this.maxOutputBytes)\n throw new Error('Computer script input exceeds the size limit.');\n const quickjsPath = trusted ? undefined : createRequire(import.meta.url).resolve('quickjs-emscripten');\n signal?.throwIfAborted();\n const started = performance.now();\n\n return new Promise((resolve, reject) => {\n const child = spawn(process.execPath, ['--input-type=module', '--eval', COMPUTER_SCRIPT_WORKER_SOURCE], {\n stdio: ['ignore', 'pipe', 'pipe', 'ipc'],\n // Preserve Electron's Node mode, but no host credentials, for restricted workers.\n env: trusted ? process.env : { ELECTRON_RUN_AS_NODE: '1' },\n });\n const controller = new AbortController();\n const logs: string[] = [];\n let outputBytes = 0;\n let completedActions = 0;\n let observations = 0;\n let actionInFlight = false;\n let settled = false;\n let completing = false;\n let outstanding = 0;\n let operation: Promise<void> = Promise.resolve();\n const finish = (error?: Error, value?: ComputerScriptExecutionResult): void => {\n if (settled) return;\n settled = true;\n clearTimeout(timeout);\n signal?.removeEventListener('abort', onAbort);\n controller.abort();\n child.kill('SIGTERM');\n const killTimer = setTimeout(() => child.kill('SIGKILL'), 250);\n killTimer.unref();\n if (error) reject(new ComputerScriptExecutionError(error.message, completedActions, actionInFlight));\n else resolve(value!);\n };\n const addOutput = (value: string): boolean => {\n outputBytes += Buffer.byteLength(value);\n if (outputBytes <= this.maxOutputBytes) return true;\n finish(new Error('Computer script output exceeded the size limit.'));\n return false;\n };\n const send = (value: object): void => {\n if (settled || !child.connected) return;\n child.send(value, (error) => {\n if (error && !settled) finish(error);\n });\n };\n const onAbort = (): void => finish(new Error('Computer script execution was cancelled.'));\n const timeout = setTimeout(() => finish(new Error('Computer script execution timed out.')), this.timeoutMs);\n timeout.unref();\n signal?.addEventListener('abort', onAbort, { once: true });\n if (signal?.aborted) return onAbort();\n child.stdout?.on('data', (chunk: Buffer) => addOutput(chunk.toString('utf8')));\n child.stderr?.on('data', (chunk: Buffer) => addOutput(chunk.toString('utf8')));\n child.on('error', (error) => finish(error));\n child.on('exit', (code, exitSignal) => {\n if (!settled)\n finish(new Error(`Computer script worker exited before completion (${exitSignal ?? code ?? 'unknown'}).`));\n });\n\n const observe = async (includeScreenshot: boolean): Promise<ComputerUseObservation> => {\n const value = await this.client.observe(controller.signal, { includeScreenshot });\n observations += 1;\n const { screenshot, ...semantic } = value;\n if (Buffer.byteLength(JSON.stringify(semantic)) > this.maxOutputBytes)\n throw new Error('Computer observation exceeds the size limit.');\n if (includeScreenshot && screenshot) {\n if (screenshot.mimeType !== 'image/png' || screenshot.data.length > Math.ceil(MAX_IMAGE_BYTES / 3) * 4) {\n throw new Error('Computer screenshot exceeds the image limit.');\n }\n return { ...semantic, screenshot };\n }\n return semantic;\n };\n\n child.on('message', (raw: WorkerMessage) => {\n if (settled) return;\n if (!raw || typeof raw !== 'object' || Buffer.byteLength(JSON.stringify(raw)) > this.maxOutputBytes + 4096) {\n finish(new Error('Computer worker message exceeds the size limit.'));\n return;\n }\n if (raw.type === 'log' && typeof raw.message === 'string') {\n const line = `[${String(raw.level)}] ${raw.message}`;\n if (addOutput(line)) logs.push(line);\n return;\n }\n if (raw.type === 'program') {\n if (\n completing ||\n typeof raw.id !== 'string' ||\n raw.id.length > 128 ||\n (raw.operation !== 'observe' && raw.operation !== 'act') ||\n outstanding >= MAX_PENDING_OPERATIONS\n ) {\n finish(new Error('Invalid or excessive computer program operations.'));\n return;\n }\n outstanding += 1;\n operation = operation\n .then(async () => {\n if (settled || controller.signal.aborted) return;\n try {\n let value: unknown;\n if (raw.operation === 'observe') {\n const settings = raw.payload;\n if (\n !settings ||\n typeof settings !== 'object' ||\n Array.isArray(settings) ||\n Object.keys(settings).some((key) => key !== 'includeScreenshot') ||\n ('includeScreenshot' in settings && typeof settings.includeScreenshot !== 'boolean')\n ) {\n throw new Error('Invalid observation options.');\n }\n value = await observe('includeScreenshot' in settings && settings.includeScreenshot === true);\n } else {\n actionInFlight = true;\n value = await this.client.act(raw.payload as ComputerUseAction, controller.signal);\n completedActions += 1;\n actionInFlight = false;\n }\n send({ type: 'response', id: raw.id, value });\n } catch (error) {\n // An action can have taken effect before its transport failed. Never run the remaining chain.\n if (actionInFlight) finish(error instanceof Error ? error : new Error(String(error)));\n else\n send({ type: 'response', id: raw.id, error: error instanceof Error ? error.message : String(error) });\n } finally {\n outstanding -= 1;\n }\n })\n .catch((error: unknown) => finish(error instanceof Error ? error : new Error(String(error))));\n return;\n }\n if (raw.type === 'failed' && typeof raw.error === 'string') {\n finish(new Error(raw.error));\n return;\n }\n if (raw.type === 'complete') {\n if (completing) {\n finish(new Error('Computer worker completed twice.'));\n return;\n }\n completing = true;\n operation = operation\n .then(async () => {\n if (settled) return;\n const resultJson = raw.resultJson;\n if (resultJson !== undefined && typeof resultJson !== 'string')\n throw new Error('Computer script returned an invalid result.');\n if (typeof resultJson === 'string' && !addOutput(resultJson)) return;\n const observation = await observe(options.includeScreenshot === true);\n if (settled || !addOutput(JSON.stringify({ ...observation, screenshot: undefined }))) return;\n finish(undefined, {\n ...(typeof resultJson === 'string' ? { result: JSON.parse(resultJson) as unknown } : {}),\n observation,\n logs,\n metrics: {\n actions: completedActions,\n observations,\n durationMs: Math.round(performance.now() - started),\n outputBytes,\n },\n });\n })\n .catch((error: unknown) => finish(error instanceof Error ? error : new Error(String(error))));\n }\n });\n send({\n type: 'start',\n scriptPath: resolvedPath,\n scriptRoot: root,\n input: JSON.parse(serializedInput) as unknown,\n trusted,\n quickjsPath,\n timeoutMs: this.timeoutMs,\n maxOutputBytes: this.maxOutputBytes,\n });\n });\n }\n}\n","import type { ComputerUseExtensionResult, ComputerUseExtensionService } from '../../types/extension';\nimport type { ComputerUseSessionClient } from '../sessionApiClient';\n\nexport class DefaultComputerUseExtensionService implements ComputerUseExtensionService {\n public constructor(private readonly client?: ComputerUseSessionClient) {}\n\n public async execute(): Promise<ComputerUseExtensionResult> {\n if (this.client === undefined)\n return { message: 'Computer use requires a DoomPi Desktop session.', level: 'error' };\n const state = await this.client.state();\n return { message: `Computer use is ${state.phase.replaceAll('_', ' ')}.`, level: 'info' };\n }\n}\n"],"mappings":"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"}