@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,63 @@
|
|
|
1
|
+
import { clientRequestSchema } from '@deepseek-ai/dsh-client-connection';
|
|
2
|
+
import { assertUsableApiKey } from '@deepseek-ai/dsh-llm';
|
|
3
|
+
|
|
4
|
+
const keyRef = 'OPENROUTER_API_KEY';
|
|
5
|
+
const facts = value => ({ configured: value?.configured === true, writable: value?.writable === true, source: value?.source });
|
|
6
|
+
|
|
7
|
+
/** A fixed account surface; clients cannot choose arbitrary credential references. */
|
|
8
|
+
export async function providerAccountRequest(ctx, payload) {
|
|
9
|
+
const credentials = ctx.get('credentials'), login = ctx.get('dscodeOpenCodeLogin');
|
|
10
|
+
if (!credentials || !login) throw Error('DSCODE accounts are unavailable.');
|
|
11
|
+
let notice;
|
|
12
|
+
switch (payload?.action) {
|
|
13
|
+
case 'status': break;
|
|
14
|
+
case 'save-openrouter': {
|
|
15
|
+
if ((await credentials.describe(keyRef)).writable !== true) throw Error('OpenRouter credentials are controlled by the launching environment.');
|
|
16
|
+
if (typeof payload.key !== 'string' || payload.key.length > 4096) throw Error('Invalid API key.');
|
|
17
|
+
const key = assertUsableApiKey(payload.key.trim(), 'DSCODE OpenRouter', keyRef);
|
|
18
|
+
await credentials.set(keyRef, key);
|
|
19
|
+
notice = 'OpenRouter key saved. Select a model under DSCODE OpenRouter.';
|
|
20
|
+
break;
|
|
21
|
+
}
|
|
22
|
+
case 'remove-openrouter':
|
|
23
|
+
if ((await credentials.describe(keyRef)).writable !== true) throw Error('OpenRouter credentials are controlled by the launching environment.');
|
|
24
|
+
await credentials.unset(keyRef); notice = 'Saved OpenRouter key removed.'; break;
|
|
25
|
+
case 'login-opencode': {
|
|
26
|
+
const result = await login.login('en');
|
|
27
|
+
if (!result.ok) throw Error(result.lines.join('\n'));
|
|
28
|
+
notice = result.lines.join('\n');
|
|
29
|
+
break;
|
|
30
|
+
}
|
|
31
|
+
case 'cancel-opencode': notice = login.cancel('en'); break;
|
|
32
|
+
case 'logout-opencode': notice = await login.logout('en'); break;
|
|
33
|
+
default: throw Error('Unknown DSCODE account action.');
|
|
34
|
+
}
|
|
35
|
+
return {
|
|
36
|
+
openrouter: facts(await credentials.describe(keyRef)),
|
|
37
|
+
grok: facts(await credentials.describe('GROK_CLI_TOKEN')),
|
|
38
|
+
opencode: { ...facts(await credentials.describe('OPENCODE_OAUTH')), pending: login.attempt !== undefined, lines: await login.status('en') },
|
|
39
|
+
...(notice ? { notice } : {}),
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function apply(ctx) {
|
|
44
|
+
ctx.inject(['connection'], scope => {
|
|
45
|
+
scope.effect(() => scope.connection.fetch.register({ path: '/api/dscode-accounts', methods: ['POST'], requestBody: 'buffered',
|
|
46
|
+
fetch: async request => {
|
|
47
|
+
let body;
|
|
48
|
+
try { body = await request.json(); } catch { return new Response('Invalid JSON', { status: 400 }); }
|
|
49
|
+
const parsed = clientRequestSchema.safeParse(body);
|
|
50
|
+
if (!parsed.success || parsed.data.method !== 'dscode-accounts') return new Response('Invalid account request', { status: 400 });
|
|
51
|
+
const { rpcId, payload } = parsed.data;
|
|
52
|
+
let result;
|
|
53
|
+
try { result = { ok: true, value: await providerAccountRequest(ctx, payload) }; }
|
|
54
|
+
catch (error) {
|
|
55
|
+
const secret = typeof payload?.key === 'string' ? payload.key.trim() : '';
|
|
56
|
+
const message = String(error.message ?? 'Account request failed.');
|
|
57
|
+
result = { ok: false, error: { code: 'dscode-accounts', message: secret ? message.replaceAll(secret, '[redacted]') : message, details: {} } };
|
|
58
|
+
}
|
|
59
|
+
return Response.json({ type: 'server-response', rpcId, result }, { headers: { 'Cache-Control': 'no-store' } });
|
|
60
|
+
},
|
|
61
|
+
}), 'dscode-accounts.rpc');
|
|
62
|
+
}).then(undefined, error => { ctx.logger.error(`Account transport failed: ${error.message}`); });
|
|
63
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// Reasoning levels differ per model: DeepSeek offers low/high/max, GPT models
|
|
2
|
+
// minimal through high, and many OpenRouter models none at all. Auxiliary calls
|
|
3
|
+
// name the level they would like and send the nearest one the model offers, or no
|
|
4
|
+
// effort when the model offers no levels.
|
|
5
|
+
|
|
6
|
+
/** Standard reasoning levels, lowest first. */
|
|
7
|
+
export const EFFORT_LEVELS = Object.freeze(['minimal', 'low', 'medium', 'high', 'xhigh', 'max']);
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* The level to request from a model.
|
|
11
|
+
* @param offered - the model's effort ids, or `undefined` when its capability is unknown.
|
|
12
|
+
* @param wanted - the level the caller would like.
|
|
13
|
+
* @returns `wanted` when offered or when the capability is unknown; otherwise the nearest
|
|
14
|
+
* offered level at or above it, else the highest below; `undefined` when the model offers
|
|
15
|
+
* no standard level.
|
|
16
|
+
*/
|
|
17
|
+
export function chooseEffort(offered, wanted) {
|
|
18
|
+
if (wanted === undefined || offered === undefined || offered.includes(wanted)) return wanted;
|
|
19
|
+
const rank = EFFORT_LEVELS.indexOf(wanted);
|
|
20
|
+
const levels = EFFORT_LEVELS.filter(level => offered.includes(level));
|
|
21
|
+
if (rank < 0 || levels.length === 0) return undefined;
|
|
22
|
+
return levels.find(level => EFFORT_LEVELS.indexOf(level) >= rank) ?? levels.at(-1);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* {@link chooseEffort} for a route, reading the model's levels from the LLM service.
|
|
27
|
+
* A service without model metadata, or a failed lookup, keeps `wanted`.
|
|
28
|
+
*/
|
|
29
|
+
export async function effortFor(llm, route, wanted, signal) {
|
|
30
|
+
if (wanted === undefined || typeof llm?.resolveModelInfo !== 'function' || !route?.provider || !route?.model) return wanted;
|
|
31
|
+
let info;
|
|
32
|
+
try { info = await llm.resolveModelInfo(route.provider, route.model, signal); }
|
|
33
|
+
catch { return wanted; }
|
|
34
|
+
return chooseEffort(info?.reasoning?.efforts?.map(effort => effort.id) ?? [], wanted);
|
|
35
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { CONTEXT_WINDOW_EXCEEDED_CODE, QUOTA_EXCEEDED_CODE, isContextWindowExceededError, isQuotaExceededError } from '@deepseek-ai/dsh-llm';
|
|
2
|
+
|
|
3
|
+
// OpenRouter's typed `metadata.error_type`, which it asks clients to route on before the status.
|
|
4
|
+
const ERROR_TYPES = Object.freeze({
|
|
5
|
+
context_length_exceeded: CONTEXT_WINDOW_EXCEEDED_CODE, token_limit_exceeded: CONTEXT_WINDOW_EXCEEDED_CODE,
|
|
6
|
+
payment_required: QUOTA_EXCEEDED_CODE, authentication: 'AUTH', permission_denied: 'AUTH',
|
|
7
|
+
rate_limit_exceeded: 'RATE_LIMIT', provider_overloaded: 'SERVER', provider_unavailable: 'SERVER', server: 'SERVER', unmapped: 'SERVER',
|
|
8
|
+
timeout: 'TIMEOUT', content_policy_violation: 'CONTENT_POLICY', refusal: 'CONTENT_POLICY',
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Harness failure code for an OpenRouter error.
|
|
13
|
+
* @param status - HTTP status of a rejected request, or undefined for an error inside a 200 stream.
|
|
14
|
+
* @param error - the `error` object (`code`, `message`, `metadata`).
|
|
15
|
+
*/
|
|
16
|
+
export function errorCode(status, error) {
|
|
17
|
+
const type = error?.metadata?.error_type;
|
|
18
|
+
if (typeof type === 'string' && Object.hasOwn(ERROR_TYPES, type)) return ERROR_TYPES[type];
|
|
19
|
+
const code = Number.isInteger(status) ? status : Number(error?.code);
|
|
20
|
+
// A 402 names token counts ("fewer max_tokens"); its status decides before any wording does.
|
|
21
|
+
if (code === 402) return QUOTA_EXCEEDED_CODE;
|
|
22
|
+
// OpenRouter can reject a replay before generation without typed metadata.
|
|
23
|
+
// Keep this narrow: an ordinary permission-denied 403 still means AUTH.
|
|
24
|
+
if (code === 403 && typeof error?.message === 'string' && /^Request blocked by content filter\b/i.test(error.message)) return 'CONTENT_POLICY';
|
|
25
|
+
const detail = [error?.message, error?.metadata?.raw].filter(value => typeof value === 'string').join(' ');
|
|
26
|
+
if (isContextWindowExceededError(detail)) return CONTEXT_WINDOW_EXCEEDED_CODE;
|
|
27
|
+
if (isQuotaExceededError(detail)) return QUOTA_EXCEEDED_CODE;
|
|
28
|
+
if (code === 401 || code === 403) return 'AUTH';
|
|
29
|
+
if (code === 429) return 'RATE_LIMIT';
|
|
30
|
+
if (code === 408 || code === 504) return 'TIMEOUT';
|
|
31
|
+
if (code >= 500) return 'SERVER';
|
|
32
|
+
if (code >= 400) return 'INVALID_REQUEST';
|
|
33
|
+
// A stream that failed after its 200 without a numeric code is an upstream failure worth retrying.
|
|
34
|
+
return 'SERVER';
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** Human-readable message for an OpenRouter error object. */
|
|
38
|
+
export function errorMessage(error, fallback) {
|
|
39
|
+
const message = typeof error?.message === 'string' && error.message.length > 0 ? error.message : fallback;
|
|
40
|
+
const provider = error?.metadata?.provider_name;
|
|
41
|
+
return typeof provider === 'string' && provider.length > 0 ? `${message} (provider: ${provider})` : message;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** Retry-After as milliseconds (seconds or an HTTP date), when valid. */
|
|
45
|
+
export function retryAfterMs(value) {
|
|
46
|
+
if (value === null || value === undefined) return undefined;
|
|
47
|
+
const delay = /^\d+$/.test(value) ? Number(value) * 1e3 : Date.parse(value) - Date.now();
|
|
48
|
+
return Number.isFinite(delay) && delay > 0 ? delay : undefined;
|
|
49
|
+
}
|
|
50
|
+
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
// OpenRouter account facts for /openrouter and the footer balance. The inference key
|
|
2
|
+
// reads the account credits and its own limit and usage; an optional management key,
|
|
3
|
+
// which cannot call models, adds every key's usage and the last 30 days of spend.
|
|
4
|
+
// This directory also ships beside the TUI, so the module imports nothing.
|
|
5
|
+
export const OPENROUTER_API = 'https://openrouter.ai/api/v1';
|
|
6
|
+
export const MANAGEMENT_REF = 'OPENROUTER_MANAGEMENT_KEY';
|
|
7
|
+
|
|
8
|
+
const finite = value => {
|
|
9
|
+
const number = Number(value);
|
|
10
|
+
return value !== null && value !== undefined && value !== '' && Number.isFinite(number) ? number : undefined;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export class OpenRouterAccountError extends Error {
|
|
14
|
+
constructor(message, status) {
|
|
15
|
+
super(message);
|
|
16
|
+
this.name = 'OpenRouterAccountError';
|
|
17
|
+
this.status = status;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
async function get(path, key, { fetch: fetchImpl = globalThis.fetch, signal } = {}) {
|
|
22
|
+
let response;
|
|
23
|
+
try {
|
|
24
|
+
response = await fetchImpl(`${OPENROUTER_API}${path}`, { headers: { authorization: `Bearer ${key}`, accept: 'application/json' }, signal });
|
|
25
|
+
} catch (error) {
|
|
26
|
+
throw new OpenRouterAccountError(`OpenRouter is unreachable: ${error instanceof Error ? error.message : String(error)}`);
|
|
27
|
+
}
|
|
28
|
+
let body;
|
|
29
|
+
try { body = await response.json(); } catch { body = undefined; }
|
|
30
|
+
if (!response.ok) throw new OpenRouterAccountError(typeof body?.error?.message === 'string' ? body.error.message : `HTTP ${response.status}`, response.status);
|
|
31
|
+
return body;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** Account credits from a `/credits` body, or undefined when it carries none. */
|
|
35
|
+
export function creditsOf(body) {
|
|
36
|
+
const total = finite(body?.data?.total_credits), used = finite(body?.data?.total_usage);
|
|
37
|
+
if (total === undefined || used === undefined || total < 0 || used < 0) return undefined;
|
|
38
|
+
return { total, used, remaining: Math.max(0, total - used) };
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** Remaining USD account credits from a `/credits` body: purchased minus used. */
|
|
42
|
+
export function parseOpenRouterCredits(body) {
|
|
43
|
+
return creditsOf(body)?.remaining ?? null;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** Remaining USD credit limit from a `/key` body; null when the key has no limit. */
|
|
47
|
+
export function parseOpenRouterKeyRemaining(body) {
|
|
48
|
+
const remaining = body?.data?.limit_remaining;
|
|
49
|
+
if (remaining == null) return null;
|
|
50
|
+
const value = Number(remaining);
|
|
51
|
+
return Number.isFinite(value) ? Math.max(0, value) : null;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function keyOf(raw) {
|
|
55
|
+
return {
|
|
56
|
+
label: typeof raw?.label === 'string' ? raw.label : undefined,
|
|
57
|
+
name: typeof raw?.name === 'string' && raw.name.length > 0 ? raw.name : undefined,
|
|
58
|
+
disabled: raw?.disabled === true,
|
|
59
|
+
limit: finite(raw?.limit),
|
|
60
|
+
limitRemaining: finite(raw?.limit_remaining),
|
|
61
|
+
usage: finite(raw?.usage),
|
|
62
|
+
usageDaily: finite(raw?.usage_daily),
|
|
63
|
+
usageWeekly: finite(raw?.usage_weekly),
|
|
64
|
+
usageMonthly: finite(raw?.usage_monthly),
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Verify a management key before it is stored. Account activity is the reading OpenRouter
|
|
70
|
+
* refuses an inference key; `/credits`, though documented as management-only, serves both.
|
|
71
|
+
* @throws OpenRouterAccountError with a message fit for the key prompt.
|
|
72
|
+
*/
|
|
73
|
+
export async function verifyManagementKey(key, options) {
|
|
74
|
+
try {
|
|
75
|
+
await get('/activity', key, options);
|
|
76
|
+
} catch (error) {
|
|
77
|
+
if (error instanceof OpenRouterAccountError && (error.status === 401 || error.status === 403)) {
|
|
78
|
+
throw new OpenRouterAccountError('This is not a management key: OpenRouter refused it for account data. Create one under Settings → Management keys.', error.status);
|
|
79
|
+
}
|
|
80
|
+
throw error;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/** The `/activity` rows (last 30 completed UTC days) as totals and the top models with the providers that served them. */
|
|
85
|
+
export function summarizeActivity(rows, top = 5) {
|
|
86
|
+
const models = new Map(), days = new Set();
|
|
87
|
+
let usage = 0, requests = 0;
|
|
88
|
+
for (const row of Array.isArray(rows) ? rows : []) {
|
|
89
|
+
if (typeof row?.model !== 'string') continue;
|
|
90
|
+
const cost = finite(row.usage) ?? 0, count = finite(row.requests) ?? 0;
|
|
91
|
+
usage += cost;
|
|
92
|
+
requests += count;
|
|
93
|
+
if (typeof row.date === 'string') days.add(row.date);
|
|
94
|
+
const entry = models.get(row.model) ?? { model: row.model, usage: 0, requests: 0, providers: new Map() };
|
|
95
|
+
entry.usage += cost;
|
|
96
|
+
entry.requests += count;
|
|
97
|
+
const name = typeof row.provider_name === 'string' && row.provider_name.length > 0 ? row.provider_name : 'unknown';
|
|
98
|
+
const served = entry.providers.get(name) ?? { name, usage: 0, requests: 0 };
|
|
99
|
+
served.usage += cost;
|
|
100
|
+
served.requests += count;
|
|
101
|
+
entry.providers.set(name, served);
|
|
102
|
+
models.set(row.model, entry);
|
|
103
|
+
}
|
|
104
|
+
const ranked = [...models.values()].sort((left, right) => right.usage - left.usage || right.requests - left.requests).slice(0, top)
|
|
105
|
+
.map(entry => ({ ...entry, providers: [...entry.providers.values()].sort((left, right) => right.usage - left.usage) }));
|
|
106
|
+
return { usage, requests, days: days.size, modelCount: models.size, models: ranked };
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Everything /openrouter shows. Each section settles on its own: `{ value }`, `{ error }`,
|
|
111
|
+
* or undefined when the key it needs is missing.
|
|
112
|
+
*/
|
|
113
|
+
export async function loadOpenRouterAccount({ apiKey, managementKey, fetch, signal } = {}) {
|
|
114
|
+
const options = { fetch, signal };
|
|
115
|
+
const section = (key, run) => key ? run().then(value => ({ value }), error => ({ error: error instanceof Error ? error.message : String(error) })) : Promise.resolve(undefined);
|
|
116
|
+
const [key, credits, keys, activity] = await Promise.all([
|
|
117
|
+
section(apiKey, async () => keyOf((await get('/key', apiKey, options))?.data)),
|
|
118
|
+
section(managementKey ?? apiKey, async () => {
|
|
119
|
+
const credits = creditsOf(await get('/credits', managementKey ?? apiKey, options));
|
|
120
|
+
if (!credits) throw new Error('OpenRouter returned no account credits');
|
|
121
|
+
return credits;
|
|
122
|
+
}),
|
|
123
|
+
section(managementKey, async () => {
|
|
124
|
+
const body = await get('/keys', managementKey, options);
|
|
125
|
+
return (Array.isArray(body?.data) ? body.data : []).map(keyOf);
|
|
126
|
+
}),
|
|
127
|
+
section(managementKey, async () => summarizeActivity((await get('/activity', managementKey, options))?.data)),
|
|
128
|
+
]);
|
|
129
|
+
return { hasApiKey: Boolean(apiKey), hasManagementKey: Boolean(managementKey), key, credits, keys, activity };
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const money = value => Number.isFinite(value) ? `$${value.toFixed(2)}` : '$--';
|
|
133
|
+
const limitText = key => key.limit === undefined ? 'no limit' : `limit ${money(key.limit)}, ${money(key.limitRemaining)} left`;
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* The panel's lines for a loaded account.
|
|
137
|
+
* @returns `{ text, tone }` rows; tone is `title`, `value`, `dim` or `error`.
|
|
138
|
+
*/
|
|
139
|
+
export function openRouterAccountLines(account, { maxKeys = 5 } = {}) {
|
|
140
|
+
const lines = [];
|
|
141
|
+
const push = (text, tone = 'value') => lines.push({ text, tone });
|
|
142
|
+
if (!account.hasApiKey) push('No OpenRouter API key: run /login openrouter.', 'error');
|
|
143
|
+
if (account.credits?.value) {
|
|
144
|
+
const { remaining, total, used } = account.credits.value;
|
|
145
|
+
push(`Account balance ${money(remaining)} · credits ${money(total)} · used ${money(used)}`, 'title');
|
|
146
|
+
} else if (account.credits?.error) push(`Account balance unavailable: ${account.credits.error}`, 'error');
|
|
147
|
+
else push('Account balance $--', 'dim');
|
|
148
|
+
if (account.key?.value) {
|
|
149
|
+
const key = account.key.value;
|
|
150
|
+
push(`This key ${key.label ?? 'unnamed'} · ${limitText(key)}`, 'title');
|
|
151
|
+
push(` today ${money(key.usageDaily)} · week ${money(key.usageWeekly)} · month ${money(key.usageMonthly)}`, 'dim');
|
|
152
|
+
} else if (account.key?.error) push(`This key unavailable: ${account.key.error}`, 'error');
|
|
153
|
+
if (!account.hasManagementKey) push('API keys and 30-day spend press m to add a management key', 'dim');
|
|
154
|
+
if (account.keys?.value) {
|
|
155
|
+
const keys = [...account.keys.value].sort((left, right) => (right.usageMonthly ?? 0) - (left.usageMonthly ?? 0));
|
|
156
|
+
push(`API keys (${keys.length})`, 'title');
|
|
157
|
+
for (const key of keys.slice(0, maxKeys)) {
|
|
158
|
+
const current = account.key?.value?.label !== undefined && key.label === account.key.value.label;
|
|
159
|
+
push(` ${key.name ?? key.label ?? 'unnamed'}${current ? ' (this key)' : ''}${key.disabled ? ' · disabled' : ''} · today ${money(key.usageDaily)} · month ${money(key.usageMonthly)} · ${limitText(key)}`, key.disabled ? 'dim' : 'value');
|
|
160
|
+
}
|
|
161
|
+
if (keys.length > maxKeys) push(` +${keys.length - maxKeys} more`, 'dim');
|
|
162
|
+
} else if (account.keys?.error) push(`API keys unavailable: ${account.keys.error}`, 'error');
|
|
163
|
+
if (account.activity?.value) {
|
|
164
|
+
const activity = account.activity.value;
|
|
165
|
+
push(`Last 30 days ${money(activity.usage)} · ${activity.requests} requests · ${activity.modelCount} models`, 'title');
|
|
166
|
+
for (const model of activity.models) {
|
|
167
|
+
push(` ${model.model} · ${money(model.usage)} · ${model.requests} req · ${model.providers.map(provider => `${provider.name} ${money(provider.usage)}`).join(', ')}`);
|
|
168
|
+
}
|
|
169
|
+
} else if (account.activity?.error) push(`Activity unavailable: ${account.activity.error}`, 'error');
|
|
170
|
+
return lines;
|
|
171
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { createConnection } from 'node:net';
|
|
2
|
+
import { readdirSync } from 'node:fs';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { randomUUID } from 'node:crypto';
|
|
5
|
+
import { socketDirectory } from './paths.mjs';
|
|
6
|
+
|
|
7
|
+
export const CLIENT_COMMANDS = ['sessions', 'send', 'reply', 'read', 'watch', 'mailbox', 'watch-mailbox', 'cancel', 'new-task'];
|
|
8
|
+
export async function* exchange(path, request, { signal } = {}) {
|
|
9
|
+
const socket = createConnection({ path });
|
|
10
|
+
socket.setEncoding('utf8');
|
|
11
|
+
socket.setTimeout(10000, () => socket.destroy(Error('DSCODE endpoint timed out')));
|
|
12
|
+
const abort = () => socket.destroy();
|
|
13
|
+
signal?.addEventListener('abort', abort, { once: true });
|
|
14
|
+
try {
|
|
15
|
+
signal?.throwIfAborted();
|
|
16
|
+
socket.write(JSON.stringify(request) + '\n');
|
|
17
|
+
let buffer = '';
|
|
18
|
+
for await (const chunk of socket) {
|
|
19
|
+
buffer += chunk;
|
|
20
|
+
if (Buffer.byteLength(buffer) > 16 * 1024 * 1024) throw Error('DSCODE response exceeds limit');
|
|
21
|
+
let index;
|
|
22
|
+
while ((index = buffer.indexOf('\n')) >= 0) {
|
|
23
|
+
const value = JSON.parse(buffer.slice(0, index)); buffer = buffer.slice(index + 1);
|
|
24
|
+
if (value.error) throw Object.assign(Error(value.error), { code: value.code });
|
|
25
|
+
if (value.type === 'ready') socket.setTimeout(0);
|
|
26
|
+
yield value;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
if (buffer.trim()) throw Error('Incomplete DSCODE response; retry with the same requestId/cursor');
|
|
30
|
+
} finally { signal?.removeEventListener('abort', abort); socket.destroy(); }
|
|
31
|
+
}
|
|
32
|
+
export async function request(path, payload) {
|
|
33
|
+
for await (const value of exchange(path, payload)) return value.result;
|
|
34
|
+
throw Error('DSCODE connection closed before acknowledgement; retry with the same requestId');
|
|
35
|
+
}
|
|
36
|
+
export async function discover(home) {
|
|
37
|
+
let directory;
|
|
38
|
+
try { directory = socketDirectory(home); } catch (error) { if (error.code === 'ENOENT') return []; throw error; }
|
|
39
|
+
const endpoints = readdirSync(directory).filter(n => /^\d+-[a-f0-9]{8}\.sock$/.test(n));
|
|
40
|
+
const results = await Promise.all(endpoints.map(async name => {
|
|
41
|
+
const path = join(directory, name);
|
|
42
|
+
try { return (await request(path, { method: 'list' })).map(session => ({ ...session, socket: path })); }
|
|
43
|
+
catch (error) { if (['ECONNREFUSED', 'ENOENT'].includes(error.code)) return []; throw error; }
|
|
44
|
+
}));
|
|
45
|
+
return results.flat();
|
|
46
|
+
}
|
|
47
|
+
export function resolveSession(sessions, id) {
|
|
48
|
+
const exact = sessions.filter(s => s.id === id);
|
|
49
|
+
const matches = exact.length ? exact : sessions.filter(s => s.id.startsWith(id));
|
|
50
|
+
if (matches.length !== 1) throw Error(matches.length ? 'Ambiguous session; use its complete ID' : 'No active session found. Run dscode sessions or open the session in dscode first.');
|
|
51
|
+
return matches[0];
|
|
52
|
+
}
|
|
53
|
+
export function parseClientArgs(argv) {
|
|
54
|
+
const [command, ...args] = argv;
|
|
55
|
+
const result = { command, mode: 'queue', source: 'cli', after: command.includes('mailbox') ? 0 : -1, limit: 100, requestId: randomUUID() };
|
|
56
|
+
if (!CLIENT_COMMANDS.includes(command)) throw Error('Unknown session command');
|
|
57
|
+
if (command !== 'sessions') { result.sessionId = args.shift(); if (!result.sessionId || result.sessionId.startsWith('-')) throw Error(`Usage: dscode ${command} SESSION_ID`); }
|
|
58
|
+
const text = []; let modeSet = false;
|
|
59
|
+
while (args.length) {
|
|
60
|
+
const arg = args.shift();
|
|
61
|
+
if (arg === '--') { text.push(...args); break; }
|
|
62
|
+
if (['--steer', '--defer'].includes(arg) && ['send', 'reply'].includes(command)) {
|
|
63
|
+
if (modeSet) throw Error('Choose only one of --steer and --defer');
|
|
64
|
+
modeSet = true; result.mode = arg === '--steer' ? 'steer' : 'defer'; continue;
|
|
65
|
+
}
|
|
66
|
+
const names = { '--source': 'source', '--title': 'title', '--kind': 'kind', '--reply-to': 'inReplyTo', '--request-id': 'requestId', '--after': 'after', '--limit': 'limit', '--home': 'home' };
|
|
67
|
+
if (names[arg]) {
|
|
68
|
+
const allowed = arg === '--home' || command === 'send' && ['--source', '--title', '--request-id', '--kind'].includes(arg) || command === 'reply' && ['--reply-to', '--request-id'].includes(arg) || ['read', 'watch', 'mailbox', 'watch-mailbox'].includes(command) && arg === '--after' || ['read', 'mailbox'].includes(command) && arg === '--limit';
|
|
69
|
+
if (!allowed || !args.length) throw Error(`Invalid ${arg} option`);
|
|
70
|
+
const value = args.shift(); result[names[arg]] = ['--after', '--limit'].includes(arg) ? Number(value) : value;
|
|
71
|
+
} else if (arg.startsWith('-')) throw Error(`Unknown option ${arg}`);
|
|
72
|
+
else text.push(arg);
|
|
73
|
+
}
|
|
74
|
+
if (['send', 'reply'].includes(command)) { result.text = text.join(' '); if (!result.text.trim()) throw Error('Send requires message text'); }
|
|
75
|
+
else if (command === 'cancel' && text.length === 1) result.messageId = text[0];
|
|
76
|
+
else if (text.length) throw Error('Unexpected arguments');
|
|
77
|
+
if (command === 'reply' && !result.inReplyTo) throw Error('Reply requires --reply-to REQUEST_MESSAGE_ID');
|
|
78
|
+
if (command === 'cancel' && !result.messageId) throw Error('Cancel requires MESSAGE_ID');
|
|
79
|
+
if (result.kind && !['request', 'notify'].includes(result.kind)) throw Error('Kind must be request or notify');
|
|
80
|
+
return result;
|
|
81
|
+
}
|
|
82
|
+
export async function runClient(argv, defaultHome) {
|
|
83
|
+
const options = parseClientArgs(argv);
|
|
84
|
+
const sessions = await discover(options.home ?? defaultHome);
|
|
85
|
+
if (options.command === 'sessions') { console.log(JSON.stringify(sessions, null, 2)); return; }
|
|
86
|
+
const session = resolveSession(sessions, options.sessionId);
|
|
87
|
+
const payload = { method: options.command, sessionId: session.id, after: options.after, limit: options.limit,
|
|
88
|
+
text: options.text, title: options.title, mode: options.mode, source: options.source, requestId: options.requestId,
|
|
89
|
+
kind: options.kind, inReplyTo: options.inReplyTo, messageId: options.messageId };
|
|
90
|
+
if (!['watch', 'watch-mailbox'].includes(options.command)) {
|
|
91
|
+
// Print the identity before dispatch so even a lost ACK can be retried.
|
|
92
|
+
if (['send', 'reply'].includes(options.command)) process.stderr.write(`requestId: ${options.requestId}\n`);
|
|
93
|
+
console.log(JSON.stringify(await request(session.socket, payload), null, 2)); return;
|
|
94
|
+
}
|
|
95
|
+
const controller = new AbortController();
|
|
96
|
+
const abort = () => controller.abort(); process.once('SIGINT', abort);
|
|
97
|
+
let closed = false;
|
|
98
|
+
try {
|
|
99
|
+
for await (const value of exchange(session.socket, payload, { signal: controller.signal })) {
|
|
100
|
+
await new Promise((resolve, reject) => process.stdout.write(JSON.stringify(value) + '\n', error => error ? reject(error) : resolve()));
|
|
101
|
+
if (value.type === 'closed') closed = true;
|
|
102
|
+
}
|
|
103
|
+
if (!closed && !controller.signal.aborted) throw Error('Stream disconnected. Reconnect with --after set to the last received event seq.');
|
|
104
|
+
} catch (error) { if (!controller.signal.aborted) throw error; }
|
|
105
|
+
finally { process.off('SIGINT', abort); }
|
|
106
|
+
}
|