dsh-simple-usage-info 0.1.0
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 +269 -0
- package/cordis.patch.yml +35 -0
- package/lib/client.d.ts +85 -0
- package/lib/client.js +620 -0
- package/lib/holiday-source.d.ts +54 -0
- package/lib/holiday-source.js +154 -0
- package/lib/holidays.d.ts +19 -0
- package/lib/holidays.js +109 -0
- package/lib/index.d.ts +46 -0
- package/lib/index.js +263 -0
- package/lib/pricing.d.ts +105 -0
- package/lib/pricing.js +225 -0
- package/package.json +88 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Marjose Darang
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
# dsh-simple-usage-info
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/dsh-simple-usage-info)
|
|
4
|
+
[](LICENSE)
|
|
5
|
+
|
|
6
|
+
A [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) plugin that puts your
|
|
7
|
+
**DeepSeek API balance** and the **current billing window** in the composer dock — the ambient row
|
|
8
|
+
directly below the message input, after the context meter.
|
|
9
|
+
|
|
10
|
+
```
|
|
11
|
+
┌──────────────────────────────────────────────────────────┐
|
|
12
|
+
│ Ask anything… │
|
|
13
|
+
│ [ model ] ▸ │
|
|
14
|
+
└──────────────────────────────────────────────────────────┘
|
|
15
|
+
◐ 12% ● DeepSeek ¥22.48 (Off-peak)
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Click the bar for the full breakdown:
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
● DeepSeek account ¥22.48
|
|
22
|
+
─────────────────────────────────────────────────────────────
|
|
23
|
+
Billing window
|
|
24
|
+
Billing Off-peak
|
|
25
|
+
Applies because Chinese public holiday
|
|
26
|
+
Peak hours today (Asia/Manila) 09:00–12:00, 14:00–18:00
|
|
27
|
+
Next switch peak in 6d 13h (Thu 09:00)
|
|
28
|
+
─────────────────────────────────────────────────────────────
|
|
29
|
+
CNY
|
|
30
|
+
Total ¥22.48
|
|
31
|
+
Granted ¥0.00
|
|
32
|
+
─────────────────────────────────────────────────────────────
|
|
33
|
+
USD
|
|
34
|
+
Total $0.00
|
|
35
|
+
Granted $0.00
|
|
36
|
+
─────────────────────────────────────────────────────────────
|
|
37
|
+
Read at 19:04 (⟳)
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
The pill reads **Off-peak** (green) or **Peak** (red). The balance is read with the same
|
|
41
|
+
`DEEPSEEK_API_KEY` credential the `deepseek-official` model route resolves — no extra setup. The
|
|
42
|
+
billing window is computed in your browser's timezone and drawn from the published rule: off-peak is
|
|
43
|
+
half price, peak is 01:00–04:00 and 06:00–10:00 UTC, Monday–Friday, excluding Chinese public
|
|
44
|
+
holidays. The holiday list is fetched from
|
|
45
|
+
[NateScarlet/holiday-cn](https://github.com/NateScarlet/holiday-cn), which scrapes the State Council
|
|
46
|
+
announcements daily, so it keeps itself current.
|
|
47
|
+
|
|
48
|
+
## Requirements
|
|
49
|
+
|
|
50
|
+
- DeepSeek Harness `0.2.0-rc.2` or later
|
|
51
|
+
- Node 20+
|
|
52
|
+
- A `DEEPSEEK_API_KEY` credential (the Models page writes one, or export it before launching)
|
|
53
|
+
|
|
54
|
+
## Install
|
|
55
|
+
|
|
56
|
+
### Recommended — the DSH plugin manager
|
|
57
|
+
|
|
58
|
+
The plugin manager forwards to `pnpm`, so install that first if it is missing:
|
|
59
|
+
|
|
60
|
+
```sh
|
|
61
|
+
bun add -g pnpm # or: corepack enable pnpm / npm i -g pnpm
|
|
62
|
+
dsh plugin --profile web add dsh-simple-usage-info
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
This installs the package, records it in the profile's `dependencies`, and appends it to
|
|
66
|
+
`dsh.profile.bundles`. Because the package declares `dsh.bundle.patch`, its own `cordis.patch.yml`
|
|
67
|
+
then supplies the loader row — there is nothing else to edit.
|
|
68
|
+
|
|
69
|
+
Restart the web server (`dsh web`) when it finishes.
|
|
70
|
+
|
|
71
|
+
### Manual — a `cordis.patch.yml` row
|
|
72
|
+
|
|
73
|
+
Use this when the package is already somewhere the profile can resolve (a local checkout, a
|
|
74
|
+
workspace link, a private registry). Append to `$DSH_HOME/profiles/web/cordis.patch.yml`:
|
|
75
|
+
|
|
76
|
+
```yaml
|
|
77
|
+
- insert:
|
|
78
|
+
- id: usage-info
|
|
79
|
+
name: dsh-simple-usage-info
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Restart the web server. Use **either** this row **or** the `bundles` entry from the recommended
|
|
83
|
+
path, never both, or the plugin loads twice.
|
|
84
|
+
|
|
85
|
+
### Manual without pnpm — add the dependency yourself
|
|
86
|
+
|
|
87
|
+
`dsh plugin` only knows how to shell out to pnpm. Without it, do the two halves by hand.
|
|
88
|
+
|
|
89
|
+
**1. Make the package resolvable from the profile.** Either install it with any package manager:
|
|
90
|
+
|
|
91
|
+
```sh
|
|
92
|
+
cd "$DSH_HOME/profiles/web"
|
|
93
|
+
bun add dsh-simple-usage-info # or: npm install dsh-simple-usage-info
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
…or link a local checkout:
|
|
97
|
+
|
|
98
|
+
```sh
|
|
99
|
+
mkdir -p "$DSH_HOME/profiles/web/node_modules"
|
|
100
|
+
ln -sfn /absolute/path/to/dsh-simple-usage-info \
|
|
101
|
+
"$DSH_HOME/profiles/web/node_modules/dsh-simple-usage-info"
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
and declare it in `$DSH_HOME/profiles/web/package.json`, because DSH treats a name as profile-local
|
|
105
|
+
only when the manifest lists it:
|
|
106
|
+
|
|
107
|
+
```json
|
|
108
|
+
{
|
|
109
|
+
"name": "dsh-profile-web",
|
|
110
|
+
"private": true,
|
|
111
|
+
"dependencies": {
|
|
112
|
+
"dsh-simple-usage-info": "link:/absolute/path/to/dsh-simple-usage-info"
|
|
113
|
+
},
|
|
114
|
+
"dsh": {
|
|
115
|
+
"profile": {
|
|
116
|
+
"bundles": [
|
|
117
|
+
////
|
|
118
|
+
]
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
**2. Activate it** with the `cordis.patch.yml` row above, or by adding `"dsh-simple-usage-info"` to
|
|
125
|
+
the `dsh.profile.bundles` array.
|
|
126
|
+
|
|
127
|
+
Restart the web server.
|
|
128
|
+
|
|
129
|
+
## Configure
|
|
130
|
+
|
|
131
|
+
Set these under the `usage-info` row, in the profile's `cordis.patch.yml`:
|
|
132
|
+
|
|
133
|
+
| Key | Default | Meaning |
|
|
134
|
+
|---|---|---|
|
|
135
|
+
| `refreshMs` | `60000` | how long one balance answer stays fresh |
|
|
136
|
+
| `timeoutMs` | `15000` | upstream request timeout |
|
|
137
|
+
| `baseURL` | `https://api.deepseek.com` | API origin |
|
|
138
|
+
| `apiKeyEnv` | `DEEPSEEK_API_KEY` | credential name holding the key |
|
|
139
|
+
| `peakWindows` | `['01:00-04:00', '06:00-10:00']` | peak windows, `HH:MM-HH:MM` UTC |
|
|
140
|
+
| `peakDays` | `[1, 2, 3, 4, 5]` | peak weekdays, `0` = Sunday |
|
|
141
|
+
| `holidayURL` | holiday-cn `{year}.json` | maintained holiday source; `''` goes offline |
|
|
142
|
+
| `holidayRefreshMs` | `43200000` | how long a fetched holiday snapshot stays fresh |
|
|
143
|
+
| `useBundledHolidays` | `true` | keep the bundled table as an offline fallback |
|
|
144
|
+
| `holidays` | `[]` | extra `YYYY-MM-DD` dates, added on top of the fetched list |
|
|
145
|
+
| `makeupWorkdaysArePeak` | `false` | treat 调休 makeup workdays as peak days |
|
|
146
|
+
| `makeupWorkdays` | `[]` | extra `YYYY-MM-DD` makeup workdays |
|
|
147
|
+
| `offPeakDiscountPercent` | `50` | reported as `pricing.discountPercent` |
|
|
148
|
+
|
|
149
|
+
For example:
|
|
150
|
+
|
|
151
|
+
```yaml
|
|
152
|
+
- id: usage-info
|
|
153
|
+
config:
|
|
154
|
+
peakWindows:
|
|
155
|
+
- '01:00-04:00'
|
|
156
|
+
- '06:00-10:00'
|
|
157
|
+
holidays:
|
|
158
|
+
- 2027-01-01
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
A malformed schedule (a bad clock, a window wrapping past midnight, a day outside 0–6) fails at
|
|
162
|
+
plugin load, so the row is skipped with a clear error instead of answering requests with a broken
|
|
163
|
+
window.
|
|
164
|
+
|
|
165
|
+
## Verify
|
|
166
|
+
|
|
167
|
+
```sh
|
|
168
|
+
# the route, once the server is running:
|
|
169
|
+
curl -s -H 'Host: 127.0.0.1:3080' http://127.0.0.1:3080/usage/balance
|
|
170
|
+
|
|
171
|
+
# the plugin really composes into a profile (throwaway home, your profile untouched):
|
|
172
|
+
bun run verify:compose
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
`pricing.holidayData` in the response tells you where the holidays came from — `remote` (fetched),
|
|
176
|
+
`bundled` (offline fallback), or `none`.
|
|
177
|
+
|
|
178
|
+
## Development
|
|
179
|
+
|
|
180
|
+
```sh
|
|
181
|
+
bun install
|
|
182
|
+
bun run preflight # host, pricing, holidays, client — 200+ assertions, no network
|
|
183
|
+
bun run preflight:live # real balance + holiday fetch; prints the masked key only
|
|
184
|
+
bun run preview:panel # prints the popover markup and stylesheet, no browser needed
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
There is no build step: `lib/index.js` is plain ESM, and `lib/client.js` is hand-authored in the web
|
|
188
|
+
client's module-loader bundle format. Neither half needs a bundler.
|
|
189
|
+
|
|
190
|
+
## Publishing
|
|
191
|
+
|
|
192
|
+
The repository publishes to npm from GitHub Actions
|
|
193
|
+
([`.github/workflows/ci.yml`](.github/workflows/ci.yml)): tests run on every push and pull request,
|
|
194
|
+
and a **GitHub Release** — or the *Run workflow* button — publishes to the registry.
|
|
195
|
+
|
|
196
|
+
Authentication uses **[npm trusted publishing](https://docs.npmjs.com/trusted-publishers)**, so
|
|
197
|
+
there is **no `NPM_TOKEN` secret and no long-lived credential to rotate**. The publish job holds
|
|
198
|
+
`id-token: write`, GitHub mints an OIDC token, and npm exchanges it for a credential valid for that
|
|
199
|
+
one publish. Provenance comes from the same token.
|
|
200
|
+
|
|
201
|
+
The two jobs install differently on purpose:
|
|
202
|
+
|
|
203
|
+
- **`test`** installs with **bun** (`bun install --frozen-lockfile`) and runs the preflight suite.
|
|
204
|
+
- **`publish`** is **npm-only and installs nothing**. The published files are committed sources with
|
|
205
|
+
no build step, so `npm publish` just packs `lib/` and `cordis.patch.yml`. It is gated on `test`
|
|
206
|
+
via `needs:`, so nothing reaches the registry untested.
|
|
207
|
+
|
|
208
|
+
### One-time setup
|
|
209
|
+
|
|
210
|
+
**Step 1 — publish the first version by hand.** This is not optional. A trusted publisher is
|
|
211
|
+
configured on a package page, and npm's own setup path is *Packages → YOUR_PACKAGE → Settings →
|
|
212
|
+
Trusted publishing* — which does not exist until the package does. An OIDC token **cannot create a
|
|
213
|
+
new package**, so publishing before this step fails with `E404` on the `PUT`.
|
|
214
|
+
|
|
215
|
+
```sh
|
|
216
|
+
bun install && bun run preflight
|
|
217
|
+
npm login # as your npm account
|
|
218
|
+
npm whoami
|
|
219
|
+
npm publish --access public
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
That publishes `0.1.0` and creates the package page.
|
|
223
|
+
|
|
224
|
+
**Step 2 — add the trusted publisher** on npmjs.com at
|
|
225
|
+
`https://www.npmjs.com/package/dsh-simple-usage-info/access`:
|
|
226
|
+
|
|
227
|
+
| Field | Value |
|
|
228
|
+
|---|---|
|
|
229
|
+
| Publisher | GitHub Actions |
|
|
230
|
+
| Organization or user | `MarJose123` — the **GitHub** owner, *not* the npm username |
|
|
231
|
+
| Repository | `dsh-simple-usage-info` |
|
|
232
|
+
| Workflow filename | `ci.yml` — the filename only, with the extension, not the full path |
|
|
233
|
+
| Environment name | *(leave blank — the job declares no environment)* |
|
|
234
|
+
| Allowed actions | **tick "Allow npm publish"** |
|
|
235
|
+
|
|
236
|
+
That last row is the trap: `npm stage publish` is always permitted, but direct `npm publish` is a
|
|
237
|
+
separate opt-in and is **off by default**. Without it the publish is rejected even though the
|
|
238
|
+
workflow is otherwise correct.
|
|
239
|
+
|
|
240
|
+
**Step 3 — release via CI.** Bump the version, then cut a GitHub Release:
|
|
241
|
+
|
|
242
|
+
```sh
|
|
243
|
+
npm version 0.1.1 --no-git-tag-version
|
|
244
|
+
git commit -am "Release 0.1.1" && git push
|
|
245
|
+
gh release create v0.1.1 --generate-notes
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
The publish job runs, and from here on every release goes through OIDC. Revoke the bootstrap token
|
|
249
|
+
if you created one — nothing needs it any more.
|
|
250
|
+
|
|
251
|
+
> If you would rather `0.1.0` be the CI-published version, bootstrap a throwaway `0.0.1` instead,
|
|
252
|
+
> then set the version back to `0.1.0` and release that. The bootstrap version is scaffolding, so it
|
|
253
|
+
> never carries provenance.
|
|
254
|
+
|
|
255
|
+
### Reading a failed publish
|
|
256
|
+
|
|
257
|
+
The two failure modes look similar but have different causes, and npm's error code tells them apart:
|
|
258
|
+
|
|
259
|
+
| Error | Meaning |
|
|
260
|
+
|---|---|
|
|
261
|
+
| `E404` on `PUT` | The package does not exist yet — do the bootstrap above |
|
|
262
|
+
| `ENEEDAUTH` | The package exists but the trusted publisher does not match: check the GitHub owner, repository, and workflow filename are **exact and case-sensitive**, and that the job has `id-token: write` |
|
|
263
|
+
|
|
264
|
+
The workflow checks for the first case before publishing and fails with the remedy instead of a bare
|
|
265
|
+
404.
|
|
266
|
+
|
|
267
|
+
## License
|
|
268
|
+
|
|
269
|
+
[MIT](LICENSE)
|
package/cordis.patch.yml
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# This package's own bundle patch: one self-insert row. A profile that lists
|
|
2
|
+
# `dsh-simple-usage-info` in `dsh.profile.bundles` applies this file, and the
|
|
3
|
+
# row loads the package's host half while `dsh.client` publishes the browser
|
|
4
|
+
# half into the web boot graph.
|
|
5
|
+
- insert:
|
|
6
|
+
- id: usage-info
|
|
7
|
+
name: dsh-simple-usage-info
|
|
8
|
+
config:
|
|
9
|
+
# How long one upstream balance answer stays fresh.
|
|
10
|
+
refreshMs: 60000
|
|
11
|
+
# Upstream request timeout.
|
|
12
|
+
timeoutMs: 15000
|
|
13
|
+
# Peak-rate windows, `HH:MM-HH:MM` UTC. Everything else is off-peak.
|
|
14
|
+
# Quoted so no YAML parser reads a clock as a sexagesimal number.
|
|
15
|
+
peakWindows:
|
|
16
|
+
- '01:00-04:00'
|
|
17
|
+
- '06:00-10:00'
|
|
18
|
+
# Peak weekdays: 0 = Sunday ... 6 = Saturday.
|
|
19
|
+
peakDays: [1, 2, 3, 4, 5]
|
|
20
|
+
# `YYYY-MM-DD` UTC dates priced off-peak in full, added on top of the
|
|
21
|
+
# fetched holidays (for a private calendar or an unpublished year).
|
|
22
|
+
holidays: []
|
|
23
|
+
# Where the maintained Chinese holiday data is read from; `{year}` is
|
|
24
|
+
# substituted. NateScarlet/holiday-cn scrapes the State Council notices
|
|
25
|
+
# daily, so the date list needs no hand maintenance. Set '' to stay
|
|
26
|
+
# offline and fall back to the bundled table.
|
|
27
|
+
holidayURL: https://raw.githubusercontent.com/NateScarlet/holiday-cn/master/{year}.json
|
|
28
|
+
# How long one fetched snapshot stays fresh (12 hours).
|
|
29
|
+
holidayRefreshMs: 43200000
|
|
30
|
+
# Keep the bundled State Council table as an offline fallback.
|
|
31
|
+
useBundledHolidays: true
|
|
32
|
+
# 调休 makeup workdays. The published rule says "Monday through Friday",
|
|
33
|
+
# which makes them off-peak, so this stays false unless you learn
|
|
34
|
+
# otherwise from your own billing.
|
|
35
|
+
makeupWorkdaysArePeak: false
|
package/lib/client.d.ts
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* dsh-simple-usage-info — browser half type surface.
|
|
3
|
+
*
|
|
4
|
+
* The shipped artifact is `lib/client.js`, hand-authored in the web client's
|
|
5
|
+
* module-loader bundle format; this declaration file exists so the package's
|
|
6
|
+
* `./client` export has a typed face. Everything is plain JavaScript at runtime,
|
|
7
|
+
* so the types below describe the objects the bundle passes around.
|
|
8
|
+
* @module dsh-simple-usage-info/client
|
|
9
|
+
*/
|
|
10
|
+
import type { Context as ClientContext } from '@deepseek-ai/cordis'
|
|
11
|
+
|
|
12
|
+
/** Services this browser plugin requires. */
|
|
13
|
+
export declare const inject: string[]
|
|
14
|
+
/** The viewer's IANA timezone, read once from the browser. */
|
|
15
|
+
export declare const zone: string
|
|
16
|
+
|
|
17
|
+
/** One window of the serialized schedule, in minutes since UTC midnight. */
|
|
18
|
+
export interface WireWindow {
|
|
19
|
+
readonly start: number
|
|
20
|
+
readonly end: number
|
|
21
|
+
readonly label: string
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** The plain-JSON schedule the host sends and the browser evaluates from. */
|
|
25
|
+
export interface WireSchedule {
|
|
26
|
+
readonly peakWindows: readonly WireWindow[]
|
|
27
|
+
readonly peakDays: readonly number[]
|
|
28
|
+
readonly holidays: readonly string[]
|
|
29
|
+
readonly makeupWorkdays: readonly string[]
|
|
30
|
+
readonly makeupWorkdaysArePeak: boolean
|
|
31
|
+
readonly offPeakDiscountPercent: number
|
|
32
|
+
readonly coveredYears: readonly number[]
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** The billing reading the browser computes for one instant. */
|
|
36
|
+
export interface WindowReading {
|
|
37
|
+
readonly window: 'peak' | 'off-peak'
|
|
38
|
+
readonly reason: string
|
|
39
|
+
readonly discountPercent: number
|
|
40
|
+
readonly nextChangeAt?: number
|
|
41
|
+
readonly nextWindow?: 'peak' | 'off-peak'
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** One label/value row of the popover. */
|
|
45
|
+
export interface PanelRow {
|
|
46
|
+
readonly label: string
|
|
47
|
+
readonly value: string
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** One titled group of popover rows. */
|
|
51
|
+
export interface PanelGroup {
|
|
52
|
+
readonly title: string
|
|
53
|
+
readonly rows: readonly PanelRow[]
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/** Everything the popover renders, as plain data. */
|
|
57
|
+
export interface PanelModel {
|
|
58
|
+
readonly headline: string
|
|
59
|
+
readonly available?: boolean
|
|
60
|
+
readonly groups: readonly PanelGroup[]
|
|
61
|
+
readonly error?: string
|
|
62
|
+
readonly footer: string
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** The composer-dock entry component. */
|
|
66
|
+
export declare function UsageBar(): unknown
|
|
67
|
+
/** Client plugin body: one entry in the composer dock. */
|
|
68
|
+
export declare function apply(ctx: ClientContext): void
|
|
69
|
+
|
|
70
|
+
/** `¥110.00` / `$110.00` / `110.00 CHF`. */
|
|
71
|
+
export declare function formatWallet(info: { currency?: string; total_balance?: string }): string
|
|
72
|
+
/** The dock's one-line text for the current state. */
|
|
73
|
+
export declare function summarize(state: { status: string; payload?: unknown }): string
|
|
74
|
+
/** The peak / off-peak pill: the window name and nothing else. */
|
|
75
|
+
export declare function priceBadge(pricing?: { window?: string } | null): unknown
|
|
76
|
+
/** The popover's contents, as data. */
|
|
77
|
+
export declare function panelModel(payload: unknown, pricing: unknown, now: number): PanelModel
|
|
78
|
+
/** `2m` / `2h 5m` / `2d 2h`, always rounding up. */
|
|
79
|
+
export declare function countdown(target?: number, now?: number): string | undefined
|
|
80
|
+
/** Which window one instant falls in, mirroring lib/pricing.js. */
|
|
81
|
+
export declare function windowAt(schedule: WireSchedule, instant: number): { window: string; reason: string }
|
|
82
|
+
/** The complete reading for one instant. */
|
|
83
|
+
export declare function readWindow(schedule: WireSchedule, instant: number): WindowReading
|
|
84
|
+
/** The peak windows as wall-clock times in a timezone. */
|
|
85
|
+
export declare function localWindows(schedule: WireSchedule, instant: number, zone?: string): string
|