@agimon-ai/doompi-computer-use 0.0.1-alpha.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.
Files changed (121) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +49 -0
  3. package/dist/_virtual/_rolldown/runtime.cjs +1 -0
  4. package/dist/adapters/computerUseApi.cjs +2 -0
  5. package/dist/adapters/computerUseApi.cjs.map +1 -0
  6. package/dist/adapters/computerUseApi.d.cts +37 -0
  7. package/dist/adapters/computerUseApi.d.cts.map +1 -0
  8. package/dist/adapters/computerUseApi.d.mts +37 -0
  9. package/dist/adapters/computerUseApi.d.mts.map +1 -0
  10. package/dist/adapters/computerUseApi.mjs +2 -0
  11. package/dist/adapters/computerUseApi.mjs.map +1 -0
  12. package/dist/adapters/pi/extension.cjs +3 -0
  13. package/dist/adapters/pi/extension.cjs.map +1 -0
  14. package/dist/adapters/pi/extension.d.cts +12 -0
  15. package/dist/adapters/pi/extension.d.cts.map +1 -0
  16. package/dist/adapters/pi/extension.d.mts +12 -0
  17. package/dist/adapters/pi/extension.d.mts.map +1 -0
  18. package/dist/adapters/pi/extension.mjs +3 -0
  19. package/dist/adapters/pi/extension.mjs.map +1 -0
  20. package/dist/adapters/pi/sessionApiClient.cjs +2 -0
  21. package/dist/adapters/pi/sessionApiClient.cjs.map +1 -0
  22. package/dist/adapters/pi/sessionApiClient.d.cts +26 -0
  23. package/dist/adapters/pi/sessionApiClient.d.cts.map +1 -0
  24. package/dist/adapters/pi/sessionApiClient.d.mts +26 -0
  25. package/dist/adapters/pi/sessionApiClient.d.mts.map +1 -0
  26. package/dist/adapters/pi/sessionApiClient.mjs +2 -0
  27. package/dist/adapters/pi/sessionApiClient.mjs.map +1 -0
  28. package/dist/adapters/webComputerUseAvailability.cjs +2 -0
  29. package/dist/adapters/webComputerUseAvailability.cjs.map +1 -0
  30. package/dist/adapters/webComputerUseAvailability.mjs +2 -0
  31. package/dist/adapters/webComputerUseAvailability.mjs.map +1 -0
  32. package/dist/adapters/webComputerUseChannel.cjs +2 -0
  33. package/dist/adapters/webComputerUseChannel.cjs.map +1 -0
  34. package/dist/adapters/webComputerUseChannel.d.cts +10 -0
  35. package/dist/adapters/webComputerUseChannel.d.cts.map +1 -0
  36. package/dist/adapters/webComputerUseChannel.d.mts +10 -0
  37. package/dist/adapters/webComputerUseChannel.d.mts.map +1 -0
  38. package/dist/adapters/webComputerUseChannel.mjs +2 -0
  39. package/dist/adapters/webComputerUseChannel.mjs.map +1 -0
  40. package/dist/commands/computerUseCommand.cjs +2 -0
  41. package/dist/commands/computerUseCommand.cjs.map +1 -0
  42. package/dist/commands/computerUseCommand.mjs +2 -0
  43. package/dist/commands/computerUseCommand.mjs.map +1 -0
  44. package/dist/container/index.cjs +2 -0
  45. package/dist/container/index.cjs.map +1 -0
  46. package/dist/container/index.d.cts +6 -0
  47. package/dist/container/index.d.cts.map +1 -0
  48. package/dist/container/index.d.mts +6 -0
  49. package/dist/container/index.d.mts.map +1 -0
  50. package/dist/container/index.mjs +2 -0
  51. package/dist/container/index.mjs.map +1 -0
  52. package/dist/extensions/pi.cjs +1 -0
  53. package/dist/extensions/pi.d.cts +2 -0
  54. package/dist/extensions/pi.d.mts +2 -0
  55. package/dist/extensions/pi.mjs +1 -0
  56. package/dist/index.cjs +1 -0
  57. package/dist/index.d.cts +10 -0
  58. package/dist/index.d.mts +10 -0
  59. package/dist/index.mjs +1 -0
  60. package/dist/services/extensionService.cjs +2 -0
  61. package/dist/services/extensionService.cjs.map +1 -0
  62. package/dist/services/extensionService.d.cts +11 -0
  63. package/dist/services/extensionService.d.cts.map +1 -0
  64. package/dist/services/extensionService.d.mts +11 -0
  65. package/dist/services/extensionService.d.mts.map +1 -0
  66. package/dist/services/extensionService.mjs +2 -0
  67. package/dist/services/extensionService.mjs.map +1 -0
  68. package/dist/services/sessionController.cjs +2 -0
  69. package/dist/services/sessionController.cjs.map +1 -0
  70. package/dist/services/sessionController.d.cts +7 -0
  71. package/dist/services/sessionController.d.cts.map +1 -0
  72. package/dist/services/sessionController.d.mts +7 -0
  73. package/dist/services/sessionController.d.mts.map +1 -0
  74. package/dist/services/sessionController.mjs +2 -0
  75. package/dist/services/sessionController.mjs.map +1 -0
  76. package/dist/services/traceRedaction.cjs +2 -0
  77. package/dist/services/traceRedaction.cjs.map +1 -0
  78. package/dist/services/traceRedaction.d.cts +29 -0
  79. package/dist/services/traceRedaction.d.cts.map +1 -0
  80. package/dist/services/traceRedaction.d.mts +29 -0
  81. package/dist/services/traceRedaction.d.mts.map +1 -0
  82. package/dist/services/traceRedaction.mjs +2 -0
  83. package/dist/services/traceRedaction.mjs.map +1 -0
  84. package/dist/sessionApi.cjs +1 -0
  85. package/dist/sessionApi.d.cts +2 -0
  86. package/dist/sessionApi.d.mts +2 -0
  87. package/dist/sessionApi.mjs +1 -0
  88. package/dist/types/computerUse.d.cts +104 -0
  89. package/dist/types/computerUse.d.cts.map +1 -0
  90. package/dist/types/computerUse.d.mts +104 -0
  91. package/dist/types/computerUse.d.mts.map +1 -0
  92. package/dist/types/computerUseApi.cjs +2 -0
  93. package/dist/types/computerUseApi.cjs.map +1 -0
  94. package/dist/types/computerUseApi.d.cts +75 -0
  95. package/dist/types/computerUseApi.d.cts.map +1 -0
  96. package/dist/types/computerUseApi.d.mts +75 -0
  97. package/dist/types/computerUseApi.d.mts.map +1 -0
  98. package/dist/types/computerUseApi.mjs +2 -0
  99. package/dist/types/computerUseApi.mjs.map +1 -0
  100. package/dist/types/extension.d.cts +17 -0
  101. package/dist/types/extension.d.cts.map +1 -0
  102. package/dist/types/extension.d.mts +17 -0
  103. package/dist/types/extension.d.mts.map +1 -0
  104. package/dist/webHub.cjs +1 -0
  105. package/dist/webHub.d.cts +3 -0
  106. package/dist/webHub.d.mts +3 -0
  107. package/dist/webHub.mjs +1 -0
  108. package/llms.txt +11 -0
  109. package/package.json +124 -0
  110. package/src/exports/webClient.ts +2 -0
  111. package/src/prompts/doompi-use-computer-use/SKILL.md +20 -0
  112. package/src/types/computerUse.ts +117 -0
  113. package/src/types/computerUseApi.ts +78 -0
  114. package/src/web/ComputerActionToolCard.tsx +51 -0
  115. package/src/web/ComputerStateToolCard.tsx +51 -0
  116. package/src/web/ComputerUsePanel.tsx +136 -0
  117. package/src/web/computerActionToolRender.ts +20 -0
  118. package/src/web/computerStateToolRender.ts +18 -0
  119. package/src/web/computerUseStore.ts +26 -0
  120. package/src/web/index.ts +41 -0
  121. package/src/web/tsconfig.json +28 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Vuong Ngo
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,49 @@
1
+ # @agimon-ai/doompi-computer-use
2
+
3
+ Session-scoped semantic computer control through the DoomPi Desktop capability.
4
+
5
+ ## Requirements
6
+
7
+ - Node.js 22.19.0 or newer
8
+ - DoomPi Desktop with Computer Use available
9
+ - `@earendil-works/pi-coding-agent` 0.85.0
10
+
11
+ ## Install
12
+
13
+ ```bash
14
+ pi install npm:@agimon-ai/doompi-computer-use
15
+ ```
16
+
17
+ ## Use
18
+
19
+ Enable the default-off **Computer Use** minor mode in the cockpit. Its Activity section then lists eligible Desktop targets, lets you select one, and starts the activation and confirmation flow. Only one session can hold a live Desktop run.
20
+
21
+ The `computer-use` minor mode exposes Activate, Deactivate, and Doctor actions. `/computer-use` reports the current state.
22
+
23
+ While active, the package exposes exactly two tools:
24
+
25
+ - `computer_state` observes the authorized window and returns a semantic snapshot.
26
+ - `computer_action` performs one semantic press, value change, or scroll against a current snapshot.
27
+
28
+ Both tools and their model guidance remain unavailable during setup and are exposed only after the native grant becomes active. The Activity section shows activation status, busy ownership, stop controls, and completed recording or trace metadata. Browser clients cannot call observation or action routes.
29
+
30
+ ## Public API
31
+
32
+ ```ts
33
+ import { activateComputerUseExtension, createComputerUseSessionClient } from '@agimon-ai/doompi-computer-use';
34
+ ```
35
+
36
+ The session API entry is available at `@agimon-ai/doompi-computer-use/session-api`. Its agent and hub routes use separate host-issued context tokens. Grants remain opaque and session-bound inside the request broker.
37
+
38
+ ## Development
39
+
40
+ ```bash
41
+ pnpm fixcode
42
+ pnpm typecheck
43
+ pnpm test
44
+ pnpm build
45
+ ```
46
+
47
+ ## License
48
+
49
+ MIT
@@ -0,0 +1 @@
1
+ var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},s=(n,r,s)=>(s=n==null?{}:e(i(n)),o(r||!n||!n.__esModule||!a.call(n,`default`)?t(s,`default`,{value:n,enumerable:!0}):s,n));exports.__toESM=s;
@@ -0,0 +1,2 @@
1
+ const e=require("../types/computerUseApi.cjs");let t=require("@agimon-ai/doompi-extension-contracts/package-api"),n=require("node:crypto");function r(e,t){return Response.json({error:e},{status:t})}function i(e){return typeof e==`object`&&e&&!Array.isArray(e)?e:void 0}async function a(e){try{return i(await e.json())??{}}catch{return{}}}function o(e){if(!(typeof e.snapshotId==`string`&&e.snapshotId.length>0&&typeof e.elementRef==`string`&&e.elementRef.length>0))return!1;let t=t=>Object.keys(e).every(e=>t.includes(e));return e.kind===`press`?t([`kind`,`snapshotId`,`elementRef`]):e.kind===`set_value`?typeof e.value==`string`&&t([`kind`,`snapshotId`,`elementRef`,`value`]):e.kind===`scroll`&&[`up`,`down`,`left`,`right`].includes(e.direction)&&(e.amount===`line`||e.amount===`page`)&&t([`kind`,`snapshotId`,`elementRef`,`direction`,`amount`])}function s(e){let t=i(e);if(typeof t?.artifactId!=`string`||t.status!==`ready`&&t.status!==`failed`)return;let n=e=>typeof e==`string`&&e.startsWith(`/api/`)?e:void 0,r=n(t.downloadUrl),a=n(t.previewUrl);return{artifactId:t.artifactId,status:t.status,...r===void 0?{}:{downloadUrl:r},...a===void 0?{}:{previewUrl:a},...typeof t.actionCount==`number`?{actionCount:t.actionCount}:{},...typeof t.completedAt==`string`?{completedAt:t.completedAt}:{}}}var c=class{sessionId;internalToken;hubToken;revision=0;wake=0;phase=`inactive`;activation;grantId;expiresAt;actionSequence=0;failure;artifact;pending;closed=!1;constructor(e){this.sessionId=e.sessionId??`unknown`,this.internalToken=e.internalToken,this.hubToken=e.hubToken}state(){return Object.freeze({sessionId:this.sessionId,revision:this.revision,wake:this.wake,phase:this.phase,...this.activation===void 0?{}:{requestId:this.activation.requestId,target:this.activation.target,durationMs:this.activation.durationSeconds*1e3},...this.expiresAt===void 0?{}:{expiresAt:this.expiresAt},...this.failure===void 0?{}:{failure:this.failure},...this.artifact===void 0?{}:{artifact:this.artifact}})}changed(){this.revision+=1,this.wake=(this.wake+1)%e.COMPUTER_USE_WAKE_LIMIT}authorized(e,t){return t!==void 0&&e.headers.get(`authorization`)===`Bearer ${t}`}async requestActivation(o){let s=(0,t.doomApiCallerFrom)(o.headers);if(s===void 0||s.locality===`remote`&&s.stepUp===`not-required`)return r(`Not found.`,404);if(this.phase!==`inactive`&&this.phase!==`failed`)return r(`Computer use is already busy.`,409);let c=await a(o),l=i(c.target),u=c.durationMs;if(l===void 0||typeof l.windowId!=`string`||typeof l.bundleId!=`string`)return r(`A Desktop target is required.`,400);if(typeof u!=`number`||!Number.isInteger(u)||u<1e3||u>18e5)return r(`The requested duration is invalid.`,400);let d=Date.now();return this.activation=Object.freeze({requestId:(0,n.randomUUID)(),target:Object.freeze({...l}),durationSeconds:u/1e3,createdAt:d,confirmationExpiresAt:d+e.COMPUTER_USE_CONFIRMATION_WINDOW_MS,caller:Object.freeze({...s})}),this.phase=`awaiting_confirmation`,this.failure=void 0,this.artifact=void 0,this.changed(),Response.json(this.state(),{status:202})}async enqueue(e,t){if(this.phase!==`active`||this.grantId===void 0)return r(`Computer use is not active.`,409);if(this.pending!==void 0)return r(`Another computer-use request is live.`,409);let i=e===`act`?++this.actionSequence:void 0,a={id:(0,n.randomUUID)(),operation:e,grantId:this.grantId,...i===void 0?{}:{sequence:i},...t===void 0?{}:{payload:t}},o=new Promise((e,t)=>{this.pending={request:a,resolve:e,reject:t}});this.changed();try{return Response.json(await o)}catch(e){return r(e instanceof Error?e.message:String(e),502)}}async fetch(t){if(this.closed)return r(`Computer-use broker is closed.`,503);let n=new URL(t.url).pathname;if(t.method===`POST`&&n===e.COMPUTER_USE_ROUTES.activate)return this.requestActivation(t);let c=n.startsWith(`/agent/`),l=n.startsWith(`/hub/`);if(c&&!this.authorized(t,this.internalToken)||l&&!this.authorized(t,this.hubToken))return r(`Not found.`,404);if(t.method===`GET`&&(n===e.COMPUTER_USE_ROUTES.agentState||n===e.COMPUTER_USE_ROUTES.hubState))return Response.json(this.state());if(t.method===`POST`&&n===e.COMPUTER_USE_ROUTES.agentObserve)return this.enqueue(`observe`);if(t.method===`POST`&&n===e.COMPUTER_USE_ROUTES.agentAction){let e=await a(t);return o(e)?this.enqueue(`act`,e):r(`A valid semantic action is required.`,400)}if(t.method===`POST`&&n===e.COMPUTER_USE_ROUTES.agentStop)return this.phase===`active`?(this.phase=`stopping`,this.changed(),Response.json(this.state(),{status:202})):r(`Computer use is not active.`,409);if(t.method===`GET`&&n===e.COMPUTER_USE_ROUTES.hubActivation)return this.activation===void 0||this.phase!==`awaiting_confirmation`?Response.json(null):(this.phase=`activating`,this.changed(),Response.json(this.activation));if(t.method===`GET`&&n===e.COMPUTER_USE_ROUTES.hubAuthorization)return Response.json(this.grantId===void 0?null:{grantId:this.grantId,expiresAt:this.expiresAt});if(t.method===`GET`&&n===e.COMPUTER_USE_ROUTES.hubNext)return Response.json(this.pending?.request??null);if(t.method===`POST`&&n===e.COMPUTER_USE_ROUTES.hubComplete){let e=await a(t),n=typeof e.id==`string`?e.id:void 0;if(this.pending===void 0||this.pending.request.id!==n)return r(`The request is stale.`,409);let i=this.pending;return this.pending=void 0,this.changed(),typeof e.error==`string`?i.reject(Error(e.error)):i.resolve(e.result),Response.json(this.state())}if(t.method===`POST`&&n===e.COMPUTER_USE_ROUTES.hubStop){let e=await a(t);if(this.phase===`activating`){if(typeof e.error==`string`)this.phase=`failed`,this.failure={code:`desktop_unavailable`,message:e.error.slice(0,512)},this.activation=void 0;else{let t=i(e.host);if(typeof t?.grantId!=`string`||!Number.isFinite(t.expiresAt))return r(`Desktop did not issue a complete grant.`,502);this.grantId=t.grantId,this.expiresAt=t.expiresAt,this.actionSequence=0,this.phase=`active`}}else this.phase=`inactive`,this.grantId=void 0,this.expiresAt=void 0,this.activation=void 0,this.artifact=s(e.artifact);return this.changed(),Response.json(this.state())}return r(`Not found.`,404)}close(){this.closed=!0,this.pending?.reject(Error(`Computer-use broker closed.`)),this.pending=void 0,this.grantId=void 0,this.expiresAt=void 0}};function l(e={}){return new c(e)}const u={basePath:e.API_BASE_PATH,start(e){return l({...e.sessionId===void 0?{}:{sessionId:e.sessionId},...e.internalToken===void 0?{}:{internalToken:e.internalToken},...e.hubToken===void 0?{}:{hubToken:e.hubToken}})}};exports.ComputerUseRequestBroker=c,exports.api=u,exports.createComputerUseApi=l;
2
+ //# sourceMappingURL=computerUseApi.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"computerUseApi.cjs","names":["COMPUTER_USE_WAKE_LIMIT","doomApiCallerFrom","randomUUID","COMPUTER_USE_CONFIRMATION_WINDOW_MS","COMPUTER_USE_ROUTES","API_BASE_PATH"],"sources":["../../src/adapters/computerUseApi.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto';\nimport {\n doomApiCallerFrom,\n type DoomApi,\n type DoomApiContext,\n type DoomApiHandler,\n} from '@agimon-ai/doompi-extension-contracts/package-api';\nimport {\n API_BASE_PATH,\n COMPUTER_USE_CONFIRMATION_WINDOW_MS,\n COMPUTER_USE_MAX_DURATION_MS,\n COMPUTER_USE_ROUTES,\n COMPUTER_USE_WAKE_LIMIT,\n type ComputerUseActivationRequest,\n type ComputerUseArtifactView,\n type ComputerUseBrokerRequest,\n type ComputerUseSessionView,\n} from '../types/computerUseApi.ts';\n\ninterface PendingRequest {\n readonly request: ComputerUseBrokerRequest;\n resolve(value: unknown): void;\n reject(error: Error): void;\n}\n\nfunction jsonError(message: string, status: number): Response {\n return Response.json({ error: message }, { status });\n}\n\nfunction record(value: unknown): Record<string, unknown> | undefined {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : undefined;\n}\n\nasync function body(request: Request): Promise<Record<string, unknown>> {\n try {\n return record(await request.json()) ?? {};\n } catch {\n return {};\n }\n}\n\nfunction semanticAction(value: Record<string, unknown>): boolean {\n const base =\n typeof value.snapshotId === 'string' &&\n value.snapshotId.length > 0 &&\n typeof value.elementRef === 'string' &&\n value.elementRef.length > 0;\n if (!base) return false;\n const allowed = (keys: readonly string[]) => Object.keys(value).every((key) => keys.includes(key));\n if (value.kind === 'press') return allowed(['kind', 'snapshotId', 'elementRef']);\n if (value.kind === 'set_value')\n return typeof value.value === 'string' && allowed(['kind', 'snapshotId', 'elementRef', 'value']);\n if (value.kind === 'scroll')\n return (\n ['up', 'down', 'left', 'right'].includes(value.direction as string) &&\n (value.amount === 'line' || value.amount === 'page') &&\n allowed(['kind', 'snapshotId', 'elementRef', 'direction', 'amount'])\n );\n return false;\n}\nfunction artifactView(value: unknown): ComputerUseArtifactView | undefined {\n const input = record(value);\n if (typeof input?.artifactId !== 'string' || (input.status !== 'ready' && input.status !== 'failed'))\n return undefined;\n const safeUrl = (candidate: unknown) =>\n typeof candidate === 'string' && candidate.startsWith('/api/') ? candidate : undefined;\n const downloadUrl = safeUrl(input.downloadUrl);\n const previewUrl = safeUrl(input.previewUrl);\n return {\n artifactId: input.artifactId,\n status: input.status,\n ...(downloadUrl === undefined ? {} : { downloadUrl }),\n ...(previewUrl === undefined ? {} : { previewUrl }),\n ...(typeof input.actionCount === 'number' ? { actionCount: input.actionCount } : {}),\n ...(typeof input.completedAt === 'string' ? { completedAt: input.completedAt } : {}),\n };\n}\n\nexport interface ComputerUseApiOptions {\n readonly sessionId?: string;\n readonly internalToken?: string;\n readonly hubToken?: string;\n}\n\nexport class ComputerUseRequestBroker implements DoomApiHandler {\n private readonly sessionId: string;\n private readonly internalToken?: string;\n private readonly hubToken?: string;\n private revision = 0;\n private wake = 0;\n private phase: ComputerUseSessionView['phase'] = 'inactive';\n private activation?: ComputerUseActivationRequest;\n private grantId?: string;\n private expiresAt?: number;\n private actionSequence = 0;\n private failure?: ComputerUseSessionView['failure'];\n private artifact?: ComputerUseArtifactView;\n private pending?: PendingRequest;\n private closed = false;\n\n public constructor(options: ComputerUseApiOptions) {\n this.sessionId = options.sessionId ?? 'unknown';\n this.internalToken = options.internalToken;\n this.hubToken = options.hubToken;\n }\n\n public state(): ComputerUseSessionView {\n return Object.freeze({\n sessionId: this.sessionId,\n revision: this.revision,\n wake: this.wake,\n phase: this.phase,\n ...(this.activation === undefined\n ? {}\n : {\n requestId: this.activation.requestId,\n target: this.activation.target,\n durationMs: this.activation.durationSeconds * 1_000,\n }),\n ...(this.expiresAt === undefined ? {} : { expiresAt: this.expiresAt }),\n ...(this.failure === undefined ? {} : { failure: this.failure }),\n ...(this.artifact === undefined ? {} : { artifact: this.artifact }),\n });\n }\n\n private changed(): void {\n this.revision += 1;\n this.wake = (this.wake + 1) % COMPUTER_USE_WAKE_LIMIT;\n }\n\n private authorized(request: Request, token: string | undefined): boolean {\n return token !== undefined && request.headers.get('authorization') === `Bearer ${token}`;\n }\n\n private async requestActivation(request: Request): Promise<Response> {\n const caller = doomApiCallerFrom(request.headers);\n if (caller === undefined || (caller.locality === 'remote' && caller.stepUp === 'not-required'))\n return jsonError('Not found.', 404);\n if (this.phase !== 'inactive' && this.phase !== 'failed') return jsonError('Computer use is already busy.', 409);\n const input = await body(request);\n const target = record(input.target);\n const durationMs = input.durationMs;\n if (target === undefined || typeof target.windowId !== 'string' || typeof target.bundleId !== 'string')\n return jsonError('A Desktop target is required.', 400);\n if (\n typeof durationMs !== 'number' ||\n !Number.isInteger(durationMs) ||\n durationMs < 1_000 ||\n durationMs > COMPUTER_USE_MAX_DURATION_MS\n )\n return jsonError('The requested duration is invalid.', 400);\n const createdAt = Date.now();\n this.activation = Object.freeze({\n requestId: randomUUID(),\n target: Object.freeze({ ...target }),\n durationSeconds: durationMs / 1_000,\n createdAt,\n confirmationExpiresAt: createdAt + COMPUTER_USE_CONFIRMATION_WINDOW_MS,\n caller: Object.freeze({ ...caller }),\n });\n this.phase = 'awaiting_confirmation';\n this.failure = undefined;\n this.artifact = undefined;\n this.changed();\n return Response.json(this.state(), { status: 202 });\n }\n\n private async enqueue(operation: ComputerUseBrokerRequest['operation'], payload?: unknown): Promise<Response> {\n if (this.phase !== 'active' || this.grantId === undefined) return jsonError('Computer use is not active.', 409);\n if (this.pending !== undefined) return jsonError('Another computer-use request is live.', 409);\n const sequence = operation === 'act' ? ++this.actionSequence : undefined;\n const request: ComputerUseBrokerRequest = {\n id: randomUUID(),\n operation,\n grantId: this.grantId,\n ...(sequence === undefined ? {} : { sequence }),\n ...(payload === undefined ? {} : { payload }),\n };\n const completion = new Promise<unknown>((resolve, reject) => {\n this.pending = { request, resolve, reject };\n });\n this.changed();\n try {\n return Response.json(await completion);\n } catch (error) {\n return jsonError(error instanceof Error ? error.message : String(error), 502);\n }\n }\n\n public async fetch(request: Request): Promise<Response> {\n if (this.closed) return jsonError('Computer-use broker is closed.', 503);\n const path = new URL(request.url).pathname;\n if (request.method === 'POST' && path === COMPUTER_USE_ROUTES.activate) return this.requestActivation(request);\n const agent = path.startsWith('/agent/');\n const hub = path.startsWith('/hub/');\n if ((agent && !this.authorized(request, this.internalToken)) || (hub && !this.authorized(request, this.hubToken)))\n return jsonError('Not found.', 404);\n\n if (request.method === 'GET' && (path === COMPUTER_USE_ROUTES.agentState || path === COMPUTER_USE_ROUTES.hubState))\n return Response.json(this.state());\n if (request.method === 'POST' && path === COMPUTER_USE_ROUTES.agentObserve) return this.enqueue('observe');\n if (request.method === 'POST' && path === COMPUTER_USE_ROUTES.agentAction) {\n const action = await body(request);\n if (!semanticAction(action)) return jsonError('A valid semantic action is required.', 400);\n return this.enqueue('act', action);\n }\n if (request.method === 'POST' && path === COMPUTER_USE_ROUTES.agentStop) {\n if (this.phase !== 'active') return jsonError('Computer use is not active.', 409);\n this.phase = 'stopping';\n this.changed();\n return Response.json(this.state(), { status: 202 });\n }\n if (request.method === 'GET' && path === COMPUTER_USE_ROUTES.hubActivation) {\n if (this.activation === undefined || this.phase !== 'awaiting_confirmation') return Response.json(null);\n this.phase = 'activating';\n this.changed();\n return Response.json(this.activation);\n }\n if (request.method === 'GET' && path === COMPUTER_USE_ROUTES.hubAuthorization)\n return Response.json(this.grantId === undefined ? null : { grantId: this.grantId, expiresAt: this.expiresAt });\n if (request.method === 'GET' && path === COMPUTER_USE_ROUTES.hubNext)\n return Response.json(this.pending?.request ?? null);\n if (request.method === 'POST' && path === COMPUTER_USE_ROUTES.hubComplete) {\n const input = await body(request);\n const id = typeof input.id === 'string' ? input.id : undefined;\n if (this.pending === undefined || this.pending.request.id !== id) return jsonError('The request is stale.', 409);\n const pending = this.pending;\n this.pending = undefined;\n this.changed();\n if (typeof input.error === 'string') pending.reject(new Error(input.error));\n else pending.resolve(input.result);\n return Response.json(this.state());\n }\n if (request.method === 'POST' && path === COMPUTER_USE_ROUTES.hubStop) {\n const input = await body(request);\n if (this.phase === 'activating') {\n if (typeof input.error === 'string') {\n this.phase = 'failed';\n this.failure = { code: 'desktop_unavailable', message: input.error.slice(0, 512) };\n this.activation = undefined;\n } else {\n const host = record(input.host);\n if (typeof host?.grantId !== 'string' || !Number.isFinite(host.expiresAt))\n return jsonError('Desktop did not issue a complete grant.', 502);\n this.grantId = host.grantId;\n this.expiresAt = host.expiresAt as number;\n this.actionSequence = 0;\n this.phase = 'active';\n }\n } else {\n this.phase = 'inactive';\n this.grantId = undefined;\n this.expiresAt = undefined;\n this.activation = undefined;\n this.artifact = artifactView(input.artifact);\n }\n this.changed();\n return Response.json(this.state());\n }\n return jsonError('Not found.', 404);\n }\n\n public close(): void {\n this.closed = true;\n this.pending?.reject(new Error('Computer-use broker closed.'));\n this.pending = undefined;\n this.grantId = undefined;\n this.expiresAt = undefined;\n }\n}\n\nexport function createComputerUseApi(options: ComputerUseApiOptions = {}): ComputerUseRequestBroker {\n return new ComputerUseRequestBroker(options);\n}\n\nexport const api: DoomApi = {\n basePath: API_BASE_PATH,\n start(context: DoomApiContext): DoomApiHandler {\n return createComputerUseApi({\n ...(context.sessionId === undefined ? {} : { sessionId: context.sessionId }),\n ...(context.internalToken === undefined ? {} : { internalToken: context.internalToken }),\n ...(context.hubToken === undefined ? {} : { hubToken: context.hubToken }),\n });\n },\n};\n"],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ import { ComputerUseSessionView } from "../types/computerUseApi.cjs";
2
+ import { DoomApi, DoomApiHandler } from "@agimon-ai/doompi-extension-contracts/package-api";
3
+ //#region src/adapters/computerUseApi.d.ts
4
+ interface ComputerUseApiOptions {
5
+ readonly sessionId?: string;
6
+ readonly internalToken?: string;
7
+ readonly hubToken?: string;
8
+ }
9
+ declare class ComputerUseRequestBroker implements DoomApiHandler {
10
+ private readonly sessionId;
11
+ private readonly internalToken?;
12
+ private readonly hubToken?;
13
+ private revision;
14
+ private wake;
15
+ private phase;
16
+ private activation?;
17
+ private grantId?;
18
+ private expiresAt?;
19
+ private actionSequence;
20
+ private failure?;
21
+ private artifact?;
22
+ private pending?;
23
+ private closed;
24
+ constructor(options: ComputerUseApiOptions);
25
+ state(): ComputerUseSessionView;
26
+ private changed;
27
+ private authorized;
28
+ private requestActivation;
29
+ private enqueue;
30
+ fetch(request: Request): Promise<Response>;
31
+ close(): void;
32
+ }
33
+ declare function createComputerUseApi(options?: ComputerUseApiOptions): ComputerUseRequestBroker;
34
+ declare const api: DoomApi;
35
+ //#endregion
36
+ export { ComputerUseApiOptions, ComputerUseRequestBroker, api, createComputerUseApi };
37
+ //# sourceMappingURL=computerUseApi.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"computerUseApi.d.cts","names":[],"sources":["../../src/adapters/computerUseApi.ts"],"mappings":";;;UAgFiB;WACN;WACA;WACA;;cAGE,oCAAoC;mBAC9B;mBACA;mBACA;UACT;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;EAER,YAAmB,SAAS;EAMrB,SAAS;UAmBR;UAKA;UAIM;UAiCA;EAsBD,MAAM,SAAS,UAAU,QAAQ;EAyEvC;;iBASO,qBAAqB,UAAS,wBAA6B;cAI9D,KAAK"}
@@ -0,0 +1,37 @@
1
+ import { ComputerUseSessionView } from "../types/computerUseApi.mjs";
2
+ import { DoomApi, DoomApiHandler } from "@agimon-ai/doompi-extension-contracts/package-api";
3
+ //#region src/adapters/computerUseApi.d.ts
4
+ interface ComputerUseApiOptions {
5
+ readonly sessionId?: string;
6
+ readonly internalToken?: string;
7
+ readonly hubToken?: string;
8
+ }
9
+ declare class ComputerUseRequestBroker implements DoomApiHandler {
10
+ private readonly sessionId;
11
+ private readonly internalToken?;
12
+ private readonly hubToken?;
13
+ private revision;
14
+ private wake;
15
+ private phase;
16
+ private activation?;
17
+ private grantId?;
18
+ private expiresAt?;
19
+ private actionSequence;
20
+ private failure?;
21
+ private artifact?;
22
+ private pending?;
23
+ private closed;
24
+ constructor(options: ComputerUseApiOptions);
25
+ state(): ComputerUseSessionView;
26
+ private changed;
27
+ private authorized;
28
+ private requestActivation;
29
+ private enqueue;
30
+ fetch(request: Request): Promise<Response>;
31
+ close(): void;
32
+ }
33
+ declare function createComputerUseApi(options?: ComputerUseApiOptions): ComputerUseRequestBroker;
34
+ declare const api: DoomApi;
35
+ //#endregion
36
+ export { ComputerUseApiOptions, ComputerUseRequestBroker, api, createComputerUseApi };
37
+ //# sourceMappingURL=computerUseApi.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"computerUseApi.d.mts","names":[],"sources":["../../src/adapters/computerUseApi.ts"],"mappings":";;;UAgFiB;WACN;WACA;WACA;;cAGE,oCAAoC;mBAC9B;mBACA;mBACA;UACT;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;EAER,YAAmB,SAAS;EAMrB,SAAS;UAmBR;UAKA;UAIM;UAiCA;EAsBD,MAAM,SAAS,UAAU,QAAQ;EAyEvC;;iBASO,qBAAqB,UAAS,wBAA6B;cAI9D,KAAK"}
@@ -0,0 +1,2 @@
1
+ import{API_BASE_PATH as e,COMPUTER_USE_CONFIRMATION_WINDOW_MS as t,COMPUTER_USE_ROUTES as n,COMPUTER_USE_WAKE_LIMIT as r}from"../types/computerUseApi.mjs";import{doomApiCallerFrom as i}from"@agimon-ai/doompi-extension-contracts/package-api";import{randomUUID as a}from"node:crypto";function o(e,t){return Response.json({error:e},{status:t})}function s(e){return typeof e==`object`&&e&&!Array.isArray(e)?e:void 0}async function c(e){try{return s(await e.json())??{}}catch{return{}}}function l(e){if(!(typeof e.snapshotId==`string`&&e.snapshotId.length>0&&typeof e.elementRef==`string`&&e.elementRef.length>0))return!1;let t=t=>Object.keys(e).every(e=>t.includes(e));return e.kind===`press`?t([`kind`,`snapshotId`,`elementRef`]):e.kind===`set_value`?typeof e.value==`string`&&t([`kind`,`snapshotId`,`elementRef`,`value`]):e.kind===`scroll`&&[`up`,`down`,`left`,`right`].includes(e.direction)&&(e.amount===`line`||e.amount===`page`)&&t([`kind`,`snapshotId`,`elementRef`,`direction`,`amount`])}function u(e){let t=s(e);if(typeof t?.artifactId!=`string`||t.status!==`ready`&&t.status!==`failed`)return;let n=e=>typeof e==`string`&&e.startsWith(`/api/`)?e:void 0,r=n(t.downloadUrl),i=n(t.previewUrl);return{artifactId:t.artifactId,status:t.status,...r===void 0?{}:{downloadUrl:r},...i===void 0?{}:{previewUrl:i},...typeof t.actionCount==`number`?{actionCount:t.actionCount}:{},...typeof t.completedAt==`string`?{completedAt:t.completedAt}:{}}}var d=class{sessionId;internalToken;hubToken;revision=0;wake=0;phase=`inactive`;activation;grantId;expiresAt;actionSequence=0;failure;artifact;pending;closed=!1;constructor(e){this.sessionId=e.sessionId??`unknown`,this.internalToken=e.internalToken,this.hubToken=e.hubToken}state(){return Object.freeze({sessionId:this.sessionId,revision:this.revision,wake:this.wake,phase:this.phase,...this.activation===void 0?{}:{requestId:this.activation.requestId,target:this.activation.target,durationMs:this.activation.durationSeconds*1e3},...this.expiresAt===void 0?{}:{expiresAt:this.expiresAt},...this.failure===void 0?{}:{failure:this.failure},...this.artifact===void 0?{}:{artifact:this.artifact}})}changed(){this.revision+=1,this.wake=(this.wake+1)%r}authorized(e,t){return t!==void 0&&e.headers.get(`authorization`)===`Bearer ${t}`}async requestActivation(e){let n=i(e.headers);if(n===void 0||n.locality===`remote`&&n.stepUp===`not-required`)return o(`Not found.`,404);if(this.phase!==`inactive`&&this.phase!==`failed`)return o(`Computer use is already busy.`,409);let r=await c(e),l=s(r.target),u=r.durationMs;if(l===void 0||typeof l.windowId!=`string`||typeof l.bundleId!=`string`)return o(`A Desktop target is required.`,400);if(typeof u!=`number`||!Number.isInteger(u)||u<1e3||u>18e5)return o(`The requested duration is invalid.`,400);let d=Date.now();return this.activation=Object.freeze({requestId:a(),target:Object.freeze({...l}),durationSeconds:u/1e3,createdAt:d,confirmationExpiresAt:d+t,caller:Object.freeze({...n})}),this.phase=`awaiting_confirmation`,this.failure=void 0,this.artifact=void 0,this.changed(),Response.json(this.state(),{status:202})}async enqueue(e,t){if(this.phase!==`active`||this.grantId===void 0)return o(`Computer use is not active.`,409);if(this.pending!==void 0)return o(`Another computer-use request is live.`,409);let n=e===`act`?++this.actionSequence:void 0,r={id:a(),operation:e,grantId:this.grantId,...n===void 0?{}:{sequence:n},...t===void 0?{}:{payload:t}},i=new Promise((e,t)=>{this.pending={request:r,resolve:e,reject:t}});this.changed();try{return Response.json(await i)}catch(e){return o(e instanceof Error?e.message:String(e),502)}}async fetch(e){if(this.closed)return o(`Computer-use broker is closed.`,503);let t=new URL(e.url).pathname;if(e.method===`POST`&&t===n.activate)return this.requestActivation(e);let r=t.startsWith(`/agent/`),i=t.startsWith(`/hub/`);if(r&&!this.authorized(e,this.internalToken)||i&&!this.authorized(e,this.hubToken))return o(`Not found.`,404);if(e.method===`GET`&&(t===n.agentState||t===n.hubState))return Response.json(this.state());if(e.method===`POST`&&t===n.agentObserve)return this.enqueue(`observe`);if(e.method===`POST`&&t===n.agentAction){let t=await c(e);return l(t)?this.enqueue(`act`,t):o(`A valid semantic action is required.`,400)}if(e.method===`POST`&&t===n.agentStop)return this.phase===`active`?(this.phase=`stopping`,this.changed(),Response.json(this.state(),{status:202})):o(`Computer use is not active.`,409);if(e.method===`GET`&&t===n.hubActivation)return this.activation===void 0||this.phase!==`awaiting_confirmation`?Response.json(null):(this.phase=`activating`,this.changed(),Response.json(this.activation));if(e.method===`GET`&&t===n.hubAuthorization)return Response.json(this.grantId===void 0?null:{grantId:this.grantId,expiresAt:this.expiresAt});if(e.method===`GET`&&t===n.hubNext)return Response.json(this.pending?.request??null);if(e.method===`POST`&&t===n.hubComplete){let t=await c(e),n=typeof t.id==`string`?t.id:void 0;if(this.pending===void 0||this.pending.request.id!==n)return o(`The request is stale.`,409);let r=this.pending;return this.pending=void 0,this.changed(),typeof t.error==`string`?r.reject(Error(t.error)):r.resolve(t.result),Response.json(this.state())}if(e.method===`POST`&&t===n.hubStop){let t=await c(e);if(this.phase===`activating`){if(typeof t.error==`string`)this.phase=`failed`,this.failure={code:`desktop_unavailable`,message:t.error.slice(0,512)},this.activation=void 0;else{let e=s(t.host);if(typeof e?.grantId!=`string`||!Number.isFinite(e.expiresAt))return o(`Desktop did not issue a complete grant.`,502);this.grantId=e.grantId,this.expiresAt=e.expiresAt,this.actionSequence=0,this.phase=`active`}}else this.phase=`inactive`,this.grantId=void 0,this.expiresAt=void 0,this.activation=void 0,this.artifact=u(t.artifact);return this.changed(),Response.json(this.state())}return o(`Not found.`,404)}close(){this.closed=!0,this.pending?.reject(Error(`Computer-use broker closed.`)),this.pending=void 0,this.grantId=void 0,this.expiresAt=void 0}};function f(e={}){return new d(e)}const p={basePath:e,start(e){return f({...e.sessionId===void 0?{}:{sessionId:e.sessionId},...e.internalToken===void 0?{}:{internalToken:e.internalToken},...e.hubToken===void 0?{}:{hubToken:e.hubToken}})}};export{d as ComputerUseRequestBroker,p as api,f as createComputerUseApi};
2
+ //# sourceMappingURL=computerUseApi.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"computerUseApi.mjs","names":[],"sources":["../../src/adapters/computerUseApi.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto';\nimport {\n doomApiCallerFrom,\n type DoomApi,\n type DoomApiContext,\n type DoomApiHandler,\n} from '@agimon-ai/doompi-extension-contracts/package-api';\nimport {\n API_BASE_PATH,\n COMPUTER_USE_CONFIRMATION_WINDOW_MS,\n COMPUTER_USE_MAX_DURATION_MS,\n COMPUTER_USE_ROUTES,\n COMPUTER_USE_WAKE_LIMIT,\n type ComputerUseActivationRequest,\n type ComputerUseArtifactView,\n type ComputerUseBrokerRequest,\n type ComputerUseSessionView,\n} from '../types/computerUseApi.ts';\n\ninterface PendingRequest {\n readonly request: ComputerUseBrokerRequest;\n resolve(value: unknown): void;\n reject(error: Error): void;\n}\n\nfunction jsonError(message: string, status: number): Response {\n return Response.json({ error: message }, { status });\n}\n\nfunction record(value: unknown): Record<string, unknown> | undefined {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : undefined;\n}\n\nasync function body(request: Request): Promise<Record<string, unknown>> {\n try {\n return record(await request.json()) ?? {};\n } catch {\n return {};\n }\n}\n\nfunction semanticAction(value: Record<string, unknown>): boolean {\n const base =\n typeof value.snapshotId === 'string' &&\n value.snapshotId.length > 0 &&\n typeof value.elementRef === 'string' &&\n value.elementRef.length > 0;\n if (!base) return false;\n const allowed = (keys: readonly string[]) => Object.keys(value).every((key) => keys.includes(key));\n if (value.kind === 'press') return allowed(['kind', 'snapshotId', 'elementRef']);\n if (value.kind === 'set_value')\n return typeof value.value === 'string' && allowed(['kind', 'snapshotId', 'elementRef', 'value']);\n if (value.kind === 'scroll')\n return (\n ['up', 'down', 'left', 'right'].includes(value.direction as string) &&\n (value.amount === 'line' || value.amount === 'page') &&\n allowed(['kind', 'snapshotId', 'elementRef', 'direction', 'amount'])\n );\n return false;\n}\nfunction artifactView(value: unknown): ComputerUseArtifactView | undefined {\n const input = record(value);\n if (typeof input?.artifactId !== 'string' || (input.status !== 'ready' && input.status !== 'failed'))\n return undefined;\n const safeUrl = (candidate: unknown) =>\n typeof candidate === 'string' && candidate.startsWith('/api/') ? candidate : undefined;\n const downloadUrl = safeUrl(input.downloadUrl);\n const previewUrl = safeUrl(input.previewUrl);\n return {\n artifactId: input.artifactId,\n status: input.status,\n ...(downloadUrl === undefined ? {} : { downloadUrl }),\n ...(previewUrl === undefined ? {} : { previewUrl }),\n ...(typeof input.actionCount === 'number' ? { actionCount: input.actionCount } : {}),\n ...(typeof input.completedAt === 'string' ? { completedAt: input.completedAt } : {}),\n };\n}\n\nexport interface ComputerUseApiOptions {\n readonly sessionId?: string;\n readonly internalToken?: string;\n readonly hubToken?: string;\n}\n\nexport class ComputerUseRequestBroker implements DoomApiHandler {\n private readonly sessionId: string;\n private readonly internalToken?: string;\n private readonly hubToken?: string;\n private revision = 0;\n private wake = 0;\n private phase: ComputerUseSessionView['phase'] = 'inactive';\n private activation?: ComputerUseActivationRequest;\n private grantId?: string;\n private expiresAt?: number;\n private actionSequence = 0;\n private failure?: ComputerUseSessionView['failure'];\n private artifact?: ComputerUseArtifactView;\n private pending?: PendingRequest;\n private closed = false;\n\n public constructor(options: ComputerUseApiOptions) {\n this.sessionId = options.sessionId ?? 'unknown';\n this.internalToken = options.internalToken;\n this.hubToken = options.hubToken;\n }\n\n public state(): ComputerUseSessionView {\n return Object.freeze({\n sessionId: this.sessionId,\n revision: this.revision,\n wake: this.wake,\n phase: this.phase,\n ...(this.activation === undefined\n ? {}\n : {\n requestId: this.activation.requestId,\n target: this.activation.target,\n durationMs: this.activation.durationSeconds * 1_000,\n }),\n ...(this.expiresAt === undefined ? {} : { expiresAt: this.expiresAt }),\n ...(this.failure === undefined ? {} : { failure: this.failure }),\n ...(this.artifact === undefined ? {} : { artifact: this.artifact }),\n });\n }\n\n private changed(): void {\n this.revision += 1;\n this.wake = (this.wake + 1) % COMPUTER_USE_WAKE_LIMIT;\n }\n\n private authorized(request: Request, token: string | undefined): boolean {\n return token !== undefined && request.headers.get('authorization') === `Bearer ${token}`;\n }\n\n private async requestActivation(request: Request): Promise<Response> {\n const caller = doomApiCallerFrom(request.headers);\n if (caller === undefined || (caller.locality === 'remote' && caller.stepUp === 'not-required'))\n return jsonError('Not found.', 404);\n if (this.phase !== 'inactive' && this.phase !== 'failed') return jsonError('Computer use is already busy.', 409);\n const input = await body(request);\n const target = record(input.target);\n const durationMs = input.durationMs;\n if (target === undefined || typeof target.windowId !== 'string' || typeof target.bundleId !== 'string')\n return jsonError('A Desktop target is required.', 400);\n if (\n typeof durationMs !== 'number' ||\n !Number.isInteger(durationMs) ||\n durationMs < 1_000 ||\n durationMs > COMPUTER_USE_MAX_DURATION_MS\n )\n return jsonError('The requested duration is invalid.', 400);\n const createdAt = Date.now();\n this.activation = Object.freeze({\n requestId: randomUUID(),\n target: Object.freeze({ ...target }),\n durationSeconds: durationMs / 1_000,\n createdAt,\n confirmationExpiresAt: createdAt + COMPUTER_USE_CONFIRMATION_WINDOW_MS,\n caller: Object.freeze({ ...caller }),\n });\n this.phase = 'awaiting_confirmation';\n this.failure = undefined;\n this.artifact = undefined;\n this.changed();\n return Response.json(this.state(), { status: 202 });\n }\n\n private async enqueue(operation: ComputerUseBrokerRequest['operation'], payload?: unknown): Promise<Response> {\n if (this.phase !== 'active' || this.grantId === undefined) return jsonError('Computer use is not active.', 409);\n if (this.pending !== undefined) return jsonError('Another computer-use request is live.', 409);\n const sequence = operation === 'act' ? ++this.actionSequence : undefined;\n const request: ComputerUseBrokerRequest = {\n id: randomUUID(),\n operation,\n grantId: this.grantId,\n ...(sequence === undefined ? {} : { sequence }),\n ...(payload === undefined ? {} : { payload }),\n };\n const completion = new Promise<unknown>((resolve, reject) => {\n this.pending = { request, resolve, reject };\n });\n this.changed();\n try {\n return Response.json(await completion);\n } catch (error) {\n return jsonError(error instanceof Error ? error.message : String(error), 502);\n }\n }\n\n public async fetch(request: Request): Promise<Response> {\n if (this.closed) return jsonError('Computer-use broker is closed.', 503);\n const path = new URL(request.url).pathname;\n if (request.method === 'POST' && path === COMPUTER_USE_ROUTES.activate) return this.requestActivation(request);\n const agent = path.startsWith('/agent/');\n const hub = path.startsWith('/hub/');\n if ((agent && !this.authorized(request, this.internalToken)) || (hub && !this.authorized(request, this.hubToken)))\n return jsonError('Not found.', 404);\n\n if (request.method === 'GET' && (path === COMPUTER_USE_ROUTES.agentState || path === COMPUTER_USE_ROUTES.hubState))\n return Response.json(this.state());\n if (request.method === 'POST' && path === COMPUTER_USE_ROUTES.agentObserve) return this.enqueue('observe');\n if (request.method === 'POST' && path === COMPUTER_USE_ROUTES.agentAction) {\n const action = await body(request);\n if (!semanticAction(action)) return jsonError('A valid semantic action is required.', 400);\n return this.enqueue('act', action);\n }\n if (request.method === 'POST' && path === COMPUTER_USE_ROUTES.agentStop) {\n if (this.phase !== 'active') return jsonError('Computer use is not active.', 409);\n this.phase = 'stopping';\n this.changed();\n return Response.json(this.state(), { status: 202 });\n }\n if (request.method === 'GET' && path === COMPUTER_USE_ROUTES.hubActivation) {\n if (this.activation === undefined || this.phase !== 'awaiting_confirmation') return Response.json(null);\n this.phase = 'activating';\n this.changed();\n return Response.json(this.activation);\n }\n if (request.method === 'GET' && path === COMPUTER_USE_ROUTES.hubAuthorization)\n return Response.json(this.grantId === undefined ? null : { grantId: this.grantId, expiresAt: this.expiresAt });\n if (request.method === 'GET' && path === COMPUTER_USE_ROUTES.hubNext)\n return Response.json(this.pending?.request ?? null);\n if (request.method === 'POST' && path === COMPUTER_USE_ROUTES.hubComplete) {\n const input = await body(request);\n const id = typeof input.id === 'string' ? input.id : undefined;\n if (this.pending === undefined || this.pending.request.id !== id) return jsonError('The request is stale.', 409);\n const pending = this.pending;\n this.pending = undefined;\n this.changed();\n if (typeof input.error === 'string') pending.reject(new Error(input.error));\n else pending.resolve(input.result);\n return Response.json(this.state());\n }\n if (request.method === 'POST' && path === COMPUTER_USE_ROUTES.hubStop) {\n const input = await body(request);\n if (this.phase === 'activating') {\n if (typeof input.error === 'string') {\n this.phase = 'failed';\n this.failure = { code: 'desktop_unavailable', message: input.error.slice(0, 512) };\n this.activation = undefined;\n } else {\n const host = record(input.host);\n if (typeof host?.grantId !== 'string' || !Number.isFinite(host.expiresAt))\n return jsonError('Desktop did not issue a complete grant.', 502);\n this.grantId = host.grantId;\n this.expiresAt = host.expiresAt as number;\n this.actionSequence = 0;\n this.phase = 'active';\n }\n } else {\n this.phase = 'inactive';\n this.grantId = undefined;\n this.expiresAt = undefined;\n this.activation = undefined;\n this.artifact = artifactView(input.artifact);\n }\n this.changed();\n return Response.json(this.state());\n }\n return jsonError('Not found.', 404);\n }\n\n public close(): void {\n this.closed = true;\n this.pending?.reject(new Error('Computer-use broker closed.'));\n this.pending = undefined;\n this.grantId = undefined;\n this.expiresAt = undefined;\n }\n}\n\nexport function createComputerUseApi(options: ComputerUseApiOptions = {}): ComputerUseRequestBroker {\n return new ComputerUseRequestBroker(options);\n}\n\nexport const api: DoomApi = {\n basePath: API_BASE_PATH,\n start(context: DoomApiContext): DoomApiHandler {\n return createComputerUseApi({\n ...(context.sessionId === undefined ? {} : { sessionId: context.sessionId }),\n ...(context.internalToken === undefined ? {} : { internalToken: context.internalToken }),\n ...(context.hubToken === undefined ? {} : { hubToken: context.hubToken }),\n });\n },\n};\n"],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ const e=require("../../commands/computerUseCommand.cjs"),t=require("../../types/computerUseApi.cjs"),n=require("../../container/index.cjs");let r=require("@agimon-ai/doompi-extension-contracts/cordis-host"),i=require("@agimon-ai/doompi-extension-contracts/mode");const a=`@agimon-ai/doompi-computer-use`,o=[`computer_state`,`computer_action`],s=`[COMPUTER USE ACTIVE]
2
+ 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, set_value, or scroll at a time. Never infer coordinates, inspect another application, bypass secure elements, or retry an uncertain outcome. Stop computer use when the task is complete.`;function c(e,t=!1){let n=e?.phase??`inactive`,r=t||n!==`inactive`&&n!==`failed`;return{activation:r?n===`stopping`?`deactivating`:n===`awaiting_confirmation`||n===`activating`?`activating`:`active`:`inactive`,condition:n===`awaiting_confirmation`?`blocked`:n===`failed`?`failed`:n===`activating`||n===`stopping`?`queued`:`ready`,...r&&n===`inactive`?{detail:`configure computer use in Activity`}:{},...n===`awaiting_confirmation`?{detail:`awaiting confirmation in Activity`}:{},actions:[{id:`activate`,enabled:!r,...r?{disabledReason:`Computer use is already enabled.`}:{}},{id:`deactivate`,enabled:r,...r?{}:{disabledReason:`Computer use is not enabled.`}},{id:`doctor`,enabled:!0}]}}function l(e,t){let n=new Set(o),r=e.getActiveTools(),i=r.filter(e=>!n.has(e));t&&i.push(...o),(i.length!==r.length||i.some((e,t)=>e!==r[t]))&&e.setActiveTools(i)}function u(r,o,u=n.createComputerUseContainer()){let d=u.client,f,p=!1,m,h,g,_=``,v,y,b=()=>{let e=f?.phase??`inactive`,n=`${p}:${e}:${f?.revision??`none`}`;m!==void 0&&n!==_&&(m.publish(c(f,p)),_=n);let r=f===void 0?void 0:p||e!==`inactive`?e:``;g!==void 0&&r!==v&&(g.ui.setStatus(t.COMPUTER_USE_MODE_STATUS_KEY,r),v=r);let i=p||e!==`inactive`?`computer use: ${e}`:void 0;g!==void 0&&i!==y&&(g.ui.setStatus(t.COMPUTER_USE_STATUS_KEY,i),y=i)},x=async()=>{if(d===void 0){f=void 0,l(o,!1),b();return}try{f=await d.state(),l(o,f.phase===`active`),b()}catch{f=void 0,l(o,!1),b()}};o.registerTool({name:`computer_state`,label:`Computer State`,description:`Observe the authorized application window and return its semantic accessibility state.`,promptSnippet:`Observe the authorized application before choosing a semantic action`,parameters:{type:`object`,properties:{},additionalProperties:!1},async execute(e,t,n){if(d===void 0||f?.phase!==`active`)throw Error(`Computer use is not active for this session.`);let r=await d.observe(n);return{content:[{type:`text`,text:JSON.stringify(r,null,2)}],details:r}}}),o.registerTool({name:`computer_action`,label:`Computer Action`,description:`Perform one constrained semantic action in the authorized application window.`,promptSnippet:`Perform one action using a current computer_state snapshot and element ref`,parameters:{type:`object`,properties:{kind:{type:`string`,enum:[`press`,`set_value`,`scroll`]},snapshotId:{type:`string`},elementRef:{type:`string`},value:{type:`string`},direction:{type:`string`,enum:[`up`,`down`,`left`,`right`]},amount:{type:`string`,enum:[`line`,`page`]}},required:[`kind`,`snapshotId`,`elementRef`],additionalProperties:!1},async execute(e,t,n){if(d===void 0||f?.phase!==`active`)throw Error(`Computer use is not active for this session.`);let r=await d.act(t,n);return{content:[{type:`text`,text:JSON.stringify(r,null,2)}],details:r}}}),r.inject([i.DOOM_MINOR_MODE_CATALOG_SERVICE],e=>{let n=(0,i.registerMinorModeOwner)((0,i.requireMinorModeCatalog)(e),{descriptor:{source:a,id:t.COMPUTER_USE_MODE_ID,label:`Computer Use`,description:`Session-scoped semantic control through DoomPi Desktop.`,order:450,actions:[{id:`activate`,label:`Activate`,description:`Open the cockpit activation workflow and native confirmation.`,contexts:[`tui`,`headless`],parameters:[]},{id:`deactivate`,label:`Deactivate`,description:`Stop this session computer-use run.`,contexts:[`tui`,`headless`],parameters:[]},{id:`doctor`,label:`Doctor`,description:`Report Desktop availability and session state.`,contexts:[`tui`,`headless`],parameters:[]}]},initialState:c(f,p),async handleAction(e,t,n){if(g=n.context,e===`activate`){if(d===void 0)throw Error(`DoomPi Desktop computer use is unavailable.`);return p=!0,await x(),b(),{message:`Computer use is ready to configure in Activity.`}}if(e===`doctor`)return await x(),{message:d===void 0?`DoomPi Desktop session API is unavailable.`:`Computer use is ${f?.phase.replaceAll(`_`,` `)??`unavailable`}.`};if(e===`deactivate`){if(d===void 0)throw Error(`DoomPi Desktop computer use is unavailable.`);return f!==void 0&&f.phase!==`inactive`&&f.phase!==`failed`&&await d.stop(n.signal),p=!1,await x(),b(),{message:`Computer use is off.`}}throw Error(`Unknown computer-use action: ${e}`)}});return m=n,()=>{n.dispose(),m===n&&(m=void 0)}}),o.on(`before_agent_start`,e=>f?.phase===`active`?{systemPrompt:`${e.systemPrompt}\n\n${s}`}:void 0),o.on(`session_start`,(e,t)=>{g=t,l(o,!1),x(),h&&clearInterval(h),h=setInterval(()=>void x(),250),h.unref?.()}),r.effect(()=>()=>{h&&clearInterval(h),h=void 0,l(o,!1),g?.ui.setStatus(t.COMPUTER_USE_MODE_STATUS_KEY,void 0),g?.ui.setStatus(t.COMPUTER_USE_STATUS_KEY,void 0),g=void 0,m?.dispose(),m=void 0},`${a}/runtime`),e.registerComputerUseCommand(o,u.service)}function d(e,t){u(e,t.pi,t.dependencies)}async function f(e,t=n.createComputerUseContainer()){let i=await(0,r.connectDoomCordisHost)(e,a,{allowStandalone:!0}),o=i.root.plugin(d,{pi:e,dependencies:t});try{await o}catch(e){try{await o.dispose()}finally{await i.dispose()}throw e}let s;e.on(`session_shutdown`,()=>s??=(async()=>{try{await o.dispose()}finally{await i.dispose()}})())}exports.COMPUTER_USE_GUIDANCE=s,exports.COMPUTER_USE_MODE_ID=t.COMPUTER_USE_MODE_ID,exports.COMPUTER_USE_TOOL_NAMES=o,exports.activateComputerUseExtension=f,exports.default=f,exports.installComputerUseRuntime=u,exports.modeState=c,exports.reconcileTools=l;
3
+ //# sourceMappingURL=extension.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extension.cjs","names":["createComputerUseContainer","COMPUTER_USE_MODE_STATUS_KEY","COMPUTER_USE_STATUS_KEY","DOOM_MINOR_MODE_CATALOG_SERVICE","registerMinorModeOwner","requireMinorModeCatalog","COMPUTER_USE_MODE_ID","connectDoomCordisHost"],"sources":["../../../src/adapters/pi/extension.ts"],"sourcesContent":["import { connectDoomCordisHost } from '@agimon-ai/doompi-extension-contracts/cordis-host';\nimport {\n DOOM_MINOR_MODE_CATALOG_SERVICE,\n type MinorModeOwnerHandle,\n type MinorModeState,\n registerMinorModeOwner,\n requireMinorModeCatalog,\n} from '@agimon-ai/doompi-extension-contracts/mode';\nimport type { Context } from '@deepseek-ai/cordis';\nimport type { ExtensionAPI, ExtensionContext } from '@earendil-works/pi-coding-agent';\nimport { registerComputerUseCommand } from '../../commands/computerUseCommand.ts';\nimport { createComputerUseContainer } from '../../container/index.ts';\nimport {\n COMPUTER_USE_MODE_ID,\n COMPUTER_USE_MODE_STATUS_KEY,\n COMPUTER_USE_STATUS_KEY,\n type ComputerUseSessionView,\n} from '../../types/computerUseApi.ts';\nimport type { ComputerUseAction } from '../../types/computerUse.ts';\nimport type { ComputerUseExtensionDependencies } from '../../types/extension.ts';\n\nconst PACKAGE_SOURCE = '@agimon-ai/doompi-computer-use';\nexport { COMPUTER_USE_MODE_ID };\nexport const COMPUTER_USE_TOOL_NAMES = ['computer_state', 'computer_action'] as const;\nexport 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, set_value, or scroll at a time. Never infer coordinates, inspect another application, bypass secure elements, or retry an uncertain outcome. Stop computer use when the task is complete.`;\n\nexport function modeState(state?: ComputerUseSessionView, enabled = false): MinorModeState {\n const phase = state?.phase ?? 'inactive';\n const running = phase !== 'inactive' && phase !== 'failed';\n const modeEnabled = enabled || running;\n const activation = modeEnabled\n ? phase === 'stopping'\n ? 'deactivating'\n : phase === 'awaiting_confirmation' || phase === 'activating'\n ? 'activating'\n : 'active'\n : 'inactive';\n return {\n activation,\n condition:\n phase === 'awaiting_confirmation'\n ? 'blocked'\n : phase === 'failed'\n ? 'failed'\n : phase === 'activating' || phase === 'stopping'\n ? 'queued'\n : 'ready',\n ...(modeEnabled && phase === 'inactive' ? { detail: 'configure computer use in Activity' } : {}),\n ...(phase === 'awaiting_confirmation' ? { detail: 'awaiting confirmation in Activity' } : {}),\n actions: [\n {\n id: 'activate',\n enabled: !modeEnabled,\n ...(!modeEnabled ? {} : { disabledReason: 'Computer use is already enabled.' }),\n },\n {\n id: 'deactivate',\n enabled: modeEnabled,\n ...(modeEnabled ? {} : { disabledReason: 'Computer use is not enabled.' }),\n },\n { id: 'doctor', enabled: true },\n ],\n };\n}\n\nexport function reconcileTools(pi: Pick<ExtensionAPI, 'getActiveTools' | 'setActiveTools'>, active: boolean): void {\n const owned = new Set<string>(COMPUTER_USE_TOOL_NAMES);\n const current = pi.getActiveTools();\n const next = current.filter((name) => !owned.has(name));\n if (active) next.push(...COMPUTER_USE_TOOL_NAMES);\n if (next.length !== current.length || next.some((name, index) => name !== current[index])) pi.setActiveTools(next);\n}\n\nexport function installComputerUseRuntime(\n cordis: Context,\n pi: ExtensionAPI,\n dependencies: ComputerUseExtensionDependencies = createComputerUseContainer(),\n): void {\n const client = dependencies.client;\n let state: ComputerUseSessionView | undefined;\n let enabled = false;\n let mode: MinorModeOwnerHandle | undefined;\n let timer: ReturnType<typeof setInterval> | undefined;\n let activeContext: ExtensionContext | undefined;\n let publishedMode = '';\n let publishedModeStatus: string | undefined;\n let publishedActivityStatus: string | undefined;\n\n const publish = (): void => {\n const phase = state?.phase ?? 'inactive';\n const projection = `${enabled}:${phase}:${state?.revision ?? 'none'}`;\n if (mode !== undefined && projection !== publishedMode) {\n mode.publish(modeState(state, enabled));\n publishedMode = projection;\n }\n const modeStatus = state === undefined ? undefined : enabled || phase !== 'inactive' ? phase : '';\n if (activeContext !== undefined && modeStatus !== publishedModeStatus) {\n activeContext.ui.setStatus(COMPUTER_USE_MODE_STATUS_KEY, modeStatus);\n publishedModeStatus = modeStatus;\n }\n const activityStatus = enabled || phase !== 'inactive' ? `computer use: ${phase}` : undefined;\n if (activeContext !== undefined && activityStatus !== publishedActivityStatus) {\n activeContext.ui.setStatus(COMPUTER_USE_STATUS_KEY, activityStatus);\n publishedActivityStatus = activityStatus;\n }\n };\n const refresh = async (): Promise<void> => {\n if (client === undefined) {\n state = undefined;\n reconcileTools(pi, false);\n publish();\n return;\n }\n try {\n state = await client.state();\n reconcileTools(pi, state.phase === 'active');\n publish();\n } catch {\n state = undefined;\n reconcileTools(pi, false);\n publish();\n }\n };\n\n pi.registerTool({\n name: 'computer_state',\n label: 'Computer State',\n description: 'Observe the authorized application window and return its semantic accessibility state.',\n promptSnippet: 'Observe the authorized application before choosing a semantic action',\n parameters: { type: 'object', properties: {}, additionalProperties: false },\n async execute(_toolCallId, _params, signal) {\n if (client === undefined || state?.phase !== 'active')\n throw new Error('Computer use is not active for this session.');\n const observation = await client.observe(signal);\n return { content: [{ type: 'text', text: JSON.stringify(observation, null, 2) }], details: observation };\n },\n });\n pi.registerTool({\n name: 'computer_action',\n label: 'Computer Action',\n description: 'Perform one constrained semantic action in the authorized application window.',\n promptSnippet: 'Perform one action using a current computer_state snapshot and element ref',\n parameters: {\n type: 'object',\n properties: {\n kind: { type: 'string', enum: ['press', 'set_value', 'scroll'] },\n snapshotId: { type: 'string' },\n elementRef: { type: 'string' },\n value: { type: 'string' },\n direction: { type: 'string', enum: ['up', 'down', 'left', 'right'] },\n amount: { type: 'string', enum: ['line', 'page'] },\n },\n required: ['kind', 'snapshotId', 'elementRef'],\n additionalProperties: false,\n },\n async execute(_toolCallId, params, signal) {\n if (client === undefined || state?.phase !== 'active')\n throw new Error('Computer use is not active for this session.');\n const result = await client.act(params as unknown as ComputerUseAction, signal);\n return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }], details: result };\n },\n });\n\n cordis.inject([DOOM_MINOR_MODE_CATALOG_SERVICE], (context) => {\n const owner = registerMinorModeOwner<ExtensionContext>(requireMinorModeCatalog(context), {\n descriptor: {\n source: PACKAGE_SOURCE,\n id: COMPUTER_USE_MODE_ID,\n label: 'Computer Use',\n description: 'Session-scoped semantic control through DoomPi Desktop.',\n order: 450,\n actions: [\n {\n id: 'activate',\n label: 'Activate',\n description: 'Open the cockpit activation workflow and native confirmation.',\n contexts: ['tui', 'headless'],\n parameters: [],\n },\n {\n id: 'deactivate',\n label: 'Deactivate',\n description: 'Stop this session computer-use run.',\n contexts: ['tui', 'headless'],\n parameters: [],\n },\n {\n id: 'doctor',\n label: 'Doctor',\n description: 'Report Desktop availability and session state.',\n contexts: ['tui', 'headless'],\n parameters: [],\n },\n ],\n },\n initialState: modeState(state, enabled),\n async handleAction(actionId, _argumentsValue, execution) {\n activeContext = execution.context;\n if (actionId === 'activate') {\n if (client === undefined) throw new Error('DoomPi Desktop computer use is unavailable.');\n enabled = true;\n await refresh();\n publish();\n return { message: 'Computer use is ready to configure in Activity.' };\n }\n if (actionId === 'doctor') {\n await refresh();\n return {\n message:\n client === undefined\n ? 'DoomPi Desktop session API is unavailable.'\n : `Computer use is ${state?.phase.replaceAll('_', ' ') ?? 'unavailable'}.`,\n };\n }\n if (actionId === 'deactivate') {\n if (client === undefined) throw new Error('DoomPi Desktop computer use is unavailable.');\n if (state !== undefined && state.phase !== 'inactive' && state.phase !== 'failed')\n await client.stop(execution.signal);\n enabled = false;\n await refresh();\n publish();\n return { message: 'Computer use is off.' };\n }\n throw new Error(`Unknown computer-use action: ${actionId}`);\n },\n });\n mode = owner;\n return () => {\n owner.dispose();\n if (mode === owner) mode = undefined;\n };\n });\n\n pi.on('before_agent_start', (event) =>\n state?.phase === 'active' ? { systemPrompt: `${event.systemPrompt}\\n\\n${COMPUTER_USE_GUIDANCE}` } : undefined,\n );\n pi.on('session_start', (_event, context) => {\n activeContext = context;\n reconcileTools(pi, false);\n void refresh();\n if (timer) clearInterval(timer);\n timer = setInterval(() => void refresh(), 250);\n timer.unref?.();\n });\n cordis.effect(\n () => () => {\n if (timer) clearInterval(timer);\n timer = undefined;\n reconcileTools(pi, false);\n activeContext?.ui.setStatus(COMPUTER_USE_MODE_STATUS_KEY, undefined);\n activeContext?.ui.setStatus(COMPUTER_USE_STATUS_KEY, undefined);\n activeContext = undefined;\n mode?.dispose();\n mode = undefined;\n },\n `${PACKAGE_SOURCE}/runtime`,\n );\n\n registerComputerUseCommand(pi, dependencies.service);\n}\n\ninterface ComputerUsePluginConfig {\n readonly pi: ExtensionAPI;\n readonly dependencies: ComputerUseExtensionDependencies;\n}\n\nfunction computerUsePlugin(cordis: Context, config: ComputerUsePluginConfig): void {\n installComputerUseRuntime(cordis, config.pi, config.dependencies);\n}\n\nexport async function activateComputerUseExtension(\n pi: ExtensionAPI,\n dependencies: ComputerUseExtensionDependencies = createComputerUseContainer(),\n): Promise<void> {\n const connection = await connectDoomCordisHost(pi, PACKAGE_SOURCE, { allowStandalone: true });\n const fiber = connection.root.plugin(computerUsePlugin, { pi, dependencies });\n try {\n await fiber;\n } catch (error) {\n try {\n await fiber.dispose();\n } finally {\n await connection.dispose();\n }\n throw error;\n }\n let disposal: Promise<void> | undefined;\n pi.on(\n 'session_shutdown',\n () =>\n (disposal ??= (async () => {\n try {\n await fiber.dispose();\n } finally {\n await connection.dispose();\n }\n })()),\n );\n}\n\nexport default activateComputerUseExtension;\n"],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import { COMPUTER_USE_MODE_ID } from "../../types/computerUseApi.cjs";
2
+ import { ComputerUseExtensionDependencies } from "../../types/extension.cjs";
3
+ import "@agimon-ai/doompi-extension-contracts/mode";
4
+ import "@deepseek-ai/cordis";
5
+ import { ExtensionAPI } from "@earendil-works/pi-coding-agent";
6
+ //#region src/adapters/pi/extension.d.ts
7
+ declare const COMPUTER_USE_TOOL_NAMES: readonly ['computer_state', 'computer_action'];
8
+ declare 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, set_value, or scroll at a time. Never infer coordinates, inspect another application, bypass secure elements, or retry an uncertain outcome. Stop computer use when the task is complete.";
9
+ declare function activateComputerUseExtension(pi: ExtensionAPI, dependencies?: ComputerUseExtensionDependencies): Promise<void>;
10
+ //#endregion
11
+ export { COMPUTER_USE_GUIDANCE, COMPUTER_USE_MODE_ID, COMPUTER_USE_TOOL_NAMES, activateComputerUseExtension, activateComputerUseExtension as default };
12
+ //# sourceMappingURL=extension.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extension.d.cts","names":[],"sources":["../../../src/adapters/pi/extension.ts"],"mappings":";;;;;;cAuBa;cACA;iBAuPS,6BACpB,IAAI,cACJ,eAAc,mCACb"}
@@ -0,0 +1,12 @@
1
+ import { COMPUTER_USE_MODE_ID } from "../../types/computerUseApi.mjs";
2
+ import { ComputerUseExtensionDependencies } from "../../types/extension.mjs";
3
+ import "@agimon-ai/doompi-extension-contracts/mode";
4
+ import "@deepseek-ai/cordis";
5
+ import { ExtensionAPI } from "@earendil-works/pi-coding-agent";
6
+ //#region src/adapters/pi/extension.d.ts
7
+ declare const COMPUTER_USE_TOOL_NAMES: readonly ['computer_state', 'computer_action'];
8
+ declare 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, set_value, or scroll at a time. Never infer coordinates, inspect another application, bypass secure elements, or retry an uncertain outcome. Stop computer use when the task is complete.";
9
+ declare function activateComputerUseExtension(pi: ExtensionAPI, dependencies?: ComputerUseExtensionDependencies): Promise<void>;
10
+ //#endregion
11
+ export { COMPUTER_USE_GUIDANCE, COMPUTER_USE_MODE_ID, COMPUTER_USE_TOOL_NAMES, activateComputerUseExtension, activateComputerUseExtension as default };
12
+ //# sourceMappingURL=extension.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extension.d.mts","names":[],"sources":["../../../src/adapters/pi/extension.ts"],"mappings":";;;;;;cAuBa;cACA;iBAuPS,6BACpB,IAAI,cACJ,eAAc,mCACb"}
@@ -0,0 +1,3 @@
1
+ import{registerComputerUseCommand as e}from"../../commands/computerUseCommand.mjs";import{COMPUTER_USE_MODE_ID as t,COMPUTER_USE_MODE_STATUS_KEY as n,COMPUTER_USE_STATUS_KEY as r}from"../../types/computerUseApi.mjs";import{createComputerUseContainer as i}from"../../container/index.mjs";import{connectDoomCordisHost as a}from"@agimon-ai/doompi-extension-contracts/cordis-host";import{DOOM_MINOR_MODE_CATALOG_SERVICE as o,registerMinorModeOwner as s,requireMinorModeCatalog as c}from"@agimon-ai/doompi-extension-contracts/mode";const l=`@agimon-ai/doompi-computer-use`,u=[`computer_state`,`computer_action`],d=`[COMPUTER USE ACTIVE]
2
+ 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, set_value, or scroll at a time. Never infer coordinates, inspect another application, bypass secure elements, or retry an uncertain outcome. Stop computer use when the task is complete.`;function f(e,t=!1){let n=e?.phase??`inactive`,r=t||n!==`inactive`&&n!==`failed`;return{activation:r?n===`stopping`?`deactivating`:n===`awaiting_confirmation`||n===`activating`?`activating`:`active`:`inactive`,condition:n===`awaiting_confirmation`?`blocked`:n===`failed`?`failed`:n===`activating`||n===`stopping`?`queued`:`ready`,...r&&n===`inactive`?{detail:`configure computer use in Activity`}:{},...n===`awaiting_confirmation`?{detail:`awaiting confirmation in Activity`}:{},actions:[{id:`activate`,enabled:!r,...r?{disabledReason:`Computer use is already enabled.`}:{}},{id:`deactivate`,enabled:r,...r?{}:{disabledReason:`Computer use is not enabled.`}},{id:`doctor`,enabled:!0}]}}function p(e,t){let n=new Set(u),r=e.getActiveTools(),i=r.filter(e=>!n.has(e));t&&i.push(...u),(i.length!==r.length||i.some((e,t)=>e!==r[t]))&&e.setActiveTools(i)}function m(a,u,m=i()){let h=m.client,g,_=!1,v,y,b,x=``,S,C,w=()=>{let e=g?.phase??`inactive`,t=`${_}:${e}:${g?.revision??`none`}`;v!==void 0&&t!==x&&(v.publish(f(g,_)),x=t);let i=g===void 0?void 0:_||e!==`inactive`?e:``;b!==void 0&&i!==S&&(b.ui.setStatus(n,i),S=i);let a=_||e!==`inactive`?`computer use: ${e}`:void 0;b!==void 0&&a!==C&&(b.ui.setStatus(r,a),C=a)},T=async()=>{if(h===void 0){g=void 0,p(u,!1),w();return}try{g=await h.state(),p(u,g.phase===`active`),w()}catch{g=void 0,p(u,!1),w()}};u.registerTool({name:`computer_state`,label:`Computer State`,description:`Observe the authorized application window and return its semantic accessibility state.`,promptSnippet:`Observe the authorized application before choosing a semantic action`,parameters:{type:`object`,properties:{},additionalProperties:!1},async execute(e,t,n){if(h===void 0||g?.phase!==`active`)throw Error(`Computer use is not active for this session.`);let r=await h.observe(n);return{content:[{type:`text`,text:JSON.stringify(r,null,2)}],details:r}}}),u.registerTool({name:`computer_action`,label:`Computer Action`,description:`Perform one constrained semantic action in the authorized application window.`,promptSnippet:`Perform one action using a current computer_state snapshot and element ref`,parameters:{type:`object`,properties:{kind:{type:`string`,enum:[`press`,`set_value`,`scroll`]},snapshotId:{type:`string`},elementRef:{type:`string`},value:{type:`string`},direction:{type:`string`,enum:[`up`,`down`,`left`,`right`]},amount:{type:`string`,enum:[`line`,`page`]}},required:[`kind`,`snapshotId`,`elementRef`],additionalProperties:!1},async execute(e,t,n){if(h===void 0||g?.phase!==`active`)throw Error(`Computer use is not active for this session.`);let r=await h.act(t,n);return{content:[{type:`text`,text:JSON.stringify(r,null,2)}],details:r}}}),a.inject([o],e=>{let n=s(c(e),{descriptor:{source:l,id:t,label:`Computer Use`,description:`Session-scoped semantic control through DoomPi Desktop.`,order:450,actions:[{id:`activate`,label:`Activate`,description:`Open the cockpit activation workflow and native confirmation.`,contexts:[`tui`,`headless`],parameters:[]},{id:`deactivate`,label:`Deactivate`,description:`Stop this session computer-use run.`,contexts:[`tui`,`headless`],parameters:[]},{id:`doctor`,label:`Doctor`,description:`Report Desktop availability and session state.`,contexts:[`tui`,`headless`],parameters:[]}]},initialState:f(g,_),async handleAction(e,t,n){if(b=n.context,e===`activate`){if(h===void 0)throw Error(`DoomPi Desktop computer use is unavailable.`);return _=!0,await T(),w(),{message:`Computer use is ready to configure in Activity.`}}if(e===`doctor`)return await T(),{message:h===void 0?`DoomPi Desktop session API is unavailable.`:`Computer use is ${g?.phase.replaceAll(`_`,` `)??`unavailable`}.`};if(e===`deactivate`){if(h===void 0)throw Error(`DoomPi Desktop computer use is unavailable.`);return g!==void 0&&g.phase!==`inactive`&&g.phase!==`failed`&&await h.stop(n.signal),_=!1,await T(),w(),{message:`Computer use is off.`}}throw Error(`Unknown computer-use action: ${e}`)}});return v=n,()=>{n.dispose(),v===n&&(v=void 0)}}),u.on(`before_agent_start`,e=>g?.phase===`active`?{systemPrompt:`${e.systemPrompt}\n\n${d}`}:void 0),u.on(`session_start`,(e,t)=>{b=t,p(u,!1),T(),y&&clearInterval(y),y=setInterval(()=>void T(),250),y.unref?.()}),a.effect(()=>()=>{y&&clearInterval(y),y=void 0,p(u,!1),b?.ui.setStatus(n,void 0),b?.ui.setStatus(r,void 0),b=void 0,v?.dispose(),v=void 0},`${l}/runtime`),e(u,m.service)}function h(e,t){m(e,t.pi,t.dependencies)}async function g(e,t=i()){let n=await a(e,l,{allowStandalone:!0}),r=n.root.plugin(h,{pi:e,dependencies:t});try{await r}catch(e){try{await r.dispose()}finally{await n.dispose()}throw e}let o;e.on(`session_shutdown`,()=>o??=(async()=>{try{await r.dispose()}finally{await n.dispose()}})())}export{d as COMPUTER_USE_GUIDANCE,t as COMPUTER_USE_MODE_ID,u as COMPUTER_USE_TOOL_NAMES,g as activateComputerUseExtension,g as default,m as installComputerUseRuntime,f as modeState,p as reconcileTools};
3
+ //# sourceMappingURL=extension.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extension.mjs","names":[],"sources":["../../../src/adapters/pi/extension.ts"],"sourcesContent":["import { connectDoomCordisHost } from '@agimon-ai/doompi-extension-contracts/cordis-host';\nimport {\n DOOM_MINOR_MODE_CATALOG_SERVICE,\n type MinorModeOwnerHandle,\n type MinorModeState,\n registerMinorModeOwner,\n requireMinorModeCatalog,\n} from '@agimon-ai/doompi-extension-contracts/mode';\nimport type { Context } from '@deepseek-ai/cordis';\nimport type { ExtensionAPI, ExtensionContext } from '@earendil-works/pi-coding-agent';\nimport { registerComputerUseCommand } from '../../commands/computerUseCommand.ts';\nimport { createComputerUseContainer } from '../../container/index.ts';\nimport {\n COMPUTER_USE_MODE_ID,\n COMPUTER_USE_MODE_STATUS_KEY,\n COMPUTER_USE_STATUS_KEY,\n type ComputerUseSessionView,\n} from '../../types/computerUseApi.ts';\nimport type { ComputerUseAction } from '../../types/computerUse.ts';\nimport type { ComputerUseExtensionDependencies } from '../../types/extension.ts';\n\nconst PACKAGE_SOURCE = '@agimon-ai/doompi-computer-use';\nexport { COMPUTER_USE_MODE_ID };\nexport const COMPUTER_USE_TOOL_NAMES = ['computer_state', 'computer_action'] as const;\nexport 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, set_value, or scroll at a time. Never infer coordinates, inspect another application, bypass secure elements, or retry an uncertain outcome. Stop computer use when the task is complete.`;\n\nexport function modeState(state?: ComputerUseSessionView, enabled = false): MinorModeState {\n const phase = state?.phase ?? 'inactive';\n const running = phase !== 'inactive' && phase !== 'failed';\n const modeEnabled = enabled || running;\n const activation = modeEnabled\n ? phase === 'stopping'\n ? 'deactivating'\n : phase === 'awaiting_confirmation' || phase === 'activating'\n ? 'activating'\n : 'active'\n : 'inactive';\n return {\n activation,\n condition:\n phase === 'awaiting_confirmation'\n ? 'blocked'\n : phase === 'failed'\n ? 'failed'\n : phase === 'activating' || phase === 'stopping'\n ? 'queued'\n : 'ready',\n ...(modeEnabled && phase === 'inactive' ? { detail: 'configure computer use in Activity' } : {}),\n ...(phase === 'awaiting_confirmation' ? { detail: 'awaiting confirmation in Activity' } : {}),\n actions: [\n {\n id: 'activate',\n enabled: !modeEnabled,\n ...(!modeEnabled ? {} : { disabledReason: 'Computer use is already enabled.' }),\n },\n {\n id: 'deactivate',\n enabled: modeEnabled,\n ...(modeEnabled ? {} : { disabledReason: 'Computer use is not enabled.' }),\n },\n { id: 'doctor', enabled: true },\n ],\n };\n}\n\nexport function reconcileTools(pi: Pick<ExtensionAPI, 'getActiveTools' | 'setActiveTools'>, active: boolean): void {\n const owned = new Set<string>(COMPUTER_USE_TOOL_NAMES);\n const current = pi.getActiveTools();\n const next = current.filter((name) => !owned.has(name));\n if (active) next.push(...COMPUTER_USE_TOOL_NAMES);\n if (next.length !== current.length || next.some((name, index) => name !== current[index])) pi.setActiveTools(next);\n}\n\nexport function installComputerUseRuntime(\n cordis: Context,\n pi: ExtensionAPI,\n dependencies: ComputerUseExtensionDependencies = createComputerUseContainer(),\n): void {\n const client = dependencies.client;\n let state: ComputerUseSessionView | undefined;\n let enabled = false;\n let mode: MinorModeOwnerHandle | undefined;\n let timer: ReturnType<typeof setInterval> | undefined;\n let activeContext: ExtensionContext | undefined;\n let publishedMode = '';\n let publishedModeStatus: string | undefined;\n let publishedActivityStatus: string | undefined;\n\n const publish = (): void => {\n const phase = state?.phase ?? 'inactive';\n const projection = `${enabled}:${phase}:${state?.revision ?? 'none'}`;\n if (mode !== undefined && projection !== publishedMode) {\n mode.publish(modeState(state, enabled));\n publishedMode = projection;\n }\n const modeStatus = state === undefined ? undefined : enabled || phase !== 'inactive' ? phase : '';\n if (activeContext !== undefined && modeStatus !== publishedModeStatus) {\n activeContext.ui.setStatus(COMPUTER_USE_MODE_STATUS_KEY, modeStatus);\n publishedModeStatus = modeStatus;\n }\n const activityStatus = enabled || phase !== 'inactive' ? `computer use: ${phase}` : undefined;\n if (activeContext !== undefined && activityStatus !== publishedActivityStatus) {\n activeContext.ui.setStatus(COMPUTER_USE_STATUS_KEY, activityStatus);\n publishedActivityStatus = activityStatus;\n }\n };\n const refresh = async (): Promise<void> => {\n if (client === undefined) {\n state = undefined;\n reconcileTools(pi, false);\n publish();\n return;\n }\n try {\n state = await client.state();\n reconcileTools(pi, state.phase === 'active');\n publish();\n } catch {\n state = undefined;\n reconcileTools(pi, false);\n publish();\n }\n };\n\n pi.registerTool({\n name: 'computer_state',\n label: 'Computer State',\n description: 'Observe the authorized application window and return its semantic accessibility state.',\n promptSnippet: 'Observe the authorized application before choosing a semantic action',\n parameters: { type: 'object', properties: {}, additionalProperties: false },\n async execute(_toolCallId, _params, signal) {\n if (client === undefined || state?.phase !== 'active')\n throw new Error('Computer use is not active for this session.');\n const observation = await client.observe(signal);\n return { content: [{ type: 'text', text: JSON.stringify(observation, null, 2) }], details: observation };\n },\n });\n pi.registerTool({\n name: 'computer_action',\n label: 'Computer Action',\n description: 'Perform one constrained semantic action in the authorized application window.',\n promptSnippet: 'Perform one action using a current computer_state snapshot and element ref',\n parameters: {\n type: 'object',\n properties: {\n kind: { type: 'string', enum: ['press', 'set_value', 'scroll'] },\n snapshotId: { type: 'string' },\n elementRef: { type: 'string' },\n value: { type: 'string' },\n direction: { type: 'string', enum: ['up', 'down', 'left', 'right'] },\n amount: { type: 'string', enum: ['line', 'page'] },\n },\n required: ['kind', 'snapshotId', 'elementRef'],\n additionalProperties: false,\n },\n async execute(_toolCallId, params, signal) {\n if (client === undefined || state?.phase !== 'active')\n throw new Error('Computer use is not active for this session.');\n const result = await client.act(params as unknown as ComputerUseAction, signal);\n return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }], details: result };\n },\n });\n\n cordis.inject([DOOM_MINOR_MODE_CATALOG_SERVICE], (context) => {\n const owner = registerMinorModeOwner<ExtensionContext>(requireMinorModeCatalog(context), {\n descriptor: {\n source: PACKAGE_SOURCE,\n id: COMPUTER_USE_MODE_ID,\n label: 'Computer Use',\n description: 'Session-scoped semantic control through DoomPi Desktop.',\n order: 450,\n actions: [\n {\n id: 'activate',\n label: 'Activate',\n description: 'Open the cockpit activation workflow and native confirmation.',\n contexts: ['tui', 'headless'],\n parameters: [],\n },\n {\n id: 'deactivate',\n label: 'Deactivate',\n description: 'Stop this session computer-use run.',\n contexts: ['tui', 'headless'],\n parameters: [],\n },\n {\n id: 'doctor',\n label: 'Doctor',\n description: 'Report Desktop availability and session state.',\n contexts: ['tui', 'headless'],\n parameters: [],\n },\n ],\n },\n initialState: modeState(state, enabled),\n async handleAction(actionId, _argumentsValue, execution) {\n activeContext = execution.context;\n if (actionId === 'activate') {\n if (client === undefined) throw new Error('DoomPi Desktop computer use is unavailable.');\n enabled = true;\n await refresh();\n publish();\n return { message: 'Computer use is ready to configure in Activity.' };\n }\n if (actionId === 'doctor') {\n await refresh();\n return {\n message:\n client === undefined\n ? 'DoomPi Desktop session API is unavailable.'\n : `Computer use is ${state?.phase.replaceAll('_', ' ') ?? 'unavailable'}.`,\n };\n }\n if (actionId === 'deactivate') {\n if (client === undefined) throw new Error('DoomPi Desktop computer use is unavailable.');\n if (state !== undefined && state.phase !== 'inactive' && state.phase !== 'failed')\n await client.stop(execution.signal);\n enabled = false;\n await refresh();\n publish();\n return { message: 'Computer use is off.' };\n }\n throw new Error(`Unknown computer-use action: ${actionId}`);\n },\n });\n mode = owner;\n return () => {\n owner.dispose();\n if (mode === owner) mode = undefined;\n };\n });\n\n pi.on('before_agent_start', (event) =>\n state?.phase === 'active' ? { systemPrompt: `${event.systemPrompt}\\n\\n${COMPUTER_USE_GUIDANCE}` } : undefined,\n );\n pi.on('session_start', (_event, context) => {\n activeContext = context;\n reconcileTools(pi, false);\n void refresh();\n if (timer) clearInterval(timer);\n timer = setInterval(() => void refresh(), 250);\n timer.unref?.();\n });\n cordis.effect(\n () => () => {\n if (timer) clearInterval(timer);\n timer = undefined;\n reconcileTools(pi, false);\n activeContext?.ui.setStatus(COMPUTER_USE_MODE_STATUS_KEY, undefined);\n activeContext?.ui.setStatus(COMPUTER_USE_STATUS_KEY, undefined);\n activeContext = undefined;\n mode?.dispose();\n mode = undefined;\n },\n `${PACKAGE_SOURCE}/runtime`,\n );\n\n registerComputerUseCommand(pi, dependencies.service);\n}\n\ninterface ComputerUsePluginConfig {\n readonly pi: ExtensionAPI;\n readonly dependencies: ComputerUseExtensionDependencies;\n}\n\nfunction computerUsePlugin(cordis: Context, config: ComputerUsePluginConfig): void {\n installComputerUseRuntime(cordis, config.pi, config.dependencies);\n}\n\nexport async function activateComputerUseExtension(\n pi: ExtensionAPI,\n dependencies: ComputerUseExtensionDependencies = createComputerUseContainer(),\n): Promise<void> {\n const connection = await connectDoomCordisHost(pi, PACKAGE_SOURCE, { allowStandalone: true });\n const fiber = connection.root.plugin(computerUsePlugin, { pi, dependencies });\n try {\n await fiber;\n } catch (error) {\n try {\n await fiber.dispose();\n } finally {\n await connection.dispose();\n }\n throw error;\n }\n let disposal: Promise<void> | undefined;\n pi.on(\n 'session_shutdown',\n () =>\n (disposal ??= (async () => {\n try {\n await fiber.dispose();\n } finally {\n await connection.dispose();\n }\n })()),\n );\n}\n\nexport default activateComputerUseExtension;\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ const e=require("../../_virtual/_rolldown/runtime.cjs"),t=require("../../types/computerUseApi.cjs");let n=require("node:http");n=e.__toESM(n,1);let r=require("@agimon-ai/doompi-extension-contracts/package-api");var i=class{options;constructor(e){this.options=e}request(e,i,a,o){return new Promise((s,c)=>{let l=a===void 0?void 0:JSON.stringify(a),u=n.default.request({socketPath:this.options.socketPath,path:`${r.DOOM_API_ROUTE_PREFIX}/${t.API_BASE_PATH}${e}`,method:i,headers:{authorization:`Bearer ${this.options.token}`,...l===void 0?{}:{"content-type":`application/json`,"content-length":Buffer.byteLength(l)}},signal:o},e=>{let t=[];e.on(`data`,e=>t.push(e)),e.on(`end`,()=>{try{let n=JSON.parse(Buffer.concat(t).toString(`utf8`));if((e.statusCode??500)>=400){let t=typeof n==`object`&&n&&`error`in n?String(n.error):`HTTP ${e.statusCode}`;c(Error(t))}else s(n)}catch(e){c(e)}})});u.on(`error`,c),l!==void 0&&u.write(l),u.end()})}async state(e){return await this.request(t.COMPUTER_USE_ROUTES.agentState,`GET`,void 0,e)}async observe(e){return await this.request(t.COMPUTER_USE_ROUTES.agentObserve,`POST`,{},e)}act(e,n){return this.request(t.COMPUTER_USE_ROUTES.agentAction,`POST`,e,n)}async stop(e){return await this.request(t.COMPUTER_USE_ROUTES.agentStop,`POST`,{},e)}};function a(e=process.env){let t=e[r.DOOM_API_SOCKET_ENV],n=e[r.DOOM_API_INTERNAL_TOKEN_ENV];return t&&n?new i({socketPath:t,token:n}):void 0}exports.UnixComputerUseSessionClient=i,exports.createComputerUseSessionClient=a;
2
+ //# sourceMappingURL=sessionApiClient.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessionApiClient.cjs","names":["http","DOOM_API_ROUTE_PREFIX","API_BASE_PATH","COMPUTER_USE_ROUTES","DOOM_API_SOCKET_ENV","DOOM_API_INTERNAL_TOKEN_ENV"],"sources":["../../../src/adapters/pi/sessionApiClient.ts"],"sourcesContent":["import http from 'node:http';\nimport {\n DOOM_API_INTERNAL_TOKEN_ENV,\n DOOM_API_ROUTE_PREFIX,\n DOOM_API_SOCKET_ENV,\n} from '@agimon-ai/doompi-extension-contracts/package-api';\nimport { API_BASE_PATH, COMPUTER_USE_ROUTES, type ComputerUseSessionView } from '../../types/computerUseApi.ts';\nimport type { ComputerUseAction, ComputerUseObservation } from '../../types/computerUse.ts';\n\nexport interface ComputerUseSessionClient {\n state(signal?: AbortSignal): Promise<ComputerUseSessionView>;\n observe(signal?: AbortSignal): Promise<ComputerUseObservation>;\n act(action: ComputerUseAction, signal?: AbortSignal): Promise<unknown>;\n stop(signal?: AbortSignal): Promise<ComputerUseSessionView>;\n}\n\ninterface ClientOptions {\n readonly socketPath: string;\n readonly token: string;\n}\n\nexport class UnixComputerUseSessionClient implements ComputerUseSessionClient {\n public constructor(private readonly options: ClientOptions) {}\n\n private request(path: string, method: 'GET' | 'POST', value?: unknown, signal?: AbortSignal): Promise<unknown> {\n return new Promise((resolve, reject) => {\n const body = value === undefined ? undefined : JSON.stringify(value);\n const request = http.request(\n {\n socketPath: this.options.socketPath,\n path: `${DOOM_API_ROUTE_PREFIX}/${API_BASE_PATH}${path}`,\n method,\n headers: {\n authorization: `Bearer ${this.options.token}`,\n ...(body === undefined\n ? {}\n : { 'content-type': 'application/json', 'content-length': Buffer.byteLength(body) }),\n },\n signal,\n },\n (response) => {\n const chunks: Buffer[] = [];\n response.on('data', (chunk: Buffer) => chunks.push(chunk));\n response.on('end', () => {\n try {\n const parsed = JSON.parse(Buffer.concat(chunks).toString('utf8')) as unknown;\n if ((response.statusCode ?? 500) >= 400) {\n const message =\n typeof parsed === 'object' && parsed !== null && 'error' in parsed\n ? String(parsed.error)\n : `HTTP ${response.statusCode}`;\n reject(new Error(message));\n } else resolve(parsed);\n } catch (error) {\n reject(error);\n }\n });\n },\n );\n request.on('error', reject);\n if (body !== undefined) request.write(body);\n request.end();\n });\n }\n\n public async state(signal?: AbortSignal): Promise<ComputerUseSessionView> {\n return (await this.request(COMPUTER_USE_ROUTES.agentState, 'GET', undefined, signal)) as ComputerUseSessionView;\n }\n\n public async observe(signal?: AbortSignal): Promise<ComputerUseObservation> {\n return (await this.request(COMPUTER_USE_ROUTES.agentObserve, 'POST', {}, signal)) as ComputerUseObservation;\n }\n\n public act(action: ComputerUseAction, signal?: AbortSignal): Promise<unknown> {\n return this.request(COMPUTER_USE_ROUTES.agentAction, 'POST', action, signal);\n }\n\n public async stop(signal?: AbortSignal): Promise<ComputerUseSessionView> {\n return (await this.request(COMPUTER_USE_ROUTES.agentStop, 'POST', {}, signal)) as ComputerUseSessionView;\n }\n}\n\nexport function createComputerUseSessionClient(\n environment: NodeJS.ProcessEnv = process.env,\n): ComputerUseSessionClient | undefined {\n const socketPath = environment[DOOM_API_SOCKET_ENV];\n const token = environment[DOOM_API_INTERNAL_TOKEN_ENV];\n return socketPath && token ? new UnixComputerUseSessionClient({ socketPath, token }) : undefined;\n}\n"],"mappings":"mNAqBA,IAAa,EAAb,KAA8E,CACxC,QAApC,YAAmB,EAAyC,CAAxB,KAAA,QAAA,CAAyB,CAE7D,QAAgB,EAAc,EAAwB,EAAiB,EAAwC,CAC7G,OAAO,IAAI,SAAS,EAAS,IAAW,CACtC,IAAM,EAAO,IAAU,IAAA,GAAY,IAAA,GAAY,KAAK,UAAU,CAAK,EAC7D,EAAUA,EAAAA,QAAK,QACnB,CACE,WAAY,KAAK,QAAQ,WACzB,KAAM,GAAGC,EAAAA,sBAAsB,GAAGC,EAAAA,gBAAgB,IAClD,SACA,QAAS,CACP,cAAe,UAAU,KAAK,QAAQ,QACtC,GAAI,IAAS,IAAA,GACT,CAAC,EACD,CAAE,eAAgB,mBAAoB,iBAAkB,OAAO,WAAW,CAAI,CAAE,CACtF,EACA,QACF,EACC,GAAa,CACZ,IAAM,EAAmB,CAAC,EAC1B,EAAS,GAAG,OAAS,GAAkB,EAAO,KAAK,CAAK,CAAC,EACzD,EAAS,GAAG,UAAa,CACvB,GAAI,CACF,IAAM,EAAS,KAAK,MAAM,OAAO,OAAO,CAAM,CAAC,CAAC,SAAS,MAAM,CAAC,EAChE,IAAK,EAAS,YAAc,MAAQ,IAAK,CACvC,IAAM,EACJ,OAAO,GAAW,UAAY,GAAmB,UAAW,EACxD,OAAO,EAAO,KAAK,EACnB,QAAQ,EAAS,aACvB,EAAW,MAAM,CAAO,CAAC,CAC3B,MAAO,EAAQ,CAAM,CACvB,OAAS,EAAO,CACd,EAAO,CAAK,CACd,CACF,CAAC,CACH,CACF,EACA,EAAQ,GAAG,QAAS,CAAM,EACtB,IAAS,IAAA,IAAW,EAAQ,MAAM,CAAI,EAC1C,EAAQ,IAAI,CACd,CAAC,CACH,CAEA,MAAa,MAAM,EAAuD,CACxE,OAAQ,MAAM,KAAK,QAAQC,EAAAA,oBAAoB,WAAY,MAAO,IAAA,GAAW,CAAM,CACrF,CAEA,MAAa,QAAQ,EAAuD,CAC1E,OAAQ,MAAM,KAAK,QAAQA,EAAAA,oBAAoB,aAAc,OAAQ,CAAC,EAAG,CAAM,CACjF,CAEA,IAAW,EAA2B,EAAwC,CAC5E,OAAO,KAAK,QAAQA,EAAAA,oBAAoB,YAAa,OAAQ,EAAQ,CAAM,CAC7E,CAEA,MAAa,KAAK,EAAuD,CACvE,OAAQ,MAAM,KAAK,QAAQA,EAAAA,oBAAoB,UAAW,OAAQ,CAAC,EAAG,CAAM,CAC9E,CACF,EAEA,SAAgB,EACd,EAAiC,QAAQ,IACH,CACtC,IAAM,EAAa,EAAYC,EAAAA,qBACzB,EAAQ,EAAYC,EAAAA,6BAC1B,OAAO,GAAc,EAAQ,IAAI,EAA6B,CAAE,aAAY,OAAM,CAAC,EAAI,IAAA,EACzF"}
@@ -0,0 +1,26 @@
1
+ import { ComputerUseSessionView } from "../../types/computerUseApi.cjs";
2
+ import { ComputerUseAction, ComputerUseObservation } from "../../types/computerUse.cjs";
3
+ //#region src/adapters/pi/sessionApiClient.d.ts
4
+ interface ComputerUseSessionClient {
5
+ state(signal?: AbortSignal): Promise<ComputerUseSessionView>;
6
+ observe(signal?: AbortSignal): Promise<ComputerUseObservation>;
7
+ act(action: ComputerUseAction, signal?: AbortSignal): Promise<unknown>;
8
+ stop(signal?: AbortSignal): Promise<ComputerUseSessionView>;
9
+ }
10
+ interface ClientOptions {
11
+ readonly socketPath: string;
12
+ readonly token: string;
13
+ }
14
+ declare class UnixComputerUseSessionClient implements ComputerUseSessionClient {
15
+ private readonly options;
16
+ constructor(options: ClientOptions);
17
+ private request;
18
+ state(signal?: AbortSignal): Promise<ComputerUseSessionView>;
19
+ observe(signal?: AbortSignal): Promise<ComputerUseObservation>;
20
+ act(action: ComputerUseAction, signal?: AbortSignal): Promise<unknown>;
21
+ stop(signal?: AbortSignal): Promise<ComputerUseSessionView>;
22
+ }
23
+ declare function createComputerUseSessionClient(environment?: NodeJS.ProcessEnv): ComputerUseSessionClient | undefined;
24
+ //#endregion
25
+ export { ComputerUseSessionClient, UnixComputerUseSessionClient, createComputerUseSessionClient };
26
+ //# sourceMappingURL=sessionApiClient.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessionApiClient.d.cts","names":[],"sources":["../../../src/adapters/pi/sessionApiClient.ts"],"mappings":";;;UASiB;EACf,MAAM,SAAS,cAAc,QAAQ;EACrC,QAAQ,SAAS,cAAc,QAAQ;EACvC,IAAI,QAAQ,mBAAmB,SAAS,cAAc;EACtD,KAAK,SAAS,cAAc,QAAQ;;UAG5B;WACC;WACA;;cAGE,wCAAwC;mBACf;EAApC,YAAoC,SAAS;UAErC;EAyCK,MAAM,SAAS,cAAc,QAAQ;EAIrC,QAAQ,SAAS,cAAc,QAAQ;EAI7C,IAAI,QAAQ,mBAAmB,SAAS,cAAc;EAIhD,KAAK,SAAS,cAAc,QAAQ;;iBAKnC,+BACd,cAAa,OAAO,aACnB"}
@@ -0,0 +1,26 @@
1
+ import { ComputerUseSessionView } from "../../types/computerUseApi.mjs";
2
+ import { ComputerUseAction, ComputerUseObservation } from "../../types/computerUse.mjs";
3
+ //#region src/adapters/pi/sessionApiClient.d.ts
4
+ interface ComputerUseSessionClient {
5
+ state(signal?: AbortSignal): Promise<ComputerUseSessionView>;
6
+ observe(signal?: AbortSignal): Promise<ComputerUseObservation>;
7
+ act(action: ComputerUseAction, signal?: AbortSignal): Promise<unknown>;
8
+ stop(signal?: AbortSignal): Promise<ComputerUseSessionView>;
9
+ }
10
+ interface ClientOptions {
11
+ readonly socketPath: string;
12
+ readonly token: string;
13
+ }
14
+ declare class UnixComputerUseSessionClient implements ComputerUseSessionClient {
15
+ private readonly options;
16
+ constructor(options: ClientOptions);
17
+ private request;
18
+ state(signal?: AbortSignal): Promise<ComputerUseSessionView>;
19
+ observe(signal?: AbortSignal): Promise<ComputerUseObservation>;
20
+ act(action: ComputerUseAction, signal?: AbortSignal): Promise<unknown>;
21
+ stop(signal?: AbortSignal): Promise<ComputerUseSessionView>;
22
+ }
23
+ declare function createComputerUseSessionClient(environment?: NodeJS.ProcessEnv): ComputerUseSessionClient | undefined;
24
+ //#endregion
25
+ export { ComputerUseSessionClient, UnixComputerUseSessionClient, createComputerUseSessionClient };
26
+ //# sourceMappingURL=sessionApiClient.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessionApiClient.d.mts","names":[],"sources":["../../../src/adapters/pi/sessionApiClient.ts"],"mappings":";;;UASiB;EACf,MAAM,SAAS,cAAc,QAAQ;EACrC,QAAQ,SAAS,cAAc,QAAQ;EACvC,IAAI,QAAQ,mBAAmB,SAAS,cAAc;EACtD,KAAK,SAAS,cAAc,QAAQ;;UAG5B;WACC;WACA;;cAGE,wCAAwC;mBACf;EAApC,YAAoC,SAAS;UAErC;EAyCK,MAAM,SAAS,cAAc,QAAQ;EAIrC,QAAQ,SAAS,cAAc,QAAQ;EAI7C,IAAI,QAAQ,mBAAmB,SAAS,cAAc;EAIhD,KAAK,SAAS,cAAc,QAAQ;;iBAKnC,+BACd,cAAa,OAAO,aACnB"}
@@ -0,0 +1,2 @@
1
+ import{API_BASE_PATH as e,COMPUTER_USE_ROUTES as t}from"../../types/computerUseApi.mjs";import n from"node:http";import{DOOM_API_INTERNAL_TOKEN_ENV as r,DOOM_API_ROUTE_PREFIX as i,DOOM_API_SOCKET_ENV as a}from"@agimon-ai/doompi-extension-contracts/package-api";var o=class{options;constructor(e){this.options=e}request(t,r,a,o){return new Promise((s,c)=>{let l=a===void 0?void 0:JSON.stringify(a),u=n.request({socketPath:this.options.socketPath,path:`${i}/${e}${t}`,method:r,headers:{authorization:`Bearer ${this.options.token}`,...l===void 0?{}:{"content-type":`application/json`,"content-length":Buffer.byteLength(l)}},signal:o},e=>{let t=[];e.on(`data`,e=>t.push(e)),e.on(`end`,()=>{try{let n=JSON.parse(Buffer.concat(t).toString(`utf8`));if((e.statusCode??500)>=400){let t=typeof n==`object`&&n&&`error`in n?String(n.error):`HTTP ${e.statusCode}`;c(Error(t))}else s(n)}catch(e){c(e)}})});u.on(`error`,c),l!==void 0&&u.write(l),u.end()})}async state(e){return await this.request(t.agentState,`GET`,void 0,e)}async observe(e){return await this.request(t.agentObserve,`POST`,{},e)}act(e,n){return this.request(t.agentAction,`POST`,e,n)}async stop(e){return await this.request(t.agentStop,`POST`,{},e)}};function s(e=process.env){let t=e[a],n=e[r];return t&&n?new o({socketPath:t,token:n}):void 0}export{o as UnixComputerUseSessionClient,s as createComputerUseSessionClient};
2
+ //# sourceMappingURL=sessionApiClient.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessionApiClient.mjs","names":[],"sources":["../../../src/adapters/pi/sessionApiClient.ts"],"sourcesContent":["import http from 'node:http';\nimport {\n DOOM_API_INTERNAL_TOKEN_ENV,\n DOOM_API_ROUTE_PREFIX,\n DOOM_API_SOCKET_ENV,\n} from '@agimon-ai/doompi-extension-contracts/package-api';\nimport { API_BASE_PATH, COMPUTER_USE_ROUTES, type ComputerUseSessionView } from '../../types/computerUseApi.ts';\nimport type { ComputerUseAction, ComputerUseObservation } from '../../types/computerUse.ts';\n\nexport interface ComputerUseSessionClient {\n state(signal?: AbortSignal): Promise<ComputerUseSessionView>;\n observe(signal?: AbortSignal): Promise<ComputerUseObservation>;\n act(action: ComputerUseAction, signal?: AbortSignal): Promise<unknown>;\n stop(signal?: AbortSignal): Promise<ComputerUseSessionView>;\n}\n\ninterface ClientOptions {\n readonly socketPath: string;\n readonly token: string;\n}\n\nexport class UnixComputerUseSessionClient implements ComputerUseSessionClient {\n public constructor(private readonly options: ClientOptions) {}\n\n private request(path: string, method: 'GET' | 'POST', value?: unknown, signal?: AbortSignal): Promise<unknown> {\n return new Promise((resolve, reject) => {\n const body = value === undefined ? undefined : JSON.stringify(value);\n const request = http.request(\n {\n socketPath: this.options.socketPath,\n path: `${DOOM_API_ROUTE_PREFIX}/${API_BASE_PATH}${path}`,\n method,\n headers: {\n authorization: `Bearer ${this.options.token}`,\n ...(body === undefined\n ? {}\n : { 'content-type': 'application/json', 'content-length': Buffer.byteLength(body) }),\n },\n signal,\n },\n (response) => {\n const chunks: Buffer[] = [];\n response.on('data', (chunk: Buffer) => chunks.push(chunk));\n response.on('end', () => {\n try {\n const parsed = JSON.parse(Buffer.concat(chunks).toString('utf8')) as unknown;\n if ((response.statusCode ?? 500) >= 400) {\n const message =\n typeof parsed === 'object' && parsed !== null && 'error' in parsed\n ? String(parsed.error)\n : `HTTP ${response.statusCode}`;\n reject(new Error(message));\n } else resolve(parsed);\n } catch (error) {\n reject(error);\n }\n });\n },\n );\n request.on('error', reject);\n if (body !== undefined) request.write(body);\n request.end();\n });\n }\n\n public async state(signal?: AbortSignal): Promise<ComputerUseSessionView> {\n return (await this.request(COMPUTER_USE_ROUTES.agentState, 'GET', undefined, signal)) as ComputerUseSessionView;\n }\n\n public async observe(signal?: AbortSignal): Promise<ComputerUseObservation> {\n return (await this.request(COMPUTER_USE_ROUTES.agentObserve, 'POST', {}, signal)) as ComputerUseObservation;\n }\n\n public act(action: ComputerUseAction, signal?: AbortSignal): Promise<unknown> {\n return this.request(COMPUTER_USE_ROUTES.agentAction, 'POST', action, signal);\n }\n\n public async stop(signal?: AbortSignal): Promise<ComputerUseSessionView> {\n return (await this.request(COMPUTER_USE_ROUTES.agentStop, 'POST', {}, signal)) as ComputerUseSessionView;\n }\n}\n\nexport function createComputerUseSessionClient(\n environment: NodeJS.ProcessEnv = process.env,\n): ComputerUseSessionClient | undefined {\n const socketPath = environment[DOOM_API_SOCKET_ENV];\n const token = environment[DOOM_API_INTERNAL_TOKEN_ENV];\n return socketPath && token ? new UnixComputerUseSessionClient({ socketPath, token }) : undefined;\n}\n"],"mappings":"qQAqBA,IAAa,EAAb,KAA8E,CACxC,QAApC,YAAmB,EAAyC,CAAxB,KAAA,QAAA,CAAyB,CAE7D,QAAgB,EAAc,EAAwB,EAAiB,EAAwC,CAC7G,OAAO,IAAI,SAAS,EAAS,IAAW,CACtC,IAAM,EAAO,IAAU,IAAA,GAAY,IAAA,GAAY,KAAK,UAAU,CAAK,EAC7D,EAAU,EAAK,QACnB,CACE,WAAY,KAAK,QAAQ,WACzB,KAAM,GAAG,EAAsB,GAAG,IAAgB,IAClD,SACA,QAAS,CACP,cAAe,UAAU,KAAK,QAAQ,QACtC,GAAI,IAAS,IAAA,GACT,CAAC,EACD,CAAE,eAAgB,mBAAoB,iBAAkB,OAAO,WAAW,CAAI,CAAE,CACtF,EACA,QACF,EACC,GAAa,CACZ,IAAM,EAAmB,CAAC,EAC1B,EAAS,GAAG,OAAS,GAAkB,EAAO,KAAK,CAAK,CAAC,EACzD,EAAS,GAAG,UAAa,CACvB,GAAI,CACF,IAAM,EAAS,KAAK,MAAM,OAAO,OAAO,CAAM,CAAC,CAAC,SAAS,MAAM,CAAC,EAChE,IAAK,EAAS,YAAc,MAAQ,IAAK,CACvC,IAAM,EACJ,OAAO,GAAW,UAAY,GAAmB,UAAW,EACxD,OAAO,EAAO,KAAK,EACnB,QAAQ,EAAS,aACvB,EAAW,MAAM,CAAO,CAAC,CAC3B,MAAO,EAAQ,CAAM,CACvB,OAAS,EAAO,CACd,EAAO,CAAK,CACd,CACF,CAAC,CACH,CACF,EACA,EAAQ,GAAG,QAAS,CAAM,EACtB,IAAS,IAAA,IAAW,EAAQ,MAAM,CAAI,EAC1C,EAAQ,IAAI,CACd,CAAC,CACH,CAEA,MAAa,MAAM,EAAuD,CACxE,OAAQ,MAAM,KAAK,QAAQ,EAAoB,WAAY,MAAO,IAAA,GAAW,CAAM,CACrF,CAEA,MAAa,QAAQ,EAAuD,CAC1E,OAAQ,MAAM,KAAK,QAAQ,EAAoB,aAAc,OAAQ,CAAC,EAAG,CAAM,CACjF,CAEA,IAAW,EAA2B,EAAwC,CAC5E,OAAO,KAAK,QAAQ,EAAoB,YAAa,OAAQ,EAAQ,CAAM,CAC7E,CAEA,MAAa,KAAK,EAAuD,CACvE,OAAQ,MAAM,KAAK,QAAQ,EAAoB,UAAW,OAAQ,CAAC,EAAG,CAAM,CAC9E,CACF,EAEA,SAAgB,EACd,EAAiC,QAAQ,IACH,CACtC,IAAM,EAAa,EAAY,GACzB,EAAQ,EAAY,GAC1B,OAAO,GAAc,EAAQ,IAAI,EAA6B,CAAE,aAAY,OAAM,CAAC,EAAI,IAAA,EACzF"}
@@ -0,0 +1,2 @@
1
+ require("../types/computerUseApi.cjs");var e=class extends Error{};function t(t,n){let r=typeof n==`object`&&n&&!Array.isArray(n)?n.error:void 0,i=typeof r==`string`?r:`HTTP ${String(t)}`;return t===404&&i===`No API 'computer-use' in this session.`?new e(i):Error(i)}function n(e){return e+5e3}exports.MissingComputerUseApiError=e,exports.computerUseSessionApiError=t,exports.missingComputerUseApiRetryAt=n;
2
+ //# sourceMappingURL=webComputerUseAvailability.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webComputerUseAvailability.cjs","names":[],"sources":["../../src/adapters/webComputerUseAvailability.ts"],"sourcesContent":["import { API_BASE_PATH } from '../types/computerUseApi.ts';\n\nexport class MissingComputerUseApiError extends Error {}\n\nexport function computerUseSessionApiError(status: number, value: unknown): Error {\n const error =\n typeof value === 'object' && value !== null && !Array.isArray(value)\n ? (value as Record<string, unknown>).error\n : undefined;\n const message = typeof error === 'string' ? error : `HTTP ${String(status)}`;\n return status === 404 && message === `No API '${API_BASE_PATH}' in this session.`\n ? new MissingComputerUseApiError(message)\n : new Error(message);\n}\n\nexport function missingComputerUseApiRetryAt(now: number): number {\n return now + 5_000;\n}\n"],"mappings":"uCAEA,IAAa,EAAb,cAAgD,KAAM,CAAC,EAEvD,SAAgB,EAA2B,EAAgB,EAAuB,CAChF,IAAM,EACJ,OAAO,GAAU,UAAY,GAAkB,CAAC,MAAM,QAAQ,CAAK,EAC9D,EAAkC,MACnC,IAAA,GACA,EAAU,OAAO,GAAU,SAAW,EAAQ,QAAQ,OAAO,CAAM,IACzE,OAAO,IAAW,KAAO,IAAY,yCACjC,IAAI,EAA2B,CAAO,EAClC,MAAM,CAAO,CACvB,CAEA,SAAgB,EAA6B,EAAqB,CAChE,OAAO,EAAM,GACf"}
@@ -0,0 +1,2 @@
1
+ import"../types/computerUseApi.mjs";var e=class extends Error{};function t(t,n){let r=typeof n==`object`&&n&&!Array.isArray(n)?n.error:void 0,i=typeof r==`string`?r:`HTTP ${String(t)}`;return t===404&&i===`No API 'computer-use' in this session.`?new e(i):Error(i)}function n(e){return e+5e3}export{e as MissingComputerUseApiError,t as computerUseSessionApiError,n as missingComputerUseApiRetryAt};
2
+ //# sourceMappingURL=webComputerUseAvailability.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webComputerUseAvailability.mjs","names":[],"sources":["../../src/adapters/webComputerUseAvailability.ts"],"sourcesContent":["import { API_BASE_PATH } from '../types/computerUseApi.ts';\n\nexport class MissingComputerUseApiError extends Error {}\n\nexport function computerUseSessionApiError(status: number, value: unknown): Error {\n const error =\n typeof value === 'object' && value !== null && !Array.isArray(value)\n ? (value as Record<string, unknown>).error\n : undefined;\n const message = typeof error === 'string' ? error : `HTTP ${String(status)}`;\n return status === 404 && message === `No API '${API_BASE_PATH}' in this session.`\n ? new MissingComputerUseApiError(message)\n : new Error(message);\n}\n\nexport function missingComputerUseApiRetryAt(now: number): number {\n return now + 5_000;\n}\n"],"mappings":"oCAEA,IAAa,EAAb,cAAgD,KAAM,CAAC,EAEvD,SAAgB,EAA2B,EAAgB,EAAuB,CAChF,IAAM,EACJ,OAAO,GAAU,UAAY,GAAkB,CAAC,MAAM,QAAQ,CAAK,EAC9D,EAAkC,MACnC,IAAA,GACA,EAAU,OAAO,GAAU,SAAW,EAAQ,QAAQ,OAAO,CAAM,IACzE,OAAO,IAAW,KAAO,IAAY,yCACjC,IAAI,EAA2B,CAAO,EAClC,MAAM,CAAO,CACvB,CAEA,SAAgB,EAA6B,EAAqB,CAChE,OAAO,EAAM,GACf"}
@@ -0,0 +1,2 @@
1
+ const e=require("../types/computerUseApi.cjs"),t=require("./webComputerUseAvailability.cjs");function n(e){return typeof e==`object`&&e&&!Array.isArray(e)?e:void 0}function r(e){let t=n(e);return t?.action===`status`||t?.action===`targets`||t?.action===`stop`||t?.action===`artifacts`?{action:t.action}:void 0}async function i(e){let n=await e.json();if(!e.ok)throw t.computerUseSessionApiError(e.status,n);return n}function a(a={}){let o;return{frameType:e.computerUseChannelType,lifecycle:`hub`,start(s){let c=new Map,l=new Map,u=new Map,d=new Map,f=new Set,p=new Map,m,h=!1,g=async(t,n,r=`GET`,i)=>s.requestSessionApi(t,{basePath:e.API_BASE_PATH,path:n,method:r,...i===void 0?{}:{body:JSON.stringify(i)}}),_=(e,t)=>{let n={state:t,targets:u.get(e.sessionId)??[],...m!==void 0&&m!==e.sessionId?{busy:!0}:{}};l.set(e.sessionId,n),s.publish(e.sessionId,n)},v=async t=>{let n=await i(await g(t,e.COMPUTER_USE_ROUTES.hubState));if(n.phase===`active`||n.phase===`activating`||n.phase===`stopping`){if(m=t.sessionId,n.phase===`active`&&!d.has(t.sessionId)){let n=await i(await g(t,e.COMPUTER_USE_ROUTES.hubAuthorization));n!==null&&d.set(t.sessionId,n.grantId)}}else m===t.sessionId&&(m=void 0),d.delete(t.sessionId);return p.delete(t.sessionId),_(t,n),n},y=async(t,n)=>{if(!s.computerUse?.available)throw Error(`DoomPi Desktop computer use is unavailable.`);try{let r=await s.computerUse.request(t,{operation:n.operation,payload:n.operation===`act`?{grantId:n.grantId,sequence:n.sequence,action:n.payload}:{grantId:n.grantId}});await i(await g(t,e.COMPUTER_USE_ROUTES.hubComplete,`POST`,{id:n.id,result:r}))}catch(r){await i(await g(t,e.COMPUTER_USE_ROUTES.hubComplete,`POST`,{id:n.id,error:r instanceof Error?r.message:String(r)}))}},b=async t=>{let n=await i(await g(t,e.COMPUTER_USE_ROUTES.hubAuthorization)),r;if(n!==null&&s.computerUse?.available)try{r=await s.computerUse.request(t,{operation:`stop`,payload:{grantId:n.grantId}})}catch(e){s.onNotice(`computer-use Desktop stop was already unavailable (${e instanceof Error?e.message:String(e)})`)}await i(await g(t,e.COMPUTER_USE_ROUTES.hubStop,`POST`,{artifact:r})),d.delete(t.sessionId),m===t.sessionId&&(m=void 0)},x=async r=>{if(!(h||f.has(r.sessionId))&&!((p.get(r.sessionId)??0)>Date.now())){f.add(r.sessionId);try{let t=await v(r);if(t.phase===`active`){let a=typeof t.expiresAt==`number`&&t.expiresAt<=Date.now(),o=!1;if(!a&&s.computerUse?.available)try{o=n(await s.computerUse.request(r,{operation:`status`}))?.ownedBySession===!0}catch{o=!0}if(a||!o){await i(await g(r,e.COMPUTER_USE_ROUTES.hubStop,`POST`)),d.delete(r.sessionId),m===r.sessionId&&(m=void 0),await v(r);return}}if(t.phase===`awaiting_confirmation`&&(m===void 0||m===r.sessionId)){if(!s.computerUse?.available)throw Error(`DoomPi Desktop computer use is unavailable.`);let t=await i(await g(r,e.COMPUTER_USE_ROUTES.hubActivation));if(t!==null){m=r.sessionId;try{let a=await s.computerUse.request(r,{operation:`activate`,payload:t});await i(await g(r,e.COMPUTER_USE_ROUTES.hubStop,`POST`,{host:a}));let o=n(a)?.grantId;typeof o==`string`&&d.set(r.sessionId,o)}catch(t){m=void 0,await i(await g(r,e.COMPUTER_USE_ROUTES.hubStop,`POST`,{error:t instanceof Error?t.message:String(t)}))}await v(r)}}t.phase===`stopping`&&(await b(r),await v(r));let a=await i(await g(r,e.COMPUTER_USE_ROUTES.hubNext));a!==null&&await y(r,a)}catch(e){e instanceof t.MissingComputerUseApiError?(p.set(r.sessionId,t.missingComputerUseApiRetryAt(Date.now())),l.delete(r.sessionId)):s.onNotice(`computer-use poll failed for ${r.sessionId} (${e instanceof Error?e.message:String(e)})`)}finally{f.delete(r.sessionId)}}};o=(e,i)=>{let a=r(i);a!==void 0&&(p.delete(e.sessionId),(async()=>{try{if(a.action===`targets`){if(!s.computerUse?.available)throw Error(`DoomPi Desktop computer use is unavailable.`);let t=await s.computerUse.request(e,{operation:`targets`});u.set(e.sessionId,Array.isArray(t)?t.filter(e=>n(e)!==void 0):[])}else a.action===`stop`&&await b(e);await v(e)}catch(n){n instanceof t.MissingComputerUseApiError?(p.set(e.sessionId,t.missingComputerUseApiRetryAt(Date.now())),l.delete(e.sessionId)):s.onNotice(`computer-use command failed for ${e.sessionId} (${n instanceof Error?n.message:String(n)})`)}})())};let S=setInterval(()=>{for(let e of c.values())x(e)},a.pollMs??250);return{payloadFor:e=>l.get(e.sessionId),sessionAdded(e){c.set(e.sessionId,e),x(e)},sessionRemoved(e){let t=c.get(e),n=d.get(e);t!==void 0&&n!==void 0&&s.computerUse?.available&&s.computerUse.request(t,{operation:`stop`,payload:{grantId:n}}).catch(e=>s.onNotice(`computer-use session cleanup failed (${e instanceof Error?e.message:String(e)})`)),c.delete(e),l.delete(e),u.delete(e),d.delete(e),f.delete(e),p.delete(e),m===e&&(m=void 0)},close(){if(h=!0,clearInterval(S),s.computerUse?.available)for(let[e,t]of d){let n=c.get(e);n!==void 0&&s.computerUse.request(n,{operation:`stop`,payload:{grantId:t}}).catch(()=>void 0)}c.clear(),l.clear(),u.clear(),d.clear(),p.clear()}}},receive(e,t){o?.(e,t)}}}const o=[a()];exports.computerUseChannelType=e.computerUseChannelType,exports.createComputerUseChannel=a,exports.webHubChannels=o;
2
+ //# sourceMappingURL=webComputerUseChannel.cjs.map