Implement extensions/vision/src/usage.ts (usage mapping + peak/off-peak cost) #256
Labels
No labels
bug
chore
documentation
enhancement
feature
ready
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
david/pi-extensions-and-skills#256
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Create
extensions/vision/src/usage.ts: translate DeepSeek's chat-completionusageobject into pi'sUsageshape (token counts plus cost) and compute the cost from thedeepseek-flashpeak/off-peak rate table. Pure functions, no IO.Background
The
visiontool returnsusagealongside its text so pi can account for the nested call in the footer,/session, and RPC session totals (pinned pi docs,docs/extensions.md, "Usage accounting"). DeepSeek reports tokens differently from pi (separate cache-hit/cache-miss input counters, a reasoning breakdown) and does not report cost at all, so this module is the adapter.DeepSeek's rates depend on the time of day and are published as peak/off-peak columns; the cost calculation must therefore derive the rate from a
Date. Peak windows are UTC[01:00, 04:00)and[06:00, 10:00)Monday–Friday; everything else is off-peak. Because DeepSeek can change prices or peak hours, the table is documented as best-effort against the published page (see the risks section of the implementation plan).No tests in this module may hit the network, so the
atargument must be injectable (mapUsage(usage, at?)).Documentation Required
A separate process downloads these into the listed folders before this issue is implemented. Check the folder for the actual reference material before starting.
docs/reference/deepseek-api/usageobject field list:completion_tokens,prompt_tokens,prompt_cache_hit_tokens,prompt_cache_miss_tokens,total_tokens,completion_tokens_details.reasoning_tokens.deepseek-flash(off-peak/peak cache-hit input, cache-miss input, output) and the peak-hours definition (01:00 - 04:00and06:00 - 10:00 UTC, Monday through Friday).docs/reference/pi-coding-agent/node_modules/@earendil-works/pi-coding-agent/docs/extensions.md, section "Usage accounting" — how a tool's returnedusageis consumed.node_modules/@earendil-works/pi-coding-agent/node_modules/@earendil-works/pi-ai/dist/types.d.ts,interface Usage— the exact target shape (input,output,cacheRead,cacheWrite,reasoning?,totalTokens,cost.{input,output,cacheRead,cacheWrite,total}).docs/reference/nodejs/Date.prototype.getUTCDay/getUTCHours, so peak detection is timezone-independent.Implementation Details
Public surface:
Mapping (pi field ← DeepSeek field):
inputprompt_cache_miss_tokenscacheReadprompt_cache_hit_tokenscacheWrite0outputcompletion_tokensreasoningcompletion_tokens_details?.reasoning_tokenstotalTokenstotal_tokenscost.inputcost.cacheReadcost.outputcost.cacheWrite0cost.totalcost.input + cost.cacheRead + cost.outputRate table for
deepseek-flash, USD per 1M tokens — keep it as a single exported constant with a comment linking the pricing page:Details:
Usagetype from the pi package (repo precedent for pi type imports exists in other extensions) or declare a structurally-identical local type; either waymapUsage's return type must be pi'sUsage.0;reasoningstaysundefinedwhen the breakdown is absent (matching pi's "left undefined by providers that don't" contract). Document that choice.getUTCDay()1–5 (Mon–Fri), andgetUTCHours()in[1,4)or[6,10). Saturday and Sunday are always off-peak.tokens * usdPerMillion / 1_000_000); do not round insidemapUsage— return the raw product so callers can format as they like.mapUsagemust be pure;atdefaults tonew Date().Test file
extensions/vision/src/usage.test.ts(TDD):cacheReadandreasoning.prompt_cache_hit_tokens: 0) and the all-undefined usage object.undefinedusage ⇒undefined.01:00,04:00,06:00,10:00UTC — each boundary test asserts both the preceding minute (off/exclusive side) and the boundary instant.02:00and07:00UTC.Acceptance Criteria
mapUsagemaps every field exactly as tabled, withcacheWriteand its cost0.reasoningisundefined(not0) whencompletion_tokens_detailsis absent.undefinedusage returnsundefined; missing numeric fields are treated as0.isPeakis true only for UTC Mon–Fri[01:00,04:00)and[06:00,10:00); all other instants (including all weekend hours) are off-peak.deepseek-flashrates andcost.totalequals the sum of the three components.extensions/vision/src/usage.test.tspasses withnode --test extensions/vision/src/usage.test.tsand touches no network.Test Plan
Expected: all tests pass, no network access, no files written.
Manual spot check of peak detection:
Expected:
true,true,false,false(the last is a Saturday).pi-loop opened and merged a pull request for this issue: #270