@henryqw/pi-multi-codex 1.0.3 → 1.0.4

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 CHANGED
@@ -13,11 +13,11 @@ pi install npm:@henryqw/pi-multi-codex
13
13
 
14
14
  ## Works with
15
15
 
16
- | Package | Why |
17
- | --- | --- |
18
- | [`@henryqw/pi-footer`](https://pi.henry.wang/extensions/pi-footer) | Improves. Shows the active slot's quota or five-hour block in the footer. |
19
- | [`@henryqw/pi-subagent`](https://pi.henry.wang/extensions/pi-subagent) | Improves. Isolated children keep Main's active Codex slot. |
20
- | [`@henryqw/pi-task-models`](https://pi.henry.wang/extensions/pi-task-models) | Improves. Numbered slots share one profile route. |
16
+ | Package | Relationship | Purpose |
17
+ | --- | --- | --- |
18
+ | [`@henryqw/pi-footer`](https://pi.henry.wang/extensions/pi-footer) | Improves | Shows the active slot's quota or five-hour block in the footer. |
19
+ | [`@henryqw/pi-subagent`](https://pi.henry.wang/extensions/pi-subagent) | Improves | Isolated children keep Main's active Codex slot. |
20
+ | [`@henryqw/pi-task-models`](https://pi.henry.wang/extensions/pi-task-models) | Improves | Numbered slots share one profile route. |
21
21
 
22
22
  ## Use
23
23
 
@@ -47,24 +47,20 @@ A numbered slot is one Codex account position in Pi.
47
47
 
48
48
  ## Config
49
49
 
50
- Automatic HTTP 429 switching is on by default. To disable it, create `~/.pi/agent/config/pi-multi-codex/config.json`:
50
+ Package-owned: `~/.pi/agent/config/pi-multi-codex/config.json`
51
51
 
52
- ```json
53
- {
54
- "autoSwitchOn429": false
55
- }
56
- ```
52
+ | Name | Description | Values | Default |
53
+ | --- | --- | --- | --- |
54
+ | `autoSwitchOn429` | Switches to another eligible slot after an HTTP 429. | Boolean. | `true` |
57
55
 
58
- The config must contain only `autoSwitchOn429` as a boolean. Invalid config is preserved and disables automatic switching.
56
+ Set `autoSwitchOn429` to `false` to disable automatic switching. The config must contain only this field as a boolean. Invalid config is preserved and disables automatic switching.
59
57
 
60
58
  ## State and storage
61
59
 
62
60
  The extension maintains a generated, credential-free quota cache at `~/.pi/agent/config/pi-multi-codex/usage.json`.
63
61
 
64
- ## Data, cost, and privacy
62
+ ## Limits and recovery
65
63
 
66
64
  The extension reads `auth.json`. It never writes or refreshes credentials.
67
65
 
68
- ## Limits and recovery
69
-
70
66
  Scoped sessions can switch only to exact scoped aliases.
@@ -1,9 +1,9 @@
1
1
  import { createHash, randomUUID } from "node:crypto";
2
2
  import { readFileSync } from "node:fs";
3
- import { chmod, mkdir, readFile, rename, rm, writeFile } from "node:fs/promises";
3
+ import { mkdir, readFile } from "node:fs/promises";
4
4
  import { join } from "node:path";
5
5
  import { setTimeout as delay } from "node:timers/promises";
6
- import { createConfigStore, extensionConfigDir } from "@henryqw/pi-config-store";
6
+ import { createConfigStore, extensionConfigDir, writePrivateTextFileAtomically } from "@henryqw/pi-config-store";
7
7
  import { lock } from "proper-lockfile";
8
8
  import {
9
9
  createAssistantMessageEventStream,
@@ -258,22 +258,11 @@ async function saveState(state: UsageState, signal?: AbortSignal): Promise<void>
258
258
  signal?.throwIfAborted();
259
259
  if (state.untrusted) return;
260
260
  const file = cachePath();
261
- const directory = extensionConfigDir("pi-multi-codex");
262
- await mkdir(directory, { recursive: true, mode: 0o700 });
263
261
  const data = `${JSON.stringify({
264
262
  slots: [...state.slots.values()].sort((a, b) => a.slot - b.slot),
265
263
  locks: [...state.locks.values()].sort((a, b) => a.slot - b.slot),
266
264
  })}\n`;
267
- const temporary = `${file}.${randomUUID()}.tmp`;
268
- try {
269
- await writeFile(temporary, data, { encoding: "utf8", mode: 0o600, flag: "wx", signal });
270
- signal?.throwIfAborted();
271
- await rename(temporary, file);
272
- signal?.throwIfAborted();
273
- await chmod(file, 0o600);
274
- } finally {
275
- await rm(temporary, { force: true }).catch(() => undefined);
276
- }
265
+ await writePrivateTextFileAtomically(file, data, { signal });
277
266
  }
278
267
 
279
268
  async function withCacheMutex<T>(operation: (signal: AbortSignal) => Promise<T>, signal?: AbortSignal): Promise<T> {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@henryqw/pi-multi-codex",
3
- "version": "1.0.3",
3
+ "version": "1.0.4",
4
4
  "description": "Use multiple ChatGPT Codex OAuth accounts in Pi.",
5
5
  "keywords": [
6
6
  "pi-package",
@@ -46,7 +46,7 @@
46
46
  "image": "https://raw.githubusercontent.com/HenryQW/pi-harness/main/extensions/pi-multi-codex/example.png"
47
47
  },
48
48
  "dependencies": {
49
- "@henryqw/pi-config-store": "^1.0.0",
49
+ "@henryqw/pi-config-store": "^1.1.0",
50
50
  "proper-lockfile": "^4.1.2"
51
51
  },
52
52
  "devDependencies": {