@toddzheng024/dscode-desktop 0.0.0-stage → 0.7.34
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/LICENSE +21 -0
- package/README.md +120 -2
- package/THIRD_PARTY_NOTICES.md +30 -0
- package/bin/apply_patch +9 -0
- package/cordis.patch.yml +433 -0
- package/docs/CHANGELOG.md +649 -0
- package/docs/account-login.md +44 -0
- package/docs/auto-review.md +128 -0
- package/docs/browser-use.md +784 -0
- package/docs/computer-use.md +81 -0
- package/docs/custom-providers.md +88 -0
- package/docs/demo.md +158 -0
- package/docs/distribution.md +58 -0
- package/docs/dscode-ultra.md +75 -0
- package/docs/email.md +296 -0
- package/docs/exec.md +40 -0
- package/docs/hub-distribution.md +212 -0
- package/docs/memory.md +121 -0
- package/docs/opencode-go.md +61 -0
- package/docs/plugin-hub.md +68 -0
- package/docs/releases/0.2.0.md +28 -0
- package/docs/releases/0.3.0.md +21 -0
- package/docs/releases/0.4.0.md +20 -0
- package/docs/releases/0.5.0.md +19 -0
- package/docs/releases/0.6.0.md +20 -0
- package/docs/releases/0.7.0.md +22 -0
- package/docs/releases/0.7.1.md +20 -0
- package/docs/releases/0.7.10.md +10 -0
- package/docs/releases/0.7.11.md +17 -0
- package/docs/releases/0.7.12.md +11 -0
- package/docs/releases/0.7.13.md +12 -0
- package/docs/releases/0.7.14.md +11 -0
- package/docs/releases/0.7.15.md +11 -0
- package/docs/releases/0.7.16.md +10 -0
- package/docs/releases/0.7.17.md +12 -0
- package/docs/releases/0.7.18.md +13 -0
- package/docs/releases/0.7.19.md +8 -0
- package/docs/releases/0.7.2.md +19 -0
- package/docs/releases/0.7.20.md +10 -0
- package/docs/releases/0.7.21.md +9 -0
- package/docs/releases/0.7.22.md +11 -0
- package/docs/releases/0.7.23.md +14 -0
- package/docs/releases/0.7.24.md +11 -0
- package/docs/releases/0.7.25.md +8 -0
- package/docs/releases/0.7.26.md +18 -0
- package/docs/releases/0.7.27.md +8 -0
- package/docs/releases/0.7.28.md +22 -0
- package/docs/releases/0.7.29.md +12 -0
- package/docs/releases/0.7.3.md +23 -0
- package/docs/releases/0.7.30.md +19 -0
- package/docs/releases/0.7.31.md +14 -0
- package/docs/releases/0.7.32.md +14 -0
- package/docs/releases/0.7.33.md +37 -0
- package/docs/releases/0.7.34.md +24 -0
- package/docs/releases/0.7.4.md +16 -0
- package/docs/releases/0.7.5.md +18 -0
- package/docs/releases/0.7.6.md +29 -0
- package/docs/releases/0.7.7.md +36 -0
- package/docs/releases/0.7.8.md +14 -0
- package/docs/releases/0.7.9.md +15 -0
- package/docs/session-bridge.md +80 -0
- package/docs/session-cards.md +53 -0
- package/docs/session-communication.md +186 -0
- package/docs/session-metrics.md +41 -0
- package/docs/skills.md +81 -0
- package/docs/triggers.md +338 -0
- package/docs/tui-commands.md +204 -0
- package/extensions/browser/manifest.json +22 -0
- package/extensions/browser/popup.css +6 -0
- package/extensions/browser/popup.html +11 -0
- package/extensions/browser/popup.mjs +47 -0
- package/extensions/browser/protocol.mjs +168 -0
- package/extensions/browser/worker.mjs +94 -0
- package/icon.svg +7 -0
- package/locale/en.json +6 -0
- package/locale/zh-cn.json +6 -0
- package/node_modules/@deepseek-ai/node-addon-system/LICENSE +21 -0
- package/node_modules/@deepseek-ai/node-addon-system/README.i18n.yaml +6 -0
- package/node_modules/@deepseek-ai/node-addon-system/README.md +15 -0
- package/node_modules/@deepseek-ai/node-addon-system/README.zh.md +15 -0
- package/node_modules/@deepseek-ai/node-addon-system/lib/flock.d.ts +13 -0
- package/node_modules/@deepseek-ai/node-addon-system/lib/flock.js +51 -0
- package/node_modules/@deepseek-ai/node-addon-system/lib/index.d.ts +73 -0
- package/node_modules/@deepseek-ai/node-addon-system/lib/index.js +98 -0
- package/node_modules/@deepseek-ai/node-addon-system/package.json +45 -0
- package/node_modules/@deepseek-ai/node-addon-system/src/flock.c +164 -0
- package/node_modules/@deepseek-ai/node-addon-system/src/main.c +298 -0
- package/node_modules/@deepseek-ai/node-addon-system-darwin-arm64/LICENSE +28 -0
- package/node_modules/@deepseek-ai/node-addon-system-darwin-arm64/README.i18n.yaml +6 -0
- package/node_modules/@deepseek-ai/node-addon-system-darwin-arm64/README.md +9 -0
- package/node_modules/@deepseek-ai/node-addon-system-darwin-arm64/README.zh.md +9 -0
- package/node_modules/@deepseek-ai/node-addon-system-darwin-arm64/bin/system.node +0 -0
- package/node_modules/@deepseek-ai/node-addon-system-darwin-arm64/package.json +31 -0
- package/node_modules/@deepseek-ai/node-addon-system-darwin-arm64/prebuilds.json +6 -0
- package/node_modules/@deepseek-ai/node-addon-system-darwin-x64/LICENSE +28 -0
- package/node_modules/@deepseek-ai/node-addon-system-darwin-x64/README.i18n.yaml +6 -0
- package/node_modules/@deepseek-ai/node-addon-system-darwin-x64/README.md +9 -0
- package/node_modules/@deepseek-ai/node-addon-system-darwin-x64/README.zh.md +9 -0
- package/node_modules/@deepseek-ai/node-addon-system-darwin-x64/bin/system.node +0 -0
- package/node_modules/@deepseek-ai/node-addon-system-darwin-x64/package.json +31 -0
- package/node_modules/@deepseek-ai/node-addon-system-darwin-x64/prebuilds.json +6 -0
- package/node_modules/@deepseek-ai/node-addon-system-linux-arm64/LICENSE +28 -0
- package/node_modules/@deepseek-ai/node-addon-system-linux-arm64/README.i18n.yaml +6 -0
- package/node_modules/@deepseek-ai/node-addon-system-linux-arm64/README.md +11 -0
- package/node_modules/@deepseek-ai/node-addon-system-linux-arm64/README.zh.md +11 -0
- package/node_modules/@deepseek-ai/node-addon-system-linux-arm64/bin/glibc/system.node +0 -0
- package/node_modules/@deepseek-ai/node-addon-system-linux-arm64/bin/landlock-run +0 -0
- package/node_modules/@deepseek-ai/node-addon-system-linux-arm64/bin/musl/system.node +0 -0
- package/node_modules/@deepseek-ai/node-addon-system-linux-arm64/package.json +31 -0
- package/node_modules/@deepseek-ai/node-addon-system-linux-arm64/prebuilds.json +24 -0
- package/node_modules/@deepseek-ai/node-addon-system-linux-x64/LICENSE +28 -0
- package/node_modules/@deepseek-ai/node-addon-system-linux-x64/README.i18n.yaml +6 -0
- package/node_modules/@deepseek-ai/node-addon-system-linux-x64/README.md +11 -0
- package/node_modules/@deepseek-ai/node-addon-system-linux-x64/README.zh.md +11 -0
- package/node_modules/@deepseek-ai/node-addon-system-linux-x64/bin/glibc/system.node +0 -0
- package/node_modules/@deepseek-ai/node-addon-system-linux-x64/bin/landlock-run +0 -0
- package/node_modules/@deepseek-ai/node-addon-system-linux-x64/bin/musl/system.node +0 -0
- package/node_modules/@deepseek-ai/node-addon-system-linux-x64/package.json +31 -0
- package/node_modules/@deepseek-ai/node-addon-system-linux-x64/prebuilds.json +24 -0
- package/package.json +156 -4
- package/plugins/account/index.mjs +178 -0
- package/plugins/account/state.mjs +123 -0
- package/plugins/auto-review/audit.mjs +24 -0
- package/plugins/auto-review/index.mjs +267 -0
- package/plugins/auto-review/policy.mjs +92 -0
- package/plugins/browser/SKILL.md +158 -0
- package/plugins/browser/access.mjs +143 -0
- package/plugins/browser/config.mjs +60 -0
- package/plugins/browser/connection.mjs +385 -0
- package/plugins/browser/desktop-client.mjs +282 -0
- package/plugins/browser/desktop-host.mjs +74 -0
- package/plugins/browser/document-identity.mjs +57 -0
- package/plugins/browser/extension-relay.mjs +66 -0
- package/plugins/browser/files.mjs +32 -0
- package/plugins/browser/index.mjs +235 -0
- package/plugins/browser/mcp-entry.mjs +18 -0
- package/plugins/browser/mcp-tools.mjs +21 -0
- package/plugins/browser/presentation.mjs +45 -0
- package/plugins/browser/preview.mjs +77 -0
- package/plugins/browser/review.mjs +20 -0
- package/plugins/browser/screenshots.mjs +35 -0
- package/plugins/clipboard-image/clipboard-image.swift +56 -0
- package/plugins/clipboard-image/index.mjs +70 -0
- package/plugins/code-review/baseline.mjs +143 -0
- package/plugins/code-review/git.mjs +163 -0
- package/plugins/code-review/index.mjs +236 -0
- package/plugins/compaction/engine.mjs +304 -0
- package/plugins/compaction/tetris.mjs +65 -0
- package/plugins/compaction/threshold.mjs +99 -0
- package/plugins/computer-use/DESKTOP-SKILL.md +64 -0
- package/plugins/computer-use/desktop-host.mjs +75 -0
- package/plugins/computer-use/desktop-skill.mjs +28 -0
- package/plugins/computer-use/desktop-upstream.mjs +3 -0
- package/plugins/computer-use/index.mjs +37 -0
- package/plugins/cordis-config/plain.mjs +31 -0
- package/plugins/credentials/index.mjs +73 -0
- package/plugins/custom/adapter.mjs +110 -0
- package/plugins/custom/config.mjs +85 -0
- package/plugins/custom/desktop-client.mjs +150 -0
- package/plugins/custom/desktop-host.mjs +78 -0
- package/plugins/custom/images.mjs +32 -0
- package/plugins/custom/index.mjs +145 -0
- package/plugins/custom/wire.mjs +179 -0
- package/plugins/desktop/client.mjs +1041 -0
- package/plugins/desktop/index.mjs +10 -0
- package/plugins/desktop/shell-environment.mjs +9 -0
- package/plugins/desktop-workspace/hooks.mjs +29 -0
- package/plugins/desktop-workspace/index.mjs +37 -0
- package/plugins/dscode/board.mjs +260 -0
- package/plugins/dscode/child-target.mjs +11 -0
- package/plugins/dscode/control.mjs +17 -0
- package/plugins/dscode/desktop-client.mjs +55 -0
- package/plugins/dscode/desktop-host.mjs +37 -0
- package/plugins/dscode/index.mjs +270 -0
- package/plugins/email/cli.mjs +32 -0
- package/plugins/email/contacts.mjs +36 -0
- package/plugins/email/desktop-client.mjs +117 -0
- package/plugins/email/desktop-host.mjs +54 -0
- package/plugins/email/desktop-service.mjs +106 -0
- package/plugins/email/gmail-oauth.mjs +69 -0
- package/plugins/email/gmail-store.mjs +2 -0
- package/plugins/email/gmail.mjs +194 -0
- package/plugins/email/imap.mjs +136 -0
- package/plugins/email/inbox.d.mts +25 -0
- package/plugins/email/inbox.mjs +76 -0
- package/plugins/email/smtp.mjs +70 -0
- package/plugins/email/store.mjs +32 -0
- package/plugins/email-tools/index.mjs +46 -0
- package/plugins/exec/cli.mjs +64 -0
- package/plugins/exec/index.mjs +112 -0
- package/plugins/grok/adapter.mjs +114 -0
- package/plugins/grok/auth.mjs +76 -0
- package/plugins/grok/billing.mjs +147 -0
- package/plugins/grok/index.mjs +123 -0
- package/plugins/grok/models.mjs +129 -0
- package/plugins/grok/status.mjs +29 -0
- package/plugins/grok/wire.mjs +268 -0
- package/plugins/hub/catalog.mjs +82 -0
- package/plugins/hub/desktop-client.mjs +114 -0
- package/plugins/hub/desktop-host.mjs +129 -0
- package/plugins/i18n/messages.d.mts +21 -0
- package/plugins/i18n/messages.mjs +537 -0
- package/plugins/jev/approval.mjs +131 -0
- package/plugins/jev/client.mjs +74 -0
- package/plugins/jev/index.mjs +100 -0
- package/plugins/memory/content.mjs +57 -0
- package/plugins/memory/desktop-host.mjs +3 -0
- package/plugins/memory/index.mjs +168 -0
- package/plugins/memory/pipeline.mjs +79 -0
- package/plugins/memory/store.mjs +93 -0
- package/plugins/message-source/kind.mjs +20 -0
- package/plugins/opencode-go/adapter.mjs +96 -0
- package/plugins/opencode-go/command.mjs +128 -0
- package/plugins/opencode-go/index.mjs +121 -0
- package/plugins/opencode-go/models.mjs +58 -0
- package/plugins/opencode-go/oauth.mjs +194 -0
- package/plugins/opencode-go/search.mjs +86 -0
- package/plugins/opencode-go/usage.mjs +120 -0
- package/plugins/opencode-go/version.mjs +10 -0
- package/plugins/opencode-go/wire.mjs +73 -0
- package/plugins/openrouter/adapter.mjs +232 -0
- package/plugins/openrouter/index.mjs +124 -0
- package/plugins/openrouter/models.mjs +157 -0
- package/plugins/openrouter/search.mjs +113 -0
- package/plugins/openrouter/wire.mjs +101 -0
- package/plugins/providers/catalog.mjs +160 -0
- package/plugins/providers/chat-messages.mjs +120 -0
- package/plugins/providers/chat-stream.mjs +174 -0
- package/plugins/providers/desktop-client.mjs +84 -0
- package/plugins/providers/desktop-host.mjs +63 -0
- package/plugins/providers/effort.mjs +35 -0
- package/plugins/providers/http-errors.mjs +50 -0
- package/plugins/providers/openrouter-account.mjs +171 -0
- package/plugins/session-bridge/client.mjs +106 -0
- package/plugins/session-bridge/communication.mjs +260 -0
- package/plugins/session-bridge/index.mjs +67 -0
- package/plugins/session-bridge/mailbox.mjs +267 -0
- package/plugins/session-bridge/paths.mjs +21 -0
- package/plugins/session-bridge/server.mjs +172 -0
- package/plugins/session-bridge/tasks.mjs +229 -0
- package/plugins/session-cards/content.mjs +64 -0
- package/plugins/session-cards/index.mjs +38 -0
- package/plugins/session-cards/manager.mjs +140 -0
- package/plugins/session-metrics/attribution.mjs +30 -0
- package/plugins/session-metrics/balance.mjs +81 -0
- package/plugins/session-metrics/desktop-client.mjs +62 -0
- package/plugins/session-metrics/desktop-host.mjs +46 -0
- package/plugins/session-metrics/index.mjs +97 -0
- package/plugins/session-metrics/pricing.mjs +84 -0
- package/plugins/session-metrics/rate.mjs +59 -0
- package/plugins/session-metrics/store.mjs +75 -0
- package/plugins/session-metrics/turns.mjs +134 -0
- package/plugins/session-metrics/view.mjs +272 -0
- package/plugins/time-marks/desktop-host.mjs +2 -0
- package/plugins/time-marks/index.mjs +116 -0
- package/plugins/time-marks/marks.mjs +152 -0
- package/plugins/triggers/cli.mjs +558 -0
- package/plugins/triggers/commands.mjs +143 -0
- package/plugins/triggers/config.mjs +264 -0
- package/plugins/triggers/desktop-client.mjs +155 -0
- package/plugins/triggers/desktop-host.mjs +88 -0
- package/plugins/triggers/desktop-management.mjs +97 -0
- package/plugins/triggers/desktop-scheduler.mjs +125 -0
- package/plugins/triggers/host.mjs +24 -0
- package/plugins/triggers/index.mjs +27 -0
- package/plugins/triggers/job-cli.mjs +110 -0
- package/plugins/triggers/jobs.mjs +156 -0
- package/plugins/triggers/launchd.mjs +101 -0
- package/plugins/triggers/lease.mjs +24 -0
- package/plugins/triggers/log.mjs +104 -0
- package/plugins/triggers/management.mjs +181 -0
- package/plugins/triggers/options.mjs +117 -0
- package/plugins/triggers/overlay.mjs +7 -0
- package/plugins/triggers/poll.mjs +65 -0
- package/plugins/triggers/run.mjs +157 -0
- package/plugins/triggers/schedule.mjs +40 -0
- package/plugins/triggers/scheduler-service.mjs +46 -0
- package/plugins/triggers/scheduler.mjs +92 -0
- package/plugins/triggers/session-run.mjs +125 -0
- package/plugins/triggers/session.mjs +48 -0
- package/plugins/triggers/source-emit.mjs +19 -0
- package/plugins/triggers/source-host.mjs +78 -0
- package/plugins/triggers/source-ingress.mjs +70 -0
- package/plugins/triggers/source-sandbox.mjs +35 -0
- package/plugins/triggers/sources.mjs +45 -0
- package/plugins/triggers/spool.mjs +145 -0
- package/plugins/triggers/tools.mjs +67 -0
- package/plugins/triggers/unattended.mjs +18 -0
- package/plugins/tui-tools/composition.mjs +28 -0
- package/plugins/tui-tools/desktop-host.mjs +2 -0
- package/plugins/tui-tools/doctor-cli.mjs +22 -0
- package/plugins/tui-tools/doctor.mjs +149 -0
- package/plugins/tui-tools/hook-sources.mjs +113 -0
- package/plugins/tui-tools/hooks.mjs +23 -0
- package/plugins/tui-tools/index.mjs +269 -0
- package/plugins/tui-tools/sandbox-runner.mjs +123 -0
- package/plugins/tui-tools/shell.mjs +27 -0
- package/plugins/tui-tools/update.mjs +111 -0
- package/plugins/tui-tools/workspace-discovery.mjs +129 -0
- package/plugins/ultra/policy.mjs +42 -0
- package/plugins/worktree-subagent/worktree.mjs +56 -0
- package/runtime-sources.json +94 -0
- package/vendor/bash/LICENSE +21 -0
- package/vendor/bash/index.js +717 -0
- package/vendor/bash/types/background.d.ts +50 -0
- package/vendor/bash/types/index.d.ts +38 -0
- package/vendor/bash/types/render.d.ts +57 -0
- package/vendor/command-goal/LICENSE +21 -0
- package/vendor/command-goal/index.js +210 -0
- package/vendor/command-goal/types/index.d.ts +10 -0
- package/vendor/computer-use/LICENSE +21 -0
- package/vendor/computer-use/lib/approval-policy.js +12 -0
- package/vendor/computer-use/lib/approval-policy.js.map +1 -0
- package/vendor/computer-use/lib/artifacts.js +79 -0
- package/vendor/computer-use/lib/artifacts.js.map +1 -0
- package/vendor/computer-use/lib/backend.js +3 -0
- package/vendor/computer-use/lib/backend.js.map +1 -0
- package/vendor/computer-use/lib/client.js +369 -0
- package/vendor/computer-use/lib/client.js.map +1 -0
- package/vendor/computer-use/lib/config.js +159 -0
- package/vendor/computer-use/lib/config.js.map +1 -0
- package/vendor/computer-use/lib/confirmations.js +99 -0
- package/vendor/computer-use/lib/confirmations.js.map +1 -0
- package/vendor/computer-use/lib/diff.js +58 -0
- package/vendor/computer-use/lib/diff.js.map +1 -0
- package/vendor/computer-use/lib/errors.js +22 -0
- package/vendor/computer-use/lib/errors.js.map +1 -0
- package/vendor/computer-use/lib/exposure.js +244 -0
- package/vendor/computer-use/lib/exposure.js.map +1 -0
- package/vendor/computer-use/lib/index.js +66 -0
- package/vendor/computer-use/lib/index.js.map +1 -0
- package/vendor/computer-use/lib/leases.js +262 -0
- package/vendor/computer-use/lib/leases.js.map +1 -0
- package/vendor/computer-use/lib/providers/macos.js +243 -0
- package/vendor/computer-use/lib/providers/macos.js.map +1 -0
- package/vendor/computer-use/lib/providers/native-helper.js +726 -0
- package/vendor/computer-use/lib/providers/native-helper.js.map +1 -0
- package/vendor/computer-use/lib/providers/unsupported.js +51 -0
- package/vendor/computer-use/lib/providers/unsupported.js.map +1 -0
- package/vendor/computer-use/lib/service.js +608 -0
- package/vendor/computer-use/lib/service.js.map +1 -0
- package/vendor/computer-use/lib/skill.js +136 -0
- package/vendor/computer-use/lib/skill.js.map +1 -0
- package/vendor/computer-use/lib/target-resolver.js +180 -0
- package/vendor/computer-use/lib/target-resolver.js.map +1 -0
- package/vendor/computer-use/lib/tools.js +511 -0
- package/vendor/computer-use/lib/tools.js.map +1 -0
- package/vendor/computer-use/lib/types/approval-policy.d.ts +13 -0
- package/vendor/computer-use/lib/types/approval-policy.d.ts.map +1 -0
- package/vendor/computer-use/lib/types/artifacts.d.ts +10 -0
- package/vendor/computer-use/lib/types/artifacts.d.ts.map +1 -0
- package/vendor/computer-use/lib/types/backend.d.ts +124 -0
- package/vendor/computer-use/lib/types/backend.d.ts.map +1 -0
- package/vendor/computer-use/lib/types/client/index.d.ts +83 -0
- package/vendor/computer-use/lib/types/client/index.d.ts.map +1 -0
- package/vendor/computer-use/lib/types/config.d.ts +94 -0
- package/vendor/computer-use/lib/types/config.d.ts.map +1 -0
- package/vendor/computer-use/lib/types/confirmations.d.ts +23 -0
- package/vendor/computer-use/lib/types/confirmations.d.ts.map +1 -0
- package/vendor/computer-use/lib/types/diff.d.ts +5 -0
- package/vendor/computer-use/lib/types/diff.d.ts.map +1 -0
- package/vendor/computer-use/lib/types/errors.d.ts +15 -0
- package/vendor/computer-use/lib/types/errors.d.ts.map +1 -0
- package/vendor/computer-use/lib/types/exposure.d.ts +30 -0
- package/vendor/computer-use/lib/types/exposure.d.ts.map +1 -0
- package/vendor/computer-use/lib/types/index.d.ts +21 -0
- package/vendor/computer-use/lib/types/index.d.ts.map +1 -0
- package/vendor/computer-use/lib/types/leases.d.ts +81 -0
- package/vendor/computer-use/lib/types/leases.d.ts.map +1 -0
- package/vendor/computer-use/lib/types/providers/macos.d.ts +39 -0
- package/vendor/computer-use/lib/types/providers/macos.d.ts.map +1 -0
- package/vendor/computer-use/lib/types/providers/native-helper.d.ts +48 -0
- package/vendor/computer-use/lib/types/providers/native-helper.d.ts.map +1 -0
- package/vendor/computer-use/lib/types/providers/unsupported.d.ts +23 -0
- package/vendor/computer-use/lib/types/providers/unsupported.d.ts.map +1 -0
- package/vendor/computer-use/lib/types/service.d.ts +58 -0
- package/vendor/computer-use/lib/types/service.d.ts.map +1 -0
- package/vendor/computer-use/lib/types/skill.d.ts +14 -0
- package/vendor/computer-use/lib/types/skill.d.ts.map +1 -0
- package/vendor/computer-use/lib/types/target-resolver.d.ts +38 -0
- package/vendor/computer-use/lib/types/target-resolver.d.ts.map +1 -0
- package/vendor/computer-use/lib/types/tools.d.ts +6 -0
- package/vendor/computer-use/lib/types/tools.d.ts.map +1 -0
- package/vendor/computer-use/lib/types/types.d.ts +270 -0
- package/vendor/computer-use/lib/types/types.d.ts.map +1 -0
- package/vendor/computer-use/lib/types/web.d.ts +33 -0
- package/vendor/computer-use/lib/types/web.d.ts.map +1 -0
- package/vendor/computer-use/lib/types.js +9 -0
- package/vendor/computer-use/lib/types.js.map +1 -0
- package/vendor/computer-use/lib/web.js +188 -0
- package/vendor/computer-use/lib/web.js.map +1 -0
- package/vendor/computer-use/native/macos/Sources/Fixture/main.swift +412 -0
- package/vendor/computer-use/native/macos/Sources/Helper/CursorImage.swift +11 -0
- package/vendor/computer-use/native/macos/Sources/Helper/CursorMotion.swift +67 -0
- package/vendor/computer-use/native/macos/Sources/Helper/CursorOverlay.swift +840 -0
- package/vendor/computer-use/native/macos/Sources/Helper/TargetedPointer.swift +327 -0
- package/vendor/computer-use/native/macos/Sources/Helper/WindowNumberMatcher.swift +29 -0
- package/vendor/computer-use/native/macos/Sources/Helper/main.swift +1244 -0
- package/vendor/computer-use/native/macos/Sources/Monitor/main.swift +153 -0
- package/vendor/computer-use/native/macos/bin/dsh-computer-use-helper +0 -0
- package/vendor/computer-use/native/macos/manifest.json +14 -0
- package/vendor/persistent/LICENSE +21 -0
- package/vendor/persistent/index.js +411 -0
- package/vendor/persistent/types/index.d.ts +24 -0
- package/vendor/subagent/LICENSE +21 -0
- package/vendor/subagent/index.js +694 -0
- package/vendor/subagent/invariant.js +52 -0
- package/vendor/subagent/model-selection-settings.js +68 -0
- package/vendor/subagent/types/index.d.ts +82 -0
- package/vendor/subagent/types/invariant.d.ts +16 -0
- package/vendor/subagent/types/list-models.d.ts +10 -0
- package/vendor/subagent/types/model-selection-settings.d.ts +45 -0
- package/vendor/subagent/types/model-selection-state.d.ts +48 -0
- package/vendor/subagent/types/model-selection.d.ts +81 -0
- package/vendor/subagent-core/LICENSE +21 -0
- package/vendor/subagent-core/index.js +3202 -0
- package/vendor/subagent-core/invariant.js +76 -0
- package/vendor/subagent-core/typert.host.d.ts +3 -0
- package/vendor/subagent-core/typert.host.js +978 -0
- package/vendor/subagent-core/typert.remote-client.d.ts +25 -0
- package/vendor/subagent-core/typert.remote-client.js +114 -0
- package/vendor/subagent-core/types/archive-admission.d.ts +16 -0
- package/vendor/subagent-core/types/archive-admission.js +151 -0
- package/vendor/subagent-core/types/assistant-output.d.ts +48 -0
- package/vendor/subagent-core/types/assistant-output.js +73 -0
- package/vendor/subagent-core/types/catalog.d.ts +84 -0
- package/vendor/subagent-core/types/catalog.js +109 -0
- package/vendor/subagent-core/types/child-agent.d.ts +156 -0
- package/vendor/subagent-core/types/child-agent.js +213 -0
- package/vendor/subagent-core/types/client.d.ts +8 -0
- package/vendor/subagent-core/types/client.js +7 -0
- package/vendor/subagent-core/types/continuation-activation.d.ts +267 -0
- package/vendor/subagent-core/types/continuation-activation.js +700 -0
- package/vendor/subagent-core/types/continuation-messages.d.ts +62 -0
- package/vendor/subagent-core/types/continuation-messages.js +106 -0
- package/vendor/subagent-core/types/continuation.d.ts +124 -0
- package/vendor/subagent-core/types/continuation.js +455 -0
- package/vendor/subagent-core/types/control-types.d.ts +135 -0
- package/vendor/subagent-core/types/control-types.js +8 -0
- package/vendor/subagent-core/types/control.d.ts +45 -0
- package/vendor/subagent-core/types/control.js +79 -0
- package/vendor/subagent-core/types/depth.d.ts +31 -0
- package/vendor/subagent-core/types/depth.js +39 -0
- package/vendor/subagent-core/types/descriptor.d.ts +144 -0
- package/vendor/subagent-core/types/descriptor.js +193 -0
- package/vendor/subagent-core/types/error.d.ts +11 -0
- package/vendor/subagent-core/types/error.js +14 -0
- package/vendor/subagent-core/types/inbox.d.ts +43 -0
- package/vendor/subagent-core/types/inbox.js +61 -0
- package/vendor/subagent-core/types/index.d.ts +320 -0
- package/vendor/subagent-core/types/index.js +475 -0
- package/vendor/subagent-core/types/internal.d.ts +58 -0
- package/vendor/subagent-core/types/internal.js +58 -0
- package/vendor/subagent-core/types/invariant.d.ts +13 -0
- package/vendor/subagent-core/types/invariant.js +91 -0
- package/vendor/subagent-core/types/lifecycle.d.ts +113 -0
- package/vendor/subagent-core/types/lifecycle.js +180 -0
- package/vendor/subagent-core/types/list-children.d.ts +36 -0
- package/vendor/subagent-core/types/list-children.js +166 -0
- package/vendor/subagent-core/types/out-of-process.d.ts +118 -0
- package/vendor/subagent-core/types/out-of-process.js +219 -0
- package/vendor/subagent-core/types/projection-types.d.ts +82 -0
- package/vendor/subagent-core/types/projection-types.js +7 -0
- package/vendor/subagent-core/types/projection.d.ts +100 -0
- package/vendor/subagent-core/types/projection.js +157 -0
- package/vendor/subagent-core/types/run-settlement.d.ts +17 -0
- package/vendor/subagent-core/types/run-settlement.js +70 -0
- package/vendor/subagent-core/types/types.d.ts +377 -0
- package/vendor/subagent-core/types/types.js +19 -0
- package/vendor/subagent-driver/LICENSE +21 -0
- package/vendor/subagent-driver/index.js +255 -0
- package/vendor/subagent-driver/types/index.d.ts +33 -0
- package/vendor/subagent-driver/types/structured.d.ts +42 -0
- package/vendor/subagent-fork/LICENSE +21 -0
- package/vendor/subagent-fork/index.js +61 -0
- package/vendor/subagent-fork/types/index.d.ts +20 -0
- package/vendor/subagent-spawn/LICENSE +21 -0
- package/vendor/subagent-spawn/index.js +45 -0
- package/vendor/subagent-spawn/types/index.d.ts +19 -0
- package/vendor/terminal/LICENSE +21 -0
- package/vendor/terminal/index.js +1093 -0
- package/vendor/terminal/types/config.d.ts +82 -0
- package/vendor/terminal/types/index.d.ts +36 -0
- package/vendor/terminal/types/sanitize.d.ts +47 -0
- package/vendor/terminal/types/session.d.ts +87 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en"><meta charset="utf-8"><title>DSCODE Browser</title>
|
|
3
|
+
<link rel="stylesheet" href="popup.css">
|
|
4
|
+
<body><h1>DSCODE Browser</h1>
|
|
5
|
+
<p>Share the current tab with a local DSCODE session. The agent can read and operate shared pages and create new tabs. Other existing tabs stay private.</p>
|
|
6
|
+
<label for="pairing">Pairing link</label><input id="pairing" type="password" autocomplete="off" spellcheck="false" placeholder="Paste from DSCODE">
|
|
7
|
+
<button id="pair">Connect and share this tab</button>
|
|
8
|
+
<button id="share" hidden>Share this tab too</button>
|
|
9
|
+
<button id="stop" hidden>Stop all sharing</button>
|
|
10
|
+
<p id="status" role="status"></p><ul id="tabs"></ul>
|
|
11
|
+
<script type="module" src="popup.mjs"></script></body></html>
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/* global chrome, document */
|
|
2
|
+
const element = id => document.getElementById(id);
|
|
3
|
+
let operation = 0;
|
|
4
|
+
async function run(action, background = false) {
|
|
5
|
+
const current = ++operation;
|
|
6
|
+
let pending = false;
|
|
7
|
+
if (!background) {
|
|
8
|
+
for (const id of ['pair', 'share']) element(id).disabled = true;
|
|
9
|
+
element('stop').disabled = action === 'stop';
|
|
10
|
+
}
|
|
11
|
+
if (action === 'pair') element('stop').hidden = false;
|
|
12
|
+
try {
|
|
13
|
+
const request = { action };
|
|
14
|
+
if (action === 'pair') request.url = element('pairing').value.trim();
|
|
15
|
+
if (action === 'pair' || action === 'share') {
|
|
16
|
+
const [tab] = await chrome.tabs.query({ active: true, lastFocusedWindow: true });
|
|
17
|
+
if (current !== operation) return;
|
|
18
|
+
request.tabId = tab?.id;
|
|
19
|
+
}
|
|
20
|
+
const result = await chrome.runtime.sendMessage(request);
|
|
21
|
+
if (current !== operation) return;
|
|
22
|
+
if (result.error) throw Error(result.error);
|
|
23
|
+
pending = !!result.pending;
|
|
24
|
+
element('status').textContent = result.message;
|
|
25
|
+
element('pair').hidden = result.connected;
|
|
26
|
+
element('pairing').hidden = result.connected;
|
|
27
|
+
element('share').hidden = !result.connected;
|
|
28
|
+
element('stop').hidden = !result.connected && !pending;
|
|
29
|
+
if (result.connected) element('pairing').value = '';
|
|
30
|
+
element('tabs').replaceChildren(...result.shared.map(tab => {
|
|
31
|
+
const item = document.createElement('li'); item.textContent = tab.title || tab.url; return item;
|
|
32
|
+
}));
|
|
33
|
+
if (pending || result.connected) setTimeout(() => { if (current === operation) return run('status', true); }, pending ? 250 : 1000);
|
|
34
|
+
} catch (error) {
|
|
35
|
+
if (current !== operation) return;
|
|
36
|
+
element('status').textContent = error.message;
|
|
37
|
+
if (action === 'pair') element('stop').hidden = true;
|
|
38
|
+
}
|
|
39
|
+
finally {
|
|
40
|
+
if (current === operation) {
|
|
41
|
+
for (const id of ['pair', 'share']) element(id).disabled = pending;
|
|
42
|
+
element('stop').disabled = false;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
for (const action of ['pair', 'share', 'stop']) element(action).addEventListener('click', () => run(action));
|
|
47
|
+
await run('status');
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
/** Map a scoped chrome.debugger connection to the CDP browser/target envelope. */
|
|
2
|
+
export class SharedTabs {
|
|
3
|
+
constructor(api, emit) {
|
|
4
|
+
this.api = api;
|
|
5
|
+
this.emit = emit;
|
|
6
|
+
this.tabs = new Map();
|
|
7
|
+
this.attachedTabs = new Set();
|
|
8
|
+
this.sessions = new Map();
|
|
9
|
+
this.discover = false;
|
|
10
|
+
this.autoAttach = false;
|
|
11
|
+
this.sequence = 0;
|
|
12
|
+
this.closed = false;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
info(tab, type = 'page') {
|
|
16
|
+
return { targetId: type === 'tab' ? `tab-${tab.id}` : tab.targetId, type,
|
|
17
|
+
title: tab.title ?? '', url: tab.url, attached: true, canAccessOpener: false, browserContextId: 'shared' };
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
event(method, params, sessionId) { this.emit({ method, params, ...(sessionId ? { sessionId } : {}) }); }
|
|
21
|
+
|
|
22
|
+
attach(tab, type, parent) {
|
|
23
|
+
const sessionId = `dscode-${++this.sequence}`;
|
|
24
|
+
this.sessions.set(sessionId, { tabId: tab.id, type, parent });
|
|
25
|
+
this.event('Target.attachedToTarget', { sessionId, targetInfo: this.info(tab, type), waitingForDebugger: false }, parent);
|
|
26
|
+
return { sessionId };
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async share(tabId) {
|
|
30
|
+
if (this.closed) throw Error('Sharing has ended. Pair again.');
|
|
31
|
+
if (this.tabs.has(tabId)) return;
|
|
32
|
+
const tab = await this.api.tabs.get(tabId);
|
|
33
|
+
// activeTab is granted by the toolbar gesture. A popup reopened from another
|
|
34
|
+
// extension surface still gets metadata only for the explicitly chosen ID.
|
|
35
|
+
if (!tab.url) {
|
|
36
|
+
const target = (await this.api.debugger.getTargets()).find(t => t.tabId === tabId);
|
|
37
|
+
tab.url = target?.url; tab.title = target?.title;
|
|
38
|
+
}
|
|
39
|
+
if (!/^https?:\/\//.test(tab.url ?? '') && tab.url !== 'about:blank') throw Error('Only HTTP(S) pages can be shared.');
|
|
40
|
+
if (this.closed) throw Error('Sharing has ended.');
|
|
41
|
+
await this.api.debugger.attach({ tabId }, '1.3');
|
|
42
|
+
this.attachedTabs.add(tabId);
|
|
43
|
+
try {
|
|
44
|
+
if (this.closed) throw Error('Sharing has ended.');
|
|
45
|
+
const { targetInfo } = await this.api.debugger.sendCommand({ tabId }, 'Target.getTargetInfo');
|
|
46
|
+
if (this.closed || !this.attachedTabs.has(tabId)) throw Error('Sharing has ended.');
|
|
47
|
+
const shared = { id: tabId, targetId: targetInfo.targetId, url: tab.url, title: tab.title };
|
|
48
|
+
this.tabs.set(tabId, shared);
|
|
49
|
+
if (this.discover) for (const type of ['tab', 'page']) this.event('Target.targetCreated', { targetInfo: this.info(shared, type) });
|
|
50
|
+
if (this.autoAttach) this.attach(shared, 'tab');
|
|
51
|
+
} catch (error) {
|
|
52
|
+
if (this.attachedTabs.delete(tabId)) await this.api.debugger.detach({ tabId }).catch(() => {});
|
|
53
|
+
throw error;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
async stop() {
|
|
58
|
+
this.closed = true;
|
|
59
|
+
const ids = [...this.attachedTabs];
|
|
60
|
+
this.attachedTabs.clear();
|
|
61
|
+
this.tabs.clear();
|
|
62
|
+
this.sessions.clear();
|
|
63
|
+
await Promise.allSettled(ids.map(tabId => this.api.debugger.detach({ tabId })));
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
update(tabId, change) {
|
|
67
|
+
const tab = this.tabs.get(tabId);
|
|
68
|
+
if (!tab) return;
|
|
69
|
+
if (change.url !== undefined) tab.url = change.url;
|
|
70
|
+
if (change.title !== undefined) tab.title = change.title;
|
|
71
|
+
for (const type of ['tab', 'page']) this.event('Target.targetInfoChanged', { targetInfo: this.info(tab, type) });
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
detach(sessionId, params = {}) {
|
|
75
|
+
const session = this.sessions.get(sessionId);
|
|
76
|
+
if (!session) return false;
|
|
77
|
+
// A detached ancestor invalidates every descendant route. Notify clients
|
|
78
|
+
// while those descendants' parent routes still exist in their session tree.
|
|
79
|
+
for (const [id, child] of [...this.sessions]) if (child.parent === sessionId) this.detach(id);
|
|
80
|
+
this.sessions.delete(sessionId);
|
|
81
|
+
this.event('Target.detachedFromTarget', { ...params, sessionId }, session.parent);
|
|
82
|
+
return true;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
remove(tabId) {
|
|
86
|
+
this.attachedTabs.delete(tabId);
|
|
87
|
+
const tab = this.tabs.get(tabId);
|
|
88
|
+
if (!tab) return;
|
|
89
|
+
this.tabs.delete(tabId);
|
|
90
|
+
for (const [id, session] of [...this.sessions]) if (session.tabId === tabId) this.detach(id);
|
|
91
|
+
for (const type of ['page', 'tab']) this.event('Target.targetDestroyed', { targetId: this.info(tab, type).targetId });
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
debuggerEvent(source, method, params) {
|
|
95
|
+
if (!this.tabs.has(source.tabId)) return;
|
|
96
|
+
for (const [sessionId, session] of [...this.sessions]) {
|
|
97
|
+
if (session.tabId !== source.tabId || session.type !== 'page' || session.child !== source.sessionId) continue;
|
|
98
|
+
if (method === 'Target.attachedToTarget') {
|
|
99
|
+
const child = `${sessionId}:${params.sessionId}`;
|
|
100
|
+
this.sessions.set(child, { tabId: source.tabId, type: 'page', child: params.sessionId, parent: sessionId });
|
|
101
|
+
this.event(method, { ...params, sessionId: child }, sessionId);
|
|
102
|
+
} else if (method === 'Target.detachedFromTarget') {
|
|
103
|
+
const child = `${sessionId}:${params.sessionId}`;
|
|
104
|
+
this.detach(child, params);
|
|
105
|
+
} else this.event(method, params, sessionId);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
async command({ method, params = {}, sessionId }) {
|
|
110
|
+
if (this.closed) throw Error('Sharing has ended.');
|
|
111
|
+
const session = sessionId ? this.sessions.get(sessionId) : undefined;
|
|
112
|
+
if (sessionId && !session) throw Error('Unknown shared session.');
|
|
113
|
+
const tab = session ? this.tabs.get(session.tabId) : undefined;
|
|
114
|
+
if (method === 'Target.getBrowserContexts') return { browserContextIds: [] };
|
|
115
|
+
if (method === 'Target.getTargets') return { targetInfos: [...this.tabs.values()].flatMap(t => [this.info(t, 'tab'), this.info(t)]) };
|
|
116
|
+
if (method === 'Target.setDiscoverTargets' && !session) {
|
|
117
|
+
this.discover = !!params.discover;
|
|
118
|
+
if (this.discover) for (const t of this.tabs.values()) for (const type of ['tab', 'page']) this.event('Target.targetCreated', { targetInfo: this.info(t, type) });
|
|
119
|
+
return {};
|
|
120
|
+
}
|
|
121
|
+
if (method === 'Target.setAutoAttach' && (!session || session.type === 'tab')) {
|
|
122
|
+
if (!params.flatten || !params.autoAttach) throw Error('Only flattened automatic attachment is supported.');
|
|
123
|
+
if (!session) {
|
|
124
|
+
if (!this.autoAttach) { this.autoAttach = true; for (const t of this.tabs.values()) this.attach(t, 'tab'); }
|
|
125
|
+
} else if (!session.attached) { session.attached = true; this.attach(tab, 'page', sessionId); }
|
|
126
|
+
return {};
|
|
127
|
+
}
|
|
128
|
+
if (method === 'Runtime.runIfWaitingForDebugger' && session?.type === 'tab') return {};
|
|
129
|
+
if (method === 'Target.attachToTarget') {
|
|
130
|
+
const found = [...this.tabs.values()].find(t => t.targetId === params.targetId || `tab-${t.id}` === params.targetId);
|
|
131
|
+
if (!found || !params.flatten) throw Error('Target is not shared.');
|
|
132
|
+
return this.attach(found, params.targetId.startsWith('tab-') ? 'tab' : 'page', sessionId);
|
|
133
|
+
}
|
|
134
|
+
if (method === 'Target.detachFromTarget') {
|
|
135
|
+
if (!this.detach(params.sessionId)) throw Error('Unknown shared session.');
|
|
136
|
+
return {};
|
|
137
|
+
}
|
|
138
|
+
if (method === 'Target.createTarget' && !session) {
|
|
139
|
+
if (params.browserContextId || (!/^https?:\/\//.test(params.url) && params.url !== 'about:blank')) throw Error('Only HTTP(S) or blank tabs in the shared browser are supported.');
|
|
140
|
+
const created = await this.api.tabs.create({ url: params.url, active: !params.background });
|
|
141
|
+
await this.share(created.id);
|
|
142
|
+
return { targetId: this.tabs.get(created.id).targetId };
|
|
143
|
+
}
|
|
144
|
+
if (['Target.closeTarget', 'Target.activateTarget'].includes(method)) {
|
|
145
|
+
const found = [...this.tabs.values()].find(t => t.targetId === params.targetId || `tab-${t.id}` === params.targetId);
|
|
146
|
+
if (!found) throw Error('Target is not shared.');
|
|
147
|
+
if (method === 'Target.closeTarget') { await this.api.tabs.remove(found.id); return { success: true }; }
|
|
148
|
+
await this.api.tabs.update(found.id, { active: true }); return {};
|
|
149
|
+
}
|
|
150
|
+
if (method === 'Browser.getVersion') return this.api.version();
|
|
151
|
+
if (!session || session.type !== 'page') throw Error(`Unsupported browser command: ${method}`);
|
|
152
|
+
// Target discovery and cookie APIs can escape the selected tab's scope.
|
|
153
|
+
if (method.startsWith('Browser.') ||
|
|
154
|
+
(method.startsWith('Target.') && !['Target.setAutoAttach', 'Target.getTargetInfo'].includes(method)) ||
|
|
155
|
+
(method.startsWith('Storage.') && method !== 'Storage.getStorageKeyForFrame') ||
|
|
156
|
+
['Network.getAllCookies', 'Network.getCookies', 'Network.setCookie', 'Network.setCookies', 'Network.deleteCookies', 'Network.clearBrowserCookies', 'Network.clearBrowserCache'].includes(method)) {
|
|
157
|
+
throw Error(`Command is outside shared-tab scope: ${method}`);
|
|
158
|
+
}
|
|
159
|
+
if (method === 'Target.getTargetInfo') {
|
|
160
|
+
if (params.targetId && params.targetId !== tab.targetId) throw Error('Target is not shared in this session.');
|
|
161
|
+
if (!session.child) return { targetInfo: this.info(tab) };
|
|
162
|
+
}
|
|
163
|
+
if (method === 'Target.setAutoAttach') {
|
|
164
|
+
params = { ...params, flatten: true, filter: [{ type: 'iframe', exclude: false }, { type: 'worker', exclude: false }, { exclude: true }] };
|
|
165
|
+
}
|
|
166
|
+
return this.api.debugger.sendCommand({ tabId: session.tabId, ...(session.child ? { sessionId: session.child } : {}) }, method, params);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/* global chrome */
|
|
2
|
+
import { SharedTabs } from './protocol.mjs';
|
|
3
|
+
|
|
4
|
+
let state;
|
|
5
|
+
let pending = false;
|
|
6
|
+
let message = 'Not sharing.';
|
|
7
|
+
|
|
8
|
+
async function stop(reason = 'Sharing stopped.') {
|
|
9
|
+
const current = state;
|
|
10
|
+
state = undefined;
|
|
11
|
+
message = reason;
|
|
12
|
+
if (current) {
|
|
13
|
+
clearInterval(current.timer);
|
|
14
|
+
current.cancelConnect?.();
|
|
15
|
+
current.socket?.close();
|
|
16
|
+
await current.tabs.stop();
|
|
17
|
+
}
|
|
18
|
+
// Detaching may finish after the user pairs a different tab. That new
|
|
19
|
+
// connection owns the badge; an older stop must not hide active sharing.
|
|
20
|
+
if (!state) await chrome.action.setBadgeText({ text: '' });
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
async function pair(url, tabId) {
|
|
24
|
+
if (state || pending) throw Error('Stop sharing before pairing another session.');
|
|
25
|
+
const endpoint = new URL(url);
|
|
26
|
+
if (endpoint.protocol !== 'ws:' || endpoint.hostname !== '127.0.0.1' || !endpoint.port ||
|
|
27
|
+
endpoint.username || endpoint.password || endpoint.hash || endpoint.pathname !== '/extension' ||
|
|
28
|
+
!/^\?token=[a-f0-9]{64}$/.test(endpoint.search)) throw Error('Paste the local pairing link from DSCODE.');
|
|
29
|
+
pending = true;
|
|
30
|
+
message = 'Pairing with DSCODE.';
|
|
31
|
+
const current = { tabs: new SharedTabs({
|
|
32
|
+
tabs: chrome.tabs, debugger: chrome.debugger,
|
|
33
|
+
version: () => ({ protocolVersion: '1.3', product: `Chrome/${navigator.userAgent.match(/Chrome\/([\d.]+)/)?.[1] ?? 'unknown'}`,
|
|
34
|
+
revision: '', userAgent: navigator.userAgent, jsVersion: '' }),
|
|
35
|
+
}, event => { if (current.socket?.readyState === WebSocket.OPEN) current.socket.send(JSON.stringify(event)); }) };
|
|
36
|
+
state = current;
|
|
37
|
+
try {
|
|
38
|
+
await current.tabs.share(tabId);
|
|
39
|
+
if (state !== current) throw Error('Pairing was cancelled.');
|
|
40
|
+
current.socket = new WebSocket(endpoint.href);
|
|
41
|
+
await new Promise((resolve, reject) => {
|
|
42
|
+
const finish = error => {
|
|
43
|
+
clearTimeout(timer);
|
|
44
|
+
current.cancelConnect = undefined;
|
|
45
|
+
current.socket.onopen = current.socket.onerror = current.socket.onclose = null;
|
|
46
|
+
if (error) reject(error); else resolve();
|
|
47
|
+
};
|
|
48
|
+
const timer = setTimeout(() => finish(Error('Could not connect to DSCODE. Generate a new pairing link.')), 10000);
|
|
49
|
+
current.cancelConnect = () => finish(Error('Pairing was cancelled.'));
|
|
50
|
+
current.socket.onopen = () => finish();
|
|
51
|
+
current.socket.onerror = current.socket.onclose = () => finish(Error('Could not connect to DSCODE.'));
|
|
52
|
+
});
|
|
53
|
+
if (state !== current) throw Error('Pairing was cancelled.');
|
|
54
|
+
current.socket.onclose = () => { if (state === current) void stop('DSCODE disconnected. Pair again to share.'); };
|
|
55
|
+
current.socket.onerror = () => { if (state === current) void stop('Connection failed. Pair again to share.'); };
|
|
56
|
+
current.socket.onmessage = async event => {
|
|
57
|
+
let command;
|
|
58
|
+
try { command = JSON.parse(event.data); } catch { await stop('Invalid connection message.'); return; }
|
|
59
|
+
if (!Number.isSafeInteger(command.id) || typeof command.method !== 'string') { await stop('Invalid connection command.'); return; }
|
|
60
|
+
let response;
|
|
61
|
+
try { response = { result: await current.tabs.command(command) }; }
|
|
62
|
+
catch (error) { response = { error: { code: -32000, message: error.message } }; }
|
|
63
|
+
if (state === current && current.socket.readyState === WebSocket.OPEN) current.socket.send(JSON.stringify({ id: command.id, ...(command.sessionId ? { sessionId: command.sessionId } : {}), ...response }));
|
|
64
|
+
};
|
|
65
|
+
current.socket.send(JSON.stringify({ type: 'ready' }));
|
|
66
|
+
current.timer = setInterval(() => { if (current.socket.readyState === WebSocket.OPEN) current.socket.send(JSON.stringify({ type: 'keepalive' })); }, 20000);
|
|
67
|
+
message = 'Sharing with DSCODE.';
|
|
68
|
+
await chrome.action.setBadgeText({ text: 'ON' });
|
|
69
|
+
await chrome.action.setBadgeBackgroundColor({ color: '#bd4520' });
|
|
70
|
+
} catch (error) { if (state === current) await stop(error.message); throw error; }
|
|
71
|
+
finally { pending = false; }
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
chrome.runtime.onMessage.addListener((request, sender, respond) => {
|
|
75
|
+
if (sender.id !== chrome.runtime.id || sender.url !== chrome.runtime.getURL('popup.html')) return false;
|
|
76
|
+
(async () => {
|
|
77
|
+
if (request.action === 'pair') await pair(request.url, request.tabId);
|
|
78
|
+
else if (request.action === 'share') {
|
|
79
|
+
if (!state || pending) throw Error('Pair with DSCODE first.');
|
|
80
|
+
await state.tabs.share(request.tabId);
|
|
81
|
+
} else if (request.action === 'stop') await stop();
|
|
82
|
+
else if (request.action !== 'status') throw Error('Unknown action.');
|
|
83
|
+
return { message, pending, shared: [...(state?.tabs.tabs.values() ?? [])].map(t => ({ title: t.title, url: t.url })), connected: !!state && !pending };
|
|
84
|
+
})().then(respond, error => respond({ error: error.message }));
|
|
85
|
+
return true;
|
|
86
|
+
});
|
|
87
|
+
chrome.debugger.onEvent.addListener((source, method, params) => state?.tabs.debuggerEvent(source, method, params));
|
|
88
|
+
chrome.debugger.onDetach.addListener((source, reason) => {
|
|
89
|
+
if (!state?.tabs.tabs.has(source.tabId)) return;
|
|
90
|
+
if (reason === 'target_closed') state.tabs.remove(source.tabId);
|
|
91
|
+
else void stop('Browser debugging was cancelled. Pair again to share.');
|
|
92
|
+
});
|
|
93
|
+
chrome.tabs.onUpdated.addListener((id, change) => state?.tabs.update(id, change));
|
|
94
|
+
chrome.tabs.onRemoved.addListener(id => state?.tabs.remove(id));
|
package/icon.svg
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 128 128">
|
|
2
|
+
<rect width="128" height="128" rx="28" fill="#0e1a2e"/>
|
|
3
|
+
<g stroke="#7dd3fc" stroke-width="6" stroke-linecap="round" fill="none">
|
|
4
|
+
<path d="M24 64h80M44 29l40 70M44 99l40-70"/>
|
|
5
|
+
<path d="m32 51 13 13-13 13m64-26L83 64l13 13M44 44l18 5 5-18m-6 66 5-18 18 5M44 84l18-5 5 18m-6-66 5 18 18-5"/>
|
|
6
|
+
</g>
|
|
7
|
+
</svg>
|
package/locale/en.json
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 DeepSeek
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
|
|
2
|
+
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
|
3
|
+
# after editing either side, bring the other along and re-record with:
|
|
4
|
+
# pnpm run verify-translation-pairing --write native/system/packages/entry/README.md
|
|
5
|
+
README.md: 8f6a4d341c8f9e4c104e5706e08d9a7d45c065e1
|
|
6
|
+
README.zh.md: 152257916df0cf40511b9743d389ae753ab6c85c
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "JavaScript entry for the prebuilt Landlock launcher and asynchronous POSIX flock."
|
|
3
|
+
kind: "package-library"
|
|
4
|
+
---
|
|
5
|
+
# @deepseek-ai/node-addon-system
|
|
6
|
+
|
|
7
|
+
English | [中文](README.zh.md)
|
|
8
|
+
|
|
9
|
+
The `./landlock-run` entry exports the Landlock launcher path, enforcement probe, grant arguments, and protocol constants. The independent `./flock` entry exports `tryLockExclusive(fd): Promise<void>`; importing either entry does not load `system.node`. The package has no root export.
|
|
10
|
+
|
|
11
|
+
The lock operation attempts `LOCK_EX | LOCK_NB` asynchronously. Keep the caller-owned descriptor open until completion; contention rejects with `EAGAIN`/`EWOULDBLOCK`, other syscall failures also reject, and errors carry their code, positive errno, and `syscall: 'flock'`. Native setup errors reject the same promise. Closing the last descriptor for the open file description releases the lock. The binding does not open, duplicate, close, or explicitly unlock descriptors.
|
|
12
|
+
|
|
13
|
+
Optional OS/CPU platform packages carry the binaries. Linux has `bin/landlock-run` and separate `bin/glibc/system.node` / `bin/musl/system.node`; macOS has `bin/system.node`. Missing or unloadable flock bindings reject acquisition, without installation-time compilation. Landlock remains a separate executable with its existing fail-closed protocol; unsupported kernels/platforms probe unusable.
|
|
14
|
+
|
|
15
|
+
The two C sources ship for auditability. See the workspace [architecture](../../docs/architecture.md), [support matrix](../../docs/support-matrix.md), and [CLI contract](../../docs/cli-contract.md).
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "预编译 Landlock 启动器与异步 POSIX flock 的 JavaScript 入口。"
|
|
3
|
+
kind: "package-library"
|
|
4
|
+
---
|
|
5
|
+
# @deepseek-ai/node-addon-system
|
|
6
|
+
|
|
7
|
+
[English](README.md) | 中文
|
|
8
|
+
|
|
9
|
+
`./landlock-run` 入口导出 Landlock 启动器路径、强制执行探测、授权参数和协议常量。独立的 `./flock` 入口导出 `tryLockExclusive(fd): Promise<void>`;导入任一入口都不会加载 `system.node`。包不提供根导出。
|
|
10
|
+
|
|
11
|
+
锁操作异步尝试 `LOCK_EX | LOCK_NB`。在完成前保持调用方拥有的描述符打开;竞争以 `EAGAIN`/`EWOULDBLOCK` 拒绝,其他系统调用失败也会拒绝,错误携带 code、正 errno 和 `syscall: 'flock'`。原生调用准备阶段的错误也会拒绝同一个 promise。关闭该打开文件描述的最后一个描述符即释放锁。绑定不打开、复制、关闭或显式解锁描述符。
|
|
12
|
+
|
|
13
|
+
可选操作系统/CPU 平台包携带二进制。Linux 包含 `bin/landlock-run` 和分别用于两种 libc 的 `bin/glibc/system.node` / `bin/musl/system.node`;macOS 包含 `bin/system.node`。flock 绑定缺失或无法加载时拒绝获取,不在安装时编译。Landlock 仍是遵循既有失败关闭协议的独立可执行文件;不支持的内核或平台探测为不可用。
|
|
14
|
+
|
|
15
|
+
两个 C 源文件随包分发以供审计。参见工作区[架构](../../docs/architecture.md)、[支持矩阵](../../docs/support-matrix.md)和 [CLI 约定](../../docs/cli-contract.md)。
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Attempt an exclusive, nonblocking POSIX flock on the caller's descriptor.
|
|
3
|
+
* The syscall runs in asynchronous work, so acquisition can occur after this
|
|
4
|
+
* call returns. Keep fd open until the promise settles; the binding never
|
|
5
|
+
* opens, duplicates, or closes it. Closing the locked descriptor releases the
|
|
6
|
+
* lock once all descriptors for its open file description are closed.
|
|
7
|
+
* @param fd - Open file descriptor to lock; ownership remains with the caller.
|
|
8
|
+
* @returns A promise resolving to void on acquisition. Contention rejects with
|
|
9
|
+
* EAGAIN/EWOULDBLOCK; other syscall failures also reject. Syscall errors carry
|
|
10
|
+
* code, positive errno, and syscall='flock'. Native setup errors, unsupported
|
|
11
|
+
* platforms, and addon loading failures reject; importing alone does not load it.
|
|
12
|
+
*/
|
|
13
|
+
export declare function tryLockExclusive(fd: number): Promise<void>;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/** Lazy POSIX flock entry; importing it does not load a native addon. */
|
|
2
|
+
import { createRequire } from 'node:module';
|
|
3
|
+
import { dirname, join } from 'node:path';
|
|
4
|
+
import { getSystemErrorName } from 'node:util';
|
|
5
|
+
let binding;
|
|
6
|
+
function loadBinding() {
|
|
7
|
+
if (binding)
|
|
8
|
+
return binding;
|
|
9
|
+
const { platform, arch } = process;
|
|
10
|
+
if (platform !== 'linux' && platform !== 'darwin') {
|
|
11
|
+
throw Object.assign(new Error(`flock is not supported on ${platform}-${arch}`), {
|
|
12
|
+
code: 'ERR_FLOCK_UNSUPPORTED_PLATFORM',
|
|
13
|
+
syscall: 'flock',
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
let filename = 'system.node';
|
|
17
|
+
if (platform === 'linux') {
|
|
18
|
+
// Node's report types omit the libc field supplied by Linux reports.
|
|
19
|
+
const report = process.report.getReport();
|
|
20
|
+
filename = join(report.header.glibcVersionRuntime ? 'glibc' : 'musl', filename);
|
|
21
|
+
}
|
|
22
|
+
const require = createRequire(import.meta.url);
|
|
23
|
+
const manifest = require.resolve(`@deepseek-ai/node-addon-system-${platform}-${arch}/package.json`);
|
|
24
|
+
binding = require(join(dirname(manifest), 'bin', filename));
|
|
25
|
+
return binding;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Attempt an exclusive, nonblocking POSIX flock on the caller's descriptor.
|
|
29
|
+
* The syscall runs in asynchronous work, so acquisition can occur after this
|
|
30
|
+
* call returns. Keep fd open until the promise settles; the binding never
|
|
31
|
+
* opens, duplicates, or closes it. Closing the locked descriptor releases the
|
|
32
|
+
* lock once all descriptors for its open file description are closed.
|
|
33
|
+
* @param fd - Open file descriptor to lock; ownership remains with the caller.
|
|
34
|
+
* @returns A promise resolving to void on acquisition. Contention rejects with
|
|
35
|
+
* EAGAIN/EWOULDBLOCK; other syscall failures also reject. Syscall errors carry
|
|
36
|
+
* code, positive errno, and syscall='flock'. Native setup errors, unsupported
|
|
37
|
+
* platforms, and addon loading failures reject; importing alone does not load it.
|
|
38
|
+
*/
|
|
39
|
+
export async function tryLockExclusive(fd) {
|
|
40
|
+
const errno = await new Promise((resolve) => {
|
|
41
|
+
loadBinding().tryLock(fd, resolve);
|
|
42
|
+
});
|
|
43
|
+
if (errno === 0)
|
|
44
|
+
return;
|
|
45
|
+
const code = getSystemErrorName(-errno);
|
|
46
|
+
throw Object.assign(new Error(`${code}: flock failed`), {
|
|
47
|
+
code,
|
|
48
|
+
errno,
|
|
49
|
+
syscall: 'flock',
|
|
50
|
+
});
|
|
51
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/** The launcher binary's file name inside each platform package's `bin/`. */
|
|
2
|
+
export declare const LAUNCHER_BIN = "landlock-run";
|
|
3
|
+
/**
|
|
4
|
+
* The exit code for every launcher-level failure (usage error, unenforcing
|
|
5
|
+
* kernel, unopenable grant root, failed exec). After a successful `exec`, the
|
|
6
|
+
* wrapped command may also return 125, so consumers also require a matching
|
|
7
|
+
* launcher-owned fatal diagnostic to attribute launcher failure. Part of the
|
|
8
|
+
* CLI contract.
|
|
9
|
+
*/
|
|
10
|
+
export declare const LAUNCHER_FAILURE_EXIT = 125;
|
|
11
|
+
/**
|
|
12
|
+
* The probe's verdict on this host: `full` when the running kernel enforces
|
|
13
|
+
* every access the launcher can govern, `partial` when an older Landlock ABI
|
|
14
|
+
* governs only a subset (still confined for everything it supports), and
|
|
15
|
+
* `unusable` when nothing can be enforced — a kernel without Landlock, a
|
|
16
|
+
* disabled LSM, or a missing binary, all indistinguishable on purpose
|
|
17
|
+
* because the consumer's answer is the same: do not trust this launcher.
|
|
18
|
+
*/
|
|
19
|
+
export type LandlockEnforcement = 'full' | 'partial' | 'unusable';
|
|
20
|
+
/**
|
|
21
|
+
* Filesystem grants for one confined run. Everything not granted is denied —
|
|
22
|
+
* Landlock rulesets are allow-lists.
|
|
23
|
+
*/
|
|
24
|
+
export interface LauncherGrants {
|
|
25
|
+
/** Roots granted read + execute beneath (the launcher's `--ro`). */
|
|
26
|
+
readonly readOnly?: readonly string[];
|
|
27
|
+
/** Roots granted full filesystem access beneath (the launcher's `--rw`). */
|
|
28
|
+
readonly readWrite?: readonly string[];
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Path of the launcher binary for this host: resolved from the per-platform
|
|
32
|
+
* npm package `@deepseek-ai/node-addon-system-<platform>-<arch>` (npm's
|
|
33
|
+
* `os`/`cpu` fields make installers fetch only the matching one). When the
|
|
34
|
+
* package is not resolvable — a platform without one, or an install that
|
|
35
|
+
* skipped the optional dependency — the returned fallback path points inside
|
|
36
|
+
* this package's own `node_modules` and simply never exists. Existence is
|
|
37
|
+
* deliberately not checked either way: {@link probe} is the single
|
|
38
|
+
* availability signal (a missing binary probes `unusable` the same way an
|
|
39
|
+
* unenforcing kernel does).
|
|
40
|
+
* @param resolvePackageJson - test hook over `require.resolve` (the default
|
|
41
|
+
* covers real installs); receives the platform package's `package.json`
|
|
42
|
+
* specifier and returns its absolute path, throwing when unresolvable.
|
|
43
|
+
* @returns the absolute launcher path to probe and exec.
|
|
44
|
+
*/
|
|
45
|
+
export declare function launcherPath(resolvePackageJson?: (specifier: string) => string): string;
|
|
46
|
+
/**
|
|
47
|
+
* The launcher grant arguments for one set of filesystem grants — everything
|
|
48
|
+
* before the `--` argv separator. A caller spawns
|
|
49
|
+
* `[launcherPath(), ...grantArgs(grants), '--', ...command]`; the flag
|
|
50
|
+
* spellings stay private to this package.
|
|
51
|
+
* @param grants - the read-only and read-write roots to allow.
|
|
52
|
+
* @returns the `--ro <path>` / `--rw <path>` argument list, read-only roots
|
|
53
|
+
* first, in the caller's order.
|
|
54
|
+
*/
|
|
55
|
+
export declare function grantArgs(grants: LauncherGrants): string[];
|
|
56
|
+
/**
|
|
57
|
+
* Functional probe: `landlock-run --probe` builds and enforces a maximal
|
|
58
|
+
* ruleset in a short-lived child and exits 0 only when the running kernel
|
|
59
|
+
* actually enforces it — `--version`-style checks would miss a kernel that
|
|
60
|
+
* has the syscalls but refuses enforcement. The probe's one report line is
|
|
61
|
+
* part of the CLI contract and distinguishes complete from per-ABI-subset
|
|
62
|
+
* enforcement; a zero exit without the partial marker reads as `full`. A
|
|
63
|
+
* failed or timed-out spawn (missing binary, wrong architecture, unenforcing
|
|
64
|
+
* kernel) probes `unusable`. Synchronous by design: consumers run it once
|
|
65
|
+
* and cache the verdict.
|
|
66
|
+
* @param launcher - the launcher path to probe; defaults to
|
|
67
|
+
* {@link launcherPath}'s resolution for this host.
|
|
68
|
+
* @param options - `timeoutMs` bounds the probe child (default 2000).
|
|
69
|
+
* @returns the enforcement verdict for this host.
|
|
70
|
+
*/
|
|
71
|
+
export declare function probe(launcher?: string, options?: {
|
|
72
|
+
timeoutMs?: number;
|
|
73
|
+
}): LandlockEnforcement;
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The JavaScript API over the prebuilt `landlock-run` launcher: resolve the
|
|
3
|
+
* binary for this host, build its grant argv, and run its functional probe.
|
|
4
|
+
*
|
|
5
|
+
* This module owns the launcher's CLI contract (`docs/cli-contract.md`) so
|
|
6
|
+
* consumers never parse launcher output or spell launcher flags themselves —
|
|
7
|
+
* the contract and the binaries version together in one package family,
|
|
8
|
+
* which makes probe-parsing drift against the binary structurally
|
|
9
|
+
* impossible. Policy stays with the consumer: this package does not know
|
|
10
|
+
* what a "sandbox mode" is, only which paths are granted read or write.
|
|
11
|
+
*
|
|
12
|
+
* Deliberately no environment-variable overrides anywhere in this module:
|
|
13
|
+
* which binary confines a process must never be decidable by the ambient
|
|
14
|
+
* environment. Test injection is by function parameter.
|
|
15
|
+
*/
|
|
16
|
+
import { spawnSync } from 'node:child_process';
|
|
17
|
+
import { createRequire } from 'node:module';
|
|
18
|
+
import { dirname, join } from 'node:path';
|
|
19
|
+
import { fileURLToPath } from 'node:url';
|
|
20
|
+
/** The launcher binary's file name inside each platform package's `bin/`. */
|
|
21
|
+
export const LAUNCHER_BIN = 'landlock-run';
|
|
22
|
+
/**
|
|
23
|
+
* The exit code for every launcher-level failure (usage error, unenforcing
|
|
24
|
+
* kernel, unopenable grant root, failed exec). After a successful `exec`, the
|
|
25
|
+
* wrapped command may also return 125, so consumers also require a matching
|
|
26
|
+
* launcher-owned fatal diagnostic to attribute launcher failure. Part of the
|
|
27
|
+
* CLI contract.
|
|
28
|
+
*/
|
|
29
|
+
export const LAUNCHER_FAILURE_EXIT = 125;
|
|
30
|
+
/**
|
|
31
|
+
* Path of the launcher binary for this host: resolved from the per-platform
|
|
32
|
+
* npm package `@deepseek-ai/node-addon-system-<platform>-<arch>` (npm's
|
|
33
|
+
* `os`/`cpu` fields make installers fetch only the matching one). When the
|
|
34
|
+
* package is not resolvable — a platform without one, or an install that
|
|
35
|
+
* skipped the optional dependency — the returned fallback path points inside
|
|
36
|
+
* this package's own `node_modules` and simply never exists. Existence is
|
|
37
|
+
* deliberately not checked either way: {@link probe} is the single
|
|
38
|
+
* availability signal (a missing binary probes `unusable` the same way an
|
|
39
|
+
* unenforcing kernel does).
|
|
40
|
+
* @param resolvePackageJson - test hook over `require.resolve` (the default
|
|
41
|
+
* covers real installs); receives the platform package's `package.json`
|
|
42
|
+
* specifier and returns its absolute path, throwing when unresolvable.
|
|
43
|
+
* @returns the absolute launcher path to probe and exec.
|
|
44
|
+
*/
|
|
45
|
+
export function launcherPath(resolvePackageJson = createRequire(import.meta.url).resolve) {
|
|
46
|
+
const platformPackage = `@deepseek-ai/node-addon-system-${process.platform}-${process.arch}`;
|
|
47
|
+
try {
|
|
48
|
+
return join(dirname(resolvePackageJson(`${platformPackage}/package.json`)), 'bin', LAUNCHER_BIN);
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
// Unresolvable platform package: no such package exists for this host, or
|
|
52
|
+
// it was not installed. Fall back to the path pnpm's layout WOULD use —
|
|
53
|
+
// absolute, inside this package's boundary (never cwd-relative: a
|
|
54
|
+
// spawnable relative path here would hand cwd control over which binary
|
|
55
|
+
// confines), and nonexistent exactly when the package is absent.
|
|
56
|
+
return fileURLToPath(new URL(`../node_modules/${platformPackage}/bin/${LAUNCHER_BIN}`, import.meta.url));
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* The launcher grant arguments for one set of filesystem grants — everything
|
|
61
|
+
* before the `--` argv separator. A caller spawns
|
|
62
|
+
* `[launcherPath(), ...grantArgs(grants), '--', ...command]`; the flag
|
|
63
|
+
* spellings stay private to this package.
|
|
64
|
+
* @param grants - the read-only and read-write roots to allow.
|
|
65
|
+
* @returns the `--ro <path>` / `--rw <path>` argument list, read-only roots
|
|
66
|
+
* first, in the caller's order.
|
|
67
|
+
*/
|
|
68
|
+
export function grantArgs(grants) {
|
|
69
|
+
return [
|
|
70
|
+
...(grants.readOnly ?? []).flatMap(root => ['--ro', root]),
|
|
71
|
+
...(grants.readWrite ?? []).flatMap(root => ['--rw', root]),
|
|
72
|
+
];
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Functional probe: `landlock-run --probe` builds and enforces a maximal
|
|
76
|
+
* ruleset in a short-lived child and exits 0 only when the running kernel
|
|
77
|
+
* actually enforces it — `--version`-style checks would miss a kernel that
|
|
78
|
+
* has the syscalls but refuses enforcement. The probe's one report line is
|
|
79
|
+
* part of the CLI contract and distinguishes complete from per-ABI-subset
|
|
80
|
+
* enforcement; a zero exit without the partial marker reads as `full`. A
|
|
81
|
+
* failed or timed-out spawn (missing binary, wrong architecture, unenforcing
|
|
82
|
+
* kernel) probes `unusable`. Synchronous by design: consumers run it once
|
|
83
|
+
* and cache the verdict.
|
|
84
|
+
* @param launcher - the launcher path to probe; defaults to
|
|
85
|
+
* {@link launcherPath}'s resolution for this host.
|
|
86
|
+
* @param options - `timeoutMs` bounds the probe child (default 2000).
|
|
87
|
+
* @returns the enforcement verdict for this host.
|
|
88
|
+
*/
|
|
89
|
+
export function probe(launcher = launcherPath(), options = {}) {
|
|
90
|
+
const result = spawnSync(launcher, ['--probe'], {
|
|
91
|
+
timeout: options.timeoutMs ?? 2000,
|
|
92
|
+
encoding: 'utf8',
|
|
93
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
94
|
+
});
|
|
95
|
+
if (result.status !== 0)
|
|
96
|
+
return 'unusable';
|
|
97
|
+
return /partially enforced/.test(result.stdout) ? 'partial' : 'full';
|
|
98
|
+
}
|