@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.
Files changed (3) hide show
  1. package/README.md +5 -0
  2. package/lib/client.js +76 -50
  3. 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:14px;padding:0 16px;border-top:1px solid var(--dsw-alias-border-l1, rgba(127,127,127,.2));background:var(--dsw-specific-menu, rgba(0,0,0,.04));color:var(--dsw-alias-label-secondary, #666);font-size:12px;line-height:1;font-family:var(--dsh-font-family-body, inherit);overflow:hidden;white-space:nowrap}",
12
- ".Jfdp_bar[data-tariff='peak']{background:linear-gradient(90deg, rgba(229,72,77,.10), var(--dsw-specific-menu, rgba(0,0,0,.04))) }",
13
- ".Jfdp_bar[data-tariff='offpeak']{background:linear-gradient(90deg, rgba(48,164,108,.10), var(--dsw-specific-menu, rgba(0,0,0,.04))) }",
14
- ".Jfdp_dot{width:9px;height:9px;border-radius:50%;flex:none;background:#e5484d;box-shadow:0 0 0 3px rgba(229,72,77,.15)}",
15
- ".Jfdp_bar[data-tariff='offpeak'] .Jfdp_dot{background:#30a46c;box-shadow:0 0 0 3px rgba(48,164,108,.15)}",
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, #111)}",
21
- ".Jfdp_price{font-variant-numeric:tabular-nums;color:var(--dsw-alias-label-secondary, #555)}",
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, #888)}",
25
- ".Jfdp_countdown{flex:none;font-weight:600;font-variant-numeric:tabular-nums;color:var(--dsw-alias-label-primary, #111)}",
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
- const LANGS = {
126
- en: { peak: "PEAK", offPeak: "OFF-PEAK", to: "to", utc: "UTC", quebec: "Quebec", changes: "changes to", in: "in", next: "next" },
127
- fr: { peak: "POINTE", offPeak: "HORS POINTE", to: "à", utc: "UTC", quebec: "Québec", changes: "passe à", in: "dans", next: "prochaine" },
128
- es: { peak: "PICO", offPeak: "VALLE", to: "a", utc: "UTC", quebec: "Québec", changes: "cambia a", in: "en", next: "próximo" }
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 + ": in " + fmtPrice(m.inputCacheMiss.peak)
173
- + " (hit " + fmtPrice(m.inputCacheHit.peak) + ") / out " + fmtPrice(m.output.peak)
174
- + " · " + t.offPeak + ": in " + fmtPrice(m.inputCacheMiss.offPeak)
175
- + " (hit " + fmtPrice(m.inputCacheHit.offPeak) + ") / out " + fmtPrice(m.output.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 = "DeepSeek token prices (USD / 1M)\n" + detail
178
- + "\n\n" + t.peak + ": 01:00–04:00 & 06:00–10:00 UTC (Mon–Fri, excl. CN holidays)"
179
- + "\n" + t.offPeak + ": all other hours (50% off)"
180
- + "\nSource: " + PRICING.source + "\nVerified: " + PRICING.verifiedAt;
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.changes + " " + nextLabel + " " + t.in + " " + remaining + " · " + fmtClock(next, "America/Toronto") + " " + t.quebec) : ""
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",
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
  }