@vantran-se/openchamber-web 1.23.0 → 1.24.3
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/bin/cli.test.js +29 -6
- package/bin/lib/cli-http.js +5 -1
- package/bin/lib/commands-status.js +5 -0
- package/dist/assets/{CodeMirrorCommentWidgets-DFg2wnpo.js → CodeMirrorCommentWidgets-BjJHrzmU.js} +1 -1
- package/dist/assets/DiffView-COVQhWGd.js +4 -0
- package/dist/assets/FilesView-B1V5JxFX.js +13 -0
- package/dist/assets/GitView-CDOJy5Ay.js +6 -0
- package/dist/assets/GuestAttachDialog-D3S0Rjic.js +1 -0
- package/dist/assets/{JsonTreeView-BKdsjg5B.js → JsonTreeView-D0C9nU7K.js} +1 -1
- package/dist/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
- package/dist/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
- package/dist/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
- package/dist/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
- package/dist/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
- package/dist/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
- package/dist/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
- package/dist/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
- package/dist/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
- package/dist/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
- package/dist/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
- package/dist/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
- package/dist/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
- package/dist/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
- package/dist/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
- package/dist/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
- package/dist/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
- package/dist/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
- package/dist/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
- package/dist/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
- package/dist/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
- package/dist/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
- package/dist/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
- package/dist/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
- package/dist/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
- package/dist/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
- package/dist/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
- package/dist/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
- package/dist/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
- package/dist/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
- package/dist/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
- package/dist/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
- package/dist/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
- package/dist/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
- package/dist/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
- package/dist/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
- package/dist/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
- package/dist/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
- package/dist/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
- package/dist/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
- package/dist/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
- package/dist/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
- package/dist/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
- package/dist/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
- package/dist/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
- package/dist/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
- package/dist/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
- package/dist/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
- package/dist/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
- package/dist/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
- package/dist/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
- package/dist/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
- package/dist/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
- package/dist/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
- package/dist/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
- package/dist/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
- package/dist/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
- package/dist/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
- package/dist/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
- package/dist/assets/LinearIssuesView-D7FKg1XJ.js +1 -0
- package/dist/assets/{MarkdownImageGallery-_5gEVr0X.js → MarkdownImageGallery-BrFjAVEf.js} +1 -1
- package/dist/assets/MarkdownRendererImpl-DWepTafh.js +12 -0
- package/dist/assets/{OnboardingScreen-DdP4_nuc.js → OnboardingScreen-Dyxxiqdt.js} +1 -1
- package/dist/assets/{PatchDiff-am3SAss2.js → PatchDiff-DnEhjXcC.js} +1 -1
- package/dist/assets/PierreDiffViewer-DyxZVVVR.js +210 -0
- package/dist/assets/{PlanView-BoJxdRZe.js → PlanView-LW2z_EAP.js} +4 -4
- package/dist/assets/PluginPane-B4tKno2h.js +3 -0
- package/dist/assets/SettingsView-DEaMulN9.js +29 -0
- package/dist/assets/{SettingsWindow-DVTdDSol.js → SettingsWindow-FLDJXOgQ.js} +1 -1
- package/dist/assets/SubmoduleDiffSummary-CvVwD-Vi.js +1 -0
- package/dist/assets/ToolOutputDialog-BiP0x2Rw.js +15 -0
- package/dist/assets/{ToolPartDiffPreview-C7WLk5i9.js → ToolPartDiffPreview-CkR4msKP.js} +2 -2
- package/dist/assets/{VirtualizedFileDiff-DcdgkH-x.js → VirtualizedFileDiff-0pyr_mHY.js} +4 -4
- package/dist/assets/WalkthroughView-yNj4nOP5.js +4 -0
- package/dist/assets/appThemeRegistry-BuUKhbYQ.js +1 -0
- package/dist/assets/commitAndPush-DvJKa3Ks.js +1 -0
- package/dist/assets/{computeVirtualFileMetrics-C8byMnRh.js → computeVirtualFileMetrics-DxTBMuu-.js} +2 -2
- package/dist/assets/de-DgxgFyGG.js +10 -0
- package/dist/assets/es-BFsZj5F_.js +16 -0
- package/dist/assets/fr-jdZ5KKQi.js +14 -0
- package/dist/assets/{index-BB7ryz8y.js → index-CKHjPKbq.js} +1 -1
- package/dist/assets/index-Cbci4i1W.js +40 -0
- package/dist/assets/index-DqaMWNrC.css +1 -0
- package/dist/assets/{isDiffPlainText-45ujMPGb.js → isDiffPlainText-D7FkBMP6.js} +1 -1
- package/dist/assets/{isFilePlainText-Cc4KFSYi.js → isFilePlainText-CL2vsrIZ.js} +1 -1
- package/dist/assets/ja-C5kKrhO4.js +16 -0
- package/dist/assets/ko-DXDTT_0O.js +16 -0
- package/dist/assets/main-CZALtVek.js +896 -0
- package/dist/assets/main-CgXMBNvG.js +2 -0
- package/dist/assets/{markdown-shiki.worker-D5fBU-lw.js → markdown-shiki.worker-CahLvHIq.js} +5 -5
- package/dist/assets/markdownCore-Dh7WEsdM.js +5 -0
- package/dist/assets/miniChat-CwTmDixi.js +2 -0
- package/dist/assets/mobile-CLf2vCtO.js +2 -0
- package/dist/assets/patchFileDiff-Bsba8KFp.js +13 -0
- package/dist/assets/pl-D-7x4Y8Q.js +16 -0
- package/dist/assets/pt-BR-CSBZrHa8.js +16 -0
- package/dist/assets/renderElectronMiniChatApp-C5gAFBk0.js +2 -0
- package/dist/assets/renderMobileApp-V4hYd32H.js +25 -0
- package/dist/assets/runtimeEndpointReset-DhlHCn-2.js +25 -0
- package/dist/assets/scheduledTasksApi-DzjbLd8P.js +1 -0
- package/dist/assets/shikiHighlight-8_3csmr6.js +1 -0
- package/dist/assets/surface-B6n7wJtt.js +1 -0
- package/dist/assets/textMateThemeFromAppTheme-CHo2fCgW.js +1 -0
- package/dist/assets/tr-Dr-oJ22L.js +7 -0
- package/dist/assets/uk-9Nx83UcI.js +16 -0
- package/dist/assets/useAppFontEffects-khZXpFL_.js +7333 -0
- package/dist/assets/useInlineCommentController-DkQ_gqpn.js +2 -0
- package/dist/assets/useRootScrollLock-DdvHf9Pt.js +2 -0
- package/dist/assets/{vendor-base-ui-DdV8vhHn.js → vendor-base-ui-CsXYnR5c.js} +1 -1
- package/dist/assets/{vendor-codemirror-language-data-DzlSIu_W.js → vendor-codemirror-language-data-CdzUmUyZ.js} +2 -2
- package/dist/assets/vendor-framer-motion-Bq3iTZ6r.js +1 -0
- package/dist/assets/vendor-katex-Cp579UoJ.css +1 -0
- package/dist/assets/{vendor-motion-dom-D_o3BTI3.js → vendor-motion-dom-DcCgeG69.js} +1 -1
- package/dist/assets/{vendor-remixicon-react-Dil0zKKT.js → vendor-remixicon-react-BDmGmFCA.js} +1 -1
- package/dist/assets/vendor-strip-json-comments-5dJlOkP1.js +4 -0
- package/dist/assets/{vendor-tanstack-react-virtual-g05Cx3z9.js → vendor-tanstack-react-virtual-ClYN8CzB.js} +1 -1
- package/dist/assets/{vendor-tanstack-virtual-core-Dubg10g5.js → vendor-tanstack-virtual-core-BewVQryB.js} +1 -1
- package/dist/assets/vendor-zod-CgAdXWZO.js +39 -0
- package/dist/assets/{web-components-CdGfR2XJ.js → web-components-B8IcVQAA.js} +2 -2
- package/dist/assets/zh-CN-Bxy_Hj3r.js +16 -0
- package/dist/assets/zh-TW-0BB4gpHM.js +16 -0
- package/dist/index.html +6 -4
- package/dist/mini-chat.html +6 -4
- package/dist/mobile.html +6 -4
- package/package.json +12 -9
- package/server/built-in-extensions/registry.json +4 -0
- package/server/index.d.ts +2 -0
- package/server/index.js +47 -23
- package/server/lib/agent-memory/runtime.js +7 -2
- package/server/lib/agent-memory/runtime.test.js +22 -0
- package/server/lib/agent-tool/DOCUMENTATION.md +17 -4
- package/server/lib/agent-tool/runtime.js +62 -15
- package/server/lib/agent-tool/runtime.test.js +88 -2
- package/server/lib/changelog/update-notes.js +2 -1
- package/server/lib/changelog/update-notes.test.js +19 -0
- package/server/lib/event-stream/DOCUMENTATION.md +26 -0
- package/server/lib/event-stream/delta-coalescer.js +0 -0
- package/server/lib/event-stream/delta-coalescer.test.js +292 -0
- package/server/lib/event-stream/global-hub.js +68 -13
- package/server/lib/event-stream/global-hub.test.js +182 -0
- package/server/lib/event-stream/global-ws-bridge.js +16 -18
- package/server/lib/event-stream/index.js +4 -0
- package/server/lib/event-stream/protocol.js +21 -7
- package/server/lib/event-stream/runtime.js +9 -6
- package/server/lib/event-stream/runtime.test.js +60 -0
- package/server/lib/fs/DOCUMENTATION.md +10 -1
- package/server/lib/fs/git-process.test.js +77 -0
- package/server/lib/fs/routes.js +58 -5
- package/server/lib/fs/routes.test.js +116 -0
- package/server/lib/fs/search.js +2 -1
- package/server/lib/git/DOCUMENTATION.md +30 -6
- package/server/lib/git/routes.js +37 -11
- package/server/lib/git/routes.test.js +78 -0
- package/server/lib/git/serial-refresh.js +93 -0
- package/server/lib/git/serial-refresh.test.js +112 -0
- package/server/lib/git/service.js +588 -74
- package/server/lib/git/service.test.js +492 -0
- package/server/lib/github/DOCUMENTATION.md +5 -0
- package/server/lib/github/pr-status.js +5 -5
- package/server/lib/github/pr-status.test.js +1 -1
- package/server/lib/github/routes.js +6 -6
- package/server/lib/guests/DOCUMENTATION.md +68 -0
- package/server/lib/guests/auth-store.js +184 -0
- package/server/lib/guests/auth-store.test.js +112 -0
- package/server/lib/guests/background.test.js +83 -0
- package/server/lib/guests/builtins.js +34 -0
- package/server/lib/guests/builtins.test.js +174 -0
- package/server/lib/guests/catalog.js +477 -0
- package/server/lib/guests/catalog.test.js +390 -0
- package/server/lib/guests/clone.js +297 -0
- package/server/lib/guests/extract-zip.js +136 -0
- package/server/lib/guests/extract-zip.test.js +109 -0
- package/server/lib/guests/files.js +308 -0
- package/server/lib/guests/files.test.js +262 -0
- package/server/lib/guests/grant-scope.js +81 -0
- package/server/lib/guests/grant-scope.test.js +75 -0
- package/server/lib/guests/host-session.js +73 -0
- package/server/lib/guests/host-session.test.js +30 -0
- package/server/lib/guests/html-styles.js +6 -0
- package/server/lib/guests/html-styles.test.js +45 -0
- package/server/lib/guests/html-tokens.js +73 -0
- package/server/lib/guests/html-tokens.test.js +53 -0
- package/server/lib/guests/install.js +406 -0
- package/server/lib/guests/install.test.js +338 -0
- package/server/lib/guests/oauth.js +501 -0
- package/server/lib/guests/oauth.test.js +481 -0
- package/server/lib/guests/persist.js +336 -0
- package/server/lib/guests/persist.test.js +288 -0
- package/server/lib/guests/request.js +112 -0
- package/server/lib/guests/request.test.js +206 -0
- package/server/lib/guests/routes.js +838 -0
- package/server/lib/guests/service.js +538 -0
- package/server/lib/guests/service.test.js +277 -0
- package/server/lib/guests/sockets.js +129 -0
- package/server/lib/guests/sockets.test.js +110 -0
- package/server/lib/guests/ssh-install.test.js +188 -0
- package/server/lib/guests/storage.js +68 -0
- package/server/lib/guests/storage.test.js +59 -0
- package/server/lib/guests/updates.js +294 -0
- package/server/lib/guests/updates.test.js +334 -0
- package/server/lib/guests/upload.js +50 -0
- package/server/lib/guests/upload.test.js +131 -0
- package/server/lib/linear/DOCUMENTATION.md +1 -1
- package/server/lib/message-queue/DOCUMENTATION.md +17 -1
- package/server/lib/message-queue/runtime.js +34 -1
- package/server/lib/message-queue/runtime.test.js +83 -6
- package/server/lib/notifications/DOCUMENTATION.md +1 -1
- package/server/lib/notifications/emitter-runtime.js +4 -3
- package/server/lib/notifications/routes.js +5 -0
- package/server/lib/openchamber-control/DOCUMENTATION.md +6 -0
- package/server/lib/openchamber-sessions/routes.js +62 -29
- package/server/lib/openchamber-sessions/routes.test.js +96 -0
- package/server/lib/opencode/DOCUMENTATION.md +73 -5
- package/server/lib/opencode/bootstrap-runtime.js +1 -0
- package/server/lib/opencode/core-routes.js +39 -1
- package/server/lib/opencode/env-runtime.js +5 -1
- package/server/lib/opencode/env-runtime.test.js +72 -0
- package/server/lib/opencode/feature-routes-runtime.js +30 -1
- package/server/lib/opencode/lifecycle-process.test.js +84 -0
- package/server/lib/opencode/lifecycle.js +58 -70
- package/server/lib/opencode/lifecycle.test.js +29 -0
- package/server/lib/opencode/managed-plugin-config.js +1 -1
- package/server/lib/opencode/openchamber-routes.js +72 -14
- package/server/lib/opencode/openchamber-routes.test.js +71 -3
- package/server/lib/opencode/proxy.js +33 -0
- package/server/lib/opencode/session-runtime.js +68 -0
- package/server/lib/opencode/session-runtime.test.js +43 -0
- package/server/lib/opencode/settings-helpers.js +11 -0
- package/server/lib/opencode/settings-helpers.test.js +24 -2
- package/server/lib/opencode/settings-normalization-runtime.js +2 -0
- package/server/lib/opencode/settings-normalization-runtime.test.js +13 -0
- package/server/lib/opencode/settings-registry.json +18 -0
- package/server/lib/opencode/settings-runtime.js +36 -9
- package/server/lib/opencode/settings-runtime.test.js +158 -2
- package/server/lib/opencode/shutdown-runtime.js +3 -0
- package/server/lib/opencode/shutdown-runtime.test.js +24 -0
- package/server/lib/opencode/theme-archive.js +53 -0
- package/server/lib/opencode/theme-catalog.js +171 -0
- package/server/lib/opencode/theme-catalog.test.js +125 -0
- package/server/lib/opencode/theme-import.test.js +144 -0
- package/server/lib/opencode/theme-runtime.js +100 -28
- package/server/lib/opencode/theme-runtime.test.js +15 -0
- package/server/lib/permission-auto-accept/DOCUMENTATION.md +8 -0
- package/server/lib/permission-auto-accept/runtime.js +13 -0
- package/server/lib/permission-auto-accept/runtime.test.js +37 -1
- package/server/lib/project-context/DOCUMENTATION.md +13 -3
- package/server/lib/project-context/runtime.js +8 -2
- package/server/lib/project-context/runtime.test.js +54 -0
- package/server/lib/projects/DOCUMENTATION.md +2 -1
- package/server/lib/projects/project-config.js +40 -11
- package/server/lib/projects/project-config.test.js +97 -0
- package/server/lib/projects/project-id.js +26 -0
- package/server/lib/quota/DOCUMENTATION.md +0 -1
- package/server/lib/quota/providers/index.js +0 -7
- package/server/lib/realtime-proxy-terminal.test.js +150 -0
- package/server/lib/realtime-proxy.js +2 -0
- package/server/lib/relay/DOCUMENTATION.md +20 -0
- package/server/lib/relay/host-client.js +7 -0
- package/server/lib/relay/host-client.test.js +14 -0
- package/server/lib/routing/DOCUMENTATION.md +83 -0
- package/server/lib/routing/defaults.js +98 -0
- package/server/lib/routing/feature-flag.js +11 -0
- package/server/lib/routing/history.js +34 -0
- package/server/lib/routing/jev.js +98 -0
- package/server/lib/routing/routes.http.test.js +100 -0
- package/server/lib/routing/routes.js +81 -0
- package/server/lib/routing/runtime.js +217 -0
- package/server/lib/routing/runtime.test.js +188 -0
- package/server/lib/routing/store.js +249 -0
- package/server/lib/routing/store.test.js +96 -0
- package/server/lib/scheduled-tasks/DOCUMENTATION.md +9 -1
- package/server/lib/scheduled-tasks/issue-2710-double-execution.test.js +28 -0
- package/server/lib/scheduled-tasks/runtime.js +14 -4
- package/server/lib/scheduled-tasks/runtime.test.js +67 -0
- package/server/lib/security/request-security.js +9 -5
- package/server/lib/security/request-security.test.js +37 -0
- package/server/lib/session-assist/DOCUMENTATION.md +131 -66
- package/server/lib/session-assist/context.js +127 -0
- package/server/lib/session-assist/context.test.js +132 -0
- package/server/lib/session-assist/prompt.js +54 -0
- package/server/lib/session-assist/runtime.js +111 -257
- package/server/lib/session-assist/runtime.test.js +203 -0
- package/server/lib/small-model/DOCUMENTATION.md +14 -2
- package/server/lib/small-model/call.js +37 -6
- package/server/lib/small-model/call.test.js +182 -0
- package/server/lib/terminal/DOCUMENTATION.md +23 -2
- package/server/lib/terminal/runtime.js +27 -5
- package/server/lib/terminal/runtime.test.js +67 -0
- package/server/lib/terminal/shutdown.js +106 -0
- package/server/lib/terminal/shutdown.test.js +84 -0
- package/server/lib/tts/service.test.js +78 -0
- package/server/lib/ui-auth/DOCUMENTATION.md +8 -0
- package/server/lib/ui-auth/session-cookie.js +51 -0
- package/server/lib/ui-auth/session-cookie.test.js +46 -0
- package/server/lib/ui-auth/ui-auth.js +56 -17
- package/server/lib/ui-auth/ui-auth.test.js +96 -0
- package/server/lib/walkthrough/DOCUMENTATION.md +15 -5
- package/server/lib/walkthrough/pr-source.test.js +21 -0
- package/server/lib/walkthrough/pull-request.js +7 -4
- package/server/lib/walkthrough/pull-request.test.js +16 -0
- package/server/lib/walkthrough/routes.js +19 -0
- package/server/lib/walkthrough/routes.test.js +26 -0
- package/server/lib/walkthrough/sources.js +13 -2
- package/server/opencode-worktree-readiness.test.js +130 -0
- package/dist/assets/DiffView-3Dn4QHbu.js +0 -4
- package/dist/assets/DirtyBranchSwitchDialog-CwOerqVi.js +0 -1
- package/dist/assets/FilesView-BdTOpew9.js +0 -17
- package/dist/assets/GitView-Dqf9vHJh.js +0 -6
- package/dist/assets/LinearIssuesView-CmbeL7I6.js +0 -1
- package/dist/assets/MarkdownRendererImpl-wVZlx4dd.js +0 -12
- package/dist/assets/PierreDiffViewer-DCsydlKs.js +0 -161
- package/dist/assets/SettingsView-CcM8pF5O.js +0 -28
- package/dist/assets/ToolOutputDialog-BgfTbDZ4.js +0 -15
- package/dist/assets/WalkthroughView-BEVUDxuw.js +0 -4
- package/dist/assets/appThemeRegistry-BK0dHKa6.js +0 -1
- package/dist/assets/de-C8jV7J9y.js +0 -10
- package/dist/assets/es-BI6J1M5R.js +0 -16
- package/dist/assets/fr-D6oDFt7E.js +0 -14
- package/dist/assets/index-BqhiCmYS.js +0 -39
- package/dist/assets/index-FqSOBz0J.css +0 -1
- package/dist/assets/ja-C_4i5EQu.js +0 -16
- package/dist/assets/ko-BFbOTpbq.js +0 -16
- package/dist/assets/main-C9ETLKFc.js +0 -2
- package/dist/assets/main-CJmb2dF8.js +0 -930
- package/dist/assets/markdownCore-DVuZpnli.js +0 -5
- package/dist/assets/miniChat-B4Ytoq2n.js +0 -2
- package/dist/assets/mobile-BUT6-lo1.js +0 -2
- package/dist/assets/patchFileDiff-8j1apICU.js +0 -13
- package/dist/assets/pl-COFvT56l.js +0 -16
- package/dist/assets/pt-BR-DtVOO2Lj.js +0 -16
- package/dist/assets/registerCustomTheme-BBXUCRnG.js +0 -1
- package/dist/assets/renderElectronMiniChatApp-B6vUG-vF.js +0 -2
- package/dist/assets/renderMobileApp-BNgHraq6.js +0 -25
- package/dist/assets/runtimeEndpointReset-B8LYpWvr.js +0 -17
- package/dist/assets/scheduledTasksApi-GC4epIYA.js +0 -1
- package/dist/assets/shikiHighlight-BJISeZsQ.js +0 -1
- package/dist/assets/surface-BvRzS58U.js +0 -1
- package/dist/assets/tr-B8Q0Go2l.js +0 -7
- package/dist/assets/uk-Dk4a-Fn-.js +0 -16
- package/dist/assets/useAppFontEffects-DpFNefUA.js +0 -7284
- package/dist/assets/useGitComparison-Dfxaqd0s.js +0 -1
- package/dist/assets/useInlineCommentController-CscsE4t-.js +0 -2
- package/dist/assets/useRootScrollLock-BaCvuRlT.js +0 -1
- package/dist/assets/vendor-framer-motion-livSKyyV.js +0 -1
- package/dist/assets/vendor-zod-BPAANqvH.js +0 -39
- package/dist/assets/zh-CN-B_BXxG1Q.js +0 -16
- package/dist/assets/zh-TW-DLrl1SPZ.js +0 -16
- package/server/lib/mcp-reconnect/DOCUMENTATION.md +0 -55
- package/server/lib/mcp-reconnect/runtime.js +0 -122
- package/server/lib/mcp-reconnect/runtime.test.js +0 -140
- package/server/lib/quota/providers/crof.js +0 -96
- package/server/lib/quota/providers/crof.test.js +0 -98
- /package/dist/assets/{vendor-katex-k3Ppq1Ha.js → vendor-katex-CHD9BdDO.js} +0 -0
package/dist/index.html
CHANGED
|
@@ -509,16 +509,18 @@
|
|
|
509
509
|
pointer-events: none;
|
|
510
510
|
}
|
|
511
511
|
</style>
|
|
512
|
-
<script type="module" crossorigin src="/assets/main-
|
|
512
|
+
<script type="module" crossorigin src="/assets/main-CgXMBNvG.js"></script>
|
|
513
513
|
<link rel="modulepreload" crossorigin href="/assets/vendor-vite-runtime-DD1OZmLC.js">
|
|
514
|
+
<link rel="modulepreload" crossorigin href="/assets/vendor-zod-CgAdXWZO.js">
|
|
514
515
|
<link rel="modulepreload" crossorigin href="/assets/vendor-scheduler-7OC5HNn7.js">
|
|
515
516
|
<link rel="modulepreload" crossorigin href="/assets/vendor-react-BUCujlKS.js">
|
|
516
517
|
<link rel="modulepreload" crossorigin href="/assets/vendor-zustand-BAGL70zf.js">
|
|
517
|
-
<link rel="modulepreload" crossorigin href="/assets/vendor-zod-BPAANqvH.js">
|
|
518
518
|
<link rel="modulepreload" crossorigin href="/assets/vendor-opencode-sdk-BJ73u-bH.js">
|
|
519
|
-
<link rel="modulepreload" crossorigin href="/assets/index-
|
|
519
|
+
<link rel="modulepreload" crossorigin href="/assets/index-Cbci4i1W.js">
|
|
520
520
|
<link rel="modulepreload" crossorigin href="/assets/contextPanelEmbeddedChat-CirXEPJq.js">
|
|
521
|
-
<link rel="
|
|
521
|
+
<link rel="modulepreload" crossorigin href="/assets/vendor-katex-CHD9BdDO.js">
|
|
522
|
+
<link rel="stylesheet" crossorigin href="/assets/index-DqaMWNrC.css">
|
|
523
|
+
<link rel="stylesheet" crossorigin href="/assets/vendor-katex-Cp579UoJ.css">
|
|
522
524
|
</head>
|
|
523
525
|
<body class="h-full bg-background text-foreground">
|
|
524
526
|
<div id="root" class="h-full">
|
package/dist/mini-chat.html
CHANGED
|
@@ -74,15 +74,17 @@
|
|
|
74
74
|
}
|
|
75
75
|
</style>
|
|
76
76
|
|
|
77
|
-
<script type="module" crossorigin src="/assets/miniChat-
|
|
77
|
+
<script type="module" crossorigin src="/assets/miniChat-CwTmDixi.js"></script>
|
|
78
78
|
<link rel="modulepreload" crossorigin href="/assets/vendor-vite-runtime-DD1OZmLC.js">
|
|
79
|
+
<link rel="modulepreload" crossorigin href="/assets/vendor-zod-CgAdXWZO.js">
|
|
79
80
|
<link rel="modulepreload" crossorigin href="/assets/vendor-scheduler-7OC5HNn7.js">
|
|
80
81
|
<link rel="modulepreload" crossorigin href="/assets/vendor-react-BUCujlKS.js">
|
|
81
82
|
<link rel="modulepreload" crossorigin href="/assets/vendor-zustand-BAGL70zf.js">
|
|
82
|
-
<link rel="modulepreload" crossorigin href="/assets/vendor-zod-BPAANqvH.js">
|
|
83
83
|
<link rel="modulepreload" crossorigin href="/assets/vendor-opencode-sdk-BJ73u-bH.js">
|
|
84
|
-
<link rel="modulepreload" crossorigin href="/assets/index-
|
|
85
|
-
<link rel="
|
|
84
|
+
<link rel="modulepreload" crossorigin href="/assets/index-Cbci4i1W.js">
|
|
85
|
+
<link rel="modulepreload" crossorigin href="/assets/vendor-katex-CHD9BdDO.js">
|
|
86
|
+
<link rel="stylesheet" crossorigin href="/assets/index-DqaMWNrC.css">
|
|
87
|
+
<link rel="stylesheet" crossorigin href="/assets/vendor-katex-Cp579UoJ.css">
|
|
86
88
|
</head>
|
|
87
89
|
<body class="h-full bg-background text-foreground">
|
|
88
90
|
<div id="root" class="h-full">
|
package/dist/mobile.html
CHANGED
|
@@ -63,15 +63,17 @@
|
|
|
63
63
|
})();
|
|
64
64
|
</script>
|
|
65
65
|
|
|
66
|
-
<script type="module" crossorigin src="/assets/mobile-
|
|
66
|
+
<script type="module" crossorigin src="/assets/mobile-CLf2vCtO.js"></script>
|
|
67
67
|
<link rel="modulepreload" crossorigin href="/assets/vendor-vite-runtime-DD1OZmLC.js">
|
|
68
|
+
<link rel="modulepreload" crossorigin href="/assets/vendor-zod-CgAdXWZO.js">
|
|
68
69
|
<link rel="modulepreload" crossorigin href="/assets/vendor-scheduler-7OC5HNn7.js">
|
|
69
70
|
<link rel="modulepreload" crossorigin href="/assets/vendor-react-BUCujlKS.js">
|
|
70
71
|
<link rel="modulepreload" crossorigin href="/assets/vendor-zustand-BAGL70zf.js">
|
|
71
|
-
<link rel="modulepreload" crossorigin href="/assets/vendor-zod-BPAANqvH.js">
|
|
72
72
|
<link rel="modulepreload" crossorigin href="/assets/vendor-opencode-sdk-BJ73u-bH.js">
|
|
73
|
-
<link rel="modulepreload" crossorigin href="/assets/index-
|
|
74
|
-
<link rel="
|
|
73
|
+
<link rel="modulepreload" crossorigin href="/assets/index-Cbci4i1W.js">
|
|
74
|
+
<link rel="modulepreload" crossorigin href="/assets/vendor-katex-CHD9BdDO.js">
|
|
75
|
+
<link rel="stylesheet" crossorigin href="/assets/index-DqaMWNrC.css">
|
|
76
|
+
<link rel="stylesheet" crossorigin href="/assets/vendor-katex-Cp579UoJ.css">
|
|
75
77
|
</head>
|
|
76
78
|
<body class="h-full bg-background text-foreground">
|
|
77
79
|
<div id="root" class="h-full"></div>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vantran-se/openchamber-web",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.24.3",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./server/index.js",
|
|
@@ -13,10 +13,11 @@
|
|
|
13
13
|
},
|
|
14
14
|
"scripts": {
|
|
15
15
|
"dev": "bun run build:watch",
|
|
16
|
-
"dev:server": "OPENCHAMBER_RELAY_HOST=${OPENCHAMBER_RELAY_HOST:-off} bun server/index.js --port ${OPENCHAMBER_PORT:-3001}",
|
|
17
|
-
"dev:server:watch": "node ./scripts/dev-server-watch.mjs",
|
|
18
|
-
"build": "vite build",
|
|
19
|
-
"build:watch": "vite build --watch",
|
|
16
|
+
"dev:server": "bun ../../scripts/build-builtin-extensions.mjs && OPENCHAMBER_RELAY_HOST=${OPENCHAMBER_RELAY_HOST:-off} bun server/index.js --port ${OPENCHAMBER_PORT:-3001}",
|
|
17
|
+
"dev:server:watch": "bun ../../scripts/build-builtin-extensions.mjs && node ./scripts/dev-server-watch.mjs",
|
|
18
|
+
"build": "bun ../../scripts/build-builtin-extensions.mjs && vite build",
|
|
19
|
+
"build:watch": "bun ../../scripts/build-builtin-extensions.mjs && vite build --watch",
|
|
20
|
+
"prepack": "bun ../../scripts/build-builtin-extensions.mjs",
|
|
20
21
|
"type-check": "tsc --noEmit",
|
|
21
22
|
"lint": "eslint \"./src/**/*.{ts,tsx}\" --config ../../eslint.config.js",
|
|
22
23
|
"test": "vitest run",
|
|
@@ -25,25 +26,27 @@
|
|
|
25
26
|
"dependencies": {
|
|
26
27
|
"@clack/prompts": "^1.1.0",
|
|
27
28
|
"@octokit/rest": "^22.0.1",
|
|
28
|
-
"@
|
|
29
|
+
"@openchamber/sdk": "workspace:*",
|
|
30
|
+
"@opencode-ai/sdk": "1.18.31",
|
|
29
31
|
"@simplewebauthn/server": "13.3.1",
|
|
30
32
|
"bun-pty": "^0.4.5",
|
|
31
33
|
"compression": "^1.8.1",
|
|
32
|
-
"cron-parser": "^
|
|
34
|
+
"cron-parser": "^5.10.1",
|
|
33
35
|
"express": "^5.1.0",
|
|
34
36
|
"http-proxy-middleware": "^3.0.5",
|
|
35
37
|
"jose": "^6.1.3",
|
|
36
38
|
"jsonc-parser": "^3.3.1",
|
|
37
39
|
"luxon": "^3.5.0",
|
|
38
40
|
"node-pty": "1.2.0-beta.12",
|
|
39
|
-
"openai": "^
|
|
41
|
+
"openai": "^7.18.0",
|
|
40
42
|
"qrcode-terminal": "^0.12.0",
|
|
41
43
|
"reflect-metadata": "^0.2.2",
|
|
42
44
|
"sherpa-onnx-node": "1.12.28",
|
|
43
45
|
"simple-git": "^3.36.0",
|
|
44
46
|
"web-push": "^3.6.7",
|
|
45
47
|
"ws": "^8.18.3",
|
|
46
|
-
"yaml": "^2.8.1"
|
|
48
|
+
"yaml": "^2.8.1",
|
|
49
|
+
"zod": "^4.3.6"
|
|
47
50
|
},
|
|
48
51
|
"devDependencies": {
|
|
49
52
|
"@base-ui/react": "^1.4.0",
|
package/server/index.d.ts
CHANGED
|
@@ -32,6 +32,8 @@ export interface StartWebUiServerOptions {
|
|
|
32
32
|
exitOnShutdown?: boolean;
|
|
33
33
|
uiPassword?: string | null;
|
|
34
34
|
desktopUpdater?: DesktopUpdater;
|
|
35
|
+
/** App-owned built-in resources outside Electron's ASAR archive. */
|
|
36
|
+
builtInExtensionsDir?: string;
|
|
35
37
|
}
|
|
36
38
|
|
|
37
39
|
export declare function startWebUiServer(
|
package/server/index.js
CHANGED
|
@@ -43,6 +43,7 @@ import {
|
|
|
43
43
|
createGlobalUiEventBroadcaster,
|
|
44
44
|
createGlobalMessageStreamHub,
|
|
45
45
|
createMessageStreamWsRuntime,
|
|
46
|
+
resolveDeltaCoalesceWindowMs,
|
|
46
47
|
DEFAULT_UPSTREAM_STALL_TIMEOUT_MS,
|
|
47
48
|
UPSTREAM_STALL_TIMEOUT_CONCURRENT_MS,
|
|
48
49
|
} from './lib/event-stream/index.js';
|
|
@@ -92,7 +93,9 @@ import { createApnsRuntime } from './lib/notifications/apns-runtime.js';
|
|
|
92
93
|
import { createNotificationTemplateRuntime } from './lib/notifications/template-runtime.js';
|
|
93
94
|
import { createPermissionAutoAcceptRuntime } from './lib/permission-auto-accept/runtime.js';
|
|
94
95
|
import { createMessageQueueRuntime } from './lib/message-queue/runtime.js';
|
|
96
|
+
import { createRoutingRuntime } from './lib/routing/runtime.js';
|
|
95
97
|
import { createGracefulShutdownRuntime } from './lib/opencode/shutdown-runtime.js';
|
|
98
|
+
import { stopAllGuestServices } from './lib/guests/service.js';
|
|
96
99
|
import { createProjectConfigRuntime } from './lib/projects/project-config.js';
|
|
97
100
|
import { migrateLegacyUserDirs } from './lib/data-dir-migration.js';
|
|
98
101
|
import { createProjectContextRuntime } from './lib/project-context/runtime.js';
|
|
@@ -112,7 +115,6 @@ import { createDevServerScanner } from './lib/dev-servers/routes.js';
|
|
|
112
115
|
import { createDevTunnelRuntime } from './lib/dev-tunnel/runtime.js';
|
|
113
116
|
import { registerBrowserControlRoutes } from './lib/browser-control/routes.js';
|
|
114
117
|
import { createSystemPromptRuntime } from './lib/system-prompt/runtime.js';
|
|
115
|
-
import { createMcpReconnectRuntime } from './lib/mcp-reconnect/runtime.js';
|
|
116
118
|
import { createOpenChamberSessionService } from './lib/openchamber-sessions/routes.js';
|
|
117
119
|
import { createScheduledTaskService } from './lib/scheduled-tasks/service.js';
|
|
118
120
|
import { createOpenChamberControlService } from './lib/openchamber-control/service.js';
|
|
@@ -298,11 +300,12 @@ const themeRuntime = createThemeRuntime({
|
|
|
298
300
|
});
|
|
299
301
|
|
|
300
302
|
const readCustomThemesFromDisk = (...args) => themeRuntime.readCustomThemesFromDisk(...args);
|
|
303
|
+
const saveImportedTheme = (...args) => themeRuntime.saveImportedTheme(...args);
|
|
304
|
+
const deleteImportedTheme = (...args) => themeRuntime.deleteImportedTheme(...args);
|
|
301
305
|
|
|
302
306
|
let notificationTemplateRuntime = null;
|
|
303
307
|
let agentToolRuntime = null;
|
|
304
308
|
let systemPromptRuntime = null;
|
|
305
|
-
let mcpReconnectRuntime = null;
|
|
306
309
|
|
|
307
310
|
const createTimeoutSignal = (...args) => notificationTemplateRuntime.createTimeoutSignal(...args);
|
|
308
311
|
const formatProjectLabel = (...args) => notificationTemplateRuntime.formatProjectLabel(...args);
|
|
@@ -891,6 +894,25 @@ const globalMessageStreamHub = createGlobalMessageStreamHub({
|
|
|
891
894
|
buildOpenCodeUrl,
|
|
892
895
|
getOpenCodeAuthHeaders,
|
|
893
896
|
upstreamStallTimeoutMs: getUpstreamStallTimeoutMs,
|
|
897
|
+
deltaCoalesceWindowMs: resolveDeltaCoalesceWindowMs(),
|
|
898
|
+
});
|
|
899
|
+
|
|
900
|
+
// OpenChamber-owned events for the UI control stream (SSE) plus the WS fan-out.
|
|
901
|
+
// OpenCode's /global/event proxy cannot carry them.
|
|
902
|
+
const broadcastOpenChamberUiEvent = createGlobalUiEventBroadcaster({
|
|
903
|
+
sseClients: uiOpenChamberEventClients,
|
|
904
|
+
wsClients: uiNotificationWsClients,
|
|
905
|
+
writeSseEvent,
|
|
906
|
+
});
|
|
907
|
+
|
|
908
|
+
// Jev model routing and the permission safety net. Dark unless
|
|
909
|
+
// OPENCHAMBER_ROUTING_ENABLE is set; every failure keeps the user's own model
|
|
910
|
+
// or the auto-accept reply it was asked about.
|
|
911
|
+
const routingRuntime = createRoutingRuntime({
|
|
912
|
+
dataDir: OPENCHAMBER_DATA_DIR,
|
|
913
|
+
buildOpenCodeUrl,
|
|
914
|
+
getOpenCodeAuthHeaders,
|
|
915
|
+
broadcastGlobalUiEvent: broadcastOpenChamberUiEvent,
|
|
894
916
|
});
|
|
895
917
|
|
|
896
918
|
const permissionAutoAcceptRuntime = createPermissionAutoAcceptRuntime({
|
|
@@ -900,6 +922,8 @@ const permissionAutoAcceptRuntime = createPermissionAutoAcceptRuntime({
|
|
|
900
922
|
readSettingsFromDiskMigrated,
|
|
901
923
|
persistSettings,
|
|
902
924
|
broadcastGlobalUiEvent,
|
|
925
|
+
evaluatePermission: (permission, directory) => routingRuntime.evaluatePermission(permission, directory),
|
|
926
|
+
onPermissionReplied: (permissionId) => routingRuntime.forgetPermission(permissionId),
|
|
903
927
|
});
|
|
904
928
|
permissionAutoAcceptRuntime.start();
|
|
905
929
|
notificationTriggerRuntime.setGetIsSessionAutoAccepting(
|
|
@@ -913,13 +937,8 @@ const messageQueueRuntime = createMessageQueueRuntime({
|
|
|
913
937
|
buildOpenCodeUrl,
|
|
914
938
|
getOpenCodeAuthHeaders,
|
|
915
939
|
sessionKnowledgeRuntime,
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
broadcastGlobalUiEvent: createGlobalUiEventBroadcaster({
|
|
919
|
-
sseClients: uiOpenChamberEventClients,
|
|
920
|
-
wsClients: uiNotificationWsClients,
|
|
921
|
-
writeSseEvent,
|
|
922
|
-
}),
|
|
940
|
+
broadcastGlobalUiEvent: broadcastOpenChamberUiEvent,
|
|
941
|
+
resolvePromptBody: (body, target) => routingRuntime.resolvePromptBody(body, target),
|
|
923
942
|
onPromptSent: (sessionId) => sessionRuntime.markUserMessageSent(sessionId),
|
|
924
943
|
dataDir: OPENCHAMBER_DATA_DIR,
|
|
925
944
|
});
|
|
@@ -1256,14 +1275,11 @@ const openCodeLifecycleRuntime = createOpenCodeLifecycleRuntime({
|
|
|
1256
1275
|
? await (agentToolRuntime?.prepareManagedOpenCodeEnv({ includeControl, includeWeb, includeMemory }) || {})
|
|
1257
1276
|
: {};
|
|
1258
1277
|
|
|
1259
|
-
// Each managed plugin appends itself to the config the previous one produced.
|
|
1260
|
-
let configContent = managedEnv.OPENCODE_CONFIG_CONTENT ?? process.env.OPENCODE_CONFIG_CONTENT;
|
|
1261
1278
|
if (settings?.optimizeSystemPrompt === true) {
|
|
1262
|
-
|
|
1279
|
+
const configContent = managedEnv.OPENCODE_CONFIG_CONTENT ?? process.env.OPENCODE_CONFIG_CONTENT;
|
|
1280
|
+
Object.assign(managedEnv, await systemPromptRuntime.prepareManagedOpenCodeEnv(configContent));
|
|
1263
1281
|
}
|
|
1264
|
-
|
|
1265
|
-
const mcpReconnectEnv = await mcpReconnectRuntime.prepareManagedOpenCodeEnv(configContent);
|
|
1266
|
-
return { ...managedEnv, ...mcpReconnectEnv };
|
|
1282
|
+
return managedEnv;
|
|
1267
1283
|
},
|
|
1268
1284
|
});
|
|
1269
1285
|
|
|
@@ -1350,14 +1366,14 @@ const resolveMemoryProjectId = createMemoryProjectResolver({
|
|
|
1350
1366
|
});
|
|
1351
1367
|
|
|
1352
1368
|
/**
|
|
1353
|
-
* Tells open panels that the
|
|
1369
|
+
* Tells open panels that the service changed what it remembers, so what it just
|
|
1354
1370
|
* stored is visible without reopening anything.
|
|
1355
1371
|
*/
|
|
1356
1372
|
const emitAgentMemoryChangedEvent = (event) => {
|
|
1357
1373
|
for (const client of uiOpenChamberEventClients) {
|
|
1358
1374
|
try {
|
|
1359
1375
|
writeSseEvent(client, {
|
|
1360
|
-
type: 'openchamber:
|
|
1376
|
+
type: 'openchamber:service-memory-changed',
|
|
1361
1377
|
properties: {
|
|
1362
1378
|
scope: event.scope,
|
|
1363
1379
|
...(event.projectId ? { projectId: event.projectId } : {}),
|
|
@@ -1383,6 +1399,7 @@ const openChamberSessionService = createOpenChamberSessionService({
|
|
|
1383
1399
|
waitForOpenCodeReady,
|
|
1384
1400
|
emitSessionCreatedEvent,
|
|
1385
1401
|
sessionKnowledgeRuntime,
|
|
1402
|
+
resolvePromptBody: (body, target) => routingRuntime.resolvePromptBody(body, target),
|
|
1386
1403
|
});
|
|
1387
1404
|
// Browser actions are published to whichever OpenChamber clients are connected;
|
|
1388
1405
|
// the one owning the browser panel answers. `emitRequest` returns the number of
|
|
@@ -1531,17 +1548,14 @@ async function main(options = {}) {
|
|
|
1531
1548
|
const address = server?.address?.();
|
|
1532
1549
|
return typeof address === 'object' && address ? address.port : null;
|
|
1533
1550
|
},
|
|
1551
|
+
// A pipe listener reports a string here, which has no address to bind back to.
|
|
1552
|
+
getActiveHost: () => server?.address?.()?.address ?? null,
|
|
1534
1553
|
});
|
|
1535
1554
|
systemPromptRuntime = createSystemPromptRuntime({
|
|
1536
1555
|
fsPromises,
|
|
1537
1556
|
path,
|
|
1538
1557
|
dataDir: OPENCHAMBER_DATA_DIR,
|
|
1539
1558
|
});
|
|
1540
|
-
mcpReconnectRuntime = createMcpReconnectRuntime({
|
|
1541
|
-
fsPromises,
|
|
1542
|
-
path,
|
|
1543
|
-
dataDir: OPENCHAMBER_DATA_DIR,
|
|
1544
|
-
});
|
|
1545
1559
|
|
|
1546
1560
|
// Pairing transports advertised to the create-device dialog. LAN reachability is
|
|
1547
1561
|
// derived from the SERVER's actual bind (a wildcard bind → the machine's LAN IP;
|
|
@@ -1943,6 +1957,8 @@ async function main(options = {}) {
|
|
|
1943
1957
|
resolveGitBinaryForSpawn,
|
|
1944
1958
|
createFsSearchRuntime: createFsSearchRuntimeFactory,
|
|
1945
1959
|
openchamberDataDir: OPENCHAMBER_DATA_DIR,
|
|
1960
|
+
openchamberVersion: OPENCHAMBER_VERSION,
|
|
1961
|
+
builtInExtensionsDir: options.builtInExtensionsDir,
|
|
1946
1962
|
openchamberUserConfigRoot: OPENCHAMBER_USER_CONFIG_ROOT,
|
|
1947
1963
|
managedChatsRoot: OPENCHAMBER_CHATS_DIR,
|
|
1948
1964
|
normalizeDirectoryPath,
|
|
@@ -1950,6 +1966,8 @@ async function main(options = {}) {
|
|
|
1950
1966
|
resolveOptionalProjectDirectory,
|
|
1951
1967
|
validateDirectoryPath,
|
|
1952
1968
|
readCustomThemesFromDisk,
|
|
1969
|
+
saveImportedTheme,
|
|
1970
|
+
deleteImportedTheme,
|
|
1953
1971
|
refreshOpenCodeAfterConfigChange,
|
|
1954
1972
|
getOpenCodeResolutionSnapshot,
|
|
1955
1973
|
getOpenCodeUpgradeCapability,
|
|
@@ -1983,6 +2001,7 @@ async function main(options = {}) {
|
|
|
1983
2001
|
writeSseEvent,
|
|
1984
2002
|
permissionAutoAcceptRuntime,
|
|
1985
2003
|
messageQueueRuntime,
|
|
2004
|
+
routingRuntime,
|
|
1986
2005
|
});
|
|
1987
2006
|
|
|
1988
2007
|
const startupPipelineResult = await startupPipelineRuntime.run({
|
|
@@ -2087,7 +2106,7 @@ async function main(options = {}) {
|
|
|
2087
2106
|
port: managed ? openCodePort : null,
|
|
2088
2107
|
};
|
|
2089
2108
|
},
|
|
2090
|
-
stop: (shutdownOptions = {}) => {
|
|
2109
|
+
stop: async (shutdownOptions = {}) => {
|
|
2091
2110
|
realtimeProxyRuntime.stop();
|
|
2092
2111
|
clearInterval(relayReconcileTimer);
|
|
2093
2112
|
try {
|
|
@@ -2100,6 +2119,11 @@ async function main(options = {}) {
|
|
|
2100
2119
|
} catch {
|
|
2101
2120
|
// best-effort shutdown of the dictation worker
|
|
2102
2121
|
}
|
|
2122
|
+
// Guest services are child processes; leaving before SIGTERM lands
|
|
2123
|
+
// (and the SIGKILL fallback fires) orphans them on the user's machine.
|
|
2124
|
+
await stopAllGuestServices().catch(() => {
|
|
2125
|
+
// best-effort teardown of guest service processes
|
|
2126
|
+
});
|
|
2103
2127
|
return gracefulShutdown({ exitProcess: shutdownOptions.exitProcess ?? false });
|
|
2104
2128
|
}
|
|
2105
2129
|
};
|
|
@@ -4,7 +4,10 @@
|
|
|
4
4
|
* What the agent has learned and chose to keep, in two scopes:
|
|
5
5
|
*
|
|
6
6
|
* - **project** — `<projectsDir>/<projectId>/memory.json`. How this codebase
|
|
7
|
-
* works, what was decided, where things live.
|
|
7
|
+
* works, what was decided, where things live. `<projectId>` is the bounded
|
|
8
|
+
* stem `projectConfigFileStemOf` gives the id (the id itself up to 200
|
|
9
|
+
* characters, `path_sha256_<digest>` beyond), the same folder that holds
|
|
10
|
+
* `project-context`'s `context.json` and sits beside the config file.
|
|
8
11
|
* - **global** — `<userConfigRoot>/memory.json`. Who the user is and how they
|
|
9
12
|
* want to be worked with. It belongs to no project, so it cannot live under
|
|
10
13
|
* one.
|
|
@@ -51,6 +54,7 @@ const PROJECT_MEMORY_MAX_ITEMS = 200;
|
|
|
51
54
|
*/
|
|
52
55
|
const MEMORY_TYPES = new Set(['fact', 'preference', 'reference']);
|
|
53
56
|
|
|
57
|
+
import { projectConfigFileStemOf } from '../projects/project-id.js';
|
|
54
58
|
import { findThreatPattern } from './threat-patterns.js';
|
|
55
59
|
|
|
56
60
|
const PROJECT_ID_PATTERN = /^[a-zA-Z0-9._:-]+$/;
|
|
@@ -211,7 +215,8 @@ export const createAgentMemoryRuntime = (deps) => {
|
|
|
211
215
|
return {
|
|
212
216
|
scope: 'project',
|
|
213
217
|
key: `project:${projectId}`,
|
|
214
|
-
|
|
218
|
+
// Same bounded folder name as `project-context` and the config file.
|
|
219
|
+
filePath: path.join(projectsDirPath, projectConfigFileStemOf(projectId), 'memory.json'),
|
|
215
220
|
};
|
|
216
221
|
}
|
|
217
222
|
throw new Error('scope is required');
|
|
@@ -3,6 +3,7 @@ import fsPromises from 'node:fs/promises';
|
|
|
3
3
|
import os from 'node:os';
|
|
4
4
|
import path from 'node:path';
|
|
5
5
|
|
|
6
|
+
import { createProjectIdFromPath, projectConfigFileStemOf } from '../projects/project-id.js';
|
|
6
7
|
import { createAgentMemoryRuntime } from './runtime.js';
|
|
7
8
|
|
|
8
9
|
const PROJECT_ID = 'path_dGVzdA';
|
|
@@ -48,6 +49,27 @@ describe('scope resolution', () => {
|
|
|
48
49
|
await fsPromises.access(projectPath());
|
|
49
50
|
});
|
|
50
51
|
|
|
52
|
+
test('a project id too long for a folder name is stored under the bounded stem', async () => {
|
|
53
|
+
// A checkout nested deep enough that its `path_<base64url>` id is longer
|
|
54
|
+
// than a folder name may be; the store lands under the bounded stem the
|
|
55
|
+
// config file and project context use, instead of failing with ENAMETOOLONG.
|
|
56
|
+
const longProjectId = createProjectIdFromPath(`/private/tmp/claude-501/${'segment-'.repeat(18)}/scratchpad/evidence/demo-repo`);
|
|
57
|
+
const stem = projectConfigFileStemOf(longProjectId);
|
|
58
|
+
expect(longProjectId.length).toBeGreaterThan(240);
|
|
59
|
+
expect(stem.startsWith('path_sha256_')).toBe(true);
|
|
60
|
+
const target = { scope: 'project', projectId: longProjectId };
|
|
61
|
+
|
|
62
|
+
expect((await runtime.read(target)).entries).toEqual([]);
|
|
63
|
+
await runtime.create(target, { title: 'Uses bun', body: 'Tests run with bun test.' });
|
|
64
|
+
|
|
65
|
+
expect((await runtime.read(target)).entries.map((e) => e.title)).toEqual(['Uses bun']);
|
|
66
|
+
expect((await runtime.readAll(longProjectId)).project.map((e) => e.title)).toEqual(['Uses bun']);
|
|
67
|
+
await fsPromises.access(path.join(rootDir, 'config', 'projects', stem, 'memory.json'));
|
|
68
|
+
expect(await fsPromises.readdir(path.join(rootDir, 'config', 'projects'))).toEqual([stem]);
|
|
69
|
+
// A short id keeps naming its folder itself.
|
|
70
|
+
expect(runtime.resolveTarget(PROJECT).filePath).toBe(projectPath());
|
|
71
|
+
});
|
|
72
|
+
|
|
51
73
|
test('rejects an unknown scope', async () => {
|
|
52
74
|
await expect(runtime.read({ scope: 'nope' })).rejects.toThrow('scope is required');
|
|
53
75
|
});
|
|
@@ -30,8 +30,10 @@ both settings are `false`.
|
|
|
30
30
|
2. `prepareManagedOpenCodeEnv()` materializes the plugin under
|
|
31
31
|
`<openchamber-data-dir>/agent-tool/` and appends its `file://` URL to
|
|
32
32
|
`OPENCODE_CONFIG_CONTENT` without replacing existing plugin entries.
|
|
33
|
-
3. A random per-child token and
|
|
34
|
-
|
|
33
|
+
3. A random per-child token and callback URL are added only to the managed
|
|
34
|
+
OpenCode child environment. The URL points at loopback, except when the
|
|
35
|
+
listener is bound to one concrete address (`--host <ip>`): that socket does
|
|
36
|
+
not answer on loopback, so the URL uses the bound address instead.
|
|
35
37
|
4. The plugin calls `POST /api/openchamber/agent-tool` with its typed input and
|
|
36
38
|
OpenCode's authoritative session directory.
|
|
37
39
|
5. The route delegates the fixed action allowlist directly to the shared
|
|
@@ -48,6 +50,9 @@ both settings are `false`.
|
|
|
48
50
|
- The tool exposes one shared parameter object rather than repeating parameters
|
|
49
51
|
in a large per-action union. Action descriptions carry only required inputs,
|
|
50
52
|
defaults, or one non-obvious semantic detail.
|
|
53
|
+
- The action schema carries `oneOf` and no `enum`. A node combining `enum` and
|
|
54
|
+
`oneOf` is valid JSON Schema, but some OpenAI-compatible gateways reject it
|
|
55
|
+
and answer with an empty completion instead of an error.
|
|
51
56
|
- Obvious fields rely on their names and JSON types. Parameter descriptions are
|
|
52
57
|
reserved for formats, dependencies, scope, and behavior that cannot be safely
|
|
53
58
|
inferred from the field name.
|
|
@@ -69,10 +74,18 @@ both settings are `false`.
|
|
|
69
74
|
|
|
70
75
|
## Security invariants
|
|
71
76
|
|
|
72
|
-
- The callback accepts
|
|
73
|
-
per-child bearer token using a timing-safe comparison.
|
|
77
|
+
- The callback accepts same-machine requests only and requires the current
|
|
78
|
+
per-child bearer token using a timing-safe comparison. Same-machine means a
|
|
79
|
+
loopback source, or, for a listener bound to one concrete address, a source
|
|
80
|
+
equal to that address: the OS sources a local connection to `<ip>` from
|
|
81
|
+
`<ip>`. A wildcard bind keeps the loopback-only rule, and another machine on
|
|
82
|
+
the network always arrives with its own address.
|
|
74
83
|
- The token is never persisted, logged, returned to the UI, or written into
|
|
75
84
|
the materialized plugin.
|
|
85
|
+
- The plugin adds the callback host to `NO_PROXY`/`no_proxy` inside the managed
|
|
86
|
+
child when it loads. Without that, an `HTTP_PROXY` in the child's environment
|
|
87
|
+
would receive a non-loopback callback, token included, because `fetch` has no
|
|
88
|
+
per-request way to skip the environment proxy.
|
|
76
89
|
- Inputs map to a fixed action and parameter allowlist. There is no arbitrary
|
|
77
90
|
CLI, shell, route, or URL forwarding.
|
|
78
91
|
- Session/worktree deletion and project-path registration are not exposed.
|
|
@@ -129,11 +129,24 @@ const createResult = ({ ok, action, data, error, exitCode }) => ({
|
|
|
129
129
|
...(Number.isInteger(exitCode) ? { exitCode } : {}),
|
|
130
130
|
});
|
|
131
131
|
|
|
132
|
+
// Node reports an IPv4 peer on a dual-stack socket as `::ffff:<ipv4>`.
|
|
133
|
+
const normalizeAddress = (value) => {
|
|
134
|
+
const address = (asNonEmptyString(value) || '').toLowerCase();
|
|
135
|
+
return address.startsWith('::ffff:') ? address.slice('::ffff:'.length) : address;
|
|
136
|
+
};
|
|
137
|
+
|
|
132
138
|
const isLoopbackAddress = (value) => {
|
|
133
|
-
const address =
|
|
134
|
-
return address === '127.0.0.1'
|
|
135
|
-
|
|
136
|
-
|
|
139
|
+
const address = normalizeAddress(value);
|
|
140
|
+
return address === '127.0.0.1' || address === '::1';
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
const WILDCARD_ADDRESSES = new Set(['0.0.0.0', '::']);
|
|
144
|
+
|
|
145
|
+
// A wildcard listener answers on loopback. A listener bound to one concrete
|
|
146
|
+
// address answers only there, so that address is the only way back in.
|
|
147
|
+
const resolveConcreteBoundAddress = (value) => {
|
|
148
|
+
const address = normalizeAddress(value);
|
|
149
|
+
return address && !WILDCARD_ADDRESSES.has(address) ? address : null;
|
|
137
150
|
};
|
|
138
151
|
|
|
139
152
|
/**
|
|
@@ -143,11 +156,16 @@ const isLoopbackAddress = (value) => {
|
|
|
143
156
|
* set, the inputs and the description differ. Generating them from one template
|
|
144
157
|
* keeps the transport, metadata and failure handling identical, which is what
|
|
145
158
|
* the caller depends on.
|
|
159
|
+
*
|
|
160
|
+
* The action schema carries `oneOf` only. A node combining `enum` and `oneOf`
|
|
161
|
+
* is valid JSON Schema, but some OpenAI-compatible gateways reject it and
|
|
162
|
+
* answer with an empty completion instead of an error, and the `oneOf` branches
|
|
163
|
+
* are what carry the per-action descriptions the model reads.
|
|
146
164
|
*/
|
|
147
|
-
const createToolEntry = ({ name, description,
|
|
165
|
+
const createToolEntry = ({ name, description, definitions, parameters }) => String.raw` ${name}: {
|
|
148
166
|
description: ${JSON.stringify(description)},
|
|
149
167
|
args: {
|
|
150
|
-
action: { type: "string",
|
|
168
|
+
action: { type: "string", oneOf: ${JSON.stringify(definitions.map((entry) => ({ const: entry.action, description: entry.description })))}, description: "OpenChamber action to perform" },
|
|
151
169
|
parameters: { type: "object", properties: ${JSON.stringify(parameters)}, additionalProperties: false, description: "Inputs for the action; use an empty object when none are needed" },
|
|
152
170
|
},
|
|
153
171
|
async execute(input, context) {
|
|
@@ -221,7 +239,6 @@ const createPluginSource = ({ includeControl, includeWeb, includeMemory }) => {
|
|
|
221
239
|
entries.push(createToolEntry({
|
|
222
240
|
name: 'openchamber',
|
|
223
241
|
description: CONTROL_TOOL_DESCRIPTION,
|
|
224
|
-
actions: OPENCHAMBER_AGENT_TOOL_ACTIONS,
|
|
225
242
|
definitions: OPENCHAMBER_AGENT_TOOL_ACTION_DEFINITIONS,
|
|
226
243
|
parameters: CONTROL_PARAMETER_PROPERTIES,
|
|
227
244
|
}));
|
|
@@ -230,7 +247,6 @@ const createPluginSource = ({ includeControl, includeWeb, includeMemory }) => {
|
|
|
230
247
|
entries.push(createToolEntry({
|
|
231
248
|
name: 'openchamber_web',
|
|
232
249
|
description: WEB_TOOL_DESCRIPTION,
|
|
233
|
-
actions: OPENCHAMBER_WEB_ACTIONS,
|
|
234
250
|
definitions: OPENCHAMBER_WEB_ACTION_DEFINITIONS,
|
|
235
251
|
parameters: WEB_PARAMETER_PROPERTIES,
|
|
236
252
|
}));
|
|
@@ -239,16 +255,33 @@ const createPluginSource = ({ includeControl, includeWeb, includeMemory }) => {
|
|
|
239
255
|
entries.push(createToolEntry({
|
|
240
256
|
name: 'openchamber_memory',
|
|
241
257
|
description: MEMORY_TOOL_DESCRIPTION,
|
|
242
|
-
actions: OPENCHAMBER_MEMORY_ACTIONS,
|
|
243
258
|
definitions: OPENCHAMBER_MEMORY_ACTION_DEFINITIONS,
|
|
244
259
|
parameters: MEMORY_PARAMETER_PROPERTIES,
|
|
245
260
|
}));
|
|
246
261
|
}
|
|
247
262
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
263
|
+
// The callback carries the per-child token over plain HTTP. With a proxy in
|
|
264
|
+
// the child's environment, fetch would hand a non-loopback callback, token
|
|
265
|
+
// included, to that proxy, and no per-request option turns that off. The
|
|
266
|
+
// exemption is added inside the child because only there is the final
|
|
267
|
+
// NO_PROXY, merged from the shell and server environments, visible.
|
|
268
|
+
return `const exemptCallbackFromProxy = () => {
|
|
269
|
+
const endpoint = process.env.OPENCHAMBER_AGENT_TOOL_URL
|
|
270
|
+
if (!endpoint || !URL.canParse(endpoint)) return
|
|
271
|
+
const host = new URL(endpoint).hostname.replace(/^\\[|\\]$/g, "")
|
|
272
|
+
for (const key of ["NO_PROXY", "no_proxy"]) {
|
|
273
|
+
const entries = (process.env[key] || "").split(",").map((entry) => entry.trim()).filter(Boolean)
|
|
274
|
+
if (!entries.includes(host)) process.env[key] = [...entries, host].join(",")
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
export const OpenChamberPlugin = async () => {
|
|
279
|
+
exemptCallbackFromProxy()
|
|
280
|
+
return {
|
|
281
|
+
tool: {
|
|
282
|
+
${entries.join('')} },
|
|
283
|
+
}
|
|
284
|
+
}
|
|
252
285
|
`;
|
|
253
286
|
};
|
|
254
287
|
|
|
@@ -259,6 +292,7 @@ export const createAgentToolRuntime = (dependencies) => {
|
|
|
259
292
|
path,
|
|
260
293
|
dataDir,
|
|
261
294
|
getActivePort,
|
|
295
|
+
getActiveHost = () => null,
|
|
262
296
|
executeAction,
|
|
263
297
|
env = process.env,
|
|
264
298
|
} = dependencies;
|
|
@@ -266,6 +300,8 @@ export const createAgentToolRuntime = (dependencies) => {
|
|
|
266
300
|
const pluginPath = path.join(pluginDirectory, 'openchamber-plugin.js');
|
|
267
301
|
let activeToken = null;
|
|
268
302
|
|
|
303
|
+
const getConcreteBoundAddress = () => resolveConcreteBoundAddress(getActiveHost());
|
|
304
|
+
|
|
269
305
|
const prepareManagedOpenCodeEnv = async ({ includeControl = true, includeWeb = true, includeMemory = true } = {}) => {
|
|
270
306
|
const port = getActivePort();
|
|
271
307
|
if (!Number.isInteger(port) || port <= 0) {
|
|
@@ -278,15 +314,26 @@ export const createAgentToolRuntime = (dependencies) => {
|
|
|
278
314
|
await fsPromises.writeFile(pluginPath, createPluginSource({ includeControl, includeWeb, includeMemory }), { mode: 0o600 });
|
|
279
315
|
activeToken = crypto.randomBytes(32).toString('base64url');
|
|
280
316
|
const pluginUrl = pathToFileURL(pluginPath).href;
|
|
317
|
+
const callbackAddress = getConcreteBoundAddress() || '127.0.0.1';
|
|
318
|
+
const callbackHost = callbackAddress.includes(':') ? `[${callbackAddress}]` : callbackAddress;
|
|
281
319
|
return {
|
|
282
320
|
OPENCODE_CONFIG_CONTENT: appendManagedPlugin(env.OPENCODE_CONFIG_CONTENT, pluginUrl, 'managed tool'),
|
|
283
|
-
OPENCHAMBER_AGENT_TOOL_URL: `http
|
|
321
|
+
OPENCHAMBER_AGENT_TOOL_URL: `http://${callbackHost}:${port}/api/openchamber/agent-tool`,
|
|
284
322
|
OPENCHAMBER_AGENT_TOOL_TOKEN: activeToken,
|
|
285
323
|
};
|
|
286
324
|
};
|
|
287
325
|
|
|
326
|
+
// The managed child runs on this machine. Reaching a listener bound to one
|
|
327
|
+
// concrete address makes the OS source the connection from that same address,
|
|
328
|
+
// so it stands in for loopback there; any other machine arrives as itself.
|
|
329
|
+
const isSameMachineAddress = (value) => {
|
|
330
|
+
if (isLoopbackAddress(value)) return true;
|
|
331
|
+
const boundAddress = getConcreteBoundAddress();
|
|
332
|
+
return boundAddress !== null && normalizeAddress(value) === boundAddress;
|
|
333
|
+
};
|
|
334
|
+
|
|
288
335
|
const authorize = (req) => {
|
|
289
|
-
if (!activeToken || !
|
|
336
|
+
if (!activeToken || !isSameMachineAddress(req.socket?.remoteAddress)) return false;
|
|
290
337
|
const header = asNonEmptyString(req.headers?.authorization);
|
|
291
338
|
if (!header?.startsWith('Bearer ')) return false;
|
|
292
339
|
const provided = Buffer.from(header.slice(7));
|