@vantran-se/openchamber-web 2.1.1 → 2.2.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 +32 -24
- package/bin/cli.js +1 -3
- package/bin/cli.test.js +40 -16
- package/bin/lib/DOCUMENTATION.md +6 -5
- package/bin/lib/cli-args.js +6 -1
- package/bin/lib/cli-args.test.js +34 -0
- package/bin/lib/cli-lifecycle.js +0 -1
- package/bin/lib/cli-network.js +8 -2
- package/bin/lib/cli-process.js +1 -1
- package/bin/lib/cli-settings-accessors.test.js +21 -13
- package/bin/lib/cli-startup.js +17 -11
- package/bin/lib/cli-startup.test.js +92 -2
- package/bin/lib/commands-connect-url.js +8 -1
- package/bin/lib/commands-schedule.js +8 -2
- package/bin/lib/commands-serve.js +15 -21
- package/bin/lib/commands-update.js +12 -24
- package/bin/lib/commands-update.test.js +14 -46
- package/dist/assets/DiffView-Cv9MSXl1.js +4 -0
- package/dist/assets/FilePreviewCommentMenu-D4kLseHj.js +4 -0
- package/dist/assets/FilesView-BVoD8I2x.js +14 -0
- package/dist/assets/{GitView-DzuzhIPx.js → GitView-Bzb8p-ew.js} +4 -4
- package/dist/assets/GuestSurfacePane-Crdbvsxo.js +1 -0
- package/dist/assets/InProgressOperationBanner-CwMjNQgk.js +2 -0
- package/dist/assets/{JsonTreeView-B_EPRjzy.js → JsonTreeView-DRKHZfsn.js} +1 -1
- package/dist/assets/MarkdownImageGallery-DZtqT1Zn.js +1 -0
- package/dist/assets/MarkdownRendererImpl-CqG7HCNd.js +10 -0
- package/dist/assets/OnboardingScreen-DMIxwYK5.js +1 -0
- package/dist/assets/{PatchDiff-6yh1csza.js → PatchDiff-CUcCg1jk.js} +1 -1
- package/dist/assets/PierreDiffViewer-CnnR-dnD.js +228 -0
- package/dist/assets/PlanView-RCBadcY7.js +5 -0
- package/dist/assets/SettingsView-CjBjZFRO.js +30 -0
- package/dist/assets/SettingsWindow-DyM7QuhI.js +1 -0
- package/dist/assets/SubmoduleDiffSummary-BWIfgMED.js +1 -0
- package/dist/assets/ToolOutputDialog-Q0P3FuAi.js +15 -0
- package/dist/assets/ToolPartDiffPreview-p7qR9FpU.js +8 -0
- package/dist/assets/{VirtualizedFileDiff-BTJVRkyo.js → VirtualizedFileDiff-CFpjL8Ns.js} +3 -3
- package/dist/assets/{Virtualizer-xCEYz34p.js → Virtualizer-C0IsclZn.js} +1 -1
- package/dist/assets/WalkthroughView-DI31zD02.js +4 -0
- package/dist/assets/appThemeRegistry-B9gkFq9i.js +1 -0
- package/dist/assets/{computeVirtualFileMetrics-CmPe29DM.js → computeVirtualFileMetrics-C2WM6JC2.js} +2 -2
- package/dist/assets/de-YKfk5MmC.js +14 -0
- package/dist/assets/es-_gwT0kr-.js +20 -0
- package/dist/assets/fileTreeStatus-D438yi8M.js +1 -0
- package/dist/assets/fr-DqzvXmIm.js +18 -0
- package/dist/assets/index-BLaHKdtx.js +1 -0
- package/dist/assets/index-BkMXRrVQ.css +1 -0
- package/dist/assets/index-DxNa7xYB.js +65 -0
- package/dist/assets/initializeSharedPreferences-Bck5EAWP.js +1 -0
- package/dist/assets/{isDiffPlainText-CQmDCnEv.js → isDiffPlainText-Dgbw8VKk.js} +1 -1
- package/dist/assets/{isFilePlainText-CYBUzW4I.js → isFilePlainText-_ZS5UYRj.js} +1 -1
- package/dist/assets/ja-B-GFYhQE.js +20 -0
- package/dist/assets/ko-mzksfqDC.js +20 -0
- package/dist/assets/main-C5Xx8dn_.js +2 -0
- package/dist/assets/main-CfBSQM1H.js +990 -0
- package/dist/assets/markdownCore-BmWwW1ll.js +7 -0
- package/dist/assets/miniChat-mnKwy4vQ.js +2 -0
- package/dist/assets/mobile-DeEQd0wZ.js +2 -0
- package/dist/assets/nl-CWQr6NSq.js +20 -0
- package/dist/assets/{parseDiffFromFile-Cy0PNxun.js → parseDiffFromFile-BUgn-T9p.js} +2 -2
- package/dist/assets/patchFileDiff-Dt8LhgBh.js +13 -0
- package/dist/assets/pl-UmRcDUX2.js +20 -0
- package/dist/assets/pt-BR-BSLybvVF.js +20 -0
- package/dist/assets/relocateRestoredSession-B5E9xb3T.js +1 -0
- package/dist/assets/renderElectronMiniChatApp-C0a9A5_J.js +2 -0
- package/dist/assets/renderMobileApp-BNncg3Pk.js +25 -0
- package/dist/assets/runtimeEndpointReset-CZ5aafpl.js +62 -0
- package/dist/assets/{selectionMarkdown-TkYk5h9l.js → selectionMarkdown-CUN3wUld.js} +9 -9
- package/dist/assets/{sessionOwnership-Bs1xbRfB.js → sessionOwnership-BSuxCEhb.js} +1 -1
- package/dist/assets/shikiHighlight-DHDx-6eM.js +1 -0
- package/dist/assets/space-apply-DM_2pRW7.js +1 -0
- package/dist/assets/space-close-Bpomt8z0.js +1 -0
- package/dist/assets/{surface-B6n7wJtt.js → surface-C-jQaGnL.js} +1 -1
- package/dist/assets/{textMateThemeFromAppTheme-CDlKffWz.js → textMateThemeFromAppTheme-DlsTphbY.js} +1 -1
- package/dist/assets/tr-gaTrX_HK.js +11 -0
- package/dist/assets/uk-CnJF6ykl.js +20 -0
- package/dist/assets/{useAppFontEffects-DCqCVGlT.js → useAppFontEffects-DGlvOqP_.js} +194 -233
- package/dist/assets/useInlineCommentController-kMN4Wg_D.js +2 -0
- package/dist/assets/{useRootScrollLock-BowwS8kq.js → useRootScrollLock-DMPpvpNP.js} +2 -2
- package/dist/assets/{vendor-base-ui-DX96QhTP.js → vendor-base-ui-Det7U81h.js} +1 -1
- package/dist/assets/{vendor-codemirror-autocomplete-DW1FQz9_.js → vendor-codemirror-autocomplete-BSHQHbKu.js} +1 -1
- package/dist/assets/{vendor-codemirror-commands-DpmhalwN.js → vendor-codemirror-commands-C4G_dPWe.js} +1 -1
- package/dist/assets/{vendor-codemirror-lang-angular-BqExbN1M.js → vendor-codemirror-lang-angular-B6LbBGHB.js} +1 -1
- package/dist/assets/{vendor-codemirror-lang-cpp-DZA36HfS.js → vendor-codemirror-lang-cpp-BWWXBx7W.js} +1 -1
- package/dist/assets/{vendor-codemirror-lang-css-B07blnnZ.js → vendor-codemirror-lang-css-Cayfb29q.js} +1 -1
- package/dist/assets/{vendor-codemirror-lang-go-BM8K9D1-.js → vendor-codemirror-lang-go-BoKlCNKw.js} +1 -1
- package/dist/assets/{vendor-codemirror-lang-html-DaH9adfE.js → vendor-codemirror-lang-html-BQWerHsJ.js} +1 -1
- package/dist/assets/{vendor-codemirror-lang-java-CsdC0viz.js → vendor-codemirror-lang-java-DWX7Fq_K.js} +1 -1
- package/dist/assets/{vendor-codemirror-lang-javascript-CpGYXGuo.js → vendor-codemirror-lang-javascript-DbpEcZM0.js} +2 -2
- package/dist/assets/{vendor-codemirror-lang-jinja-BBeGzXw5.js → vendor-codemirror-lang-jinja-D1JIJRA7.js} +1 -1
- package/dist/assets/{vendor-codemirror-lang-json-58T70Hqs.js → vendor-codemirror-lang-json-BzgckzmB.js} +1 -1
- package/dist/assets/{vendor-codemirror-lang-less-BI-xCA59.js → vendor-codemirror-lang-less-B9EpDXFi.js} +1 -1
- package/dist/assets/{vendor-codemirror-lang-liquid-zEcMa-zy.js → vendor-codemirror-lang-liquid-9U7kRbSf.js} +1 -1
- package/dist/assets/{vendor-codemirror-lang-markdown-BLKnlLP4.js → vendor-codemirror-lang-markdown-D2TEBIvZ.js} +1 -1
- package/dist/assets/{vendor-codemirror-lang-php-9f35M83-.js → vendor-codemirror-lang-php-BT6sDVzE.js} +1 -1
- package/dist/assets/vendor-codemirror-lang-python-jAMtYiA9.js +3 -0
- package/dist/assets/{vendor-codemirror-lang-rust-MNDL_jZQ.js → vendor-codemirror-lang-rust-CVO56EiL.js} +1 -1
- package/dist/assets/{vendor-codemirror-lang-sass-p9epsSNm.js → vendor-codemirror-lang-sass-DZlOoUWu.js} +1 -1
- package/dist/assets/{vendor-codemirror-lang-sql-Bqzh0EXX.js → vendor-codemirror-lang-sql-fZ6t1DPw.js} +1 -1
- package/dist/assets/{vendor-codemirror-lang-vue-BnNUWV-p.js → vendor-codemirror-lang-vue-DxbqrLiE.js} +1 -1
- package/dist/assets/{vendor-codemirror-lang-wast-C2a-oLmk.js → vendor-codemirror-lang-wast-DyU1Gt-I.js} +1 -1
- package/dist/assets/vendor-codemirror-lang-xml-C9a_K5_p.js +1 -0
- package/dist/assets/{vendor-codemirror-lang-yaml-C0sjswB0.js → vendor-codemirror-lang-yaml-Cptq8l0e.js} +1 -1
- package/dist/assets/{vendor-codemirror-language-ByBn5zIW.js → vendor-codemirror-language-DufXoQvE.js} +2 -2
- package/dist/assets/vendor-codemirror-language-data-CtwSWKtX.js +2 -0
- package/dist/assets/{vendor-codemirror-search-ib-sHD5W.js → vendor-codemirror-search-CvXM_pZg.js} +1 -1
- package/dist/assets/{vendor-codemirror-state-G3UuR-be.js → vendor-codemirror-state-Dek9sMtw.js} +1 -1
- package/dist/assets/{vendor-codemirror-view-Bniqp7p5.js → vendor-codemirror-view-1e0FQ6Wn.js} +1 -1
- package/dist/assets/vendor-framer-motion-DxDVhOLc.js +9 -0
- package/dist/assets/vendor-katex-CuQvj9-L.js +257 -0
- package/dist/assets/vendor-katex-DdZNUVNG.css +1 -0
- package/dist/assets/{vendor-motion-dom-DcCgeG69.js → vendor-motion-dom-HXPOMxb7.js} +1 -1
- package/dist/assets/{vendor-opencode-client-DHzhmLwV.js → vendor-opencode-client-BmFcUkbQ.js} +1 -1
- package/dist/assets/{vendor-replit-codemirror-vim-DkzqxN2H.js → vendor-replit-codemirror-vim-BlJRn-cW.js} +2 -2
- package/dist/assets/{vendor-tanstack-react-virtual-H_JmXOFV.js → vendor-tanstack-react-virtual-CvuLsk7D.js} +1 -1
- package/dist/assets/{vendor-tanstack-virtual-core-Dxc8hSTB.js → vendor-tanstack-virtual-core-DPaNcJcT.js} +1 -1
- package/dist/assets/zh-CN-t2vigSB1.js +20 -0
- package/dist/assets/zh-TW-jAgqBokB.js +20 -0
- package/dist/index.html +6 -6
- package/dist/mini-chat.html +6 -6
- package/dist/mobile.html +6 -6
- package/package.json +8 -5
- package/server/index.js +80 -36
- package/server/lib/agent-memory/actions.js +1 -6
- package/server/lib/agent-memory/routes.js +1 -2
- package/server/lib/agent-memory/runtime.js +1 -8
- package/server/lib/agent-tool/DOCUMENTATION.md +7 -3
- package/server/lib/agent-tool/runtime.js +3 -6
- package/server/lib/agent-tool/runtime.test.js +0 -2
- package/server/lib/browser-control/DOCUMENTATION.md +6 -0
- package/server/lib/changelog/update-notes.js +1 -1
- package/server/lib/context-obligatory/runtime.js +1 -2
- package/server/lib/dev-tunnel/DOCUMENTATION.md +8 -0
- package/server/lib/dev-tunnel/client.js +21 -10
- package/server/lib/dev-tunnel/tunnel.test.js +34 -0
- package/server/lib/dispatch-results/runtime.js +1 -1
- package/server/lib/enterprise-mode.d.ts +1 -0
- package/server/lib/enterprise-mode.js +13 -2
- package/server/lib/enterprise-mode.test.js +21 -0
- package/server/lib/event-stream/DOCUMENTATION.md +2 -2
- package/server/lib/event-stream/index.js +1 -3
- package/server/lib/event-stream/translate-v2.js +1 -9
- package/server/lib/event-stream/translate-v2.test.js +0 -11
- package/server/lib/fs/DOCUMENTATION.md +5 -2
- package/server/lib/fs/routes.js +62 -15
- package/server/lib/fs/routes.test.js +278 -48
- package/server/lib/fs/workspace-file-names.js +104 -0
- package/server/lib/fs/workspace-file-names.test.js +62 -0
- package/server/lib/git/DOCUMENTATION.md +17 -5
- package/server/lib/git/contributor-provenance-storage.js +9 -6
- package/server/lib/git/contributor-provenance-storage.test.js +29 -0
- package/server/lib/git/credential-broker.js +1 -1
- package/server/lib/git/credential-resolver.js +1 -4
- package/server/lib/git/credentials.js +1 -0
- package/server/lib/git/discovery-endpoint.js +1 -1
- package/server/lib/git/identity-provisioning.js +2 -1
- package/server/lib/git/identity-storage.js +3 -4
- package/server/lib/git/lfs-discovery.js +14 -14
- package/server/lib/git/lfs-discovery.test.js +16 -6
- package/server/lib/git/network-operation-plan.js +50 -62
- package/server/lib/git/network-operation-plan.test.js +103 -1
- package/server/lib/git/network-operation-registry.js +4 -6
- package/server/lib/git/network-operation-storage.js +4 -6
- package/server/lib/git/network-operations.js +12 -4
- package/server/lib/git/network-operations.test.js +19 -6
- package/server/lib/git/redaction.js +2 -1
- package/server/lib/git/repository-credential-runtime.js +5 -3
- package/server/lib/git/repository-credential-runtime.test.js +22 -0
- package/server/lib/git/routes.js +31 -137
- package/server/lib/git/routes.test.js +2 -2
- package/server/lib/git/service.js +143 -27
- package/server/lib/git/service.test.js +215 -1
- package/server/lib/git/ssh-credential-storage.js +1 -4
- package/server/lib/git/submodule-discovery.js +1 -1
- package/server/lib/git/worktree-bootstrap-storage.js +3 -4
- package/server/lib/git/worktree-bootstrap-storage.test.js +15 -0
- package/server/lib/git/worktree-creation.js +194 -0
- package/server/lib/git/worktree-creation.test.js +155 -0
- package/server/lib/github/DOCUMENTATION.md +11 -6
- package/server/lib/github/auth.js +2 -4
- package/server/lib/github/device-flow.js +2 -2
- package/server/lib/github/gh-cli-credential.js +1 -0
- package/server/lib/github/octokit.js +31 -0
- package/server/lib/github/pr-status.js +35 -18
- package/server/lib/github/pr-status.test.js +271 -3
- package/server/lib/github/reference-search.js +102 -13
- package/server/lib/github/reference-search.test.js +48 -7
- package/server/lib/github/routes.auth.test.js +18 -0
- package/server/lib/github/routes.js +360 -6
- package/server/lib/github/routes.mutations.test.js +239 -0
- package/server/lib/github/routes.test.js +134 -2
- package/server/lib/gitlab/DOCUMENTATION.md +5 -1
- package/server/lib/gitlab/auth-storage.test.js +1 -0
- package/server/lib/gitlab/mappers.js +30 -1
- package/server/lib/gitlab/resources.js +230 -6
- package/server/lib/gitlab/resources.test.js +179 -0
- package/server/lib/gitlab/routes.js +200 -6
- package/server/lib/gitlab/routes.test.js +186 -2
- package/server/lib/gitlab/validation.js +1 -5
- package/server/lib/guests/DOCUMENTATION.md +1 -1
- package/server/lib/guests/oauth.js +2 -2
- package/server/lib/guests/service.js +1 -1
- package/server/lib/guests/sockets.js +1 -1
- package/server/lib/injected-env.d.ts +8 -0
- package/server/lib/injected-env.js +50 -0
- package/server/lib/injected-env.test.js +56 -0
- package/server/lib/linear/DOCUMENTATION.md +5 -6
- package/server/lib/linear/issues.js +62 -4
- package/server/lib/linear/issues.test.js +68 -0
- package/server/lib/linear/oauth.js +5 -5
- package/server/lib/linear/parse.js +2 -9
- package/server/lib/message-queue/DOCUMENTATION.md +23 -1
- package/server/lib/message-queue/runtime.js +85 -12
- package/server/lib/message-queue/runtime.test.js +172 -2
- package/server/lib/notifications/apns-runtime.js +5 -6
- package/server/lib/notifications/apns-runtime.test.js +20 -4
- package/server/lib/openchamber-control/DOCUMENTATION.md +19 -1
- package/server/lib/openchamber-control/actions.js +2 -1
- package/server/lib/openchamber-control/service.js +119 -20
- package/server/lib/openchamber-control/service.test.js +166 -0
- package/server/lib/openchamber-sessions/archive-store.js +1 -6
- package/server/lib/openchamber-sessions/routes.js +47 -12
- package/server/lib/openchamber-sessions/routes.test.js +65 -2
- package/server/lib/openchamber-sessions/session-metadata-store.js +1 -6
- package/server/lib/opencode/DOCUMENTATION.md +22 -8
- package/server/lib/opencode/agents.js +62 -0
- package/server/lib/opencode/auth-state-runtime.js +3 -1
- package/server/lib/opencode/auth.d.ts +1 -1
- package/server/lib/opencode/auth.js +8 -0
- package/server/lib/opencode/auth.test.js +31 -0
- package/server/lib/opencode/config-entity-routes.js +16 -0
- package/server/lib/opencode/config-entity-v2.test.js +16 -1
- package/server/lib/opencode/config-paths.test.js +2 -2
- package/server/lib/opencode/config-v2.js +2 -4
- package/server/lib/opencode/feature-routes-runtime.js +89 -49
- package/server/lib/opencode/lifecycle.js +41 -21
- package/server/lib/opencode/lifecycle.test.js +50 -2
- package/server/lib/opencode/model-discovery.js +1 -1
- package/server/lib/opencode/model-discovery.test.js +17 -0
- package/server/lib/opencode/models-metadata.js +0 -2
- package/server/lib/opencode/openchamber-routes.test.js +3 -3
- package/server/lib/opencode/plugins.js +6 -9
- package/server/lib/opencode/provider-source-route.test.js +101 -3
- package/server/lib/opencode/providers-disabled.test.js +59 -0
- package/server/lib/opencode/providers.js +34 -0
- package/server/lib/opencode/proxy.js +11 -3
- package/server/lib/opencode/routes.js +40 -2
- package/server/lib/opencode/settings-helpers.js +27 -1
- package/server/lib/opencode/settings-helpers.test.js +19 -7
- package/server/lib/opencode/settings-registry.json +27 -16
- package/server/lib/opencode/settings-runtime.test.js +18 -0
- package/server/lib/opencode/shared-service-runtime.js +23 -104
- package/server/lib/opencode/shared.js +77 -46
- package/server/lib/opencode/shared.test.js +12 -12
- package/server/lib/opencode/shutdown-runtime.test.js +2 -3
- package/server/lib/opencode/skill-routes.js +123 -38
- package/server/lib/opencode/skill-routes.test.js +201 -0
- package/server/lib/opencode/skills.js +81 -34
- package/server/lib/opencode/skills.test.js +176 -21
- package/server/lib/opencode/startup-pipeline-runtime.js +6 -3
- package/server/lib/opencode/startup-pipeline-runtime.test.js +2 -1
- package/server/lib/opencode/watcher.test.js +0 -54
- package/server/lib/outbound-proxy.js +52 -0
- package/server/lib/outbound-proxy.test.js +55 -0
- package/server/lib/package-manager.js +23 -17
- package/server/lib/package-manager.test.js +5 -18
- package/server/lib/permission-auto-accept/DOCUMENTATION.md +1 -1
- package/server/lib/permission-auto-accept/runtime.js +19 -47
- package/server/lib/permission-auto-accept/runtime.test.js +2 -2
- package/server/lib/project-context/DOCUMENTATION.md +7 -1
- package/server/lib/project-context/routes.js +1 -2
- package/server/lib/project-context/runtime.js +12 -14
- package/server/lib/project-context/runtime.test.js +78 -2
- package/server/lib/projects/project-config.js +30 -15
- package/server/lib/projects/project-config.test.js +30 -0
- package/server/lib/projects/project-setup.js +1 -2
- package/server/lib/projects/routes.js +1 -2
- package/server/lib/quota/DOCUMENTATION.md +35 -7
- package/server/lib/quota/index.js +1 -0
- package/server/lib/quota/providers/claude/index.js +1 -1
- package/server/lib/quota/providers/cline-pass.js +1 -1
- package/server/lib/quota/providers/exe-dev.js +1 -1
- package/server/lib/quota/providers/google/index.js +1 -1
- package/server/lib/quota/providers/hyper.js +1 -1
- package/server/lib/quota/providers/kimi.js +116 -36
- package/server/lib/quota/providers/kimi.test.js +128 -3
- package/server/lib/quota/providers/opencode-go.js +144 -21
- package/server/lib/quota/providers/opencode-go.test.js +229 -6
- package/server/lib/quota/providers/openrouter.js +1 -1
- package/server/lib/quota/providers/zenmux.js +1 -1
- package/server/lib/quota/utils/auth.js +1 -0
- package/server/lib/quota/utils/transformers.js +2 -6
- package/server/lib/relay/DOCUMENTATION.md +18 -3
- package/server/lib/relay/e2ee.js +7 -7
- package/server/lib/relay/host-client.js +84 -13
- package/server/lib/relay/host-client.test.js +201 -1
- package/server/lib/relay/identity.js +6 -29
- package/server/lib/relay/identity.test.js +18 -28
- package/server/lib/relay/key-store.js +141 -0
- package/server/lib/relay/key-store.test.js +138 -0
- package/server/lib/relay/service.js +8 -8
- package/server/lib/relay/service.test.js +10 -5
- package/server/lib/relay/signing-key.js +13 -36
- package/server/lib/relay/tunnel-codec.js +10 -10
- package/server/lib/route-module-exports.test.js +22 -0
- package/server/lib/routing/DOCUMENTATION.md +23 -3
- package/server/lib/routing/cache.js +87 -0
- package/server/lib/routing/defaults.js +11 -0
- package/server/lib/routing/history.js +12 -4
- package/server/lib/routing/runtime.js +39 -3
- package/server/lib/routing/runtime.test.js +81 -2
- package/server/lib/routing/store.js +12 -1
- package/server/lib/routing/store.test.js +13 -0
- package/server/lib/scheduled-tasks/DOCUMENTATION.md +59 -1
- package/server/lib/scheduled-tasks/existing-session.js +119 -0
- package/server/lib/scheduled-tasks/existing-session.test.js +350 -0
- package/server/lib/scheduled-tasks/loops.js +1 -8
- package/server/lib/scheduled-tasks/routes.js +8 -8
- package/server/lib/scheduled-tasks/runtime.js +103 -13
- package/server/lib/scheduled-tasks/runtime.test.js +48 -0
- package/server/lib/scheduled-tasks/service.js +33 -11
- package/server/lib/scheduled-tasks/service.test.js +128 -2
- package/server/lib/scheduled-tasks/session-defaults.js +27 -0
- package/server/lib/scheduled-tasks/session-defaults.test.js +19 -0
- package/server/lib/session-assist/context.js +1 -0
- package/server/lib/session-folders/routes.js +2 -2
- package/server/lib/session-goal/objectives.js +1 -1
- package/server/lib/session-knowledge/routes.js +2 -2
- package/server/lib/session-knowledge/runtime.js +1 -2
- package/server/lib/session-work/DOCUMENTATION.md +39 -14
- package/server/lib/session-work/questions.js +31 -2
- package/server/lib/session-work/runtime.js +22 -13
- package/server/lib/session-work/runtime.test.js +43 -26
- package/server/lib/session-work/state.js +10 -4
- package/server/lib/session-work/state.test.js +8 -1
- package/server/lib/shared/DOCUMENTATION.md +89 -0
- package/server/lib/shared/guards.js +53 -0
- package/server/lib/shared/guards.test.js +112 -0
- package/server/lib/skills-catalog/DOCUMENTATION.md +10 -8
- package/server/lib/skills-catalog/cache.js +3 -2
- package/server/lib/skills-catalog/curated-sources.js +5 -1
- package/server/lib/skills-catalog/git.js +107 -20
- package/server/lib/skills-catalog/git.test.js +78 -0
- package/server/lib/skills-catalog/install.js +21 -12
- package/server/lib/skills-catalog/scan.js +25 -15
- package/server/lib/skills-catalog/source.js +26 -1
- package/server/lib/skills-catalog/source.test.js +27 -0
- package/server/lib/source-control/DOCUMENTATION.md +2 -1
- package/server/lib/source-control/audit-storage.js +7 -6
- package/server/lib/source-control/audit-storage.test.js +11 -0
- package/server/lib/source-control/binding-service.js +2 -5
- package/server/lib/source-control/change-request-worktree.js +90 -0
- package/server/lib/source-control/change-request-worktree.test.js +121 -0
- package/server/lib/source-control/mutation-executor.js +1 -1
- package/server/lib/source-control/mutation-storage.js +11 -5
- package/server/lib/source-control/provider-instance.js +1 -2
- package/server/lib/source-control/repository-identity.js +1 -1
- package/server/lib/source-control/routes.js +14 -2
- package/server/lib/spaces/DOCUMENTATION.md +42 -17
- package/server/lib/spaces/command-stream.test.js +15 -0
- package/server/lib/spaces/dispatcher.js +7 -0
- package/server/lib/spaces/dispatcher.test.js +17 -0
- package/server/lib/spaces/hardening.js +2 -2
- package/server/lib/spaces/hardening.test.js +1 -1
- package/server/lib/spaces/host.js +2 -0
- package/server/lib/spaces/journey.js +66 -5
- package/server/lib/spaces/journey.test.js +95 -4
- package/server/lib/spaces/layout.js +1 -1
- package/server/lib/spaces/places/docker-disk.js +38 -14
- package/server/lib/spaces/places/docker-disk.test.js +80 -1
- package/server/lib/spaces/places/docker.js +35 -11
- package/server/lib/spaces/places/fake-docker.js +22 -3
- package/server/lib/spaces/places/memory-place.js +3 -0
- package/server/lib/spaces/places/packed.docker.live.test.js +1 -1
- package/server/lib/spaces/routes.js +5 -0
- package/server/lib/spaces/routes.test.js +4 -2
- package/server/lib/spaces/run-command.js +9 -2
- package/server/lib/spaces/tools.js +4 -5
- package/server/lib/spaces/tools.test.js +2 -2
- package/server/lib/terminal/runtime.js +18 -6
- package/server/lib/terminal/runtime.test.js +66 -0
- package/server/lib/tts/index.js +3 -0
- package/server/lib/tts/service.js +4 -2
- package/server/lib/walkthrough/DOCUMENTATION.md +3 -1
- package/server/lib/walkthrough/index.js +2 -3
- package/server/lib/walkthrough/pr-source.test.js +22 -0
- package/server/lib/walkthrough/sources.js +6 -1
- package/server/opencode-proxy.test.js +127 -0
- package/bin/lib/commands-startup.test.js +0 -15
- package/dist/assets/CodeMirrorCommentWidgets-CVDSjcrP.js +0 -1
- package/dist/assets/DiffView-Ct7vL3fD.js +0 -4
- package/dist/assets/FilesView-DT0uEYgT.js +0 -17
- package/dist/assets/GuestSurfacePane-DVvk1VPu.js +0 -1
- package/dist/assets/LinearIssuesView-C10MwA9h.js +0 -1
- package/dist/assets/MarkdownImageGallery-BbN_K_3d.js +0 -1
- package/dist/assets/MarkdownRendererImpl-BLt2Tkk9.js +0 -10
- package/dist/assets/OnboardingScreen-Bgp5A3WB.js +0 -1
- package/dist/assets/PierreDiffViewer-CWJLj-S-.js +0 -210
- package/dist/assets/PlanView-DsRWnsOI.js +0 -5
- package/dist/assets/PublishDialog-CCeKloRu.js +0 -2
- package/dist/assets/SettingsView-BuPPsNPp.js +0 -30
- package/dist/assets/SettingsWindow-CM5fL8Ot.js +0 -1
- package/dist/assets/SubmoduleDiffSummary-CfsMcfiQ.js +0 -1
- package/dist/assets/ToolOutputDialog-mZrfSofz.js +0 -15
- package/dist/assets/ToolPartDiffPreview-BUGCRYEL.js +0 -8
- package/dist/assets/WalkthroughView-ClBo7PPd.js +0 -4
- package/dist/assets/appThemeRegistry-CxzMxR-H.js +0 -1
- package/dist/assets/de-CBla4hjd.js +0 -14
- package/dist/assets/es-BmnZtxTD.js +0 -20
- package/dist/assets/fileTreeStatus-BSHFIGEg.js +0 -1
- package/dist/assets/fr-OVKIBUZO.js +0 -18
- package/dist/assets/index-CKCFKmjF.js +0 -1
- package/dist/assets/index-Dbx4V4GN.css +0 -1
- package/dist/assets/index-vQ1Pg1cr.js +0 -61
- package/dist/assets/ja-6v-yr-gE.js +0 -20
- package/dist/assets/ko-I_ZLvgQ9.js +0 -20
- package/dist/assets/main-CmO4dRtR.js +0 -2
- package/dist/assets/main-b9vqhlYM.js +0 -999
- package/dist/assets/markdownCore-BPEZRQfP.js +0 -7
- package/dist/assets/miniChat-B5Oi7B-6.js +0 -2
- package/dist/assets/mobile-CVtShif9.js +0 -2
- package/dist/assets/nl-DcvIJf46.js +0 -20
- package/dist/assets/patchFileDiff-CW3wCH1O.js +0 -13
- package/dist/assets/pl-JxCUl0sd.js +0 -20
- package/dist/assets/pt-BR-L89mjja2.js +0 -20
- package/dist/assets/relocateRestoredSession-DYh_9oBa.js +0 -1
- package/dist/assets/renderElectronMiniChatApp-BD-1JHSg.js +0 -2
- package/dist/assets/renderMobileApp-7s5InXt1.js +0 -25
- package/dist/assets/runtimeEndpointReset-DqLJC6L1.js +0 -53
- package/dist/assets/shikiHighlight-CXgZnvHh.js +0 -1
- package/dist/assets/space-apply-1trGVIl8.js +0 -1
- package/dist/assets/space-close-y7j-NuBv.js +0 -1
- package/dist/assets/tr-ka5J1flt.js +0 -11
- package/dist/assets/uk-PyGe6Q_u.js +0 -20
- package/dist/assets/useInlineCommentController-CrjSGCpi.js +0 -2
- package/dist/assets/vendor-codemirror-lang-python-B7ClrMIT.js +0 -3
- package/dist/assets/vendor-codemirror-lang-xml-C8tGnS64.js +0 -1
- package/dist/assets/vendor-codemirror-language-data-q2bKO1EM.js +0 -2
- package/dist/assets/vendor-framer-motion-Bq3iTZ6r.js +0 -1
- package/dist/assets/vendor-katex-CHD9BdDO.js +0 -257
- package/dist/assets/vendor-katex-Cp579UoJ.css +0 -1
- package/dist/assets/zh-CN-B0P2tybJ.js +0 -20
- package/dist/assets/zh-TW-Bs9C5cN8.js +0 -20
|
@@ -9,11 +9,7 @@ import { isSupportedOpenCodeVersion, readOpenCodeInfo } from './compatibility.js
|
|
|
9
9
|
|
|
10
10
|
const endpointSchema = z.object({
|
|
11
11
|
url: z.string(),
|
|
12
|
-
auth: z.object({
|
|
13
|
-
type: z.literal('basic'),
|
|
14
|
-
username: z.string(),
|
|
15
|
-
password: z.string(),
|
|
16
|
-
}).optional(),
|
|
12
|
+
auth: z.object({ type: z.literal('basic'), username: z.string(), password: z.string() }).optional(),
|
|
17
13
|
});
|
|
18
14
|
|
|
19
15
|
const createConnectionError = (code, message, details = {}, cause) => {
|
|
@@ -22,134 +18,57 @@ const createConnectionError = (code, message, details = {}, cause) => {
|
|
|
22
18
|
Object.assign(error, details);
|
|
23
19
|
return error;
|
|
24
20
|
};
|
|
25
|
-
|
|
26
|
-
const unavailableError = (message, cause) => createConnectionError(
|
|
27
|
-
'OPENCODE_SERVICE_UNAVAILABLE',
|
|
28
|
-
message,
|
|
29
|
-
{},
|
|
30
|
-
cause,
|
|
31
|
-
);
|
|
32
|
-
|
|
21
|
+
const unavailableError = (message, cause) => createConnectionError('OPENCODE_SERVICE_UNAVAILABLE', message, {}, cause);
|
|
33
22
|
const normalizeEndpoint = (endpoint) => {
|
|
34
23
|
const parsed = endpointSchema.safeParse(endpoint);
|
|
35
|
-
if (!parsed.success)
|
|
36
|
-
throw unavailableError('OpenCode shared service did not return an endpoint');
|
|
37
|
-
}
|
|
38
|
-
|
|
24
|
+
if (!parsed.success) throw unavailableError('OpenCode shared service did not return an endpoint');
|
|
39
25
|
let url;
|
|
40
|
-
try {
|
|
41
|
-
|
|
42
|
-
} catch (cause) {
|
|
43
|
-
throw unavailableError('OpenCode shared service returned an invalid URL', cause);
|
|
44
|
-
}
|
|
45
|
-
if ((url.protocol !== 'http:' && url.protocol !== 'https:') || !url.hostname) {
|
|
46
|
-
throw unavailableError('OpenCode shared service returned an unsupported URL');
|
|
47
|
-
}
|
|
48
|
-
|
|
26
|
+
try { url = new URL(parsed.data.url); } catch (cause) { throw unavailableError('OpenCode shared service returned an invalid URL', cause); }
|
|
27
|
+
if (!['http:', 'https:'].includes(url.protocol) || !url.hostname) throw unavailableError('OpenCode shared service returned an unsupported URL');
|
|
49
28
|
return { ...parsed.data, url: url.origin };
|
|
50
29
|
};
|
|
51
|
-
|
|
52
|
-
const defaultRegistrationFile = () => join(
|
|
53
|
-
process.env.XDG_STATE_HOME ?? join(homedir(), '.local', 'state'),
|
|
54
|
-
'opencode',
|
|
55
|
-
'service.json',
|
|
56
|
-
);
|
|
57
|
-
|
|
30
|
+
const defaultRegistrationFile = () => join(process.env.XDG_STATE_HOME ?? join(homedir(), '.local', 'state'), 'opencode', 'service.json');
|
|
58
31
|
const registrationExists = async (options = {}) => {
|
|
59
|
-
try {
|
|
60
|
-
|
|
61
|
-
return true;
|
|
62
|
-
} catch (error) {
|
|
63
|
-
if (error?.code === 'ENOENT') return false;
|
|
64
|
-
throw error;
|
|
65
|
-
}
|
|
32
|
+
try { await access(options.file ?? defaultRegistrationFile()); return true; }
|
|
33
|
+
catch (error) { if (error?.code === 'ENOENT') return false; throw error; }
|
|
66
34
|
};
|
|
67
35
|
|
|
68
36
|
export const createSharedOpenCodeServiceRuntime = ({
|
|
69
|
-
service = Service,
|
|
70
|
-
|
|
71
|
-
ensureOptions,
|
|
72
|
-
readInfo = readOpenCodeInfo,
|
|
73
|
-
isSupportedVersion = isSupportedOpenCodeVersion,
|
|
74
|
-
hasRegistration = registrationExists,
|
|
37
|
+
service = Service, fetchImpl = fetch, ensureOptions, readInfo = readOpenCodeInfo,
|
|
38
|
+
isSupportedVersion = isSupportedOpenCodeVersion, hasRegistration = registrationExists,
|
|
75
39
|
}) => {
|
|
76
40
|
let activeConnection = null;
|
|
77
|
-
|
|
78
41
|
const resolveEndpoint = async () => {
|
|
79
42
|
let discovered;
|
|
80
|
-
try {
|
|
81
|
-
discovered = await service.discover(ensureOptions);
|
|
82
|
-
} catch (cause) {
|
|
83
|
-
throw unavailableError('Could not discover the OpenCode shared service', cause);
|
|
84
|
-
}
|
|
43
|
+
try { discovered = await service.discover(ensureOptions); } catch (cause) { throw unavailableError('Could not discover the OpenCode shared service', cause); }
|
|
85
44
|
if (discovered) return normalizeEndpoint(discovered);
|
|
86
|
-
|
|
87
45
|
try {
|
|
88
|
-
if (await hasRegistration(ensureOptions))
|
|
89
|
-
throw unavailableError(
|
|
90
|
-
'An incompatible or unhealthy OpenCode shared service is already registered',
|
|
91
|
-
);
|
|
92
|
-
}
|
|
46
|
+
if (await hasRegistration(ensureOptions)) throw unavailableError('An incompatible or unhealthy OpenCode shared service is already registered');
|
|
93
47
|
} catch (cause) {
|
|
94
48
|
if (cause?.code === 'OPENCODE_SERVICE_UNAVAILABLE') throw cause;
|
|
95
49
|
throw unavailableError('Could not inspect the OpenCode shared service registration', cause);
|
|
96
50
|
}
|
|
97
|
-
try {
|
|
98
|
-
|
|
99
|
-
} catch (cause) {
|
|
51
|
+
try { return normalizeEndpoint(await service.ensure(ensureOptions)); }
|
|
52
|
+
catch (cause) {
|
|
100
53
|
if (cause?.code === 'OPENCODE_SERVICE_UNAVAILABLE') throw cause;
|
|
101
54
|
throw unavailableError('Could not start the OpenCode shared service', cause);
|
|
102
55
|
}
|
|
103
56
|
};
|
|
104
|
-
|
|
105
57
|
const probe = async (endpoint) => {
|
|
106
58
|
let headers;
|
|
107
|
-
try {
|
|
108
|
-
headers = { ...(service.headers(endpoint) ?? {}) };
|
|
109
|
-
} catch (cause) {
|
|
110
|
-
throw unavailableError('Could not authenticate with the OpenCode shared service', cause);
|
|
111
|
-
}
|
|
59
|
+
try { headers = { ...(service.headers(endpoint) ?? {}) }; } catch (cause) { throw unavailableError('Could not authenticate with the OpenCode shared service', cause); }
|
|
112
60
|
let info;
|
|
113
|
-
try {
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
} catch (cause) {
|
|
119
|
-
throw unavailableError('Could not reach the OpenCode shared service', cause);
|
|
120
|
-
}
|
|
121
|
-
if (!info) {
|
|
122
|
-
throw unavailableError('OpenCode shared service did not return valid service information');
|
|
123
|
-
}
|
|
124
|
-
if (!isSupportedVersion(info.version)) {
|
|
125
|
-
throw createConnectionError(
|
|
126
|
-
'OPENCODE_INCOMPATIBLE',
|
|
127
|
-
`OpenCode shared service version ${info.version} is incompatible`,
|
|
128
|
-
{ foundVersion: info.version },
|
|
129
|
-
);
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
return {
|
|
133
|
-
kind: 'shared-local',
|
|
134
|
-
endpoint,
|
|
135
|
-
version: info.version,
|
|
136
|
-
};
|
|
61
|
+
try { info = await readInfo(await fetchImpl(new URL('/api/info', endpoint.url), { headers: { Accept: 'application/json', ...headers } })); }
|
|
62
|
+
catch (cause) { throw unavailableError('Could not reach the OpenCode shared service', cause); }
|
|
63
|
+
if (!info) throw unavailableError('OpenCode shared service did not return valid service information');
|
|
64
|
+
if (!isSupportedVersion(info.version)) throw createConnectionError('OPENCODE_INCOMPATIBLE', `OpenCode shared service version ${info.version} is incompatible`, { foundVersion: info.version });
|
|
65
|
+
return { kind: 'shared-local', endpoint, version: info.version };
|
|
137
66
|
};
|
|
138
|
-
|
|
139
|
-
const establishConnection = async () => {
|
|
140
|
-
const replacement = await probe(await resolveEndpoint());
|
|
141
|
-
activeConnection = replacement;
|
|
142
|
-
return replacement;
|
|
143
|
-
};
|
|
144
|
-
|
|
67
|
+
const establishConnection = async () => { const replacement = await probe(await resolveEndpoint()); activeConnection = replacement; return replacement; };
|
|
145
68
|
return {
|
|
146
|
-
connect: establishConnection,
|
|
147
|
-
recover: establishConnection,
|
|
148
|
-
getConnection: () => activeConnection,
|
|
69
|
+
connect: establishConnection, recover: establishConnection, getConnection: () => activeConnection,
|
|
149
70
|
getBaseUrl: () => activeConnection?.endpoint.url ?? null,
|
|
150
71
|
getHeaders: () => activeConnection ? { ...(service.headers(activeConnection.endpoint) ?? {}) } : {},
|
|
151
|
-
dispose: async () => {
|
|
152
|
-
activeConnection = null;
|
|
153
|
-
},
|
|
72
|
+
dispose: async () => { activeConnection = null; },
|
|
154
73
|
};
|
|
155
74
|
};
|
|
@@ -87,7 +87,14 @@ function sanitizeFrontmatter(frontmatter) {
|
|
|
87
87
|
}
|
|
88
88
|
|
|
89
89
|
function parseMdFile(filePath) {
|
|
90
|
-
|
|
90
|
+
return parseMdContent(fs.readFileSync(filePath, 'utf8'), filePath);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
async function parseMdFileAsync(filePath) {
|
|
94
|
+
return parseMdContent(await fs.promises.readFile(filePath, 'utf8'), filePath);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function parseMdContent(rawContent, filePath) {
|
|
91
98
|
// Strip a UTF-8 BOM so frontmatter is recognized regardless of the editor
|
|
92
99
|
// that saved the file.
|
|
93
100
|
const content = rawContent.charCodeAt(0) === 0xfeff ? rawContent.slice(1) : rawContent;
|
|
@@ -119,16 +126,19 @@ function parseMdFile(filePath) {
|
|
|
119
126
|
return { frontmatter, body };
|
|
120
127
|
}
|
|
121
128
|
|
|
122
|
-
|
|
129
|
+
// `flag: 'wx'` creates the file and fails with EEXIST when it is already
|
|
130
|
+
// there; that error is passed on as is so a caller can tell it apart.
|
|
131
|
+
function writeMdFile(filePath, frontmatter, body, { flag = 'w' } = {}) {
|
|
123
132
|
try {
|
|
124
133
|
const cleanedFrontmatter = Object.fromEntries(
|
|
125
134
|
Object.entries(frontmatter).filter(([, value]) => value != null)
|
|
126
135
|
);
|
|
127
136
|
const yamlStr = yaml.stringify(cleanedFrontmatter);
|
|
128
137
|
const content = `---\n${yamlStr}---\n\n${body}`;
|
|
129
|
-
fs.writeFileSync(filePath, content, 'utf8');
|
|
138
|
+
fs.writeFileSync(filePath, content, { encoding: 'utf8', flag });
|
|
130
139
|
console.log(`Successfully wrote markdown file: ${filePath}`);
|
|
131
140
|
} catch (error) {
|
|
141
|
+
if (error?.code === 'EEXIST') throw error;
|
|
132
142
|
console.error(`Failed to write markdown file ${filePath}:`, error);
|
|
133
143
|
throw new Error('Failed to write agent markdown file');
|
|
134
144
|
}
|
|
@@ -703,34 +713,62 @@ function writePromptFile(filePath, content) {
|
|
|
703
713
|
|
|
704
714
|
// ============== SKILL FILE OPERATIONS ==============
|
|
705
715
|
|
|
706
|
-
function
|
|
707
|
-
|
|
716
|
+
async function pathExists(target) {
|
|
717
|
+
try {
|
|
718
|
+
await fs.promises.access(target);
|
|
719
|
+
return true;
|
|
720
|
+
} catch {
|
|
721
|
+
return false;
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
// At most this many file-system calls of one walk are in flight at once.
|
|
726
|
+
const SKILL_WALK_CONCURRENCY = 8;
|
|
727
|
+
|
|
728
|
+
// Async so a skills tree with tens of thousands of entries (a bundled `.venv`
|
|
729
|
+
// or `node_modules`) does not hold the server's event loop for seconds.
|
|
730
|
+
// Sibling directories are read in parallel, a few calls at a time, and their
|
|
731
|
+
// results are joined in readdir order, so the order matches the old
|
|
732
|
+
// synchronous depth-first walk exactly.
|
|
733
|
+
async function walkSkillMdFiles(rootDir) {
|
|
734
|
+
if (!rootDir || !(await pathExists(rootDir))) return [];
|
|
708
735
|
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
736
|
+
let active = 0;
|
|
737
|
+
const waiting = [];
|
|
738
|
+
const limited = async (call) => {
|
|
739
|
+
if (active >= SKILL_WALK_CONCURRENCY) await new Promise((resolve) => waiting.push(resolve));
|
|
740
|
+
active += 1;
|
|
741
|
+
try {
|
|
742
|
+
return await call();
|
|
743
|
+
} finally {
|
|
744
|
+
active -= 1;
|
|
745
|
+
waiting.shift()?.();
|
|
746
|
+
}
|
|
747
|
+
};
|
|
748
|
+
|
|
749
|
+
// `ancestors` holds the real paths of the directories on the path to `dir`.
|
|
750
|
+
// Links (symlinks and Windows junctions) are followed at any depth; a link
|
|
751
|
+
// back to one of its own ancestors is skipped instead of recursing forever.
|
|
752
|
+
// Two links to the same target elsewhere in the tree are both walked, as the
|
|
753
|
+
// top level always did.
|
|
754
|
+
const walk = async (dir, ancestors) => {
|
|
716
755
|
let realDir;
|
|
717
756
|
try {
|
|
718
|
-
realDir = fs.
|
|
757
|
+
realDir = await limited(() => fs.promises.realpath(dir));
|
|
719
758
|
} catch {
|
|
720
|
-
return;
|
|
759
|
+
return [];
|
|
721
760
|
}
|
|
722
|
-
if (ancestors.has(realDir)) return;
|
|
761
|
+
if (ancestors.has(realDir)) return [];
|
|
723
762
|
|
|
724
763
|
let entries = [];
|
|
725
764
|
try {
|
|
726
|
-
entries = fs.
|
|
765
|
+
entries = await limited(() => fs.promises.readdir(dir, { withFileTypes: true }));
|
|
727
766
|
} catch {
|
|
728
|
-
return;
|
|
767
|
+
return [];
|
|
729
768
|
}
|
|
730
769
|
|
|
731
|
-
ancestors.add(realDir);
|
|
732
|
-
|
|
733
|
-
for (const entry of entries) {
|
|
770
|
+
const childAncestors = new Set(ancestors).add(realDir);
|
|
771
|
+
const found = await Promise.all(entries.map(async (entry) => {
|
|
734
772
|
const fullPath = path.join(dir, entry.name);
|
|
735
773
|
// Junctions report as links, not directories. A link whose target cannot be
|
|
736
774
|
// stat'ed is skipped, the way an unreadable directory is, instead of failing
|
|
@@ -739,33 +777,26 @@ function walkSkillMdFiles(rootDir) {
|
|
|
739
777
|
let isFileEntry = entry.isFile();
|
|
740
778
|
if (entry.isSymbolicLink()) {
|
|
741
779
|
try {
|
|
742
|
-
const target = fs.
|
|
780
|
+
const target = await limited(() => fs.promises.stat(fullPath));
|
|
743
781
|
isDirectoryEntry = target.isDirectory();
|
|
744
782
|
isFileEntry = target.isFile();
|
|
745
783
|
} catch {
|
|
746
|
-
|
|
784
|
+
return [];
|
|
747
785
|
}
|
|
748
786
|
}
|
|
749
|
-
if (isDirectoryEntry)
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
if (isFileEntry && entry.name === 'SKILL.md') {
|
|
754
|
-
results.push(fullPath);
|
|
755
|
-
}
|
|
756
|
-
}
|
|
757
|
-
ancestors.delete(realDir);
|
|
787
|
+
if (isDirectoryEntry) return walk(fullPath, childAncestors);
|
|
788
|
+
return isFileEntry && entry.name === 'SKILL.md' ? [fullPath] : [];
|
|
789
|
+
}));
|
|
790
|
+
return found.flat();
|
|
758
791
|
};
|
|
759
792
|
|
|
760
|
-
walk(rootDir);
|
|
761
|
-
return results;
|
|
793
|
+
return walk(rootDir, new Set());
|
|
762
794
|
}
|
|
763
795
|
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
} catch {
|
|
796
|
+
// `parsed` is what `parseMdFileAsync(skillMdPath)` resolved to, or null when
|
|
797
|
+
// the file could not be read; an unreadable file adds nothing.
|
|
798
|
+
function addSkillFromMdFile(skillsMap, skillMdPath, parsed, scope, source) {
|
|
799
|
+
if (!parsed) {
|
|
769
800
|
return;
|
|
770
801
|
}
|
|
771
802
|
|
|
@@ -818,21 +849,21 @@ function resolveSkillSearchDirectories(workingDirectory) {
|
|
|
818
849
|
return directories;
|
|
819
850
|
}
|
|
820
851
|
|
|
821
|
-
function listSkillSupportingFiles(skillDir) {
|
|
822
|
-
if (!
|
|
852
|
+
async function listSkillSupportingFiles(skillDir) {
|
|
853
|
+
if (!(await pathExists(skillDir))) {
|
|
823
854
|
return [];
|
|
824
855
|
}
|
|
825
856
|
|
|
826
857
|
const files = [];
|
|
827
858
|
|
|
828
|
-
function walkDir(dir, relativePath = '') {
|
|
829
|
-
const entries = fs.
|
|
859
|
+
async function walkDir(dir, relativePath = '') {
|
|
860
|
+
const entries = await fs.promises.readdir(dir, { withFileTypes: true });
|
|
830
861
|
for (const entry of entries) {
|
|
831
862
|
const fullPath = path.join(dir, entry.name);
|
|
832
863
|
const relPath = relativePath ? path.join(relativePath, entry.name) : entry.name;
|
|
833
864
|
|
|
834
865
|
if (entry.isDirectory()) {
|
|
835
|
-
walkDir(fullPath, relPath);
|
|
866
|
+
await walkDir(fullPath, relPath);
|
|
836
867
|
} else if (entry.name !== 'SKILL.md') {
|
|
837
868
|
files.push({
|
|
838
869
|
name: entry.name,
|
|
@@ -843,7 +874,7 @@ function listSkillSupportingFiles(skillDir) {
|
|
|
843
874
|
}
|
|
844
875
|
}
|
|
845
876
|
|
|
846
|
-
walkDir(skillDir);
|
|
877
|
+
await walkDir(skillDir);
|
|
847
878
|
return files;
|
|
848
879
|
}
|
|
849
880
|
|
|
@@ -910,6 +941,7 @@ export {
|
|
|
910
941
|
SKILL_SCOPE,
|
|
911
942
|
ensureDirs,
|
|
912
943
|
parseMdFile,
|
|
944
|
+
parseMdFileAsync,
|
|
913
945
|
writeMdFile,
|
|
914
946
|
readConfigFile,
|
|
915
947
|
readConfigLayer,
|
|
@@ -919,7 +951,6 @@ export {
|
|
|
919
951
|
readWorktreeDirectorySetting,
|
|
920
952
|
getConfigForPath,
|
|
921
953
|
writeConfig,
|
|
922
|
-
lookupSectionEntry,
|
|
923
954
|
getJsonEntrySource,
|
|
924
955
|
getJsonWriteTarget,
|
|
925
956
|
getAncestors,
|
|
@@ -933,5 +964,5 @@ export {
|
|
|
933
964
|
listSkillSupportingFiles,
|
|
934
965
|
readSkillSupportingFile,
|
|
935
966
|
writeSkillSupportingFile,
|
|
936
|
-
deleteSkillSupportingFile
|
|
967
|
+
deleteSkillSupportingFile
|
|
937
968
|
};
|
|
@@ -404,19 +404,19 @@ describe('walkSkillMdFiles', () => {
|
|
|
404
404
|
// the type argument is ignored on POSIX.
|
|
405
405
|
const linkDirectory = (target, relativeLink) =>
|
|
406
406
|
fs.symlinkSync(target, path.join(FIXTURE_DIR, relativeLink), process.platform === 'win32' ? 'junction' : 'dir');
|
|
407
|
-
const foundRelative = () =>
|
|
408
|
-
walkSkillMdFiles(FIXTURE_DIR)
|
|
407
|
+
const foundRelative = async () =>
|
|
408
|
+
(await walkSkillMdFiles(FIXTURE_DIR))
|
|
409
409
|
.map((found) => path.relative(FIXTURE_DIR, found).split(path.sep).join('/'))
|
|
410
410
|
.sort();
|
|
411
411
|
|
|
412
|
-
it('walks a skill deployed as a link inside the scanned root', () => {
|
|
412
|
+
it('walks a skill deployed as a link inside the scanned root', async () => {
|
|
413
413
|
writeSkill('real-skill');
|
|
414
414
|
fs.mkdirSync(path.join(FIXTURE_DIR, 'collection'), { recursive: true });
|
|
415
415
|
writeSkill(path.join('collection', 'nested-skill'));
|
|
416
416
|
linkDirectory(path.join(FIXTURE_DIR, 'real-skill'), 'linked-skill');
|
|
417
417
|
linkDirectory(path.join(FIXTURE_DIR, 'collection'), 'collection-link');
|
|
418
418
|
|
|
419
|
-
expect(foundRelative()).toEqual([
|
|
419
|
+
expect(await foundRelative()).toEqual([
|
|
420
420
|
'collection-link/nested-skill/SKILL.md',
|
|
421
421
|
'collection/nested-skill/SKILL.md',
|
|
422
422
|
'linked-skill/SKILL.md',
|
|
@@ -424,24 +424,24 @@ describe('walkSkillMdFiles', () => {
|
|
|
424
424
|
]);
|
|
425
425
|
});
|
|
426
426
|
|
|
427
|
-
it('ends on a link that points back into the scanned tree', () => {
|
|
427
|
+
it('ends on a link that points back into the scanned tree', async () => {
|
|
428
428
|
fs.mkdirSync(path.join(FIXTURE_DIR, 'loopdir'), { recursive: true });
|
|
429
429
|
writeSkill('loopdir');
|
|
430
430
|
linkDirectory(FIXTURE_DIR, path.join('loopdir', 'back'));
|
|
431
431
|
|
|
432
|
-
expect(foundRelative()).toEqual(['loopdir/SKILL.md']);
|
|
432
|
+
expect(await foundRelative()).toEqual(['loopdir/SKILL.md']);
|
|
433
433
|
});
|
|
434
434
|
|
|
435
|
-
it('skips a link whose target is gone and keeps the rest of the scan', () => {
|
|
435
|
+
it('skips a link whose target is gone and keeps the rest of the scan', async () => {
|
|
436
436
|
writeSkill('real-skill');
|
|
437
437
|
fs.mkdirSync(path.join(FIXTURE_DIR, 'gone-skill'), { recursive: true });
|
|
438
438
|
linkDirectory(path.join(FIXTURE_DIR, 'gone-skill'), 'dangling-link');
|
|
439
439
|
fs.rmSync(path.join(FIXTURE_DIR, 'gone-skill'), { recursive: true, force: true });
|
|
440
440
|
|
|
441
|
-
expect(foundRelative()).toEqual(['real-skill/SKILL.md']);
|
|
441
|
+
expect(await foundRelative()).toEqual(['real-skill/SKILL.md']);
|
|
442
442
|
});
|
|
443
443
|
|
|
444
|
-
it('follows a link nested below the top level of the scanned root', () => {
|
|
444
|
+
it('follows a link nested below the top level of the scanned root', async () => {
|
|
445
445
|
const outside = `${FIXTURE_DIR}-outside`;
|
|
446
446
|
fs.rmSync(outside, { recursive: true, force: true });
|
|
447
447
|
fs.mkdirSync(path.join(outside, 'deep-skill'), { recursive: true });
|
|
@@ -449,20 +449,20 @@ describe('walkSkillMdFiles', () => {
|
|
|
449
449
|
fs.mkdirSync(path.join(FIXTURE_DIR, 'group'), { recursive: true });
|
|
450
450
|
try {
|
|
451
451
|
linkDirectory(path.join(outside, 'deep-skill'), path.join('group', 'linked'));
|
|
452
|
-
expect(foundRelative()).toEqual(['group/linked/SKILL.md']);
|
|
452
|
+
expect(await foundRelative()).toEqual(['group/linked/SKILL.md']);
|
|
453
453
|
} finally {
|
|
454
454
|
fs.rmSync(outside, { recursive: true, force: true });
|
|
455
455
|
}
|
|
456
456
|
});
|
|
457
457
|
|
|
458
|
-
it('ends on a nested link loop between two directories', () => {
|
|
458
|
+
it('ends on a nested link loop between two directories', async () => {
|
|
459
459
|
fs.mkdirSync(path.join(FIXTURE_DIR, 'a'), { recursive: true });
|
|
460
460
|
fs.mkdirSync(path.join(FIXTURE_DIR, 'b'), { recursive: true });
|
|
461
461
|
writeSkill('a');
|
|
462
462
|
linkDirectory(path.join(FIXTURE_DIR, 'b'), path.join('a', 'to-b'));
|
|
463
463
|
linkDirectory(path.join(FIXTURE_DIR, 'a'), path.join('b', 'to-a'));
|
|
464
464
|
|
|
465
|
-
expect(foundRelative()).toEqual(['a/SKILL.md', 'b/to-a/SKILL.md']);
|
|
465
|
+
expect(await foundRelative()).toEqual(['a/SKILL.md', 'b/to-a/SKILL.md']);
|
|
466
466
|
});
|
|
467
467
|
});
|
|
468
468
|
|
|
@@ -67,8 +67,7 @@ describe('graceful shutdown runtime', () => {
|
|
|
67
67
|
const runtime = createRuntime(server);
|
|
68
68
|
await runtime.gracefulShutdown({ exitProcess: false });
|
|
69
69
|
|
|
70
|
-
vi.advanceTimersByTime(1000);
|
|
71
|
-
await Promise.resolve();
|
|
70
|
+
await vi.advanceTimersByTime(1000);
|
|
72
71
|
|
|
73
72
|
expect(warnSpy).not.toHaveBeenCalledWith('Server close timeout reached, forcing shutdown');
|
|
74
73
|
expect(vi.getTimerCount()).toBe(0);
|
|
@@ -317,7 +316,7 @@ describe('graceful shutdown runtime', () => {
|
|
|
317
316
|
await first;
|
|
318
317
|
await runtime.gracefulShutdown();
|
|
319
318
|
expect(order).toEqual(['gate', 'viewers', 'proxy', 'relay', 'dictation', 'guests']);
|
|
320
|
-
await vi.
|
|
319
|
+
await vi.advanceTimersByTime(200);
|
|
321
320
|
expect(reconcile).not.toHaveBeenCalled();
|
|
322
321
|
expect(vi.getTimerCount()).toBe(0);
|
|
323
322
|
});
|