@aiworker/web 1.22.0 → 1.23.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.
- package/README.md +4 -4
- package/bin/cli.js +14 -4
- package/bin/cli.test.js +165 -73
- package/bin/lib/cli-api-target.js +2 -2
- package/bin/lib/cli-args.js +119 -119
- package/bin/lib/cli-lifecycle.js +9 -9
- package/bin/lib/cli-network.js +3 -3
- package/bin/lib/cli-paths.js +3 -3
- package/bin/lib/cli-ports.js +2 -2
- package/bin/lib/cli-process.js +4 -4
- package/bin/lib/cli-startup.js +64 -15
- package/bin/lib/cli-tunnel-profiles.js +1 -1
- package/bin/lib/cli-tunnel-utils.js +2 -2
- package/bin/lib/commands-connect-url.js +19 -19
- package/bin/lib/commands-lifecycle.js +27 -27
- package/bin/lib/commands-logs.js +5 -5
- package/bin/lib/commands-models.js +1 -1
- package/bin/lib/commands-projects.js +1 -1
- package/bin/lib/commands-schedule.js +1 -1
- package/bin/lib/commands-serve.js +29 -29
- package/bin/lib/commands-session.js +1 -1
- package/bin/lib/commands-startup.js +45 -10
- package/bin/lib/commands-status.js +1 -1
- package/bin/lib/commands-tunnel.js +40 -40
- package/bin/lib/commands-update.js +1 -1
- package/bin/lib/commands-update.test.js +6 -6
- package/dist/assets/{CodeMirrorCommentWidgets-B3u7UIcE.js → CodeMirrorCommentWidgets-B1Gizi3a.js} +1 -1
- package/dist/assets/DiffView-DXjVsEOw.js +4 -0
- package/dist/assets/DirtyBranchSwitchDialog-aig6zJjg.js +1 -0
- package/dist/assets/FilesView-CJdG0-wk.js +17 -0
- package/dist/assets/GitView-BXsS3jG6.js +6 -0
- package/dist/assets/{JsonTreeView-B0BdZEHG.js → JsonTreeView-D_hpXBnF.js} +1 -1
- package/dist/assets/LinearIssuesView-BoUiLQG1.js +1 -0
- package/dist/assets/MarkdownImageGallery-B_B_a9KS.js +1 -0
- package/dist/assets/MarkdownRendererImpl-xgyyLiBM.js +12 -0
- package/dist/assets/OnboardingScreen-DIp84OWt.js +1 -0
- package/dist/assets/{PatchDiff-DvfqDql7.js → PatchDiff-8p6nLJaU.js} +1 -1
- package/dist/assets/PierreDiffViewer-DjC8nTk9.js +161 -0
- package/dist/assets/PlanView-CJTmOF6I.js +5 -0
- package/dist/assets/SettingsView-DD-JqIJx.js +28 -0
- package/dist/assets/{SettingsWindow-i45U1Cy1.js → SettingsWindow-Cpb4hM6q.js} +1 -1
- package/dist/assets/SymbolsNerdFontMono-Regular-aK5vsLov.woff2 +0 -0
- package/dist/assets/{ToolOutputDialog-BTwyh5OF.js → ToolOutputDialog-DfaKZXNU.js} +6 -6
- package/dist/assets/ToolPartDiffPreview-DtZLzrSK.js +8 -0
- package/dist/assets/{VirtualizedFileDiff-DD8lDVej.js → VirtualizedFileDiff-C8i9HpTB.js} +1 -1
- package/dist/assets/WalkthroughView-DeKMvZlL.js +4 -0
- package/dist/assets/{computeVirtualFileMetrics-BMIRgMHv.js → computeVirtualFileMetrics-BBI7ZwrC.js} +2 -2
- package/dist/assets/contextPanelEmbeddedChat-BdA6bdky.js +1 -0
- package/dist/assets/de-DCrsQ5zS.js +10 -0
- package/dist/assets/es-Dwv4YfH6.js +16 -0
- package/dist/assets/fr-BCWg4Cnx.js +14 -0
- package/dist/assets/ghostty-vt-DdA0Zryv.wasm +0 -0
- package/dist/assets/index-B68h5S5B.css +1 -0
- package/dist/assets/index-DVwMarHI.js +39 -0
- package/dist/assets/{index-CODwDsU_.js → index-jXSK5RrB.js} +1 -1
- package/dist/assets/{isDiffPlainText-BqayB8d3.js → isDiffPlainText-B_x_rVon.js} +1 -1
- package/dist/assets/{isFilePlainText-QfoiKJNY.js → isFilePlainText-DW_xMer1.js} +1 -1
- package/dist/assets/ja-Bruw3RYC.js +16 -0
- package/dist/assets/ko-idhXGF8j.js +16 -0
- package/dist/assets/main-BkyaQhJX.js +930 -0
- package/dist/assets/{main-C5DVOxc6.js → main-CzdPuL0s.js} +2 -2
- package/dist/assets/markdownCore-Cn4Tyejo.js +5 -0
- package/dist/assets/{miniChat-DUJ4irZc.js → miniChat-CCkqKOLp.js} +2 -2
- package/dist/assets/{mobile-CcaxB0n4.js → mobile-mvxTo055.js} +2 -2
- package/dist/assets/patchFileDiff-Csk4iNUi.js +13 -0
- package/dist/assets/pl-CGZWUqZJ.js +16 -0
- package/dist/assets/pt-BR-B8V7u7tA.js +16 -0
- package/dist/assets/renderElectronMiniChatApp-BxoyujA5.js +2 -0
- package/dist/assets/renderMobileApp-B48CsP4r.js +25 -0
- package/dist/assets/runtimeEndpointReset-Bg5gx18H.js +17 -0
- package/dist/assets/scheduledTasksApi-BW0Etzwz.js +1 -0
- package/dist/assets/{shikiHighlight-DYOWuY65.js → shikiHighlight-CRl0SUC9.js} +1 -1
- package/dist/assets/surface-oMvhsog3.js +1 -0
- package/dist/assets/tr-BK_KiO2V.js +7 -0
- package/dist/assets/uk-CG74xV8N.js +16 -0
- package/dist/assets/useAppFontEffects-CPKeOpUo.js +7284 -0
- package/dist/assets/useGitComparison-DH220WmO.js +1 -0
- package/dist/assets/useInlineCommentController-BiWz4AVb.js +2 -0
- package/dist/assets/useRootScrollLock-BS4-kr7P.js +1 -0
- package/dist/assets/{vendor-base-ui-BeMD8X_w.js → vendor-base-ui-DdV8vhHn.js} +1 -1
- package/dist/assets/{vendor-codemirror-language-data-DFZik9R2.js → vendor-codemirror-language-data-Bg4AEeCr.js} +2 -2
- package/dist/assets/vendor-zod-BPAANqvH.js +39 -0
- package/dist/assets/{web-components-Bhg83tjf.js → web-components-z7hfnS8n.js} +1 -1
- package/dist/assets/zh-CN-T4AXofZI.js +16 -0
- package/dist/assets/zh-TW-Dte40sxp.js +16 -0
- package/dist/index.html +21 -59
- package/dist/mini-chat.html +7 -7
- package/dist/mobile.html +5 -5
- package/package.json +3 -4
- package/server/index.d.ts +15 -0
- package/server/index.js +158 -89
- package/server/lib/agent-memory/actions.js +2 -2
- package/server/lib/agent-memory/feature-flag.js +1 -1
- package/server/lib/agent-memory/feature-flag.test.js +8 -8
- package/server/lib/agent-memory/routes.js +2 -2
- package/server/lib/agent-tool/runtime.js +37 -54
- package/server/lib/agent-tool/runtime.test.js +59 -59
- package/server/lib/browser-control/broker.js +3 -3
- package/server/lib/browser-control/broker.test.js +1 -1
- package/server/lib/changelog/update-notes.js +82 -0
- package/server/lib/changelog/update-notes.test.js +59 -0
- package/server/lib/client-auth/remote-clients.test.js +5 -5
- package/server/lib/context-obligatory/runtime.js +7 -7
- package/server/lib/context-obligatory/runtime.test.js +5 -5
- package/server/lib/data-dir-migration.js +40 -0
- package/server/lib/data-dir-migration.test.js +59 -0
- package/server/lib/dev-servers/parse.js +2 -2
- package/server/lib/dev-servers/parse.test.js +2 -2
- package/server/lib/dev-servers/routes.js +1 -1
- package/server/lib/dev-tunnel/DOCUMENTATION.md +13 -4
- package/server/lib/dev-tunnel/client.js +1 -1
- package/server/lib/dev-tunnel/runtime.js +5 -5
- package/server/lib/dev-tunnel/tunnel.test.js +21 -1
- package/server/lib/dictation/local/model-catalog.js +1 -1
- package/server/lib/dictation/local/worker-process.js +2 -2
- package/server/lib/event-stream/directory-ws-bridge.js +1 -1
- package/server/lib/event-stream/global-ws-bridge.js +1 -1
- package/server/lib/event-stream/protocol.test.js +4 -4
- package/server/lib/event-stream/runtime.test.js +18 -18
- package/server/lib/fs/DOCUMENTATION.md +5 -0
- package/server/lib/fs/routes.js +68 -26
- package/server/lib/fs/routes.test.js +208 -22
- package/server/lib/git/DOCUMENTATION.md +32 -6
- package/server/lib/git/identity-storage.js +1 -1
- package/server/lib/git/issue-2746-longpaths.test.js +4 -4
- package/server/lib/git/routes.js +41 -5
- package/server/lib/git/service.js +300 -224
- package/server/lib/git/service.test.js +596 -28
- package/server/lib/github/auth.js +8 -8
- package/server/lib/github/pr-status.js +1 -1
- package/server/lib/github/routes.js +2 -2
- package/server/lib/inherited-env.js +17 -10
- package/server/lib/inherited-env.test.js +10 -11
- package/server/lib/linear/auth.js +8 -8
- package/server/lib/linear/auth.test.js +24 -24
- package/server/lib/linear/issues.test.js +6 -6
- package/server/lib/linear/mapping.test.js +4 -4
- package/server/lib/linear/oauth.js +2 -2
- package/server/lib/linear/oauth.test.js +14 -14
- package/server/lib/linear/routes.js +5 -5
- package/server/lib/linear/routes.test.js +16 -16
- package/server/lib/linear/status-runtime.test.js +9 -9
- package/server/lib/linear/status.js +1 -1
- package/server/lib/linear/status.test.js +15 -15
- package/server/lib/linear/teams.test.js +4 -4
- package/server/lib/magic-prompts/routes.js +2 -2
- package/server/lib/mcp-reconnect/DOCUMENTATION.md +55 -0
- package/server/lib/mcp-reconnect/runtime.js +122 -0
- package/server/lib/mcp-reconnect/runtime.test.js +140 -0
- package/server/lib/message-queue/DOCUMENTATION.md +161 -0
- package/server/lib/message-queue/runtime.js +870 -0
- package/server/lib/message-queue/runtime.test.js +482 -0
- package/server/lib/network-defaults.js +23 -0
- package/server/lib/network-defaults.test.js +52 -0
- package/server/lib/notifications/apns-runtime.js +17 -17
- package/server/lib/notifications/apns-runtime.test.js +11 -11
- package/server/lib/notifications/emitter-runtime.js +1 -1
- package/server/lib/notifications/emitter-runtime.test.js +1 -1
- package/server/lib/notifications/push-runtime.js +7 -7
- package/server/lib/notifications/routes.js +1 -1
- package/server/lib/notifications/runtime.js +1 -1
- package/server/lib/openchamber-control/action-resolution.test.js +10 -10
- package/server/lib/openchamber-control/actions.js +24 -24
- package/server/lib/openchamber-control/error.js +4 -4
- package/server/lib/openchamber-control/routes.js +2 -2
- package/server/lib/openchamber-control/routes.test.js +5 -5
- package/server/lib/openchamber-control/screenshots.js +1 -1
- package/server/lib/openchamber-control/screenshots.test.js +1 -1
- package/server/lib/openchamber-control/service.js +50 -50
- package/server/lib/openchamber-control/service.test.js +5 -5
- package/server/lib/openchamber-sessions/routes.js +124 -22
- package/server/lib/openchamber-sessions/routes.test.js +99 -11
- package/server/lib/opencode/DOCUMENTATION.md +30 -6
- package/server/lib/opencode/auth.js +1 -1
- package/server/lib/opencode/bootstrap-runtime.js +8 -6
- package/server/lib/opencode/cli-options.js +8 -8
- package/server/lib/opencode/config-paths.test.js +116 -0
- package/server/lib/opencode/core-routes.js +8 -7
- package/server/lib/opencode/core-routes.test.js +11 -11
- package/server/lib/opencode/env-config.js +5 -5
- package/server/lib/opencode/env-config.test.js +7 -7
- package/server/lib/opencode/env-runtime.js +10 -10
- package/server/lib/opencode/env-runtime.test.js +18 -18
- package/server/lib/opencode/feature-routes-runtime.js +19 -12
- package/server/lib/opencode/hmr-state-runtime.js +2 -2
- package/server/lib/opencode/hmr-state-runtime.test.js +1 -1
- package/server/lib/opencode/input-history-scope.js +14 -0
- package/server/lib/opencode/lifecycle.js +8 -8
- package/server/lib/opencode/lifecycle.test.js +4 -4
- package/server/lib/opencode/managed-plugin-config.js +35 -0
- package/server/lib/opencode/managed-process-registry.js +3 -3
- package/server/lib/opencode/mcp-oauth-callback.test.js +2 -2
- package/server/lib/opencode/openchamber-routes.js +79 -19
- package/server/lib/opencode/openchamber-routes.test.js +139 -12
- package/server/lib/opencode/plugins.js +2 -2
- package/server/lib/opencode/plugins.test.js +1 -1
- package/server/lib/opencode/project-icon-routes.js +2 -2
- package/server/lib/opencode/project-icon-routes.test.js +1 -1
- package/server/lib/opencode/providers.js +44 -2
- package/server/lib/opencode/providers.test.js +131 -4
- package/server/lib/opencode/proxy.js +2 -2
- package/server/lib/opencode/pwa-manifest-routes.js +1 -1
- package/server/lib/opencode/restart-session-recovery.test.js +1 -1
- package/server/lib/opencode/routes-upgrade.test.js +4 -4
- package/server/lib/opencode/routes.js +19 -17
- package/server/lib/opencode/server-startup-runtime.js +6 -6
- package/server/lib/opencode/session-runtime.js +3 -3
- package/server/lib/opencode/session-runtime.test.js +6 -6
- package/server/lib/opencode/settings-files.js +214 -0
- package/server/lib/opencode/settings-helpers.js +116 -44
- package/server/lib/opencode/settings-helpers.test.js +354 -12
- package/server/lib/opencode/settings-registry.json +747 -0
- package/server/lib/opencode/settings-runtime.js +141 -20
- package/server/lib/opencode/settings-runtime.test.js +191 -4
- package/server/lib/opencode/shared.js +5 -2
- package/server/lib/opencode/shared.test.js +7 -7
- package/server/lib/opencode/shutdown-runtime.js +2 -0
- package/server/lib/opencode/skill-routes.js +2 -1
- package/server/lib/opencode/snippets.js +1 -2
- package/server/lib/opencode/startup-performance.js +1 -1
- package/server/lib/opencode/startup-performance.test.js +6 -6
- package/server/lib/opencode/static-routes-runtime.js +8 -8
- package/server/lib/opencode/static-routes-runtime.test.js +7 -7
- package/server/lib/opencode/upgrade-capability.js +2 -2
- package/server/lib/opencode/upgrade-capability.test.js +3 -3
- package/server/lib/package-manager.js +17 -42
- package/server/lib/package-manager.test.js +19 -19
- package/server/lib/permission-auto-accept/runtime.js +1 -1
- package/server/lib/project-context/DOCUMENTATION.md +25 -1
- package/server/lib/project-context/routes.http.test.js +18 -0
- package/server/lib/project-context/routes.js +16 -1
- package/server/lib/project-context/runtime.js +248 -23
- package/server/lib/project-context/runtime.test.js +106 -3
- package/server/lib/projects/DOCUMENTATION.md +76 -0
- package/server/lib/projects/project-config.js +144 -11
- package/server/lib/projects/project-id.js +17 -0
- package/server/lib/projects/project-setup.js +409 -0
- package/server/lib/projects/project-setup.test.js +557 -0
- package/server/lib/projects/routes.js +59 -0
- package/server/lib/quota/DOCUMENTATION.md +40 -2
- package/server/lib/quota/credentials/providers.js +4 -0
- package/server/lib/quota/credentials/store.js +4 -4
- package/server/lib/quota/credentials/store.test.js +8 -8
- package/server/lib/quota/index.js +1 -0
- package/server/lib/quota/providers/cline-pass.js +125 -0
- package/server/lib/quota/providers/cline-pass.test.js +103 -0
- package/server/lib/quota/providers/exe-dev.js +75 -0
- package/server/lib/quota/providers/exe-dev.test.js +47 -0
- package/server/lib/quota/providers/hyper.js +118 -0
- package/server/lib/quota/providers/hyper.test.js +126 -0
- package/server/lib/quota/providers/index.js +22 -0
- package/server/lib/quota/providers/neuralwatt.js +3 -6
- package/server/lib/quota/providers/neuralwatt.test.js +7 -7
- package/server/lib/quota/providers/ollama-cloud.js +32 -1
- package/server/lib/quota/providers/ollama-cloud.test.js +33 -1
- package/server/lib/quota/providers/opencode-go.js +3 -2
- package/server/lib/quota/providers/opencode-go.test.js +35 -6
- package/server/lib/quota/providers/openrouter.js +119 -24
- package/server/lib/quota/providers/openrouter.test.js +330 -0
- package/server/lib/quota/providers/xai.js +1 -1
- package/server/lib/quota/routes.js +2 -0
- package/server/lib/quota/utils/auth.js +1 -1
- package/server/lib/relay/DOCUMENTATION.md +56 -1
- package/server/lib/relay/cross-compat.test.js +26 -0
- package/server/lib/relay/downstream-scheduler.js +154 -0
- package/server/lib/relay/downstream-scheduler.test.js +162 -0
- package/server/lib/relay/e2ee.js +10 -8
- package/server/lib/relay/flow-control.test.js +177 -0
- package/server/lib/relay/host-client.js +38 -9
- package/server/lib/relay/host-client.test.js +9 -1
- package/server/lib/relay/host-lock.js +1 -1
- package/server/lib/relay/service.js +5 -5
- package/server/lib/relay/tunnel-codec.js +9 -0
- package/server/lib/relay/tunnel-host.js +69 -18
- package/server/lib/relay/tunnel-host.test.js +9 -1
- package/server/lib/scheduled-tasks/issue-2710-double-execution.test.js +2 -2
- package/server/lib/scheduled-tasks/routes.js +5 -5
- package/server/lib/scheduled-tasks/service.js +25 -25
- package/server/lib/scheduled-tasks/service.test.js +1 -1
- package/server/lib/security/bind-host.js +4 -4
- package/server/lib/security/bind-host.test.js +1 -1
- package/server/lib/security/request-security.js +11 -5
- package/server/lib/security/request-security.test.js +14 -14
- package/server/lib/session-assist/runtime.js +15 -18
- package/server/lib/session-folders/routes.js +2 -2
- package/server/lib/session-folders/routes.test.js +8 -8
- package/server/lib/session-goal/DOCUMENTATION.md +20 -7
- package/server/lib/session-goal/create.js +4 -2
- package/server/lib/session-goal/create.test.js +1 -1
- package/server/lib/session-goal/objectives.js +4 -4
- package/server/lib/session-goal/routes.js +1 -1
- package/server/lib/session-goal/runtime.js +91 -30
- package/server/lib/session-goal/runtime.test.js +428 -2
- package/server/lib/session-knowledge/runtime.js +11 -11
- package/server/lib/session-knowledge/runtime.test.js +5 -5
- package/server/lib/skills-catalog/DOCUMENTATION.md +1 -1
- package/server/lib/skills-catalog/cache.test.js +2 -2
- package/server/lib/skills-catalog/disk-cache.js +5 -5
- package/server/lib/skills-catalog/github-meta.test.js +2 -2
- package/server/lib/skills-catalog/install.js +3 -2
- package/server/lib/small-model/DOCUMENTATION.md +7 -2
- package/server/lib/small-model/call.js +18 -7
- package/server/lib/small-model/call.test.js +58 -6
- package/server/lib/small-model/index.js +12 -16
- package/server/lib/small-model/index.test.js +1 -1
- package/server/lib/small-model/resolve.js +1 -1
- package/server/lib/small-model/resolve.test.js +1 -1
- package/server/lib/small-model/routes.js +2 -1
- package/server/lib/small-model/runtime-providers.js +15 -7
- package/server/lib/small-model/runtime-providers.test.js +7 -1
- package/server/lib/system-prompt/runtime.js +3 -22
- package/server/lib/system-prompt/runtime.test.js +3 -3
- package/server/lib/terminal/DOCUMENTATION.md +14 -10
- package/server/lib/terminal/runtime.js +190 -31
- package/server/lib/terminal/runtime.test.js +572 -38
- package/server/lib/terminal/shells.js +20 -3
- package/server/lib/terminal/shells.test.js +33 -2
- package/server/lib/tts/base-url.js +3 -3
- package/server/lib/tts/routes.test.js +20 -20
- package/server/lib/ui-auth/ui-auth.js +12 -9
- package/server/lib/ui-auth/ui-auth.test.js +19 -3
- package/server/lib/ui-auth/ui-passkeys.js +7 -7
- package/server/lib/walkthrough/DOCUMENTATION.md +33 -14
- package/server/lib/walkthrough/index.js +1 -0
- package/server/lib/walkthrough/jobs.test.js +1 -1
- package/server/lib/walkthrough/language.test.js +1 -1
- package/server/lib/walkthrough/model-settings.js +11 -15
- package/server/lib/walkthrough/model-settings.test.js +1 -1
- package/server/lib/walkthrough/prompt.js +3 -1
- package/server/lib/walkthrough/pull-request.test.js +5 -5
- package/server/lib/walkthrough/reproduce-2607.test.js +2 -2
- package/server/lib/walkthrough/routes.test.js +26 -5
- package/server/lib/walkthrough/sources.js +23 -2
- package/server/lib/walkthrough/store.js +3 -3
- package/server/lib/walkthrough/store.test.js +1 -1
- package/server/opencode-proxy.test.js +2 -2
- package/server/proxy-headers.js +1 -1
- package/server/sse-routes.test.js +4 -4
- package/README.md.bak +0 -250
- package/bin/lib/DOCUMENTATION.md.bak +0 -163
- package/dist/assets/CommitSection-SGBCAW0w.js +0 -1
- package/dist/assets/DiffView-DluiRSla.js +0 -4
- package/dist/assets/FilesView-Bdq8ppva.js +0 -17
- package/dist/assets/GitView-Znn7VJcP.js +0 -6
- package/dist/assets/LinearIssuesView-jP-hXyac.js +0 -1
- package/dist/assets/MarkdownImageGallery-ClOvuZxC.js +0 -1
- package/dist/assets/MarkdownRendererImpl-Dt9mjTRN.js +0 -12
- package/dist/assets/OnboardingScreen-D2DG7K6b.js +0 -1
- package/dist/assets/PierreDiffViewer-B7m3f0d7.js +0 -157
- package/dist/assets/PlanView-B0F3BtPZ.js +0 -5
- package/dist/assets/SettingsView-BBW-S-gh.js +0 -28
- package/dist/assets/ToolPartDiffPreview-CUNe28U1.js +0 -8
- package/dist/assets/WalkthroughView-egQgxel3.js +0 -4
- package/dist/assets/contextPanelEmbeddedChat-C3fjDbdg.js +0 -1
- package/dist/assets/de-C1P6X5Rs.js +0 -9
- package/dist/assets/es-CDgaF1_t.js +0 -15
- package/dist/assets/fr-Bgxqvvz_.js +0 -13
- package/dist/assets/index-C57jT0Sa.css +0 -1
- package/dist/assets/index-DW_E3rnL.js +0 -7
- package/dist/assets/ja-BDRrEcNP.js +0 -15
- package/dist/assets/ko-Ba8sQV79.js +0 -15
- package/dist/assets/main-Bv5Pkngh.js +0 -928
- package/dist/assets/markdownCore-CZwzz5gw.js +0 -3
- package/dist/assets/patchFileDiff-yNfWXN4E.js +0 -10
- package/dist/assets/pl-Dioz29BI.js +0 -15
- package/dist/assets/pt-BR-DIs6ElwV.js +0 -15
- package/dist/assets/renderElectronMiniChatApp-BcKLHXKe.js +0 -2
- package/dist/assets/renderMobileApp-D9yQJy0L.js +0 -25
- package/dist/assets/runtimeEndpointReset-CjhvxLH0.js +0 -16
- package/dist/assets/scheduledTasksApi-DLW0mkQK.js +0 -1
- package/dist/assets/tr-DFnMlPxY.js +0 -6
- package/dist/assets/uk-ZrCNjM7Y.js +0 -15
- package/dist/assets/useAppFontEffects-CjrntdL0.js +0 -7310
- package/dist/assets/useInlineCommentController-CDEuSlPH.js +0 -2
- package/dist/assets/useRootScrollLock-BHYPkrLv.js +0 -1
- package/dist/assets/vendor-ghostty-web-CrxinGGH.js +0 -13
- package/dist/assets/vendor-zod-BLfBSgBh.js +0 -39
- package/dist/assets/zh-CN-iv_AV4EC.js +0 -15
- package/dist/assets/zh-TW-CzEUk38j.js +0 -15
- package/server/index.d.ts.bak +0 -39
- package/server/lib/agent-tool/DOCUMENTATION.md.bak +0 -119
- package/server/lib/browser-control/DOCUMENTATION.md.bak +0 -50
- package/server/lib/context-obligatory/DOCUMENTATION.md.bak +0 -19
- package/server/lib/dev-tunnel/DOCUMENTATION.md.bak +0 -57
- package/server/lib/dictation/DOCUMENTATION.md.bak +0 -100
- package/server/lib/event-stream/DOCUMENTATION.md.bak +0 -62
- package/server/lib/fs/DOCUMENTATION.md.bak +0 -47
- package/server/lib/git/DOCUMENTATION.md.bak +0 -193
- package/server/lib/github/DOCUMENTATION.md.bak +0 -183
- package/server/lib/linear/DOCUMENTATION.md.bak +0 -97
- package/server/lib/linear/OAUTH-BROKER-HANDOFF.md.bak +0 -91
- package/server/lib/markdown-image-grants/DOCUMENTATION.md.bak +0 -40
- package/server/lib/notifications/APNS.md.bak +0 -135
- package/server/lib/notifications/DOCUMENTATION.md.bak +0 -138
- package/server/lib/openchamber-control/DOCUMENTATION.md.bak +0 -64
- package/server/lib/opencode/DOCUMENTATION.md.bak +0 -431
- package/server/lib/opencode/managed-process-registry.d.ts.bak +0 -13
- package/server/lib/opencode/provider-env-aliases.d.ts.bak +0 -3
- package/server/lib/permission-auto-accept/DOCUMENTATION.md.bak +0 -34
- package/server/lib/project-context/DOCUMENTATION.md.bak +0 -160
- package/server/lib/quota/DOCUMENTATION.md.bak +0 -123
- package/server/lib/relay/DOCUMENTATION.md.bak +0 -100
- package/server/lib/scheduled-tasks/DOCUMENTATION.md.bak +0 -182
- package/server/lib/session-assist/DOCUMENTATION.md.bak +0 -66
- package/server/lib/session-goal/DOCUMENTATION.md.bak +0 -213
- package/server/lib/session-knowledge/DOCUMENTATION.md.bak +0 -89
- package/server/lib/skills-catalog/DOCUMENTATION.md.bak +0 -151
- package/server/lib/small-model/DOCUMENTATION.md.bak +0 -212
- package/server/lib/system-prompt/DOCUMENTATION.md.bak +0 -36
- package/server/lib/terminal/DOCUMENTATION.md.bak +0 -50
- package/server/lib/text/DOCUMENTATION.md.bak +0 -35
- package/server/lib/tts/DOCUMENTATION.md.bak +0 -147
- package/server/lib/tunnels/DOCUMENTATION.md.bak +0 -21
- package/server/lib/ui-auth/DOCUMENTATION.md.bak +0 -44
- package/server/lib/walkthrough/DOCUMENTATION.md.bak +0 -411
|
@@ -14,6 +14,6 @@
|
|
|
14
14
|
const TRUTHY = new Set(['1', 'true', 'yes', 'on']);
|
|
15
15
|
|
|
16
16
|
export const isAgentMemoryFeatureAvailable = () => {
|
|
17
|
-
const raw = process.env.
|
|
17
|
+
const raw = process.env.AIWORKER_MEMORY_ENABLE;
|
|
18
18
|
return typeof raw === 'string' && TRUTHY.has(raw.trim().toLowerCase());
|
|
19
19
|
};
|
|
@@ -2,37 +2,37 @@ import { afterEach, describe, expect, test } from 'bun:test';
|
|
|
2
2
|
|
|
3
3
|
import { isAgentMemoryFeatureAvailable } from './feature-flag.js';
|
|
4
4
|
|
|
5
|
-
const original = process.env.
|
|
5
|
+
const original = process.env.AIWORKER_MEMORY_ENABLE;
|
|
6
6
|
|
|
7
7
|
afterEach(() => {
|
|
8
|
-
if (original === undefined) delete process.env.
|
|
9
|
-
else process.env.
|
|
8
|
+
if (original === undefined) delete process.env.AIWORKER_MEMORY_ENABLE;
|
|
9
|
+
else process.env.AIWORKER_MEMORY_ENABLE = original;
|
|
10
10
|
});
|
|
11
11
|
|
|
12
12
|
describe('the unreleased feature gate', () => {
|
|
13
13
|
test('is closed when the variable is unset', () => {
|
|
14
|
-
delete process.env.
|
|
14
|
+
delete process.env.AIWORKER_MEMORY_ENABLE;
|
|
15
15
|
expect(isAgentMemoryFeatureAvailable()).toBe(false);
|
|
16
16
|
});
|
|
17
17
|
|
|
18
18
|
test('opens for the usual truthy spellings', () => {
|
|
19
19
|
for (const value of ['1', 'true', 'TRUE', 'yes', 'on', ' true ']) {
|
|
20
|
-
process.env.
|
|
20
|
+
process.env.AIWORKER_MEMORY_ENABLE = value;
|
|
21
21
|
expect(isAgentMemoryFeatureAvailable()).toBe(true);
|
|
22
22
|
}
|
|
23
23
|
});
|
|
24
24
|
|
|
25
25
|
test('stays closed for anything else, including "false"', () => {
|
|
26
26
|
for (const value of ['', '0', 'false', 'no', 'off', 'maybe']) {
|
|
27
|
-
process.env.
|
|
27
|
+
process.env.AIWORKER_MEMORY_ENABLE = value;
|
|
28
28
|
expect(isAgentMemoryFeatureAvailable()).toBe(false);
|
|
29
29
|
}
|
|
30
30
|
});
|
|
31
31
|
|
|
32
32
|
test('is read per call, so a process started with it set is what decides', () => {
|
|
33
|
-
delete process.env.
|
|
33
|
+
delete process.env.AIWORKER_MEMORY_ENABLE;
|
|
34
34
|
expect(isAgentMemoryFeatureAvailable()).toBe(false);
|
|
35
|
-
process.env.
|
|
35
|
+
process.env.AIWORKER_MEMORY_ENABLE = '1';
|
|
36
36
|
expect(isAgentMemoryFeatureAvailable()).toBe(true);
|
|
37
37
|
});
|
|
38
38
|
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* AiWorker agent memory routes.
|
|
3
3
|
*
|
|
4
4
|
* The scope is a query parameter rather than part of the path, because global
|
|
5
5
|
* and project memory are the same resource with two homes: one set of handlers
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* scope wrong must fail loudly, never silently write the user's global memory
|
|
8
8
|
* from a project-scoped call.
|
|
9
9
|
*
|
|
10
|
-
* Memory is created by the agent through the `
|
|
10
|
+
* Memory is created by the agent through the `aiworker_memory` tool, so
|
|
11
11
|
* there is no create route here; the panel reads, corrects, and deletes.
|
|
12
12
|
*
|
|
13
13
|
* The body parser is attached per route rather than globally: the generic
|
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
import { parse as parseJsonc } from 'jsonc-parser';
|
|
2
1
|
import { pathToFileURL } from 'node:url';
|
|
2
|
+
import { appendManagedPlugin } from '../opencode/managed-plugin-config.js';
|
|
3
3
|
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
AIWORKER_AGENT_TOOL_ACTION_DEFINITIONS,
|
|
5
|
+
AIWORKER_AGENT_TOOL_ACTIONS,
|
|
6
|
+
AIWORKER_MEMORY_ACTION_DEFINITIONS,
|
|
7
|
+
AIWORKER_MEMORY_ACTIONS,
|
|
8
8
|
resolveAgentToolAction,
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
AIWORKER_WEB_ACTION_DEFINITIONS,
|
|
10
|
+
AIWORKER_WEB_ACTIONS,
|
|
11
11
|
} from '../openchamber-control/actions.js';
|
|
12
12
|
|
|
13
13
|
const TOOL_SCHEMA_VERSION = 1;
|
|
14
14
|
// Everything either managed tool may ask for; the agent allowlist stays
|
|
15
15
|
// narrower than the full control surface.
|
|
16
|
-
const ACTIONS = new Set([...
|
|
16
|
+
const ACTIONS = new Set([...AIWORKER_AGENT_TOOL_ACTIONS, ...AIWORKER_WEB_ACTIONS, ...AIWORKER_MEMORY_ACTIONS]);
|
|
17
17
|
const AGENT_TOOL_ACTION_TITLES = Object.fromEntries(
|
|
18
18
|
[
|
|
19
|
-
...
|
|
20
|
-
...
|
|
21
|
-
...
|
|
19
|
+
...AIWORKER_AGENT_TOOL_ACTION_DEFINITIONS,
|
|
20
|
+
...AIWORKER_WEB_ACTION_DEFINITIONS,
|
|
21
|
+
...AIWORKER_MEMORY_ACTION_DEFINITIONS,
|
|
22
22
|
].map(({ action, title }) => [action, title]),
|
|
23
23
|
);
|
|
24
24
|
|
|
@@ -108,9 +108,9 @@ const MEMORY_PARAMETER_PROPERTIES = {
|
|
|
108
108
|
...MEMORY_PARAMETER_OVERRIDES,
|
|
109
109
|
};
|
|
110
110
|
|
|
111
|
-
const CONTROL_TOOL_DESCRIPTION = "Control
|
|
111
|
+
const CONTROL_TOOL_DESCRIPTION = "Control AiWorker projects, sessions, and scheduled tasks on the user's behalf. Sessions and scheduled tasks you create are for the user to follow and interact with; never use this tool to delegate parts of your own current task. Use one action per call. Scope with projectId or directory; omit both to use the current session directory. Session dispatches return immediately by default and you receive no notification when a dispatched session finishes, so never promise to report back on it; the user follows it in AiWorker; a dispatched session needs no follow-up from you. If the user later asks how it went, use session.messages (add wait to block until it is idle, lastAssistant for just the final answer) — session.send always sends a NEW prompt and never just waits. Set wait only when the user asks or the next step requires the completed result. Session and worktree deletion are unavailable.";
|
|
112
112
|
|
|
113
|
-
const WEB_TOOL_DESCRIPTION = "Look at and interact with a web page in
|
|
113
|
+
const WEB_TOOL_DESCRIPTION = "Look at and interact with a web page in AiWorker's browser panel, so you can check your own work rather than describing what you expect. Use one action per call. Open a page, snapshot it to read its text and its interactive elements, then click, type or scroll using the selectors the snapshot returned; snapshots also report any errors the page logged. Pass a selector to browser.snapshot to read one part of a long page. browser.inspect returns computed styles when the question is how something renders. Set viewport to check a layout at mobile, tablet or desktop size. The page runs with the user's real logins, so treat what you see as their live session.";
|
|
114
114
|
|
|
115
115
|
const MEMORY_TOOL_DESCRIPTION = "Keep what you learn across sessions, so the user does not have to explain the same thing twice. Use one action per call. The session already lists the titles of what is stored. A title is an abbreviation, not the memory: read the entry with memory.read before acting on it, because titles leave out the conditions and exceptions that decide how the memory applies, and the ones that look self-explanatory hide them most often. Save something only when it will still be true in a later session — a stable preference, a project convention, a decision and its reason, or a hard-won pointer. Do not save one-off task state, anything you can read from the code, secrets or credentials, or anything the user asked you not to keep. Choose the scope deliberately: global is about the user and reaches every project, so put a project's conventions in project scope. What you save is shown to the user as unreviewed until they confirm it, so save plainly and say what you saved when it matters.";
|
|
116
116
|
|
|
@@ -147,7 +147,7 @@ const isLoopbackAddress = (value) => {
|
|
|
147
147
|
const createToolEntry = ({ name, description, actions, definitions, parameters }) => String.raw` ${name}: {
|
|
148
148
|
description: ${JSON.stringify(description)},
|
|
149
149
|
args: {
|
|
150
|
-
action: { type: "string", enum: ${JSON.stringify(actions)}, oneOf: ${JSON.stringify(definitions.map((entry) => ({ const: entry.action, description: entry.description })))}, description: "
|
|
150
|
+
action: { type: "string", enum: ${JSON.stringify(actions)}, oneOf: ${JSON.stringify(definitions.map((entry) => ({ const: entry.action, description: entry.description })))}, description: "AiWorker action to perform" },
|
|
151
151
|
parameters: { type: "object", properties: ${JSON.stringify(parameters)}, additionalProperties: false, description: "Inputs for the action; use an empty object when none are needed" },
|
|
152
152
|
},
|
|
153
153
|
async execute(input, context) {
|
|
@@ -169,15 +169,15 @@ const createToolEntry = ({ name, description, actions, definitions, parameters }
|
|
|
169
169
|
},
|
|
170
170
|
},
|
|
171
171
|
})
|
|
172
|
-
const endpoint = process.env.
|
|
173
|
-
const token = process.env.
|
|
172
|
+
const endpoint = process.env.AIWORKER_AGENT_TOOL_URL
|
|
173
|
+
const token = process.env.AIWORKER_AGENT_TOOL_TOKEN
|
|
174
174
|
const failure = (payload) => ({
|
|
175
175
|
title,
|
|
176
176
|
output: JSON.stringify(payload),
|
|
177
|
-
metadata: {
|
|
177
|
+
metadata: { aiworker: { schemaVersion: ${TOOL_SCHEMA_VERSION}, action: args.action, description: title, ok: false } },
|
|
178
178
|
})
|
|
179
179
|
if (!endpoint || !token) {
|
|
180
|
-
return failure({ schemaVersion: ${TOOL_SCHEMA_VERSION}, ok: false, action: args.action, error: { message: "
|
|
180
|
+
return failure({ schemaVersion: ${TOOL_SCHEMA_VERSION}, ok: false, action: args.action, error: { message: "AiWorker managed tool connection is unavailable" } })
|
|
181
181
|
}
|
|
182
182
|
|
|
183
183
|
try {
|
|
@@ -205,8 +205,8 @@ const createToolEntry = ({ name, description, actions, definitions, parameters }
|
|
|
205
205
|
},
|
|
206
206
|
},
|
|
207
207
|
})
|
|
208
|
-
if (valid) return { title, output, metadata: {
|
|
209
|
-
return failure({ schemaVersion: ${TOOL_SCHEMA_VERSION}, ok: false, action: args.action, error: { message: "
|
|
208
|
+
if (valid) return { title, output, metadata: { aiworker: { schemaVersion: ${TOOL_SCHEMA_VERSION}, action: args.action, description: title, ok: result.ok === true } } }
|
|
209
|
+
return failure({ schemaVersion: ${TOOL_SCHEMA_VERSION}, ok: false, action: args.action, error: { message: "AiWorker returned an invalid response", kind: "runtime", status: response.status } })
|
|
210
210
|
} catch (error) {
|
|
211
211
|
if (context.abort.aborted) throw error
|
|
212
212
|
return failure({ schemaVersion: ${TOOL_SCHEMA_VERSION}, ok: false, action: args.action, error: { message: error instanceof Error ? error.message : String(error), kind: "runtime" } })
|
|
@@ -219,56 +219,39 @@ const createPluginSource = ({ includeControl, includeWeb, includeMemory }) => {
|
|
|
219
219
|
const entries = [];
|
|
220
220
|
if (includeControl) {
|
|
221
221
|
entries.push(createToolEntry({
|
|
222
|
-
name: '
|
|
222
|
+
name: 'aiworker',
|
|
223
223
|
description: CONTROL_TOOL_DESCRIPTION,
|
|
224
|
-
actions:
|
|
225
|
-
definitions:
|
|
224
|
+
actions: AIWORKER_AGENT_TOOL_ACTIONS,
|
|
225
|
+
definitions: AIWORKER_AGENT_TOOL_ACTION_DEFINITIONS,
|
|
226
226
|
parameters: CONTROL_PARAMETER_PROPERTIES,
|
|
227
227
|
}));
|
|
228
228
|
}
|
|
229
229
|
if (includeWeb) {
|
|
230
230
|
entries.push(createToolEntry({
|
|
231
|
-
name: '
|
|
231
|
+
name: 'aiworker_web',
|
|
232
232
|
description: WEB_TOOL_DESCRIPTION,
|
|
233
|
-
actions:
|
|
234
|
-
definitions:
|
|
233
|
+
actions: AIWORKER_WEB_ACTIONS,
|
|
234
|
+
definitions: AIWORKER_WEB_ACTION_DEFINITIONS,
|
|
235
235
|
parameters: WEB_PARAMETER_PROPERTIES,
|
|
236
236
|
}));
|
|
237
237
|
}
|
|
238
238
|
if (includeMemory) {
|
|
239
239
|
entries.push(createToolEntry({
|
|
240
|
-
name: '
|
|
240
|
+
name: 'aiworker_memory',
|
|
241
241
|
description: MEMORY_TOOL_DESCRIPTION,
|
|
242
|
-
actions:
|
|
243
|
-
definitions:
|
|
242
|
+
actions: AIWORKER_MEMORY_ACTIONS,
|
|
243
|
+
definitions: AIWORKER_MEMORY_ACTION_DEFINITIONS,
|
|
244
244
|
parameters: MEMORY_PARAMETER_PROPERTIES,
|
|
245
245
|
}));
|
|
246
246
|
}
|
|
247
247
|
|
|
248
|
-
return `export const
|
|
248
|
+
return `export const AiWorkerPlugin = async () => ({
|
|
249
249
|
tool: {
|
|
250
250
|
${entries.join('')} },
|
|
251
251
|
})
|
|
252
252
|
`;
|
|
253
253
|
};
|
|
254
254
|
|
|
255
|
-
const mergePluginConfig = (rawConfig, pluginUrl) => {
|
|
256
|
-
const errors = [];
|
|
257
|
-
const parsed = asNonEmptyString(rawConfig) ? parseJsonc(rawConfig, errors, { allowTrailingComma: true }) : {};
|
|
258
|
-
if (errors.length > 0 || !parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
|
259
|
-
throw new Error('OPENCODE_CONFIG_CONTENT must contain a valid JSON object before OpenChamber can inject its managed tool');
|
|
260
|
-
}
|
|
261
|
-
if (parsed.plugin !== undefined && !Array.isArray(parsed.plugin)) {
|
|
262
|
-
throw new Error('OPENCODE_CONFIG_CONTENT plugin must be an array before OpenChamber can inject its managed tool');
|
|
263
|
-
}
|
|
264
|
-
const configured = Array.isArray(parsed.plugin) ? parsed.plugin : [];
|
|
265
|
-
parsed.plugin = [
|
|
266
|
-
...configured.filter((value) => value !== pluginUrl && (!Array.isArray(value) || value[0] !== pluginUrl)),
|
|
267
|
-
pluginUrl,
|
|
268
|
-
];
|
|
269
|
-
return JSON.stringify(parsed);
|
|
270
|
-
};
|
|
271
|
-
|
|
272
255
|
export const createAgentToolRuntime = (dependencies) => {
|
|
273
256
|
const {
|
|
274
257
|
crypto,
|
|
@@ -286,19 +269,19 @@ export const createAgentToolRuntime = (dependencies) => {
|
|
|
286
269
|
const prepareManagedOpenCodeEnv = async ({ includeControl = true, includeWeb = true, includeMemory = true } = {}) => {
|
|
287
270
|
const port = getActivePort();
|
|
288
271
|
if (!Number.isInteger(port) || port <= 0) {
|
|
289
|
-
throw new Error('
|
|
272
|
+
throw new Error('AiWorker listener port is unavailable for managed tool injection');
|
|
290
273
|
}
|
|
291
274
|
if (!includeControl && !includeWeb && !includeMemory) {
|
|
292
|
-
throw new Error('At least one
|
|
275
|
+
throw new Error('At least one AiWorker managed tool must be enabled to inject the plugin');
|
|
293
276
|
}
|
|
294
277
|
await fsPromises.mkdir(pluginDirectory, { recursive: true });
|
|
295
278
|
await fsPromises.writeFile(pluginPath, createPluginSource({ includeControl, includeWeb, includeMemory }), { mode: 0o600 });
|
|
296
279
|
activeToken = crypto.randomBytes(32).toString('base64url');
|
|
297
280
|
const pluginUrl = pathToFileURL(pluginPath).href;
|
|
298
281
|
return {
|
|
299
|
-
OPENCODE_CONFIG_CONTENT:
|
|
300
|
-
|
|
301
|
-
|
|
282
|
+
OPENCODE_CONFIG_CONTENT: appendManagedPlugin(env.OPENCODE_CONFIG_CONTENT, pluginUrl, 'managed tool'),
|
|
283
|
+
AIWORKER_AGENT_TOOL_URL: `http://127.0.0.1:${port}/api/openchamber/agent-tool`,
|
|
284
|
+
AIWORKER_AGENT_TOOL_TOKEN: activeToken,
|
|
302
285
|
};
|
|
303
286
|
};
|
|
304
287
|
|
|
@@ -322,10 +305,10 @@ export const createAgentToolRuntime = (dependencies) => {
|
|
|
322
305
|
}
|
|
323
306
|
const action = resolution.action;
|
|
324
307
|
if (!ACTIONS.has(action)) {
|
|
325
|
-
return createResult({ ok: false, action, error: { message: `Unsupported
|
|
308
|
+
return createResult({ ok: false, action, error: { message: `Unsupported AiWorker action: ${action}`, kind: 'usage' } });
|
|
326
309
|
}
|
|
327
310
|
if (typeof executeAction !== 'function') {
|
|
328
|
-
return createResult({ ok: false, action, error: { message: '
|
|
311
|
+
return createResult({ ok: false, action, error: { message: 'AiWorker control service is unavailable', kind: 'runtime' } });
|
|
329
312
|
}
|
|
330
313
|
try {
|
|
331
314
|
const data = await executeAction(action, { ...payload.input, action }, payload.contextDirectory, options);
|
|
@@ -8,7 +8,7 @@ import request from 'supertest';
|
|
|
8
8
|
import { afterEach, describe, expect, it, vi } from 'vitest';
|
|
9
9
|
|
|
10
10
|
import { createAgentToolRuntime } from './runtime.js';
|
|
11
|
-
import {
|
|
11
|
+
import { AIWORKER_AGENT_TOOL_ACTION_DEFINITIONS, AIWORKER_CONTROL_ACTION_DEFINITIONS } from '../openchamber-control/actions.js';
|
|
12
12
|
|
|
13
13
|
const temporaryDirectories = [];
|
|
14
14
|
|
|
@@ -36,7 +36,7 @@ const createRuntime = async (overrides = {}) => {
|
|
|
36
36
|
|
|
37
37
|
describe('agent tool action allowlist', () => {
|
|
38
38
|
it('defines a short title and agent description for every action', () => {
|
|
39
|
-
expect(
|
|
39
|
+
expect(AIWORKER_CONTROL_ACTION_DEFINITIONS.every(({ action, title, description }) => action && title && description)).toBe(true);
|
|
40
40
|
});
|
|
41
41
|
|
|
42
42
|
it.each([
|
|
@@ -90,28 +90,28 @@ describe('managed agent tool runtime', () => {
|
|
|
90
90
|
['example-plugin', { flag: true }],
|
|
91
91
|
expect.stringContaining('/agent-tool/openchamber-plugin.js'),
|
|
92
92
|
]);
|
|
93
|
-
expect(preparedEnv.
|
|
94
|
-
expect(preparedEnv.
|
|
95
|
-
expect(source).toContain('
|
|
96
|
-
for (const { action, description } of
|
|
93
|
+
expect(preparedEnv.AIWORKER_AGENT_TOOL_URL).toBe('http://127.0.0.1:3901/api/openchamber/agent-tool');
|
|
94
|
+
expect(preparedEnv.AIWORKER_AGENT_TOOL_TOKEN).toMatch(/^[A-Za-z0-9_-]+$/);
|
|
95
|
+
expect(source).toContain('aiworker: {');
|
|
96
|
+
for (const { action, description } of AIWORKER_AGENT_TOOL_ACTION_DEFINITIONS) {
|
|
97
97
|
expect(source).toContain(JSON.stringify({ const: action, description }));
|
|
98
98
|
}
|
|
99
99
|
expect(source).not.toContain('"schedule.status"');
|
|
100
100
|
const pluginModule = await import(`${pathToFileURL(pluginPath).href}?schema=${Date.now()}`);
|
|
101
|
-
const hooks = await pluginModule.
|
|
102
|
-
expect(hooks.tool.
|
|
103
|
-
expect(hooks.tool.
|
|
104
|
-
expect(hooks.tool.
|
|
101
|
+
const hooks = await pluginModule.AiWorkerPlugin();
|
|
102
|
+
expect(hooks.tool.aiworker.description).toContain('Session dispatches return immediately by default');
|
|
103
|
+
expect(hooks.tool.aiworker.description).toContain('Set wait only when the user asks or the next step requires the completed result');
|
|
104
|
+
expect(hooks.tool.aiworker.args.action.oneOf).toContainEqual({
|
|
105
105
|
const: 'session.messages',
|
|
106
106
|
description: 'Read text-only messages and current sessionStatus for sessionId; directory and limit 10 are defaults',
|
|
107
107
|
});
|
|
108
|
-
expect(hooks.tool.
|
|
108
|
+
expect(hooks.tool.aiworker.args.parameters.properties.wait.description).toBe(
|
|
109
109
|
'Wait for current session activity to become idle. Omit by default; use only when the user asks or the next step requires the completed result',
|
|
110
110
|
);
|
|
111
|
-
expect(hooks.tool.
|
|
112
|
-
expect(source).not.toContain('title: "
|
|
111
|
+
expect(hooks.tool.aiworker.args.parameters.properties.sessionId).toEqual({ type: 'string' });
|
|
112
|
+
expect(source).not.toContain('title: "AiWorker"');
|
|
113
113
|
expect(source).not.toContain('@opencode-ai/plugin');
|
|
114
|
-
expect(source).not.toContain(preparedEnv.
|
|
114
|
+
expect(source).not.toContain(preparedEnv.AIWORKER_AGENT_TOOL_TOKEN);
|
|
115
115
|
});
|
|
116
116
|
|
|
117
117
|
it('emits both tools, each carrying only its own actions and inputs', async () => {
|
|
@@ -119,18 +119,18 @@ describe('managed agent tool runtime', () => {
|
|
|
119
119
|
await runtime.prepareManagedOpenCodeEnv();
|
|
120
120
|
const pluginPath = path.join(dataDir, 'agent-tool', 'openchamber-plugin.js');
|
|
121
121
|
const pluginModule = await import(`${pathToFileURL(pluginPath).href}?both=${Date.now()}`);
|
|
122
|
-
const { tool } = await pluginModule.
|
|
122
|
+
const { tool } = await pluginModule.AiWorkerPlugin();
|
|
123
123
|
|
|
124
|
-
const controlActions = tool.
|
|
125
|
-
const webActions = tool.
|
|
124
|
+
const controlActions = tool.aiworker.args.action.enum;
|
|
125
|
+
const webActions = tool.aiworker_web.args.action.enum;
|
|
126
126
|
expect(webActions).toContain('browser.open');
|
|
127
127
|
expect(controlActions).not.toContain('browser.open');
|
|
128
128
|
expect(webActions).not.toContain('session.create');
|
|
129
129
|
|
|
130
130
|
// Turning one tool off has to remove its inputs too, not just its actions.
|
|
131
|
-
expect(Object.keys(tool.
|
|
132
|
-
expect(Object.keys(tool.
|
|
133
|
-
expect(Object.keys(tool.
|
|
131
|
+
expect(Object.keys(tool.aiworker_web.args.parameters.properties)).toContain('url');
|
|
132
|
+
expect(Object.keys(tool.aiworker.args.parameters.properties)).not.toContain('url');
|
|
133
|
+
expect(Object.keys(tool.aiworker.args.parameters.properties)).toContain('sessionId');
|
|
134
134
|
});
|
|
135
135
|
|
|
136
136
|
it('accepts inputs passed beside the action, not only inside parameters', async () => {
|
|
@@ -138,14 +138,14 @@ describe('managed agent tool runtime', () => {
|
|
|
138
138
|
const prepared = await runtime.prepareManagedOpenCodeEnv();
|
|
139
139
|
const pluginPath = path.join(dataDir, 'agent-tool', 'openchamber-plugin.js');
|
|
140
140
|
const pluginModule = await import(`${pathToFileURL(pluginPath).href}?flat=${Date.now()}`);
|
|
141
|
-
const { tool } = await pluginModule.
|
|
141
|
+
const { tool } = await pluginModule.AiWorkerPlugin();
|
|
142
142
|
|
|
143
143
|
const sent = [];
|
|
144
144
|
const originalFetch = globalThis.fetch;
|
|
145
|
-
const originalUrl = process.env.
|
|
146
|
-
const originalToken = process.env.
|
|
147
|
-
process.env.
|
|
148
|
-
process.env.
|
|
145
|
+
const originalUrl = process.env.AIWORKER_AGENT_TOOL_URL;
|
|
146
|
+
const originalToken = process.env.AIWORKER_AGENT_TOOL_TOKEN;
|
|
147
|
+
process.env.AIWORKER_AGENT_TOOL_URL = prepared.AIWORKER_AGENT_TOOL_URL;
|
|
148
|
+
process.env.AIWORKER_AGENT_TOOL_TOKEN = prepared.AIWORKER_AGENT_TOOL_TOKEN;
|
|
149
149
|
globalThis.fetch = async (_endpoint, init) => {
|
|
150
150
|
sent.push(JSON.parse(init.body));
|
|
151
151
|
return new Response(JSON.stringify({ schemaVersion: 1, ok: true, action: 'browser.open', data: {} }));
|
|
@@ -154,24 +154,24 @@ describe('managed agent tool runtime', () => {
|
|
|
154
154
|
|
|
155
155
|
try {
|
|
156
156
|
// The shape a model actually produced: url and viewport next to action.
|
|
157
|
-
await tool.
|
|
157
|
+
await tool.aiworker_web.execute(
|
|
158
158
|
{ action: 'browser.open', url: 'https://example.test', viewport: 'mobile' },
|
|
159
159
|
context,
|
|
160
160
|
);
|
|
161
161
|
// The documented shape must keep working, and win when both are present.
|
|
162
|
-
await tool.
|
|
162
|
+
await tool.aiworker_web.execute(
|
|
163
163
|
{ action: 'browser.open', url: 'https://ignored.test', parameters: { url: 'https://example.test/nested' } },
|
|
164
164
|
context,
|
|
165
165
|
);
|
|
166
166
|
// Both tools come from one template, so session control accepts it too.
|
|
167
|
-
await tool.
|
|
167
|
+
await tool.aiworker.execute(
|
|
168
168
|
{ action: 'session.messages', sessionId: 'ses_1', limit: 3 },
|
|
169
169
|
context,
|
|
170
170
|
);
|
|
171
171
|
} finally {
|
|
172
172
|
globalThis.fetch = originalFetch;
|
|
173
|
-
process.env.
|
|
174
|
-
process.env.
|
|
173
|
+
process.env.AIWORKER_AGENT_TOOL_URL = originalUrl;
|
|
174
|
+
process.env.AIWORKER_AGENT_TOOL_TOKEN = originalToken;
|
|
175
175
|
}
|
|
176
176
|
|
|
177
177
|
expect(sent[0].input).toEqual({ action: 'browser.open', url: 'https://example.test', viewport: 'mobile' });
|
|
@@ -184,9 +184,9 @@ describe('managed agent tool runtime', () => {
|
|
|
184
184
|
await runtime.prepareManagedOpenCodeEnv({ includeControl: false, includeWeb: true, includeMemory: false });
|
|
185
185
|
const pluginPath = path.join(dataDir, 'agent-tool', 'openchamber-plugin.js');
|
|
186
186
|
const pluginModule = await import(`${pathToFileURL(pluginPath).href}?web=${Date.now()}`);
|
|
187
|
-
const { tool } = await pluginModule.
|
|
187
|
+
const { tool } = await pluginModule.AiWorkerPlugin();
|
|
188
188
|
|
|
189
|
-
expect(Object.keys(tool)).toEqual(['
|
|
189
|
+
expect(Object.keys(tool)).toEqual(['aiworker_web']);
|
|
190
190
|
});
|
|
191
191
|
|
|
192
192
|
it('exposes memory as its own tool carrying only its own inputs', async () => {
|
|
@@ -194,14 +194,14 @@ describe('managed agent tool runtime', () => {
|
|
|
194
194
|
await runtime.prepareManagedOpenCodeEnv({ includeControl: true, includeWeb: false, includeMemory: true });
|
|
195
195
|
const pluginPath = path.join(dataDir, 'agent-tool', 'openchamber-plugin.js');
|
|
196
196
|
const pluginModule = await import(`${pathToFileURL(pluginPath).href}?memory=${Date.now()}`);
|
|
197
|
-
const { tool } = await pluginModule.
|
|
197
|
+
const { tool } = await pluginModule.AiWorkerPlugin();
|
|
198
198
|
|
|
199
|
-
expect(Object.keys(tool)).toEqual(['
|
|
200
|
-
expect(Object.keys(tool.
|
|
199
|
+
expect(Object.keys(tool)).toEqual(['aiworker', 'aiworker_memory']);
|
|
200
|
+
expect(Object.keys(tool.aiworker_memory.args.parameters.properties).sort())
|
|
201
201
|
.toEqual(['body', 'memoryId', 'scope', 'title', 'type']);
|
|
202
202
|
// Memory inputs must not leak into the control tool's schema, which the
|
|
203
203
|
// model pays for on every unrelated call.
|
|
204
|
-
expect(Object.keys(tool.
|
|
204
|
+
expect(Object.keys(tool.aiworker.args.parameters.properties)).not.toContain('memoryId');
|
|
205
205
|
});
|
|
206
206
|
|
|
207
207
|
it('omits memory entirely when the user turns it off', async () => {
|
|
@@ -209,9 +209,9 @@ describe('managed agent tool runtime', () => {
|
|
|
209
209
|
await runtime.prepareManagedOpenCodeEnv({ includeControl: true, includeWeb: false, includeMemory: false });
|
|
210
210
|
const pluginPath = path.join(dataDir, 'agent-tool', 'openchamber-plugin.js');
|
|
211
211
|
const pluginModule = await import(`${pathToFileURL(pluginPath).href}?nomemory=${Date.now()}`);
|
|
212
|
-
const { tool } = await pluginModule.
|
|
212
|
+
const { tool } = await pluginModule.AiWorkerPlugin();
|
|
213
213
|
|
|
214
|
-
expect(Object.keys(tool)).toEqual(['
|
|
214
|
+
expect(Object.keys(tool)).toEqual(['aiworker']);
|
|
215
215
|
});
|
|
216
216
|
|
|
217
217
|
it('injects the plugin when memory is the only tool left on', async () => {
|
|
@@ -219,9 +219,9 @@ describe('managed agent tool runtime', () => {
|
|
|
219
219
|
await runtime.prepareManagedOpenCodeEnv({ includeControl: false, includeWeb: false, includeMemory: true });
|
|
220
220
|
const pluginPath = path.join(dataDir, 'agent-tool', 'openchamber-plugin.js');
|
|
221
221
|
const pluginModule = await import(`${pathToFileURL(pluginPath).href}?onlymemory=${Date.now()}`);
|
|
222
|
-
const { tool } = await pluginModule.
|
|
222
|
+
const { tool } = await pluginModule.AiWorkerPlugin();
|
|
223
223
|
|
|
224
|
-
expect(Object.keys(tool)).toEqual(['
|
|
224
|
+
expect(Object.keys(tool)).toEqual(['aiworker_memory']);
|
|
225
225
|
});
|
|
226
226
|
|
|
227
227
|
it('refuses to inject a plugin with no tools in it', async () => {
|
|
@@ -236,7 +236,7 @@ describe('managed agent tool runtime', () => {
|
|
|
236
236
|
});
|
|
237
237
|
|
|
238
238
|
it('accepts the bare action a tool name already qualifies', async () => {
|
|
239
|
-
// Observed: the model called `read` on
|
|
239
|
+
// Observed: the model called `read` on aiworker_memory, having taken the
|
|
240
240
|
// tool's own name for the namespace.
|
|
241
241
|
const executeAction = vi.fn(async () => ({ memory: {} }));
|
|
242
242
|
const { runtime } = await createRuntime({ executeAction });
|
|
@@ -244,7 +244,7 @@ describe('managed agent tool runtime', () => {
|
|
|
244
244
|
const result = await runtime.execute({
|
|
245
245
|
input: { action: 'read', title: 'Uses bun' },
|
|
246
246
|
contextDirectory: '/work/project',
|
|
247
|
-
tool: '
|
|
247
|
+
tool: 'aiworker_memory',
|
|
248
248
|
});
|
|
249
249
|
|
|
250
250
|
expect(result.ok).toBe(true);
|
|
@@ -262,7 +262,7 @@ describe('managed agent tool runtime', () => {
|
|
|
262
262
|
|
|
263
263
|
const result = await runtime.execute({
|
|
264
264
|
input: { action: 'get' },
|
|
265
|
-
tool: '
|
|
265
|
+
tool: 'aiworker_memory',
|
|
266
266
|
});
|
|
267
267
|
|
|
268
268
|
expect(result.ok).toBe(false);
|
|
@@ -276,7 +276,7 @@ describe('managed agent tool runtime', () => {
|
|
|
276
276
|
|
|
277
277
|
const result = await runtime.execute({
|
|
278
278
|
input: { action: 'open', url: 'https://example.test' },
|
|
279
|
-
tool: '
|
|
279
|
+
tool: 'aiworker_memory',
|
|
280
280
|
});
|
|
281
281
|
|
|
282
282
|
expect(result.ok).toBe(false);
|
|
@@ -318,7 +318,7 @@ describe('managed agent tool runtime', () => {
|
|
|
318
318
|
it('forwards cancellation to the shared control service', async () => {
|
|
319
319
|
const executeAction = vi.fn(async (_action, _input, _directory, options) => {
|
|
320
320
|
await new Promise((resolve, reject) => {
|
|
321
|
-
options.signal.addEventListener('abort', () => reject(Object.assign(new Error('
|
|
321
|
+
options.signal.addEventListener('abort', () => reject(Object.assign(new Error('AiWorker action was cancelled'), { statusCode: 499 })), { once: true });
|
|
322
322
|
});
|
|
323
323
|
});
|
|
324
324
|
const { runtime } = await createRuntime({ executeAction });
|
|
@@ -330,7 +330,7 @@ describe('managed agent tool runtime', () => {
|
|
|
330
330
|
await expect(pending).resolves.toEqual(expect.objectContaining({
|
|
331
331
|
ok: false,
|
|
332
332
|
action: 'projects.list',
|
|
333
|
-
error: { message: '
|
|
333
|
+
error: { message: 'AiWorker action was cancelled', kind: 'runtime' },
|
|
334
334
|
}));
|
|
335
335
|
expect(executeAction).toHaveBeenCalledWith('projects.list', { action: 'projects.list' }, undefined, { signal: controller.signal });
|
|
336
336
|
});
|
|
@@ -348,7 +348,7 @@ describe('managed agent tool runtime', () => {
|
|
|
348
348
|
|
|
349
349
|
const response = await request(app)
|
|
350
350
|
.post('/api/openchamber/agent-tool')
|
|
351
|
-
.set('authorization', `Bearer ${env.
|
|
351
|
+
.set('authorization', `Bearer ${env.AIWORKER_AGENT_TOOL_TOKEN}`)
|
|
352
352
|
.send({ input: { action: 'projects.list' } })
|
|
353
353
|
.expect(200);
|
|
354
354
|
expect(response.body).toEqual(expect.objectContaining({ ok: true, action: 'projects.list' }));
|
|
@@ -364,18 +364,18 @@ describe('managed agent tool runtime', () => {
|
|
|
364
364
|
});
|
|
365
365
|
activePort = server.address().port;
|
|
366
366
|
|
|
367
|
-
const previousUrl = process.env.
|
|
368
|
-
const previousToken = process.env.
|
|
367
|
+
const previousUrl = process.env.AIWORKER_AGENT_TOOL_URL;
|
|
368
|
+
const previousToken = process.env.AIWORKER_AGENT_TOOL_TOKEN;
|
|
369
369
|
try {
|
|
370
370
|
const env = await runtime.prepareManagedOpenCodeEnv();
|
|
371
|
-
process.env.
|
|
372
|
-
process.env.
|
|
371
|
+
process.env.AIWORKER_AGENT_TOOL_URL = env.AIWORKER_AGENT_TOOL_URL;
|
|
372
|
+
process.env.AIWORKER_AGENT_TOOL_TOKEN = env.AIWORKER_AGENT_TOOL_TOKEN;
|
|
373
373
|
const pluginPath = path.join(dataDir, 'agent-tool', 'openchamber-plugin.js');
|
|
374
374
|
const pluginModule = await import(`${pathToFileURL(pluginPath).href}?test=${Date.now()}`);
|
|
375
|
-
const hooks = await pluginModule.
|
|
375
|
+
const hooks = await pluginModule.AiWorkerPlugin();
|
|
376
376
|
const metadata = vi.fn();
|
|
377
377
|
|
|
378
|
-
const result = await hooks.tool.
|
|
378
|
+
const result = await hooks.tool.aiworker.execute(
|
|
379
379
|
{ action: 'projects.list', parameters: {} },
|
|
380
380
|
{ directory: '/work/project', abort: new AbortController().signal, metadata },
|
|
381
381
|
);
|
|
@@ -387,18 +387,18 @@ describe('managed agent tool runtime', () => {
|
|
|
387
387
|
data: { projects: [] },
|
|
388
388
|
});
|
|
389
389
|
expect(result.title).toBe('List configured projects');
|
|
390
|
-
expect(result.metadata.
|
|
390
|
+
expect(result.metadata.aiworker.description).toBe('List configured projects');
|
|
391
391
|
expect(metadata).toHaveBeenCalledWith(expect.objectContaining({
|
|
392
392
|
title: 'List configured projects',
|
|
393
393
|
metadata: expect.objectContaining({
|
|
394
|
-
|
|
394
|
+
aiworker: expect.objectContaining({ description: 'List configured projects' }),
|
|
395
395
|
}),
|
|
396
396
|
}));
|
|
397
397
|
} finally {
|
|
398
|
-
if (previousUrl === undefined) delete process.env.
|
|
399
|
-
else process.env.
|
|
400
|
-
if (previousToken === undefined) delete process.env.
|
|
401
|
-
else process.env.
|
|
398
|
+
if (previousUrl === undefined) delete process.env.AIWORKER_AGENT_TOOL_URL;
|
|
399
|
+
else process.env.AIWORKER_AGENT_TOOL_URL = previousUrl;
|
|
400
|
+
if (previousToken === undefined) delete process.env.AIWORKER_AGENT_TOOL_TOKEN;
|
|
401
|
+
else process.env.AIWORKER_AGENT_TOOL_TOKEN = previousToken;
|
|
402
402
|
await new Promise((resolve, reject) => server.close((error) => error ? reject(error) : resolve()));
|
|
403
403
|
}
|
|
404
404
|
});
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Request/response broker between the agent tool and the in-app browser.
|
|
3
3
|
*
|
|
4
4
|
* The browser lives in the renderer, not the server, so the server cannot act
|
|
5
|
-
* on a page directly. It publishes a request over the existing
|
|
5
|
+
* on a page directly. It publishes a request over the existing AiWorker
|
|
6
6
|
* event stream and waits for the client that owns the browser view to post the
|
|
7
7
|
* result back.
|
|
8
8
|
*
|
|
@@ -73,8 +73,8 @@ export const createBrowserControlBroker = ({
|
|
|
73
73
|
// environment can do, and leave deciding whether it matters to the
|
|
74
74
|
// caller rather than handing it an instruction it cannot carry out.
|
|
75
75
|
return Promise.reject(new BrowserControlError(
|
|
76
|
-
'No
|
|
77
|
-
+ 'interacting with a page works when
|
|
76
|
+
'No AiWorker client connected here can control a page. Reading and '
|
|
77
|
+
+ 'interacting with a page works when AiWorker runs as its desktop '
|
|
78
78
|
+ 'application; a web browser tab can display a page but cannot be '
|
|
79
79
|
+ 'driven. Nothing was changed. Mention this to the user only if it '
|
|
80
80
|
+ 'affects what they asked for.',
|
|
@@ -102,7 +102,7 @@ describe('browser control broker', () => {
|
|
|
102
102
|
test('fails everything in flight when the owning client disconnects', async () => {
|
|
103
103
|
const { broker } = createBroker();
|
|
104
104
|
const inflight = broker.request('browser.snapshot', {});
|
|
105
|
-
broker.rejectAll('The
|
|
105
|
+
broker.rejectAll('The AiWorker client disconnected');
|
|
106
106
|
await expect(inflight).rejects.toThrow('disconnected');
|
|
107
107
|
expect(broker.pendingCount).toBe(0);
|
|
108
108
|
});
|