pi-harness-runtime 0.9.6 → 0.9.10
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 +41 -10
- package/README.md +42 -5
- package/footer-status.ts +108 -11
- package/harness/e2e/minimax-quota-scraper.ts +46 -4
- package/index.ts +272 -16
- package/mirror.ts +194 -18
- package/package.json +1 -1
- package/packages/a2a-adapter/package.json +1 -1
- package/packages/auth/package.json +1 -1
- package/packages/autonomous-refactor/package.json +1 -1
- package/packages/cache-strategy/package.json +1 -1
- package/packages/capability-registry/package.json +1 -1
- package/packages/checkpoint/package.json +1 -1
- package/packages/cli-plugin-sdk/package.json +1 -1
- package/packages/code-generation/package.json +1 -1
- package/packages/code-review/package.json +1 -1
- package/packages/codex-adapter/package.json +1 -1
- package/packages/context-compiler/package.json +1 -1
- package/packages/context-manager/package.json +1 -1
- package/packages/cookie-sanitizer/README.md +141 -0
- package/packages/cookie-sanitizer/dist/atomic-write.d.ts +38 -0
- package/packages/cookie-sanitizer/dist/atomic-write.d.ts.map +1 -0
- package/packages/cookie-sanitizer/dist/atomic-write.js +67 -0
- package/packages/cookie-sanitizer/dist/atomic-write.js.map +1 -0
- package/packages/cookie-sanitizer/dist/detect-format.d.ts +36 -0
- package/packages/cookie-sanitizer/dist/detect-format.d.ts.map +1 -0
- package/packages/cookie-sanitizer/dist/detect-format.js +88 -0
- package/packages/cookie-sanitizer/dist/detect-format.js.map +1 -0
- package/packages/cookie-sanitizer/dist/index.d.ts +41 -0
- package/packages/cookie-sanitizer/dist/index.d.ts.map +1 -0
- package/packages/cookie-sanitizer/dist/index.js +39 -0
- package/packages/cookie-sanitizer/dist/index.js.map +1 -0
- package/packages/cookie-sanitizer/dist/infer-provider.d.ts +29 -0
- package/packages/cookie-sanitizer/dist/infer-provider.d.ts.map +1 -0
- package/packages/cookie-sanitizer/dist/infer-provider.js +96 -0
- package/packages/cookie-sanitizer/dist/infer-provider.js.map +1 -0
- package/packages/cookie-sanitizer/dist/normalize.d.ts +26 -0
- package/packages/cookie-sanitizer/dist/normalize.d.ts.map +1 -0
- package/packages/cookie-sanitizer/dist/normalize.js +75 -0
- package/packages/cookie-sanitizer/dist/normalize.js.map +1 -0
- package/packages/cookie-sanitizer/dist/parse-json.d.ts +45 -0
- package/packages/cookie-sanitizer/dist/parse-json.d.ts.map +1 -0
- package/packages/cookie-sanitizer/dist/parse-json.js +108 -0
- package/packages/cookie-sanitizer/dist/parse-json.js.map +1 -0
- package/packages/cookie-sanitizer/dist/parse-netscape.d.ts +43 -0
- package/packages/cookie-sanitizer/dist/parse-netscape.d.ts.map +1 -0
- package/packages/cookie-sanitizer/dist/parse-netscape.js +99 -0
- package/packages/cookie-sanitizer/dist/parse-netscape.js.map +1 -0
- package/packages/cookie-sanitizer/dist/sync.d.ts +62 -0
- package/packages/cookie-sanitizer/dist/sync.d.ts.map +1 -0
- package/packages/cookie-sanitizer/dist/sync.js +266 -0
- package/packages/cookie-sanitizer/dist/sync.js.map +1 -0
- package/packages/cookie-sanitizer/dist/types.d.ts +100 -0
- package/packages/cookie-sanitizer/dist/types.d.ts.map +1 -0
- package/packages/cookie-sanitizer/dist/types.js +13 -0
- package/packages/cookie-sanitizer/dist/types.js.map +1 -0
- package/packages/cookie-sanitizer/dist/watcher.d.ts +51 -0
- package/packages/cookie-sanitizer/dist/watcher.d.ts.map +1 -0
- package/packages/cookie-sanitizer/dist/watcher.js +148 -0
- package/packages/cookie-sanitizer/dist/watcher.js.map +1 -0
- package/packages/cookie-sanitizer/package.json +27 -0
- package/packages/cookie-sanitizer/src/atomic-write.ts +79 -0
- package/packages/cookie-sanitizer/src/detect-format.ts +102 -0
- package/packages/cookie-sanitizer/src/index.ts +89 -0
- package/packages/cookie-sanitizer/src/infer-provider.ts +103 -0
- package/packages/cookie-sanitizer/src/normalize.ts +92 -0
- package/packages/cookie-sanitizer/src/parse-json.ts +122 -0
- package/packages/cookie-sanitizer/src/parse-netscape.ts +118 -0
- package/packages/cookie-sanitizer/src/sync.ts +304 -0
- package/packages/cookie-sanitizer/src/types.ts +101 -0
- package/packages/cookie-sanitizer/src/watcher.ts +180 -0
- package/packages/cookie-sanitizer/test/infer.test.ts +110 -0
- package/packages/cookie-sanitizer/test/normalize.test.ts +113 -0
- package/packages/cookie-sanitizer/test/parse.test.ts +204 -0
- package/packages/cookie-sanitizer/test/sync.test.ts +231 -0
- package/packages/cookie-sanitizer/test/watcher.test.ts +27 -0
- package/packages/cookie-sanitizer/tsconfig.json +8 -0
- package/packages/cost-optimizer/package.json +1 -1
- package/packages/django-plugin/package.json +1 -1
- package/packages/doc-generator/package.json +1 -1
- package/packages/evaluation-engine/package.json +1 -1
- package/packages/evaluation-runner/package.json +1 -1
- package/packages/experience-replay/package.json +1 -1
- package/packages/feedback-collector/package.json +1 -1
- package/packages/framework-detector/package.json +1 -1
- package/packages/framework-plugin-sdk/package.json +1 -1
- package/packages/frappe-plugin/package.json +1 -1
- package/packages/generic-web-plugin/package.json +1 -1
- package/packages/health-monitor/package.json +1 -1
- package/packages/laravel-plugin/package.json +1 -1
- package/packages/learning-engine/package.json +1 -1
- package/packages/mcp-adapter/package.json +1 -1
- package/packages/memory-engine/package.json +1 -1
- package/packages/model-registry/package.json +1 -1
- package/packages/nextjs-plugin/package.json +1 -1
- package/packages/notification/package.json +1 -1
- package/packages/observability/package.json +1 -1
- package/packages/performance-optimizer/package.json +1 -1
- package/packages/project-analyzer/package.json +1 -1
- package/packages/prompt-compiler/package.json +1 -1
- package/packages/prompt-versioning/package.json +1 -1
- package/packages/provider-adapter-sdk/package.json +1 -1
- package/packages/provider-router/package.json +1 -1
- package/packages/provider-selector/package.json +1 -1
- package/packages/providers/dist/index.d.ts +1 -0
- package/packages/providers/dist/index.d.ts.map +1 -1
- package/packages/providers/dist/index.js +1 -0
- package/packages/providers/dist/index.js.map +1 -1
- package/packages/providers/dist/provider-id.d.ts +39 -0
- package/packages/providers/dist/provider-id.d.ts.map +1 -0
- package/packages/providers/dist/provider-id.js +96 -0
- package/packages/providers/dist/provider-id.js.map +1 -0
- package/packages/providers/package.json +1 -1
- package/packages/providers/src/index.ts +1 -0
- package/packages/providers/src/provider-id.ts +110 -0
- package/packages/quota-manager/package.json +1 -1
- package/packages/rate-limiter/package.json +1 -1
- package/packages/react-vite-plugin/package.json +1 -1
- package/packages/release-manager/package.json +1 -1
- package/packages/requirement-compiler/package.json +1 -1
- package/packages/runtime/package.json +1 -1
- package/packages/scheduler/package.json +1 -1
- package/packages/session/package.json +1 -1
- package/packages/shared-context/package.json +1 -1
- package/packages/skill-registry/package.json +1 -1
- package/packages/sprint-planner/package.json +1 -1
- package/packages/task-compiler/package.json +1 -1
- package/packages/test-data-generator/package.json +1 -1
- package/packages/test-generator/package.json +1 -1
- package/packages/token-estimation/package.json +1 -1
- package/packages/token-optimizer/package.json +1 -1
- package/packages/tui/package.json +1 -1
- package/packages/types/package.json +1 -1
- package/packages/worktree/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,15 +2,55 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
|
4
4
|
|
|
5
|
-
### [0.9.
|
|
5
|
+
### [0.9.10](https://github.com/ManotLuijiu/pi-harness-runtime/compare/v0.9.8...v0.9.10) (2026-07-23)
|
|
6
|
+
|
|
7
|
+
### Bug Fixes
|
|
8
|
+
|
|
9
|
+
* **tests:** update footer-status expectations for provider label prefix
|
|
10
|
+
|
|
11
|
+
### [0.9.9](https://github.com/ManotLuijiu/pi-harness-runtime/compare/v0.9.8...v0.9.9) (2026-07-23)
|
|
12
|
+
|
|
13
|
+
### Bug Fixes
|
|
14
|
+
|
|
15
|
+
* **release:** test workflow trigger via manual version bump
|
|
16
|
+
|
|
17
|
+
### [0.9.8](https://github.com/ManotLuijiu/pi-harness-runtime/compare/v0.9.5...v0.9.8) (2026-07-23)
|
|
18
|
+
|
|
19
|
+
### Features
|
|
20
|
+
|
|
21
|
+
* **cookie-sanitizer:** discoverable drop folder + per-provider mirror ([772eda5](https://github.com/ManotLuijiu/pi-harness-runtime/commit/772eda5c5c698572a1cef2dc93df0278e9a380ee))
|
|
22
|
+
|
|
23
|
+
### Bug Fixes
|
|
24
|
+
|
|
25
|
+
* harden auto-resume after compaction ([13378e8](https://github.com/ManotLuijiu/pi-harness-runtime/commit/13378e852c984ead0e66f0adeffc073ff58af50c))
|
|
26
|
+
* resume after output-limit error stops ([8c75a24](https://github.com/ManotLuijiu/pi-harness-runtime/commit/8c75a2432082c4f9ba6296ffe2d04b636863bf2f))
|
|
27
|
+
|
|
28
|
+
### [0.9.3](https://github.com/ManotLuijiu/pi-harness-runtime/compare/v0.5.0-beta.1...v0.9.3) (2026-07-14)
|
|
29
|
+
|
|
30
|
+
### Bug Fixes
|
|
31
|
+
|
|
32
|
+
* auto-resume pi dev with literal resume ([#51](https://github.com/ManotLuijiu/pi-harness-runtime/issues/51)) ([fd98762](https://github.com/ManotLuijiu/pi-harness-runtime/commit/fd987629f6062a4a7ff7a28d9dfb607962f5a4a9))
|
|
6
33
|
|
|
34
|
+
### [0.9.7](https://github.com/ManotLuijiu/pi-harness-runtime/compare/v0.9.5...v0.9.7) (2026-07-16)
|
|
7
35
|
|
|
8
36
|
### Bug Fixes
|
|
9
37
|
|
|
10
38
|
* harden auto-resume after compaction ([13378e8](https://github.com/ManotLuijiu/pi-harness-runtime/commit/13378e852c984ead0e66f0adeffc073ff58af50c))
|
|
39
|
+
* resume after output-limit error stops ([8c75a24](https://github.com/ManotLuijiu/pi-harness-runtime/commit/8c75a2432082c4f9ba6296ffe2d04b636863bf2f))
|
|
11
40
|
|
|
12
41
|
### [0.9.3](https://github.com/ManotLuijiu/pi-harness-runtime/compare/v0.5.0-beta.1...v0.9.3) (2026-07-14)
|
|
13
42
|
|
|
43
|
+
### Bug Fixes
|
|
44
|
+
|
|
45
|
+
* auto-resume pi dev with literal resume ([#51](https://github.com/ManotLuijiu/pi-harness-runtime/issues/51)) ([fd98762](https://github.com/ManotLuijiu/pi-harness-runtime/commit/fd987629f6062a4a7ff7a28d9dfb607962f5a4a9))
|
|
46
|
+
|
|
47
|
+
### [0.9.6](https://github.com/ManotLuijiu/pi-harness-runtime/compare/v0.9.5...v0.9.6) (2026-07-16)
|
|
48
|
+
|
|
49
|
+
### Bug Fixes
|
|
50
|
+
|
|
51
|
+
* harden auto-resume after compaction ([13378e8](https://github.com/ManotLuijiu/pi-harness-runtime/commit/13378e852c984ead0e66f0adeffc073ff58af50c))
|
|
52
|
+
|
|
53
|
+
### [0.9.3](https://github.com/ManotLuijiu/pi-harness-runtime/compare/v0.5.0-beta.1...v0.9.3) (2026-07-14)
|
|
14
54
|
|
|
15
55
|
### Bug Fixes
|
|
16
56
|
|
|
@@ -18,7 +58,6 @@ All notable changes to this project will be documented in this file. See [standa
|
|
|
18
58
|
|
|
19
59
|
### [0.9.5](https://github.com/ManotLuijiu/pi-harness-runtime/compare/v0.9.4...v0.9.5) (2026-07-15)
|
|
20
60
|
|
|
21
|
-
|
|
22
61
|
### Features
|
|
23
62
|
|
|
24
63
|
* add 15 packages from subagent batch + test expansions ([c82d898](https://github.com/ManotLuijiu/pi-harness-runtime/commit/c82d898277779886cdd1f7f42087698762becde3))
|
|
@@ -30,14 +69,12 @@ All notable changes to this project will be documented in this file. See [standa
|
|
|
30
69
|
* add package metadata for auth, scheduler, shared-context, token-estimation ([67e2621](https://github.com/ManotLuijiu/pi-harness-runtime/commit/67e26211633f01de4f0d5eca76abc4d40d1ee0ea))
|
|
31
70
|
* flesh out RFC 71-75 specs + fix codex-adapter LSP types ([38b8643](https://github.com/ManotLuijiu/pi-harness-runtime/commit/38b86438ef45f75d1c34caf5b4f401d29c76d44d))
|
|
32
71
|
|
|
33
|
-
|
|
34
72
|
### Bug Fixes
|
|
35
73
|
|
|
36
74
|
* auto-resume after compaction and output limits ([0cff2bc](https://github.com/ManotLuijiu/pi-harness-runtime/commit/0cff2bcf9035a699496e2726b74a1576863cf82e))
|
|
37
75
|
|
|
38
76
|
### [0.9.4](https://github.com/ManotLuijiu/pi-harness-runtime/compare/v0.5.0-beta.1...v0.9.4) (2026-07-14)
|
|
39
77
|
|
|
40
|
-
|
|
41
78
|
### Features
|
|
42
79
|
|
|
43
80
|
* configure Dependabot to target develop with auto-merge ([9e12b46](https://github.com/ManotLuijiu/pi-harness-runtime/commit/9e12b4620179b91d2dc1a4627e199920d3890f31))
|
|
@@ -45,7 +82,6 @@ All notable changes to this project will be documented in this file. See [standa
|
|
|
45
82
|
* RFC-0052 skill-registry gap fixes + 40 new RFCs (0061-0100) ([6defd26](https://github.com/ManotLuijiu/pi-harness-runtime/commit/6defd26ff931fb9f93548647bf3a76098aa1d48b))
|
|
46
83
|
* RFC-0060 memory-engine fixes + simplify auto-resume ([#52](https://github.com/ManotLuijiu/pi-harness-runtime/issues/52)) ([fb4de1a](https://github.com/ManotLuijiu/pi-harness-runtime/commit/fb4de1a9d1de74b875aabb58d0c06f7116994ca3))
|
|
47
84
|
|
|
48
|
-
|
|
49
85
|
### Bug Fixes
|
|
50
86
|
|
|
51
87
|
* collapse duplicate version keys in workspace package.json files ([f3a7289](https://github.com/ManotLuijiu/pi-harness-runtime/commit/f3a728923a96308296e45d7ce3db8fe3ad36780a))
|
|
@@ -54,12 +90,10 @@ All notable changes to this project will be documented in this file. See [standa
|
|
|
54
90
|
|
|
55
91
|
### [0.9.1](https://github.com/ManotLuijiu/pi-harness-runtime/compare/v0.7.1...v0.9.1) (2026-07-13)
|
|
56
92
|
|
|
57
|
-
|
|
58
93
|
### Features
|
|
59
94
|
|
|
60
95
|
* **release:** add synced-workspace release script ([617649d](https://github.com/ManotLuijiu/pi-harness-runtime/commit/617649d0b2227ebb4355eec4979b0c65822d60e3))
|
|
61
96
|
|
|
62
|
-
|
|
63
97
|
### Bug Fixes
|
|
64
98
|
|
|
65
99
|
* publish missing runtime modules ([3fc7058](https://github.com/ManotLuijiu/pi-harness-runtime/commit/3fc70586d0cd10f4d38eab67e4cadaec20aaeb56))
|
|
@@ -67,19 +101,16 @@ All notable changes to this project will be documented in this file. See [standa
|
|
|
67
101
|
|
|
68
102
|
## [0.9.0](https://github.com/ManotLuijiu/pi-harness-runtime/compare/v0.7.1...v0.9.0) (2026-07-13)
|
|
69
103
|
|
|
70
|
-
|
|
71
104
|
### Features
|
|
72
105
|
|
|
73
106
|
* **release:** add synced-workspace release script ([617649d](https://github.com/ManotLuijiu/pi-harness-runtime/commit/617649d0b2227ebb4355eec4979b0c65822d60e3))
|
|
74
107
|
|
|
75
|
-
|
|
76
108
|
### Bug Fixes
|
|
77
109
|
|
|
78
110
|
* **release:** remove redundant Bump version step — was double-bumping version (0.7.1→0.8.0) when tag pushed ([413ad6d](https://github.com/ManotLuijiu/pi-harness-runtime/commit/413ad6d49356ec62b94e9a4e09d3475ef39bebd6))
|
|
79
111
|
|
|
80
112
|
### [0.7.1](https://github.com/ManotLuijiu/pi-harness-runtime/compare/v0.6.3...v0.7.1) (2026-07-13)
|
|
81
113
|
|
|
82
|
-
|
|
83
114
|
### Bug Fixes
|
|
84
115
|
|
|
85
116
|
* **release:** set make_latest=true so new releases auto-mark as Latest ([26a7bb9](https://github.com/ManotLuijiu/pi-harness-runtime/commit/26a7bb98f3e603a9d68cbf39ca1558bc579d1a4a))
|
package/README.md
CHANGED
|
@@ -191,9 +191,26 @@ bun test # 131+ tests passing
|
|
|
191
191
|
|
|
192
192
|
## Automatic Quota Fetching
|
|
193
193
|
|
|
194
|
-
Quota data is automatically
|
|
194
|
+
Quota data is automatically surfaced per-provider:
|
|
195
195
|
|
|
196
|
-
|
|
196
|
+
| Provider | Source | Cadence |
|
|
197
|
+
|---|---|---|
|
|
198
|
+
| MiniMax | Playwright + cookies (continuous scrape) | every ~15 min |
|
|
199
|
+
| OpenAI / OpenAI Codex | TUI message capture (signal on limit) | on first limit hit |
|
|
200
|
+
| GLM (Z.ai / Zhipu) | TUI message capture (signal on limit) | on first limit hit |
|
|
201
|
+
| Anthropic | TUI message capture (signal on limit) | on first limit hit |
|
|
202
|
+
| OpenRouter | TUI message capture (signal on limit) | on first limit hit |
|
|
203
|
+
| Other / unknown | (no data — footer shows hint) | — |
|
|
204
|
+
|
|
205
|
+
The footer line carries the provider label, so you always know which LLM the data is from:
|
|
206
|
+
|
|
207
|
+
```
|
|
208
|
+
MiniMax: 5h: 92% left · week: 80% left # continuous (scrape)
|
|
209
|
+
OpenAI: 5h: -- · week: -- (no signal yet) # pending first limit hit
|
|
210
|
+
GLM: limit hit (tokens), reset 2026-07-23T17:28:00Z # TUI signal observed
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
1. **MiniMax setup** (one-time):
|
|
197
214
|
|
|
198
215
|
```bash
|
|
199
216
|
# Install EditThisCookie Chrome extension
|
|
@@ -202,13 +219,33 @@ Quota data is automatically fetched from MiniMax console every 5 minutes:
|
|
|
202
219
|
# Save to ~/.config/minimax-cookies.txt
|
|
203
220
|
```
|
|
204
221
|
|
|
205
|
-
|
|
222
|
+
**Recommended:** drop the file into the dedicated cookie folder. The runtime
|
|
223
|
+
normalizes any format (Netscape or EditThisCookie JSON, any filename) on its own:
|
|
224
|
+
|
|
225
|
+
```bash
|
|
226
|
+
# Save cookies as any name, any format into:
|
|
227
|
+
mkdir -p ~/.pi-harness-runtime/cookies
|
|
228
|
+
cp ~/Downloads/platform.minimax.io_cookies.txt ~/.pi-harness-runtime/cookies/
|
|
229
|
+
# …or use the EditThisCookie extension export (JSON) — same folder works.
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
The `cookie-sanitizer` package (`@pi-harness/cookie-sanitizer`) runs chokidar v5 on this
|
|
233
|
+
folder, normalizes everything to standard Netscape, and writes the canonical cache at
|
|
234
|
+
`~/.config/minimax-cookies.txt`. Live update latency: <1 second after drop.
|
|
235
|
+
|
|
236
|
+
2. **Other providers**: no setup needed. The runtime reads messages from the active
|
|
237
|
+
session and captures quota-exhaustion signals from the TUI. Once any limit is hit
|
|
238
|
+
(e.g. `OpenAI: context length exceeded, reset in 3 hr 27 min`), the footer updates
|
|
239
|
+
immediately and the data persists across `~/.pi/usage-status/mirror.json`.
|
|
240
|
+
|
|
241
|
+
3. **Environment** (optional override):
|
|
206
242
|
|
|
207
243
|
```bash
|
|
208
|
-
export QUOTA_COOKIE_FILE
|
|
244
|
+
export QUOTA_COOKIE_FILE=/path/to/your/cookies.txt
|
|
245
|
+
# When set, the sanitizer is bypassed and the scraper reads this file directly.
|
|
209
246
|
```
|
|
210
247
|
|
|
211
|
-
|
|
248
|
+
4. **Done!** Quota auto-refreshes every 5 minutes. Cookie file changes sync within ~1 second.
|
|
212
249
|
|
|
213
250
|
## Roadmap
|
|
214
251
|
|
package/footer-status.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { MirrorRecord } from "./mirror.ts";
|
|
1
|
+
import type { MirrorRecord, ProviderMirrorRecord } from "./mirror.ts";
|
|
2
2
|
import { formatQuotaStatus } from "./harness/e2e/quota-status.js";
|
|
3
3
|
import {
|
|
4
4
|
parseContextWindowStatusLine,
|
|
@@ -39,29 +39,126 @@ export function parseFooterStatusValue(value: string): ParsedFooterStatusValue {
|
|
|
39
39
|
return { kind: "unknown", value: null };
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
+
/** Display name for a provider id. Used as the footer label. */
|
|
43
|
+
function providerDisplayName(provider: string | null | undefined): string {
|
|
44
|
+
if (!provider) return "Provider";
|
|
45
|
+
switch (provider) {
|
|
46
|
+
case "minimax":
|
|
47
|
+
return "MiniMax";
|
|
48
|
+
case "openai":
|
|
49
|
+
return "OpenAI";
|
|
50
|
+
case "openai-codex":
|
|
51
|
+
return "OpenAI Codex";
|
|
52
|
+
case "glm":
|
|
53
|
+
return "GLM";
|
|
54
|
+
case "anthropic":
|
|
55
|
+
return "Anthropic";
|
|
56
|
+
case "openrouter":
|
|
57
|
+
return "OpenRouter";
|
|
58
|
+
default:
|
|
59
|
+
return provider;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** Hint shown when the provider has no usage data yet. */
|
|
64
|
+
function missingDataHint(
|
|
65
|
+
provider: string | null | undefined,
|
|
66
|
+
hasCookieSource: boolean,
|
|
67
|
+
): string {
|
|
68
|
+
if (provider === "minimax") {
|
|
69
|
+
return "drop minimax cookies into ~/.pi-harness-runtime/cookies/";
|
|
70
|
+
}
|
|
71
|
+
if (provider === "openai-codex") {
|
|
72
|
+
return "will update on first TUI limit signal";
|
|
73
|
+
}
|
|
74
|
+
if (
|
|
75
|
+
provider === "openai" ||
|
|
76
|
+
provider === "glm" ||
|
|
77
|
+
provider === "anthropic" ||
|
|
78
|
+
provider === "openrouter"
|
|
79
|
+
) {
|
|
80
|
+
return "no signal yet (updates on first limit hit)";
|
|
81
|
+
}
|
|
82
|
+
if (!hasCookieSource) return "no usage source configured";
|
|
83
|
+
return "no data yet";
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/** Normalize an unknown mirror record into a ProviderMirrorRecord view. */
|
|
87
|
+
function toProviderView(
|
|
88
|
+
mirror: MirrorRecord | ProviderMirrorRecord | null,
|
|
89
|
+
): ProviderMirrorRecord | null {
|
|
90
|
+
if (!mirror) return null;
|
|
91
|
+
const m = mirror as ProviderMirrorRecord;
|
|
92
|
+
if (typeof m.provider === "string") return m;
|
|
93
|
+
// Legacy flat-shape: already a single record without a provider wrapper.
|
|
94
|
+
return {
|
|
95
|
+
synced_at: m.synced_at ?? new Date().toISOString(),
|
|
96
|
+
provider: (m as MirrorRecord).provider ?? "",
|
|
97
|
+
source: "scrape",
|
|
98
|
+
model: (m as MirrorRecord).model,
|
|
99
|
+
h5_used_pct: (m as MirrorRecord).h5_used_pct,
|
|
100
|
+
h5_resets_at: (m as MirrorRecord).h5_resets_at,
|
|
101
|
+
weekly_used_pct: (m as MirrorRecord).weekly_used_pct,
|
|
102
|
+
weekly_resets_at: (m as MirrorRecord).weekly_resets_at,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
|
|
42
106
|
export function buildFooterStatusValue(
|
|
43
107
|
local: { today: { tokens: number; cost: number } },
|
|
44
|
-
mirror: MirrorRecord | null,
|
|
108
|
+
mirror: MirrorRecord | ProviderMirrorRecord | null,
|
|
45
109
|
freshness: "fresh" | "stale" | "expired" | "missing",
|
|
110
|
+
hasCookieSource: boolean = true,
|
|
111
|
+
activeProvider: string | null = null,
|
|
46
112
|
): string {
|
|
113
|
+
const view = toProviderView(mirror);
|
|
114
|
+
const provider = activeProvider ?? view?.provider ?? null;
|
|
115
|
+
const label = providerDisplayName(provider);
|
|
116
|
+
|
|
117
|
+
// Continuous data path: a fresh record has 5h or weekly percentages.
|
|
47
118
|
if (
|
|
48
|
-
|
|
119
|
+
view &&
|
|
49
120
|
freshness !== "expired" &&
|
|
50
|
-
(
|
|
121
|
+
(view.h5_used_pct !== undefined || view.weekly_used_pct !== undefined)
|
|
51
122
|
) {
|
|
52
123
|
const quotaStatus = formatQuotaStatus({
|
|
53
|
-
provider: "minimax",
|
|
54
|
-
h5UsedPct:
|
|
55
|
-
h5ResetsAt:
|
|
56
|
-
weeklyUsedPct:
|
|
57
|
-
weeklyResetsAt:
|
|
58
|
-
scrapedAt:
|
|
124
|
+
provider: (provider ?? "minimax") as "minimax",
|
|
125
|
+
h5UsedPct: view.h5_used_pct ?? 0,
|
|
126
|
+
h5ResetsAt: view.h5_resets_at,
|
|
127
|
+
weeklyUsedPct: view.weekly_used_pct ?? 0,
|
|
128
|
+
weeklyResetsAt: view.weekly_resets_at,
|
|
129
|
+
scrapedAt: view.synced_at,
|
|
59
130
|
});
|
|
60
131
|
const freshnessSuffix =
|
|
61
132
|
freshness === "fresh" || freshness === "missing" ? "" : ` · ${freshness}`;
|
|
62
|
-
return `${quotaStatus.extended}${freshnessSuffix}`;
|
|
133
|
+
return `${label}: ${quotaStatus.extended}${freshnessSuffix}`;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// TUI-signal path: an exhausted record from a limit hit.
|
|
137
|
+
if (
|
|
138
|
+
view &&
|
|
139
|
+
view.exhausted &&
|
|
140
|
+
(view.limitType !== undefined || view.resets_at !== undefined)
|
|
141
|
+
) {
|
|
142
|
+
const reset = view.resets_at ?? view.h5_resets_at ?? "soon";
|
|
143
|
+
return `${label}: limit hit (${view.limitType ?? "tokens"}), reset ${reset}`;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Discoverable hint when we have no data yet.
|
|
147
|
+
if (
|
|
148
|
+
provider &&
|
|
149
|
+
(!view || freshness === "expired" || freshness === "missing")
|
|
150
|
+
) {
|
|
151
|
+
const hint = missingDataHint(provider, hasCookieSource);
|
|
152
|
+
// MiniMax-on-fresh-machine still gets the cookie hint; for others
|
|
153
|
+
// the hint explains the signal-driven design.
|
|
154
|
+
if (provider === "minimax" && !hasCookieSource) {
|
|
155
|
+
return `${label}: 5h: -- (${hint})`;
|
|
156
|
+
}
|
|
157
|
+
return `${label}: 5h: -- · week: -- (${hint})`;
|
|
63
158
|
}
|
|
64
159
|
|
|
160
|
+
// Silent fallback: only reached if we genuinely don't know the provider.
|
|
161
|
+
// No "5h/week: --" line here because we'd be making up data.
|
|
65
162
|
const todayStr = `${(local.today.tokens / 1000).toFixed(1)}k tok · $${local.today.cost.toFixed(3)}`;
|
|
66
163
|
return `today: ${todayStr}`;
|
|
67
164
|
}
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* - Capture API responses for usage data
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
-
import { existsSync, readFileSync } from "node:fs";
|
|
13
|
+
import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
|
|
14
14
|
import { join } from "node:path";
|
|
15
15
|
import { homedir } from "node:os";
|
|
16
16
|
import { parseMiniMaxQuotaText } from "./minimax-quota-parser.js";
|
|
@@ -385,10 +385,19 @@ export class MiniMaxQuotaScraper {
|
|
|
385
385
|
throw new Error(msg);
|
|
386
386
|
}
|
|
387
387
|
|
|
388
|
+
// Pre-load the canonical cache so that the runtime-owned file
|
|
389
|
+
// (written by packages/cookie-sanitizer) takes precedence over
|
|
390
|
+
// whatever `this.config.cookieFile` points at. Both eventually
|
|
391
|
+
// resolve to the same standard Netscape format.
|
|
388
392
|
const cookies = loadNetscapeCookies(this.config.cookieFile!);
|
|
389
393
|
|
|
390
394
|
if (cookies.length === 0) {
|
|
391
|
-
const
|
|
395
|
+
const dropHint = join(homedir(), ".pi-harness-runtime", "cookies");
|
|
396
|
+
const msg =
|
|
397
|
+
`No cookies found.\n` +
|
|
398
|
+
`Drop your platform.minimax.io cookies (Netscape or EditThisCookie JSON) into:\n` +
|
|
399
|
+
` ${dropHint}\n` +
|
|
400
|
+
`…or run: bun packages/auth/src/run-minimax-auth.ts auth`;
|
|
392
401
|
if (!this.config.quiet) console.error("[MiniMaxQuotaScraper] " + msg);
|
|
393
402
|
throw new Error(msg);
|
|
394
403
|
}
|
|
@@ -474,10 +483,43 @@ export class MiniMaxQuotaScraper {
|
|
|
474
483
|
}
|
|
475
484
|
|
|
476
485
|
/**
|
|
477
|
-
* Check if cookie
|
|
486
|
+
* Check if any cookie source exists.
|
|
487
|
+
*
|
|
488
|
+
* "Source" can be either:
|
|
489
|
+
* - the canonical cache (this.config.cookieFile) — runtime-owned,
|
|
490
|
+
* populated by packages/cookie-sanitizer
|
|
491
|
+
* - the user-facing drop folder — ~/.pi-harness-runtime/cookies/
|
|
492
|
+
* — populated by humans (any name, any format)
|
|
493
|
+
*
|
|
494
|
+
* Either is enough to attempt the scrape.
|
|
478
495
|
*/
|
|
479
496
|
hasCookieFile(): boolean {
|
|
480
|
-
|
|
497
|
+
// Canonical cache present?
|
|
498
|
+
if (existsSync(this.config.cookieFile!)) return true;
|
|
499
|
+
|
|
500
|
+
// Drop folder has anything readable? (Sync would normalize it on the next trigger.)
|
|
501
|
+
try {
|
|
502
|
+
const dropDir = join(homedir(), ".pi-harness-runtime", "cookies");
|
|
503
|
+
if (existsSync(dropDir)) {
|
|
504
|
+
const entries = readdirSync(dropDir);
|
|
505
|
+
if (entries.length > 0) return true;
|
|
506
|
+
// One-level walk into subfolders.
|
|
507
|
+
for (const name of entries) {
|
|
508
|
+
try {
|
|
509
|
+
if (statSync(join(dropDir, name)).isDirectory()) {
|
|
510
|
+
const sub = readdirSync(join(dropDir, name));
|
|
511
|
+
if (sub.length > 0) return true;
|
|
512
|
+
}
|
|
513
|
+
} catch {
|
|
514
|
+
// ignore unreadable sub-entry
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
} catch {
|
|
519
|
+
// best-effort; treat as no
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
return false;
|
|
481
523
|
}
|
|
482
524
|
|
|
483
525
|
/**
|