@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.
@@ -1,10 +1,11 @@
1
1
  import { a as COMMAND_NAME, i as COMMAND_DESCRIPTION, r as ComputerScriptRunner, t as DefaultComputerUseExtensionService } from "../extensionService-BSqhP2uB.mjs";
2
- import { a as computerScriptOutput, d as COMPUTER_USE_ROUTES, f as COMPUTER_USE_STATUS_KEY, i as computerScriptFailure, l as COMPUTER_USE_MODE_ID, m as computerUseChannelType, n as modeState, o as API_BASE_PATH, p as COMPUTER_USE_WAKE_LIMIT, r as computerObservationOutput, s as COMPUTER_USE_CONFIRMATION_WINDOW_MS } from "../computerUseMode-C1r5mG7K.mjs";
2
+ import { a as computerScriptOutput, d as COMPUTER_USE_ROUTES, f as COMPUTER_USE_STATUS_KEY, i as computerScriptFailure, l as COMPUTER_USE_MODE_ID, m as computerUseChannelType, n as modeState, o as API_BASE_PATH, p as COMPUTER_USE_WAKE_LIMIT, r as computerObservationOutput, s as COMPUTER_USE_CONFIRMATION_WINDOW_MS } from "../computerUseMode-QSRNQAYf.mjs";
3
3
  import path from "node:path";
4
4
  import { composeRootHooks, defineChannel, defineRoot, defineRoutedContribution } from "@agimon-ai/doompi-core/extensionFile";
5
5
  import { defineMinorMode, serverMinorModes } from "@agimon-ai/doompi-minor-mode";
6
6
  import { defineServerPlugin } from "@agimon-ai/doompi-core/serverFacet";
7
7
  import { randomUUID } from "node:crypto";
8
+ import { doomApiCallerFrom } from "@agimon-ai/doompi-core/packageApi";
8
9
  import { apiResponse, defineApiRoutes } from "@agimon-ai/doompi-core/web";
9
10
  //#region src/services/mcpTools/index.ts
10
11
  const COMPUTER_USE_MCP_TOOLS_SERVICE = "doom/computer-use-mcp-tools";
@@ -33,12 +34,28 @@ function mountMcpTools(tools) {
33
34
  * disagreement this file exists to prevent. The dispatcher now reads this
34
35
  * table, so the page, the broker and the hub all resolve one set of strings.
35
36
  *
36
- * Only `activate` is reachable from a browser. The `/agent/` and `/hub/` routes
37
+ * Activation, status, cancellation and recording reads are reachable from a browser. The `/agent/` and `/hub/` routes
37
38
  * each demand a host-issued bearer token and answer 404 without one; they are
38
39
  * declared here because they are this API's surface, not because a page calls
39
40
  * them.
40
41
  */
41
42
  var apiRoutes_default = defineApiRoutes({
43
+ artifact: {
44
+ method: "GET",
45
+ path: COMPUTER_USE_ROUTES.artifact,
46
+ query: ["artifactId", "offset"],
47
+ raw: true
48
+ },
49
+ activationState: {
50
+ method: "GET",
51
+ path: COMPUTER_USE_ROUTES.activate,
52
+ response: apiResponse()
53
+ },
54
+ cancelActivation: {
55
+ method: "DELETE",
56
+ path: COMPUTER_USE_ROUTES.activate,
57
+ response: apiResponse()
58
+ },
42
59
  activate: {
43
60
  method: "POST",
44
61
  path: COMPUTER_USE_ROUTES.activate,
@@ -154,6 +171,7 @@ function artifactView(value) {
154
171
  return {
155
172
  artifactId: input.artifactId,
156
173
  status: input.status,
174
+ ...typeof input.sizeBytes === "number" && Number.isSafeInteger(input.sizeBytes) && input.sizeBytes > 0 ? { sizeBytes: input.sizeBytes } : {},
157
175
  ...downloadUrl === void 0 ? {} : { downloadUrl },
158
176
  ...previewUrl === void 0 ? {} : { previewUrl },
159
177
  ...typeof input.actionCount === "number" ? { actionCount: input.actionCount } : {},
@@ -274,9 +292,10 @@ var ComputerUseRequestBroker = class ComputerUseRequestBroker {
274
292
  return token !== void 0 && request.headers.get("authorization") === `Bearer ${token}`;
275
293
  }
276
294
  async requestActivation(request) {
277
- if (!this.desktop?.available || !this.desktop.authorize(request.headers)) return jsonError("Not found.", 404);
295
+ if (!this.desktop?.available || !(this.desktop.authorizeActivation?.(request.headers) ?? this.desktop.authorize(request.headers))) return jsonError("Not found.", 404);
278
296
  if (this.desktop.enabled === false) return jsonError("Enable computer use in global Desktop settings first.", 409);
279
- const caller = {
297
+ const stamped = doomApiCallerFrom(request.headers);
298
+ const caller = stamped?.locality === "remote" ? stamped : {
280
299
  locality: "local",
281
300
  stepUp: "not-required"
282
301
  };
@@ -284,10 +303,10 @@ var ComputerUseRequestBroker = class ComputerUseRequestBroker {
284
303
  const input = await body(request);
285
304
  const target = record$1(input.target);
286
305
  const durationMs = input.durationMs;
287
- if (target === void 0 || typeof target.windowId !== "string" || typeof target.bundleId !== "string") return jsonError("A Desktop target is required.", 400);
306
+ 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);
288
307
  if (typeof durationMs !== "number" || !Number.isInteger(durationMs) || durationMs < 1e3 || durationMs > 18e5) return jsonError("The requested duration is invalid.", 400);
289
- this.desktop.claim();
290
308
  try {
309
+ this.desktop.claim(request.headers);
291
310
  await this.beforeActivate?.();
292
311
  } catch (error) {
293
312
  return jsonError(error instanceof Error ? error.message : String(error), 409);
@@ -296,7 +315,7 @@ var ComputerUseRequestBroker = class ComputerUseRequestBroker {
296
315
  const createdAt = Date.now();
297
316
  this.activation = Object.freeze({
298
317
  requestId: randomUUID(),
299
- target: Object.freeze({ ...target }),
318
+ ...target === void 0 ? {} : { target: Object.freeze({ ...target }) },
300
319
  durationSeconds: durationMs / 1e3,
301
320
  createdAt,
302
321
  confirmationExpiresAt: createdAt + COMPUTER_USE_CONFIRMATION_WINDOW_MS,
@@ -358,7 +377,28 @@ var ComputerUseRequestBroker = class ComputerUseRequestBroker {
358
377
  }
359
378
  async fetch(request) {
360
379
  if (this.closed) return jsonError("Computer-use broker is closed.", 503);
361
- const path = new URL(request.url).pathname;
380
+ const url = new URL(request.url);
381
+ const path = url.pathname;
382
+ if (request.method === "GET" && path === apiRoutes_default.artifact.path) {
383
+ if (!(this.desktop?.authorizeRecording?.(request.headers) ?? this.desktop?.authorize(request.headers)) || !this.desktop?.fetchRecording) return jsonError("Not found.", 404);
384
+ const artifactId = url.searchParams.get("artifactId") ?? "";
385
+ const offsetText = url.searchParams.get("offset") ?? "";
386
+ const offset = Number(offsetText);
387
+ if (!/^[0-9]+$/u.test(offsetText) || !Number.isSafeInteger(offset) || offset < 0 || offset > 134217728) return jsonError("Invalid recording offset.", 400);
388
+ return this.desktop.fetchRecording(artifactId, `bytes=${offset}-${offset + 1048576 - 1}`);
389
+ }
390
+ if (path === apiRoutes_default.activate.path && request.method === "GET") {
391
+ if (!this.desktop?.authorizePending?.(request.headers) && !(this.desktop?.authorizeRecording?.(request.headers) ?? this.desktop?.authorize(request.headers))) return jsonError("Not found.", 404);
392
+ return Response.json(this.state());
393
+ }
394
+ if (path === apiRoutes_default.activate.path && request.method === "DELETE") {
395
+ if (!this.desktop?.authorizePending?.(request.headers)) return jsonError("Not found.", 404);
396
+ if (this.phase !== "awaiting_confirmation" && this.phase !== "activating") return jsonError("No activation is pending.", 409);
397
+ this.phase = "stopping";
398
+ this.rejectPending("The activation was cancelled.");
399
+ this.changed();
400
+ return Response.json(this.state(), { status: 202 });
401
+ }
362
402
  if (request.method === "POST" && path === apiRoutes_default.activate.path) return this.requestActivation(request);
363
403
  const agent = path.startsWith("/agent/");
364
404
  const hub = path.startsWith("/hub/");
@@ -415,6 +455,11 @@ var ComputerUseRequestBroker = class ComputerUseRequestBroker {
415
455
  } else {
416
456
  const host = record$1(input.host);
417
457
  if (typeof host?.grantId !== "string" || !Number.isFinite(host.expiresAt) || host.expiresAt <= Date.now()) return jsonError("Desktop did not issue a complete grant.", 502);
458
+ const selectedTarget = record$1(host.target);
459
+ if (this.activation !== void 0 && selectedTarget !== void 0) this.activation = Object.freeze({
460
+ ...this.activation,
461
+ target: Object.freeze({ ...selectedTarget })
462
+ });
418
463
  this.grantId = host.grantId;
419
464
  this.expiresAt = host.expiresAt;
420
465
  this.actionSequence = 0;
@@ -435,7 +480,7 @@ var ComputerUseRequestBroker = class ComputerUseRequestBroker {
435
480
  this.grantId = void 0;
436
481
  this.expiresAt = void 0;
437
482
  this.activation = void 0;
438
- this.artifact = artifactView(input.artifact);
483
+ this.artifact = artifactView(input.artifact) ?? this.artifact;
439
484
  }
440
485
  this.changed();
441
486
  return Response.json(this.state());
@@ -965,10 +1010,10 @@ function createComputerUseChannel() {
965
1010
  const authorization = await responseJson(await sessionRequest(scope, COMPUTER_USE_ROUTES.hubAuthorization));
966
1011
  let artifact;
967
1012
  if (authorization !== null && host.computerUse?.available) try {
968
- artifact = await host.computerUse.request(scope, {
1013
+ artifact = record(await host.computerUse.request(scope, {
969
1014
  operation: "stop",
970
1015
  payload: { grantId: authorization.grantId }
971
- });
1016
+ }))?.artifact;
972
1017
  } catch (error) {
973
1018
  const message = error instanceof Error ? error.message : String(error);
974
1019
  artifact = {
@@ -1134,7 +1179,7 @@ function createComputerUseChannel() {
1134
1179
  };
1135
1180
  },
1136
1181
  receive(scope, payload, connection) {
1137
- if (connection.desktopAuthorized !== true) return;
1182
+ if (connection.desktopAuthorized !== true && connection.computerUseAuthorized !== true) return;
1138
1183
  receiveCommand?.(scope, payload);
1139
1184
  }
1140
1185
  };