@toddzheng024/dscode-desktop 0.0.0-stage → 0.7.33
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 +641 -0
- package/docs/account-login.md +44 -0
- package/docs/auto-review.md +128 -0
- package/docs/browser-use.md +783 -0
- package/docs/computer-use.md +81 -0
- package/docs/custom-providers.md +88 -0
- package/docs/demo.md +76 -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 +190 -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 +30 -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 +98 -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 +146 -0
- package/plugins/grok/index.mjs +122 -0
- package/plugins/grok/models.mjs +129 -0
- package/plugins/grok/status.mjs +28 -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 +99 -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 +120 -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 +119 -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 +123 -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 +68 -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 +96 -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 +271 -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 +148 -0
- package/plugins/tui-tools/hook-sources.mjs +113 -0
- package/plugins/tui-tools/hooks.mjs +23 -0
- package/plugins/tui-tools/index.mjs +268 -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,194 @@
|
|
|
1
|
+
import { LlmError } from '@deepseek-ai/dsh-llm';
|
|
2
|
+
|
|
3
|
+
// Signing in to OpenCode Go with an OpenCode console account instead of a pasted API key.
|
|
4
|
+
//
|
|
5
|
+
// The console speaks the OAuth device flow (RFC 8628) to the public client `opencode-cli`,
|
|
6
|
+
// which is OpenCode's own CLI; DSCODE borrows that client id, so the consent page names the
|
|
7
|
+
// OpenCode CLI. The access token does not work on the public `zen/go/v1` endpoint: the
|
|
8
|
+
// console's `/api/config` names the account's own inference endpoint for `opencode-go`,
|
|
9
|
+
// which takes the token as a bearer plus `x-opencode-org-id` (probed 2026-09).
|
|
10
|
+
//
|
|
11
|
+
// Refresh tokens rotate: every refresh returns a new one and voids the old. DSCODE therefore
|
|
12
|
+
// keeps its own grant, separate from any OpenCode CLI login, and re-reads the store before
|
|
13
|
+
// giving up on a refused refresh, because another DSCODE process may have rotated it first.
|
|
14
|
+
|
|
15
|
+
export const CONSOLE_URL = 'https://opencode.ai/console';
|
|
16
|
+
export const CLIENT_ID = 'opencode-cli';
|
|
17
|
+
/** Credential reference holding the grant, as JSON, in the shared store. */
|
|
18
|
+
export const GRANT_REF = 'OPENCODE_OAUTH';
|
|
19
|
+
const DEVICE_GRANT = 'urn:ietf:params:oauth:grant-type:device_code';
|
|
20
|
+
/** Refresh once the access token has less than this left. */
|
|
21
|
+
export const REFRESH_MARGIN_MS = 5 * 60 * 1000;
|
|
22
|
+
const GRANT_VERSION = 1;
|
|
23
|
+
|
|
24
|
+
async function request(fetchImpl, url, { method = 'GET', body, token, orgID, signal } = {}) {
|
|
25
|
+
const response = await fetchImpl(url, {
|
|
26
|
+
method, signal, redirect: 'error',
|
|
27
|
+
headers: {
|
|
28
|
+
accept: 'application/json',
|
|
29
|
+
...(body !== undefined ? { 'content-type': 'application/json' } : {}),
|
|
30
|
+
...(token !== undefined ? { authorization: `Bearer ${token}` } : {}),
|
|
31
|
+
...(orgID !== undefined ? { 'x-org-id': orgID } : {}),
|
|
32
|
+
},
|
|
33
|
+
...(body !== undefined ? { body: JSON.stringify(body) } : {}),
|
|
34
|
+
});
|
|
35
|
+
const text = await response.text();
|
|
36
|
+
let json;
|
|
37
|
+
try { json = JSON.parse(text); } catch { json = undefined; }
|
|
38
|
+
return { status: response.status, ok: response.ok, json, text };
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const describe = result => result.json?.error_description ?? result.json?.error ?? `HTTP ${result.status}`;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Start a device login.
|
|
45
|
+
* @returns `{ deviceCode, userCode, url, intervalMs, expiresAt }`; `url` already carries the user code.
|
|
46
|
+
*/
|
|
47
|
+
export async function startDeviceLogin({ fetch: fetchImpl = globalThis.fetch, server = CONSOLE_URL, now = Date.now() } = {}) {
|
|
48
|
+
const result = await request(fetchImpl, `${server}/auth/device/code`, { method: 'POST', body: { client_id: CLIENT_ID } });
|
|
49
|
+
const device = result.json;
|
|
50
|
+
if (!result.ok || typeof device?.device_code !== 'string' || typeof device.user_code !== 'string') {
|
|
51
|
+
throw new Error(`OpenCode refused to start a login: ${describe(result)}`);
|
|
52
|
+
}
|
|
53
|
+
const url = new URL(device.verification_uri_complete ?? device.verification_uri ?? '/console/device', `${server}/`);
|
|
54
|
+
if (url.protocol !== 'https:' && url.protocol !== 'http:') throw new Error('OpenCode returned an unusable verification URL');
|
|
55
|
+
return {
|
|
56
|
+
deviceCode: device.device_code,
|
|
57
|
+
userCode: device.user_code,
|
|
58
|
+
url: url.href,
|
|
59
|
+
intervalMs: Math.max(1, Number(device.interval) || 5) * 1000,
|
|
60
|
+
expiresAt: now + Math.max(1, Number(device.expires_in) || 600) * 1000,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Poll until the user approves, the code expires or `signal` aborts.
|
|
66
|
+
* @returns the token response (`access_token`, `refresh_token`, `expires_in`).
|
|
67
|
+
*/
|
|
68
|
+
export async function pollDeviceToken(device, { fetch: fetchImpl = globalThis.fetch, server = CONSOLE_URL, signal, sleep, now = () => Date.now() } = {}) {
|
|
69
|
+
const wait = sleep ?? (ms => new Promise((resolve, reject) => {
|
|
70
|
+
const timer = setTimeout(resolve, ms);
|
|
71
|
+
signal?.addEventListener('abort', () => { clearTimeout(timer); reject(signal.reason); }, { once: true });
|
|
72
|
+
}));
|
|
73
|
+
let interval = device.intervalMs;
|
|
74
|
+
while (now() < device.expiresAt) {
|
|
75
|
+
await wait(interval);
|
|
76
|
+
signal?.throwIfAborted();
|
|
77
|
+
const result = await request(fetchImpl, `${server}/auth/device/token`, { method: 'POST', signal, body: { grant_type: DEVICE_GRANT, device_code: device.deviceCode, client_id: CLIENT_ID } });
|
|
78
|
+
if (typeof result.json?.access_token === 'string') return result.json;
|
|
79
|
+
const error = result.json?.error;
|
|
80
|
+
if (error === 'authorization_pending') continue;
|
|
81
|
+
if (error === 'slow_down') { interval += 5000; continue; }
|
|
82
|
+
// A transient gateway failure is not an answer; keep polling until the code expires.
|
|
83
|
+
if (result.status >= 500 || result.status === 429) continue;
|
|
84
|
+
throw new Error(error === 'expired_token' ? 'the login code expired before it was approved' : error === 'access_denied' ? 'the login was declined' : `OpenCode refused the login: ${describe(result)}`);
|
|
85
|
+
}
|
|
86
|
+
throw new Error('the login code expired before it was approved');
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Turn a token response into a stored grant: the account, and the first organisation (by
|
|
91
|
+
* name) whose console config carries `opencode-go`, with the inference endpoint it names.
|
|
92
|
+
*/
|
|
93
|
+
export async function completeGrant(token, { fetch: fetchImpl = globalThis.fetch, server = CONSOLE_URL, now = Date.now() } = {}) {
|
|
94
|
+
const access = token.access_token;
|
|
95
|
+
const [user, orgs] = await Promise.all([
|
|
96
|
+
request(fetchImpl, `${server}/api/user`, { token: access }),
|
|
97
|
+
request(fetchImpl, `${server}/api/orgs`, { token: access }),
|
|
98
|
+
]);
|
|
99
|
+
if (!user.ok || !orgs.ok || !Array.isArray(orgs.json)) throw new Error(`OpenCode did not return the account: ${describe(user.ok ? orgs : user)}`);
|
|
100
|
+
const sorted = orgs.json.filter(org => typeof org?.id === 'string')
|
|
101
|
+
.toSorted((a, b) => String(a.name).localeCompare(String(b.name)) || a.id.localeCompare(b.id));
|
|
102
|
+
for (const org of sorted) {
|
|
103
|
+
const config = await request(fetchImpl, `${server}/api/config`, { token: access, orgID: org.id });
|
|
104
|
+
const go = config.ok ? config.json?.config?.provider?.['opencode-go'] : undefined;
|
|
105
|
+
if (typeof go?.api !== 'string' || !URL.canParse(go.api)) continue;
|
|
106
|
+
return {
|
|
107
|
+
version: GRANT_VERSION,
|
|
108
|
+
access,
|
|
109
|
+
refresh: token.refresh_token,
|
|
110
|
+
expires: now + Math.max(0, Number(token.expires_in) || 0) * 1000,
|
|
111
|
+
server,
|
|
112
|
+
api: go.api.replace(/\/+$/, ''),
|
|
113
|
+
orgID: org.id,
|
|
114
|
+
...(typeof org.name === 'string' ? { orgName: org.name } : {}),
|
|
115
|
+
...(typeof user.json?.email === 'string' ? { email: user.json.email } : {}),
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
throw new Error('this OpenCode account has no organisation with an OpenCode Go subscription');
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/** Exchange the grant's refresh token; the returned grant carries the rotated one. */
|
|
122
|
+
export async function refreshGrant(grant, { fetch: fetchImpl = globalThis.fetch, now = Date.now() } = {}) {
|
|
123
|
+
const result = await request(fetchImpl, `${grant.server ?? CONSOLE_URL}/auth/device/token`, { method: 'POST', body: { grant_type: 'refresh_token', refresh_token: grant.refresh, client_id: CLIENT_ID } });
|
|
124
|
+
if (typeof result.json?.access_token !== 'string') {
|
|
125
|
+
const error = new Error(`OpenCode refused to refresh the login: ${describe(result)}`);
|
|
126
|
+
error.invalidGrant = result.json?.error === 'invalid_grant';
|
|
127
|
+
throw error;
|
|
128
|
+
}
|
|
129
|
+
return {
|
|
130
|
+
...grant,
|
|
131
|
+
access: result.json.access_token,
|
|
132
|
+
refresh: result.json.refresh_token ?? grant.refresh,
|
|
133
|
+
expires: now + Math.max(0, Number(result.json.expires_in) || 0) * 1000,
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/** A stored grant, or undefined for anything that is not one. */
|
|
138
|
+
export function parseGrant(value) {
|
|
139
|
+
if (typeof value !== 'string' || value.length === 0) return undefined;
|
|
140
|
+
let grant;
|
|
141
|
+
try { grant = JSON.parse(value); } catch { return undefined; }
|
|
142
|
+
const valid = grant?.version === GRANT_VERSION && typeof grant.access === 'string' && typeof grant.refresh === 'string'
|
|
143
|
+
&& Number.isFinite(grant.expires) && typeof grant.api === 'string' && URL.canParse(grant.api) && typeof grant.orgID === 'string';
|
|
144
|
+
return valid ? grant : undefined;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/** The account facts safe to show: no token ever leaves through here. */
|
|
148
|
+
export function grantSummary(grant, now = Date.now()) {
|
|
149
|
+
return { email: grant.email, orgName: grant.orgName, expiresInDays: Math.max(0, Math.round((grant.expires - now) / 86400000)) };
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* The grant as request auth, refreshed when it is about to expire. One refresh runs at a
|
|
154
|
+
* time per process; a refused refresh re-reads the store, because another DSCODE process
|
|
155
|
+
* may already have rotated the token.
|
|
156
|
+
*/
|
|
157
|
+
export class GrantSession {
|
|
158
|
+
/** @param store - `{ read(): Promise<string|undefined>, write(value): Promise<void> }` over the shared store. */
|
|
159
|
+
constructor(store, { fetch, now = () => Date.now() } = {}) {
|
|
160
|
+
this.store = store;
|
|
161
|
+
this.fetch = fetch;
|
|
162
|
+
this.now = now;
|
|
163
|
+
this.pending = undefined;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
async current() {
|
|
167
|
+
return parseGrant(await this.store.read());
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/** Request auth from the stored grant, or undefined when there is none. */
|
|
171
|
+
async auth() {
|
|
172
|
+
let grant = await this.current();
|
|
173
|
+
if (grant === undefined) return undefined;
|
|
174
|
+
if (grant.expires - this.now() < REFRESH_MARGIN_MS) grant = await this.refresh(grant);
|
|
175
|
+
return { apiKey: grant.access, baseURL: grant.api, headers: { 'x-opencode-org-id': grant.orgID } };
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
refresh(grant) {
|
|
179
|
+
this.pending ??= (async () => {
|
|
180
|
+
try {
|
|
181
|
+
const next = await refreshGrant(grant, { ...(this.fetch ? { fetch: this.fetch } : {}), now: this.now() });
|
|
182
|
+
await this.store.write(JSON.stringify(next));
|
|
183
|
+
return next;
|
|
184
|
+
} catch (error) {
|
|
185
|
+
const stored = await this.current();
|
|
186
|
+
if (stored !== undefined && stored.refresh !== grant.refresh && stored.expires - this.now() >= REFRESH_MARGIN_MS) return stored;
|
|
187
|
+
throw new LlmError(`OpenCode Go login ${error.invalidGrant ? 'expired or was revoked' : 'could not be refreshed'}; run /opencode login again`, 'AUTH', { cause: error });
|
|
188
|
+
} finally {
|
|
189
|
+
this.pending = undefined;
|
|
190
|
+
}
|
|
191
|
+
})();
|
|
192
|
+
return this.pending;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { WebError } from '@deepseek-ai/dsh-web';
|
|
2
|
+
|
|
3
|
+
// Web search for OpenCode Go sessions. Go has no search endpoint of its own; OpenCode's
|
|
4
|
+
// client searches through Exa's hosted MCP server, which answers without an API key, and
|
|
5
|
+
// DSCODE does the same so a Go session needs no DeepSeek or OpenRouter key to search.
|
|
6
|
+
// `EXA_API_KEY`, when set, moves the calls onto that Exa account.
|
|
7
|
+
export const EXA_SEARCH_ID = 'exa';
|
|
8
|
+
export const EXA_MCP_URL = 'https://mcp.exa.ai/mcp';
|
|
9
|
+
const DEFAULT_MAX_RESULTS = 8;
|
|
10
|
+
const CONTEXT_CHARACTERS = 10_000;
|
|
11
|
+
const SNIPPET_CHARACTERS = 1_000;
|
|
12
|
+
const TIMEOUT_MS = 25_000;
|
|
13
|
+
|
|
14
|
+
/** The JSON-RPC result text of an MCP answer, sent as one JSON body or as SSE `data:` lines. */
|
|
15
|
+
export function mcpText(body) {
|
|
16
|
+
const payloads = [body.trim(), ...body.split('\n').filter(line => line.startsWith('data:')).map(line => line.slice(5).trim())];
|
|
17
|
+
for (const payload of payloads) {
|
|
18
|
+
if (!payload.startsWith('{')) continue;
|
|
19
|
+
let parsed;
|
|
20
|
+
try { parsed = JSON.parse(payload); } catch { continue; }
|
|
21
|
+
if (parsed?.error) throw new WebError(`Exa search failed: ${typeof parsed.error.message === 'string' ? parsed.error.message : 'unknown error'}`, 'WEB_PROVIDER_ERROR');
|
|
22
|
+
const text = parsed?.result?.content?.find(item => typeof item?.text === 'string' && item.text.length > 0)?.text;
|
|
23
|
+
if (text !== undefined) return text;
|
|
24
|
+
}
|
|
25
|
+
return undefined;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Sources from Exa's text answer: `Title:`/`URL:`/`Highlights:` records separated by `---`.
|
|
30
|
+
* Records without a URL are dropped, and repeated URLs keep their first record.
|
|
31
|
+
*/
|
|
32
|
+
export function exaSources(text) {
|
|
33
|
+
const seen = new Set(), sources = [];
|
|
34
|
+
for (const record of text.split(/\n-{3,}\n/)) {
|
|
35
|
+
const url = record.match(/^URL:\s*(\S+)/m)?.[1];
|
|
36
|
+
if (!url || seen.has(url)) continue;
|
|
37
|
+
seen.add(url);
|
|
38
|
+
const title = record.match(/^Title:\s*(.+)$/m)?.[1]?.trim();
|
|
39
|
+
const cut = record.search(/^(?:Highlights|Text|Summary):/m);
|
|
40
|
+
const snippet = cut < 0 ? '' : record.slice(record.indexOf(':', cut) + 1).replace(/\n\.\.\.\n/g, '\n').trim().slice(0, SNIPPET_CHARACTERS);
|
|
41
|
+
sources.push({ url, ...(title ? { title } : {}), ...(snippet ? { snippet } : {}) });
|
|
42
|
+
}
|
|
43
|
+
return sources;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** Exa's `web_search_exa` tool over its hosted MCP endpoint. */
|
|
47
|
+
export class ExaSearchProvider {
|
|
48
|
+
id = EXA_SEARCH_ID;
|
|
49
|
+
|
|
50
|
+
/** @param resolveOptions - `{ resolveApiKey(), userAgent, fetch? }` for the next search. */
|
|
51
|
+
constructor(resolveOptions) {
|
|
52
|
+
this.resolveOptions = resolveOptions;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
available() {
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
async search(request, signal) {
|
|
60
|
+
const options = this.resolveOptions();
|
|
61
|
+
// An unreadable key store falls back to the keyless endpoint rather than failing the search.
|
|
62
|
+
const apiKey = await Promise.resolve(options.resolveApiKey?.()).catch(() => undefined);
|
|
63
|
+
const url = new URL(EXA_MCP_URL);
|
|
64
|
+
if (apiKey) url.searchParams.set('exaApiKey', apiKey);
|
|
65
|
+
const timeout = AbortSignal.timeout(TIMEOUT_MS);
|
|
66
|
+
const combined = signal ? AbortSignal.any([signal, timeout]) : timeout;
|
|
67
|
+
let response, body;
|
|
68
|
+
try {
|
|
69
|
+
response = await (options.fetch ?? globalThis.fetch)(url, {
|
|
70
|
+
method: 'POST', redirect: 'error', signal: combined,
|
|
71
|
+
headers: { 'content-type': 'application/json', accept: 'application/json, text/event-stream', ...(options.userAgent ? { 'user-agent': options.userAgent } : {}) },
|
|
72
|
+
body: JSON.stringify({ jsonrpc: '2.0', id: 1, method: 'tools/call', params: { name: 'web_search_exa', arguments: {
|
|
73
|
+
query: request.query, type: 'auto', numResults: request.maxResults ?? DEFAULT_MAX_RESULTS, livecrawl: 'fallback', contextMaxCharacters: CONTEXT_CHARACTERS,
|
|
74
|
+
} } }),
|
|
75
|
+
});
|
|
76
|
+
body = await response.text();
|
|
77
|
+
} catch (error) {
|
|
78
|
+
if (signal?.aborted) throw new WebError('Exa search was cancelled', 'WEB_ABORTED', { cause: error ?? signal.reason });
|
|
79
|
+
if (timeout.aborted) throw new WebError(`Exa search timed out after ${TIMEOUT_MS / 1000}s`, 'WEB_PROVIDER_ERROR', { cause: error });
|
|
80
|
+
throw new WebError(`Exa search request failed: ${error instanceof Error ? error.message : String(error)}`, 'WEB_PROVIDER_ERROR', { cause: error });
|
|
81
|
+
}
|
|
82
|
+
if (!response.ok) throw new WebError(`Exa search failed (HTTP ${response.status}): ${body.slice(0, 200)}`, 'WEB_PROVIDER_ERROR');
|
|
83
|
+
const text = mcpText(body);
|
|
84
|
+
return { sources: text === undefined ? [] : exaSources(text), truncated: false };
|
|
85
|
+
}
|
|
86
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
|
|
4
|
+
// What the OpenCode Go subscription has used. Go caps usage per rolling five hours, per week
|
|
5
|
+
// and per month; the account's inference service answers all three at `<root>/go/v1/usage`
|
|
6
|
+
// (the console's own proxy maps the public `/zen/go/v1/usage` there), with the account token
|
|
7
|
+
// and `x-opencode-org-id` — without the org header it answers 403. Each window carries a used
|
|
8
|
+
// percentage, `ok` or `rate-limited`, and when it resets.
|
|
9
|
+
//
|
|
10
|
+
// The endpoint is the console's own, not documented: every field is optional, and a shape
|
|
11
|
+
// change degrades to "usage unavailable", never to a wrong number. The status line runs in
|
|
12
|
+
// the terminal process, so the snapshot is also kept in DSH_HOME, as the Grok window is.
|
|
13
|
+
|
|
14
|
+
/** OpenCode's own clients poll no faster; one read a minute is plenty for a five-hour window. */
|
|
15
|
+
export const GO_USAGE_TTL_MS = 60_000;
|
|
16
|
+
export const WINDOWS = Object.freeze(['rolling', 'weekly', 'monthly']);
|
|
17
|
+
const FILE = 'opencode-go-usage.json';
|
|
18
|
+
const VERSION = 1;
|
|
19
|
+
let state;
|
|
20
|
+
let fetchedAt = 0;
|
|
21
|
+
let pending;
|
|
22
|
+
let disk;
|
|
23
|
+
|
|
24
|
+
/** The usage URL beside an account's chat endpoint (`…/go/openai/v1` → `…/go/v1/usage`), or undefined. */
|
|
25
|
+
export function usageURL(api) {
|
|
26
|
+
if (typeof api !== 'string' || !URL.canParse(api)) return undefined;
|
|
27
|
+
const url = new URL(api);
|
|
28
|
+
const path = url.pathname.replace(/\/+$/, '');
|
|
29
|
+
if (!/\/openai\/v1$/.test(path)) return undefined;
|
|
30
|
+
url.pathname = path.replace(/\/openai\/v1$/, '/v1/usage');
|
|
31
|
+
return url.href;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** The three windows from one usage body, each with `percent`, `limited` and `resetsAt` when present. */
|
|
35
|
+
export function parseGoUsage(body) {
|
|
36
|
+
const usage = {};
|
|
37
|
+
for (const name of WINDOWS) {
|
|
38
|
+
const window = body?.usage?.[name];
|
|
39
|
+
if (window === null || typeof window !== 'object') continue;
|
|
40
|
+
const percent = Number(window.percent);
|
|
41
|
+
const resetsAt = typeof window.resetsAt === 'string' && Number.isFinite(Date.parse(window.resetsAt)) ? window.resetsAt : undefined;
|
|
42
|
+
usage[name] = {
|
|
43
|
+
...(Number.isFinite(percent) ? { percent: Math.min(100, Math.max(0, percent)) } : {}),
|
|
44
|
+
...(window.status === 'rate-limited' ? { limited: true } : {}),
|
|
45
|
+
...(resetsAt ? { resetsAt } : {}),
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
return usage;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** One read with request auth from the grant session; undefined when it cannot be read. */
|
|
52
|
+
export async function fetchGoUsage(auth, { fetch: fetchImpl = globalThis.fetch, now = Date.now() } = {}) {
|
|
53
|
+
const url = usageURL(auth?.baseURL);
|
|
54
|
+
if (url === undefined || typeof fetchImpl !== 'function') return undefined;
|
|
55
|
+
try {
|
|
56
|
+
const response = await fetchImpl(url, { headers: { authorization: `Bearer ${auth.apiKey}`, accept: 'application/json', ...auth.headers } });
|
|
57
|
+
if (!response.ok) return undefined;
|
|
58
|
+
const usage = parseGoUsage(await response.json());
|
|
59
|
+
return Object.keys(usage).length === 0 ? undefined : { ...usage, fetchedAt: now };
|
|
60
|
+
} catch {
|
|
61
|
+
return undefined;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** Refresh at most once per interval, one read in flight; the last good snapshot survives a failed read. */
|
|
66
|
+
export async function currentGoUsage({ home, resolveAuth, fetch, now = Date.now() } = {}) {
|
|
67
|
+
if (state !== undefined && now - fetchedAt < GO_USAGE_TTL_MS) return state;
|
|
68
|
+
if (pending) return pending;
|
|
69
|
+
pending = (async () => {
|
|
70
|
+
const auth = await Promise.resolve(resolveAuth?.()).catch(() => undefined);
|
|
71
|
+
if (auth === undefined) return state;
|
|
72
|
+
const next = await fetchGoUsage(auth, { ...(fetch ? { fetch } : {}), now });
|
|
73
|
+
if (next !== undefined) {
|
|
74
|
+
state = next;
|
|
75
|
+
fetchedAt = now;
|
|
76
|
+
if (home !== undefined) writeGoUsage(home, next);
|
|
77
|
+
}
|
|
78
|
+
return state;
|
|
79
|
+
})().finally(() => { pending = undefined; });
|
|
80
|
+
return pending;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/** The snapshot the status line renders: this process's own, else the file another process wrote. */
|
|
84
|
+
export function goUsageNow(home = process.env.DSH_HOME, now = Date.now()) {
|
|
85
|
+
if (state !== undefined) return state;
|
|
86
|
+
if (home === undefined) return undefined;
|
|
87
|
+
if (disk !== undefined && disk.home === home && now - disk.at < GO_USAGE_TTL_MS) return disk.value;
|
|
88
|
+
let value;
|
|
89
|
+
try {
|
|
90
|
+
const cached = JSON.parse(readFileSync(join(home, FILE), 'utf8'));
|
|
91
|
+
if (cached?.version === VERSION) value = cached;
|
|
92
|
+
} catch { /* no snapshot yet */ }
|
|
93
|
+
disk = { home, at: now, value };
|
|
94
|
+
return value;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/** Atomic write of one snapshot; a failure leaves the previous file alone. */
|
|
98
|
+
export function writeGoUsage(home, snapshot) {
|
|
99
|
+
try {
|
|
100
|
+
mkdirSync(home, { recursive: true });
|
|
101
|
+
const path = join(home, FILE);
|
|
102
|
+
writeFileSync(`${path}.tmp`, JSON.stringify({ version: VERSION, ...snapshot }));
|
|
103
|
+
renameSync(`${path}.tmp`, path);
|
|
104
|
+
} catch { /* the status line keeps its previous state */ }
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/** Forget the snapshot, here and on disk: after signing out the status line shows no usage. */
|
|
108
|
+
export function clearGoUsage(home) {
|
|
109
|
+
setGoUsage(undefined, 0);
|
|
110
|
+
if (home !== undefined) rmSync(join(home, FILE), { force: true });
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/** Replace the in-memory snapshot; for tests. */
|
|
114
|
+
export function setGoUsage(next, at = Date.now()) {
|
|
115
|
+
state = next;
|
|
116
|
+
fetchedAt = at;
|
|
117
|
+
pending = undefined;
|
|
118
|
+
disk = undefined;
|
|
119
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
|
|
3
|
+
/** The DSCODE version third-party services see; the package root is two levels up in a checkout and in the bundle. */
|
|
4
|
+
export function dscodeVersion() {
|
|
5
|
+
try {
|
|
6
|
+
return JSON.parse(readFileSync(new URL('../../package.json', import.meta.url), 'utf8')).version;
|
|
7
|
+
} catch {
|
|
8
|
+
return undefined;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { LlmError } from '@deepseek-ai/dsh-llm';
|
|
2
|
+
import { serializeMessages } from '../openrouter/wire.mjs';
|
|
3
|
+
import { ultraRequest } from '../ultra/policy.mjs';
|
|
4
|
+
|
|
5
|
+
// OpenCode Go chat completions on the wire. Go forwards request fields to each model's
|
|
6
|
+
// upstream, which rejects OpenRouter's extensions (`reasoning: {effort}`, `provider`,
|
|
7
|
+
// `session_id`), so the body keeps to the OpenAI fields every upstream accepts. The SSE
|
|
8
|
+
// stream is OpenAI's too, so the OpenRouter translation reads it unchanged.
|
|
9
|
+
|
|
10
|
+
export const PROVIDER = 'opencode-go';
|
|
11
|
+
/** `replayState.response.kind` for responses this adapter produced. */
|
|
12
|
+
export const REPLAY_KIND = 'dscode-opencode-go';
|
|
13
|
+
export const LABEL = 'OpenCode Go';
|
|
14
|
+
const WIRE = Object.freeze({ off: 'none', low: 'low', high: 'high', max: 'max', ultra: 'max' });
|
|
15
|
+
// DeepSeek rejects a thinking-mode tool-call turn replayed without `reasoning_content`.
|
|
16
|
+
const REASONING_CONTENT_MODELS = /^deepseek-/;
|
|
17
|
+
const DIALECT = Object.freeze({ provider: PROVIDER, reasoningContent: model => REASONING_CONTENT_MODELS.test(model) });
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Reasoning controls a model offers through this route.
|
|
21
|
+
* @param entry - the model's catalog entry, if any.
|
|
22
|
+
* @returns `{ levels, defaultEffort, wire }`, or undefined when the catalog does not describe the model.
|
|
23
|
+
*/
|
|
24
|
+
export function modelReasoning(entry) {
|
|
25
|
+
if (!entry?.efforts?.length) return undefined;
|
|
26
|
+
const levels = [...entry.efforts];
|
|
27
|
+
return { levels, defaultEffort: levels.includes('high') ? 'high' : levels[0], wire: Object.fromEntries(levels.map(level => [level, WIRE[level]])) };
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** A title needs no deliberation: reasoning off when the model allows it, else its lowest level. */
|
|
31
|
+
function titleEffort(reasoning) {
|
|
32
|
+
return reasoning.levels[0];
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* The chat-completions body for one harness request.
|
|
37
|
+
* @param options - harness request (images already prepared into `images`).
|
|
38
|
+
* @param context - `{ entry, images }`: the model's catalog entry and prepared request images.
|
|
39
|
+
*/
|
|
40
|
+
export function requestBody(options, { entry, images } = {}) {
|
|
41
|
+
const reasoning = modelReasoning(entry);
|
|
42
|
+
const effort = options.purpose === 'session-title' && reasoning ? titleEffort(reasoning) : options.reasoningEffort;
|
|
43
|
+
const wireEffort = effort === undefined ? undefined : reasoning?.wire[effort];
|
|
44
|
+
if (effort !== undefined && reasoning !== undefined && wireEffort === undefined) {
|
|
45
|
+
throw new LlmError(`${LABEL} model "${options.model}" does not offer reasoning effort "${effort}"`, 'UNSUPPORTED_REASONING_EFFORT');
|
|
46
|
+
}
|
|
47
|
+
const messages = ultraRequest(options, serializeMessages(options.messages, { model: options.model, system: options.system, images, dialect: { ...DIALECT, provider: options.provider ?? PROVIDER } }));
|
|
48
|
+
// Delegation tools are offered at every effort; workflow and ralph never are.
|
|
49
|
+
const tools = (options.tools ?? []).filter(tool => tool.name !== 'workflow' && tool.name !== 'ralph')
|
|
50
|
+
.map(tool => ({ type: 'function', function: { name: tool.name, description: tool.description, parameters: tool.parameters } }));
|
|
51
|
+
return {
|
|
52
|
+
model: options.model,
|
|
53
|
+
messages,
|
|
54
|
+
stream: true,
|
|
55
|
+
stream_options: { include_usage: true },
|
|
56
|
+
...(tools.length > 0 ? { tools } : {}),
|
|
57
|
+
...(wireEffort !== undefined ? { reasoning_effort: wireEffort } : {}),
|
|
58
|
+
...(options.maxTokens !== undefined ? { max_tokens: options.maxTokens } : {}),
|
|
59
|
+
...(options.temperature !== undefined ? { temperature: options.temperature } : {}),
|
|
60
|
+
...(options.stop !== undefined ? { stop: options.stop } : {}),
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* A clearer message for Go's account-side refusals, or the gateway's own text.
|
|
66
|
+
* The DeepSeek rows need the workspace's Global region, a setting only the user can change.
|
|
67
|
+
*/
|
|
68
|
+
export function explainError(message) {
|
|
69
|
+
if (typeof message === 'string' && /requires Global regions/i.test(message)) {
|
|
70
|
+
return `${message} (OpenCode console → your workspace → Privacy → select Global)`;
|
|
71
|
+
}
|
|
72
|
+
return message;
|
|
73
|
+
}
|