@agimon-ai/doompi-computer-use 0.0.1-alpha.2 → 0.0.1-alpha.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -4
- package/dist/_virtual/_rolldown/runtime.cjs +23 -1
- package/dist/api-contracts.cjs +7 -0
- package/dist/api-contracts.d.cts +2 -0
- package/dist/api-contracts.d.mts +2 -0
- package/dist/api-contracts.mjs +2 -0
- package/dist/extensions/mcp.cjs +56 -0
- package/dist/extensions/mcp.cjs.map +1 -0
- package/dist/extensions/mcp.d.cts +5 -0
- package/dist/extensions/mcp.d.cts.map +1 -0
- package/dist/extensions/mcp.d.mts +5 -0
- package/dist/extensions/mcp.d.mts.map +1 -0
- package/dist/extensions/mcp.mjs +51 -0
- package/dist/extensions/mcp.mjs.map +1 -0
- package/dist/extensions/pi.cjs +51 -1
- package/dist/extensions/pi.cjs.map +1 -0
- package/dist/extensions/pi.d.cts +7 -2
- package/dist/extensions/pi.d.cts.map +1 -0
- package/dist/extensions/pi.d.mts +7 -2
- package/dist/extensions/pi.d.mts.map +1 -0
- package/dist/extensions/pi.mjs +46 -1
- package/dist/extensions/pi.mjs.map +1 -0
- package/dist/extensions/server.cjs +72 -0
- package/dist/extensions/server.cjs.map +1 -0
- package/dist/extensions/server.d.cts +5 -0
- package/dist/extensions/server.d.cts.map +1 -0
- package/dist/extensions/server.d.mts +5 -0
- package/dist/extensions/server.d.mts.map +1 -0
- package/dist/extensions/server.mjs +67 -0
- package/dist/extensions/server.mjs.map +1 -0
- package/dist/extensions/web.mjs +625 -0
- package/dist/extensions/web.mjs.map +1 -0
- package/dist/index.cjs +18 -1
- package/dist/index.d.cts +12 -10
- package/dist/index.d.mts +12 -10
- package/dist/index.mjs +8 -1
- package/dist/src/constants/computerUse.cjs +17 -0
- package/dist/src/constants/computerUse.cjs.map +1 -0
- package/dist/src/constants/computerUse.d.cts +5 -0
- package/dist/src/constants/computerUse.d.cts.map +1 -0
- package/dist/src/constants/computerUse.d.mts +5 -0
- package/dist/src/constants/computerUse.d.mts.map +1 -0
- package/dist/src/constants/computerUse.mjs +14 -0
- package/dist/src/constants/computerUse.mjs.map +1 -0
- package/dist/src/extensions/(backend)/channel/computer-use.server.cjs +7 -0
- package/dist/src/extensions/(backend)/channel/computer-use.server.cjs.map +1 -0
- package/dist/src/extensions/(backend)/channel/computer-use.server.mjs +8 -0
- package/dist/src/extensions/(backend)/channel/computer-use.server.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/_runtime/index.cli.cjs +8 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/_runtime/index.cli.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/_runtime/index.cli.mjs +8 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/_runtime/index.cli.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/_runtime/index.server.cjs +11 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/_runtime/index.server.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/_runtime/index.server.mjs +11 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/_runtime/index.server.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/api/computer-use/route.server.cjs +6 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/api/computer-use/route.server.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/api/computer-use/route.server.mjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/api/computer-use/route.server.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/command/computer-use.cli.cjs +6 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/command/computer-use.cli.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/command/computer-use.cli.mjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/command/computer-use.cli.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/command/computer-use.server.cjs +6 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/command/computer-use.server.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/command/computer-use.server.mjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/command/computer-use.server.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/before-agent-start.cli.cjs +6 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/before-agent-start.cli.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/before-agent-start.cli.mjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/before-agent-start.cli.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/before-agent-start.server.cjs +6 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/before-agent-start.server.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/before-agent-start.server.mjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/before-agent-start.server.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/session-shutdown.server.cjs +6 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/session-shutdown.server.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/session-shutdown.server.mjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/session-shutdown.server.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/session-start.cli.cjs +6 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/session-start.cli.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/session-start.cli.mjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/session-start.cli.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/root.cli.cjs +15 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/root.cli.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/root.cli.mjs +16 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/root.cli.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/root.server.cjs +17 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/root.server.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/root.server.mjs +18 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/root.server.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/00-computer-state.cli.cjs +6 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/00-computer-state.cli.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/00-computer-state.cli.mjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/00-computer-state.cli.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/00-computer-state.server.cjs +6 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/00-computer-state.server.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/00-computer-state.server.mjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/00-computer-state.server.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/10-computer-action.cli.cjs +6 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/10-computer-action.cli.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/10-computer-action.cli.mjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/10-computer-action.cli.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/10-computer-action.server.cjs +6 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/10-computer-action.server.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/10-computer-action.server.mjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/10-computer-action.server.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/20-computer-exec.cli.cjs +6 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/20-computer-exec.cli.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/20-computer-exec.cli.mjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/20-computer-exec.cli.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/20-computer-exec.server.cjs +6 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/20-computer-exec.server.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/20-computer-exec.server.mjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/20-computer-exec.server.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool-restriction/computer-use.cli.cjs +6 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool-restriction/computer-use.cli.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool-restriction/computer-use.cli.mjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool-restriction/computer-use.cli.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool-restriction/computer-use.server.cjs +6 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool-restriction/computer-use.server.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool-restriction/computer-use.server.mjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool-restriction/computer-use.server.mjs.map +1 -0
- package/dist/src/models/computerUseMode.cjs +43 -0
- package/dist/src/models/computerUseMode.cjs.map +1 -0
- package/dist/src/models/computerUseMode.mjs +42 -0
- package/dist/src/models/computerUseMode.mjs.map +1 -0
- package/dist/src/models/computerUseState.cjs +89 -0
- package/dist/src/models/computerUseState.cjs.map +1 -0
- package/dist/src/models/computerUseState.d.cts +6 -0
- package/dist/src/models/computerUseState.d.cts.map +1 -0
- package/dist/src/models/computerUseState.d.mts +6 -0
- package/dist/src/models/computerUseState.d.mts.map +1 -0
- package/dist/src/models/computerUseState.mjs +88 -0
- package/dist/src/models/computerUseState.mjs.map +1 -0
- package/dist/src/schemas/apiContracts.cjs +194 -0
- package/dist/src/schemas/apiContracts.cjs.map +1 -0
- package/dist/src/schemas/apiContracts.d.cts +53 -0
- package/dist/src/schemas/apiContracts.d.cts.map +1 -0
- package/dist/src/schemas/apiContracts.d.mts +53 -0
- package/dist/src/schemas/apiContracts.d.mts.map +1 -0
- package/dist/src/schemas/apiContracts.mjs +191 -0
- package/dist/src/schemas/apiContracts.mjs.map +1 -0
- package/dist/src/services/computerScriptRunner/index.cjs +171 -0
- package/dist/src/services/computerScriptRunner/index.cjs.map +1 -0
- package/dist/src/services/computerScriptRunner/index.d.cts +12 -0
- package/dist/src/services/computerScriptRunner/index.d.cts.map +1 -0
- package/dist/src/services/computerScriptRunner/index.d.mts +12 -0
- package/dist/src/services/computerScriptRunner/index.d.mts.map +1 -0
- package/dist/src/services/computerScriptRunner/index.mjs +171 -0
- package/dist/src/services/computerScriptRunner/index.mjs.map +1 -0
- package/dist/src/services/computerUseApi/index.cjs +291 -0
- package/dist/src/services/computerUseApi/index.cjs.map +1 -0
- package/dist/src/services/computerUseApi/index.mjs +289 -0
- package/dist/src/services/computerUseApi/index.mjs.map +1 -0
- package/dist/src/services/computerUseCommand/index.cjs +15 -0
- package/dist/src/services/computerUseCommand/index.cjs.map +1 -0
- package/dist/src/services/computerUseCommand/index.mjs +15 -0
- package/dist/src/services/computerUseCommand/index.mjs.map +1 -0
- package/dist/src/services/computerUseRuntime/index.cjs +300 -0
- package/dist/src/services/computerUseRuntime/index.cjs.map +1 -0
- package/dist/src/services/computerUseRuntime/index.mjs +299 -0
- package/dist/src/services/computerUseRuntime/index.mjs.map +1 -0
- package/dist/src/services/computerUseServer/index.cjs +350 -0
- package/dist/src/services/computerUseServer/index.cjs.map +1 -0
- package/dist/src/services/computerUseServer/index.mjs +348 -0
- package/dist/src/services/computerUseServer/index.mjs.map +1 -0
- package/dist/src/services/dependencies/index.cjs +27 -0
- package/dist/src/services/dependencies/index.cjs.map +1 -0
- package/dist/src/services/dependencies/index.d.cts +6 -0
- package/dist/src/services/dependencies/index.d.cts.map +1 -0
- package/dist/src/services/dependencies/index.d.mts +6 -0
- package/dist/src/services/dependencies/index.d.mts.map +1 -0
- package/dist/src/services/dependencies/index.mjs +24 -0
- package/dist/src/services/dependencies/index.mjs.map +1 -0
- package/dist/src/services/extensionService/index.cjs +21 -0
- package/dist/src/services/extensionService/index.cjs.map +1 -0
- package/dist/src/services/extensionService/index.d.cts +10 -0
- package/dist/src/services/extensionService/index.d.cts.map +1 -0
- package/dist/src/services/extensionService/index.d.mts +10 -0
- package/dist/src/services/extensionService/index.d.mts.map +1 -0
- package/dist/src/services/extensionService/index.mjs +21 -0
- package/dist/src/services/extensionService/index.mjs.map +1 -0
- package/dist/src/services/mcpTools/index.cjs +17 -0
- package/dist/src/services/mcpTools/index.cjs.map +1 -0
- package/dist/src/services/mcpTools/index.mjs +16 -0
- package/dist/src/services/mcpTools/index.mjs.map +1 -0
- package/dist/src/services/sessionApiClient/index.cjs +9 -0
- package/dist/src/services/sessionApiClient/index.cjs.map +1 -0
- package/dist/src/services/sessionApiClient/index.d.cts +15 -0
- package/dist/src/services/sessionApiClient/index.d.cts.map +1 -0
- package/dist/src/services/sessionApiClient/index.d.mts +15 -0
- package/dist/src/services/sessionApiClient/index.d.mts.map +1 -0
- package/dist/src/services/sessionApiClient/index.mjs +9 -0
- package/dist/src/services/sessionApiClient/index.mjs.map +1 -0
- package/dist/src/services/traceRedaction/index.cjs +19 -0
- package/dist/src/services/traceRedaction/index.cjs.map +1 -0
- package/dist/{services/traceRedaction.d.mts → src/services/traceRedaction/index.d.cts} +6 -7
- package/dist/src/services/traceRedaction/index.d.cts.map +1 -0
- package/dist/{services/traceRedaction.d.cts → src/services/traceRedaction/index.d.mts} +6 -7
- package/dist/src/services/traceRedaction/index.d.mts.map +1 -0
- package/dist/src/services/traceRedaction/index.mjs +19 -0
- package/dist/src/services/traceRedaction/index.mjs.map +1 -0
- package/dist/src/services/webComputerUseAvailability/index.cjs +13 -0
- package/dist/src/services/webComputerUseAvailability/index.cjs.map +1 -0
- package/dist/src/services/webComputerUseAvailability/index.mjs +12 -0
- package/dist/src/services/webComputerUseAvailability/index.mjs.map +1 -0
- package/dist/src/services/webComputerUseChannel/index.cjs +251 -0
- package/dist/src/services/webComputerUseChannel/index.cjs.map +1 -0
- package/dist/src/services/webComputerUseChannel/index.mjs +250 -0
- package/dist/src/services/webComputerUseChannel/index.mjs.map +1 -0
- package/dist/src/types/apiRoutes.cjs +84 -0
- package/dist/src/types/apiRoutes.cjs.map +1 -0
- package/dist/src/types/apiRoutes.mjs +84 -0
- package/dist/src/types/apiRoutes.mjs.map +1 -0
- package/dist/src/types/computerScript.d.cts +38 -0
- package/dist/src/types/computerScript.d.cts.map +1 -0
- package/dist/src/types/computerScript.d.mts +38 -0
- package/dist/src/types/computerScript.d.mts.map +1 -0
- package/dist/{types → src/types}/computerUse.d.cts +14 -14
- package/dist/src/types/computerUse.d.cts.map +1 -0
- package/dist/{types → src/types}/computerUse.d.mts +14 -14
- package/dist/src/types/computerUse.d.mts.map +1 -0
- package/dist/src/types/computerUseApi.cjs +41 -0
- package/dist/src/types/computerUseApi.cjs.map +1 -0
- package/dist/{types → src/types}/computerUseApi.d.cts +28 -20
- package/dist/src/types/computerUseApi.d.cts.map +1 -0
- package/dist/{types → src/types}/computerUseApi.d.mts +28 -20
- package/dist/src/types/computerUseApi.d.mts.map +1 -0
- package/dist/src/types/computerUseApi.mjs +33 -0
- package/dist/src/types/computerUseApi.mjs.map +1 -0
- package/dist/src/types/extension.d.cts +19 -0
- package/dist/src/types/extension.d.cts.map +1 -0
- package/dist/src/types/extension.d.mts +19 -0
- package/dist/src/types/extension.d.mts.map +1 -0
- package/docs/computer-scripts.md +37 -0
- package/llms.txt +1 -0
- package/package.json +55 -33
- package/src/prompts/doompi-use-computer-use/SKILL.md +1 -1
- package/src/types/computerUse.ts +3 -2
- package/src/types/computerUseApi.ts +9 -6
- package/dist/adapters/computerUseApi.cjs +0 -2
- package/dist/adapters/computerUseApi.cjs.map +0 -1
- package/dist/adapters/computerUseApi.d.cts +0 -37
- package/dist/adapters/computerUseApi.d.cts.map +0 -1
- package/dist/adapters/computerUseApi.d.mts +0 -37
- package/dist/adapters/computerUseApi.d.mts.map +0 -1
- package/dist/adapters/computerUseApi.mjs +0 -2
- package/dist/adapters/computerUseApi.mjs.map +0 -1
- package/dist/adapters/pi/extension.cjs +0 -3
- package/dist/adapters/pi/extension.cjs.map +0 -1
- package/dist/adapters/pi/extension.d.cts +0 -12
- package/dist/adapters/pi/extension.d.cts.map +0 -1
- package/dist/adapters/pi/extension.d.mts +0 -12
- package/dist/adapters/pi/extension.d.mts.map +0 -1
- package/dist/adapters/pi/extension.mjs +0 -3
- package/dist/adapters/pi/extension.mjs.map +0 -1
- package/dist/adapters/pi/sessionApiClient.cjs +0 -2
- package/dist/adapters/pi/sessionApiClient.cjs.map +0 -1
- package/dist/adapters/pi/sessionApiClient.d.cts +0 -26
- package/dist/adapters/pi/sessionApiClient.d.cts.map +0 -1
- package/dist/adapters/pi/sessionApiClient.d.mts +0 -26
- package/dist/adapters/pi/sessionApiClient.d.mts.map +0 -1
- package/dist/adapters/pi/sessionApiClient.mjs +0 -2
- package/dist/adapters/pi/sessionApiClient.mjs.map +0 -1
- package/dist/adapters/webComputerUseAvailability.cjs +0 -2
- package/dist/adapters/webComputerUseAvailability.cjs.map +0 -1
- package/dist/adapters/webComputerUseAvailability.mjs +0 -2
- package/dist/adapters/webComputerUseAvailability.mjs.map +0 -1
- package/dist/adapters/webComputerUseChannel.cjs +0 -2
- package/dist/adapters/webComputerUseChannel.cjs.map +0 -1
- package/dist/adapters/webComputerUseChannel.d.cts +0 -10
- package/dist/adapters/webComputerUseChannel.d.cts.map +0 -1
- package/dist/adapters/webComputerUseChannel.d.mts +0 -10
- package/dist/adapters/webComputerUseChannel.d.mts.map +0 -1
- package/dist/adapters/webComputerUseChannel.mjs +0 -2
- package/dist/adapters/webComputerUseChannel.mjs.map +0 -1
- package/dist/commands/computerUseCommand.cjs +0 -2
- package/dist/commands/computerUseCommand.cjs.map +0 -1
- package/dist/commands/computerUseCommand.mjs +0 -2
- package/dist/commands/computerUseCommand.mjs.map +0 -1
- package/dist/container/index.cjs +0 -2
- package/dist/container/index.cjs.map +0 -1
- package/dist/container/index.d.cts +0 -6
- package/dist/container/index.d.cts.map +0 -1
- package/dist/container/index.d.mts +0 -6
- package/dist/container/index.d.mts.map +0 -1
- package/dist/container/index.mjs +0 -2
- package/dist/container/index.mjs.map +0 -1
- package/dist/services/extensionService.cjs +0 -2
- package/dist/services/extensionService.cjs.map +0 -1
- package/dist/services/extensionService.d.cts +0 -11
- package/dist/services/extensionService.d.cts.map +0 -1
- package/dist/services/extensionService.d.mts +0 -11
- package/dist/services/extensionService.d.mts.map +0 -1
- package/dist/services/extensionService.mjs +0 -2
- package/dist/services/extensionService.mjs.map +0 -1
- package/dist/services/sessionController.cjs +0 -2
- package/dist/services/sessionController.cjs.map +0 -1
- package/dist/services/sessionController.d.cts +0 -7
- package/dist/services/sessionController.d.cts.map +0 -1
- package/dist/services/sessionController.d.mts +0 -7
- package/dist/services/sessionController.d.mts.map +0 -1
- package/dist/services/sessionController.mjs +0 -2
- package/dist/services/sessionController.mjs.map +0 -1
- package/dist/services/traceRedaction.cjs +0 -2
- package/dist/services/traceRedaction.cjs.map +0 -1
- package/dist/services/traceRedaction.d.cts.map +0 -1
- package/dist/services/traceRedaction.d.mts.map +0 -1
- package/dist/services/traceRedaction.mjs +0 -2
- package/dist/services/traceRedaction.mjs.map +0 -1
- package/dist/sessionApi.cjs +0 -1
- package/dist/sessionApi.d.cts +0 -2
- package/dist/sessionApi.d.mts +0 -2
- package/dist/sessionApi.mjs +0 -1
- package/dist/types/computerUse.d.cts.map +0 -1
- package/dist/types/computerUse.d.mts.map +0 -1
- package/dist/types/computerUseApi.cjs +0 -2
- package/dist/types/computerUseApi.cjs.map +0 -1
- package/dist/types/computerUseApi.d.cts.map +0 -1
- package/dist/types/computerUseApi.d.mts.map +0 -1
- package/dist/types/computerUseApi.mjs +0 -2
- package/dist/types/computerUseApi.mjs.map +0 -1
- package/dist/types/extension.d.cts +0 -17
- package/dist/types/extension.d.cts.map +0 -1
- package/dist/types/extension.d.mts +0 -17
- package/dist/types/extension.d.mts.map +0 -1
- package/dist/webHub.cjs +0 -1
- package/dist/webHub.d.cts +0 -3
- package/dist/webHub.d.mts +0 -3
- package/dist/webHub.mjs +0 -1
- package/src/exports/webClient.ts +0 -2
- package/src/web/ComputerActionToolCard.tsx +0 -51
- package/src/web/ComputerStateToolCard.tsx +0 -51
- package/src/web/ComputerUsePanel.tsx +0 -136
- package/src/web/computerActionToolRender.ts +0 -20
- package/src/web/computerStateToolRender.ts +0 -18
- package/src/web/computerUseStore.ts +0 -26
- package/src/web/index.ts +0 -41
- package/src/web/tsconfig.json +0 -28
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
const require_computerUseApi = require("../../types/computerUseApi.cjs");
|
|
2
|
+
const require_apiRoutes = require("../../types/apiRoutes.cjs");
|
|
3
|
+
let node_crypto = require("node:crypto");
|
|
4
|
+
let _agimon_ai_doompi_core_package_api = require("@agimon-ai/doompi-core/package-api");
|
|
5
|
+
//#region src/services/computerUseApi/index.ts
|
|
6
|
+
function jsonError(message, status) {
|
|
7
|
+
return Response.json({ error: message }, { status });
|
|
8
|
+
}
|
|
9
|
+
function record(value) {
|
|
10
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
|
|
11
|
+
}
|
|
12
|
+
async function body(request) {
|
|
13
|
+
try {
|
|
14
|
+
return record(await request.json()) ?? {};
|
|
15
|
+
} catch {
|
|
16
|
+
return {};
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
function semanticAction(value) {
|
|
20
|
+
if (!(typeof value.snapshotId === "string" && value.snapshotId.length > 0 && typeof value.elementRef === "string" && value.elementRef.length > 0)) return false;
|
|
21
|
+
const allowed = (keys) => Object.keys(value).every((key) => keys.includes(key));
|
|
22
|
+
if (value.kind === "press" || value.kind === "focus") return allowed([
|
|
23
|
+
"kind",
|
|
24
|
+
"snapshotId",
|
|
25
|
+
"elementRef"
|
|
26
|
+
]);
|
|
27
|
+
if (value.kind === "set_value") return typeof value.value === "string" && allowed([
|
|
28
|
+
"kind",
|
|
29
|
+
"snapshotId",
|
|
30
|
+
"elementRef",
|
|
31
|
+
"value"
|
|
32
|
+
]);
|
|
33
|
+
if (value.kind === "scroll") return [
|
|
34
|
+
"up",
|
|
35
|
+
"down",
|
|
36
|
+
"left",
|
|
37
|
+
"right"
|
|
38
|
+
].includes(value.direction) && (value.amount === "line" || value.amount === "page") && allowed([
|
|
39
|
+
"kind",
|
|
40
|
+
"snapshotId",
|
|
41
|
+
"elementRef",
|
|
42
|
+
"direction",
|
|
43
|
+
"amount"
|
|
44
|
+
]);
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
function artifactView(value) {
|
|
48
|
+
const input = record(value);
|
|
49
|
+
if (typeof input?.artifactId !== "string" || input.status !== "ready" && input.status !== "failed") return void 0;
|
|
50
|
+
const safeUrl = (candidate) => typeof candidate === "string" && candidate.startsWith("/api/") ? candidate : void 0;
|
|
51
|
+
const downloadUrl = safeUrl(input.downloadUrl);
|
|
52
|
+
const previewUrl = safeUrl(input.previewUrl);
|
|
53
|
+
const artifactFailure = record(input.failure);
|
|
54
|
+
const safeFailure = typeof artifactFailure?.code === "string" && typeof artifactFailure.message === "string" ? {
|
|
55
|
+
code: artifactFailure.code.slice(0, 128),
|
|
56
|
+
message: artifactFailure.message.slice(0, 512)
|
|
57
|
+
} : void 0;
|
|
58
|
+
return {
|
|
59
|
+
artifactId: input.artifactId,
|
|
60
|
+
status: input.status,
|
|
61
|
+
...downloadUrl === void 0 ? {} : { downloadUrl },
|
|
62
|
+
...previewUrl === void 0 ? {} : { previewUrl },
|
|
63
|
+
...typeof input.actionCount === "number" ? { actionCount: input.actionCount } : {},
|
|
64
|
+
...typeof input.completedAt === "string" ? { completedAt: input.completedAt } : {},
|
|
65
|
+
...safeFailure === void 0 ? {} : { failure: safeFailure }
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
var ComputerUseRequestBroker = class ComputerUseRequestBroker {
|
|
69
|
+
sessionId;
|
|
70
|
+
internalToken;
|
|
71
|
+
hubToken;
|
|
72
|
+
directEvents;
|
|
73
|
+
requestTimeoutMs;
|
|
74
|
+
revision = 0;
|
|
75
|
+
wake = 0;
|
|
76
|
+
phase = "inactive";
|
|
77
|
+
activation;
|
|
78
|
+
grantId;
|
|
79
|
+
expiresAt;
|
|
80
|
+
actionSequence = 0;
|
|
81
|
+
failure;
|
|
82
|
+
artifact;
|
|
83
|
+
pending;
|
|
84
|
+
closed = false;
|
|
85
|
+
static DEFAULT_REQUEST_TIMEOUT_MS = 3e4;
|
|
86
|
+
constructor(options) {
|
|
87
|
+
this.sessionId = options.sessionId ?? "unknown";
|
|
88
|
+
this.internalToken = options.internalToken;
|
|
89
|
+
this.hubToken = options.hubToken;
|
|
90
|
+
this.directEvents = options.directEvents;
|
|
91
|
+
this.requestTimeoutMs = options.requestTimeoutMs ?? ComputerUseRequestBroker.DEFAULT_REQUEST_TIMEOUT_MS;
|
|
92
|
+
}
|
|
93
|
+
state() {
|
|
94
|
+
return Object.freeze({
|
|
95
|
+
sessionId: this.sessionId,
|
|
96
|
+
revision: this.revision,
|
|
97
|
+
wake: this.wake,
|
|
98
|
+
phase: this.phase,
|
|
99
|
+
...this.activation === void 0 ? {} : {
|
|
100
|
+
requestId: this.activation.requestId,
|
|
101
|
+
target: this.activation.target,
|
|
102
|
+
durationMs: this.activation.durationSeconds * 1e3
|
|
103
|
+
},
|
|
104
|
+
...this.expiresAt === void 0 ? {} : { expiresAt: this.expiresAt },
|
|
105
|
+
...this.failure === void 0 ? {} : { failure: this.failure },
|
|
106
|
+
...this.artifact === void 0 ? {} : { artifact: this.artifact }
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
changed() {
|
|
110
|
+
this.revision += 1;
|
|
111
|
+
this.wake = (this.wake + 1) % require_computerUseApi.COMPUTER_USE_WAKE_LIMIT;
|
|
112
|
+
this.directEvents.publish(require_computerUseApi.computerUseChannelType, this.sessionId, this.state());
|
|
113
|
+
}
|
|
114
|
+
authorized(request, token) {
|
|
115
|
+
return token !== void 0 && request.headers.get("authorization") === `Bearer ${token}`;
|
|
116
|
+
}
|
|
117
|
+
async requestActivation(request) {
|
|
118
|
+
const caller = (0, _agimon_ai_doompi_core_package_api.doomApiCallerFrom)(request.headers);
|
|
119
|
+
if (caller === void 0 || caller.locality === "remote" && caller.stepUp === "not-required") return jsonError("Not found.", 404);
|
|
120
|
+
if (this.phase !== "inactive" && this.phase !== "failed") return jsonError("Computer use is already busy.", 409);
|
|
121
|
+
const input = await body(request);
|
|
122
|
+
const target = record(input.target);
|
|
123
|
+
const durationMs = input.durationMs;
|
|
124
|
+
if (target === void 0 || typeof target.windowId !== "string" || typeof target.bundleId !== "string") return jsonError("A Desktop target is required.", 400);
|
|
125
|
+
if (typeof durationMs !== "number" || !Number.isInteger(durationMs) || durationMs < 1e3 || durationMs > 18e5) return jsonError("The requested duration is invalid.", 400);
|
|
126
|
+
const createdAt = Date.now();
|
|
127
|
+
this.activation = Object.freeze({
|
|
128
|
+
requestId: (0, node_crypto.randomUUID)(),
|
|
129
|
+
target: Object.freeze({ ...target }),
|
|
130
|
+
durationSeconds: durationMs / 1e3,
|
|
131
|
+
createdAt,
|
|
132
|
+
confirmationExpiresAt: createdAt + require_computerUseApi.COMPUTER_USE_CONFIRMATION_WINDOW_MS,
|
|
133
|
+
caller: Object.freeze({ ...caller })
|
|
134
|
+
});
|
|
135
|
+
this.phase = "awaiting_confirmation";
|
|
136
|
+
this.failure = void 0;
|
|
137
|
+
this.artifact = void 0;
|
|
138
|
+
this.changed();
|
|
139
|
+
return Response.json(this.state(), { status: 202 });
|
|
140
|
+
}
|
|
141
|
+
rejectPending(message) {
|
|
142
|
+
const pending = this.pending;
|
|
143
|
+
if (pending === void 0) return;
|
|
144
|
+
this.pending = void 0;
|
|
145
|
+
pending.dispose();
|
|
146
|
+
pending.reject(new Error(message));
|
|
147
|
+
}
|
|
148
|
+
stopAfterUncertainRequest(message) {
|
|
149
|
+
if (this.phase === "active") {
|
|
150
|
+
this.phase = "stopping";
|
|
151
|
+
this.changed();
|
|
152
|
+
}
|
|
153
|
+
this.rejectPending(message);
|
|
154
|
+
}
|
|
155
|
+
async enqueue(operation, payload, signal) {
|
|
156
|
+
if (this.phase !== "active" || this.grantId === void 0) return jsonError("Computer use is not active.", 409);
|
|
157
|
+
if (this.pending !== void 0) return jsonError("Another computer-use request is live.", 409);
|
|
158
|
+
if (signal?.aborted === true) return jsonError("The computer-use request was cancelled.", 499);
|
|
159
|
+
const sequence = operation === "act" ? ++this.actionSequence : void 0;
|
|
160
|
+
const request = {
|
|
161
|
+
id: (0, node_crypto.randomUUID)(),
|
|
162
|
+
operation,
|
|
163
|
+
grantId: this.grantId,
|
|
164
|
+
...sequence === void 0 ? {} : { sequence },
|
|
165
|
+
...payload === void 0 ? {} : { payload }
|
|
166
|
+
};
|
|
167
|
+
const completion = new Promise((resolve, reject) => {
|
|
168
|
+
const onAbort = () => this.stopAfterUncertainRequest("The computer-use request was cancelled.");
|
|
169
|
+
const timer = setTimeout(() => this.stopAfterUncertainRequest("The computer-use request timed out."), this.requestTimeoutMs);
|
|
170
|
+
timer.unref?.();
|
|
171
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
172
|
+
this.pending = {
|
|
173
|
+
request,
|
|
174
|
+
resolve,
|
|
175
|
+
reject,
|
|
176
|
+
dispose: () => {
|
|
177
|
+
clearTimeout(timer);
|
|
178
|
+
signal?.removeEventListener("abort", onAbort);
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
});
|
|
182
|
+
this.changed();
|
|
183
|
+
try {
|
|
184
|
+
return Response.json(await completion);
|
|
185
|
+
} catch (error) {
|
|
186
|
+
return jsonError(error instanceof Error ? error.message : String(error), 502);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
async fetch(request) {
|
|
190
|
+
if (this.closed) return jsonError("Computer-use broker is closed.", 503);
|
|
191
|
+
const path = new URL(request.url).pathname;
|
|
192
|
+
if (request.method === "POST" && path === require_apiRoutes.default.activate.path) return this.requestActivation(request);
|
|
193
|
+
const agent = path.startsWith("/agent/");
|
|
194
|
+
const hub = path.startsWith("/hub/");
|
|
195
|
+
if (agent && !this.authorized(request, this.internalToken) || hub && !this.authorized(request, this.hubToken)) return jsonError("Not found.", 404);
|
|
196
|
+
if (request.method === "GET" && (path === require_apiRoutes.default.agentState.path || path === require_apiRoutes.default.hubState.path)) return Response.json(this.state());
|
|
197
|
+
if (request.method === "POST" && path === require_apiRoutes.default.agentObserve.path) return this.enqueue("observe", void 0, request.signal);
|
|
198
|
+
if (request.method === "POST" && path === require_apiRoutes.default.agentAction.path) {
|
|
199
|
+
const action = await body(request);
|
|
200
|
+
if (!semanticAction(action)) return jsonError("A valid semantic action is required.", 400);
|
|
201
|
+
return this.enqueue("act", action, request.signal);
|
|
202
|
+
}
|
|
203
|
+
if (request.method === "POST" && path === require_apiRoutes.default.agentStop.path) {
|
|
204
|
+
if (this.phase !== "active") return jsonError("Computer use is not active.", 409);
|
|
205
|
+
this.phase = "stopping";
|
|
206
|
+
this.rejectPending("The computer-use request was stopped.");
|
|
207
|
+
this.changed();
|
|
208
|
+
return Response.json(this.state(), { status: 202 });
|
|
209
|
+
}
|
|
210
|
+
if (request.method === "GET" && path === require_apiRoutes.default.hubActivation.path) {
|
|
211
|
+
if (this.activation === void 0 || this.phase !== "awaiting_confirmation") return Response.json(null);
|
|
212
|
+
this.phase = "activating";
|
|
213
|
+
this.changed();
|
|
214
|
+
return Response.json(this.activation);
|
|
215
|
+
}
|
|
216
|
+
if (request.method === "GET" && path === require_apiRoutes.default.hubAuthorization.path) return Response.json(this.grantId === void 0 ? null : {
|
|
217
|
+
grantId: this.grantId,
|
|
218
|
+
expiresAt: this.expiresAt
|
|
219
|
+
});
|
|
220
|
+
if (request.method === "GET" && path === require_apiRoutes.default.hubNext.path) return Response.json(this.pending?.request ?? null);
|
|
221
|
+
if (request.method === "POST" && path === require_apiRoutes.default.hubComplete.path) {
|
|
222
|
+
const input = await body(request);
|
|
223
|
+
const id = typeof input.id === "string" ? input.id : void 0;
|
|
224
|
+
if (this.pending === void 0 || this.pending.request.id !== id) return jsonError("The request is stale.", 409);
|
|
225
|
+
const pending = this.pending;
|
|
226
|
+
this.pending = void 0;
|
|
227
|
+
pending.dispose();
|
|
228
|
+
this.changed();
|
|
229
|
+
if (typeof input.error === "string") pending.reject(new Error(input.error));
|
|
230
|
+
else pending.resolve(input.result);
|
|
231
|
+
return Response.json(this.state());
|
|
232
|
+
}
|
|
233
|
+
if (request.method === "POST" && path === require_apiRoutes.default.hubStop.path) {
|
|
234
|
+
const input = await body(request);
|
|
235
|
+
if (this.phase === "activating") {
|
|
236
|
+
if (typeof input.error === "string") {
|
|
237
|
+
this.phase = "failed";
|
|
238
|
+
this.failure = {
|
|
239
|
+
code: "desktop_unavailable",
|
|
240
|
+
message: input.error.slice(0, 512)
|
|
241
|
+
};
|
|
242
|
+
this.activation = void 0;
|
|
243
|
+
} else {
|
|
244
|
+
const host = record(input.host);
|
|
245
|
+
if (typeof host?.grantId !== "string" || !Number.isFinite(host.expiresAt)) return jsonError("Desktop did not issue a complete grant.", 502);
|
|
246
|
+
this.grantId = host.grantId;
|
|
247
|
+
this.expiresAt = host.expiresAt;
|
|
248
|
+
this.actionSequence = 0;
|
|
249
|
+
this.phase = "active";
|
|
250
|
+
}
|
|
251
|
+
} else {
|
|
252
|
+
this.rejectPending("The computer-use session stopped.");
|
|
253
|
+
this.phase = "inactive";
|
|
254
|
+
this.grantId = void 0;
|
|
255
|
+
this.expiresAt = void 0;
|
|
256
|
+
this.activation = void 0;
|
|
257
|
+
this.artifact = artifactView(input.artifact);
|
|
258
|
+
}
|
|
259
|
+
this.changed();
|
|
260
|
+
return Response.json(this.state());
|
|
261
|
+
}
|
|
262
|
+
return jsonError("Not found.", 404);
|
|
263
|
+
}
|
|
264
|
+
close() {
|
|
265
|
+
this.closed = true;
|
|
266
|
+
this.rejectPending("Computer-use broker closed.");
|
|
267
|
+
this.grantId = void 0;
|
|
268
|
+
this.expiresAt = void 0;
|
|
269
|
+
}
|
|
270
|
+
};
|
|
271
|
+
function createComputerUseApi(options) {
|
|
272
|
+
return new ComputerUseRequestBroker(options);
|
|
273
|
+
}
|
|
274
|
+
const api = {
|
|
275
|
+
basePath: require_computerUseApi.API_BASE_PATH,
|
|
276
|
+
start(context) {
|
|
277
|
+
if (context.directEvents === void 0) throw new Error("Computer-use API requires the session direct event bus.");
|
|
278
|
+
return createComputerUseApi({
|
|
279
|
+
...context.sessionId === void 0 ? {} : { sessionId: context.sessionId },
|
|
280
|
+
...context.internalToken === void 0 ? {} : { internalToken: context.internalToken },
|
|
281
|
+
...context.hubToken === void 0 ? {} : { hubToken: context.hubToken },
|
|
282
|
+
directEvents: context.directEvents
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
};
|
|
286
|
+
//#endregion
|
|
287
|
+
exports.ComputerUseRequestBroker = ComputerUseRequestBroker;
|
|
288
|
+
exports.api = api;
|
|
289
|
+
exports.createComputerUseApi = createComputerUseApi;
|
|
290
|
+
|
|
291
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["COMPUTER_USE_WAKE_LIMIT","computerUseChannelType","doomApiCallerFrom","randomUUID","COMPUTER_USE_CONFIRMATION_WINDOW_MS","routes","API_BASE_PATH"],"sources":["../../../../src/services/computerUseApi/index.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto';\n\nimport type { DoomDirectEventBus } from '@agimon-ai/doompi-core/hub-channel';\nimport {\n doomApiCallerFrom,\n type DoomApi,\n type DoomApiContext,\n type DoomApiHandler,\n} from '@agimon-ai/doompi-core/package-api';\n\nimport routes from '../../types/apiRoutes';\nimport {\n API_BASE_PATH,\n computerUseChannelType,\n COMPUTER_USE_CONFIRMATION_WINDOW_MS,\n COMPUTER_USE_MAX_DURATION_MS,\n COMPUTER_USE_WAKE_LIMIT,\n type ComputerUseActivationRequest,\n type ComputerUseArtifactView,\n type ComputerUseBrokerRequest,\n type ComputerUseSessionView,\n} from '../../types/computerUseApi';\n\ninterface PendingRequest {\n readonly request: ComputerUseBrokerRequest;\n readonly dispose: () => void;\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' || value.kind === 'focus') 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 const artifactFailure = record(input.failure);\n const safeFailure =\n typeof artifactFailure?.code === 'string' && typeof artifactFailure.message === 'string'\n ? { code: artifactFailure.code.slice(0, 128), message: artifactFailure.message.slice(0, 512) }\n : undefined;\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 ...(safeFailure === undefined ? {} : { failure: safeFailure }),\n };\n}\n\nexport interface ComputerUseApiOptions {\n readonly sessionId?: string;\n readonly internalToken?: string;\n readonly hubToken?: string;\n readonly directEvents: DoomDirectEventBus;\n readonly requestTimeoutMs?: number;\n}\n\nexport class ComputerUseRequestBroker implements DoomApiHandler {\n private readonly sessionId: string;\n private readonly internalToken?: string;\n private readonly hubToken?: string;\n private readonly directEvents: DoomDirectEventBus;\n private readonly requestTimeoutMs: number;\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 private static readonly DEFAULT_REQUEST_TIMEOUT_MS = 30_000;\n public constructor(options: ComputerUseApiOptions) {\n this.sessionId = options.sessionId ?? 'unknown';\n this.internalToken = options.internalToken;\n this.hubToken = options.hubToken;\n this.directEvents = options.directEvents;\n this.requestTimeoutMs = options.requestTimeoutMs ?? ComputerUseRequestBroker.DEFAULT_REQUEST_TIMEOUT_MS;\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 this.directEvents.publish(computerUseChannelType, this.sessionId, this.state());\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 rejectPending(message: string): void {\n const pending = this.pending;\n if (pending === undefined) return;\n this.pending = undefined;\n pending.dispose();\n pending.reject(new Error(message));\n }\n\n private stopAfterUncertainRequest(message: string): void {\n if (this.phase === 'active') {\n this.phase = 'stopping';\n this.changed();\n }\n this.rejectPending(message);\n }\n\n private async enqueue(\n operation: ComputerUseBrokerRequest['operation'],\n payload?: unknown,\n signal?: AbortSignal,\n ): 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 if (signal?.aborted === true) return jsonError('The computer-use request was cancelled.', 499);\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 const onAbort = () => this.stopAfterUncertainRequest('The computer-use request was cancelled.');\n const timer = setTimeout(\n () => this.stopAfterUncertainRequest('The computer-use request timed out.'),\n this.requestTimeoutMs,\n );\n timer.unref?.();\n signal?.addEventListener('abort', onAbort, { once: true });\n this.pending = {\n request,\n resolve,\n reject,\n dispose: () => {\n clearTimeout(timer);\n signal?.removeEventListener('abort', onAbort);\n },\n };\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 === routes.activate.path) 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 === routes.agentState.path || path === routes.hubState.path))\n return Response.json(this.state());\n if (request.method === 'POST' && path === routes.agentObserve.path)\n return this.enqueue('observe', undefined, request.signal);\n if (request.method === 'POST' && path === routes.agentAction.path) {\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, request.signal);\n }\n if (request.method === 'POST' && path === routes.agentStop.path) {\n if (this.phase !== 'active') return jsonError('Computer use is not active.', 409);\n this.phase = 'stopping';\n this.rejectPending('The computer-use request was stopped.');\n this.changed();\n return Response.json(this.state(), { status: 202 });\n }\n if (request.method === 'GET' && path === routes.hubActivation.path) {\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 === routes.hubAuthorization.path)\n return Response.json(this.grantId === undefined ? null : { grantId: this.grantId, expiresAt: this.expiresAt });\n if (request.method === 'GET' && path === routes.hubNext.path) return Response.json(this.pending?.request ?? null);\n if (request.method === 'POST' && path === routes.hubComplete.path) {\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 pending.dispose();\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 === routes.hubStop.path) {\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.rejectPending('The computer-use session stopped.');\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.rejectPending('Computer-use broker closed.');\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 if (context.directEvents === undefined) throw new Error('Computer-use API requires the session direct event bus.');\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 directEvents: context.directEvents,\n });\n },\n};\n"],"mappings":";;;;;AA8BA,SAAS,UAAU,SAAiB,QAA0B;CAC5D,OAAO,SAAS,KAAK,EAAE,OAAO,QAAQ,GAAG,EAAE,OAAO,CAAC;AACrD;AAEA,SAAS,OAAO,OAAqD;CACnE,OAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK,IACrE,QACD,KAAA;AACN;AAEA,eAAe,KAAK,SAAoD;CACtE,IAAI;EACF,OAAO,OAAO,MAAM,QAAQ,KAAK,CAAC,KAAK,CAAC;CAC1C,QAAQ;EACN,OAAO,CAAC;CACV;AACF;AAEA,SAAS,eAAe,OAAyC;CAM/D,IAAI,EAJF,OAAO,MAAM,eAAe,YAC5B,MAAM,WAAW,SAAS,KAC1B,OAAO,MAAM,eAAe,YAC5B,MAAM,WAAW,SAAS,IACjB,OAAO;CAClB,MAAM,WAAW,SAA4B,OAAO,KAAK,KAAK,CAAC,CAAC,OAAO,QAAQ,KAAK,SAAS,GAAG,CAAC;CACjG,IAAI,MAAM,SAAS,WAAW,MAAM,SAAS,SAAS,OAAO,QAAQ;EAAC;EAAQ;EAAc;CAAY,CAAC;CACzG,IAAI,MAAM,SAAS,aACjB,OAAO,OAAO,MAAM,UAAU,YAAY,QAAQ;EAAC;EAAQ;EAAc;EAAc;CAAO,CAAC;CACjG,IAAI,MAAM,SAAS,UACjB,OACE;EAAC;EAAM;EAAQ;EAAQ;CAAO,CAAC,CAAC,SAAS,MAAM,SAAmB,MACjE,MAAM,WAAW,UAAU,MAAM,WAAW,WAC7C,QAAQ;EAAC;EAAQ;EAAc;EAAc;EAAa;CAAQ,CAAC;CAEvE,OAAO;AACT;AACA,SAAS,aAAa,OAAqD;CACzE,MAAM,QAAQ,OAAO,KAAK;CAC1B,IAAI,OAAO,OAAO,eAAe,YAAa,MAAM,WAAW,WAAW,MAAM,WAAW,UACzF,OAAO,KAAA;CACT,MAAM,WAAW,cACf,OAAO,cAAc,YAAY,UAAU,WAAW,OAAO,IAAI,YAAY,KAAA;CAC/E,MAAM,cAAc,QAAQ,MAAM,WAAW;CAC7C,MAAM,aAAa,QAAQ,MAAM,UAAU;CAC3C,MAAM,kBAAkB,OAAO,MAAM,OAAO;CAC5C,MAAM,cACJ,OAAO,iBAAiB,SAAS,YAAY,OAAO,gBAAgB,YAAY,WAC5E;EAAE,MAAM,gBAAgB,KAAK,MAAM,GAAG,GAAG;EAAG,SAAS,gBAAgB,QAAQ,MAAM,GAAG,GAAG;CAAE,IAC3F,KAAA;CACN,OAAO;EACL,YAAY,MAAM;EAClB,QAAQ,MAAM;EACd,GAAI,gBAAgB,KAAA,IAAY,CAAC,IAAI,EAAE,YAAY;EACnD,GAAI,eAAe,KAAA,IAAY,CAAC,IAAI,EAAE,WAAW;EACjD,GAAI,OAAO,MAAM,gBAAgB,WAAW,EAAE,aAAa,MAAM,YAAY,IAAI,CAAC;EAClF,GAAI,OAAO,MAAM,gBAAgB,WAAW,EAAE,aAAa,MAAM,YAAY,IAAI,CAAC;EAClF,GAAI,gBAAgB,KAAA,IAAY,CAAC,IAAI,EAAE,SAAS,YAAY;CAC9D;AACF;AAUA,IAAa,2BAAb,MAAa,yBAAmD;CAC9D;CACA;CACA;CACA;CACA;CACA,WAAmB;CACnB,OAAe;CACf,QAAiD;CACjD;CACA;CACA;CACA,iBAAyB;CACzB;CACA;CACA;CACA,SAAiB;CAEjB,OAAwB,6BAA6B;CACrD,YAAmB,SAAgC;EACjD,KAAK,YAAY,QAAQ,aAAa;EACtC,KAAK,gBAAgB,QAAQ;EAC7B,KAAK,WAAW,QAAQ;EACxB,KAAK,eAAe,QAAQ;EAC5B,KAAK,mBAAmB,QAAQ,oBAAoB,yBAAyB;CAC/E;CAEA,QAAuC;EACrC,OAAO,OAAO,OAAO;GACnB,WAAW,KAAK;GAChB,UAAU,KAAK;GACf,MAAM,KAAK;GACX,OAAO,KAAK;GACZ,GAAI,KAAK,eAAe,KAAA,IACpB,CAAC,IACD;IACE,WAAW,KAAK,WAAW;IAC3B,QAAQ,KAAK,WAAW;IACxB,YAAY,KAAK,WAAW,kBAAkB;GAChD;GACJ,GAAI,KAAK,cAAc,KAAA,IAAY,CAAC,IAAI,EAAE,WAAW,KAAK,UAAU;GACpE,GAAI,KAAK,YAAY,KAAA,IAAY,CAAC,IAAI,EAAE,SAAS,KAAK,QAAQ;GAC9D,GAAI,KAAK,aAAa,KAAA,IAAY,CAAC,IAAI,EAAE,UAAU,KAAK,SAAS;EACnE,CAAC;CACH;CAEA,UAAwB;EACtB,KAAK,YAAY;EACjB,KAAK,QAAQ,KAAK,OAAO,KAAKA,uBAAAA;EAC9B,KAAK,aAAa,QAAQC,uBAAAA,wBAAwB,KAAK,WAAW,KAAK,MAAM,CAAC;CAChF;CAEA,WAAmB,SAAkB,OAAoC;EACvE,OAAO,UAAU,KAAA,KAAa,QAAQ,QAAQ,IAAI,eAAe,MAAM,UAAU;CACnF;CAEA,MAAc,kBAAkB,SAAqC;EACnE,MAAM,UAAA,GAASC,mCAAAA,kBAAAA,CAAkB,QAAQ,OAAO;EAChD,IAAI,WAAW,KAAA,KAAc,OAAO,aAAa,YAAY,OAAO,WAAW,gBAC7E,OAAO,UAAU,cAAc,GAAG;EACpC,IAAI,KAAK,UAAU,cAAc,KAAK,UAAU,UAAU,OAAO,UAAU,iCAAiC,GAAG;EAC/G,MAAM,QAAQ,MAAM,KAAK,OAAO;EAChC,MAAM,SAAS,OAAO,MAAM,MAAM;EAClC,MAAM,aAAa,MAAM;EACzB,IAAI,WAAW,KAAA,KAAa,OAAO,OAAO,aAAa,YAAY,OAAO,OAAO,aAAa,UAC5F,OAAO,UAAU,iCAAiC,GAAG;EACvD,IACE,OAAO,eAAe,YACtB,CAAC,OAAO,UAAU,UAAU,KAC5B,aAAa,OACb,aAAA,MAEA,OAAO,UAAU,sCAAsC,GAAG;EAC5D,MAAM,YAAY,KAAK,IAAI;EAC3B,KAAK,aAAa,OAAO,OAAO;GAC9B,YAAA,GAAWC,YAAAA,WAAAA,CAAW;GACtB,QAAQ,OAAO,OAAO,EAAE,GAAG,OAAO,CAAC;GACnC,iBAAiB,aAAa;GAC9B;GACA,uBAAuB,YAAYC,uBAAAA;GACnC,QAAQ,OAAO,OAAO,EAAE,GAAG,OAAO,CAAC;EACrC,CAAC;EACD,KAAK,QAAQ;EACb,KAAK,UAAU,KAAA;EACf,KAAK,WAAW,KAAA;EAChB,KAAK,QAAQ;EACb,OAAO,SAAS,KAAK,KAAK,MAAM,GAAG,EAAE,QAAQ,IAAI,CAAC;CACpD;CAEA,cAAsB,SAAuB;EAC3C,MAAM,UAAU,KAAK;EACrB,IAAI,YAAY,KAAA,GAAW;EAC3B,KAAK,UAAU,KAAA;EACf,QAAQ,QAAQ;EAChB,QAAQ,OAAO,IAAI,MAAM,OAAO,CAAC;CACnC;CAEA,0BAAkC,SAAuB;EACvD,IAAI,KAAK,UAAU,UAAU;GAC3B,KAAK,QAAQ;GACb,KAAK,QAAQ;EACf;EACA,KAAK,cAAc,OAAO;CAC5B;CAEA,MAAc,QACZ,WACA,SACA,QACmB;EACnB,IAAI,KAAK,UAAU,YAAY,KAAK,YAAY,KAAA,GAAW,OAAO,UAAU,+BAA+B,GAAG;EAC9G,IAAI,KAAK,YAAY,KAAA,GAAW,OAAO,UAAU,yCAAyC,GAAG;EAC7F,IAAI,QAAQ,YAAY,MAAM,OAAO,UAAU,2CAA2C,GAAG;EAC7F,MAAM,WAAW,cAAc,QAAQ,EAAE,KAAK,iBAAiB,KAAA;EAC/D,MAAM,UAAoC;GACxC,KAAA,GAAID,YAAAA,WAAAA,CAAW;GACf;GACA,SAAS,KAAK;GACd,GAAI,aAAa,KAAA,IAAY,CAAC,IAAI,EAAE,SAAS;GAC7C,GAAI,YAAY,KAAA,IAAY,CAAC,IAAI,EAAE,QAAQ;EAC7C;EACA,MAAM,aAAa,IAAI,SAAkB,SAAS,WAAW;GAC3D,MAAM,gBAAgB,KAAK,0BAA0B,yCAAyC;GAC9F,MAAM,QAAQ,iBACN,KAAK,0BAA0B,qCAAqC,GAC1E,KAAK,gBACP;GACA,MAAM,QAAQ;GACd,QAAQ,iBAAiB,SAAS,SAAS,EAAE,MAAM,KAAK,CAAC;GACzD,KAAK,UAAU;IACb;IACA;IACA;IACA,eAAe;KACb,aAAa,KAAK;KAClB,QAAQ,oBAAoB,SAAS,OAAO;IAC9C;GACF;EACF,CAAC;EACD,KAAK,QAAQ;EACb,IAAI;GACF,OAAO,SAAS,KAAK,MAAM,UAAU;EACvC,SAAS,OAAO;GACd,OAAO,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,GAAG,GAAG;EAC9E;CACF;CAEA,MAAa,MAAM,SAAqC;EACtD,IAAI,KAAK,QAAQ,OAAO,UAAU,kCAAkC,GAAG;EACvE,MAAM,OAAO,IAAI,IAAI,QAAQ,GAAG,CAAC,CAAC;EAClC,IAAI,QAAQ,WAAW,UAAU,SAASE,kBAAAA,QAAO,SAAS,MAAM,OAAO,KAAK,kBAAkB,OAAO;EACrG,MAAM,QAAQ,KAAK,WAAW,SAAS;EACvC,MAAM,MAAM,KAAK,WAAW,OAAO;EACnC,IAAK,SAAS,CAAC,KAAK,WAAW,SAAS,KAAK,aAAa,KAAO,OAAO,CAAC,KAAK,WAAW,SAAS,KAAK,QAAQ,GAC7G,OAAO,UAAU,cAAc,GAAG;EAEpC,IAAI,QAAQ,WAAW,UAAU,SAASA,kBAAAA,QAAO,WAAW,QAAQ,SAASA,kBAAAA,QAAO,SAAS,OAC3F,OAAO,SAAS,KAAK,KAAK,MAAM,CAAC;EACnC,IAAI,QAAQ,WAAW,UAAU,SAASA,kBAAAA,QAAO,aAAa,MAC5D,OAAO,KAAK,QAAQ,WAAW,KAAA,GAAW,QAAQ,MAAM;EAC1D,IAAI,QAAQ,WAAW,UAAU,SAASA,kBAAAA,QAAO,YAAY,MAAM;GACjE,MAAM,SAAS,MAAM,KAAK,OAAO;GACjC,IAAI,CAAC,eAAe,MAAM,GAAG,OAAO,UAAU,wCAAwC,GAAG;GACzF,OAAO,KAAK,QAAQ,OAAO,QAAQ,QAAQ,MAAM;EACnD;EACA,IAAI,QAAQ,WAAW,UAAU,SAASA,kBAAAA,QAAO,UAAU,MAAM;GAC/D,IAAI,KAAK,UAAU,UAAU,OAAO,UAAU,+BAA+B,GAAG;GAChF,KAAK,QAAQ;GACb,KAAK,cAAc,uCAAuC;GAC1D,KAAK,QAAQ;GACb,OAAO,SAAS,KAAK,KAAK,MAAM,GAAG,EAAE,QAAQ,IAAI,CAAC;EACpD;EACA,IAAI,QAAQ,WAAW,SAAS,SAASA,kBAAAA,QAAO,cAAc,MAAM;GAClE,IAAI,KAAK,eAAe,KAAA,KAAa,KAAK,UAAU,yBAAyB,OAAO,SAAS,KAAK,IAAI;GACtG,KAAK,QAAQ;GACb,KAAK,QAAQ;GACb,OAAO,SAAS,KAAK,KAAK,UAAU;EACtC;EACA,IAAI,QAAQ,WAAW,SAAS,SAASA,kBAAAA,QAAO,iBAAiB,MAC/D,OAAO,SAAS,KAAK,KAAK,YAAY,KAAA,IAAY,OAAO;GAAE,SAAS,KAAK;GAAS,WAAW,KAAK;EAAU,CAAC;EAC/G,IAAI,QAAQ,WAAW,SAAS,SAASA,kBAAAA,QAAO,QAAQ,MAAM,OAAO,SAAS,KAAK,KAAK,SAAS,WAAW,IAAI;EAChH,IAAI,QAAQ,WAAW,UAAU,SAASA,kBAAAA,QAAO,YAAY,MAAM;GACjE,MAAM,QAAQ,MAAM,KAAK,OAAO;GAChC,MAAM,KAAK,OAAO,MAAM,OAAO,WAAW,MAAM,KAAK,KAAA;GACrD,IAAI,KAAK,YAAY,KAAA,KAAa,KAAK,QAAQ,QAAQ,OAAO,IAAI,OAAO,UAAU,yBAAyB,GAAG;GAC/G,MAAM,UAAU,KAAK;GACrB,KAAK,UAAU,KAAA;GACf,QAAQ,QAAQ;GAChB,KAAK,QAAQ;GACb,IAAI,OAAO,MAAM,UAAU,UAAU,QAAQ,OAAO,IAAI,MAAM,MAAM,KAAK,CAAC;QACrE,QAAQ,QAAQ,MAAM,MAAM;GACjC,OAAO,SAAS,KAAK,KAAK,MAAM,CAAC;EACnC;EACA,IAAI,QAAQ,WAAW,UAAU,SAASA,kBAAAA,QAAO,QAAQ,MAAM;GAC7D,MAAM,QAAQ,MAAM,KAAK,OAAO;GAChC,IAAI,KAAK,UAAU,cAAc;IAC/B,IAAI,OAAO,MAAM,UAAU,UAAU;KACnC,KAAK,QAAQ;KACb,KAAK,UAAU;MAAE,MAAM;MAAuB,SAAS,MAAM,MAAM,MAAM,GAAG,GAAG;KAAE;KACjF,KAAK,aAAa,KAAA;IACpB,OAAO;KACL,MAAM,OAAO,OAAO,MAAM,IAAI;KAC9B,IAAI,OAAO,MAAM,YAAY,YAAY,CAAC,OAAO,SAAS,KAAK,SAAS,GACtE,OAAO,UAAU,2CAA2C,GAAG;KACjE,KAAK,UAAU,KAAK;KACpB,KAAK,YAAY,KAAK;KACtB,KAAK,iBAAiB;KACtB,KAAK,QAAQ;IACf;GACF,OAAO;IACL,KAAK,cAAc,mCAAmC;IACtD,KAAK,QAAQ;IACb,KAAK,UAAU,KAAA;IACf,KAAK,YAAY,KAAA;IACjB,KAAK,aAAa,KAAA;IAClB,KAAK,WAAW,aAAa,MAAM,QAAQ;GAC7C;GACA,KAAK,QAAQ;GACb,OAAO,SAAS,KAAK,KAAK,MAAM,CAAC;EACnC;EACA,OAAO,UAAU,cAAc,GAAG;CACpC;CAEA,QAAqB;EACnB,KAAK,SAAS;EACd,KAAK,cAAc,6BAA6B;EAChD,KAAK,UAAU,KAAA;EACf,KAAK,YAAY,KAAA;CACnB;AACF;AAEA,SAAgB,qBAAqB,SAA0D;CAC7F,OAAO,IAAI,yBAAyB,OAAO;AAC7C;AAEA,MAAa,MAAe;CAC1B,UAAUC,uBAAAA;CACV,MAAM,SAAyC;EAC7C,IAAI,QAAQ,iBAAiB,KAAA,GAAW,MAAM,IAAI,MAAM,yDAAyD;EACjH,OAAO,qBAAqB;GAC1B,GAAI,QAAQ,cAAc,KAAA,IAAY,CAAC,IAAI,EAAE,WAAW,QAAQ,UAAU;GAC1E,GAAI,QAAQ,kBAAkB,KAAA,IAAY,CAAC,IAAI,EAAE,eAAe,QAAQ,cAAc;GACtF,GAAI,QAAQ,aAAa,KAAA,IAAY,CAAC,IAAI,EAAE,UAAU,QAAQ,SAAS;GACvE,cAAc,QAAQ;EACxB,CAAC;CACH;AACF"}
|
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
import { API_BASE_PATH, COMPUTER_USE_CONFIRMATION_WINDOW_MS, COMPUTER_USE_WAKE_LIMIT, computerUseChannelType } from "../../types/computerUseApi.mjs";
|
|
2
|
+
import apiRoutes_default from "../../types/apiRoutes.mjs";
|
|
3
|
+
import { randomUUID } from "node:crypto";
|
|
4
|
+
import { doomApiCallerFrom } from "@agimon-ai/doompi-core/package-api";
|
|
5
|
+
//#region src/services/computerUseApi/index.ts
|
|
6
|
+
function jsonError(message, status) {
|
|
7
|
+
return Response.json({ error: message }, { status });
|
|
8
|
+
}
|
|
9
|
+
function record(value) {
|
|
10
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
|
|
11
|
+
}
|
|
12
|
+
async function body(request) {
|
|
13
|
+
try {
|
|
14
|
+
return record(await request.json()) ?? {};
|
|
15
|
+
} catch {
|
|
16
|
+
return {};
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
function semanticAction(value) {
|
|
20
|
+
if (!(typeof value.snapshotId === "string" && value.snapshotId.length > 0 && typeof value.elementRef === "string" && value.elementRef.length > 0)) return false;
|
|
21
|
+
const allowed = (keys) => Object.keys(value).every((key) => keys.includes(key));
|
|
22
|
+
if (value.kind === "press" || value.kind === "focus") return allowed([
|
|
23
|
+
"kind",
|
|
24
|
+
"snapshotId",
|
|
25
|
+
"elementRef"
|
|
26
|
+
]);
|
|
27
|
+
if (value.kind === "set_value") return typeof value.value === "string" && allowed([
|
|
28
|
+
"kind",
|
|
29
|
+
"snapshotId",
|
|
30
|
+
"elementRef",
|
|
31
|
+
"value"
|
|
32
|
+
]);
|
|
33
|
+
if (value.kind === "scroll") return [
|
|
34
|
+
"up",
|
|
35
|
+
"down",
|
|
36
|
+
"left",
|
|
37
|
+
"right"
|
|
38
|
+
].includes(value.direction) && (value.amount === "line" || value.amount === "page") && allowed([
|
|
39
|
+
"kind",
|
|
40
|
+
"snapshotId",
|
|
41
|
+
"elementRef",
|
|
42
|
+
"direction",
|
|
43
|
+
"amount"
|
|
44
|
+
]);
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
function artifactView(value) {
|
|
48
|
+
const input = record(value);
|
|
49
|
+
if (typeof input?.artifactId !== "string" || input.status !== "ready" && input.status !== "failed") return void 0;
|
|
50
|
+
const safeUrl = (candidate) => typeof candidate === "string" && candidate.startsWith("/api/") ? candidate : void 0;
|
|
51
|
+
const downloadUrl = safeUrl(input.downloadUrl);
|
|
52
|
+
const previewUrl = safeUrl(input.previewUrl);
|
|
53
|
+
const artifactFailure = record(input.failure);
|
|
54
|
+
const safeFailure = typeof artifactFailure?.code === "string" && typeof artifactFailure.message === "string" ? {
|
|
55
|
+
code: artifactFailure.code.slice(0, 128),
|
|
56
|
+
message: artifactFailure.message.slice(0, 512)
|
|
57
|
+
} : void 0;
|
|
58
|
+
return {
|
|
59
|
+
artifactId: input.artifactId,
|
|
60
|
+
status: input.status,
|
|
61
|
+
...downloadUrl === void 0 ? {} : { downloadUrl },
|
|
62
|
+
...previewUrl === void 0 ? {} : { previewUrl },
|
|
63
|
+
...typeof input.actionCount === "number" ? { actionCount: input.actionCount } : {},
|
|
64
|
+
...typeof input.completedAt === "string" ? { completedAt: input.completedAt } : {},
|
|
65
|
+
...safeFailure === void 0 ? {} : { failure: safeFailure }
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
var ComputerUseRequestBroker = class ComputerUseRequestBroker {
|
|
69
|
+
sessionId;
|
|
70
|
+
internalToken;
|
|
71
|
+
hubToken;
|
|
72
|
+
directEvents;
|
|
73
|
+
requestTimeoutMs;
|
|
74
|
+
revision = 0;
|
|
75
|
+
wake = 0;
|
|
76
|
+
phase = "inactive";
|
|
77
|
+
activation;
|
|
78
|
+
grantId;
|
|
79
|
+
expiresAt;
|
|
80
|
+
actionSequence = 0;
|
|
81
|
+
failure;
|
|
82
|
+
artifact;
|
|
83
|
+
pending;
|
|
84
|
+
closed = false;
|
|
85
|
+
static DEFAULT_REQUEST_TIMEOUT_MS = 3e4;
|
|
86
|
+
constructor(options) {
|
|
87
|
+
this.sessionId = options.sessionId ?? "unknown";
|
|
88
|
+
this.internalToken = options.internalToken;
|
|
89
|
+
this.hubToken = options.hubToken;
|
|
90
|
+
this.directEvents = options.directEvents;
|
|
91
|
+
this.requestTimeoutMs = options.requestTimeoutMs ?? ComputerUseRequestBroker.DEFAULT_REQUEST_TIMEOUT_MS;
|
|
92
|
+
}
|
|
93
|
+
state() {
|
|
94
|
+
return Object.freeze({
|
|
95
|
+
sessionId: this.sessionId,
|
|
96
|
+
revision: this.revision,
|
|
97
|
+
wake: this.wake,
|
|
98
|
+
phase: this.phase,
|
|
99
|
+
...this.activation === void 0 ? {} : {
|
|
100
|
+
requestId: this.activation.requestId,
|
|
101
|
+
target: this.activation.target,
|
|
102
|
+
durationMs: this.activation.durationSeconds * 1e3
|
|
103
|
+
},
|
|
104
|
+
...this.expiresAt === void 0 ? {} : { expiresAt: this.expiresAt },
|
|
105
|
+
...this.failure === void 0 ? {} : { failure: this.failure },
|
|
106
|
+
...this.artifact === void 0 ? {} : { artifact: this.artifact }
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
changed() {
|
|
110
|
+
this.revision += 1;
|
|
111
|
+
this.wake = (this.wake + 1) % COMPUTER_USE_WAKE_LIMIT;
|
|
112
|
+
this.directEvents.publish(computerUseChannelType, this.sessionId, this.state());
|
|
113
|
+
}
|
|
114
|
+
authorized(request, token) {
|
|
115
|
+
return token !== void 0 && request.headers.get("authorization") === `Bearer ${token}`;
|
|
116
|
+
}
|
|
117
|
+
async requestActivation(request) {
|
|
118
|
+
const caller = doomApiCallerFrom(request.headers);
|
|
119
|
+
if (caller === void 0 || caller.locality === "remote" && caller.stepUp === "not-required") return jsonError("Not found.", 404);
|
|
120
|
+
if (this.phase !== "inactive" && this.phase !== "failed") return jsonError("Computer use is already busy.", 409);
|
|
121
|
+
const input = await body(request);
|
|
122
|
+
const target = record(input.target);
|
|
123
|
+
const durationMs = input.durationMs;
|
|
124
|
+
if (target === void 0 || typeof target.windowId !== "string" || typeof target.bundleId !== "string") return jsonError("A Desktop target is required.", 400);
|
|
125
|
+
if (typeof durationMs !== "number" || !Number.isInteger(durationMs) || durationMs < 1e3 || durationMs > 18e5) return jsonError("The requested duration is invalid.", 400);
|
|
126
|
+
const createdAt = Date.now();
|
|
127
|
+
this.activation = Object.freeze({
|
|
128
|
+
requestId: randomUUID(),
|
|
129
|
+
target: Object.freeze({ ...target }),
|
|
130
|
+
durationSeconds: durationMs / 1e3,
|
|
131
|
+
createdAt,
|
|
132
|
+
confirmationExpiresAt: createdAt + COMPUTER_USE_CONFIRMATION_WINDOW_MS,
|
|
133
|
+
caller: Object.freeze({ ...caller })
|
|
134
|
+
});
|
|
135
|
+
this.phase = "awaiting_confirmation";
|
|
136
|
+
this.failure = void 0;
|
|
137
|
+
this.artifact = void 0;
|
|
138
|
+
this.changed();
|
|
139
|
+
return Response.json(this.state(), { status: 202 });
|
|
140
|
+
}
|
|
141
|
+
rejectPending(message) {
|
|
142
|
+
const pending = this.pending;
|
|
143
|
+
if (pending === void 0) return;
|
|
144
|
+
this.pending = void 0;
|
|
145
|
+
pending.dispose();
|
|
146
|
+
pending.reject(new Error(message));
|
|
147
|
+
}
|
|
148
|
+
stopAfterUncertainRequest(message) {
|
|
149
|
+
if (this.phase === "active") {
|
|
150
|
+
this.phase = "stopping";
|
|
151
|
+
this.changed();
|
|
152
|
+
}
|
|
153
|
+
this.rejectPending(message);
|
|
154
|
+
}
|
|
155
|
+
async enqueue(operation, payload, signal) {
|
|
156
|
+
if (this.phase !== "active" || this.grantId === void 0) return jsonError("Computer use is not active.", 409);
|
|
157
|
+
if (this.pending !== void 0) return jsonError("Another computer-use request is live.", 409);
|
|
158
|
+
if (signal?.aborted === true) return jsonError("The computer-use request was cancelled.", 499);
|
|
159
|
+
const sequence = operation === "act" ? ++this.actionSequence : void 0;
|
|
160
|
+
const request = {
|
|
161
|
+
id: randomUUID(),
|
|
162
|
+
operation,
|
|
163
|
+
grantId: this.grantId,
|
|
164
|
+
...sequence === void 0 ? {} : { sequence },
|
|
165
|
+
...payload === void 0 ? {} : { payload }
|
|
166
|
+
};
|
|
167
|
+
const completion = new Promise((resolve, reject) => {
|
|
168
|
+
const onAbort = () => this.stopAfterUncertainRequest("The computer-use request was cancelled.");
|
|
169
|
+
const timer = setTimeout(() => this.stopAfterUncertainRequest("The computer-use request timed out."), this.requestTimeoutMs);
|
|
170
|
+
timer.unref?.();
|
|
171
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
172
|
+
this.pending = {
|
|
173
|
+
request,
|
|
174
|
+
resolve,
|
|
175
|
+
reject,
|
|
176
|
+
dispose: () => {
|
|
177
|
+
clearTimeout(timer);
|
|
178
|
+
signal?.removeEventListener("abort", onAbort);
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
});
|
|
182
|
+
this.changed();
|
|
183
|
+
try {
|
|
184
|
+
return Response.json(await completion);
|
|
185
|
+
} catch (error) {
|
|
186
|
+
return jsonError(error instanceof Error ? error.message : String(error), 502);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
async fetch(request) {
|
|
190
|
+
if (this.closed) return jsonError("Computer-use broker is closed.", 503);
|
|
191
|
+
const path = new URL(request.url).pathname;
|
|
192
|
+
if (request.method === "POST" && path === apiRoutes_default.activate.path) return this.requestActivation(request);
|
|
193
|
+
const agent = path.startsWith("/agent/");
|
|
194
|
+
const hub = path.startsWith("/hub/");
|
|
195
|
+
if (agent && !this.authorized(request, this.internalToken) || hub && !this.authorized(request, this.hubToken)) return jsonError("Not found.", 404);
|
|
196
|
+
if (request.method === "GET" && (path === apiRoutes_default.agentState.path || path === apiRoutes_default.hubState.path)) return Response.json(this.state());
|
|
197
|
+
if (request.method === "POST" && path === apiRoutes_default.agentObserve.path) return this.enqueue("observe", void 0, request.signal);
|
|
198
|
+
if (request.method === "POST" && path === apiRoutes_default.agentAction.path) {
|
|
199
|
+
const action = await body(request);
|
|
200
|
+
if (!semanticAction(action)) return jsonError("A valid semantic action is required.", 400);
|
|
201
|
+
return this.enqueue("act", action, request.signal);
|
|
202
|
+
}
|
|
203
|
+
if (request.method === "POST" && path === apiRoutes_default.agentStop.path) {
|
|
204
|
+
if (this.phase !== "active") return jsonError("Computer use is not active.", 409);
|
|
205
|
+
this.phase = "stopping";
|
|
206
|
+
this.rejectPending("The computer-use request was stopped.");
|
|
207
|
+
this.changed();
|
|
208
|
+
return Response.json(this.state(), { status: 202 });
|
|
209
|
+
}
|
|
210
|
+
if (request.method === "GET" && path === apiRoutes_default.hubActivation.path) {
|
|
211
|
+
if (this.activation === void 0 || this.phase !== "awaiting_confirmation") return Response.json(null);
|
|
212
|
+
this.phase = "activating";
|
|
213
|
+
this.changed();
|
|
214
|
+
return Response.json(this.activation);
|
|
215
|
+
}
|
|
216
|
+
if (request.method === "GET" && path === apiRoutes_default.hubAuthorization.path) return Response.json(this.grantId === void 0 ? null : {
|
|
217
|
+
grantId: this.grantId,
|
|
218
|
+
expiresAt: this.expiresAt
|
|
219
|
+
});
|
|
220
|
+
if (request.method === "GET" && path === apiRoutes_default.hubNext.path) return Response.json(this.pending?.request ?? null);
|
|
221
|
+
if (request.method === "POST" && path === apiRoutes_default.hubComplete.path) {
|
|
222
|
+
const input = await body(request);
|
|
223
|
+
const id = typeof input.id === "string" ? input.id : void 0;
|
|
224
|
+
if (this.pending === void 0 || this.pending.request.id !== id) return jsonError("The request is stale.", 409);
|
|
225
|
+
const pending = this.pending;
|
|
226
|
+
this.pending = void 0;
|
|
227
|
+
pending.dispose();
|
|
228
|
+
this.changed();
|
|
229
|
+
if (typeof input.error === "string") pending.reject(new Error(input.error));
|
|
230
|
+
else pending.resolve(input.result);
|
|
231
|
+
return Response.json(this.state());
|
|
232
|
+
}
|
|
233
|
+
if (request.method === "POST" && path === apiRoutes_default.hubStop.path) {
|
|
234
|
+
const input = await body(request);
|
|
235
|
+
if (this.phase === "activating") {
|
|
236
|
+
if (typeof input.error === "string") {
|
|
237
|
+
this.phase = "failed";
|
|
238
|
+
this.failure = {
|
|
239
|
+
code: "desktop_unavailable",
|
|
240
|
+
message: input.error.slice(0, 512)
|
|
241
|
+
};
|
|
242
|
+
this.activation = void 0;
|
|
243
|
+
} else {
|
|
244
|
+
const host = record(input.host);
|
|
245
|
+
if (typeof host?.grantId !== "string" || !Number.isFinite(host.expiresAt)) return jsonError("Desktop did not issue a complete grant.", 502);
|
|
246
|
+
this.grantId = host.grantId;
|
|
247
|
+
this.expiresAt = host.expiresAt;
|
|
248
|
+
this.actionSequence = 0;
|
|
249
|
+
this.phase = "active";
|
|
250
|
+
}
|
|
251
|
+
} else {
|
|
252
|
+
this.rejectPending("The computer-use session stopped.");
|
|
253
|
+
this.phase = "inactive";
|
|
254
|
+
this.grantId = void 0;
|
|
255
|
+
this.expiresAt = void 0;
|
|
256
|
+
this.activation = void 0;
|
|
257
|
+
this.artifact = artifactView(input.artifact);
|
|
258
|
+
}
|
|
259
|
+
this.changed();
|
|
260
|
+
return Response.json(this.state());
|
|
261
|
+
}
|
|
262
|
+
return jsonError("Not found.", 404);
|
|
263
|
+
}
|
|
264
|
+
close() {
|
|
265
|
+
this.closed = true;
|
|
266
|
+
this.rejectPending("Computer-use broker closed.");
|
|
267
|
+
this.grantId = void 0;
|
|
268
|
+
this.expiresAt = void 0;
|
|
269
|
+
}
|
|
270
|
+
};
|
|
271
|
+
function createComputerUseApi(options) {
|
|
272
|
+
return new ComputerUseRequestBroker(options);
|
|
273
|
+
}
|
|
274
|
+
const api = {
|
|
275
|
+
basePath: API_BASE_PATH,
|
|
276
|
+
start(context) {
|
|
277
|
+
if (context.directEvents === void 0) throw new Error("Computer-use API requires the session direct event bus.");
|
|
278
|
+
return createComputerUseApi({
|
|
279
|
+
...context.sessionId === void 0 ? {} : { sessionId: context.sessionId },
|
|
280
|
+
...context.internalToken === void 0 ? {} : { internalToken: context.internalToken },
|
|
281
|
+
...context.hubToken === void 0 ? {} : { hubToken: context.hubToken },
|
|
282
|
+
directEvents: context.directEvents
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
};
|
|
286
|
+
//#endregion
|
|
287
|
+
export { ComputerUseRequestBroker, api, createComputerUseApi };
|
|
288
|
+
|
|
289
|
+
//# sourceMappingURL=index.mjs.map
|