dsh-web-search-ddg
aooyoo
Zero-token DuckDuckGo search provider for the DeepSeek Harness (DSH) web seam — local headless browser, no API key, no m…
PROJECT TOPICS
PROJECT README
English | 简体中文 | Português (Brasil)
After installation, open Settings → API Usage in DeepSeek Harness to view your DeepSeek API usage. The page shows your account balance, estimated spend, token counts, and API request count over the last 24 hours (14 days in the daily view), rendered as a timeline bar chart similar to the official DeepSeek platform usage page.
GET /user/balance endpoint.DEEPSEEK_API_KEY credential through the harness credentials service.┌─────────────────────────────── Host (Node.js) ───────────────────────────────┐
│ src/index.js │
│ • ctx.on('llm/stream', ...) ← waterfall: folds every real model call's │
│ provider-reported TokenUsage (input/output/cache-hit/cache-miss, │
│ already disjoint, matching DeepSeek billing vocabulary) │
│ into in-memory hourly + daily buckets │
│ • fetchBalance() ← credentials.resolve('DEEPSEEK_API_KEY') │
│ → subprocess curl → https://api.deepseek.com/user/balance │
│ (web.fetch cannot send an Authorization header, hence curl) │
│ • webServer.register('/ds-api-usage/snapshot') ← JSON endpoint for client │
└──────────────────────────────────────────────────────────────────────────────┘
│ fetch('/ds-api-usage/snapshot')
▼
┌────────────────────────────── Client (browser) ─────────────────────────────┐
│ client/bundle.js (web bundle; client/index.js = dynamic-plugin source) │
│ • slots.inject('settings.section') → new settings page (localized label) │
│ • balance card + 3 metric cards + timeline bar chart │
│ (cost / tokens / requests; 24h or 14d) │
│ • auto-refresh every 30 s (native setInterval in the static bundle) │
└──────────────────────────────────────────────────────────────────────────────┘
usage chunk of every streaming model call (StreamChunk with type: 'usage', TokenUsage), the same provider-reported numbers the harness itself uses for session stats.PRICING table (src/index.js), applied per model:hit pricemiss priceoutput pricepeak / offPeak rates are priced by the request's UTC hour (windows in peakHoursUtc; 01:00–04:00 and 06:00–10:00 UTC); the rest use their flat rate.$DSH_HOME/storages/ds-api-usage.json (writes debounced to at most one per 60 s, flushed on plugin shutdown, fail-safe: a read/write error never breaks accounting). The 14-day view therefore survives web-app restarts; delete the file to reset. The harness separately keeps its own durable per-session token projection.dsh plugin add (recommended, from GitHub or npm)Install directly from this GitHub repository:
dsh plugin --profile web add github:Sev7een/ds-api-usage
or, once published to npm:
dsh plugin --profile web add dsh-plugin-ds-api-usage
dsh plugin forwards to pnpm in the profile directory and reconciles the
package into the profile's bundle list (dsh.profile.bundles). The package's
cordis.patch.yml (declared via dsh.bundle.patch in package.json) then
inserts the plugin row into the host composition, and the dsh.client
declaration makes the web shell load client/bundle.js as the settings page.
The original is a dynamic Cordis plugin, created per session with cordis_define / cordis_run (see the DeepSeek Harness docs). The code.host body is src/index.js minus the module.exports wrapper; the code.client body is client/index.js minus the wrapper.
Note: the dynamic form uses the sandbox-private
harness.handle/host.callchannel (client/index.js), while the static bundle form (client/bundle.js) talks to the host over the HTTP route/ds-api-usage/snapshot. Keep both in sync when changing the protocol.
Add a row to the host composition (cordis.patch.yml of your profile):
- insert:
- id: ds-api-usage
name: 'dsh-plugin-ds-api-usage'
or, without installing the package, by a relative path to this repository. The plugin is host-plane: it reads the host credentials, subprocess, timer, and webServer services and registers the client settings page in the root-scoped settings.section slot, so it should live in the host composition, not inside an agent preset.
DEEPSEEK_API_KEY credential resolvable via the credentials service)curl available on the host for the balance endpointnpm run check # syntax-check both halves
npm test # offline test suite: pricing parser (fixtures) + peak/off-peak rate logic
.github/workflows/update-pricing.yml (daily cron + manual dispatch) re-parses the official pricing pages and opens a PR when the table changes; npm run update:pricing does the same locally (--apply writes the generated block in src/index.js). Edit the table only through the script — the block between the __PRICING_BEGIN__ / __PRICING_END__ markers is generated.locale service (namespace settings.ds-api-usage) and follows the harness's active locale: dictionaries ship for the harness's zh/en ids plus a pt-BR entry for future harness support (keys missing in the active locale fall back to zh).The repository ships two workflows — no secrets or API keys are required, and the only prerequisite is GitHub Actions being enabled for the repository (default; check Settings → Actions → General → Allow all actions):
ci.yml — runs on every push and pull request: npm run check (syntax of both halves) and npm test (offline test suite with page fixtures).update-pricing.yml — re-parses the official DeepSeek pricing pages every day (06:23 UTC cron) and on manual dispatch (Actions → update-pricing → Run workflow). When the table changes it opens a PR with the regenerated block (the workflow declares contents: write and pull-requests: write on the default GITHUB_TOKEN — nothing to configure). If the docs page is restructured, the parser validation fails and the job fails loudly instead of opening a bad PR.After the first push, run Actions → update-pricing → Run workflow once to validate the pipeline end-to-end (a no change result is the expected, green outcome when prices are current).
CLASSIFICATION EVIDENCE
系统优先读取 GitHub Topics,再与站内分类词典和词根规则比对。