dsh-api-dashboard 1.4.4 → 1.4.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 +1 -1
- package/client/client.js +30 -15
- package/cordis.patch.yml +2 -2
- package/package.json +1 -1
- package/src/index.js +249 -50
package/README.md
CHANGED
|
@@ -125,7 +125,7 @@ dsh plugin --profile web add link:/root/dsha-api-dashboard
|
|
|
125
125
|
|
|
126
126
|
## 更新日志
|
|
127
127
|
|
|
128
|
-
最近一版 **v1.4.
|
|
128
|
+
最近一版 **v1.4.5** —— 消耗估算口径三处修正:**峰谷改按「事件发生时刻」计价**(旧实现按「打开面板那一刻」,谷时跑的量在峰时查看会被翻倍)、**法定节假日全天算谷时**、**缓存写入按官方 ×125% 单独计价**;同时把十一家厂商的价格表逐条对官方原文重核,并补录 40+ 条新模型(GPT-6 Astra、Claude Fable 5.1、GLM-5.3-FlashX、MiniMax-M3、Gemini 3.5 Flash、Grok 4.7 / 4.6、MiMo V2.6 等);另修「点设置抽搐一下」与刷新间隔 300 秒两处交互根因。一版一行的完整历史见 [`CHANGELOG.md`](CHANGELOG.md)。
|
|
129
129
|
|
|
130
130
|
## License
|
|
131
131
|
|
package/client/client.js
CHANGED
|
@@ -1445,7 +1445,7 @@ window.__ModuleLoader__.load({
|
|
|
1445
1445
|
//#endregion
|
|
1446
1446
|
|
|
1447
1447
|
//#region 设置面板 (安全阈值 + 中转站)
|
|
1448
|
-
function SettingsModal({ isOpen, onClose, onBack, t, config, initialSection }) {
|
|
1448
|
+
function SettingsModal({ isOpen, onClose, onBack, t, config, initialSection, underScrim }) {
|
|
1449
1449
|
const [section, setSection] = react.useState(initialSection || "basic");
|
|
1450
1450
|
const [relays, setRelays] = react.useState([]);
|
|
1451
1451
|
const [models, setModels] = react.useState([]);
|
|
@@ -1938,21 +1938,30 @@ window.__ModuleLoader__.load({
|
|
|
1938
1938
|
]),
|
|
1939
1939
|
// v1.3.3: 更新结果改为醒目横幅 —— 原来的 11px 灰色字在移动端几乎看不到,
|
|
1940
1940
|
// 用户点完「一键更新」后以为没反应。成功=绿色底, 失败=红色底, 检查有新版=原来的灰色。
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1941
|
+
// 2026-09-22: 外面这层是**固定高度槽位**。原来结果行是条件渲染, 打开面板时它还不存在,
|
|
1942
|
+
// checkUpdate 回来才插入(约 23px) —— 而面板是 position:fixed + bottom:0 + 高度随内容,
|
|
1943
|
+
// 于是「上边缘往上跳一下」; 本地请求 <20ms, 往往在滑入动画(.22s)期间就填充 → 边滑边长。
|
|
1944
|
+
// 槽位恒定后结果填进同一高度, 打开过程中版面零位移。
|
|
1945
|
+
react.createElement("div", { key: "upd_slot", style: { minHeight: "16px", marginTop: "8px" } }, [
|
|
1946
|
+
upd.msg ? react.createElement("div", { key: "upd_msg", style: {
|
|
1947
|
+
color: upd.phase === "fail" ? "#b33" : upd.phase === "done" ? "#1a7a3a" : "#777b84",
|
|
1948
|
+
background: upd.phase === "fail" ? "#fde8e8" : upd.phase === "done" ? "#e8fde8" : "transparent",
|
|
1949
|
+
fontSize: upd.phase === "done" || upd.phase === "fail" ? "13px" : "11px",
|
|
1950
|
+
fontWeight: upd.phase === "done" || upd.phase === "fail" ? "600" : "400",
|
|
1951
|
+
padding: upd.phase === "done" || upd.phase === "fail" ? "8px 10px" : "0",
|
|
1952
|
+
borderRadius: upd.phase === "done" || upd.phase === "fail" ? "6px" : "0",
|
|
1953
|
+
lineHeight: "1.4"
|
|
1954
|
+
} }, upd.msg) : (upd.info?.hasUpdate ? react.createElement("div", { key: "upd_msg", style: { color: "#777b84", fontSize: "11px" } },
|
|
1955
|
+
t("update.available") + " v" + upd.info.remote) : null),
|
|
1956
|
+
]),
|
|
1952
1957
|
]),
|
|
1953
1958
|
]),
|
|
1954
1959
|
]);
|
|
1955
|
-
|
|
1960
|
+
// 2026-09-22: 从看板打开设置时, 下层 DashboardDrawer 的 .dshadb_scrim **仍在**(S1 的修法就是保留它),
|
|
1961
|
+
// 而两层遮罩同为 rgba(0,0,0,0.35) → 叠加后总暗度 1-(0.65)² ≈ 0.58, 打开瞬间背景从 0.35 渐暗到 0.58
|
|
1962
|
+
// (dshadb-fadein .15s), 看上去「又抽了一下」。已知下层已有遮罩时本层不再重复加深 ——
|
|
1963
|
+
// 只把背景设为透明, scrim 本身保留(继续拦截点击 / 点空白关闭)。
|
|
1964
|
+
return react.createElement("div", { className: "dshadb_scrim", style: underScrim ? { background: "transparent" } : undefined, onClick: (e) => { if (e.target === e.currentTarget) onClose(); } }, [
|
|
1956
1965
|
react.createElement("div", { className: "dshadb_swipeguard", "aria-hidden": "true", key: "swipeguard" }),
|
|
1957
1966
|
output,
|
|
1958
1967
|
]);
|
|
@@ -2620,7 +2629,12 @@ window.__ModuleLoader__.load({
|
|
|
2620
2629
|
const openDetail = (id) => { setDetailId(id); setView("detail"); };
|
|
2621
2630
|
const closeDetail = () => setView("list");
|
|
2622
2631
|
const closeList = () => setView("bar");
|
|
2623
|
-
|
|
2632
|
+
// 2026-09-22: 原来这里是 setView("bar") + setSettingsOpen(true) 同帧生效 —— 从看板点设置时,
|
|
2633
|
+
// DashboardDrawer 会被**当场卸载**、SettingsModal 同时挂载, 两块全屏遮罩一换一, 而 drawer
|
|
2634
|
+
// 的 .dshadb_scrim 只有入场动画没有出场动画 → 视觉上「啪」一下(维护者反馈「点设置会抽搐一下」)。
|
|
2635
|
+
// 改为: 打开设置时**不**收看板(设置面板照常盖在它上面), 关闭设置时再收 —— 交互结果不变
|
|
2636
|
+
// (关掉设置后一样回到状态条), 但中间那次同帧卸载/挂载消失了。
|
|
2637
|
+
const openSettings = (section) => { setSettingsSection(section || "basic"); setSettingsOpen(true); };
|
|
2624
2638
|
|
|
2625
2639
|
// v0.6.0: 启动自动检查更新 (一次静默请求, 服务端 5 分钟缓存; 结果供设置弹窗直接显示)
|
|
2626
2640
|
react.useEffect(() => {
|
|
@@ -2656,7 +2670,8 @@ window.__ModuleLoader__.load({
|
|
|
2656
2670
|
react.createElement(BarReadout, { t, onOpen: openList, onOpenSettings: () => openSettings("basic"), selectedId, onSelect: handleSelect, config, cost: costDisp, provider: curProvider, key: "bar" }),
|
|
2657
2671
|
view === "list" ? react.createElement(DashboardDrawer, { isOpen: true, onClose: closeList, t, selectedId, onSelect: handleSelect, onOpenDetail: (id) => { setDetailId(id); setView("detail"); }, onAddRelay: () => openSettings("relays"), onAddCustom: () => openSettings("models"), onOpenSettings: () => openSettings("basic"), config, currentModel, key: "drawer" }) : null,
|
|
2658
2672
|
view === "detail" ? react.createElement(PlatformDetail, { isOpen: true, onClose: closeDetail, platformId: detailId, t, useProjection, config, key: "detail" }) : null,
|
|
2659
|
-
|
|
2673
|
+
// 2026-09-22: underScrim —— view 是 list/detail 时下层已有全屏遮罩, 设置面板不再叠加第二层 (见 SettingsModal)
|
|
2674
|
+
isSettingsOpen ? react.createElement(SettingsModal, { isOpen: true, underScrim: view !== "bar", onClose: () => { setSettingsOpen(false); setView("bar"); }, onBack: () => { setSettingsOpen(false); setView("list"); }, t, config, initialSection: settingsSection, key: "settings" }) : null,
|
|
2660
2675
|
]),
|
|
2661
2676
|
subRow,
|
|
2662
2677
|
]);
|
package/cordis.patch.yml
CHANGED
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -618,6 +618,17 @@ export const planBalancesFetch = ({ force = false, peek = false, hasData = false
|
|
|
618
618
|
/** v1.4.0: 刷新间隔白名单化 —— 1~60 秒 (下限由 5 秒放宽到 1 秒, 用户要求更快) */
|
|
619
619
|
export const clampRefreshSec = (v) => Math.min(Math.max(Math.round(Number(v) || 1), 1), 60)
|
|
620
620
|
|
|
621
|
+
/**
|
|
622
|
+
* 毫秒级夹取 (2026-09-22 补漏): sanitizePersistedShape 只夹**状态文件**读出来的值,
|
|
623
|
+
* 而从 config (cordis.patch.yml / profile 配置) 进来的值**没有任何夹取** ——
|
|
624
|
+
* 于是 patch 里写死的 refreshIntervalMs: 300000 (300 秒) 会绕过 clampRefreshSec 直接生效,
|
|
625
|
+
* 用户看到「刷新间隔 300 秒」。这里给 config 这条路补上同一道闸门。
|
|
626
|
+
*/
|
|
627
|
+
export const clampMs = (v, min, max, fallback) => {
|
|
628
|
+
const n = Number(v)
|
|
629
|
+
return Number.isFinite(n) ? Math.min(Math.max(Math.round(n), min), max) : fallback
|
|
630
|
+
}
|
|
631
|
+
|
|
621
632
|
/**
|
|
622
633
|
* 第 2 层自动判定的补充素材: 提取 settings.yaml 里 `llm-pi-ai.providers.<name>` 的
|
|
623
634
|
* **全部 provider 名**,包括没有写 baseURL 的 provider。这样即使别人没有手写 URL,
|
|
@@ -755,10 +766,14 @@ const fnv1a = (str) => {
|
|
|
755
766
|
// 北京时间 09:00~12:00 / 14:00~18:00 为峰时(100%), 其余时段谷时特惠(5折)
|
|
756
767
|
// ============================================================
|
|
757
768
|
// v1.3.4 (2026-09-10): 官方同日 12:00 起调整 Flash 系列定价(最高降幅 60%), 并收敛模型名 ——
|
|
758
|
-
// deepseek-v4-flash → deepseek-flash (旧名仍可调用, 由 V4.1-Flash 服务并按 Flash 价计费, 定价页注 1)
|
|
759
|
-
//
|
|
769
|
+
// deepseek-v4-flash → deepseek-flash (旧名仍可调用, 由 V4.1-Flash 服务并按 Flash 价计费, 定价页注 1)。
|
|
770
|
+
// ⚠️ 2026-09-22 复核更正: 官方注(2) 已改写为「为响应广大用户的需求, 我们决定在 2026 年 9 月 14 日之后
|
|
771
|
+
// 继续提供 DeepSeek V4 Pro 的 API 调用服务, 计费方式保持不变」—— **Pro 档仍在售、仍按 Pro 价计费**,
|
|
772
|
+
// 故本表 pro 档保留正确。此前「9-14 后 pro 请求全部路由到 Flash 并按 Flash 价计费」的记录已作废, 勿再回填。
|
|
760
773
|
// 来源: https://api-docs.deepseek.com/zh-cn/quick_start/pricing (CNY) 与 /quick_start/pricing (USD) ——
|
|
761
|
-
// USD 表为官方直发(非 ÷7 换算, 实际口径约 1 USD ≈ 6.67 CNY),
|
|
774
|
+
// USD 表为官方直发(非 ÷7 换算, 实际口径约 1 USD ≈ 6.67 CNY), 已逐项核对与表内值一致 (2026-09-22)。
|
|
775
|
+
// ⚠️ 官方英文页明确: 高峰时段为 UTC 01:00-04:00 / 06:00-10:00 (北京 9-12 / 14-18) 周一至周五,
|
|
776
|
+
// **excluding Chinese public holidays**(不含中国法定节假日) —— 见 isPeakTime 的已知缺口。
|
|
762
777
|
export const V4_RATES = {
|
|
763
778
|
CNY: {
|
|
764
779
|
peak: { 'deepseek-flash': { cacheHit: 0.04, cacheMiss: 2, output: 8 }, 'deepseek-v4-pro': { cacheHit: 0.3, cacheMiss: 9, output: 27 } },
|
|
@@ -778,10 +793,41 @@ export const V4_RATES = {
|
|
|
778
793
|
*/
|
|
779
794
|
const USD_TO_CNY_RATE = 7
|
|
780
795
|
|
|
781
|
-
/**
|
|
796
|
+
/**
|
|
797
|
+
* 中国法定节假日 (2026 年) —— DeepSeek 官方定价页**英文版**明确:
|
|
798
|
+
* "Peak hours are 01:00 - 04:00 and 06:00 - 10:00 UTC, Monday through Friday,
|
|
799
|
+
* **excluding Chinese public holidays**. All other hours are off-peak, including weekends
|
|
800
|
+
* and Chinese public holidays in full."
|
|
801
|
+
* 即法定节假日**全天按空闲(谷)价**计费。这不是可选项: 漏掉它会在这 33 天里把消耗按峰价高估一倍。
|
|
802
|
+
* 来源: 国务院办公厅《关于2026年部分节假日安排的通知》(2025-11-04 发布)
|
|
803
|
+
* https://www.gov.cn/zhengce/zhengceku/202511/content_7047091.htm
|
|
804
|
+
* ⚠️ 维护: 国务院办每年 11 月公布**次年**安排 —— 跨年前必须补下一年表; 表外年份按"无节假日"回落旧行为(保守)。
|
|
805
|
+
* ⚠️ 调休上班的周末(2026 年为 02-14 / 02-28 / 05-09 / 09-20 / 10-10)不列入本表:
|
|
806
|
+
* 官方口径是 "Monday through Friday" 字面 —— 周末本身就已是谷时, 无需专门处理。
|
|
807
|
+
*/
|
|
808
|
+
const CN_HOLIDAY_RANGES = {
|
|
809
|
+
2026: [
|
|
810
|
+
['2026-01-01', '2026-01-03'], // 元旦 3 天
|
|
811
|
+
['2026-02-15', '2026-02-23'], // 春节 9 天
|
|
812
|
+
['2026-04-04', '2026-04-06'], // 清明节 3 天
|
|
813
|
+
['2026-05-01', '2026-05-05'], // 劳动节 5 天
|
|
814
|
+
['2026-06-19', '2026-06-21'], // 端午节 3 天
|
|
815
|
+
['2026-09-25', '2026-09-27'], // 中秋节 3 天
|
|
816
|
+
['2026-10-01', '2026-10-07'], // 国庆节 7 天
|
|
817
|
+
],
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
/** 该北京日期 (yyyy-mm-dd) 是否落在法定节假日区间内。未收录的年份返回 false (不表态)。 */
|
|
821
|
+
export const isCnHoliday = (ymd) => {
|
|
822
|
+
const ranges = CN_HOLIDAY_RANGES[Number(String(ymd).slice(0, 4))]
|
|
823
|
+
if (!Array.isArray(ranges)) return false
|
|
824
|
+
return ranges.some(([from, to]) => ymd >= from && ymd <= to)
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
/** 北京时间(UTC+8)的日期/星期/小时, 先 +8h 再取值, 避免跨日界(00:00~08:00)星期比北京时间早一天 */
|
|
782
828
|
const bjtParts = (timestamp) => {
|
|
783
829
|
const d = new Date(timestamp + 8 * 3600 * 1000)
|
|
784
|
-
return { weekday: d.getUTCDay(), hour: d.getUTCHours() }
|
|
830
|
+
return { weekday: d.getUTCDay(), hour: d.getUTCHours(), ymd: d.toISOString().slice(0, 10) }
|
|
785
831
|
}
|
|
786
832
|
|
|
787
833
|
/**
|
|
@@ -790,13 +836,15 @@ const bjtParts = (timestamp) => {
|
|
|
790
836
|
* 周末(周六日): 整天都是谷时特惠。
|
|
791
837
|
*/
|
|
792
838
|
export const isPeakTime = (timestamp = Date.now()) => {
|
|
793
|
-
const { weekday, hour } = bjtParts(timestamp)
|
|
839
|
+
const { weekday, hour, ymd } = bjtParts(timestamp)
|
|
794
840
|
// 周末(0=周日, 6=周六)整天谷时
|
|
795
841
|
if (weekday === 0 || weekday === 6) return false
|
|
842
|
+
// 法定节假日全天谷时 (官方英文定价页: "excluding Chinese public holidays ... in full")
|
|
843
|
+
if (isCnHoliday(ymd)) return false
|
|
796
844
|
return (hour >= 9 && hour < 12) || (hour >= 14 && hour < 18)
|
|
797
845
|
}
|
|
798
846
|
|
|
799
|
-
/** 当前是否周末 */
|
|
847
|
+
/** 当前是否周末 (注意: 周末与法定节假日是两回事, 峰谷判定请用 isPeakTime) */
|
|
800
848
|
export const isWeekend = (timestamp = Date.now()) => {
|
|
801
849
|
const { weekday } = bjtParts(timestamp)
|
|
802
850
|
return weekday === 0 || weekday === 6
|
|
@@ -831,27 +879,76 @@ export const MODEL_PRICES = {
|
|
|
831
879
|
// 来源: modelradar.cn 2026-09-03 快照 (各模型 sourceUrl 均指官方定价页)。
|
|
832
880
|
// 仅采纳与官方口径无分歧的条目; 与原表冲突时保留原值并注明 ——
|
|
833
881
|
// radar 的 GPT-5.6 系输出价全呈「输入×1.25」异常模式, 疑似抓错列, 未采纳。
|
|
834
|
-
// ⚠️ OpenAI / Anthropic / Gemini
|
|
835
|
-
//
|
|
882
|
+
// ⚠️ 上注为 v1.4.0 时期状况。v1.4.5 (2026-09-22) 起: OpenAI / Anthropic / **Gemini** 三家均已用官方原文逐条核对
|
|
883
|
+
// (OpenAI / Anthropic 的价格藏在页面内嵌转义 JSON 里; Gemini 走 ai.google.dev 定价页的 Standard 档表),
|
|
884
|
+
// 并**整段补录 xAI Grok** —— 此前表内没有任何 grok 键, 全部落 defaultPrices。
|
|
885
|
+
// 下列海外条目现为官方现价; 有账单单据时仍以单据为准。
|
|
836
886
|
// OpenAI GPT-5.6 系列 (radar 报 sol 输出 $5 / terra $2.5 / luna $0.25, 均为输入×1.25 异常模式, 未采纳)
|
|
837
|
-
|
|
887
|
+
// —— 2026-09-22 官方 API 定价页 (openai.com/api/pricing 的内嵌 JSON) 逐条核对 ——
|
|
888
|
+
// 注: 该页 HTML 里的价格藏在 <script> 的双层转义 JSON 中, 不在 <table> 里; 本容器内 chromium 无网络渲染不了,
|
|
889
|
+
// 但直接取页面 + 还原转义即可拿到官方原文 (无需代理)。同一页还列出 GPT-Image-2.5 / GPT-Live-1 / GPT-Realtime-2.1 mini。
|
|
890
|
+
// ⚠️ 官方现列表价 $5/$30, 已无促销标记 —— 旧值 4/20 记的是"临时促销价", 按 AGENTS.md 红线(促销必须有官方原文兜底)改用官方现价。
|
|
891
|
+
'gpt-6-astra': { cacheHit: 1.0, cacheMiss: 10.0, output: 50.0 }, // 官方 Input $10 / Cached input $1 / Output $50 (官方页当前最强档)
|
|
892
|
+
'gpt-5.6-sol': { cacheHit: 0.5, cacheMiss: 5.0, output: 30.0 }, // 官方 $5 / $0.5 / $30
|
|
838
893
|
'gpt-5.6-terra': { cacheHit: 0.2, cacheMiss: 2.0, output: 12.0 }, // 2026-07-30 降价
|
|
839
894
|
'gpt-5.6-luna': { cacheHit: 0.02, cacheMiss: 0.2, output: 1.2 }, // 2026-07-30 降价
|
|
840
|
-
'gpt-5.3-codex': { cacheHit: 0.175, cacheMiss: 1.75, output: 14.0 }, //
|
|
895
|
+
'gpt-5.3-codex': { cacheHit: 0.175, cacheMiss: 1.75, output: 14.0 }, // ⚠️ 2026-09-22 复核: OpenAI 官方 API 定价页现**未列**此模型(页面只列 GPT-6 Astra / GPT-5.6 三档 / 图像 / Live / Realtime), 值仍为 radar 二手源, 未能取证
|
|
841
896
|
// Anthropic Claude 5
|
|
842
|
-
'claude-opus-5': { cacheHit: 0.5, cacheMiss: 5.0, output: 25.0 }, // v1.2.0 修正缓存读价: Anthropic 缓存读=0.1×输入, radar 对照 claude.com/pricing (opus-4-8 亦 $0.5); 原误标"无缓存折扣"
|
|
843
|
-
'claude-sonnet-5': { cacheHit: 0.2, cacheMiss: 2.0, output: 10.0 },
|
|
844
|
-
'claude-sonnet-4-6': { cacheHit: 0.30, cacheMiss: 3.00, output: 15.00 },
|
|
845
|
-
'claude-haiku-4-5': { cacheHit: 0.10, cacheMiss: 1.00, output: 5.00 },
|
|
846
|
-
//
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
'
|
|
852
|
-
'
|
|
853
|
-
'
|
|
854
|
-
'
|
|
897
|
+
'claude-opus-5': { cacheHit: 0.5, cacheMiss: 5.0, cacheWrite: 6.25, output: 25.0 }, // v1.2.0 修正缓存读价: Anthropic 缓存读=0.1×输入, radar 对照 claude.com/pricing (opus-4-8 亦 $0.5); 原误标"无缓存折扣"
|
|
898
|
+
'claude-sonnet-5': { cacheHit: 0.2, cacheMiss: 2.0, cacheWrite: 2.5, output: 10.0 },
|
|
899
|
+
'claude-sonnet-4-6': { cacheHit: 0.30, cacheMiss: 3.00, cacheWrite: 3.75, output: 15.00 },
|
|
900
|
+
'claude-haiku-4-5': { cacheHit: 0.10, cacheMiss: 1.00, cacheWrite: 1.25, output: 5.00 },
|
|
901
|
+
// —— 2026-09-22 官方 API 定价页 (anthropic.com/pricing 的 ApiTab) 核对后补录 ——
|
|
902
|
+
// 官方**同时**给出 Prompt caching 的 Read/Write 两档: Write 一律 = 输入价 ×125%
|
|
903
|
+
// (Opus 5 $6.25/$5、Sonnet 5 $2.50/$2、Haiku 4.5 $1.25/$1、Fable 5.1 $12.50/$10 全部吻合),
|
|
904
|
+
// Read 多数 = 输入价 ×10%(本表 cacheHit 口径), **Fable 5.1 例外仅 2.5%**。
|
|
905
|
+
// ⚠️ 现有 claude-opus-5 / sonnet-5 / sonnet-4-6 / haiku-4-5 四条经核对与官方逐项一致, 未改动。
|
|
906
|
+
'claude-fable-5.1': { cacheHit: 0.25, cacheMiss: 10.0, cacheWrite: 12.5, output: 50.0 }, // 官方 $10 / $0.25(缓存读仅 2.5%) / $50; 缓存写 $12.50
|
|
907
|
+
'claude-fable-5': { cacheHit: 1.0, cacheMiss: 10.0, cacheWrite: 12.5, output: 50.0 }, // 官方 $10 / $1 / $50; 缓存写 $12.50
|
|
908
|
+
'claude-opus-4-8': { cacheHit: 0.5, cacheMiss: 5.0, cacheWrite: 6.25, output: 25.0 }, // 官方 $5 / $0.5 / $25; 缓存写 $6.25
|
|
909
|
+
'claude-sonnet-4-5': { cacheHit: 0.30, cacheMiss: 3.0, cacheWrite: 3.75, output: 15.0 }, // 官方 $3 / $0.30 / $15; 缓存写 $3.75
|
|
910
|
+
// —— Google Gemini (2026-09-22 官方页 ai.google.dev/gemini-api/docs/pricing 的 Standard 档 Text API 逐条核对) ——
|
|
911
|
+
// 官方口径: Context caching price 一律 = 输入价 **10%**(3.7/3.8/3.6 Flash $0.075/$0.75、3.5 Flash $0.15/$1.50、
|
|
912
|
+
// 3.5 Flash-Lite $0.03/$0.30、3.1 Flash-Lite $0.025/$0.25、3.1 Pro $0.20/$2.00、3 Flash Preview $0.05/$0.50、
|
|
913
|
+
// 2.5 Pro $0.125/$1.25、2.5 Flash $0.03/$0.30、2.5 Flash-Lite $0.01/$0.10 全部吻合)。
|
|
914
|
+
// ⇒ 凡官方页**列出** Context caching price 的条目一律按官方值入库。旧表把 3 条标成「无缓存折扣」是错的(见下三条 ✗→✓)。
|
|
915
|
+
// ⚠️ 促销价: 3.6/3.7/3.8 Flash 官方明文 "through December 31, 2026", 到期翻倍($1.50/$7.50/缓存 $0.15) —— 有到期日兜底才可入库。
|
|
916
|
+
// ⚠️ 分档: 3.1 Pro / 2.5 Pro 官方另有 >200k 档, 本表取主档(与 Claude 同口径), 更贵档见各条注释。
|
|
917
|
+
'gemini-3.8-flash': { cacheHit: 0.075, cacheMiss: 0.75, output: 3.75 }, // 官方 $0.75/$3.75/缓存 $0.075; 促销至 2026-12-31, 之后 $1.50/$7.50
|
|
918
|
+
'gemini-3.7-flash': { cacheHit: 0.075, cacheMiss: 0.75, output: 3.75 }, // 同上
|
|
919
|
+
'gemini-3.6-flash': { cacheHit: 0.075, cacheMiss: 0.75, output: 3.75 }, // 同上
|
|
920
|
+
'gemini-3.5-flash': { cacheHit: 0.15, cacheMiss: 1.5, output: 9.0 }, // 官方 $1.50/$9.00/缓存 $0.15 ✚补录: 旧表无此键 → 落默认价($1/$2), 输出低估 4.5 倍
|
|
921
|
+
'gemini-3.5-flash-lite': { cacheHit: 0.03, cacheMiss: 0.3, output: 2.5 }, // 官方 $0.30/$2.50/缓存 $0.03 ✗→✓ 旧 cacheHit 0.3 且标「无缓存折扣」, 官方页明列 $0.03 → 高估缓存读 10 倍
|
|
922
|
+
'gemini-3.1-flash-lite': { cacheHit: 0.025, cacheMiss: 0.25, output: 1.5 }, // 官方 $0.25(text/图/视频)/$1.50/缓存 $0.025 ✚补录
|
|
923
|
+
'gemini-3-flash-preview': { cacheHit: 0.05, cacheMiss: 0.5, output: 3.0 }, // 官方 $0.50/$3.00/缓存 $0.05 ✗→✓ 旧 0.025 = 输入的 5%, 官方是 10%
|
|
924
|
+
'gemini-3.1-pro': { cacheHit: 0.20, cacheMiss: 2.0, output: 12.0 }, // 官方 $2.00/$12.00/缓存 $0.20 ✗→✓ 旧 cacheHit 2.0 且标「无缓存折扣」→ 高估缓存读 10 倍; >200k 档 $4/$18/缓存 $0.40
|
|
925
|
+
'gemini-omni-flash': { cacheHit: 1.5, cacheMiss: 1.5, output: 9.0 }, // 官方 $1.50/$9.00(text) ✚补录; 官方页**未列**缓存价 → 按输入价计, 不假设折扣(video 输出 $17.50 未建模)
|
|
926
|
+
'gemini-2.5-pro': { cacheHit: 0.125, cacheMiss: 1.25, output: 10.00 }, // 官方 $1.25/$10.00/缓存 $0.125; >200k 档 $2.50/$15.00/缓存 $0.25
|
|
927
|
+
'gemini-2.5-flash': { cacheHit: 0.03, cacheMiss: 0.3, output: 2.5 }, // 官方 $0.30(text/图/视频; audio $1.00)/$2.50/缓存 $0.03
|
|
928
|
+
'gemini-2.5-flash-lite':{ cacheHit: 0.01, cacheMiss: 0.10, output: 0.40 }, // 官方 $0.10/$0.40/缓存 $0.01 ✚补录: 旧表无此键 → 落默认价, 输入高估 10 倍 / 输出高估 5 倍
|
|
929
|
+
|
|
930
|
+
// —— xAI Grok (2026-09-22 官方页 docs.x.ai/docs/pricing 的 Text API 表逐条核对, **整段补录**) ——
|
|
931
|
+
// ⚠️ v1.4.5 之前本表**没有任何 grok 键**: 所有 grok 请求落 defaultPrices(USD $1/$2, 缓存读 $0.1),
|
|
932
|
+
// 而 grok-4.7 / 4.6 真价 $2/$6 → 输入少算 2 倍、输出少算 3 倍; grok-4.3 / 4.20 系输入输出各少算 25%。
|
|
933
|
+
// 官方口径: 每模型两档, 长上下文阈值一律 **200k tokens**(≥200k 时输入×2、输出×2、缓存×2);
|
|
934
|
+
// 本表取**主档(短上下文)**入库, 与同为 200k 阈值的 gemini-3.1-pro / gemini-2.5-pro 处理一致。
|
|
935
|
+
// 交叉验证: 官方页面内嵌机读数据 __XAI_PUBLIC_MODELS__ 的 us-east-1 / us-west-2 集群与本表逐项吻合;
|
|
936
|
+
// 其 us-central-1 集群是 US 区域端点价(= 标准 ×1.1, 目前只覆盖 4.7/4.6), 未入库。
|
|
937
|
+
// 未建模: Batch API 对 4.3 / 4.20 系有 20% 折扣; Priority Processing 一律 ×2 标准价。
|
|
938
|
+
// 未收录: 官方页现只列 grok-4.3 起的在售模型, grok-3 / grok-4 / grok-4-fast 等已不在页内 → 落默认价。
|
|
939
|
+
'grok-4.7': { cacheHit: 0.50, cacheMiss: 2.0, output: 6.0 }, // 官方 $2.00/$6.00/缓存 $0.50 (500k 上限); ≥200k: $4/$12/缓存 $1
|
|
940
|
+
'grok-4.6': { cacheHit: 0.50, cacheMiss: 2.0, output: 6.0 }, // 同上
|
|
941
|
+
'grok-4.5': { cacheHit: 0.30, cacheMiss: 2.0, output: 6.0 }, // 官方 $2.00/$6.00/缓存 $0.30; ≥200k: $4/$12/缓存 $0.60
|
|
942
|
+
'grok-4.3': { cacheHit: 0.20, cacheMiss: 1.25, output: 2.5 }, // 官方 $1.25/$2.50/缓存 $0.20 (1M 上限); ≥200k: $2.50/$5/缓存 $0.40
|
|
943
|
+
'grok-4.20': { cacheHit: 0.20, cacheMiss: 1.25, output: 2.5 }, // 官方别名(等价 grok-4.20-0309-reasoning, 同价)
|
|
944
|
+
'grok-4.20-reasoning': { cacheHit: 0.20, cacheMiss: 1.25, output: 2.5 }, // 官方别名; 连带 -latest / -0309 等
|
|
945
|
+
'grok-4.20-non-reasoning': { cacheHit: 0.20, cacheMiss: 1.25, output: 2.5 }, // 官方 $1.25/$2.50/缓存 $0.20 (1M)
|
|
946
|
+
'grok-4.20-multi-agent-0309': { cacheHit: 0.20, cacheMiss: 1.25, output: 2.5 }, // 官方 $1.25/$2.50/缓存 $0.20 (1M)
|
|
947
|
+
'grok-4.20-0309-reasoning': { cacheHit: 0.20, cacheMiss: 1.25, output: 2.5 }, // 官方 $1.25/$2.50/缓存 $0.20 (1M)
|
|
948
|
+
'grok-4.20-0309-non-reasoning': { cacheHit: 0.20, cacheMiss: 1.25, output: 2.5 }, // 官方 $1.25/$2.50/缓存 $0.20 (1M)
|
|
949
|
+
'grok-build-0.1': { cacheHit: 0.20, cacheMiss: 1.0, output: 2.0 }, // 官方 $1.00/$2.00/缓存 $0.20 (256k); ≥200k: $2/$4/缓存 $0.40
|
|
950
|
+
'grok-code-fast-1': { cacheHit: 0.20, cacheMiss: 1.0, output: 2.0 }, // grok-build-0.1 的官方别名(-1-0825 亦由安全后缀命中)
|
|
951
|
+
'grok-code-fast': { cacheHit: 0.20, cacheMiss: 1.0, output: 2.0 }, // 同上(别名短名)
|
|
855
952
|
// —— 国内厂商: 单位 CNY/百万tokens (原生官方价, 不要再 ÷7) ——
|
|
856
953
|
// 阿里云百炼 Qwen3 (华北2/北京; help.aliyun.com/zh/model-studio/model-pricing 2026-09-10 抓取)
|
|
857
954
|
// 官方上下文缓存规则: 命中按「标准输入单价 10%」计费。
|
|
@@ -862,6 +959,10 @@ export const MODEL_PRICES = {
|
|
|
862
959
|
'qwen3.7-plus': { cacheHit: 0.16, cacheMiss: 1.6, output: 6.4 }, // v1.4.0: 官方限时 8 折 (原价 ¥2/¥8)
|
|
863
960
|
'qwen3.7-flash': { cacheHit: 0.02, cacheMiss: 0.2, output: 0.8 }, // v1.4.0: 官方 ¥0.2/¥0.8 (旧值 0.21/0.91 系中转站高档位, 已废)
|
|
864
961
|
'qwen3.8-flash': { cacheHit: 0.1, cacheMiss: 0.8, output: 2.7 }, // 官方 ¥0.8/¥2.7; cacheHit ¥0.1 同 3.8-max 为控制台例外价
|
|
962
|
+
// —— 2026-09-22 官方百炼定价页 (help.aliyun.com/zh/model-studio/model-pricing) 核对后补录 ——
|
|
963
|
+
'qwen3.8-max-prime': { cacheHit: 2.4, cacheMiss: 24, output: 72 }, // 官方优速模式(Prime) ¥24/¥72; 官方未单列缓存价, 按"显式缓存命中=标准输入 10%"规则推
|
|
964
|
+
'qwen3.8-omni-flash': { cacheHit: 0.1, cacheMiss: 0.8, output: 2.7 }, // 官方 ¥0.8/¥2.7/缓存命中 ¥0.1 (3.8 系里唯一官方单列缓存价的)
|
|
965
|
+
'qwen3.5-plus': { cacheHit: 0.08, cacheMiss: 0.8, output: 4.8 }, // 官方 [0,128K) ¥0.8/¥4.8
|
|
865
966
|
'qwen3.8-27b': { cacheHit: 0.3, cacheMiss: 3, output: 12 }, // v1.4.0: 官方 ¥3/¥12; 缓存命中按官方 10% 规则 → ¥0.3 (旧值 ¥0.6 偏高 100%)
|
|
866
967
|
'qwen3.6-plus': { cacheHit: 0.2, cacheMiss: 2, output: 12 }, // 官方 ¥2/¥12 (256K 档 ¥8/¥48 未做分档)
|
|
867
968
|
// 智谱 GLM (docs.bigmodel.cn/cn/guide/start/pricing 2026-09-10 抓取)
|
|
@@ -871,13 +972,30 @@ export const MODEL_PRICES = {
|
|
|
871
972
|
'glm-5.1': { cacheHit: 2, cacheMiss: 8, output: 28 }, // 官方 ≥32K 档 ¥8/¥28/缓存 ¥2 ([0,32K) 档为 ¥6/¥24/¥1.3)
|
|
872
973
|
'glm-5-turbo': { cacheHit: 1.8, cacheMiss: 7, output: 26 }, // v1.4.0: 官方 ≥32K 档 ¥7/¥26/缓存 ¥1.8 (旧值 1.68/8.4/28 两档都不符)
|
|
873
974
|
'glm-5.3-flash': { cacheHit: 0.23, cacheMiss: 0.8, output: 2.8 }, // 官方 ¥0.8/¥2.8/缓存 ¥0.23
|
|
975
|
+
// —— 2026-09-22 官方定价页 (docs.bigmodel.cn/cn/guide/start/pricing) 逐条核对后补录 ——
|
|
976
|
+
// 分档口径 = 按**输入长度**在 32K 切开 ([0, 32K) / ≥32K); 分档模型一律取更贵的 ≥32K 档(保守)。
|
|
977
|
+
'glm-5.3-flashx': { cacheHit: 0.57, cacheMiss: 2, output: 7 }, // 官方 ¥2/¥7/缓存 ¥0.57 (1M)
|
|
978
|
+
'glm-5': { cacheHit: 1.5, cacheMiss: 6, output: 22 }, // 官方 ≥32K 档 ¥6/¥22/缓存 ¥1.5 ([0,32K) 档为 ¥4/¥18/缓存 ¥1)
|
|
979
|
+
'glm-4.7': { cacheHit: 0.8, cacheMiss: 4, output: 16 }, // 官方 [32K,200K) 档 ¥4/¥16/缓存 ¥0.8 (低档 ¥2~3/¥8~14)
|
|
980
|
+
'glm-4.7-flashx': { cacheHit: 0.1, cacheMiss: 0.5, output: 3 }, // 官方 ¥0.5/¥3/缓存 ¥0.1 (200K)
|
|
981
|
+
'glm-4.5-air': { cacheHit: 0.24, cacheMiss: 1.2, output: 8 }, // 官方 [32K,128K) 档 ¥1.2/¥8/缓存 ¥0.24
|
|
982
|
+
'glm-4-air-250414': { cacheHit: 0.25, cacheMiss: 0.5, output: 0.5 }, // 官方 ¥0.5/¥0.5/缓存 ¥0.25
|
|
983
|
+
'glm-4-long': { cacheHit: 0.5, cacheMiss: 1, output: 1 }, // 官方 ¥1/¥1/缓存 ¥0.5 (1M)
|
|
984
|
+
// ⚠️ 这一条同时修掉一个键名错配: 原来 'glm-4-flashx-250414' 没有任何键能收它(旧值 0.05/0.1/0.1 被挂在
|
|
985
|
+
// 'glm-4-flash' 上), 而官方 GLM-4-Flash-250414 其实是**免费**、GLM-4-FlashX-250414 才是 ¥0.1/¥0.1/缓存 ¥0.05。
|
|
986
|
+
// 'glm-4-flashx' 比 'glm-4-flash' 长, matchModelPrice 取最长键 → FlashX 现在能命中自己的价。
|
|
987
|
+
'glm-4-flashx': { cacheHit: 0.05, cacheMiss: 0.1, output: 0.1 }, // 官方 GLM-4-FlashX-250414 ¥0.1/¥0.1/缓存 ¥0.05
|
|
874
988
|
// Kimi / Moonshot (platform.kimi.com/docs/pricing/* 2026-09-10 抓取, 均 CNY)
|
|
875
989
|
'kimi-k3': { cacheHit: 2, cacheMiss: 20, output: 100 }, // v1.4.0: 官方 ¥2/¥20/¥100 (旧值全线 +5%)
|
|
876
990
|
'kimi-k2.7-code': { cacheHit: 1.3, cacheMiss: 6.5, output: 27 }, // 官方 ¥1.3/¥6.5/¥27
|
|
877
991
|
'kimi-k2.7-code-highspeed': { cacheHit: 2.6, cacheMiss: 13, output: 54 },// v1.4.0 新增: 官方高速版 ¥2.6/¥13/¥54
|
|
878
992
|
'kimi-k2.6': { cacheHit: 1.1, cacheMiss: 6.5, output: 27 }, // v1.4.0: 官方缓存命中 ¥1.1 (旧值误抄成 k2.7-code 的 ¥1.3)
|
|
879
|
-
|
|
880
|
-
//
|
|
993
|
+
// ⚠️ 官方已于 **2026-08-31 全平台下线** (platform.kimi.com/docs/models.md, 调用返回 404), 官方无价目。
|
|
994
|
+
// 值仍为 v1.3.4 的 USD×7 保号迁移, **非官方价**, 仅作旧会话估算占位 —— 2026-09-22 复核确认下线, 未能取证。
|
|
995
|
+
'kimi-k2.5': { cacheHit: 0.679, cacheMiss: 3.864, output: 20.279 },
|
|
996
|
+
// 字节豆包 Seed —— ⚠️ 2026-09-22 复核: 火山方舟官方文档/定价页都是 SPA, fetch 只拿到壳(0 表),
|
|
997
|
+
// 而本容器内 chromium 无网络(无法渲染), 故**仍未能取证**。下列值仍是 v1.3.4 的 ×7 保号迁移, **非官方价**。
|
|
998
|
+
// 取证路径: 用带网络的浏览器打开 volcengine.com/docs/82379/1544106 抄表后回填。
|
|
881
999
|
'doubao-seed-2.0-pro-32k': { cacheHit: 0.616, cacheMiss: 3.087, output: 15.449 },
|
|
882
1000
|
'doubao-seed-2.0-pro-128k': { cacheHit: 0.924, cacheMiss: 4.634, output: 23.17 },
|
|
883
1001
|
'doubao-seed-2.0-pro-256k': { cacheHit: 1.855, cacheMiss: 9.268, output: 46.347 },
|
|
@@ -896,19 +1014,36 @@ export const MODEL_PRICES = {
|
|
|
896
1014
|
// MiniMax (platform.minimaxi.com/docs/guides/pricing-paygo 2026-09-10 抓取)
|
|
897
1015
|
'minimax-m2.7': { cacheHit: 0.42, cacheMiss: 2.1, output: 8.4 }, // v1.4.0 修复: 官方缓存读 ¥0.42 (旧值拿 cacheMiss ¥2.1 顶替 → 长会话高估 5 倍, 同 AGENTS.md 红线 4)
|
|
898
1016
|
'minimax-m2.7-highspeed': { cacheHit: 0.42, cacheMiss: 4.2, output: 16.8 }, // v1.4.0 新增: 官方高速版
|
|
1017
|
+
'minimax-m3': { cacheHit: 0.42, cacheMiss: 2.1, output: 8.4 }, // 2026-09-22 官方"永久五折" ≤512k 输入档 ¥2.1/¥8.4/缓存 ¥0.42 (>512k 档 ¥4.2/¥16.8/缓存 ¥0.84)
|
|
899
1018
|
// 美团 LongCat (中转站实测; 官方页未取到明文)
|
|
900
1019
|
'longcat-2.0': { cacheHit: 0.1, cacheMiss: 5, output: 20 }, // 实测 ¥5/¥20/缓存 ¥0.1
|
|
901
|
-
// 腾讯混元
|
|
1020
|
+
// 腾讯混元 —— ⚠️ 2026-09-22 复核: 官方计费页 (cloud.tencent.com/document/product/1729/97731) 与模型列表里
|
|
1021
|
+
// **均无以下三个 API 名** (官方现役计费项为 Hunyuan-a13b / hunyuan-role-latest / hunyuan-translation /
|
|
1022
|
+
// Tencent HY Vision 1.5 Instruct 等), 无从对照 → 下列值仍是 v1.3.4 的 ×7 保号迁移, **非官方价**。
|
|
1023
|
+
// 若确认是历史名/中转站命名, 可整段删除; 现在保留只为老会话估算不断档。
|
|
902
1024
|
'hunyuan-2.0-instruct-128k': { cacheHit: 4.347, cacheMiss: 4.347, output: 10.745 },
|
|
903
1025
|
'hunyuan-2.0-think-128k': { cacheHit: 5.117, cacheMiss: 5.117, output: 20.468 },
|
|
904
1026
|
'hunyuan-turbo-s': { cacheHit: 0.77, cacheMiss: 0.77, output: 1.932 },
|
|
905
1027
|
// 阶跃星辰 (platform.stepfun.com/docs/zh/guides/pricing/details 2026-09-10 抓取)
|
|
906
1028
|
'step-3.7-flash': { cacheHit: 0.27, cacheMiss: 1.35, output: 8.1 }, // 官方 ¥1.35/¥8.1/缓存 ¥0.27
|
|
907
1029
|
'step-3.5-flash': { cacheHit: 0.14, cacheMiss: 0.7, output: 2.1 }, // 官方 ¥0.7/¥2.1/缓存 ¥0.14
|
|
1030
|
+
'step-5-preview': { cacheHit: 0.35, cacheMiss: 7, output: 20 }, // 2026-09-22 官方新增 ¥7/¥20/缓存 ¥0.35
|
|
1031
|
+
'step-1o-turbo-vision': { cacheHit: 0.5, cacheMiss: 2.5, output: 8 }, // 2026-09-22 官方 ¥2.5/¥8/缓存 ¥0.5
|
|
908
1032
|
// 小米 MiMo — 官方 2026-05-27 起「永久降价」(最高降幅 99%), 取消上下文分档; 与中转站 tokenrhythm 实时报价一致。
|
|
909
1033
|
// v1.3.4 修的「除两次 7」结论正确, v1.4.0 起改为直接存官方 CNY 原值, 不再有 ÷7 环节。
|
|
910
|
-
|
|
911
|
-
|
|
1034
|
+
// —— 2026-09-22 官方按量付费页 (platform.xiaomimimo.com/docs/zh-CN/price/pay-as-you-go) 逐条核对 ——
|
|
1035
|
+
// V2.6 系列于当日发布(官方 updates/model 页 2026-09-22「模型发布」), 与 V2.5 系**同价**(实时推理档)。
|
|
1036
|
+
// ✚补录 3 条: 此前表内无任何 v2.6 键 → 全部落 defaultPrices(USD $1/$2), 按国内口径换算后为 ¥7/¥14,
|
|
1037
|
+
// 即 v2.6-pro 高估 2.33 倍、v2.6-flash 高估 7 倍。
|
|
1038
|
+
// ⚠️ V2.5 系官方下线公告 (updates/deprecate): **北京时间 2026-10-21 10:00 直接下线, 无系统替换模型** —
|
|
1039
|
+
// 保留其键仅供旧会话估算, 到期后新调用会失败, 别再把新流量算作 v2.5。
|
|
1040
|
+
// 未建模: 批量推理档(v2.6-pro ¥1.5/¥3、v2.6-flash ¥0.5/¥1)、mimo-v2.5-asr(按音频时长 ¥0.5/小时)、
|
|
1041
|
+
// 国内联网服务(¥16/1000 次); 官方另有 USD 表($0.435/$0.87 等), 按「原生币种存储」规则本表只用 CNY 表。
|
|
1042
|
+
'mimo-v2.6-pro': { cacheHit: 0.025, cacheMiss: 3, output: 6 }, // 官方实时推理 ¥3/¥6/缓存 ¥0.025 (与 v2.5-pro 同价)
|
|
1043
|
+
'mimo-v2.6-flash': { cacheHit: 0.02, cacheMiss: 1, output: 2 }, // 官方实时推理 ¥1/¥2/缓存 ¥0.02 (与 v2.5 同价)
|
|
1044
|
+
'mimo-v2.6-pro-ultraspeed': { cacheHit: 0.25, cacheMiss: 30, output: 60 }, // 官方 ¥30/¥60/缓存 ¥0.25 (旗舰性能 + 最高 20 倍推理速度)
|
|
1045
|
+
'mimo-v2.5': { cacheHit: 0.02, cacheMiss: 1, output: 2 }, // 官方 ¥1/¥2/缓存 ¥0.02 ⚠️ 2026-10-21 10:00 下线
|
|
1046
|
+
'mimo-v2.5-pro': { cacheHit: 0.025, cacheMiss: 3, output: 6 }, // 官方 ¥3/¥6/缓存 ¥0.025 ⚠️ 2026-10-21 10:00 下线
|
|
912
1047
|
// —— 以下为历史/参考模型 (2025-08, 实际以平台为准) ——
|
|
913
1048
|
// 币种规则同上: 海外的写 USD, 国内的写 CNY。
|
|
914
1049
|
// 🔴 v1.4.0 重要修复: 本段「国内」条目历来填的是**官方 CNY 原值**(不是 ÷7 后的 USD),
|
|
@@ -927,7 +1062,9 @@ export const MODEL_PRICES = {
|
|
|
927
1062
|
'claude-3-5-sonnet': { cacheHit: 0.3, cacheMiss: 3, output: 15 },
|
|
928
1063
|
'claude-3-5-haiku': { cacheHit: 0.08, cacheMiss: 0.8, output: 4 },
|
|
929
1064
|
'claude-3-opus': { cacheHit: 1.5, cacheMiss: 15, output: 75 },
|
|
930
|
-
// Gemini —
|
|
1065
|
+
// Gemini 历史条目 — ⚠️ 2026-09-22 复核: 官方定价页现**已不列** 2.0 / 1.5 全系(页面自 Gemini 2.5 起),
|
|
1066
|
+
// 故这三条的「缓存读 = 输入 ×25%」口径**无法取证**, 原样保留仅作旧会话估算占位, **非官方现价**。
|
|
1067
|
+
// 现役 Gemini 3.x / 2.5 官方页一律「缓存读 = 输入 ×10%」(2026-09-22 逐条吻合) —— 历史 25% 口径勿再套用到新条目。
|
|
931
1068
|
'gemini-2.0-flash': { cacheHit: 0.025, cacheMiss: 0.1, output: 0.4 },
|
|
932
1069
|
'gemini-2.0-pro': { cacheHit: 0.625, cacheMiss: 2.5, output: 10 },
|
|
933
1070
|
'gemini-1.5-pro': { cacheHit: 0.875, cacheMiss: 3.5, output: 10.5 },
|
|
@@ -943,15 +1080,20 @@ export const MODEL_PRICES = {
|
|
|
943
1080
|
'glm-4-plus': { cacheHit: 2.5, cacheMiss: 5, output: 5 }, // ✅ v1.4.0 修复: 官方 ¥2.5/¥5/¥5 (旧口径下显示 ¥17.5/¥35/¥35, 高 7 倍)
|
|
944
1081
|
'glm-4-flash': { cacheHit: 0.05, cacheMiss: 0.1, output: 0.1 }, // ⚠️ 官方 GLM-4-Flash-250414 现为免费; 此处保留历史 ¥0.1 档(宁高不低, 中转站可能仍计费)
|
|
945
1082
|
// 通义千问 (官方 CNY; 2026-09-10 抓取)
|
|
946
|
-
'qwen-plus': { cacheHit: 0.
|
|
1083
|
+
'qwen-plus': { cacheHit: 0.08, cacheMiss: 0.8, output: 2 }, // 官方 ¥0.8/¥2 ✅ (2026-09-22 核对: 现役 qwen-plus-2025-01-25 无阶梯计价);
|
|
1084
|
+
// ⚠️ cacheHit 原值 0.4(=输入 50%) **无官方依据** —— 官方明文「显式缓存命中按标准输入单价的 10% 计费」,
|
|
1085
|
+
// 同表其余 8 个 qwen 条目也都严格等于 10%, 只有 qwen-plus / qwen-turbo 是 50% → 已按官方规则改为 0.08 (旧值高估缓存读 5 倍)。
|
|
947
1086
|
'qwen-max': { cacheHit: 0.24, cacheMiss: 2.4, output: 9.6 },// v1.4.0: 官方现价 ¥2.4/¥9.6 (旧值 20/60 是远古价)
|
|
948
|
-
'qwen-turbo': { cacheHit: 0.
|
|
949
|
-
'qwen2.5-72b-instruct': { cacheHit: 2, cacheMiss: 4, output: 12 }, // 官方
|
|
950
|
-
// Kimi — ⚠️
|
|
1087
|
+
'qwen-turbo': { cacheHit: 0.03, cacheMiss: 0.3, output: 0.6 },// 官方 ¥0.3/¥0.6 (思考模式输出 ¥3) ✅; cacheHit 同上按官方 10% 规则改为 0.03 (旧值 0.15=50%)
|
|
1088
|
+
'qwen2.5-72b-instruct': { cacheHit: 2, cacheMiss: 4, output: 12 }, // ⚠️ 官方 2026-05-13 已下线(百炼下线公告), 保留仅为旧会话估算占位
|
|
1089
|
+
// Kimi — ⚠️ 官方 **2026-08-31 已全平台下线 moonshot-v1 全系** (调用 404), 官方价目已撤, 无法取证。
|
|
1090
|
+
// 下列值与原 Moonshot 官方历史价(¥12/¥12 一档)对不上, 仅作旧会话估算占位, 别当官方价引用。
|
|
951
1091
|
'moonshot-v1-8k': { cacheHit: 0.6, cacheMiss: 1.2, output: 2.4 },
|
|
952
1092
|
'moonshot-v1-32k': { cacheHit: 1.2, cacheMiss: 2.4, output: 4.8 },
|
|
953
1093
|
'moonshot-v1-128k': { cacheHit: 3, cacheMiss: 6, output: 12 },
|
|
954
|
-
// 阶跃星辰
|
|
1094
|
+
// 阶跃星辰 —— ⚠️ 2026-09-22 复核: 官方定价页现仅列 step-5-preview / step-3.7-flash / step-3.5-flash(-2603)
|
|
1095
|
+
// / step-1o-turbo-vision 与音频系列, **无下列 step-1-flash / step-1-8k / step-1-32k**(历史款),
|
|
1096
|
+
// 官方无从对照, 值仍为旧存留, **非当前官方价**。
|
|
955
1097
|
'step-1-flash': { cacheHit: 0.5, cacheMiss: 1, output: 2 },
|
|
956
1098
|
'step-1-8k': { cacheHit: 2, cacheMiss: 4, output: 8 },
|
|
957
1099
|
'step-1-32k': { cacheHit: 4, cacheMiss: 8, output: 15 },
|
|
@@ -995,9 +1137,13 @@ export const nativeCurrencyOf = (model) => (modelRegion(model) === '海外' ? 'U
|
|
|
995
1137
|
* 默认配置(国内 CNY / 海外 USD)下两边同币种, 根本不走换算 —— 这正是 v1.4.0 想达到的效果。
|
|
996
1138
|
*/
|
|
997
1139
|
const convertPrice = (price, from, to) => {
|
|
998
|
-
|
|
1140
|
+
// v1.5.0: cacheWrite 是**可选**档 (官方 Anthropic/阿里 = 输入 ×125%) —— 必须一并带过,
|
|
1141
|
+
// 否则会被这里静默丢掉, 缓存写入就退化成按 cacheMiss 计 (这正是 T14 第一次没测过的原因)。
|
|
1142
|
+
const cw = price.cacheWrite
|
|
1143
|
+
const withCw = (o) => (cw !== undefined ? { ...o, cacheWrite: cw } : o)
|
|
1144
|
+
if (from === to) return withCw({ cacheHit: price.cacheHit, cacheMiss: price.cacheMiss, output: price.output })
|
|
999
1145
|
const k = from === 'USD' ? USD_TO_CNY_RATE : 1 / USD_TO_CNY_RATE
|
|
1000
|
-
return { cacheHit: price.cacheHit * k, cacheMiss: price.cacheMiss * k, output: price.output * k }
|
|
1146
|
+
return withCw({ cacheHit: price.cacheHit * k, cacheMiss: price.cacheMiss * k, output: price.output * k })
|
|
1001
1147
|
}
|
|
1002
1148
|
|
|
1003
1149
|
/**
|
|
@@ -1038,7 +1184,7 @@ const matchModelPrice = (model) => {
|
|
|
1038
1184
|
}
|
|
1039
1185
|
|
|
1040
1186
|
/** 解析模型单价, 仅 deepseek-flash / deepseek-v4-* 支持峰谷自动切换; chat/reasoner 等走通用价格表 */
|
|
1041
|
-
export const resolveModelPrice = (configOrGetter, model, timestamp = Date.now()) => {
|
|
1187
|
+
export const resolveModelPrice = (configOrGetter, model, timestamp = Date.now(), phase = null) => {
|
|
1042
1188
|
const config = typeof configOrGetter === 'function' ? configOrGetter() : configOrGetter
|
|
1043
1189
|
const peak = isPeakTime(timestamp)
|
|
1044
1190
|
const display = currencyForModel(config, model)
|
|
@@ -1056,7 +1202,10 @@ export const resolveModelPrice = (configOrGetter, model, timestamp = Date.now())
|
|
|
1056
1202
|
if (typeof model === 'string' && (model.startsWith('deepseek-v4') || model.startsWith('deepseek-flash'))) {
|
|
1057
1203
|
const table = V4_RATES[display] ?? V4_RATES.CNY
|
|
1058
1204
|
const key = model.startsWith('deepseek-v4-pro') ? 'deepseek-v4-pro' : 'deepseek-flash'
|
|
1059
|
-
|
|
1205
|
+
// v1.5.0 峰谷分相: phase 显式给出时以它为准(历史上的每笔消耗按各自发生时刻计价),
|
|
1206
|
+
// 为 null 才回退到「按 timestamp 判定」的老行为 —— 默认参数保持向后兼容。
|
|
1207
|
+
const usePeak = phase === 'peak' ? true : phase === 'offPeak' ? false : peak
|
|
1208
|
+
const hit = (usePeak ? table.peak[key] : table.offPeak[key])
|
|
1060
1209
|
if (hit) return { ...hit }
|
|
1061
1210
|
}
|
|
1062
1211
|
|
|
@@ -1912,6 +2061,29 @@ export function makeCostProjection(configOrGetter, services) {
|
|
|
1912
2061
|
})
|
|
1913
2062
|
const round6 = (n) => Math.round(n * 1e6) / 1e6
|
|
1914
2063
|
|
|
2064
|
+
/**
|
|
2065
|
+
* v1.5.0: 某模型是否走 V4 峰谷表 —— 条件必须与 resolveModelPrice 内部一致
|
|
2066
|
+
* (用户在 config.prices 里自填过价的那一档不算峰谷, 自填价不做峰谷切换)。
|
|
2067
|
+
*/
|
|
2068
|
+
const phaseOfModel = (model, ts) => {
|
|
2069
|
+
if (typeof model !== 'string') return null
|
|
2070
|
+
if (!(model.startsWith('deepseek-v4') || model.startsWith('deepseek-flash'))) return null
|
|
2071
|
+
const cfg = getConfig()
|
|
2072
|
+
if (cfg?.prices && Object.prototype.hasOwnProperty.call(cfg.prices, model) && cfg.prices[model]) return null
|
|
2073
|
+
return isPeakTime(ts) ? 'peak' : 'offPeak'
|
|
2074
|
+
}
|
|
2075
|
+
/** 往分相桶加一份用量 (不可变更新)。 */
|
|
2076
|
+
const phaseAdd = (map, model, phase, buckets) => {
|
|
2077
|
+
const cur = map[model] ?? {}
|
|
2078
|
+
return { ...map, [model]: { ...cur, [phase]: addBuckets(cur[phase] ?? zero(), buckets) } }
|
|
2079
|
+
}
|
|
2080
|
+
/** 从分相桶减一份 (替换语义); 该相不存在时原样返回。 */
|
|
2081
|
+
const phaseSub = (map, model, phase, buckets) => {
|
|
2082
|
+
const cur = map[model]
|
|
2083
|
+
if (cur === undefined || cur[phase] === undefined) return map
|
|
2084
|
+
return { ...map, [model]: { ...cur, [phase]: subBuckets(cur[phase], buckets) } }
|
|
2085
|
+
}
|
|
2086
|
+
|
|
1915
2087
|
/**
|
|
1916
2088
|
* v1.4.0: 从一条 assistant stream 里取**最后一次** usage chunk。
|
|
1917
2089
|
* 与 dsh-llm 的 `lastAssistantStreamChunk(stream, 'usage')` 同语义, 本地实现以免给插件引入额外依赖
|
|
@@ -1959,8 +2131,16 @@ export function makeCostProjection(configOrGetter, services) {
|
|
|
1959
2131
|
tokens.cacheWrite += b.cacheWriteTokens
|
|
1960
2132
|
tokens.output += b.outputTokens
|
|
1961
2133
|
// 支持 DeepSeek 谷峰自动计费
|
|
1962
|
-
|
|
1963
|
-
|
|
2134
|
+
// v1.5.0: 缓存写入单独计价 —— 官方普遍按**标准输入价的 125%**收 (Anthropic $6.25/$5、阿里显式缓存明文 125%、
|
|
2135
|
+
// MiniMax 2.625/2.1), Kimi K3 更是另有 ¥20/1M 的写入费。表里没给 cacheWrite 的条目回落到 cacheMiss (= 旧行为, 结果不变)。
|
|
2136
|
+
const costOf = (bk, price) => ((bk.uncachedInputTokens * price.cacheMiss + bk.cacheWriteTokens * (price.cacheWrite ?? price.cacheMiss) + bk.cacheReadTokens * price.cacheHit + bk.outputTokens * price.output)) / 1e6
|
|
2137
|
+
// v1.5.0: 有分相数据就按峰/谷各自计价 (每笔用量用**它发生那一刻**的价),
|
|
2138
|
+
// 没有(老缓存/非峰谷模型)才回退到按当前时刻计价的老行为。
|
|
2139
|
+
const pb = state?.phaseBuckets?.[model]
|
|
2140
|
+
const c = (pb !== undefined && (pb.peak !== undefined || pb.offPeak !== undefined))
|
|
2141
|
+
? costOf(pb.peak ?? zero(), resolveModelPrice(cfg, model, undefined, 'peak'))
|
|
2142
|
+
+ costOf(pb.offPeak ?? zero(), resolveModelPrice(cfg, model, undefined, 'offPeak'))
|
|
2143
|
+
: (() => { const price = resolveModelPrice(cfg, model); return costOf(b, price) })()
|
|
1964
2144
|
// v1.3.2: 该模型实际币种 (海外模型可能与主货币不同)
|
|
1965
2145
|
const cur = currencyForModel(cfg, model)
|
|
1966
2146
|
if (c > 0) {
|
|
@@ -2013,15 +2193,26 @@ export function makeCostProjection(configOrGetter, services) {
|
|
|
2013
2193
|
if (usage === null) return unchanged ? state : { ...state, currentModel: nextModel, currentProvider: nextProvider }
|
|
2014
2194
|
const model = nextModel ?? 'unknown'
|
|
2015
2195
|
const buckets = bucketsOf(usage)
|
|
2196
|
+
// v1.5.0: 按**事件发生时刻**(event.time)判定峰谷, 而不是等 summarize 时用 Date.now()。
|
|
2197
|
+
// 后者会把整段历史消耗都按"打开面板那一刻"的时段计价 —— DeepSeek 峰谷价差 2 倍,
|
|
2198
|
+
// 谷时跑的量在峰时查看会被翻倍, 反之漏掉一半。事件无 time 时回退当前时刻。
|
|
2199
|
+
const eventTime = Number.isFinite(event?.time) ? event.time : Date.now()
|
|
2200
|
+
const phase = phaseOfModel(model, eventTime)
|
|
2016
2201
|
const prev = state.last !== null && state.last.turn === turn && state.last.step === step ? state.last : null
|
|
2017
2202
|
if (prev !== null && prev.model === model && bucketsEqual(prev.buckets, buckets)) {
|
|
2018
2203
|
return unchanged ? state : { ...state, currentModel: nextModel, currentProvider: nextProvider }
|
|
2019
2204
|
}
|
|
2020
2205
|
const isNewModel = !(model in state.byModel)
|
|
2021
2206
|
let byModel = state.byModel
|
|
2022
|
-
|
|
2207
|
+
let phaseBuckets = state.phaseBuckets ?? {}
|
|
2208
|
+
if (prev !== null) {
|
|
2209
|
+
byModel = { ...byModel, [prev.model]: subBuckets(byModel[prev.model] ?? zero(), prev.buckets) }
|
|
2210
|
+
// 替换槽位时, 分相桶也要按**上一个事件当时的相**回退, 否则重试会把同一笔算两次。
|
|
2211
|
+
if (prev.phase) phaseBuckets = phaseSub(phaseBuckets, prev.model, prev.phase, prev.buckets)
|
|
2212
|
+
}
|
|
2023
2213
|
byModel = { ...byModel, [model]: addBuckets(byModel[model] ?? zero(), buckets) }
|
|
2024
|
-
|
|
2214
|
+
if (phase) phaseBuckets = phaseAdd(phaseBuckets, model, phase, buckets)
|
|
2215
|
+
return { ...state, currentModel: nextModel, currentProvider: nextProvider, last: { turn, step, model, buckets, phase }, byModel, phaseBuckets, modelOrder: isNewModel ? [...state.modelOrder, model] : state.modelOrder }
|
|
2025
2216
|
}
|
|
2026
2217
|
|
|
2027
2218
|
return {
|
|
@@ -2041,6 +2232,8 @@ export function makeCostProjection(configOrGetter, services) {
|
|
|
2041
2232
|
cacheWriteTokens: z.number(),
|
|
2042
2233
|
outputTokens: z.number(),
|
|
2043
2234
|
}),
|
|
2235
|
+
/** v1.5.0: 该事件发生时的峰谷相, 替换槽位时要按同一个相回退分相桶。 */
|
|
2236
|
+
phase: z.string().nullable().optional(),
|
|
2044
2237
|
}).nullable(),
|
|
2045
2238
|
byModel: z.record(z.string(), z.object({
|
|
2046
2239
|
uncachedInputTokens: z.number(),
|
|
@@ -2048,21 +2241,26 @@ export function makeCostProjection(configOrGetter, services) {
|
|
|
2048
2241
|
cacheWriteTokens: z.number(),
|
|
2049
2242
|
outputTokens: z.number(),
|
|
2050
2243
|
})),
|
|
2244
|
+
/** v1.5.0: 按事件发生时刻拆分的峰/谷用量桶 (仅走 V4 峰谷表的模型才会出现)。 */
|
|
2245
|
+
phaseBuckets: z.record(z.string(), z.object({
|
|
2246
|
+
peak: z.object({ uncachedInputTokens: z.number(), cacheReadTokens: z.number(), cacheWriteTokens: z.number(), outputTokens: z.number() }).optional(),
|
|
2247
|
+
offPeak: z.object({ uncachedInputTokens: z.number(), cacheReadTokens: z.number(), cacheWriteTokens: z.number(), outputTokens: z.number() }).optional(),
|
|
2248
|
+
})).optional(),
|
|
2051
2249
|
modelOrder: z.array(z.string()),
|
|
2052
2250
|
/** v1.4.0: 本投影所属会话 id —— 子代理汇总要拿它去查 `subagentCatalog`。空串表示未知。 */
|
|
2053
2251
|
sessionId: z.string(),
|
|
2054
2252
|
inheritedEventCount: z.number().int().nonnegative(),
|
|
2055
2253
|
ownBoundaryKnown: z.boolean(),
|
|
2056
2254
|
ownChildIds: z.array(z.string()),
|
|
2057
|
-
own: z.object({ currentModel: z.string().nullable(), currentProvider: z.string().nullable(), last: z.any().nullable(), byModel: z.record(z.string(), z.object({ uncachedInputTokens: z.number().nonnegative(), cacheReadTokens: z.number().nonnegative(), cacheWriteTokens: z.number().nonnegative(), outputTokens: z.number().nonnegative() })), modelOrder: z.array(z.string()) }),
|
|
2255
|
+
own: z.object({ currentModel: z.string().nullable(), currentProvider: z.string().nullable(), last: z.any().nullable(), byModel: z.record(z.string(), z.object({ uncachedInputTokens: z.number().nonnegative(), cacheReadTokens: z.number().nonnegative(), cacheWriteTokens: z.number().nonnegative(), outputTokens: z.number().nonnegative() })), phaseBuckets: z.record(z.string(), z.any()).optional(), modelOrder: z.array(z.string()) }),
|
|
2058
2256
|
}),
|
|
2059
2257
|
init: (header, inheritedEventCount) => ({
|
|
2060
|
-
currentModel: null, currentProvider: null, last: null, byModel: {}, modelOrder: [],
|
|
2258
|
+
currentModel: null, currentProvider: null, last: null, byModel: {}, phaseBuckets: {}, modelOrder: [],
|
|
2061
2259
|
sessionId: typeof header?.id === 'string' ? header.id : '',
|
|
2062
2260
|
inheritedEventCount: Number.isSafeInteger(inheritedEventCount) && inheritedEventCount >= 0 ? inheritedEventCount : 0,
|
|
2063
2261
|
ownBoundaryKnown: (Number.isSafeInteger(inheritedEventCount) && inheritedEventCount >= 0) || !header?.isSeeded,
|
|
2064
2262
|
ownChildIds: [],
|
|
2065
|
-
own: { currentModel: null, currentProvider: null, last: null, byModel: {}, modelOrder: [] },
|
|
2263
|
+
own: { currentModel: null, currentProvider: null, last: null, byModel: {}, phaseBuckets: {}, modelOrder: [] },
|
|
2066
2264
|
}),
|
|
2067
2265
|
apply: (state, event) => {
|
|
2068
2266
|
const full = foldUsage(state, event)
|
|
@@ -2131,7 +2329,7 @@ export function makeCostProjection(configOrGetter, services) {
|
|
|
2131
2329
|
}
|
|
2132
2330
|
},
|
|
2133
2331
|
},
|
|
2134
|
-
stateVersion:
|
|
2332
|
+
stateVersion: 4,
|
|
2135
2333
|
}
|
|
2136
2334
|
}
|
|
2137
2335
|
|
|
@@ -2152,9 +2350,10 @@ export function apply(ctx, config) {
|
|
|
2152
2350
|
}
|
|
2153
2351
|
} catch { /* 忽略 */ }
|
|
2154
2352
|
const runtimeConfig = {
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2353
|
+
// ⚠️ 两个来源都要夹: persisted 已被 sanitizePersistedShape 夹过, 但 config 没有 (见 clampMs 注释)。
|
|
2354
|
+
refreshIntervalMs: clampMs(persisted.refreshIntervalMs ?? config.refreshIntervalMs, 1000, 60000, 5000),
|
|
2355
|
+
clientPollIntervalMs: clampMs(persisted.clientPollIntervalMs ?? config.clientPollIntervalMs, 1000, 60000, 5000),
|
|
2356
|
+
timeoutMs: clampMs(persisted.timeoutMs ?? config.timeoutMs, 1000, 60000, 8000),
|
|
2158
2357
|
presets: config.presets ?? PLATFORM_PRESETS.map(p => p.id),
|
|
2159
2358
|
// H-1 (v1.4.1): 这里必须带 Array.isArray —— 状态文件形状跑偏时 apply() 抛出 =
|
|
2160
2359
|
// 整个 dsh web 启动失败(migratePersistedState 已消毒, 这里是第二道防线)
|