@javierfrancoleal/deepseek-prices 1.0.3 → 1.0.5
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/README.md +5 -0
- package/lib/client.js +76 -50
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -18,6 +18,8 @@ temps réel :
|
|
|
18
18
|
- **Le compte à rebours** jusqu'au prochain changement de tarif, avec l'heure locale
|
|
19
19
|
du basculement.
|
|
20
20
|
- **La date de vérification** des prix (survol de la barre).
|
|
21
|
+
- **L'idiome et le thème** : la barre suit la langue sélectionnée dans DeepSeek
|
|
22
|
+
Harness (anglais / chinois) et les jetons de thème `--dsw-*` (clair / sombre).
|
|
21
23
|
|
|
22
24
|
---
|
|
23
25
|
|
|
@@ -91,6 +93,9 @@ des prix, la compare à la grille embarquée, et ajoute un enregistrement JSONL
|
|
|
91
93
|
|
|
92
94
|
La barre affiche la date de vérification embarquée au survol.
|
|
93
95
|
|
|
96
|
+
Un **rappel de vérification** quotidien (via l'agenda de DeepSeek Harness) rappelle
|
|
97
|
+
de contrôler ce registre et de mettre à jour les prix embarqués en cas de dérive.
|
|
98
|
+
|
|
94
99
|
---
|
|
95
100
|
|
|
96
101
|
## Configuration / limites
|
package/lib/client.js
CHANGED
|
@@ -6,24 +6,20 @@ window.__ModuleLoader__.load({
|
|
|
6
6
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
7
7
|
const React = require("react");
|
|
8
8
|
|
|
9
|
-
// ── styles
|
|
9
|
+
// ── styles (DeepSeek Harness design tokens; theme-aware) ────────────────
|
|
10
10
|
const CSS = [
|
|
11
|
-
".Jfdp_bar{box-sizing:border-box;width:100%;height:34px;display:flex;align-items:center;gap:
|
|
12
|
-
".
|
|
13
|
-
".Jfdp_bar[data-tariff='offpeak']{background:
|
|
14
|
-
".
|
|
15
|
-
".Jfdp_bar[data-tariff='offpeak'] .
|
|
16
|
-
".Jfdp_status{flex:none;font-weight:700;font-size:12px;letter-spacing:.06em;color:var(--dsw-alias-label-primary, #111)}",
|
|
17
|
-
".Jfdp_bar[data-tariff='peak'] .Jfdp_status{color:#e5484d}",
|
|
18
|
-
".Jfdp_bar[data-tariff='offpeak'] .Jfdp_status{color:#30a46c}",
|
|
11
|
+
".Jfdp_bar{box-sizing:border-box;width:100%;height:34px;display:flex;align-items:center;gap:12px;padding:0 16px;background:var(--dsw-specific-menu);border-top:1px solid var(--dsw-alias-border-l1);backdrop-filter:var(--dsw-menu-backdrop-filter);color:var(--dsw-alias-label-secondary);font-size:12px;line-height:1;overflow:hidden;white-space:nowrap}",
|
|
12
|
+
".Jfdp_dot{width:8px;height:8px;border-radius:50%;flex:none;background:var(--dsw-alias-state-warn-primary)}",
|
|
13
|
+
".Jfdp_bar[data-tariff='offpeak'] .Jfdp_dot{background:var(--dsw-alias-state-success-primary)}",
|
|
14
|
+
".Jfdp_status{flex:none;font-weight:700;font-size:12px;letter-spacing:.06em;color:var(--dsw-alias-state-warn-primary)}",
|
|
15
|
+
".Jfdp_bar[data-tariff='offpeak'] .Jfdp_status{color:var(--dsw-alias-state-success-primary)}",
|
|
19
16
|
".Jfdp_model{display:inline-flex;align-items:baseline;gap:6px;flex:none}",
|
|
20
|
-
".Jfdp_modelName{font-weight:600;color:var(--dsw-alias-label-primary
|
|
21
|
-
".Jfdp_price{font-variant-numeric:tabular-nums;color:var(--dsw-alias-label-secondary
|
|
17
|
+
".Jfdp_modelName{font-weight:600;color:var(--dsw-alias-label-primary)}",
|
|
18
|
+
".Jfdp_price{font-variant-numeric:tabular-nums;color:var(--dsw-alias-label-secondary)}",
|
|
22
19
|
".Jfdp_arrow{opacity:.55}",
|
|
23
20
|
".Jfdp_spacer{flex:1}",
|
|
24
|
-
".Jfdp_clock{flex:none;font-variant-numeric:tabular-nums;color:var(--dsw-alias-label-tertiary
|
|
25
|
-
".Jfdp_countdown{flex:none;font-weight:600;font-variant-numeric:tabular-nums;color:var(--dsw-alias-label-primary
|
|
26
|
-
".Jfdp_countdown b{color:var(--dsw-alias-label-secondary, #555);font-weight:600}",
|
|
21
|
+
".Jfdp_clock{flex:none;font-variant-numeric:tabular-nums;color:var(--dsw-alias-label-tertiary)}",
|
|
22
|
+
".Jfdp_countdown{flex:none;font-weight:600;font-variant-numeric:tabular-nums;color:var(--dsw-alias-label-primary)}",
|
|
27
23
|
".Jfdp_hideSmall{flex:none}",
|
|
28
24
|
"@media (max-width:900px){.Jfdp_bar{gap:8px;padding:0 10px}.Jfdp_hideSmall{display:none}}"
|
|
29
25
|
].join("\n");
|
|
@@ -108,35 +104,63 @@ window.__ModuleLoader__.load({
|
|
|
108
104
|
return "--:--";
|
|
109
105
|
}
|
|
110
106
|
}
|
|
111
|
-
function fmtDuration(ms) {
|
|
107
|
+
function fmtDuration(ms, t) {
|
|
112
108
|
let s = Math.max(0, Math.floor(ms / 1000));
|
|
113
109
|
const h = Math.floor(s / 3600);
|
|
114
110
|
const m = Math.floor((s % 3600) / 60);
|
|
115
111
|
const sec = s % 60;
|
|
116
|
-
if (h > 0) return h + "h " + m + "m " + sec + "s";
|
|
117
|
-
if (m > 0) return m + "m " + sec + "s";
|
|
118
|
-
return sec + "s";
|
|
112
|
+
if (h > 0) return h + t("unit.h") + " " + m + t("unit.m") + " " + sec + t("unit.s");
|
|
113
|
+
if (m > 0) return m + t("unit.m") + " " + sec + t("unit.s");
|
|
114
|
+
return sec + t("unit.s");
|
|
119
115
|
}
|
|
120
116
|
function fmtPrice(n) {
|
|
121
117
|
if (n < 0.01) return "$" + n.toFixed(3);
|
|
122
118
|
return "$" + n.toFixed(2);
|
|
123
119
|
}
|
|
124
120
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
121
|
+
// ── i18n namespace (follows the language selected in DeepSeek Harness) ──
|
|
122
|
+
const NS = "deepseekPrices";
|
|
123
|
+
const zh = {
|
|
124
|
+
"status.peak": "高峰",
|
|
125
|
+
"status.offPeak": "错峰",
|
|
126
|
+
"clock.utc": "UTC",
|
|
127
|
+
"clock.quebec": "魁北克",
|
|
128
|
+
"countdown.changesTo": "切换至",
|
|
129
|
+
"countdown.in": "于",
|
|
130
|
+
"unit.h": "时",
|
|
131
|
+
"unit.m": "分",
|
|
132
|
+
"unit.s": "秒",
|
|
133
|
+
"tooltip.title": "DeepSeek 令牌价格(美元 / 100 万令牌)",
|
|
134
|
+
"tooltip.input": "输入",
|
|
135
|
+
"tooltip.output": "输出",
|
|
136
|
+
"tooltip.hit": "命中",
|
|
137
|
+
"tooltip.peakHours": "高峰:01:00–04:00 与 06:00–10:00 UTC(周一至周五,不含中国法定节假日)",
|
|
138
|
+
"tooltip.offPeakRule": "错峰:其余时间(5 折)",
|
|
139
|
+
"tooltip.source": "来源",
|
|
140
|
+
"tooltip.verified": "核实日期"
|
|
141
|
+
};
|
|
142
|
+
const en = {
|
|
143
|
+
"status.peak": "PEAK",
|
|
144
|
+
"status.offPeak": "OFF-PEAK",
|
|
145
|
+
"clock.utc": "UTC",
|
|
146
|
+
"clock.quebec": "Quebec",
|
|
147
|
+
"countdown.changesTo": "changes to",
|
|
148
|
+
"countdown.in": "in",
|
|
149
|
+
"unit.h": "h",
|
|
150
|
+
"unit.m": "m",
|
|
151
|
+
"unit.s": "s",
|
|
152
|
+
"tooltip.title": "DeepSeek token prices (USD / 1M tokens)",
|
|
153
|
+
"tooltip.input": "in",
|
|
154
|
+
"tooltip.output": "out",
|
|
155
|
+
"tooltip.hit": "hit",
|
|
156
|
+
"tooltip.peakHours": "Peak: 01:00–04:00 & 06:00–10:00 UTC (Mon–Fri, excl. CN holidays)",
|
|
157
|
+
"tooltip.offPeakRule": "Off-peak: all other hours (50% off)",
|
|
158
|
+
"tooltip.source": "Source",
|
|
159
|
+
"tooltip.verified": "Verified"
|
|
129
160
|
};
|
|
130
|
-
function pickLang() {
|
|
131
|
-
try {
|
|
132
|
-
const l = (navigator.language || "").toLowerCase();
|
|
133
|
-
if (l.indexOf("fr") === 0) return "fr";
|
|
134
|
-
if (l.indexOf("en") === 0) return "en";
|
|
135
|
-
} catch (e) { /* ignore */ }
|
|
136
|
-
return "es";
|
|
137
|
-
}
|
|
138
161
|
|
|
139
|
-
function PriceBar() {
|
|
162
|
+
function PriceBar(_props) {
|
|
163
|
+
const t = _props && typeof _props.t === "function" ? _props.t : function (k) { return k; };
|
|
140
164
|
const [now, setNow] = React.useState(function () { return new Date(); });
|
|
141
165
|
React.useEffect(function () {
|
|
142
166
|
const id = setInterval(function () { setNow(new Date()); }, 1000);
|
|
@@ -145,12 +169,10 @@ window.__ModuleLoader__.load({
|
|
|
145
169
|
|
|
146
170
|
const peak = isPeak(now);
|
|
147
171
|
const next = nextTransition(now);
|
|
148
|
-
const lang = pickLang();
|
|
149
|
-
const t = LANGS[lang] || LANGS.es;
|
|
150
172
|
const tariff = peak ? "peak" : "offpeak";
|
|
151
|
-
const statusLabel = peak ? t.peak : t.offPeak;
|
|
152
|
-
const nextLabel = next ? (isPeak(next) ? t.peak : t.offPeak) : "";
|
|
153
|
-
const remaining = next ? fmtDuration(next.getTime() - now.getTime()) : "—";
|
|
173
|
+
const statusLabel = peak ? t("status.peak") : t("status.offPeak");
|
|
174
|
+
const nextLabel = next ? (isPeak(next) ? t("status.peak") : t("status.offPeak")) : "";
|
|
175
|
+
const remaining = next ? fmtDuration(next.getTime() - now.getTime(), t) : "—";
|
|
154
176
|
|
|
155
177
|
const modelRows = Object.keys(PRICING.models).map(function (key) {
|
|
156
178
|
const m = PRICING.models[key];
|
|
@@ -166,18 +188,18 @@ window.__ModuleLoader__.load({
|
|
|
166
188
|
);
|
|
167
189
|
});
|
|
168
190
|
|
|
169
|
-
// Full-detail tooltip (cache hit + cache miss + output, peak & off-peak).
|
|
170
191
|
const detail = Object.keys(PRICING.models).map(function (key) {
|
|
171
192
|
const m = PRICING.models[key];
|
|
172
|
-
return m.label + " — " + t.peak + ":
|
|
173
|
-
+ " (hit " + fmtPrice(m.inputCacheHit.peak) + ") /
|
|
174
|
-
+ " · " + t.offPeak + ":
|
|
175
|
-
+ " (hit " + fmtPrice(m.inputCacheHit.offPeak) + ") /
|
|
193
|
+
return m.label + " — " + t("status.peak") + ": " + t("tooltip.input") + " " + fmtPrice(m.inputCacheMiss.peak)
|
|
194
|
+
+ " (" + t("tooltip.hit") + " " + fmtPrice(m.inputCacheHit.peak) + ") / " + t("tooltip.output") + " " + fmtPrice(m.output.peak)
|
|
195
|
+
+ " · " + t("status.offPeak") + ": " + t("tooltip.input") + " " + fmtPrice(m.inputCacheMiss.offPeak)
|
|
196
|
+
+ " (" + t("tooltip.hit") + " " + fmtPrice(m.inputCacheHit.offPeak) + ") / " + t("tooltip.output") + " " + fmtPrice(m.output.offPeak);
|
|
176
197
|
}).join("\n");
|
|
177
|
-
const title = "
|
|
178
|
-
+ "\n\n" + t.
|
|
179
|
-
+ "\n" + t.
|
|
180
|
-
+ "\
|
|
198
|
+
const title = t("tooltip.title") + "\n" + detail
|
|
199
|
+
+ "\n\n" + t("tooltip.peakHours")
|
|
200
|
+
+ "\n" + t("tooltip.offPeakRule")
|
|
201
|
+
+ "\n" + t("tooltip.source") + ": " + PRICING.source
|
|
202
|
+
+ "\n" + t("tooltip.verified") + ": " + PRICING.verifiedAt;
|
|
181
203
|
|
|
182
204
|
return React.createElement("div", {
|
|
183
205
|
className: "Jfdp_bar",
|
|
@@ -190,21 +212,25 @@ window.__ModuleLoader__.load({
|
|
|
190
212
|
React.createElement("span", { className: "Jfdp_hideSmall" }, "·"),
|
|
191
213
|
modelRows,
|
|
192
214
|
React.createElement("span", { className: "Jfdp_spacer" }),
|
|
193
|
-
React.createElement("span", { className: "Jfdp_clock" }, t.utc + " " + fmtClock(now, "UTC")),
|
|
194
|
-
React.createElement("span", { className: "Jfdp_clock Jfdp_hideSmall" }, t.quebec + " " + fmtClock(now, "America/Toronto")),
|
|
215
|
+
React.createElement("span", { className: "Jfdp_clock" }, t("clock.utc") + " " + fmtClock(now, "UTC")),
|
|
216
|
+
React.createElement("span", { className: "Jfdp_clock Jfdp_hideSmall" }, t("clock.quebec") + " " + fmtClock(now, "America/Toronto")),
|
|
195
217
|
React.createElement("span", { className: "Jfdp_countdown" },
|
|
196
|
-
next ? (t.
|
|
218
|
+
next ? (t("countdown.changesTo") + " " + nextLabel + " " + t("countdown.in") + " " + remaining + " · " + fmtClock(next, "America/Toronto") + " " + t("clock.quebec")) : ""
|
|
197
219
|
)
|
|
198
220
|
);
|
|
199
221
|
}
|
|
200
222
|
|
|
201
|
-
const inject = ["slots"];
|
|
223
|
+
const inject = ["slots", "locale"];
|
|
202
224
|
function apply(ctx) {
|
|
225
|
+
ctx.effect(function () {
|
|
226
|
+
return ctx.locale.register(NS, { zh, en });
|
|
227
|
+
}, "deepseek-prices: locale dictionaries");
|
|
203
228
|
ctx.slots.inject("shell.bottom", function () {
|
|
204
229
|
return ctx.slots.register({
|
|
205
230
|
name: "shell.bottom",
|
|
206
231
|
id: "jfranco-deepseek-prices",
|
|
207
|
-
order: 0
|
|
232
|
+
order: 0,
|
|
233
|
+
locale: NS
|
|
208
234
|
}, PriceBar);
|
|
209
235
|
});
|
|
210
236
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@javierfrancoleal/deepseek-prices",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.5",
|
|
4
4
|
"description": "Live DeepSeek API token price bar for the web GUI: peak/off-peak tariff, UTC + local (Quebec) clocks, countdown to the next tariff change, and a daily self-verification against the official DeepSeek pricing page.",
|
|
5
5
|
"author": "J.Franco",
|
|
6
6
|
"license": "MIT",
|
|
@@ -42,6 +42,7 @@
|
|
|
42
42
|
"client": {
|
|
43
43
|
"platform": "web",
|
|
44
44
|
"inject": [
|
|
45
|
+
"@deepseek-ai/dsh-client-locale",
|
|
45
46
|
"@deepseek-ai/dsh-client-ui-layout"
|
|
46
47
|
]
|
|
47
48
|
}
|