@agimon-ai/doompi-computer-use 0.0.1-alpha.49 → 0.0.1-alpha.51

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.
@@ -3,13 +3,14 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_extensionService = require("../extensionService-CIDyPyzP.cjs");
6
- const require_computerUseMode = require("../computerUseMode-KnoOWve4.cjs");
6
+ const require_computerUseMode = require("../computerUseMode-C1Cj1ZlK.cjs");
7
7
  let node_path = require("node:path");
8
8
  node_path = require_extensionService.__toESM(node_path, 1);
9
9
  let _agimon_ai_doompi_core_extensionFile = require("@agimon-ai/doompi-core/extensionFile");
10
10
  let _agimon_ai_doompi_minor_mode = require("@agimon-ai/doompi-minor-mode");
11
11
  let _agimon_ai_doompi_core_serverFacet = require("@agimon-ai/doompi-core/serverFacet");
12
12
  let node_crypto = require("node:crypto");
13
+ let _agimon_ai_doompi_core_packageApi = require("@agimon-ai/doompi-core/packageApi");
13
14
  let _agimon_ai_doompi_core_web = require("@agimon-ai/doompi-core/web");
14
15
  //#region src/services/mcpTools/index.ts
15
16
  const COMPUTER_USE_MCP_TOOLS_SERVICE = "doom/computer-use-mcp-tools";
@@ -38,12 +39,28 @@ function mountMcpTools(tools) {
38
39
  * disagreement this file exists to prevent. The dispatcher now reads this
39
40
  * table, so the page, the broker and the hub all resolve one set of strings.
40
41
  *
41
- * Only `activate` is reachable from a browser. The `/agent/` and `/hub/` routes
42
+ * Activation, status, cancellation and recording reads are reachable from a browser. The `/agent/` and `/hub/` routes
42
43
  * each demand a host-issued bearer token and answer 404 without one; they are
43
44
  * declared here because they are this API's surface, not because a page calls
44
45
  * them.
45
46
  */
46
47
  var apiRoutes_default = (0, _agimon_ai_doompi_core_web.defineApiRoutes)({
48
+ artifact: {
49
+ method: "GET",
50
+ path: require_computerUseMode.COMPUTER_USE_ROUTES.artifact,
51
+ query: ["artifactId", "offset"],
52
+ raw: true
53
+ },
54
+ activationState: {
55
+ method: "GET",
56
+ path: require_computerUseMode.COMPUTER_USE_ROUTES.activate,
57
+ response: (0, _agimon_ai_doompi_core_web.apiResponse)()
58
+ },
59
+ cancelActivation: {
60
+ method: "DELETE",
61
+ path: require_computerUseMode.COMPUTER_USE_ROUTES.activate,
62
+ response: (0, _agimon_ai_doompi_core_web.apiResponse)()
63
+ },
47
64
  activate: {
48
65
  method: "POST",
49
66
  path: require_computerUseMode.COMPUTER_USE_ROUTES.activate,
@@ -159,6 +176,7 @@ function artifactView(value) {
159
176
  return {
160
177
  artifactId: input.artifactId,
161
178
  status: input.status,
179
+ ...typeof input.sizeBytes === "number" && Number.isSafeInteger(input.sizeBytes) && input.sizeBytes > 0 ? { sizeBytes: input.sizeBytes } : {},
162
180
  ...downloadUrl === void 0 ? {} : { downloadUrl },
163
181
  ...previewUrl === void 0 ? {} : { previewUrl },
164
182
  ...typeof input.actionCount === "number" ? { actionCount: input.actionCount } : {},
@@ -279,9 +297,10 @@ var ComputerUseRequestBroker = class ComputerUseRequestBroker {
279
297
  return token !== void 0 && request.headers.get("authorization") === `Bearer ${token}`;
280
298
  }
281
299
  async requestActivation(request) {
282
- if (!this.desktop?.available || !this.desktop.authorize(request.headers)) return jsonError("Not found.", 404);
300
+ if (!this.desktop?.available || !(this.desktop.authorizeActivation?.(request.headers) ?? this.desktop.authorize(request.headers))) return jsonError("Not found.", 404);
283
301
  if (this.desktop.enabled === false) return jsonError("Enable computer use in global Desktop settings first.", 409);
284
- const caller = {
302
+ const stamped = (0, _agimon_ai_doompi_core_packageApi.doomApiCallerFrom)(request.headers);
303
+ const caller = stamped?.locality === "remote" ? stamped : {
285
304
  locality: "local",
286
305
  stepUp: "not-required"
287
306
  };
@@ -289,10 +308,10 @@ var ComputerUseRequestBroker = class ComputerUseRequestBroker {
289
308
  const input = await body(request);
290
309
  const target = record$1(input.target);
291
310
  const durationMs = input.durationMs;
292
- if (target === void 0 || typeof target.windowId !== "string" || typeof target.bundleId !== "string") return jsonError("A Desktop target is required.", 400);
311
+ if (target === void 0 && (input.target !== void 0 || caller.locality !== "remote") || target !== void 0 && (typeof target.windowId !== "string" || typeof target.bundleId !== "string")) return jsonError("A Desktop target is required, or a remote request must leave selection to the Mac.", 400);
293
312
  if (typeof durationMs !== "number" || !Number.isInteger(durationMs) || durationMs < 1e3 || durationMs > 18e5) return jsonError("The requested duration is invalid.", 400);
294
- this.desktop.claim();
295
313
  try {
314
+ this.desktop.claim(request.headers);
296
315
  await this.beforeActivate?.();
297
316
  } catch (error) {
298
317
  return jsonError(error instanceof Error ? error.message : String(error), 409);
@@ -301,7 +320,7 @@ var ComputerUseRequestBroker = class ComputerUseRequestBroker {
301
320
  const createdAt = Date.now();
302
321
  this.activation = Object.freeze({
303
322
  requestId: (0, node_crypto.randomUUID)(),
304
- target: Object.freeze({ ...target }),
323
+ ...target === void 0 ? {} : { target: Object.freeze({ ...target }) },
305
324
  durationSeconds: durationMs / 1e3,
306
325
  createdAt,
307
326
  confirmationExpiresAt: createdAt + require_computerUseMode.COMPUTER_USE_CONFIRMATION_WINDOW_MS,
@@ -363,7 +382,28 @@ var ComputerUseRequestBroker = class ComputerUseRequestBroker {
363
382
  }
364
383
  async fetch(request) {
365
384
  if (this.closed) return jsonError("Computer-use broker is closed.", 503);
366
- const path = new URL(request.url).pathname;
385
+ const url = new URL(request.url);
386
+ const path = url.pathname;
387
+ if (request.method === "GET" && path === apiRoutes_default.artifact.path) {
388
+ if (!(this.desktop?.authorizeRecording?.(request.headers) ?? this.desktop?.authorize(request.headers)) || !this.desktop?.fetchRecording) return jsonError("Not found.", 404);
389
+ const artifactId = url.searchParams.get("artifactId") ?? "";
390
+ const offsetText = url.searchParams.get("offset") ?? "";
391
+ const offset = Number(offsetText);
392
+ if (!/^[0-9]+$/u.test(offsetText) || !Number.isSafeInteger(offset) || offset < 0 || offset > 134217728) return jsonError("Invalid recording offset.", 400);
393
+ return this.desktop.fetchRecording(artifactId, `bytes=${offset}-${offset + 1048576 - 1}`);
394
+ }
395
+ if (path === apiRoutes_default.activate.path && request.method === "GET") {
396
+ if (!this.desktop?.authorizePending?.(request.headers) && !(this.desktop?.authorizeRecording?.(request.headers) ?? this.desktop?.authorize(request.headers))) return jsonError("Not found.", 404);
397
+ return Response.json(this.state());
398
+ }
399
+ if (path === apiRoutes_default.activate.path && request.method === "DELETE") {
400
+ if (!this.desktop?.authorizePending?.(request.headers)) return jsonError("Not found.", 404);
401
+ if (this.phase !== "awaiting_confirmation" && this.phase !== "activating") return jsonError("No activation is pending.", 409);
402
+ this.phase = "stopping";
403
+ this.rejectPending("The activation was cancelled.");
404
+ this.changed();
405
+ return Response.json(this.state(), { status: 202 });
406
+ }
367
407
  if (request.method === "POST" && path === apiRoutes_default.activate.path) return this.requestActivation(request);
368
408
  const agent = path.startsWith("/agent/");
369
409
  const hub = path.startsWith("/hub/");
@@ -420,6 +460,11 @@ var ComputerUseRequestBroker = class ComputerUseRequestBroker {
420
460
  } else {
421
461
  const host = record$1(input.host);
422
462
  if (typeof host?.grantId !== "string" || !Number.isFinite(host.expiresAt) || host.expiresAt <= Date.now()) return jsonError("Desktop did not issue a complete grant.", 502);
463
+ const selectedTarget = record$1(host.target);
464
+ if (this.activation !== void 0 && selectedTarget !== void 0) this.activation = Object.freeze({
465
+ ...this.activation,
466
+ target: Object.freeze({ ...selectedTarget })
467
+ });
423
468
  this.grantId = host.grantId;
424
469
  this.expiresAt = host.expiresAt;
425
470
  this.actionSequence = 0;
@@ -440,7 +485,7 @@ var ComputerUseRequestBroker = class ComputerUseRequestBroker {
440
485
  this.grantId = void 0;
441
486
  this.expiresAt = void 0;
442
487
  this.activation = void 0;
443
- this.artifact = artifactView(input.artifact);
488
+ this.artifact = artifactView(input.artifact) ?? this.artifact;
444
489
  }
445
490
  this.changed();
446
491
  return Response.json(this.state());
@@ -970,10 +1015,10 @@ function createComputerUseChannel() {
970
1015
  const authorization = await responseJson(await sessionRequest(scope, require_computerUseMode.COMPUTER_USE_ROUTES.hubAuthorization));
971
1016
  let artifact;
972
1017
  if (authorization !== null && host.computerUse?.available) try {
973
- artifact = await host.computerUse.request(scope, {
1018
+ artifact = record(await host.computerUse.request(scope, {
974
1019
  operation: "stop",
975
1020
  payload: { grantId: authorization.grantId }
976
- });
1021
+ }))?.artifact;
977
1022
  } catch (error) {
978
1023
  const message = error instanceof Error ? error.message : String(error);
979
1024
  artifact = {
@@ -1139,7 +1184,7 @@ function createComputerUseChannel() {
1139
1184
  };
1140
1185
  },
1141
1186
  receive(scope, payload, connection) {
1142
- if (connection.desktopAuthorized !== true) return;
1187
+ if (connection.desktopAuthorized !== true && connection.computerUseAuthorized !== true) return;
1143
1188
  receiveCommand?.(scope, payload);
1144
1189
  }
1145
1190
  };