oc-codex-multi-auth 6.14.4 → 6.16.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/README.md +49 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +159 -55
- package/dist/index.js.map +1 -1
- package/dist/lib/accounts/persistence.d.ts +53 -3
- package/dist/lib/accounts/persistence.d.ts.map +1 -1
- package/dist/lib/accounts/persistence.js +110 -4
- package/dist/lib/accounts/persistence.js.map +1 -1
- package/dist/lib/accounts/state.d.ts +1 -0
- package/dist/lib/accounts/state.d.ts.map +1 -1
- package/dist/lib/accounts/state.js +11 -0
- package/dist/lib/accounts/state.js.map +1 -1
- package/dist/lib/accounts.d.ts +1 -1
- package/dist/lib/accounts.d.ts.map +1 -1
- package/dist/lib/accounts.js +1 -1
- package/dist/lib/accounts.js.map +1 -1
- package/dist/lib/auth/login-runner.d.ts +2 -0
- package/dist/lib/auth/login-runner.d.ts.map +1 -1
- package/dist/lib/auth/login-runner.js +44 -12
- package/dist/lib/auth/login-runner.js.map +1 -1
- package/dist/lib/auth/loopback-flow.d.ts +124 -0
- package/dist/lib/auth/loopback-flow.d.ts.map +1 -0
- package/dist/lib/auth/loopback-flow.js +112 -0
- package/dist/lib/auth/loopback-flow.js.map +1 -0
- package/dist/lib/auth/plan-tier.d.ts +21 -0
- package/dist/lib/auth/plan-tier.d.ts.map +1 -0
- package/dist/lib/auth/plan-tier.js +92 -0
- package/dist/lib/auth/plan-tier.js.map +1 -0
- package/dist/lib/auth/token-utils.d.ts +8 -10
- package/dist/lib/auth/token-utils.d.ts.map +1 -1
- package/dist/lib/auth/token-utils.js +27 -18
- package/dist/lib/auth/token-utils.js.map +1 -1
- package/dist/lib/codex-usage.d.ts +13 -1
- package/dist/lib/codex-usage.d.ts.map +1 -1
- package/dist/lib/codex-usage.js +27 -8
- package/dist/lib/codex-usage.js.map +1 -1
- package/dist/lib/config.d.ts +8 -0
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +28 -0
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/constants.d.ts +5 -2
- package/dist/lib/constants.d.ts.map +1 -1
- package/dist/lib/constants.js +5 -2
- package/dist/lib/constants.js.map +1 -1
- package/dist/lib/desktop-notifications.d.ts +14 -0
- package/dist/lib/desktop-notifications.d.ts.map +1 -0
- package/dist/lib/desktop-notifications.js +59 -0
- package/dist/lib/desktop-notifications.js.map +1 -0
- package/dist/lib/quota-notification-state.d.ts +25 -0
- package/dist/lib/quota-notification-state.d.ts.map +1 -0
- package/dist/lib/quota-notification-state.js +94 -0
- package/dist/lib/quota-notification-state.js.map +1 -0
- package/dist/lib/quota-notifications.d.ts +79 -0
- package/dist/lib/quota-notifications.d.ts.map +1 -0
- package/dist/lib/quota-notifications.js +401 -0
- package/dist/lib/quota-notifications.js.map +1 -0
- package/dist/lib/schemas.d.ts +9 -0
- package/dist/lib/schemas.d.ts.map +1 -1
- package/dist/lib/schemas.js +7 -0
- package/dist/lib/schemas.js.map +1 -1
- package/dist/lib/storage/flagged.d.ts.map +1 -1
- package/dist/lib/storage/flagged.js +5 -0
- package/dist/lib/storage/flagged.js.map +1 -1
- package/dist/lib/storage/migrations.d.ts +2 -0
- package/dist/lib/storage/migrations.d.ts.map +1 -1
- package/dist/lib/storage/migrations.js.map +1 -1
- package/dist/lib/tools/codex-limits.d.ts.map +1 -1
- package/dist/lib/tools/codex-limits.js +7 -4
- package/dist/lib/tools/codex-limits.js.map +1 -1
- package/dist/lib/tools/codex-list.d.ts.map +1 -1
- package/dist/lib/tools/codex-list.js +13 -1
- package/dist/lib/tools/codex-list.js.map +1 -1
- package/dist/lib/tools/codex-status.d.ts.map +1 -1
- package/dist/lib/tools/codex-status.js +8 -0
- package/dist/lib/tools/codex-status.js.map +1 -1
- package/dist/lib/tui-status.d.ts.map +1 -1
- package/dist/lib/tui-status.js +6 -2
- package/dist/lib/tui-status.js.map +1 -1
- package/dist/lib/types.d.ts +1 -0
- package/dist/lib/types.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
type NotificationCallback = (error: Error | null) => void;
|
|
2
|
+
type ExecuteFile = (file: string, args: string[], options: {
|
|
3
|
+
timeout: number;
|
|
4
|
+
windowsHide: boolean;
|
|
5
|
+
}, callback: NotificationCallback) => unknown;
|
|
6
|
+
export type DesktopNotifier = (title: string, message: string) => Promise<boolean>;
|
|
7
|
+
export declare function isDesktopNotificationSupported(platform?: NodeJS.Platform): boolean;
|
|
8
|
+
export declare function createDesktopNotifier(options?: {
|
|
9
|
+
platform?: NodeJS.Platform;
|
|
10
|
+
executeFile?: ExecuteFile;
|
|
11
|
+
}): DesktopNotifier;
|
|
12
|
+
export declare const sendDesktopNotification: DesktopNotifier;
|
|
13
|
+
export {};
|
|
14
|
+
//# sourceMappingURL=desktop-notifications.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"desktop-notifications.d.ts","sourceRoot":"","sources":["../../lib/desktop-notifications.ts"],"names":[],"mappings":"AAaA,KAAK,oBAAoB,GAAG,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,KAAK,IAAI,CAAC;AAC1D,KAAK,WAAW,GAAG,CAClB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,OAAO,CAAA;CAAE,EAClD,QAAQ,EAAE,oBAAoB,KAC1B,OAAO,CAAC;AAEb,MAAM,MAAM,eAAe,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;AAYnF,wBAAgB,8BAA8B,CAC7C,QAAQ,GAAE,MAAM,CAAC,QAA2B,GAC1C,OAAO,CAET;AAED,wBAAgB,qBAAqB,CAAC,OAAO,CAAC,EAAE;IAC/C,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC;IAC3B,WAAW,CAAC,EAAE,WAAW,CAAC;CAC1B,GAAG,eAAe,CAwClB;AAED,eAAO,MAAM,uBAAuB,iBAA0B,CAAC"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { execFile } from "node:child_process";
|
|
2
|
+
import { logDebug, logWarn } from "./logger.js";
|
|
3
|
+
const DELIVERY_TIMEOUT_MS = 10_000;
|
|
4
|
+
const MACOS_NOTIFICATION_SCRIPT = `
|
|
5
|
+
function run(argv) {
|
|
6
|
+
const app = Application.currentApplication();
|
|
7
|
+
app.includeStandardAdditions = true;
|
|
8
|
+
app.displayNotification(argv[1], { withTitle: argv[0] });
|
|
9
|
+
}
|
|
10
|
+
`.trim();
|
|
11
|
+
const executeFile = (file, args, options, callback) => {
|
|
12
|
+
return execFile(file, args, options, (error) => callback(error));
|
|
13
|
+
};
|
|
14
|
+
function getErrorCode(error) {
|
|
15
|
+
if (typeof error !== "object" || error === null)
|
|
16
|
+
return "unknown";
|
|
17
|
+
const code = error.code;
|
|
18
|
+
return typeof code === "string" || typeof code === "number" ? String(code) : "unknown";
|
|
19
|
+
}
|
|
20
|
+
export function isDesktopNotificationSupported(platform = process.platform) {
|
|
21
|
+
return platform === "darwin";
|
|
22
|
+
}
|
|
23
|
+
export function createDesktopNotifier(options) {
|
|
24
|
+
const platform = options?.platform ?? process.platform;
|
|
25
|
+
const run = options?.executeFile ?? executeFile;
|
|
26
|
+
let warningLogged = false;
|
|
27
|
+
const warnOnce = (message) => {
|
|
28
|
+
if (warningLogged)
|
|
29
|
+
return;
|
|
30
|
+
warningLogged = true;
|
|
31
|
+
logWarn(message);
|
|
32
|
+
};
|
|
33
|
+
return async (title, message) => {
|
|
34
|
+
if (!isDesktopNotificationSupported(platform)) {
|
|
35
|
+
warnOnce("Desktop quota notifications are supported only on macOS.");
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
return await new Promise((resolve) => {
|
|
39
|
+
try {
|
|
40
|
+
run("/usr/bin/osascript", ["-l", "JavaScript", "-e", MACOS_NOTIFICATION_SCRIPT, title, message], { timeout: DELIVERY_TIMEOUT_MS, windowsHide: true }, (error) => {
|
|
41
|
+
if (!error) {
|
|
42
|
+
resolve(true);
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
logDebug(`Desktop quota notification failed with code ${getErrorCode(error)}`);
|
|
46
|
+
warnOnce("Desktop quota notification delivery failed on macOS.");
|
|
47
|
+
resolve(false);
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
logDebug(`Desktop quota notification threw with code ${getErrorCode(error)}`);
|
|
52
|
+
warnOnce("Desktop quota notification delivery failed on macOS.");
|
|
53
|
+
resolve(false);
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
export const sendDesktopNotification = createDesktopNotifier();
|
|
59
|
+
//# sourceMappingURL=desktop-notifications.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"desktop-notifications.js","sourceRoot":"","sources":["../../lib/desktop-notifications.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAE9C,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAEhD,MAAM,mBAAmB,GAAG,MAAM,CAAC;AACnC,MAAM,yBAAyB,GAAG;;;;;;CAMjC,CAAC,IAAI,EAAE,CAAC;AAYT,MAAM,WAAW,GAAgB,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE;IAClE,OAAO,QAAQ,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;AAClE,CAAC,CAAC;AAEF,SAAS,YAAY,CAAC,KAAc;IACnC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,SAAS,CAAC;IAClE,MAAM,IAAI,GAAI,KAAiC,CAAC,IAAI,CAAC;IACrD,OAAO,OAAO,IAAI,KAAK,QAAQ,IAAI,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AACxF,CAAC;AAED,MAAM,UAAU,8BAA8B,CAC7C,WAA4B,OAAO,CAAC,QAAQ;IAE5C,OAAO,QAAQ,KAAK,QAAQ,CAAC;AAC9B,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,OAGrC;IACA,MAAM,QAAQ,GAAG,OAAO,EAAE,QAAQ,IAAI,OAAO,CAAC,QAAQ,CAAC;IACvD,MAAM,GAAG,GAAG,OAAO,EAAE,WAAW,IAAI,WAAW,CAAC;IAChD,IAAI,aAAa,GAAG,KAAK,CAAC;IAE1B,MAAM,QAAQ,GAAG,CAAC,OAAe,EAAQ,EAAE;QAC1C,IAAI,aAAa;YAAE,OAAO;QAC1B,aAAa,GAAG,IAAI,CAAC;QACrB,OAAO,CAAC,OAAO,CAAC,CAAC;IAClB,CAAC,CAAC;IAEF,OAAO,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;QAC/B,IAAI,CAAC,8BAA8B,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC/C,QAAQ,CAAC,0DAA0D,CAAC,CAAC;YACrE,OAAO,KAAK,CAAC;QACd,CAAC;QAED,OAAO,MAAM,IAAI,OAAO,CAAU,CAAC,OAAO,EAAE,EAAE;YAC7C,IAAI,CAAC;gBACJ,GAAG,CACF,oBAAoB,EACpB,CAAC,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,yBAAyB,EAAE,KAAK,EAAE,OAAO,CAAC,EACrE,EAAE,OAAO,EAAE,mBAAmB,EAAE,WAAW,EAAE,IAAI,EAAE,EACnD,CAAC,KAAK,EAAE,EAAE;oBACT,IAAI,CAAC,KAAK,EAAE,CAAC;wBACZ,OAAO,CAAC,IAAI,CAAC,CAAC;wBACd,OAAO;oBACR,CAAC;oBACD,QAAQ,CAAC,+CAA+C,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;oBAC/E,QAAQ,CAAC,sDAAsD,CAAC,CAAC;oBACjE,OAAO,CAAC,KAAK,CAAC,CAAC;gBAChB,CAAC,CACD,CAAC;YACH,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBAChB,QAAQ,CAAC,8CAA8C,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;gBAC9E,QAAQ,CAAC,sDAAsD,CAAC,CAAC;gBACjE,OAAO,CAAC,KAAK,CAAC,CAAC;YAChB,CAAC;QACF,CAAC,CAAC,CAAC;IACJ,CAAC,CAAC;AACH,CAAC;AAED,MAAM,CAAC,MAAM,uBAAuB,GAAG,qBAAqB,EAAE,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export interface QuotaWindowNotificationState {
|
|
2
|
+
/**
|
|
3
|
+
* The remaining-percent reading this window was last seen at. It is the
|
|
4
|
+
* only per-window state: which threshold is "armed" is derived from it, so
|
|
5
|
+
* storing that separately would let a corrupt extra field invalidate an
|
|
6
|
+
* otherwise usable file.
|
|
7
|
+
*/
|
|
8
|
+
lastPercent?: number;
|
|
9
|
+
}
|
|
10
|
+
export interface QuotaNotificationState {
|
|
11
|
+
fiveHour: QuotaWindowNotificationState;
|
|
12
|
+
weekly: QuotaWindowNotificationState;
|
|
13
|
+
lastDeliveredAt?: number;
|
|
14
|
+
updatedAt: number;
|
|
15
|
+
}
|
|
16
|
+
export declare function getQuotaNotificationStatePath(activeProjectStoragePath: string): string;
|
|
17
|
+
export declare function readQuotaNotificationState(statePath: string): Promise<QuotaNotificationState | undefined>;
|
|
18
|
+
export declare function updateQuotaNotificationState<T>(statePath: string, update: (state: QuotaNotificationState | undefined) => Promise<{
|
|
19
|
+
state: QuotaNotificationState;
|
|
20
|
+
result: T;
|
|
21
|
+
}> | {
|
|
22
|
+
state: QuotaNotificationState;
|
|
23
|
+
result: T;
|
|
24
|
+
}): Promise<T>;
|
|
25
|
+
//# sourceMappingURL=quota-notification-state.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quota-notification-state.d.ts","sourceRoot":"","sources":["../../lib/quota-notification-state.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,4BAA4B;IAC5C;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,sBAAsB;IACtC,QAAQ,EAAE,4BAA4B,CAAC;IACvC,MAAM,EAAE,4BAA4B,CAAC;IACrC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,6BAA6B,CAAC,wBAAwB,EAAE,MAAM,GAAG,MAAM,CAEtF;AAsCD,wBAAsB,0BAA0B,CAC/C,SAAS,EAAE,MAAM,GACf,OAAO,CAAC,sBAAsB,GAAG,SAAS,CAAC,CAS7C;AAYD,wBAAsB,4BAA4B,CAAC,CAAC,EACnD,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,CAAC,KAAK,EAAE,sBAAsB,GAAG,SAAS,KAAK,OAAO,CAAC;IAC9D,KAAK,EAAE,sBAAsB,CAAC;IAC9B,MAAM,EAAE,CAAC,CAAC;CACV,CAAC,GAAG;IACJ,KAAK,EAAE,sBAAsB,CAAC;IAC9B,MAAM,EAAE,CAAC,CAAC;CACV,GACC,OAAO,CAAC,CAAC,CAAC,CA8BZ"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { promises as fs } from "node:fs";
|
|
2
|
+
import { dirname, join } from "node:path";
|
|
3
|
+
import { lock } from "proper-lockfile";
|
|
4
|
+
import { renameWithWindowsRetry } from "./storage/atomic-write.js";
|
|
5
|
+
import { logDebug, logWarn } from "./logger.js";
|
|
6
|
+
export function getQuotaNotificationStatePath(activeProjectStoragePath) {
|
|
7
|
+
return join(dirname(activeProjectStoragePath), "oc-codex-multi-auth-quota-notifications.json");
|
|
8
|
+
}
|
|
9
|
+
function parseWindowState(value) {
|
|
10
|
+
if (typeof value !== "object" || value === null)
|
|
11
|
+
return undefined;
|
|
12
|
+
const record = value;
|
|
13
|
+
const lastPercent = record.lastPercent;
|
|
14
|
+
if (lastPercent !== undefined &&
|
|
15
|
+
(typeof lastPercent !== "number" ||
|
|
16
|
+
!Number.isFinite(lastPercent) ||
|
|
17
|
+
lastPercent < 0 ||
|
|
18
|
+
lastPercent > 100)) {
|
|
19
|
+
return undefined;
|
|
20
|
+
}
|
|
21
|
+
// Older files may carry an `activeThreshold` key. It is ignored rather than
|
|
22
|
+
// rejected so an upgrade does not discard a usable state file.
|
|
23
|
+
return { lastPercent };
|
|
24
|
+
}
|
|
25
|
+
function parseState(value) {
|
|
26
|
+
if (typeof value !== "object" || value === null)
|
|
27
|
+
return undefined;
|
|
28
|
+
const record = value;
|
|
29
|
+
const fiveHour = parseWindowState(record.fiveHour);
|
|
30
|
+
const weekly = parseWindowState(record.weekly);
|
|
31
|
+
const lastDeliveredAt = record.lastDeliveredAt;
|
|
32
|
+
if (!fiveHour || !weekly || typeof record.updatedAt !== "number" || !Number.isFinite(record.updatedAt)) {
|
|
33
|
+
return undefined;
|
|
34
|
+
}
|
|
35
|
+
if (lastDeliveredAt !== undefined &&
|
|
36
|
+
(typeof lastDeliveredAt !== "number" || !Number.isFinite(lastDeliveredAt) || lastDeliveredAt < 0)) {
|
|
37
|
+
return undefined;
|
|
38
|
+
}
|
|
39
|
+
return { fiveHour, weekly, lastDeliveredAt, updatedAt: record.updatedAt };
|
|
40
|
+
}
|
|
41
|
+
export async function readQuotaNotificationState(statePath) {
|
|
42
|
+
try {
|
|
43
|
+
return parseState(JSON.parse(await fs.readFile(statePath, "utf-8")));
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
if (error.code !== "ENOENT") {
|
|
47
|
+
logWarn(`Failed to read quota notification state from ${statePath}: ${error.message}`);
|
|
48
|
+
}
|
|
49
|
+
return undefined;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
async function writeState(statePath, state) {
|
|
53
|
+
const tempPath = `${statePath}.${process.pid}.${Date.now()}.tmp`;
|
|
54
|
+
try {
|
|
55
|
+
await fs.writeFile(tempPath, JSON.stringify(state, null, 2), { mode: 0o600 });
|
|
56
|
+
await renameWithWindowsRetry(tempPath, statePath);
|
|
57
|
+
}
|
|
58
|
+
finally {
|
|
59
|
+
await fs.rm(tempPath, { force: true }).catch(() => undefined);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
export async function updateQuotaNotificationState(statePath, update) {
|
|
63
|
+
await fs.mkdir(dirname(statePath), { recursive: true, mode: 0o700 });
|
|
64
|
+
let compromised;
|
|
65
|
+
const release = await lock(statePath, {
|
|
66
|
+
realpath: false,
|
|
67
|
+
stale: 10_000,
|
|
68
|
+
update: 2_000,
|
|
69
|
+
retries: {
|
|
70
|
+
retries: 5,
|
|
71
|
+
factor: 1.5,
|
|
72
|
+
minTimeout: 50,
|
|
73
|
+
maxTimeout: 500,
|
|
74
|
+
randomize: true,
|
|
75
|
+
},
|
|
76
|
+
onCompromised: (error) => {
|
|
77
|
+
compromised = error;
|
|
78
|
+
logDebug(`Quota notification state lock compromised: ${error.message}`);
|
|
79
|
+
},
|
|
80
|
+
});
|
|
81
|
+
try {
|
|
82
|
+
const next = await update(await readQuotaNotificationState(statePath));
|
|
83
|
+
if (compromised)
|
|
84
|
+
throw compromised;
|
|
85
|
+
await writeState(statePath, next.state);
|
|
86
|
+
return next.result;
|
|
87
|
+
}
|
|
88
|
+
finally {
|
|
89
|
+
await release().catch((error) => {
|
|
90
|
+
logDebug(`Failed to release quota notification state lock: ${error.message}`);
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=quota-notification-state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quota-notification-state.js","sourceRoot":"","sources":["../../lib/quota-notification-state.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { type QuotaNotificationsConfig } from "./config.js";
|
|
2
|
+
import { type CodexUsageSummary } from "./codex-usage.js";
|
|
3
|
+
import { type DesktopNotifier } from "./desktop-notifications.js";
|
|
4
|
+
import { type QuotaNotificationState, type QuotaWindowNotificationState } from "./quota-notification-state.js";
|
|
5
|
+
import { type AccountMetadataV3, type AccountStorageV3 } from "./storage.js";
|
|
6
|
+
export type QuotaWindowName = "fiveHour" | "weekly";
|
|
7
|
+
export interface AggregatedQuotaWindow {
|
|
8
|
+
/** Headroom of the enabled account with the most room left in this window. */
|
|
9
|
+
remainingPercent?: number;
|
|
10
|
+
/**
|
|
11
|
+
* Reset time of the account `remainingPercent` was taken from. Always the
|
|
12
|
+
* same account, so the pair describes a quota one account actually has.
|
|
13
|
+
*/
|
|
14
|
+
resetAtMs?: number;
|
|
15
|
+
/**
|
|
16
|
+
* Earliest reset across every enabled account with usable usage, set only
|
|
17
|
+
* when some other account recovers before {@link resetAtMs}. Reported as its
|
|
18
|
+
* own value rather than folded into `resetAtMs`, because a max-percent /
|
|
19
|
+
* min-reset pair describes a quota no account holds.
|
|
20
|
+
*/
|
|
21
|
+
earliestResetAtMs?: number;
|
|
22
|
+
}
|
|
23
|
+
export interface AggregatedQuotaUsage {
|
|
24
|
+
fiveHour: AggregatedQuotaWindow;
|
|
25
|
+
weekly: AggregatedQuotaWindow;
|
|
26
|
+
}
|
|
27
|
+
export interface QuotaThresholdCrossing {
|
|
28
|
+
window: QuotaWindowName;
|
|
29
|
+
threshold: number;
|
|
30
|
+
remainingPercent: number;
|
|
31
|
+
/** Reset of the account `remainingPercent` came from; never a different one. */
|
|
32
|
+
resetAtMs?: number;
|
|
33
|
+
/** Earliest reset in the pool, when it is not `resetAtMs`. */
|
|
34
|
+
earliestResetAtMs?: number;
|
|
35
|
+
}
|
|
36
|
+
export interface AccountQuotaSummary {
|
|
37
|
+
usage: CodexUsageSummary;
|
|
38
|
+
}
|
|
39
|
+
export interface QuotaMonitor {
|
|
40
|
+
start(): void;
|
|
41
|
+
dispose(): void;
|
|
42
|
+
runNow(): Promise<void>;
|
|
43
|
+
}
|
|
44
|
+
type MonitorDependencies = {
|
|
45
|
+
loadConfig: () => QuotaNotificationsConfig;
|
|
46
|
+
loadStorage: () => Promise<AccountStorageV3 | null>;
|
|
47
|
+
fetchSummary: (storage: AccountStorageV3, account: AccountMetadataV3 | undefined, onCredentialsPersisted: () => void) => Promise<AccountQuotaSummary | null>;
|
|
48
|
+
notify: DesktopNotifier;
|
|
49
|
+
notificationsSupported: () => boolean;
|
|
50
|
+
/**
|
|
51
|
+
* Called once per check when refreshing an account rotated its single-use
|
|
52
|
+
* refresh token to disk. The host wires this to its account-manager cache
|
|
53
|
+
* invalidation; see {@link fetchUsageForAccount} for why it is mandatory.
|
|
54
|
+
*/
|
|
55
|
+
onCredentialsPersisted: () => void;
|
|
56
|
+
now: () => number;
|
|
57
|
+
initialDelayMs: number;
|
|
58
|
+
};
|
|
59
|
+
export declare function aggregateQuotaUsage(summaries: readonly AccountQuotaSummary[], now?: number): AggregatedQuotaUsage;
|
|
60
|
+
/**
|
|
61
|
+
* Decide whether this observation crosses a threshold downward.
|
|
62
|
+
*
|
|
63
|
+
* A threshold fires when the window is at or below it *and* the previous
|
|
64
|
+
* observation was strictly above it, which is the "rises above it after a
|
|
65
|
+
* reset" contract in `docs/configuration.md`. The most severe matching
|
|
66
|
+
* threshold wins, and the selection does not assume `thresholds` is sorted.
|
|
67
|
+
*/
|
|
68
|
+
export declare function transitionQuotaWindow(previous: QuotaWindowNotificationState, current: AggregatedQuotaWindow, thresholds: readonly number[]): {
|
|
69
|
+
state: QuotaWindowNotificationState;
|
|
70
|
+
threshold?: number;
|
|
71
|
+
};
|
|
72
|
+
export declare function transitionQuotaState(previous: QuotaNotificationState | undefined, usage: AggregatedQuotaUsage, thresholds: readonly number[], now?: number): {
|
|
73
|
+
state: QuotaNotificationState;
|
|
74
|
+
crossings: QuotaThresholdCrossing[];
|
|
75
|
+
};
|
|
76
|
+
export declare function formatQuotaNotification(usage: AggregatedQuotaUsage): string;
|
|
77
|
+
export declare function createQuotaMonitor(overrides?: Partial<MonitorDependencies>): QuotaMonitor;
|
|
78
|
+
export {};
|
|
79
|
+
//# sourceMappingURL=quota-notifications.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quota-notifications.d.ts","sourceRoot":"","sources":["../../lib/quota-notifications.ts"],"names":[],"mappings":"AAAA,OAAO,EAA2C,KAAK,wBAAwB,EAAE,MAAM,aAAa,CAAC;AACrG,OAAO,EASN,KAAK,iBAAiB,EACtB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAGN,KAAK,eAAe,EACpB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAGN,KAAK,sBAAsB,EAC3B,KAAK,4BAA4B,EACjC,MAAM,+BAA+B,CAAC;AAEvC,OAAO,EAAgB,KAAK,iBAAiB,EAAE,KAAK,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAM3F,MAAM,MAAM,eAAe,GAAG,UAAU,GAAG,QAAQ,CAAC;AAEpD,MAAM,WAAW,qBAAqB;IACrC,8EAA8E;IAC9E,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,oBAAoB;IACpC,QAAQ,EAAE,qBAAqB,CAAC;IAChC,MAAM,EAAE,qBAAqB,CAAC;CAC9B;AAED,MAAM,WAAW,sBAAsB;IACtC,MAAM,EAAE,eAAe,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,MAAM,CAAC;IACzB,gFAAgF;IAChF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,8DAA8D;IAC9D,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,mBAAmB;IACnC,KAAK,EAAE,iBAAiB,CAAC;CACzB;AAED,MAAM,WAAW,YAAY;IAC5B,KAAK,IAAI,IAAI,CAAC;IACd,OAAO,IAAI,IAAI,CAAC;IAChB,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED,KAAK,mBAAmB,GAAG;IAC1B,UAAU,EAAE,MAAM,wBAAwB,CAAC;IAC3C,WAAW,EAAE,MAAM,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC;IACpD,YAAY,EAAE,CACb,OAAO,EAAE,gBAAgB,EACzB,OAAO,EAAE,iBAAiB,GAAG,SAAS,EACtC,sBAAsB,EAAE,MAAM,IAAI,KAC9B,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC,CAAC;IACzC,MAAM,EAAE,eAAe,CAAC;IACxB,sBAAsB,EAAE,MAAM,OAAO,CAAC;IACtC;;;;OAIG;IACH,sBAAsB,EAAE,MAAM,IAAI,CAAC;IACnC,GAAG,EAAE,MAAM,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;CACvB,CAAC;AAsEF,wBAAgB,mBAAmB,CAClC,SAAS,EAAE,SAAS,mBAAmB,EAAE,EACzC,GAAG,SAAa,GACd,oBAAoB,CAKtB;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CACpC,QAAQ,EAAE,4BAA4B,EACtC,OAAO,EAAE,qBAAqB,EAC9B,UAAU,EAAE,SAAS,MAAM,EAAE,GAC3B;IAAE,KAAK,EAAE,4BAA4B,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,CAa7D;AAED,wBAAgB,oBAAoB,CACnC,QAAQ,EAAE,sBAAsB,GAAG,SAAS,EAC5C,KAAK,EAAE,oBAAoB,EAC3B,UAAU,EAAE,SAAS,MAAM,EAAE,EAC7B,GAAG,SAAa,GACd;IAAE,KAAK,EAAE,sBAAsB,CAAC;IAAC,SAAS,EAAE,sBAAsB,EAAE,CAAA;CAAE,CAgCxE;AAeD,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,oBAAoB,GAAG,MAAM,CAE3E;AAUD,wBAAgB,kBAAkB,CAAC,SAAS,GAAE,OAAO,CAAC,mBAAmB,CAAM,GAAG,YAAY,CA0O7F"}
|