@kenz1117/dsh-ui-usage-billing 1.0.1 → 1.0.3
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.en.md +2 -0
- package/README.md +35 -25
- package/lib/client.js +1241 -490
- package/lib/index.js +679 -50
- package/lib/types/client/locales.d.ts +1 -1
- package/lib/types/client/pricing.d.ts +65 -5
- package/lib/types/client/vendor-logos.d.ts +9 -0
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -70,7 +70,21 @@ const PLAN_KNOWLEDGE = {
|
|
|
70
70
|
"minimax": { type: "code" },
|
|
71
71
|
"minimax-cn": { type: "code" },
|
|
72
72
|
"minimax-token-plan": { type: "code" },
|
|
73
|
-
"minimax-token-plan-cn": { type: "code" }
|
|
73
|
+
"minimax-token-plan-cn": { type: "code" },
|
|
74
|
+
"hunyuan-token-plan": { type: "code" },
|
|
75
|
+
"tencent-token-plan": { type: "code" },
|
|
76
|
+
"hy-token-plan": { type: "code" },
|
|
77
|
+
"xinghuo-token-plan": { type: "code" },
|
|
78
|
+
"xfyun-coding": { type: "code" },
|
|
79
|
+
"spark-coding": { type: "code" },
|
|
80
|
+
"huawei-token-plan": { type: "code" },
|
|
81
|
+
"pangu-token-plan": { type: "code" },
|
|
82
|
+
"huawei-maas-token-plan": { type: "code" },
|
|
83
|
+
"volcengine-agent-plan": { type: "code" },
|
|
84
|
+
"ark-agent-plan": { type: "code" },
|
|
85
|
+
"baidu-token-plan": { type: "code" },
|
|
86
|
+
"ernie-token-plan": { type: "code" },
|
|
87
|
+
"wenxin-token-plan": { type: "code" }
|
|
74
88
|
};
|
|
75
89
|
/**
|
|
76
90
|
* 订阅/plan provider id 变体 → PLAN_KNOWLEDGE 规范键(引用 dsh-spend 的别名归一化)。
|
|
@@ -312,6 +326,23 @@ const MODEL_CATALOG = [
|
|
|
312
326
|
output: 28
|
|
313
327
|
}
|
|
314
328
|
},
|
|
329
|
+
{
|
|
330
|
+
key: "glm-5.3-flash",
|
|
331
|
+
name: "GLM-5.3-Flash",
|
|
332
|
+
provider: "智谱 AI",
|
|
333
|
+
colorVar: "dsw-static-blue-300",
|
|
334
|
+
price: {
|
|
335
|
+
currency: "CNY",
|
|
336
|
+
input: .8,
|
|
337
|
+
cacheHit: .23,
|
|
338
|
+
output: 2.8
|
|
339
|
+
},
|
|
340
|
+
promo: {
|
|
341
|
+
factor: .5,
|
|
342
|
+
endsAtMs: Date.UTC(2026, 8, 8, 16, 0, 0),
|
|
343
|
+
note: "限时 5 折"
|
|
344
|
+
}
|
|
345
|
+
},
|
|
315
346
|
{
|
|
316
347
|
key: "glm-4.6",
|
|
317
348
|
name: "GLM-4.6",
|
|
@@ -392,10 +423,66 @@ const MODEL_CATALOG = [
|
|
|
392
423
|
colorVar: "dsw-static-blue-600",
|
|
393
424
|
price: {
|
|
394
425
|
currency: "CNY",
|
|
395
|
-
input:
|
|
396
|
-
cacheHit: 1.
|
|
397
|
-
output:
|
|
398
|
-
}
|
|
426
|
+
input: 12,
|
|
427
|
+
cacheHit: 1.5,
|
|
428
|
+
output: 36
|
|
429
|
+
},
|
|
430
|
+
extraRows: [
|
|
431
|
+
{
|
|
432
|
+
label: "显式缓存创建",
|
|
433
|
+
input: 15
|
|
434
|
+
},
|
|
435
|
+
{
|
|
436
|
+
label: "显式缓存命中",
|
|
437
|
+
input: 1
|
|
438
|
+
},
|
|
439
|
+
{
|
|
440
|
+
label: "Batch File",
|
|
441
|
+
input: 6,
|
|
442
|
+
output: 18,
|
|
443
|
+
note: "长期半价"
|
|
444
|
+
},
|
|
445
|
+
{
|
|
446
|
+
label: "Batch Chat",
|
|
447
|
+
input: 12,
|
|
448
|
+
output: 36,
|
|
449
|
+
note: "与标准价一致"
|
|
450
|
+
}
|
|
451
|
+
]
|
|
452
|
+
},
|
|
453
|
+
{
|
|
454
|
+
key: "qwen-3.8-flash",
|
|
455
|
+
name: "Qwen3.8 Flash",
|
|
456
|
+
provider: "阿里通义",
|
|
457
|
+
colorVar: "dsw-static-blue-400",
|
|
458
|
+
price: {
|
|
459
|
+
currency: "CNY",
|
|
460
|
+
input: 1,
|
|
461
|
+
cacheHit: .1,
|
|
462
|
+
output: 3
|
|
463
|
+
},
|
|
464
|
+
extraRows: [
|
|
465
|
+
{
|
|
466
|
+
label: "显式缓存创建",
|
|
467
|
+
input: 1.25
|
|
468
|
+
},
|
|
469
|
+
{
|
|
470
|
+
label: "显式缓存命中",
|
|
471
|
+
input: .1
|
|
472
|
+
},
|
|
473
|
+
{
|
|
474
|
+
label: "Batch File",
|
|
475
|
+
input: .5,
|
|
476
|
+
output: 1.5,
|
|
477
|
+
note: "长期半价"
|
|
478
|
+
},
|
|
479
|
+
{
|
|
480
|
+
label: "Batch Chat",
|
|
481
|
+
input: 1,
|
|
482
|
+
output: 3,
|
|
483
|
+
note: "与标准价一致"
|
|
484
|
+
}
|
|
485
|
+
]
|
|
399
486
|
},
|
|
400
487
|
{
|
|
401
488
|
key: "qwen-max",
|
|
@@ -404,10 +491,36 @@ const MODEL_CATALOG = [
|
|
|
404
491
|
colorVar: "dsw-static-blue-300",
|
|
405
492
|
price: {
|
|
406
493
|
currency: "CNY",
|
|
407
|
-
input:
|
|
408
|
-
cacheHit: .
|
|
409
|
-
output:
|
|
410
|
-
}
|
|
494
|
+
input: 12,
|
|
495
|
+
cacheHit: 1.2,
|
|
496
|
+
output: 36
|
|
497
|
+
},
|
|
498
|
+
promo: {
|
|
499
|
+
factor: .5,
|
|
500
|
+
note: "限时 5 折"
|
|
501
|
+
},
|
|
502
|
+
extraRows: [
|
|
503
|
+
{
|
|
504
|
+
label: "显式缓存创建",
|
|
505
|
+
input: 15
|
|
506
|
+
},
|
|
507
|
+
{
|
|
508
|
+
label: "显式缓存命中",
|
|
509
|
+
input: 1.2
|
|
510
|
+
},
|
|
511
|
+
{
|
|
512
|
+
label: "Batch File",
|
|
513
|
+
input: 6,
|
|
514
|
+
output: 18,
|
|
515
|
+
note: "长期半价"
|
|
516
|
+
},
|
|
517
|
+
{
|
|
518
|
+
label: "Batch Chat",
|
|
519
|
+
input: 12,
|
|
520
|
+
output: 36,
|
|
521
|
+
note: "与标准价一致"
|
|
522
|
+
}
|
|
523
|
+
]
|
|
411
524
|
},
|
|
412
525
|
{
|
|
413
526
|
key: "qwen-plus",
|
|
@@ -419,7 +532,29 @@ const MODEL_CATALOG = [
|
|
|
419
532
|
input: .8,
|
|
420
533
|
cacheHit: .08,
|
|
421
534
|
output: 4.8
|
|
422
|
-
}
|
|
535
|
+
},
|
|
536
|
+
extraRows: [
|
|
537
|
+
{
|
|
538
|
+
label: "显式缓存创建",
|
|
539
|
+
input: 1
|
|
540
|
+
},
|
|
541
|
+
{
|
|
542
|
+
label: "显式缓存命中",
|
|
543
|
+
input: .08
|
|
544
|
+
},
|
|
545
|
+
{
|
|
546
|
+
label: "Batch File",
|
|
547
|
+
input: .4,
|
|
548
|
+
output: 2.4,
|
|
549
|
+
note: "长期半价"
|
|
550
|
+
},
|
|
551
|
+
{
|
|
552
|
+
label: "Batch Chat",
|
|
553
|
+
input: .8,
|
|
554
|
+
output: 4.8,
|
|
555
|
+
note: "与标准价一致"
|
|
556
|
+
}
|
|
557
|
+
]
|
|
423
558
|
},
|
|
424
559
|
{
|
|
425
560
|
key: "qwen-flash",
|
|
@@ -431,7 +566,14 @@ const MODEL_CATALOG = [
|
|
|
431
566
|
input: .2,
|
|
432
567
|
cacheHit: .02,
|
|
433
568
|
output: 2
|
|
434
|
-
}
|
|
569
|
+
},
|
|
570
|
+
extraRows: [{
|
|
571
|
+
label: "显式缓存创建",
|
|
572
|
+
input: .25
|
|
573
|
+
}, {
|
|
574
|
+
label: "显式缓存命中",
|
|
575
|
+
input: .02
|
|
576
|
+
}]
|
|
435
577
|
},
|
|
436
578
|
{
|
|
437
579
|
key: "doubao",
|
|
@@ -469,6 +611,42 @@ const MODEL_CATALOG = [
|
|
|
469
611
|
output: 8
|
|
470
612
|
}
|
|
471
613
|
},
|
|
614
|
+
{
|
|
615
|
+
key: "doubao-seed-evolving",
|
|
616
|
+
name: "Doubao-Seed-Evolving",
|
|
617
|
+
provider: "字节豆包",
|
|
618
|
+
colorVar: "dsw-static-red-500",
|
|
619
|
+
price: {
|
|
620
|
+
currency: "CNY",
|
|
621
|
+
input: 6,
|
|
622
|
+
cacheHit: 1.2,
|
|
623
|
+
output: 30
|
|
624
|
+
}
|
|
625
|
+
},
|
|
626
|
+
{
|
|
627
|
+
key: "doubao-seed-2.1-pro",
|
|
628
|
+
name: "Doubao Seed-2.1 Pro",
|
|
629
|
+
provider: "字节豆包",
|
|
630
|
+
colorVar: "dsw-static-red-400",
|
|
631
|
+
price: {
|
|
632
|
+
currency: "CNY",
|
|
633
|
+
input: 6,
|
|
634
|
+
cacheHit: 1.2,
|
|
635
|
+
output: 30
|
|
636
|
+
}
|
|
637
|
+
},
|
|
638
|
+
{
|
|
639
|
+
key: "doubao-seed-2.1-turbo",
|
|
640
|
+
name: "Doubao Seed-2.1 Turbo",
|
|
641
|
+
provider: "字节豆包",
|
|
642
|
+
colorVar: "dsw-static-red-300",
|
|
643
|
+
price: {
|
|
644
|
+
currency: "CNY",
|
|
645
|
+
input: 3,
|
|
646
|
+
cacheHit: .6,
|
|
647
|
+
output: 15
|
|
648
|
+
}
|
|
649
|
+
},
|
|
472
650
|
{
|
|
473
651
|
key: "kimi",
|
|
474
652
|
name: "Kimi K2.7 Code",
|
|
@@ -795,6 +973,343 @@ const MODEL_CATALOG = [
|
|
|
795
973
|
output: .3
|
|
796
974
|
}
|
|
797
975
|
},
|
|
976
|
+
{
|
|
977
|
+
key: "claude-opus-4-6",
|
|
978
|
+
name: "Claude Opus 4.6",
|
|
979
|
+
provider: "Anthropic",
|
|
980
|
+
colorVar: "dsw-static-red-500",
|
|
981
|
+
price: {
|
|
982
|
+
currency: "USD",
|
|
983
|
+
input: 5,
|
|
984
|
+
cacheHit: .5,
|
|
985
|
+
output: 25
|
|
986
|
+
}
|
|
987
|
+
},
|
|
988
|
+
{
|
|
989
|
+
key: "claude-sonnet-4-6",
|
|
990
|
+
name: "Claude Sonnet 4.6",
|
|
991
|
+
provider: "Anthropic",
|
|
992
|
+
colorVar: "dsw-static-red-400",
|
|
993
|
+
price: {
|
|
994
|
+
currency: "USD",
|
|
995
|
+
input: 3,
|
|
996
|
+
cacheHit: .3,
|
|
997
|
+
output: 15
|
|
998
|
+
}
|
|
999
|
+
},
|
|
1000
|
+
{
|
|
1001
|
+
key: "claude-haiku-4-5",
|
|
1002
|
+
name: "Claude Haiku 4.5",
|
|
1003
|
+
provider: "Anthropic",
|
|
1004
|
+
colorVar: "dsw-static-red-300",
|
|
1005
|
+
price: {
|
|
1006
|
+
currency: "USD",
|
|
1007
|
+
input: 1,
|
|
1008
|
+
cacheHit: .1,
|
|
1009
|
+
output: 5
|
|
1010
|
+
}
|
|
1011
|
+
},
|
|
1012
|
+
{
|
|
1013
|
+
key: "claude-opus-5",
|
|
1014
|
+
name: "Claude Opus 5",
|
|
1015
|
+
provider: "Anthropic",
|
|
1016
|
+
colorVar: "dsw-static-red-500",
|
|
1017
|
+
price: {
|
|
1018
|
+
currency: "USD",
|
|
1019
|
+
input: 5,
|
|
1020
|
+
cacheHit: .5,
|
|
1021
|
+
output: 25
|
|
1022
|
+
}
|
|
1023
|
+
},
|
|
1024
|
+
{
|
|
1025
|
+
key: "claude-sonnet-5",
|
|
1026
|
+
name: "Claude Sonnet 5",
|
|
1027
|
+
provider: "Anthropic",
|
|
1028
|
+
colorVar: "dsw-static-red-400",
|
|
1029
|
+
price: {
|
|
1030
|
+
currency: "USD",
|
|
1031
|
+
input: 2,
|
|
1032
|
+
cacheHit: .2,
|
|
1033
|
+
output: 10
|
|
1034
|
+
}
|
|
1035
|
+
},
|
|
1036
|
+
{
|
|
1037
|
+
key: "mistral-large-2512",
|
|
1038
|
+
name: "Mistral Large 3",
|
|
1039
|
+
provider: "Mistral AI",
|
|
1040
|
+
colorVar: "dsw-static-violet-500",
|
|
1041
|
+
price: {
|
|
1042
|
+
currency: "USD",
|
|
1043
|
+
input: .5,
|
|
1044
|
+
cacheHit: .05,
|
|
1045
|
+
output: 1.5
|
|
1046
|
+
}
|
|
1047
|
+
},
|
|
1048
|
+
{
|
|
1049
|
+
key: "mistral-small-2603",
|
|
1050
|
+
name: "Mistral Small 4",
|
|
1051
|
+
provider: "Mistral AI",
|
|
1052
|
+
colorVar: "dsw-static-violet-400",
|
|
1053
|
+
price: {
|
|
1054
|
+
currency: "USD",
|
|
1055
|
+
input: .15,
|
|
1056
|
+
cacheHit: .015,
|
|
1057
|
+
output: .6
|
|
1058
|
+
}
|
|
1059
|
+
},
|
|
1060
|
+
{
|
|
1061
|
+
key: "ministral-8b-latest",
|
|
1062
|
+
name: "Ministral 8B",
|
|
1063
|
+
provider: "Mistral AI",
|
|
1064
|
+
colorVar: "dsw-static-violet-300",
|
|
1065
|
+
price: {
|
|
1066
|
+
currency: "USD",
|
|
1067
|
+
input: .1,
|
|
1068
|
+
cacheHit: .01,
|
|
1069
|
+
output: .1
|
|
1070
|
+
}
|
|
1071
|
+
},
|
|
1072
|
+
{
|
|
1073
|
+
key: "command-a-03-2025",
|
|
1074
|
+
name: "Command A",
|
|
1075
|
+
provider: "Cohere",
|
|
1076
|
+
colorVar: "dsw-static-cyan-500",
|
|
1077
|
+
price: {
|
|
1078
|
+
currency: "USD",
|
|
1079
|
+
input: 2.5,
|
|
1080
|
+
cacheHit: .25,
|
|
1081
|
+
output: 10
|
|
1082
|
+
}
|
|
1083
|
+
},
|
|
1084
|
+
{
|
|
1085
|
+
key: "command-r-08-2024",
|
|
1086
|
+
name: "Command R",
|
|
1087
|
+
provider: "Cohere",
|
|
1088
|
+
colorVar: "dsw-static-cyan-400",
|
|
1089
|
+
price: {
|
|
1090
|
+
currency: "USD",
|
|
1091
|
+
input: .15,
|
|
1092
|
+
cacheHit: .015,
|
|
1093
|
+
output: .6
|
|
1094
|
+
}
|
|
1095
|
+
},
|
|
1096
|
+
{
|
|
1097
|
+
key: "longcat-2.0",
|
|
1098
|
+
name: "LongCat 2.0",
|
|
1099
|
+
provider: "美团",
|
|
1100
|
+
colorVar: "dsw-static-amber-500",
|
|
1101
|
+
price: {
|
|
1102
|
+
currency: "CNY",
|
|
1103
|
+
input: 4,
|
|
1104
|
+
cacheHit: .8,
|
|
1105
|
+
output: 16
|
|
1106
|
+
},
|
|
1107
|
+
estimated: true
|
|
1108
|
+
},
|
|
1109
|
+
{
|
|
1110
|
+
key: "minicpm-v-4.5",
|
|
1111
|
+
name: "MiniCPM-V 4.5",
|
|
1112
|
+
provider: "面壁智能",
|
|
1113
|
+
colorVar: "dsw-static-green-500",
|
|
1114
|
+
price: {
|
|
1115
|
+
currency: "CNY",
|
|
1116
|
+
input: 1,
|
|
1117
|
+
cacheHit: .2,
|
|
1118
|
+
output: 4
|
|
1119
|
+
},
|
|
1120
|
+
estimated: true
|
|
1121
|
+
},
|
|
1122
|
+
{
|
|
1123
|
+
key: "ernie-4.5",
|
|
1124
|
+
name: "ERNIE-4.5 300B",
|
|
1125
|
+
provider: "百度文心",
|
|
1126
|
+
colorVar: "dsw-static-blue-300",
|
|
1127
|
+
price: {
|
|
1128
|
+
currency: "CNY",
|
|
1129
|
+
input: 2,
|
|
1130
|
+
cacheHit: .4,
|
|
1131
|
+
output: 8
|
|
1132
|
+
},
|
|
1133
|
+
estimated: true
|
|
1134
|
+
},
|
|
1135
|
+
{
|
|
1136
|
+
key: "dots-3-note-preview",
|
|
1137
|
+
name: "Dots3-Note Preview",
|
|
1138
|
+
provider: "小红书",
|
|
1139
|
+
colorVar: "dsw-static-red-500",
|
|
1140
|
+
price: {
|
|
1141
|
+
currency: "CNY",
|
|
1142
|
+
input: 2,
|
|
1143
|
+
cacheHit: .4,
|
|
1144
|
+
output: 8
|
|
1145
|
+
},
|
|
1146
|
+
estimated: true
|
|
1147
|
+
},
|
|
1148
|
+
{
|
|
1149
|
+
key: "qwen3.6-max",
|
|
1150
|
+
name: "Qwen3.6 Max",
|
|
1151
|
+
provider: "阿里通义",
|
|
1152
|
+
colorVar: "dsw-static-orange-500",
|
|
1153
|
+
price: {
|
|
1154
|
+
currency: "CNY",
|
|
1155
|
+
input: 9,
|
|
1156
|
+
cacheHit: .9,
|
|
1157
|
+
output: 54
|
|
1158
|
+
},
|
|
1159
|
+
extraRows: [{
|
|
1160
|
+
label: "显式缓存创建",
|
|
1161
|
+
input: 11.25
|
|
1162
|
+
}, {
|
|
1163
|
+
label: "显式缓存命中",
|
|
1164
|
+
input: .9
|
|
1165
|
+
}]
|
|
1166
|
+
},
|
|
1167
|
+
{
|
|
1168
|
+
key: "qwen3-coder-plus",
|
|
1169
|
+
name: "Qwen3-Coder Plus",
|
|
1170
|
+
provider: "阿里通义",
|
|
1171
|
+
colorVar: "dsw-static-orange-400",
|
|
1172
|
+
price: {
|
|
1173
|
+
currency: "CNY",
|
|
1174
|
+
input: 4,
|
|
1175
|
+
cacheHit: .8,
|
|
1176
|
+
output: 16
|
|
1177
|
+
},
|
|
1178
|
+
extraRows: [{
|
|
1179
|
+
label: "显式缓存创建",
|
|
1180
|
+
input: 5
|
|
1181
|
+
}, {
|
|
1182
|
+
label: "显式缓存命中",
|
|
1183
|
+
input: .4
|
|
1184
|
+
}]
|
|
1185
|
+
},
|
|
1186
|
+
{
|
|
1187
|
+
key: "qwen3-coder",
|
|
1188
|
+
name: "Qwen3-Coder 480B",
|
|
1189
|
+
provider: "阿里通义",
|
|
1190
|
+
colorVar: "dsw-static-orange-300",
|
|
1191
|
+
price: {
|
|
1192
|
+
currency: "CNY",
|
|
1193
|
+
input: 4,
|
|
1194
|
+
cacheHit: .8,
|
|
1195
|
+
output: 16
|
|
1196
|
+
},
|
|
1197
|
+
estimated: true
|
|
1198
|
+
},
|
|
1199
|
+
{
|
|
1200
|
+
key: "glm-4.5-x",
|
|
1201
|
+
name: "GLM-4.5-X",
|
|
1202
|
+
provider: "智谱 AI",
|
|
1203
|
+
colorVar: "dsw-static-blue-400",
|
|
1204
|
+
price: {
|
|
1205
|
+
currency: "CNY",
|
|
1206
|
+
input: 4,
|
|
1207
|
+
cacheHit: 1,
|
|
1208
|
+
output: 16
|
|
1209
|
+
},
|
|
1210
|
+
estimated: true
|
|
1211
|
+
},
|
|
1212
|
+
{
|
|
1213
|
+
key: "glm-5.2-fast",
|
|
1214
|
+
name: "GLM-5.2 Fast",
|
|
1215
|
+
provider: "智谱 AI",
|
|
1216
|
+
colorVar: "dsw-static-blue-300",
|
|
1217
|
+
price: {
|
|
1218
|
+
currency: "CNY",
|
|
1219
|
+
input: 6,
|
|
1220
|
+
cacheHit: 1.2,
|
|
1221
|
+
output: 24
|
|
1222
|
+
},
|
|
1223
|
+
estimated: true
|
|
1224
|
+
},
|
|
1225
|
+
{
|
|
1226
|
+
key: "kimi-k3-fast",
|
|
1227
|
+
name: "Kimi K3 Fast",
|
|
1228
|
+
provider: "月之暗面",
|
|
1229
|
+
colorVar: "dsw-static-cyan-400",
|
|
1230
|
+
price: {
|
|
1231
|
+
currency: "CNY",
|
|
1232
|
+
input: 20,
|
|
1233
|
+
cacheHit: 2,
|
|
1234
|
+
output: 100
|
|
1235
|
+
},
|
|
1236
|
+
estimated: true
|
|
1237
|
+
},
|
|
1238
|
+
{
|
|
1239
|
+
key: "kimi-k2.7-code-fast",
|
|
1240
|
+
name: "Kimi K2.7 Code Fast",
|
|
1241
|
+
provider: "月之暗面",
|
|
1242
|
+
colorVar: "dsw-static-cyan-400",
|
|
1243
|
+
price: {
|
|
1244
|
+
currency: "CNY",
|
|
1245
|
+
input: 6.5,
|
|
1246
|
+
cacheHit: 1.3,
|
|
1247
|
+
output: 27
|
|
1248
|
+
},
|
|
1249
|
+
estimated: true
|
|
1250
|
+
},
|
|
1251
|
+
{
|
|
1252
|
+
key: "kimi-k2.6-fast",
|
|
1253
|
+
name: "Kimi K2.6 Fast",
|
|
1254
|
+
provider: "月之暗面",
|
|
1255
|
+
colorVar: "dsw-static-cyan-300",
|
|
1256
|
+
price: {
|
|
1257
|
+
currency: "CNY",
|
|
1258
|
+
input: 6.5,
|
|
1259
|
+
cacheHit: 1.1,
|
|
1260
|
+
output: 27
|
|
1261
|
+
},
|
|
1262
|
+
estimated: true
|
|
1263
|
+
},
|
|
1264
|
+
{
|
|
1265
|
+
key: "kimi-k2.6-turbo",
|
|
1266
|
+
name: "Kimi K2.6 Turbo",
|
|
1267
|
+
provider: "月之暗面",
|
|
1268
|
+
colorVar: "dsw-static-cyan-300",
|
|
1269
|
+
price: {
|
|
1270
|
+
currency: "CNY",
|
|
1271
|
+
input: 6.5,
|
|
1272
|
+
cacheHit: 1.1,
|
|
1273
|
+
output: 27
|
|
1274
|
+
},
|
|
1275
|
+
estimated: true
|
|
1276
|
+
},
|
|
1277
|
+
{
|
|
1278
|
+
key: "kimi-k2-thinking-turbo",
|
|
1279
|
+
name: "Kimi K2 Thinking Turbo",
|
|
1280
|
+
provider: "月之暗面",
|
|
1281
|
+
colorVar: "dsw-static-cyan-300",
|
|
1282
|
+
price: {
|
|
1283
|
+
currency: "CNY",
|
|
1284
|
+
input: 8,
|
|
1285
|
+
cacheHit: 1,
|
|
1286
|
+
output: 58
|
|
1287
|
+
}
|
|
1288
|
+
},
|
|
1289
|
+
{
|
|
1290
|
+
key: "doubao-seed-2.0-code",
|
|
1291
|
+
name: "Doubao Seed-2.0 Code",
|
|
1292
|
+
provider: "字节豆包",
|
|
1293
|
+
colorVar: "dsw-static-red-500",
|
|
1294
|
+
price: {
|
|
1295
|
+
currency: "CNY",
|
|
1296
|
+
input: 3.2,
|
|
1297
|
+
cacheHit: .64,
|
|
1298
|
+
output: 16
|
|
1299
|
+
}
|
|
1300
|
+
},
|
|
1301
|
+
{
|
|
1302
|
+
key: "doubao-seed-2.0-lite",
|
|
1303
|
+
name: "Doubao Seed-2.0 Lite",
|
|
1304
|
+
provider: "字节豆包",
|
|
1305
|
+
colorVar: "dsw-static-red-300",
|
|
1306
|
+
price: {
|
|
1307
|
+
currency: "CNY",
|
|
1308
|
+
input: .6,
|
|
1309
|
+
cacheHit: .12,
|
|
1310
|
+
output: 3.6
|
|
1311
|
+
}
|
|
1312
|
+
},
|
|
798
1313
|
{
|
|
799
1314
|
key: "other",
|
|
800
1315
|
name: "其他模型",
|
|
@@ -802,10 +1317,10 @@ const MODEL_CATALOG = [
|
|
|
802
1317
|
colorVar: "dsw-static-neutral-bluish-500",
|
|
803
1318
|
price: {
|
|
804
1319
|
currency: "CNY",
|
|
805
|
-
input:
|
|
806
|
-
cacheHit:
|
|
807
|
-
cacheMiss:
|
|
808
|
-
output:
|
|
1320
|
+
input: 0,
|
|
1321
|
+
cacheHit: 0,
|
|
1322
|
+
cacheMiss: 0,
|
|
1323
|
+
output: 0
|
|
809
1324
|
}
|
|
810
1325
|
}
|
|
811
1326
|
];
|
|
@@ -825,10 +1340,66 @@ const MODEL_KEY_ALIASES = {
|
|
|
825
1340
|
"glm-4.7": "glm-4.7",
|
|
826
1341
|
"glm-5-turbo": "glm-5-turbo",
|
|
827
1342
|
"glm-5.1": "glm-5.1",
|
|
1343
|
+
"glm-5.3-flash": "glm-5.3-flash",
|
|
828
1344
|
"glm-5v-turbo": "glm-5v-turbo",
|
|
829
1345
|
"glm-5v.1": "glm-5v-turbo",
|
|
1346
|
+
"claude-opus-4-6": "claude-opus-4-6",
|
|
1347
|
+
"claude-opus-4.6": "claude-opus-4-6",
|
|
1348
|
+
"claude-sonnet-4-6": "claude-sonnet-4-6",
|
|
1349
|
+
"claude-sonnet-4.6": "claude-sonnet-4-6",
|
|
1350
|
+
"claude-haiku-4-5": "claude-haiku-4-5",
|
|
1351
|
+
"claude-haiku-4.5": "claude-haiku-4-5",
|
|
1352
|
+
"claude-opus-5": "claude-opus-5",
|
|
1353
|
+
"claude-sonnet-5": "claude-sonnet-5",
|
|
1354
|
+
"mistral-large-2512": "mistral-large-2512",
|
|
1355
|
+
"mistral-large-3": "mistral-large-2512",
|
|
1356
|
+
"mistral-small-2603": "mistral-small-2603",
|
|
1357
|
+
"mistral-small-4": "mistral-small-2603",
|
|
1358
|
+
"ministral-8b-latest": "ministral-8b-latest",
|
|
1359
|
+
"ministral-8b": "ministral-8b-latest",
|
|
1360
|
+
"command-a-03-2025": "command-a-03-2025",
|
|
1361
|
+
"command-a": "command-a-03-2025",
|
|
1362
|
+
"command-r-08-2024": "command-r-08-2024",
|
|
1363
|
+
"command-r": "command-r-08-2024",
|
|
1364
|
+
"longcat-2.0": "longcat-2.0",
|
|
1365
|
+
"longcat-2": "longcat-2.0",
|
|
1366
|
+
"minicpm-v-4.5": "minicpm-v-4.5",
|
|
1367
|
+
"minicpm-v-4.5-thinking": "minicpm-v-4.5",
|
|
1368
|
+
"ernie-4.5": "ernie-4.5",
|
|
1369
|
+
"ernie-4.5-300b": "ernie-4.5",
|
|
1370
|
+
"dots-3-note-preview": "dots-3-note-preview",
|
|
1371
|
+
"dots-3-note": "dots-3-note-preview",
|
|
1372
|
+
"dots3-note-preview": "dots-3-note-preview",
|
|
1373
|
+
"rednote-dots3": "dots-3-note-preview",
|
|
1374
|
+
"doubao-seed-evolving": "doubao-seed-evolving",
|
|
1375
|
+
"doubao-seed-evolve": "doubao-seed-evolving",
|
|
1376
|
+
"doubao-seed-2.1-pro": "doubao-seed-2.1-pro",
|
|
1377
|
+
"doubao-seed-2.1-pro-290000": "doubao-seed-2.1-pro",
|
|
1378
|
+
"doubao-seed-2.1-turbo": "doubao-seed-2.1-turbo",
|
|
1379
|
+
"doubao-seed-2-1-turbo": "doubao-seed-2.1-turbo",
|
|
830
1380
|
"qwen3.8-max": "qwen-3.8-max",
|
|
1381
|
+
"qwen3.8-flash": "qwen-3.8-flash",
|
|
831
1382
|
"qwen3.7-max": "qwen-max",
|
|
1383
|
+
"qwen3.6-max": "qwen3.6-max",
|
|
1384
|
+
"qwen3.6-max-preview": "qwen3.6-max",
|
|
1385
|
+
"qwen3-coder-plus": "qwen3-coder-plus",
|
|
1386
|
+
"qwen3-coder": "qwen3-coder",
|
|
1387
|
+
"qwen3-coder-480b": "qwen3-coder",
|
|
1388
|
+
"glm-4.5-x": "glm-4.5-x",
|
|
1389
|
+
"glm-4.5x": "glm-4.5-x",
|
|
1390
|
+
"glm-5.2-fast": "glm-5.2-fast",
|
|
1391
|
+
"glm-5.2f": "glm-5.2-fast",
|
|
1392
|
+
"kimi-k3-fast": "kimi-k3-fast",
|
|
1393
|
+
"kimi-k3f": "kimi-k3-fast",
|
|
1394
|
+
"kimi-k2.7-code-fast": "kimi-k2.7-code-fast",
|
|
1395
|
+
"kimi-k2.7-code-f": "kimi-k2.7-code-fast",
|
|
1396
|
+
"kimi-k2.6-fast": "kimi-k2.6-fast",
|
|
1397
|
+
"kimi-k2.6-turbo": "kimi-k2.6-turbo",
|
|
1398
|
+
"kimi-k2-thinking-turbo": "kimi-k2-thinking-turbo",
|
|
1399
|
+
"doubao-seed-2.0-code": "doubao-seed-2.0-code",
|
|
1400
|
+
"doubao-seed-2-0-code": "doubao-seed-2.0-code",
|
|
1401
|
+
"doubao-seed-2.0-lite": "doubao-seed-2.0-lite",
|
|
1402
|
+
"doubao-seed-2-0-lite": "doubao-seed-2.0-lite",
|
|
832
1403
|
"qwen-max": "qwen-max",
|
|
833
1404
|
"hunyuan-t1": "hunyuan-t1",
|
|
834
1405
|
"step-3.7-flash": "step",
|
|
@@ -952,6 +1523,42 @@ function isPriced(key) {
|
|
|
952
1523
|
return FALLBACK_RATES.some((rate) => rate.key.toLowerCase() === resolved.toLowerCase());
|
|
953
1524
|
}
|
|
954
1525
|
/**
|
|
1526
|
+
* 促销在 nowMs 是否生效:factor 必须落在 (0,1) 区间,截止时刻及之后视为过期;
|
|
1527
|
+
* endsAtMs 缺省表示长期活动,在 factor 合法期间持续生效。
|
|
1528
|
+
* 导出供测试:纯函数。
|
|
1529
|
+
* @param promo - 待判定的促销窗口。
|
|
1530
|
+
* @param nowMs - 判定时刻(epoch ms)。
|
|
1531
|
+
*/
|
|
1532
|
+
function isPromoActive(promo, nowMs) {
|
|
1533
|
+
const expired = promo.endsAtMs !== void 0 && nowMs >= promo.endsAtMs;
|
|
1534
|
+
return Number.isFinite(nowMs) && !expired && promo.factor > 0 && promo.factor < 1;
|
|
1535
|
+
}
|
|
1536
|
+
/**
|
|
1537
|
+
* 把限时促销折入条目单价:生效期内返回 price 主档与 offPeak 全部乘 factor 的
|
|
1538
|
+
* 副本,其余字段原样保留;不在促销期(过期/未开始/factor 非法)原样返回。
|
|
1539
|
+
* 幂等由调用方保证——计价与费率表显示各自只折一次,勿对已折价副本重复应用。
|
|
1540
|
+
* @param entry - 目录条目(price 保持刊例价口径)。
|
|
1541
|
+
* @param nowMs - 判定时刻(epoch ms)。
|
|
1542
|
+
*/
|
|
1543
|
+
function applyPromo(entry, nowMs) {
|
|
1544
|
+
const { promo } = entry;
|
|
1545
|
+
if (promo === void 0 || !isPromoActive(promo, nowMs)) return entry;
|
|
1546
|
+
const scaled = (band) => ({
|
|
1547
|
+
input: band.input * promo.factor,
|
|
1548
|
+
cacheHit: band.cacheHit * promo.factor,
|
|
1549
|
+
...band.cacheMiss !== void 0 ? { cacheMiss: band.cacheMiss * promo.factor } : {},
|
|
1550
|
+
output: band.output * promo.factor
|
|
1551
|
+
});
|
|
1552
|
+
return {
|
|
1553
|
+
...entry,
|
|
1554
|
+
price: {
|
|
1555
|
+
...scaled(entry.price),
|
|
1556
|
+
currency: entry.price.currency,
|
|
1557
|
+
...entry.price.offPeak !== void 0 ? { offPeak: scaled(entry.price.offPeak) } : {}
|
|
1558
|
+
}
|
|
1559
|
+
};
|
|
1560
|
+
}
|
|
1561
|
+
/**
|
|
955
1562
|
* Price one band's token usage in CNY. The stats `input` field is the TOTAL
|
|
956
1563
|
* prompt tokens (cacheHit + cacheMiss), so billing splits it: the cache-hit
|
|
957
1564
|
* share prices at the hit rate and the remaining share at the miss rate.
|
|
@@ -980,15 +1587,17 @@ function priceBandCost(band, buckets, currency) {
|
|
|
980
1587
|
* @param peakShare - share of traffic in the peak band (0..1); defaults to {@link DEFAULT_PEAK_SHARE}.
|
|
981
1588
|
* @returns the estimated cost in CNY.
|
|
982
1589
|
*/
|
|
983
|
-
function computeCost(entry, buckets, peakShare = DEFAULT_PEAK_SHARE) {
|
|
984
|
-
const
|
|
985
|
-
const
|
|
1590
|
+
function computeCost(entry, buckets, peakShare = DEFAULT_PEAK_SHARE, nowMs = Date.now()) {
|
|
1591
|
+
const priced = applyPromo(entry, nowMs);
|
|
1592
|
+
const peak = priceBandCost(priced.price, buckets, priced.price.currency);
|
|
1593
|
+
const off = priced.price.offPeak === void 0 ? peak : priceBandCost(priced.price.offPeak, buckets, priced.price.currency);
|
|
986
1594
|
return peak * peakShare + off * (1 - peakShare);
|
|
987
1595
|
}
|
|
988
1596
|
/**
|
|
989
1597
|
* 按调用时刻精确判定高峰/空闲档并计价(P0-1:替代固定比例混合)。时刻未知
|
|
990
1598
|
* (null/NaN,理论不发生在真实事件流)时回退 {@link DEFAULT_PEAK_SHARE} 混合,
|
|
991
|
-
* 保持旧语义不低估。平档模型(无 offPeak
|
|
1599
|
+
* 保持旧语义不低估。平档模型(无 offPeak)两个时段同价。限时促销与峰谷档
|
|
1600
|
+
* 同口径:按事件时刻判定该笔流量当时享受的单价。
|
|
992
1601
|
* @param entry - the catalog entry whose prices apply.
|
|
993
1602
|
* @param buckets - token usage counts.
|
|
994
1603
|
* @param timeMs - the call's wall-clock time (epoch ms); null falls back to the peak-share mix.
|
|
@@ -996,9 +1605,10 @@ function computeCost(entry, buckets, peakShare = DEFAULT_PEAK_SHARE) {
|
|
|
996
1605
|
* @returns the estimated cost in CNY(USD 计价模型已按当前汇率折算)。
|
|
997
1606
|
*/
|
|
998
1607
|
function computeCostAt(entry, buckets, timeMs, peakShare = DEFAULT_PEAK_SHARE) {
|
|
999
|
-
if (entry.price.offPeak === void 0) return priceBandCost(entry.price, buckets, entry.price.currency);
|
|
1000
1608
|
if (timeMs === null || timeMs === void 0 || !Number.isFinite(timeMs)) return computeCost(entry, buckets, peakShare);
|
|
1001
|
-
|
|
1609
|
+
const priced = applyPromo(entry, timeMs);
|
|
1610
|
+
if (priced.price.offPeak === void 0) return priceBandCost(priced.price, buckets, priced.price.currency);
|
|
1611
|
+
return priceBandCost(tierAt(timeMs) === "peak" ? priced.price : priced.price.offPeak, buckets, priced.price.currency);
|
|
1002
1612
|
}
|
|
1003
1613
|
/**
|
|
1004
1614
|
* Format an amount with adaptive precision and the given currency symbol.
|
|
@@ -3980,6 +4590,7 @@ const UsageBillingSettingsSchema = z.object({ [ENABLE_USAGE_STATS_TOOL_FIELD]: z
|
|
|
3980
4590
|
const PRICING_REFRESH_INTERVAL_MS = 360 * 60 * 1e3;
|
|
3981
4591
|
/** 订阅套餐额度缓存时长(毫秒):上游配额 API 低频变化,5 分钟足够。 */
|
|
3982
4592
|
const SUBSCRIPTION_CACHE_MS = 300 * 1e3;
|
|
4593
|
+
const BALANCE_CACHE_MS = 300 * 1e3;
|
|
3983
4594
|
/** DeepSeek 余额查询的默认凭据引用(与 llm-deepseek 的默认引用一致)。 */
|
|
3984
4595
|
const DEFAULT_BALANCE_API_KEY_ENV = "DEEPSEEK_API_KEY";
|
|
3985
4596
|
/**
|
|
@@ -4463,6 +5074,10 @@ function apply(ctx, config = {}) {
|
|
|
4463
5074
|
res.end(JSON.stringify(live));
|
|
4464
5075
|
}
|
|
4465
5076
|
}), "usage-billing: pricing route");
|
|
5077
|
+
let balanceCache = {
|
|
5078
|
+
at: 0,
|
|
5079
|
+
doc: { balances: [] }
|
|
5080
|
+
};
|
|
4466
5081
|
ctx.effect(() => ctx.webServer.register({
|
|
4467
5082
|
kind: "exact",
|
|
4468
5083
|
path: "/api/billing/balance",
|
|
@@ -4476,39 +5091,53 @@ function apply(ctx, config = {}) {
|
|
|
4476
5091
|
...providers["deepseek"],
|
|
4477
5092
|
apiKeyEnv: config.balanceApiKeyEnv ?? DEFAULT_BALANCE_API_KEY_ENV
|
|
4478
5093
|
};
|
|
4479
|
-
|
|
4480
|
-
|
|
4481
|
-
|
|
4482
|
-
for (const row of [
|
|
4483
|
-
...balances,
|
|
4484
|
-
...custom,
|
|
4485
|
-
...declared
|
|
4486
|
-
]) if (row.error === "unauthorized") warnAuthOnce("balance", row.provider, row.displayName);
|
|
4487
|
-
const official = balances.find((row) => row.provider === "deepseek");
|
|
4488
|
-
let reconcile;
|
|
4489
|
-
if (official !== void 0 && official.totalBalance !== void 0) {
|
|
4490
|
-
const now = Date.now();
|
|
4491
|
-
const today = dayStamp(now);
|
|
4492
|
-
let todayOfficialCost = 0;
|
|
4493
|
-
try {
|
|
4494
|
-
todayOfficialCost = (await aggregator.aggregate()).byDay[today]?.officialCost ?? 0;
|
|
4495
|
-
} catch {}
|
|
4496
|
-
const result = reconcileBalanceDelta(reconcileRef, official, todayOfficialCost, today, now);
|
|
4497
|
-
reconcileRef = result.ref;
|
|
4498
|
-
if (result.event !== null && result.event.kind !== "flat") reconcile = {
|
|
4499
|
-
...result.event,
|
|
4500
|
-
provider: official.displayName
|
|
4501
|
-
};
|
|
4502
|
-
if (result.ref !== null) persistReconcileRef();
|
|
5094
|
+
if (Date.now() - balanceCache.at < BALANCE_CACHE_MS) {
|
|
5095
|
+
res.end(JSON.stringify(balanceCache.doc));
|
|
5096
|
+
return;
|
|
4503
5097
|
}
|
|
4504
|
-
|
|
4505
|
-
balances
|
|
5098
|
+
try {
|
|
5099
|
+
const balances = await queryBalances(ctx, providers);
|
|
5100
|
+
const custom = await queryCustomBalances(ctx, config.customBalances ?? []);
|
|
5101
|
+
const declared = await queryDeclaredEndpoints(ctx, piProviders, config.declaredEndpoints ?? []);
|
|
5102
|
+
for (const row of [
|
|
4506
5103
|
...balances,
|
|
4507
5104
|
...custom,
|
|
4508
5105
|
...declared
|
|
4509
|
-
],
|
|
4510
|
-
|
|
4511
|
-
|
|
5106
|
+
]) if (row.error === "unauthorized") warnAuthOnce("balance", row.provider, row.displayName);
|
|
5107
|
+
const official = balances.find((row) => row.provider === "deepseek");
|
|
5108
|
+
let reconcile;
|
|
5109
|
+
if (official !== void 0 && official.totalBalance !== void 0) {
|
|
5110
|
+
const now = Date.now();
|
|
5111
|
+
const today = dayStamp(now);
|
|
5112
|
+
let todayOfficialCost = 0;
|
|
5113
|
+
try {
|
|
5114
|
+
todayOfficialCost = (await aggregator.aggregate()).byDay[today]?.officialCost ?? 0;
|
|
5115
|
+
} catch {}
|
|
5116
|
+
const result = reconcileBalanceDelta(reconcileRef, official, todayOfficialCost, today, now);
|
|
5117
|
+
reconcileRef = result.ref;
|
|
5118
|
+
if (result.event !== null && result.event.kind !== "flat") reconcile = {
|
|
5119
|
+
...result.event,
|
|
5120
|
+
provider: official.displayName
|
|
5121
|
+
};
|
|
5122
|
+
if (result.ref !== null) persistReconcileRef();
|
|
5123
|
+
}
|
|
5124
|
+
const doc = {
|
|
5125
|
+
balances: [
|
|
5126
|
+
...balances,
|
|
5127
|
+
...custom,
|
|
5128
|
+
...declared
|
|
5129
|
+
],
|
|
5130
|
+
...reconcile === void 0 ? {} : { reconcile }
|
|
5131
|
+
};
|
|
5132
|
+
balanceCache = {
|
|
5133
|
+
at: Date.now(),
|
|
5134
|
+
doc
|
|
5135
|
+
};
|
|
5136
|
+
res.end(JSON.stringify(doc));
|
|
5137
|
+
} catch (error) {
|
|
5138
|
+
console.warn("[usage-billing] refreshBalances failed; serving cached balances:", error);
|
|
5139
|
+
res.end(JSON.stringify(balanceCache.doc));
|
|
5140
|
+
}
|
|
4512
5141
|
}
|
|
4513
5142
|
}), "usage-billing: balance route");
|
|
4514
5143
|
ctx.effect(() => ctx.webServer.register({
|