pi-spark 0.26.0 → 0.27.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/docs/background-model-calls-and-openai-codex-sessions.md +2 -0
- package/package.json +1 -1
- package/src/data/holiday-cn-2026.json +205 -0
- package/src/features/credits/pricing.ts +1 -1
- package/src/features/credits/providers/deepseek.ts +36 -34
- package/src/features/credits/types.ts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.27.0](https://github.com/zlliang/pi-spark/compare/v0.26.0...v0.27.0) (2026-09-20)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* **credits:** honor Chinese holidays in DeepSeek off-peak pricing ([fc99f7d](https://github.com/zlliang/pi-spark/commit/fc99f7d152091e7c751745b46f35840676270538))
|
|
9
|
+
|
|
3
10
|
## [0.26.0](https://github.com/zlliang/pi-spark/compare/v0.25.0...v0.26.0) (2026-09-20)
|
|
4
11
|
|
|
5
12
|
|
|
@@ -74,4 +74,6 @@ Cache admission remains provider-controlled and noisy. In repeated GPT-5.6 Luna
|
|
|
74
74
|
|
|
75
75
|
Use the [`measuring-model-cache`](../.agents/skills/measuring-model-cache/SKILL.md) skill to repeat the comparison after changes to Pi, providers, session handling, title, recap, or other background model features.
|
|
76
76
|
|
|
77
|
+
---
|
|
78
|
+
|
|
77
79
|
**Update Sep 19, 2026:** Background calls now use Pi 0.86's `ctx.modelRegistry.streamSimple(...).result()` to support extension-registered providers and resolve authentication automatically. Independent Codex UUIDv7 sessions and cleanup in `finally` remain unchanged.
|
package/package.json
CHANGED
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://raw.githubusercontent.com/NateScarlet/holiday-cn/master/schema.json",
|
|
3
|
+
"$id": "https://raw.githubusercontent.com/NateScarlet/holiday-cn/master/2026.json",
|
|
4
|
+
"year": 2026,
|
|
5
|
+
"papers": [
|
|
6
|
+
"https://www.gov.cn/zhengce/zhengceku/202511/content_7047091.htm"
|
|
7
|
+
],
|
|
8
|
+
"days": [
|
|
9
|
+
{
|
|
10
|
+
"name": "元旦",
|
|
11
|
+
"date": "2026-01-01",
|
|
12
|
+
"isOffDay": true
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"name": "元旦",
|
|
16
|
+
"date": "2026-01-02",
|
|
17
|
+
"isOffDay": true
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"name": "元旦",
|
|
21
|
+
"date": "2026-01-03",
|
|
22
|
+
"isOffDay": true
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"name": "元旦",
|
|
26
|
+
"date": "2026-01-04",
|
|
27
|
+
"isOffDay": false
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"name": "春节",
|
|
31
|
+
"date": "2026-02-14",
|
|
32
|
+
"isOffDay": false
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"name": "春节",
|
|
36
|
+
"date": "2026-02-15",
|
|
37
|
+
"isOffDay": true
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"name": "春节",
|
|
41
|
+
"date": "2026-02-16",
|
|
42
|
+
"isOffDay": true
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"name": "春节",
|
|
46
|
+
"date": "2026-02-17",
|
|
47
|
+
"isOffDay": true
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
"name": "春节",
|
|
51
|
+
"date": "2026-02-18",
|
|
52
|
+
"isOffDay": true
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"name": "春节",
|
|
56
|
+
"date": "2026-02-19",
|
|
57
|
+
"isOffDay": true
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"name": "春节",
|
|
61
|
+
"date": "2026-02-20",
|
|
62
|
+
"isOffDay": true
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
"name": "春节",
|
|
66
|
+
"date": "2026-02-21",
|
|
67
|
+
"isOffDay": true
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
"name": "春节",
|
|
71
|
+
"date": "2026-02-22",
|
|
72
|
+
"isOffDay": true
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
"name": "春节",
|
|
76
|
+
"date": "2026-02-23",
|
|
77
|
+
"isOffDay": true
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
"name": "春节",
|
|
81
|
+
"date": "2026-02-28",
|
|
82
|
+
"isOffDay": false
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
"name": "清明节",
|
|
86
|
+
"date": "2026-04-04",
|
|
87
|
+
"isOffDay": true
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
"name": "清明节",
|
|
91
|
+
"date": "2026-04-05",
|
|
92
|
+
"isOffDay": true
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
"name": "清明节",
|
|
96
|
+
"date": "2026-04-06",
|
|
97
|
+
"isOffDay": true
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
"name": "劳动节",
|
|
101
|
+
"date": "2026-05-01",
|
|
102
|
+
"isOffDay": true
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
"name": "劳动节",
|
|
106
|
+
"date": "2026-05-02",
|
|
107
|
+
"isOffDay": true
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
"name": "劳动节",
|
|
111
|
+
"date": "2026-05-03",
|
|
112
|
+
"isOffDay": true
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
"name": "劳动节",
|
|
116
|
+
"date": "2026-05-04",
|
|
117
|
+
"isOffDay": true
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
"name": "劳动节",
|
|
121
|
+
"date": "2026-05-05",
|
|
122
|
+
"isOffDay": true
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
"name": "劳动节",
|
|
126
|
+
"date": "2026-05-09",
|
|
127
|
+
"isOffDay": false
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
"name": "端午节",
|
|
131
|
+
"date": "2026-06-19",
|
|
132
|
+
"isOffDay": true
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
"name": "端午节",
|
|
136
|
+
"date": "2026-06-20",
|
|
137
|
+
"isOffDay": true
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
"name": "端午节",
|
|
141
|
+
"date": "2026-06-21",
|
|
142
|
+
"isOffDay": true
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
"name": "国庆节",
|
|
146
|
+
"date": "2026-09-20",
|
|
147
|
+
"isOffDay": false
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
"name": "中秋节",
|
|
151
|
+
"date": "2026-09-25",
|
|
152
|
+
"isOffDay": true
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
"name": "中秋节",
|
|
156
|
+
"date": "2026-09-26",
|
|
157
|
+
"isOffDay": true
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
"name": "中秋节",
|
|
161
|
+
"date": "2026-09-27",
|
|
162
|
+
"isOffDay": true
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
"name": "国庆节",
|
|
166
|
+
"date": "2026-10-01",
|
|
167
|
+
"isOffDay": true
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
"name": "国庆节",
|
|
171
|
+
"date": "2026-10-02",
|
|
172
|
+
"isOffDay": true
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
"name": "国庆节",
|
|
176
|
+
"date": "2026-10-03",
|
|
177
|
+
"isOffDay": true
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
"name": "国庆节",
|
|
181
|
+
"date": "2026-10-04",
|
|
182
|
+
"isOffDay": true
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
"name": "国庆节",
|
|
186
|
+
"date": "2026-10-05",
|
|
187
|
+
"isOffDay": true
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
"name": "国庆节",
|
|
191
|
+
"date": "2026-10-06",
|
|
192
|
+
"isOffDay": true
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
"name": "国庆节",
|
|
196
|
+
"date": "2026-10-07",
|
|
197
|
+
"isOffDay": true
|
|
198
|
+
},
|
|
199
|
+
{
|
|
200
|
+
"name": "国庆节",
|
|
201
|
+
"date": "2026-10-10",
|
|
202
|
+
"isOffDay": false
|
|
203
|
+
}
|
|
204
|
+
]
|
|
205
|
+
}
|
|
@@ -23,7 +23,7 @@ export interface PricingRule {
|
|
|
23
23
|
|
|
24
24
|
/** Updates registry and active model prices without changing the provider's rule data. */
|
|
25
25
|
export function applyPricingRules(ctx: ExtensionContext, provider: CreditsProvider, timestamp: number): void {
|
|
26
|
-
(provider.pricingRules ?? []).forEach((rule) => {
|
|
26
|
+
(provider.pricingRules?.(timestamp) ?? []).forEach((rule) => {
|
|
27
27
|
const cost = resolveCost(rule, timestamp);
|
|
28
28
|
const model = ctx.modelRegistry.find(provider.id, rule.model);
|
|
29
29
|
|
|
@@ -4,8 +4,12 @@ import { http, withAuth } from "../../../utils/http";
|
|
|
4
4
|
import type { Cost } from "../pricing";
|
|
5
5
|
import type { Credits, CreditsProvider } from "../types";
|
|
6
6
|
|
|
7
|
+
import holidays2026 from "../../../data/holiday-cn-2026.json" with { type: "json" };
|
|
8
|
+
|
|
7
9
|
const PROVIDER = "deepseek";
|
|
8
10
|
const URL = "https://api.deepseek.com/user/balance";
|
|
11
|
+
const BEIJING_OFFSET_MS = 8 * 60 * 60 * 1000;
|
|
12
|
+
const HOLIDAYS = new Set(holidays2026.days.filter((day) => day.isOffDay).map((day) => day.date));
|
|
9
13
|
|
|
10
14
|
interface DeepSeekBalanceResponse {
|
|
11
15
|
balance_infos?: DeepSeekBalanceInfo[] | null;
|
|
@@ -16,46 +20,44 @@ interface DeepSeekBalanceInfo {
|
|
|
16
20
|
total_balance?: string | number;
|
|
17
21
|
}
|
|
18
22
|
|
|
23
|
+
/** Checks for an all-day off-peak date in Beijing, including weekends with makeup work. */
|
|
24
|
+
function isDeepSeekOffPeakDay(timestamp: number): boolean {
|
|
25
|
+
// Beijing uses UTC+8 without daylight saving time.
|
|
26
|
+
const date = new Date(timestamp + BEIJING_OFFSET_MS);
|
|
27
|
+
const day = date.getUTCDay();
|
|
28
|
+
|
|
29
|
+
// Years without bundled holiday data fall back to weekends only.
|
|
30
|
+
return day === 0 || day === 6 || HOLIDAYS.has(date.toISOString().slice(0, 10));
|
|
31
|
+
}
|
|
32
|
+
|
|
19
33
|
export const deepseekProvider: CreditsProvider = {
|
|
20
34
|
id: PROVIDER,
|
|
21
35
|
label: "DeepSeek",
|
|
22
36
|
link: "https://platform.deepseek.com/usage",
|
|
23
37
|
|
|
24
38
|
// See https://api-docs.deepseek.com/quick_start/pricing/.
|
|
25
|
-
pricingRules
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
{ start: "06:00", end: "10:00", days: [1, 2, 3, 4, 5], cost: { input: 0.3, output: 1.2, cacheRead: 0.006, cacheWrite: 0, label: "Peak" } },
|
|
48
|
-
],
|
|
49
|
-
},
|
|
50
|
-
{
|
|
51
|
-
model: "deepseek-v4-pro",
|
|
52
|
-
defaultCost: { input: 0.66, output: 1.98, cacheRead: 0.022, cacheWrite: 0, label: "Off-peak" },
|
|
53
|
-
windows: [
|
|
54
|
-
{ start: "01:00", end: "04:00", days: [1, 2, 3, 4, 5], cost: { input: 1.32, output: 3.96, cacheRead: 0.044, cacheWrite: 0, label: "Peak" } },
|
|
55
|
-
{ start: "06:00", end: "10:00", days: [1, 2, 3, 4, 5], cost: { input: 1.32, output: 3.96, cacheRead: 0.044, cacheWrite: 0, label: "Peak" } },
|
|
56
|
-
],
|
|
57
|
-
},
|
|
58
|
-
],
|
|
39
|
+
pricingRules(timestamp) {
|
|
40
|
+
const offPeakDay = isDeepSeekOffPeakDay(timestamp);
|
|
41
|
+
|
|
42
|
+
return [
|
|
43
|
+
{
|
|
44
|
+
model: "deepseek-flash",
|
|
45
|
+
defaultCost: { input: 0.15, output: 0.6, cacheRead: 0.003, cacheWrite: 0, label: "Off-peak" },
|
|
46
|
+
windows: offPeakDay ? [] : [
|
|
47
|
+
{ start: "01:00", end: "04:00", cost: { input: 0.3, output: 1.2, cacheRead: 0.006, cacheWrite: 0, label: "Peak" } },
|
|
48
|
+
{ start: "06:00", end: "10:00", cost: { input: 0.3, output: 1.2, cacheRead: 0.006, cacheWrite: 0, label: "Peak" } },
|
|
49
|
+
],
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
model: "deepseek-v4-pro",
|
|
53
|
+
defaultCost: { input: 0.66, output: 1.98, cacheRead: 0.022, cacheWrite: 0, label: "Off-peak" },
|
|
54
|
+
windows: offPeakDay ? [] : [
|
|
55
|
+
{ start: "01:00", end: "04:00", cost: { input: 1.32, output: 3.96, cacheRead: 0.044, cacheWrite: 0, label: "Peak" } },
|
|
56
|
+
{ start: "06:00", end: "10:00", cost: { input: 1.32, output: 3.96, cacheRead: 0.044, cacheWrite: 0, label: "Peak" } },
|
|
57
|
+
],
|
|
58
|
+
},
|
|
59
|
+
];
|
|
60
|
+
},
|
|
59
61
|
|
|
60
62
|
async fetch(apiKey, signal, cost?: Cost): Promise<Credits> {
|
|
61
63
|
const payload = await withAuth(http, apiKey).get(URL, { signal }).json<DeepSeekBalanceResponse>();
|
|
@@ -27,7 +27,7 @@ export interface CreditsProvider {
|
|
|
27
27
|
readonly id: CreditsProviderId;
|
|
28
28
|
readonly label: string;
|
|
29
29
|
readonly link?: string;
|
|
30
|
-
readonly pricingRules?: PricingRule[];
|
|
30
|
+
readonly pricingRules?: (timestamp: number) => PricingRule[];
|
|
31
31
|
fetch(apiKey: string, signal: AbortSignal, cost?: Cost): Promise<Credits>;
|
|
32
32
|
register?(pi: ExtensionAPI, ctx: ExtensionContext, refresh: RefreshCredits): void;
|
|
33
33
|
}
|