@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
|
@@ -2,13 +2,13 @@ import fs from 'fs';
|
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import os from 'os';
|
|
4
4
|
|
|
5
|
-
const
|
|
6
|
-
? path.resolve(process.env.
|
|
7
|
-
: path.join(os.homedir(), '.config', '
|
|
5
|
+
const AIWORKER_DATA_DIR = process.env.AIWORKER_DATA_DIR
|
|
6
|
+
? path.resolve(process.env.AIWORKER_DATA_DIR)
|
|
7
|
+
: path.join(os.homedir(), '.config', 'aiworker');
|
|
8
8
|
|
|
9
|
-
const STORAGE_DIR =
|
|
9
|
+
const STORAGE_DIR = AIWORKER_DATA_DIR;
|
|
10
10
|
const STORAGE_FILE = path.join(STORAGE_DIR, 'github-auth.json');
|
|
11
|
-
const SETTINGS_FILE = path.join(
|
|
11
|
+
const SETTINGS_FILE = path.join(AIWORKER_DATA_DIR, 'settings.json');
|
|
12
12
|
|
|
13
13
|
const DEFAULT_GITHUB_CLIENT_ID = 'Ov23lizomPOC3eFYo56r';
|
|
14
14
|
const DEFAULT_GITHUB_SCOPES = 'repo read:org workflow read:user user:email';
|
|
@@ -45,7 +45,7 @@ function readJsonFile() {
|
|
|
45
45
|
function writeJsonFile(payload) {
|
|
46
46
|
ensureStorageDir();
|
|
47
47
|
|
|
48
|
-
// Atomic write so multiple
|
|
48
|
+
// Atomic write so multiple AiWorker instances can safely share the same file.
|
|
49
49
|
const tmpFile = `${STORAGE_FILE}.${process.pid}.${Date.now()}.tmp`;
|
|
50
50
|
fs.writeFileSync(tmpFile, JSON.stringify(payload, null, 2), 'utf8');
|
|
51
51
|
try {
|
|
@@ -299,7 +299,7 @@ export function clearGitHubAuth() {
|
|
|
299
299
|
}
|
|
300
300
|
|
|
301
301
|
export function getGitHubClientId() {
|
|
302
|
-
const raw = process.env.
|
|
302
|
+
const raw = process.env.AIWORKER_GITHUB_CLIENT_ID;
|
|
303
303
|
const clientId = typeof raw === 'string' ? raw.trim() : '';
|
|
304
304
|
if (clientId) return clientId;
|
|
305
305
|
|
|
@@ -317,7 +317,7 @@ export function getGitHubClientId() {
|
|
|
317
317
|
}
|
|
318
318
|
|
|
319
319
|
export function getGitHubScopes() {
|
|
320
|
-
const raw = process.env.
|
|
320
|
+
const raw = process.env.AIWORKER_GITHUB_SCOPES;
|
|
321
321
|
const fromEnv = typeof raw === 'string' ? raw.trim() : '';
|
|
322
322
|
if (fromEnv) return fromEnv;
|
|
323
323
|
|
|
@@ -339,7 +339,7 @@ const repoPullsCache = new Map();
|
|
|
339
339
|
// head, and while that one is open the open-PR path wins and never reads this
|
|
340
340
|
// cache at all. "No history yet" is the volatile answer, since closing or
|
|
341
341
|
// merging a PR elsewhere flips it, so it expires far sooner. Either way, doing
|
|
342
|
-
// it from
|
|
342
|
+
// it from AiWorker invalidates the entry immediately.
|
|
343
343
|
const HISTORICAL_PR_FOUND_TTL_MS = 6 * 60 * 60 * 1000;
|
|
344
344
|
const HISTORICAL_PR_ABSENT_TTL_MS = 10 * 60 * 1000;
|
|
345
345
|
const HISTORICAL_PR_CACHE_MAX_ENTRIES = 500;
|
|
@@ -281,7 +281,7 @@ export function registerGitHubRoutes(app) {
|
|
|
281
281
|
const clientId = getGitHubClientId();
|
|
282
282
|
if (!clientId) {
|
|
283
283
|
return res.status(400).json({
|
|
284
|
-
error: 'GitHub OAuth client not configured. Set
|
|
284
|
+
error: 'GitHub OAuth client not configured. Set AIWORKER_GITHUB_CLIENT_ID.',
|
|
285
285
|
});
|
|
286
286
|
}
|
|
287
287
|
|
|
@@ -313,7 +313,7 @@ export function registerGitHubRoutes(app) {
|
|
|
313
313
|
const clientId = getGitHubClientId();
|
|
314
314
|
if (!clientId) {
|
|
315
315
|
return res.status(400).json({
|
|
316
|
-
error: 'GitHub OAuth client not configured. Set
|
|
316
|
+
error: 'GitHub OAuth client not configured. Set AIWORKER_GITHUB_CLIENT_ID.',
|
|
317
317
|
});
|
|
318
318
|
}
|
|
319
319
|
|
|
@@ -6,13 +6,15 @@
|
|
|
6
6
|
* external command it spawns, which corrupts Python venv detection and any
|
|
7
7
|
* other program that reads argv[0]/$0 while leaving `/proc/self/exe` correct.
|
|
8
8
|
*
|
|
9
|
-
* See
|
|
9
|
+
* See aiworker/openchamber#2588 and pingdotgg/t3code#2509.
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
import { createRequire } from 'node:module';
|
|
13
13
|
import { existsSync } from 'node:fs';
|
|
14
14
|
|
|
15
|
-
const
|
|
15
|
+
const POSIX_ENV_BINARIES = ['/usr/bin/env', '/bin/env'];
|
|
16
|
+
/** Variables a PTY shell must never inherit from the AiWorker host process. */
|
|
17
|
+
const PTY_HOST_PRIVATE_VARIABLES = Object.freeze(['ARGV0', 'NODE_CHANNEL_FD']);
|
|
16
18
|
|
|
17
19
|
/**
|
|
18
20
|
* Remove AppImage `ARGV0` from a mutable env object (or `process.env`).
|
|
@@ -49,26 +51,31 @@ export function clearAppImageArgv0FromProcessEnv() {
|
|
|
49
51
|
}
|
|
50
52
|
|
|
51
53
|
/**
|
|
52
|
-
* Resolve a
|
|
54
|
+
* Resolve a POSIX PTY launch that unsets host-private variables before the
|
|
55
|
+
* shell starts.
|
|
53
56
|
*
|
|
54
|
-
* `bun-pty` merges the OS environ into the child, so deleting
|
|
55
|
-
* JS env object alone is not enough
|
|
56
|
-
*
|
|
57
|
+
* `bun-pty` merges the OS environ into the child, so deleting a variable from
|
|
58
|
+
* the JS env object alone is not enough: AppImage `ARGV0` came back on Linux,
|
|
59
|
+
* and the daemon's `NODE_CHANNEL_FD` came back everywhere (Node then warns
|
|
60
|
+
* "Failed to parse IPC channel number" when a CLI such as opencode exits).
|
|
61
|
+
* Wrapping with `env -u NAME ...` unsets them before execing the real shell.
|
|
62
|
+
* No-op on Windows and when no `env` binary is found.
|
|
57
63
|
*
|
|
58
64
|
* @param {string} executable
|
|
59
65
|
* @param {string[]} args
|
|
66
|
+
* @param {readonly string[]} variables
|
|
60
67
|
* @returns {{ executable: string, args: string[] }}
|
|
61
68
|
*/
|
|
62
|
-
export function
|
|
63
|
-
if (process.platform
|
|
69
|
+
export function resolvePosixPtyLaunch(executable, args = [], variables = PTY_HOST_PRIVATE_VARIABLES) {
|
|
70
|
+
if (process.platform === 'win32' || variables.length === 0) {
|
|
64
71
|
return { executable, args };
|
|
65
72
|
}
|
|
66
|
-
const envBinary =
|
|
73
|
+
const envBinary = POSIX_ENV_BINARIES.find((candidate) => existsSync(candidate));
|
|
67
74
|
if (!envBinary) {
|
|
68
75
|
return { executable, args };
|
|
69
76
|
}
|
|
70
77
|
return {
|
|
71
78
|
executable: envBinary,
|
|
72
|
-
args: ['-u',
|
|
79
|
+
args: [...variables.flatMap((name) => ['-u', name]), executable, ...args],
|
|
73
80
|
};
|
|
74
81
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { describe, expect, it } from 'vitest';
|
|
2
2
|
import {
|
|
3
3
|
clearAppImageArgv0FromProcessEnv,
|
|
4
|
-
|
|
4
|
+
resolvePosixPtyLaunch,
|
|
5
5
|
stripAppImageArgv0Leak,
|
|
6
6
|
} from './inherited-env.js';
|
|
7
7
|
|
|
@@ -9,7 +9,7 @@ describe('stripAppImageArgv0Leak', () => {
|
|
|
9
9
|
it('removes ARGV0 from a child env object', () => {
|
|
10
10
|
const env = {
|
|
11
11
|
PATH: '/usr/bin',
|
|
12
|
-
ARGV0: '/path/to/
|
|
12
|
+
ARGV0: '/path/to/AiWorker-1.17.2-linux-x86_64.AppImage',
|
|
13
13
|
SHELL: '/bin/zsh',
|
|
14
14
|
};
|
|
15
15
|
|
|
@@ -35,7 +35,7 @@ describe('stripAppImageArgv0Leak', () => {
|
|
|
35
35
|
describe('clearAppImageArgv0FromProcessEnv', () => {
|
|
36
36
|
it('removes ARGV0 from process.env', () => {
|
|
37
37
|
const previous = process.env.ARGV0;
|
|
38
|
-
process.env.ARGV0 = '/path/to/
|
|
38
|
+
process.env.ARGV0 = '/path/to/AiWorker.AppImage';
|
|
39
39
|
try {
|
|
40
40
|
clearAppImageArgv0FromProcessEnv();
|
|
41
41
|
expect(process.env.ARGV0).toBeUndefined();
|
|
@@ -46,18 +46,17 @@ describe('clearAppImageArgv0FromProcessEnv', () => {
|
|
|
46
46
|
});
|
|
47
47
|
});
|
|
48
48
|
|
|
49
|
-
describe('
|
|
50
|
-
it('wraps the shell with env -u
|
|
51
|
-
if (process.platform
|
|
52
|
-
expect(
|
|
49
|
+
describe('resolvePosixPtyLaunch', () => {
|
|
50
|
+
it('wraps the shell with env -u for every host-private variable on POSIX', () => {
|
|
51
|
+
if (process.platform === 'win32') return;
|
|
52
|
+
expect(resolvePosixPtyLaunch('/bin/zsh', ['-l'])).toEqual({
|
|
53
53
|
executable: expect.stringMatching(/\/env$/),
|
|
54
|
-
args: ['-u', 'ARGV0', '/bin/zsh', '-l'],
|
|
54
|
+
args: ['-u', 'ARGV0', '-u', 'NODE_CHANNEL_FD', '/bin/zsh', '-l'],
|
|
55
55
|
});
|
|
56
56
|
});
|
|
57
57
|
|
|
58
|
-
it('leaves
|
|
59
|
-
|
|
60
|
-
expect(resolveLinuxPtyLaunch('/bin/zsh', ['-l'])).toEqual({
|
|
58
|
+
it('leaves the launch unchanged with nothing to unset', () => {
|
|
59
|
+
expect(resolvePosixPtyLaunch('/bin/zsh', ['-l'], [])).toEqual({
|
|
61
60
|
executable: '/bin/zsh',
|
|
62
61
|
args: ['-l'],
|
|
63
62
|
});
|
|
@@ -5,17 +5,17 @@ import { isPlainObject, readEnv, readFiniteNumber, readTrimmedString } from './p
|
|
|
5
5
|
|
|
6
6
|
const DEFAULT_LINEAR_CLIENT_ID = '91bbe26a69a2c8568d3683f1e01e776c';
|
|
7
7
|
const DEFAULT_LINEAR_SCOPES = 'read,write,comments:create';
|
|
8
|
-
const DEFAULT_LINEAR_BROKER_URL = 'https://api.
|
|
8
|
+
const DEFAULT_LINEAR_BROKER_URL = 'https://api.aiworker.dev/v1/oauth/linear';
|
|
9
9
|
const ACCESS_TOKEN_REFRESH_SKEW_MS = 2 * 60_000;
|
|
10
10
|
const LEGACY_WORKSPACE_ID = 'legacy';
|
|
11
11
|
const SESSION_COMMENTS_SETTING_KEY = 'linearSessionComments';
|
|
12
12
|
|
|
13
13
|
function resolveDataDir() {
|
|
14
|
-
const fromEnv = readEnv('
|
|
14
|
+
const fromEnv = readEnv('AIWORKER_DATA_DIR');
|
|
15
15
|
if (fromEnv) {
|
|
16
16
|
return path.resolve(fromEnv);
|
|
17
17
|
}
|
|
18
|
-
return path.join(os.homedir(), '.config', '
|
|
18
|
+
return path.join(os.homedir(), '.config', 'aiworker');
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
function storageFile() {
|
|
@@ -377,7 +377,7 @@ export function toLinearPublicStatus(auth, workspaces = getLinearAuthWorkspaces(
|
|
|
377
377
|
}
|
|
378
378
|
|
|
379
379
|
export function getLinearClientId() {
|
|
380
|
-
const fromEnv = readEnv('
|
|
380
|
+
const fromEnv = readEnv('AIWORKER_LINEAR_CLIENT_ID');
|
|
381
381
|
if (fromEnv) return fromEnv;
|
|
382
382
|
const stored = readSettingString('linearClientId');
|
|
383
383
|
if (stored) return stored;
|
|
@@ -385,13 +385,13 @@ export function getLinearClientId() {
|
|
|
385
385
|
}
|
|
386
386
|
|
|
387
387
|
export function getLinearClientSecret() {
|
|
388
|
-
const fromEnv = readEnv('
|
|
388
|
+
const fromEnv = readEnv('AIWORKER_LINEAR_CLIENT_SECRET');
|
|
389
389
|
if (fromEnv) return fromEnv;
|
|
390
390
|
return readSettingString('linearClientSecret');
|
|
391
391
|
}
|
|
392
392
|
|
|
393
393
|
export function getLinearScopes() {
|
|
394
|
-
const fromEnv = readEnv('
|
|
394
|
+
const fromEnv = readEnv('AIWORKER_LINEAR_SCOPES');
|
|
395
395
|
if (fromEnv) return fromEnv;
|
|
396
396
|
const stored = readSettingString('linearScopes');
|
|
397
397
|
if (stored) return stored;
|
|
@@ -399,7 +399,7 @@ export function getLinearScopes() {
|
|
|
399
399
|
}
|
|
400
400
|
|
|
401
401
|
export function getLinearBrokerUrl() {
|
|
402
|
-
const fromEnv = readEnv('
|
|
402
|
+
const fromEnv = readEnv('AIWORKER_LINEAR_BROKER_URL');
|
|
403
403
|
if (fromEnv) return fromEnv.replace(/\/+$/, '');
|
|
404
404
|
const stored = readSettingString('linearBrokerUrl');
|
|
405
405
|
if (stored) return stored.replace(/\/+$/, '');
|
|
@@ -407,7 +407,7 @@ export function getLinearBrokerUrl() {
|
|
|
407
407
|
}
|
|
408
408
|
|
|
409
409
|
export function getLinearRedirectUri() {
|
|
410
|
-
const fromEnv = readEnv('
|
|
410
|
+
const fromEnv = readEnv('AIWORKER_LINEAR_REDIRECT_URI');
|
|
411
411
|
if (fromEnv) return fromEnv;
|
|
412
412
|
const stored = readSettingString('linearRedirectUri');
|
|
413
413
|
if (stored) return stored;
|
|
@@ -26,23 +26,23 @@ describe('Linear auth storage', () => {
|
|
|
26
26
|
let previousRedirect;
|
|
27
27
|
|
|
28
28
|
beforeEach(() => {
|
|
29
|
-
previousDataDir = process.env.
|
|
30
|
-
previousPort = process.env.
|
|
31
|
-
previousClientId = process.env.
|
|
32
|
-
previousRedirect = process.env.
|
|
29
|
+
previousDataDir = process.env.AIWORKER_DATA_DIR;
|
|
30
|
+
previousPort = process.env.AIWORKER_PORT;
|
|
31
|
+
previousClientId = process.env.AIWORKER_LINEAR_CLIENT_ID;
|
|
32
|
+
previousRedirect = process.env.AIWORKER_LINEAR_REDIRECT_URI;
|
|
33
33
|
dataDir = makeTempDir();
|
|
34
|
-
process.env.
|
|
35
|
-
delete process.env.
|
|
36
|
-
delete process.env.
|
|
37
|
-
delete process.env.
|
|
38
|
-
delete process.env.
|
|
34
|
+
process.env.AIWORKER_DATA_DIR = dataDir;
|
|
35
|
+
delete process.env.AIWORKER_LINEAR_CLIENT_ID;
|
|
36
|
+
delete process.env.AIWORKER_LINEAR_SCOPES;
|
|
37
|
+
delete process.env.AIWORKER_LINEAR_REDIRECT_URI;
|
|
38
|
+
delete process.env.AIWORKER_PORT;
|
|
39
39
|
});
|
|
40
40
|
|
|
41
41
|
afterEach(() => {
|
|
42
|
-
restoreEnv('
|
|
43
|
-
restoreEnv('
|
|
44
|
-
restoreEnv('
|
|
45
|
-
restoreEnv('
|
|
42
|
+
restoreEnv('AIWORKER_DATA_DIR', previousDataDir);
|
|
43
|
+
restoreEnv('AIWORKER_PORT', previousPort);
|
|
44
|
+
restoreEnv('AIWORKER_LINEAR_CLIENT_ID', previousClientId);
|
|
45
|
+
restoreEnv('AIWORKER_LINEAR_REDIRECT_URI', previousRedirect);
|
|
46
46
|
fs.rmSync(dataDir, { recursive: true, force: true });
|
|
47
47
|
});
|
|
48
48
|
|
|
@@ -58,7 +58,7 @@ describe('Linear auth storage', () => {
|
|
|
58
58
|
expiresAt: Date.now() + 60_000,
|
|
59
59
|
scope: 'read,write',
|
|
60
60
|
user: { id: 'user-1', name: 'Ada', displayName: 'Ada Lovelace', email: 'ada@example.com', avatarUrl: 'https://example.com/a.png' },
|
|
61
|
-
organization: { id: 'org-1', name: '
|
|
61
|
+
organization: { id: 'org-1', name: 'AiWorker', urlKey: 'aiworker' },
|
|
62
62
|
});
|
|
63
63
|
|
|
64
64
|
const stored = getLinearAuth();
|
|
@@ -75,12 +75,12 @@ describe('Linear auth storage', () => {
|
|
|
75
75
|
email: 'ada@example.com',
|
|
76
76
|
avatarUrl: 'https://example.com/a.png',
|
|
77
77
|
},
|
|
78
|
-
organization: { id: 'org-1', name: '
|
|
78
|
+
organization: { id: 'org-1', name: 'AiWorker', urlKey: 'aiworker' },
|
|
79
79
|
scope: 'read,write',
|
|
80
80
|
workspaces: [{
|
|
81
81
|
id: 'org-1',
|
|
82
|
-
name: '
|
|
83
|
-
urlKey: '
|
|
82
|
+
name: 'AiWorker',
|
|
83
|
+
urlKey: 'aiworker',
|
|
84
84
|
current: true,
|
|
85
85
|
user: {
|
|
86
86
|
id: 'user-1',
|
|
@@ -137,14 +137,14 @@ describe('Linear auth storage', () => {
|
|
|
137
137
|
|
|
138
138
|
it('uses the baked-in client id unless env or settings override it', () => {
|
|
139
139
|
expect(getLinearClientId()).toBe(DEFAULT_LINEAR_CLIENT_ID_VALUE);
|
|
140
|
-
process.env.
|
|
140
|
+
process.env.AIWORKER_LINEAR_CLIENT_ID = 'env-client';
|
|
141
141
|
expect(getLinearClientId()).toBe('env-client');
|
|
142
142
|
});
|
|
143
143
|
|
|
144
144
|
it('uses the stable public broker callback by default', () => {
|
|
145
|
-
process.env.
|
|
146
|
-
expect(getLinearRedirectUri()).toBe('https://api.
|
|
147
|
-
process.env.
|
|
145
|
+
process.env.AIWORKER_PORT = '3001';
|
|
146
|
+
expect(getLinearRedirectUri()).toBe('https://api.aiworker.dev/v1/oauth/linear/callback');
|
|
147
|
+
process.env.AIWORKER_LINEAR_REDIRECT_URI = 'http://localhost:3000/linear/oauth/callback';
|
|
148
148
|
expect(getLinearRedirectUri()).toBe('http://localhost:3000/linear/oauth/callback');
|
|
149
149
|
});
|
|
150
150
|
|
|
@@ -161,7 +161,7 @@ describe('Linear auth storage', () => {
|
|
|
161
161
|
accessToken: 'legacy-access',
|
|
162
162
|
refreshToken: 'legacy-refresh',
|
|
163
163
|
user: { id: 'user-1', name: 'Ada' },
|
|
164
|
-
organization: { id: 'org-1', name: '
|
|
164
|
+
organization: { id: 'org-1', name: 'AiWorker', urlKey: 'aiworker' },
|
|
165
165
|
}), 'utf8');
|
|
166
166
|
|
|
167
167
|
const stored = getLinearAuth();
|
|
@@ -216,7 +216,7 @@ describe('Linear auth storage', () => {
|
|
|
216
216
|
setLinearAuth({
|
|
217
217
|
accessToken: 'access-1',
|
|
218
218
|
user: { id: 'user-1', name: 'Ada' },
|
|
219
|
-
organization: { id: 'org-1', name: '
|
|
219
|
+
organization: { id: 'org-1', name: 'AiWorker', urlKey: 'aiworker' },
|
|
220
220
|
});
|
|
221
221
|
const file = JSON.parse(fs.readFileSync(getLinearAuthFilePath(), 'utf8'));
|
|
222
222
|
file.workspaces[0].authorizedAt = 111;
|
|
@@ -225,7 +225,7 @@ describe('Linear auth storage', () => {
|
|
|
225
225
|
setLinearAuth({
|
|
226
226
|
accessToken: 'access-1',
|
|
227
227
|
user: { id: 'user-1', name: 'Ada' },
|
|
228
|
-
organization: { id: 'org-1', name: '
|
|
228
|
+
organization: { id: 'org-1', name: 'AiWorker', urlKey: 'aiworker' },
|
|
229
229
|
workspaceId: 'org-1',
|
|
230
230
|
}, { activate: false });
|
|
231
231
|
expect(getLinearAuth().authorizedAt).toBe(111);
|
|
@@ -40,9 +40,9 @@ describe('Linear issue list/get', () => {
|
|
|
40
40
|
let previousDataDir;
|
|
41
41
|
|
|
42
42
|
beforeEach(() => {
|
|
43
|
-
previousDataDir = process.env.
|
|
43
|
+
previousDataDir = process.env.AIWORKER_DATA_DIR;
|
|
44
44
|
dataDir = makeTempDir();
|
|
45
|
-
process.env.
|
|
45
|
+
process.env.AIWORKER_DATA_DIR = dataDir;
|
|
46
46
|
setLinearAuth({
|
|
47
47
|
accessToken: 'access-1',
|
|
48
48
|
refreshToken: 'refresh-1',
|
|
@@ -56,9 +56,9 @@ describe('Linear issue list/get', () => {
|
|
|
56
56
|
vi.unstubAllGlobals();
|
|
57
57
|
clearLinearAuth();
|
|
58
58
|
if (previousDataDir === undefined) {
|
|
59
|
-
delete process.env.
|
|
59
|
+
delete process.env.AIWORKER_DATA_DIR;
|
|
60
60
|
} else {
|
|
61
|
-
process.env.
|
|
61
|
+
process.env.AIWORKER_DATA_DIR = previousDataDir;
|
|
62
62
|
}
|
|
63
63
|
fs.rmSync(dataDir, { recursive: true, force: true });
|
|
64
64
|
});
|
|
@@ -336,7 +336,7 @@ describe('Linear issue list/get', () => {
|
|
|
336
336
|
expect(body.query).toContain('mutation CommentCreate');
|
|
337
337
|
expect(body.variables.input).toEqual({
|
|
338
338
|
issueId: 'issue-uuid-1',
|
|
339
|
-
body: '
|
|
339
|
+
body: 'AiWorker session started.',
|
|
340
340
|
});
|
|
341
341
|
expect(options.headers.Authorization).toBe('Bearer access-1');
|
|
342
342
|
return jsonResponse({
|
|
@@ -351,7 +351,7 @@ describe('Linear issue list/get', () => {
|
|
|
351
351
|
|
|
352
352
|
const result = await createLinearIssueComment({
|
|
353
353
|
issueId: 'ENG-12',
|
|
354
|
-
body: '
|
|
354
|
+
body: 'AiWorker session started.',
|
|
355
355
|
});
|
|
356
356
|
expect(result).toEqual({ connected: true, comment: { id: 'comment-9' } });
|
|
357
357
|
expect(JSON.stringify(result)).not.toContain('access-1');
|
|
@@ -18,16 +18,16 @@ describe('Linear project mapping storage', () => {
|
|
|
18
18
|
let previousDataDir;
|
|
19
19
|
|
|
20
20
|
beforeEach(() => {
|
|
21
|
-
previousDataDir = process.env.
|
|
21
|
+
previousDataDir = process.env.AIWORKER_DATA_DIR;
|
|
22
22
|
dataDir = makeTempDir();
|
|
23
|
-
process.env.
|
|
23
|
+
process.env.AIWORKER_DATA_DIR = dataDir;
|
|
24
24
|
});
|
|
25
25
|
|
|
26
26
|
afterEach(() => {
|
|
27
27
|
if (previousDataDir === undefined) {
|
|
28
|
-
delete process.env.
|
|
28
|
+
delete process.env.AIWORKER_DATA_DIR;
|
|
29
29
|
} else {
|
|
30
|
-
process.env.
|
|
30
|
+
process.env.AIWORKER_DATA_DIR = previousDataDir;
|
|
31
31
|
}
|
|
32
32
|
fs.rmSync(dataDir, { recursive: true, force: true });
|
|
33
33
|
});
|
|
@@ -141,7 +141,7 @@ export async function startAuthorization({ origin } = {}) {
|
|
|
141
141
|
const clientId = getLinearClientId();
|
|
142
142
|
if (!clientId) {
|
|
143
143
|
throw new LinearOAuthError(
|
|
144
|
-
'Linear OAuth client not configured. Set
|
|
144
|
+
'Linear OAuth client not configured. Set AIWORKER_LINEAR_CLIENT_ID.',
|
|
145
145
|
'LINEAR_CLIENT_ID_MISSING',
|
|
146
146
|
);
|
|
147
147
|
}
|
|
@@ -269,7 +269,7 @@ export async function consumeAuthorizationCallback({ code, state, error, errorDe
|
|
|
269
269
|
}
|
|
270
270
|
if (!pending?.codeVerifier) {
|
|
271
271
|
throw failAuthorization(
|
|
272
|
-
'This authorization session has expired or is unknown to the running app. Return to
|
|
272
|
+
'This authorization session has expired or is unknown to the running app. Return to AiWorker and click Connect again.',
|
|
273
273
|
'UNKNOWN_STATE',
|
|
274
274
|
);
|
|
275
275
|
}
|
|
@@ -20,23 +20,23 @@ describe('Linear OAuth PKCE', () => {
|
|
|
20
20
|
let previousRedirect;
|
|
21
21
|
|
|
22
22
|
beforeEach(() => {
|
|
23
|
-
previousDataDir = process.env.
|
|
24
|
-
previousPort = process.env.
|
|
25
|
-
previousRedirect = process.env.
|
|
23
|
+
previousDataDir = process.env.AIWORKER_DATA_DIR;
|
|
24
|
+
previousPort = process.env.AIWORKER_PORT;
|
|
25
|
+
previousRedirect = process.env.AIWORKER_LINEAR_REDIRECT_URI;
|
|
26
26
|
dataDir = makeTempDir();
|
|
27
|
-
process.env.
|
|
28
|
-
process.env.
|
|
29
|
-
delete process.env.
|
|
30
|
-
process.env.
|
|
27
|
+
process.env.AIWORKER_DATA_DIR = dataDir;
|
|
28
|
+
process.env.AIWORKER_PORT = '3001';
|
|
29
|
+
delete process.env.AIWORKER_LINEAR_CLIENT_ID;
|
|
30
|
+
process.env.AIWORKER_LINEAR_REDIRECT_URI = 'http://127.0.0.1:3001/linear/oauth/callback';
|
|
31
31
|
clearPendingAuthorizationsForTests();
|
|
32
32
|
});
|
|
33
33
|
|
|
34
34
|
afterEach(() => {
|
|
35
35
|
vi.unstubAllGlobals();
|
|
36
36
|
clearPendingAuthorizationsForTests();
|
|
37
|
-
restoreEnv('
|
|
38
|
-
restoreEnv('
|
|
39
|
-
restoreEnv('
|
|
37
|
+
restoreEnv('AIWORKER_DATA_DIR', previousDataDir);
|
|
38
|
+
restoreEnv('AIWORKER_PORT', previousPort);
|
|
39
|
+
restoreEnv('AIWORKER_LINEAR_REDIRECT_URI', previousRedirect);
|
|
40
40
|
fs.rmSync(dataDir, { recursive: true, force: true });
|
|
41
41
|
});
|
|
42
42
|
|
|
@@ -113,7 +113,7 @@ describe('Linear OAuth PKCE', () => {
|
|
|
113
113
|
});
|
|
114
114
|
|
|
115
115
|
it('claims a broker callback and exchanges it locally with PKCE', async () => {
|
|
116
|
-
delete process.env.
|
|
116
|
+
delete process.env.AIWORKER_LINEAR_REDIRECT_URI;
|
|
117
117
|
const brokerAndTokenFetch = vi.fn(async (url, init) => {
|
|
118
118
|
const target = String(url);
|
|
119
119
|
if (target.endsWith('/start')) {
|
|
@@ -121,7 +121,7 @@ describe('Linear OAuth PKCE', () => {
|
|
|
121
121
|
expect(body.state).toMatch(/^[A-Za-z0-9_-]{43}$/);
|
|
122
122
|
expect(body.claimSecret).toMatch(/^[A-Za-z0-9_-]{43}$/);
|
|
123
123
|
return new Response(JSON.stringify({
|
|
124
|
-
redirectUri: 'https://api.
|
|
124
|
+
redirectUri: 'https://api.aiworker.dev/v1/oauth/linear/callback',
|
|
125
125
|
expiresIn: 600,
|
|
126
126
|
}), { status: 200 });
|
|
127
127
|
}
|
|
@@ -134,7 +134,7 @@ describe('Linear OAuth PKCE', () => {
|
|
|
134
134
|
if (target === 'https://api.linear.app/oauth/token') {
|
|
135
135
|
const body = new URLSearchParams(init.body);
|
|
136
136
|
expect(body.get('code')).toBe('broker-code');
|
|
137
|
-
expect(body.get('redirect_uri')).toBe('https://api.
|
|
137
|
+
expect(body.get('redirect_uri')).toBe('https://api.aiworker.dev/v1/oauth/linear/callback');
|
|
138
138
|
expect(body.get('code_verifier')).toMatch(/^[A-Za-z0-9_-]{43}$/);
|
|
139
139
|
return new Response(JSON.stringify({
|
|
140
140
|
access_token: 'broker-access',
|
|
@@ -148,7 +148,7 @@ describe('Linear OAuth PKCE', () => {
|
|
|
148
148
|
|
|
149
149
|
const started = await startAuthorization({ origin: 'desktop' });
|
|
150
150
|
const authorizationUrl = new URL(started.authorizationUrl);
|
|
151
|
-
expect(authorizationUrl.searchParams.get('redirect_uri')).toBe('https://api.
|
|
151
|
+
expect(authorizationUrl.searchParams.get('redirect_uri')).toBe('https://api.aiworker.dev/v1/oauth/linear/callback');
|
|
152
152
|
|
|
153
153
|
const result = await pollAuthorizationBroker();
|
|
154
154
|
expect(result).toMatchObject({ accessToken: 'broker-access', origin: 'desktop' });
|
|
@@ -29,7 +29,7 @@ function renderLinearOAuthCallbackPage({ title, message, desktopReturn }) {
|
|
|
29
29
|
<head>
|
|
30
30
|
<meta charset="utf-8">
|
|
31
31
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
32
|
-
<title>${escapeHtml(title)} —
|
|
32
|
+
<title>${escapeHtml(title)} — AiWorker</title>
|
|
33
33
|
<style>
|
|
34
34
|
:root { color-scheme: light dark; }
|
|
35
35
|
body { margin: 0; min-height: 100vh; display: flex; align-items: center; justify-content: center;
|
|
@@ -46,8 +46,8 @@ function renderLinearOAuthCallbackPage({ title, message, desktopReturn }) {
|
|
|
46
46
|
<main>
|
|
47
47
|
<h1>${escapeHtml(title)}</h1>
|
|
48
48
|
<p>${escapeHtml(message)}</p>
|
|
49
|
-
${desktopReturn ? `<a class="return" href="
|
|
50
|
-
<script>window.location.href = '
|
|
49
|
+
${desktopReturn ? `<a class="return" href="aiworker://focus/linear-auth">Return to AiWorker</a>
|
|
50
|
+
<script>window.location.href = 'aiworker://focus/linear-auth';</script>` : ''}
|
|
51
51
|
</main>
|
|
52
52
|
</body>
|
|
53
53
|
</html>`;
|
|
@@ -103,7 +103,7 @@ export function registerLinearRoutes(app) {
|
|
|
103
103
|
|
|
104
104
|
return finish(200, {
|
|
105
105
|
title: 'Authorization Complete',
|
|
106
|
-
message: 'You can close this tab and return to
|
|
106
|
+
message: 'You can close this tab and return to AiWorker.',
|
|
107
107
|
desktopReturn: result.origin === 'desktop',
|
|
108
108
|
});
|
|
109
109
|
} catch (error) {
|
|
@@ -113,7 +113,7 @@ export function registerLinearRoutes(app) {
|
|
|
113
113
|
: 502;
|
|
114
114
|
return finish(status, {
|
|
115
115
|
title: 'Authorization Failed',
|
|
116
|
-
message: error instanceof Error ? error.message : 'Linear authorization failed. Return to
|
|
116
|
+
message: error instanceof Error ? error.message : 'Linear authorization failed. Return to AiWorker and click Connect again.',
|
|
117
117
|
desktopReturn: error?.origin === 'desktop',
|
|
118
118
|
});
|
|
119
119
|
}
|
|
@@ -25,23 +25,23 @@ describe('Linear auth routes', () => {
|
|
|
25
25
|
let previousDataDir;
|
|
26
26
|
|
|
27
27
|
beforeEach(() => {
|
|
28
|
-
previousDataDir = process.env.
|
|
28
|
+
previousDataDir = process.env.AIWORKER_DATA_DIR;
|
|
29
29
|
dataDir = makeTempDir();
|
|
30
|
-
process.env.
|
|
31
|
-
process.env.
|
|
32
|
-
process.env.
|
|
33
|
-
delete process.env.
|
|
30
|
+
process.env.AIWORKER_DATA_DIR = dataDir;
|
|
31
|
+
process.env.AIWORKER_PORT = '3001';
|
|
32
|
+
process.env.AIWORKER_LINEAR_REDIRECT_URI = 'http://127.0.0.1:3001/linear/oauth/callback';
|
|
33
|
+
delete process.env.AIWORKER_LINEAR_CLIENT_ID;
|
|
34
34
|
});
|
|
35
35
|
|
|
36
36
|
afterEach(() => {
|
|
37
37
|
vi.unstubAllGlobals();
|
|
38
38
|
if (previousDataDir === undefined) {
|
|
39
|
-
delete process.env.
|
|
39
|
+
delete process.env.AIWORKER_DATA_DIR;
|
|
40
40
|
} else {
|
|
41
|
-
process.env.
|
|
41
|
+
process.env.AIWORKER_DATA_DIR = previousDataDir;
|
|
42
42
|
}
|
|
43
|
-
delete process.env.
|
|
44
|
-
delete process.env.
|
|
43
|
+
delete process.env.AIWORKER_PORT;
|
|
44
|
+
delete process.env.AIWORKER_LINEAR_REDIRECT_URI;
|
|
45
45
|
fs.rmSync(dataDir, { recursive: true, force: true });
|
|
46
46
|
});
|
|
47
47
|
|
|
@@ -76,7 +76,7 @@ describe('Linear auth routes', () => {
|
|
|
76
76
|
email: 'ada@example.com',
|
|
77
77
|
avatarUrl: 'https://example.com/a.png',
|
|
78
78
|
},
|
|
79
|
-
organization: { id: 'org-1', name: '
|
|
79
|
+
organization: { id: 'org-1', name: 'AiWorker', urlKey: 'aiworker' },
|
|
80
80
|
},
|
|
81
81
|
});
|
|
82
82
|
}
|
|
@@ -89,7 +89,7 @@ describe('Linear auth routes', () => {
|
|
|
89
89
|
.expect(200);
|
|
90
90
|
|
|
91
91
|
expect(callback.text).toContain('Authorization Complete');
|
|
92
|
-
expect(callback.text).toContain('
|
|
92
|
+
expect(callback.text).toContain('aiworker://focus/linear-auth');
|
|
93
93
|
|
|
94
94
|
const status = await request(app).get('/api/linear/auth/status').expect(200);
|
|
95
95
|
expect(status.body.connected).toBe(true);
|
|
@@ -100,12 +100,12 @@ describe('Linear auth routes', () => {
|
|
|
100
100
|
email: 'ada@example.com',
|
|
101
101
|
avatarUrl: 'https://example.com/a.png',
|
|
102
102
|
});
|
|
103
|
-
expect(status.body.organization).toEqual({ id: 'org-1', name: '
|
|
103
|
+
expect(status.body.organization).toEqual({ id: 'org-1', name: 'AiWorker', urlKey: 'aiworker' });
|
|
104
104
|
expect(status.body.scope).toBe('read,write,comments:create');
|
|
105
105
|
expect(status.body.workspaces).toEqual([{
|
|
106
106
|
id: 'org-1',
|
|
107
|
-
name: '
|
|
108
|
-
urlKey: '
|
|
107
|
+
name: 'AiWorker',
|
|
108
|
+
urlKey: 'aiworker',
|
|
109
109
|
current: true,
|
|
110
110
|
user: {
|
|
111
111
|
id: 'user-1',
|
|
@@ -133,7 +133,7 @@ describe('Linear auth routes', () => {
|
|
|
133
133
|
.expect(400);
|
|
134
134
|
expect(tokenFetch).not.toHaveBeenCalled();
|
|
135
135
|
expect(response.text).toContain('Authorization Failed');
|
|
136
|
-
expect(response.text).not.toContain('
|
|
136
|
+
expect(response.text).not.toContain('aiworker://');
|
|
137
137
|
});
|
|
138
138
|
|
|
139
139
|
it('omits the desktop deep link for flows started outside the desktop shell', async () => {
|
|
@@ -162,7 +162,7 @@ describe('Linear auth routes', () => {
|
|
|
162
162
|
.get('/linear/oauth/callback')
|
|
163
163
|
.query({ state, code: 'auth-code' })
|
|
164
164
|
.expect(200);
|
|
165
|
-
expect(response.text).not.toContain('
|
|
165
|
+
expect(response.text).not.toContain('aiworker://');
|
|
166
166
|
});
|
|
167
167
|
|
|
168
168
|
it('disconnects and revokes the refresh token', async () => {
|