songjongdevsecops/dsh-pico-detector

dsh-pico-detector

DeepSeek Harness plugin: live DeepSeek API peak/off-peak tariff state and spend tracking, for the agent, the chat, a sidebar chip and Settings (Windows, Linux, macOS).

未分類cordiscost-trackingdeepseek

dsh-pico-detector

DeepSeek sells its API at two rates: PEAK (full price) and OFF-PEAK (half price). This plugin tells you which one is in effect right now, and how much the API has cost you, inside DeepSeek Harness.

One plugin line, four surfaces:

WhoHowWhat you get
the agentpico_status and deepseek_spend toolsthe state now and the next transition, so it can decide to defer heavy work; the spend of the window
you, in the chat/pico and /gasto commandsthe same texts, read-only
you, in the GUIchip in the sidebar footercolored dot with the rate in effect, short label, countdown inside the approach window, spend of the window
you, in the GUISettings → Pico Detectorspend breakdown, FX rate, currency and window, next transitions, policy in effect

Peak rules are always evaluated in Beijing time (the official rule). Times are shown in your zone, taken from your machine; pin another zone with displayTimezone (see Configuration).

Requirements

  • Node.js ^22.19.0 || >=24.0.0 (the same range DeepSeek Harness supports).
  • pnpm on PATH — the harness manages profile plugins with it.
  • DeepSeek Harness itself, e.g. npx @deepseek-ai/dsh web.

Install

Works the same on Linux, macOS and Windows. Open a terminal (PowerShell is fine on Windows) and run:

# 1. pnpm (needed by `dsh plugin`)
npm install -g pnpm

# 2. add the plugin to your `web` profile
npx @deepseek-ai/dsh plugin --profile web add github:songjongdevsecops/dsh-pico-detector

# 3. restart the harness: the bundle layer is read at boot
#    stop `dsh web` (Ctrl+C) and start it again
npx @deepseek-ai/dsh web

If dsh is already installed globally, step 2 is dsh plugin --profile web add github:songjongdevsecops/dsh-pico-detector.

After the restart: the chip is at the bottom of the sidebar, the tools and the /pico, /gasto commands are live, and Settings → Pico Detector has the currency and window switches.

What the install does

dsh plugin add runs pnpm in ~/.dsh/profiles/web/ (on Windows, %USERPROFILE%\.dsh\profiles\web\), so the spec can be a GitHub repo, a tarball, a local path or a registry name. Because this package declares dsh.bundle.patch, the harness then appends dsh-pico-detector to dsh.profile.bundles in the profile manifest — that line in the profile is the only activation, and it is applied at every boot. Nothing else to configure.

The package has no build step and no native dependencies: plain ESM using only Node built-ins (node:zlib, node:fs, node:os). Nothing to compile on any OS.

Update and uninstall

# update: re-run the add command above (it resolves the repo again), then restart
npx @deepseek-ai/dsh plugin --profile web remove dsh-pico-detector   # uninstall, then restart

Peak policy (official)

Source: api-docs.deepseek.com/quick_start/pricing, checked on 2026-08-23 and again on 2026-09-10 (no rule change).

The official wording is in UTC: "Peak hours are 01:00 - 04:00 and 06:00 - 10:00 UTC, Monday through Friday (all other hours are off-peak)." Converted to Beijing time:

WindowBeijing (UTC+8)
PEAK, morning (Mon–Fri)09:00 – 12:00
PEAK, afternoon (Mon–Fri)14:00 – 18:00
OFF-PEAKevery other hour
Weekend (Sat–Sun in Beijing)all day OFF-PEAK

The week boundary follows the Beijing calendar, which matters at the edges of the day for anyone not in Beijing: the plugin computes it that way.

States

The state names are DeepSeek's own (peak / off-peak). The UI labels are in Portuguese.

StateLabelColorMeaning
off_peakOFF-PEAK (metade do preço)greenOFF-PEAK active, half price
peakPEAK (preço cheio)redPEAK active, full price
approaching_peakPEAK EM BREVEamberPEAK starts within approachMinutes
approaching_off_peakOFF-PEAK EM BREVEamberPEAK ends within approachMinutes

The color always means the rate in effect, never the incoming one: green only while OFF-PEAK is active, red only while PEAK is active. Amber is the current rate changing within the approach window, and then the label says which way. Default approach window: 30 minutes (approachMinutes).

Where the money number comes from

The DeepSeek API has no usage endpoint: GET /user/balance exists, and balance is not spend (it moves with top-ups, promo credits and any other client using the same key). What the invoice uses is the published rule tokens × price, and the tokens are recorded, per model step, with the instant and the model, in the harness's durable session ledger:

~/.dsh/sessions/<workspace>/<session>/session.v4.jsonl.zstd (v3 on older harnesses)

Each step is priced by the model in that event and by the tariff in effect at that event's instant (not at query time, which would be wrong on every day that crosses a window boundary), with the three buckets priced differently: input without cache, cache read and output.

ModelInput (1M)Cache read (1M)Output (1M)
deepseek-flashUS$ 0.15 / 0.30US$ 0.003 / 0.006US$ 0.60 / 1.20
deepseek-v4-proUS$ 0.66 / 1.32US$ 0.022 / 0.044US$ 1.98 / 3.96

(off-peak / peak; off-peak is half price. Source: api-docs.deepseek.com/quick_start/pricing, checked 2026-10-07.)

What the number does not cover, and the UI says so: LLM calls outside the agent loop (session titles, web search) record the request but not tokens, so the total is a floor. A model missing from the price table is priced as Flash and flagged as such. An unreadable session log is counted as an error and shown, never summed as zero.

Exchange rate: a chain of keyless public sources (awesomeapi → frankfurter → open.er-api), first one to answer wins and is named in the result; 30-minute cache. If all fail, the last reading is shown marked stale with its age and the reason; if there was never a reading, the total stays in USD instead of inventing a number.

Refresh cadence: the rate is checked every 10 s (pure computation) and the spend every 60 s (incremental disk read; ~1.3 ms in the steady state).

Configuration

Everything falls back to a sane default: a wrong config never breaks the detector. Override by id in your profile patch (~/.dsh/profiles/web/cordis.patch.yml). A patch replaces the whole config of the line, so restate every key you want to keep:

- id: pico-detector
  config:
    policy:
      timezone: 'Asia/Shanghai'
      peakWindows: [['09:00', '12:00'], ['14:00', '18:00']]
      weekendOffpeak: true
    displayTimezone: 'Europe/Lisbon'        # omit to use your machine's zone
    approachMinutes: 30
    spend:
      interval: 'today'                     # today | 24h | 7d | 30d | month
      currency: 'BRL'                       # any ISO-4217 code

Troubleshooting

  • pnpm not found on PATH — npm install -g pnpm, then re-run the command.
  • Plugin installed but nothing appears — restart the harness; the bundle layer is read at boot, not at install time.
  • Spend shows 0 while sessions exist — the ledger lives under $DSH_HOME (default ~/.dsh). If you moved it, set DSH_HOME or the spend.home config.
  • pnpm blocks a build script — it does not for this package: there is no prepare/build script. (A git-hosted dependency with one would need an allowBuilds entry.)
  • Wrong time zone — the default is your machine's zone; pin another with displayTimezone (see above).

Verification

The package ships its own check suite. Run it on the installed copy, which has the harness packages around it:

node ~/.dsh/profiles/web/node_modules/dsh-pico-detector/lib/selfcheck.mjs
# on Windows: %USERPROFILE%\.dsh\profiles\web\node_modules\dsh-pico-detector\lib\selfcheck.mjs

It covers the peak policy (windows, exact boundaries, weekend, timezone conversion, approach states and config fallback), pricing against the official table, the session-log container reader (concatenated frames, interrupted frame, corrupt file), a ledger fixture, the FX chain, money formatting and the UI registration.

License

MIT