@henryqw/pi-multi-codex 0.3.10 → 0.3.12
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 +5 -0
- package/extensions/multi-codex.ts +3 -28
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,6 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
Use multiple ChatGPT Codex OAuth accounts in Pi.
|
|
4
4
|
|
|
5
|
+
## Why
|
|
6
|
+
|
|
7
|
+
- **Created for**: Using multiple ChatGPT Codex OAuth accounts from one Pi installation.
|
|
8
|
+
- **Advantage**: Before work starts, quota-aware routing selects the managed slot with the most remaining seven-day quota without changing in-progress sessions.
|
|
9
|
+
|
|
5
10
|
## Install
|
|
6
11
|
|
|
7
12
|
```bash
|
|
@@ -2,6 +2,7 @@ import { createHash, randomUUID } from "node:crypto";
|
|
|
2
2
|
import { readFileSync } from "node:fs";
|
|
3
3
|
import { chmod, mkdir, readFile, rename, rm, writeFile } from "node:fs/promises";
|
|
4
4
|
import { join } from "node:path";
|
|
5
|
+
import { setTimeout as delay } from "node:timers/promises";
|
|
5
6
|
import { lock } from "proper-lockfile";
|
|
6
7
|
import {
|
|
7
8
|
createAssistantMessageEventStream,
|
|
@@ -259,32 +260,6 @@ function errorCode(error: unknown): string | undefined {
|
|
|
259
260
|
return error && typeof error === "object" && "code" in error ? String(error.code) : undefined;
|
|
260
261
|
}
|
|
261
262
|
|
|
262
|
-
function sleepUnref(ms: number, signal?: AbortSignal): Promise<void> {
|
|
263
|
-
return new Promise((resolve, reject) => {
|
|
264
|
-
if (signal?.aborted) return reject(signal.reason);
|
|
265
|
-
let abort: () => void;
|
|
266
|
-
const cleanup = () => signal?.removeEventListener("abort", abort);
|
|
267
|
-
const timer = setTimeout(() => {
|
|
268
|
-
cleanup();
|
|
269
|
-
resolve();
|
|
270
|
-
}, ms);
|
|
271
|
-
timer.unref?.();
|
|
272
|
-
abort = () => {
|
|
273
|
-
clearTimeout(timer);
|
|
274
|
-
cleanup();
|
|
275
|
-
reject(signal?.reason);
|
|
276
|
-
};
|
|
277
|
-
signal?.addEventListener("abort", abort, { once: true });
|
|
278
|
-
if (signal?.aborted) abort();
|
|
279
|
-
});
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
function cleanupSignal(): AbortSignal {
|
|
283
|
-
const controller = new AbortController();
|
|
284
|
-
void sleepUnref(CLEANUP_TIMEOUT_MS).then(() => controller.abort());
|
|
285
|
-
return controller.signal;
|
|
286
|
-
}
|
|
287
|
-
|
|
288
263
|
async function withCacheMutex<T>(operation: (signal: AbortSignal) => Promise<T>, signal?: AbortSignal): Promise<T> {
|
|
289
264
|
signal?.throwIfAborted();
|
|
290
265
|
await mkdir(join(getAgentDir(), "config", "pi-multi-codex"), { recursive: true, mode: 0o700 });
|
|
@@ -310,7 +285,7 @@ async function withCacheMutex<T>(operation: (signal: AbortSignal) => Promise<T>,
|
|
|
310
285
|
}
|
|
311
286
|
} catch (error) {
|
|
312
287
|
if (errorCode(error) !== "ELOCKED") throw error;
|
|
313
|
-
await
|
|
288
|
+
await delay(CACHE_MUTEX_RETRY_MS, undefined, { signal, ref: false });
|
|
314
289
|
}
|
|
315
290
|
}
|
|
316
291
|
throw new Error("Cache mutex acquisition ended unexpectedly.");
|
|
@@ -694,7 +669,7 @@ class CodexQuotaStatus {
|
|
|
694
669
|
} finally {
|
|
695
670
|
if (owner) {
|
|
696
671
|
this.stopHeartbeat(slot, owner);
|
|
697
|
-
await this.release(slot, owner, session.signal.aborted ?
|
|
672
|
+
await this.release(slot, owner, session.signal.aborted ? AbortSignal.timeout(CLEANUP_TIMEOUT_MS) : session.signal).catch(() => undefined);
|
|
698
673
|
}
|
|
699
674
|
}
|
|
700
675
|
}
|