oh-my-codex 0.18.2 → 0.18.3
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/Cargo.toml +1 -1
- package/dist/agents/__tests__/definitions.test.js +9 -0
- package/dist/agents/__tests__/definitions.test.js.map +1 -1
- package/dist/agents/__tests__/native-config.test.js +1 -0
- package/dist/agents/__tests__/native-config.test.js.map +1 -1
- package/dist/agents/definitions.d.ts.map +1 -1
- package/dist/agents/definitions.js +10 -0
- package/dist/agents/definitions.js.map +1 -1
- package/dist/auth/__tests__/config-sessions.test.d.ts +2 -0
- package/dist/auth/__tests__/config-sessions.test.d.ts.map +1 -0
- package/dist/auth/__tests__/config-sessions.test.js +48 -0
- package/dist/auth/__tests__/config-sessions.test.js.map +1 -0
- package/dist/auth/__tests__/quota-rotation.test.d.ts +2 -0
- package/dist/auth/__tests__/quota-rotation.test.d.ts.map +1 -0
- package/dist/auth/__tests__/quota-rotation.test.js +33 -0
- package/dist/auth/__tests__/quota-rotation.test.js.map +1 -0
- package/dist/auth/__tests__/redact.test.d.ts +2 -0
- package/dist/auth/__tests__/redact.test.d.ts.map +1 -0
- package/dist/auth/__tests__/redact.test.js +20 -0
- package/dist/auth/__tests__/redact.test.js.map +1 -0
- package/dist/auth/__tests__/storage.test.d.ts +2 -0
- package/dist/auth/__tests__/storage.test.d.ts.map +1 -0
- package/dist/auth/__tests__/storage.test.js +108 -0
- package/dist/auth/__tests__/storage.test.js.map +1 -0
- package/dist/auth/config.d.ts +9 -0
- package/dist/auth/config.d.ts.map +1 -0
- package/dist/auth/config.js +77 -0
- package/dist/auth/config.js.map +1 -0
- package/dist/auth/hotswap.d.ts +36 -0
- package/dist/auth/hotswap.d.ts.map +1 -0
- package/dist/auth/hotswap.js +159 -0
- package/dist/auth/hotswap.js.map +1 -0
- package/dist/auth/index.d.ts +8 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +8 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/paths.d.ts +12 -0
- package/dist/auth/paths.d.ts.map +1 -0
- package/dist/auth/paths.js +78 -0
- package/dist/auth/paths.js.map +1 -0
- package/dist/auth/quota-detector.d.ts +10 -0
- package/dist/auth/quota-detector.d.ts.map +1 -0
- package/dist/auth/quota-detector.js +40 -0
- package/dist/auth/quota-detector.js.map +1 -0
- package/dist/auth/redact.d.ts +2 -0
- package/dist/auth/redact.d.ts.map +1 -0
- package/dist/auth/redact.js +26 -0
- package/dist/auth/redact.js.map +1 -0
- package/dist/auth/rotation.d.ts +9 -0
- package/dist/auth/rotation.d.ts.map +1 -0
- package/dist/auth/rotation.js +26 -0
- package/dist/auth/rotation.js.map +1 -0
- package/dist/auth/sessions.d.ts +15 -0
- package/dist/auth/sessions.d.ts.map +1 -0
- package/dist/auth/sessions.js +62 -0
- package/dist/auth/sessions.js.map +1 -0
- package/dist/auth/storage.d.ts +27 -0
- package/dist/auth/storage.d.ts.map +1 -0
- package/dist/auth/storage.js +111 -0
- package/dist/auth/storage.js.map +1 -0
- package/dist/cli/__tests__/auth.test.d.ts +2 -0
- package/dist/cli/__tests__/auth.test.d.ts.map +1 -0
- package/dist/cli/__tests__/auth.test.js +168 -0
- package/dist/cli/__tests__/auth.test.js.map +1 -0
- package/dist/cli/__tests__/doctor-warning-copy.test.js +51 -0
- package/dist/cli/__tests__/doctor-warning-copy.test.js.map +1 -1
- package/dist/cli/__tests__/explore.test.js +20 -0
- package/dist/cli/__tests__/explore.test.js.map +1 -1
- package/dist/cli/__tests__/index.test.js +10 -0
- package/dist/cli/__tests__/index.test.js.map +1 -1
- package/dist/cli/__tests__/nested-help-routing.test.js +1 -0
- package/dist/cli/__tests__/nested-help-routing.test.js.map +1 -1
- package/dist/cli/__tests__/setup-agents-overwrite.test.js +30 -1
- package/dist/cli/__tests__/setup-agents-overwrite.test.js.map +1 -1
- package/dist/cli/__tests__/setup-install-mode.test.js +47 -0
- package/dist/cli/__tests__/setup-install-mode.test.js.map +1 -1
- package/dist/cli/auth.d.ts +4 -0
- package/dist/cli/auth.d.ts.map +1 -0
- package/dist/cli/auth.js +89 -0
- package/dist/cli/auth.js.map +1 -0
- package/dist/cli/doctor.d.ts.map +1 -1
- package/dist/cli/doctor.js +19 -7
- package/dist/cli/doctor.js.map +1 -1
- package/dist/cli/explore.d.ts.map +1 -1
- package/dist/cli/explore.js +12 -0
- package/dist/cli/explore.js.map +1 -1
- package/dist/cli/index.d.ts +20 -2
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +104 -6
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/setup.d.ts.map +1 -1
- package/dist/cli/setup.js +11 -3
- package/dist/cli/setup.js.map +1 -1
- package/dist/config/__tests__/deep-interview.test.d.ts +2 -0
- package/dist/config/__tests__/deep-interview.test.d.ts.map +1 -0
- package/dist/config/__tests__/deep-interview.test.js +239 -0
- package/dist/config/__tests__/deep-interview.test.js.map +1 -0
- package/dist/config/__tests__/generator-idempotent.test.js +123 -0
- package/dist/config/__tests__/generator-idempotent.test.js.map +1 -1
- package/dist/config/deep-interview.d.ts +22 -0
- package/dist/config/deep-interview.d.ts.map +1 -0
- package/dist/config/deep-interview.js +151 -0
- package/dist/config/deep-interview.js.map +1 -0
- package/dist/config/generator.d.ts +5 -2
- package/dist/config/generator.d.ts.map +1 -1
- package/dist/config/generator.js +106 -36
- package/dist/config/generator.js.map +1 -1
- package/dist/hooks/__tests__/agents-overlay.test.js +2 -0
- package/dist/hooks/__tests__/agents-overlay.test.js.map +1 -1
- package/dist/hooks/__tests__/explore-routing.test.js +1 -0
- package/dist/hooks/__tests__/explore-routing.test.js.map +1 -1
- package/dist/hooks/__tests__/keyword-detector.test.js +301 -0
- package/dist/hooks/__tests__/keyword-detector.test.js.map +1 -1
- package/dist/hooks/deep-interview-config-instruction.d.ts +3 -0
- package/dist/hooks/deep-interview-config-instruction.d.ts.map +1 -0
- package/dist/hooks/deep-interview-config-instruction.js +47 -0
- package/dist/hooks/deep-interview-config-instruction.js.map +1 -0
- package/dist/hooks/explore-routing.d.ts.map +1 -1
- package/dist/hooks/explore-routing.js +1 -0
- package/dist/hooks/explore-routing.js.map +1 -1
- package/dist/hooks/keyword-detector.d.ts +5 -0
- package/dist/hooks/keyword-detector.d.ts.map +1 -1
- package/dist/hooks/keyword-detector.js +52 -8
- package/dist/hooks/keyword-detector.js.map +1 -1
- package/dist/hud/__tests__/hud-tmux-injection.test.js +4 -4
- package/dist/hud/__tests__/hud-tmux-injection.test.js.map +1 -1
- package/dist/hud/__tests__/reconcile.test.js +94 -9
- package/dist/hud/__tests__/reconcile.test.js.map +1 -1
- package/dist/hud/__tests__/tmux.test.js +103 -1
- package/dist/hud/__tests__/tmux.test.js.map +1 -1
- package/dist/hud/reconcile.d.ts +1 -1
- package/dist/hud/reconcile.d.ts.map +1 -1
- package/dist/hud/reconcile.js +8 -0
- package/dist/hud/reconcile.js.map +1 -1
- package/dist/hud/tmux.d.ts +7 -0
- package/dist/hud/tmux.d.ts.map +1 -1
- package/dist/hud/tmux.js +46 -9
- package/dist/hud/tmux.js.map +1 -1
- package/dist/question/deep-interview.d.ts +2 -0
- package/dist/question/deep-interview.d.ts.map +1 -1
- package/dist/question/deep-interview.js.map +1 -1
- package/dist/scripts/__tests__/codex-native-hook.test.js +387 -0
- package/dist/scripts/__tests__/codex-native-hook.test.js.map +1 -1
- package/dist/scripts/codex-native-hook.d.ts.map +1 -1
- package/dist/scripts/codex-native-hook.js +24 -2
- package/dist/scripts/codex-native-hook.js.map +1 -1
- package/dist/state/__tests__/planning-gate.test.d.ts +2 -0
- package/dist/state/__tests__/planning-gate.test.d.ts.map +1 -0
- package/dist/state/__tests__/planning-gate.test.js +219 -0
- package/dist/state/__tests__/planning-gate.test.js.map +1 -0
- package/dist/state/workflow-transition.d.ts +23 -0
- package/dist/state/workflow-transition.d.ts.map +1 -1
- package/dist/state/workflow-transition.js +63 -0
- package/dist/state/workflow-transition.js.map +1 -1
- package/dist/team/__tests__/tmux-session.test.js +86 -0
- package/dist/team/__tests__/tmux-session.test.js.map +1 -1
- package/dist/team/tmux-session.d.ts.map +1 -1
- package/dist/team/tmux-session.js +7 -0
- package/dist/team/tmux-session.js.map +1 -1
- package/package.json +1 -1
- package/plugins/oh-my-codex/.codex-plugin/plugin.json +1 -1
- package/plugins/oh-my-codex/skills/deep-interview/SKILL.md +10 -0
- package/plugins/oh-my-codex/skills/ralplan/SKILL.md +6 -2
- package/prompts/scholastic.md +11 -0
- package/skills/deep-interview/SKILL.md +10 -0
- package/skills/ralplan/SKILL.md +6 -2
- package/src/scripts/__tests__/codex-native-hook.test.ts +485 -0
- package/src/scripts/codex-native-hook.ts +23 -1
- package/templates/catalog-manifest.json +5 -0
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { spawn } from "child_process";
|
|
2
|
+
import { dirname } from "path";
|
|
3
|
+
import { homedir } from "os";
|
|
4
|
+
import { buildPlatformCommandSpec, classifySpawnError } from "../utils/platform-command.js";
|
|
5
|
+
import { readAuthConfig } from "./config.js";
|
|
6
|
+
import { isQuotaError } from "./quota-detector.js";
|
|
7
|
+
import { redactAuthSecrets } from "./redact.js";
|
|
8
|
+
import { buildRotationPlan, nextSlotAfter } from "./rotation.js";
|
|
9
|
+
import { findLatestRolloutSession } from "./sessions.js";
|
|
10
|
+
import { listSlots, markSlotQuota, readAuthMetadata, useSlot } from "./storage.js";
|
|
11
|
+
export function stripHotswapArg(args) {
|
|
12
|
+
return args.filter((arg) => arg !== "--hotswap");
|
|
13
|
+
}
|
|
14
|
+
async function runCodexDirect(cwd, args, env) {
|
|
15
|
+
const spec = buildPlatformCommandSpec("codex", args, process.platform, env);
|
|
16
|
+
return await new Promise((resolve, reject) => {
|
|
17
|
+
const child = spawn(spec.command, spec.args, {
|
|
18
|
+
cwd,
|
|
19
|
+
env,
|
|
20
|
+
stdio: ["inherit", "inherit", "pipe"],
|
|
21
|
+
...(process.platform === "win32" ? { windowsHide: true } : {}),
|
|
22
|
+
});
|
|
23
|
+
let stderr = "";
|
|
24
|
+
child.stderr?.on("data", (chunk) => {
|
|
25
|
+
const text = redactAuthSecrets(chunk.toString("utf-8"));
|
|
26
|
+
stderr += text;
|
|
27
|
+
process.stderr.write(text);
|
|
28
|
+
});
|
|
29
|
+
child.on("error", (error) => {
|
|
30
|
+
const kind = classifySpawnError(error);
|
|
31
|
+
if (kind === "missing") {
|
|
32
|
+
reject(new Error("failed to launch codex: executable not found in PATH"));
|
|
33
|
+
}
|
|
34
|
+
else if (kind === "blocked") {
|
|
35
|
+
reject(new Error(`failed to launch codex: executable is blocked (${error.code || "blocked"})`));
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
reject(error);
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
child.on("close", (status, signal) => {
|
|
42
|
+
resolve({ status: typeof status === "number" ? status : 1, signal, stderr });
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
export function buildResumeArgsWithPreservedFlags(originalArgs, sessionId) {
|
|
47
|
+
const preserved = [];
|
|
48
|
+
for (let index = 0; index < originalArgs.length; index++) {
|
|
49
|
+
const arg = originalArgs[index];
|
|
50
|
+
if (arg === "--")
|
|
51
|
+
break;
|
|
52
|
+
if (arg === "-c" || arg === "--config" || arg === "--model" || arg === "-m") {
|
|
53
|
+
preserved.push(arg);
|
|
54
|
+
const value = originalArgs[index + 1];
|
|
55
|
+
if (value && !value.startsWith("-")) {
|
|
56
|
+
preserved.push(value);
|
|
57
|
+
index += 1;
|
|
58
|
+
}
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
if (arg.startsWith("--config=") ||
|
|
62
|
+
arg.startsWith("--model=") ||
|
|
63
|
+
arg === "--dangerously-bypass-approvals-and-sandbox") {
|
|
64
|
+
preserved.push(arg);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return ["resume", sessionId, ...preserved];
|
|
68
|
+
}
|
|
69
|
+
function codexHomeFromAuthPath(authPath) {
|
|
70
|
+
return dirname(authPath);
|
|
71
|
+
}
|
|
72
|
+
function hotswapSessionId() {
|
|
73
|
+
return `omx-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
74
|
+
}
|
|
75
|
+
export async function runAuthHotswap(options) {
|
|
76
|
+
const cwd = options.cwd ?? process.cwd();
|
|
77
|
+
const env = options.env ?? process.env;
|
|
78
|
+
const home = options.home ?? homedir();
|
|
79
|
+
const lifecycle = options.lifecycle;
|
|
80
|
+
const rawArgs = stripHotswapArg(options.argv);
|
|
81
|
+
const notifyTempResult = lifecycle.resolveNotifyTempContract(rawArgs, env);
|
|
82
|
+
const normalizedArgs = lifecycle.normalizeCodexLaunchArgs(notifyTempResult.passthroughArgs.filter((arg) => arg !== "--direct" && arg !== "--tmux"));
|
|
83
|
+
const config = await readAuthConfig(cwd, home);
|
|
84
|
+
const slots = await listSlots(home);
|
|
85
|
+
if (slots.length === 0) {
|
|
86
|
+
process.stderr.write("[omx auth] no slots configured; run `omx auth add <slot>` first.\n");
|
|
87
|
+
return 1;
|
|
88
|
+
}
|
|
89
|
+
const sessionId = hotswapSessionId();
|
|
90
|
+
const prepared = await lifecycle.prepareCodexHomeForLaunch(cwd, sessionId, env);
|
|
91
|
+
const childCodexHome = prepared.codexHomeOverride || (env.CODEX_HOME && env.CODEX_HOME.trim()) || `${home}/.codex`;
|
|
92
|
+
const liveAuthPath = `${childCodexHome}/auth.json`;
|
|
93
|
+
const metadata = await readAuthMetadata(home);
|
|
94
|
+
const plan = buildRotationPlan(slots, config, metadata.currentSlot);
|
|
95
|
+
let currentSlot = plan.order[0];
|
|
96
|
+
if (!currentSlot) {
|
|
97
|
+
process.stderr.write("[omx auth] no slots configured; run `omx auth add <slot>` first.\n");
|
|
98
|
+
return 1;
|
|
99
|
+
}
|
|
100
|
+
const exhausted = new Set();
|
|
101
|
+
let resumeArgs = null;
|
|
102
|
+
try {
|
|
103
|
+
await useSlot(currentSlot, liveAuthPath, home);
|
|
104
|
+
await lifecycle.preLaunch(cwd, sessionId, notifyTempResult.contract, prepared.codexHomeOverride, true, false);
|
|
105
|
+
const baseEnv = {
|
|
106
|
+
...env,
|
|
107
|
+
...(prepared.codexHomeOverride ? { CODEX_HOME: prepared.codexHomeOverride } : {}),
|
|
108
|
+
...(prepared.sqliteHomeOverride ? { CODEX_SQLITE_HOME: prepared.sqliteHomeOverride } : {}),
|
|
109
|
+
};
|
|
110
|
+
const omxRoot = lifecycle.resolveOmxRootForLaunch(cwd, env);
|
|
111
|
+
if (omxRoot)
|
|
112
|
+
baseEnv.OMX_ROOT = omxRoot;
|
|
113
|
+
for (let attempt = 0; attempt < plan.order.length; attempt++) {
|
|
114
|
+
const attemptArgs = lifecycle.injectModelInstructionsBypassArgs(cwd, resumeArgs ?? normalizedArgs, baseEnv, lifecycle.sessionModelInstructionsPath(cwd, sessionId));
|
|
115
|
+
process.stderr.write(`[omx auth] using slot ${currentSlot}\n`);
|
|
116
|
+
const result = await runCodexDirect(cwd, attemptArgs, baseEnv);
|
|
117
|
+
if (result.status === 0)
|
|
118
|
+
return 0;
|
|
119
|
+
if (!isQuotaError({ status: result.status, signal: result.signal, stderr: result.stderr }, config)) {
|
|
120
|
+
return result.status || 1;
|
|
121
|
+
}
|
|
122
|
+
await markSlotQuota(currentSlot, home);
|
|
123
|
+
exhausted.add(currentSlot);
|
|
124
|
+
if (plan.mode === "manual") {
|
|
125
|
+
process.stderr.write(`[omx auth] quota detected for slot ${currentSlot}; rotation=manual, run \`omx auth use <slot>\` to switch accounts.\n`);
|
|
126
|
+
return 1;
|
|
127
|
+
}
|
|
128
|
+
const next = nextSlotAfter(plan.order, currentSlot, exhausted);
|
|
129
|
+
if (!next) {
|
|
130
|
+
process.stderr.write(`[omx auth] all slots exhausted: ${[...exhausted].join(", ")}\n`);
|
|
131
|
+
return 1;
|
|
132
|
+
}
|
|
133
|
+
const latest = await findLatestRolloutSession(codexHomeFromAuthPath(liveAuthPath), home);
|
|
134
|
+
if (!latest) {
|
|
135
|
+
process.stderr.write("[omx auth] quota detected but no Codex rollout session was found to resume.\n");
|
|
136
|
+
return 1;
|
|
137
|
+
}
|
|
138
|
+
currentSlot = next;
|
|
139
|
+
await useSlot(currentSlot, liveAuthPath, home);
|
|
140
|
+
resumeArgs = buildResumeArgsWithPreservedFlags(normalizedArgs, latest.id);
|
|
141
|
+
process.stderr.write(`[omx auth] quota detected; rotating to slot ${currentSlot} and resuming ${latest.id}\n`);
|
|
142
|
+
}
|
|
143
|
+
process.stderr.write(`[omx auth] all slots exhausted: ${plan.order.join(", ")}\n`);
|
|
144
|
+
return 1;
|
|
145
|
+
}
|
|
146
|
+
catch (err) {
|
|
147
|
+
process.stderr.write(`[omx auth] ${redactAuthSecrets(err)}\n`);
|
|
148
|
+
return 1;
|
|
149
|
+
}
|
|
150
|
+
finally {
|
|
151
|
+
await lifecycle.postLaunch(cwd, sessionId, prepared.codexHomeOverride, true, prepared.projectLocalCodexHomeForCleanup).catch((err) => {
|
|
152
|
+
process.stderr.write(`[omx auth] postLaunch warning: ${redactAuthSecrets(err)}\n`);
|
|
153
|
+
});
|
|
154
|
+
await lifecycle.cleanupRuntimeCodexHome(prepared.runtimeCodexHomeForCleanup, prepared.projectLocalCodexHomeForCleanup).catch((err) => {
|
|
155
|
+
process.stderr.write(`[omx auth] cleanup warning: ${redactAuthSecrets(err)}\n`);
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
//# sourceMappingURL=hotswap.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hotswap.js","sourceRoot":"","sources":["../../src/auth/hotswap.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,qBAAqB,CAAC;AACpC,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,qBAAqB,CAAC;AACpC,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export declare const AUTH_DIR_MODE = 448;
|
|
2
|
+
export declare const AUTH_FILE_MODE = 384;
|
|
3
|
+
export declare function resolveOmxAuthDir(home?: string): string;
|
|
4
|
+
export declare function resolveAuthMetadataPath(home?: string): string;
|
|
5
|
+
export declare function validateSlotName(slot: string): string;
|
|
6
|
+
export declare function resolveSlotPath(slot: string, home?: string): string;
|
|
7
|
+
export declare function resolveDefaultCodexHome(home?: string): string;
|
|
8
|
+
export declare function resolveLiveAuthPath(cwd?: string, env?: NodeJS.ProcessEnv, home?: string): string;
|
|
9
|
+
export declare function ensurePrivateDir(dir: string): Promise<void>;
|
|
10
|
+
export declare function assertReadableFile(path: string, label: string): Promise<void>;
|
|
11
|
+
export declare function assertNoSymlink(path: string, label: string): Promise<void>;
|
|
12
|
+
//# sourceMappingURL=paths.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/auth/paths.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,aAAa,MAAQ,CAAC;AACnC,eAAO,MAAM,cAAc,MAAQ,CAAC;AAEpC,wBAAgB,iBAAiB,CAAC,IAAI,SAAY,GAAG,MAAM,CAE1D;AAED,wBAAgB,uBAAuB,CAAC,IAAI,SAAY,GAAG,MAAM,CAEhE;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAWrD;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,SAAY,GAAG,MAAM,CAStE;AAED,wBAAgB,uBAAuB,CAAC,IAAI,SAAY,GAAG,MAAM,CAEhE;AAED,wBAAgB,mBAAmB,CACjC,GAAG,SAAgB,EACnB,GAAG,GAAE,MAAM,CAAC,UAAwB,EACpC,IAAI,SAAY,GACf,MAAM,CAGR;AAED,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CASjE;AAED,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAUnF;AAED,wBAAsB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAShF"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { homedir } from "os";
|
|
2
|
+
import { basename, join, resolve } from "path";
|
|
3
|
+
import { lstat, mkdir, stat } from "fs/promises";
|
|
4
|
+
import { resolveCodexHomeForLaunch } from "../cli/codex-home.js";
|
|
5
|
+
export const AUTH_DIR_MODE = 0o700;
|
|
6
|
+
export const AUTH_FILE_MODE = 0o600;
|
|
7
|
+
export function resolveOmxAuthDir(home = homedir()) {
|
|
8
|
+
return join(home, ".omx", "auth");
|
|
9
|
+
}
|
|
10
|
+
export function resolveAuthMetadataPath(home = homedir()) {
|
|
11
|
+
return join(resolveOmxAuthDir(home), "slots.json");
|
|
12
|
+
}
|
|
13
|
+
export function validateSlotName(slot) {
|
|
14
|
+
const trimmed = slot.trim();
|
|
15
|
+
if (!/^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/.test(trimmed)) {
|
|
16
|
+
throw new Error("invalid auth slot name: use 1-64 letters, numbers, '.', '_' or '-' and start with a letter or number");
|
|
17
|
+
}
|
|
18
|
+
if (trimmed === "." || trimmed === ".." || basename(trimmed) !== trimmed) {
|
|
19
|
+
throw new Error("invalid auth slot name: path traversal is not allowed");
|
|
20
|
+
}
|
|
21
|
+
return trimmed;
|
|
22
|
+
}
|
|
23
|
+
export function resolveSlotPath(slot, home = homedir()) {
|
|
24
|
+
const safeSlot = validateSlotName(slot);
|
|
25
|
+
const authDir = resolveOmxAuthDir(home);
|
|
26
|
+
const candidate = resolve(authDir, `${safeSlot}.json`);
|
|
27
|
+
const expected = join(resolve(authDir), `${safeSlot}.json`);
|
|
28
|
+
if (candidate !== expected) {
|
|
29
|
+
throw new Error("invalid auth slot path");
|
|
30
|
+
}
|
|
31
|
+
return candidate;
|
|
32
|
+
}
|
|
33
|
+
export function resolveDefaultCodexHome(home = homedir()) {
|
|
34
|
+
return join(home, ".codex");
|
|
35
|
+
}
|
|
36
|
+
export function resolveLiveAuthPath(cwd = process.cwd(), env = process.env, home = homedir()) {
|
|
37
|
+
const codexHome = resolveCodexHomeForLaunch(cwd, env) || resolveDefaultCodexHome(home);
|
|
38
|
+
return join(codexHome, "auth.json");
|
|
39
|
+
}
|
|
40
|
+
export async function ensurePrivateDir(dir) {
|
|
41
|
+
await mkdir(dir, { recursive: true, mode: AUTH_DIR_MODE });
|
|
42
|
+
const info = await lstat(dir);
|
|
43
|
+
if (info.isSymbolicLink())
|
|
44
|
+
throw new Error(`auth directory must not be a symlink: ${dir}`);
|
|
45
|
+
if (!info.isDirectory())
|
|
46
|
+
throw new Error(`auth path is not a directory: ${dir}`);
|
|
47
|
+
if (process.platform !== "win32") {
|
|
48
|
+
const { chmod } = await import("fs/promises");
|
|
49
|
+
await chmod(dir, AUTH_DIR_MODE).catch(() => undefined);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
export async function assertReadableFile(path, label) {
|
|
53
|
+
try {
|
|
54
|
+
const info = await stat(path);
|
|
55
|
+
if (!info.isFile())
|
|
56
|
+
throw new Error(`${label} is not a file: ${path}`);
|
|
57
|
+
}
|
|
58
|
+
catch (err) {
|
|
59
|
+
if (err && typeof err === "object" && "code" in err && err.code === "ENOENT") {
|
|
60
|
+
throw new Error(`${label} not found: ${path}`);
|
|
61
|
+
}
|
|
62
|
+
throw err;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
export async function assertNoSymlink(path, label) {
|
|
66
|
+
try {
|
|
67
|
+
const { lstat } = await import("fs/promises");
|
|
68
|
+
const info = await lstat(path);
|
|
69
|
+
if (info.isSymbolicLink())
|
|
70
|
+
throw new Error(`${label} must not be a symlink: ${path}`);
|
|
71
|
+
}
|
|
72
|
+
catch (err) {
|
|
73
|
+
if (err && typeof err === "object" && "code" in err && err.code === "ENOENT")
|
|
74
|
+
return;
|
|
75
|
+
throw err;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/auth/paths.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { AuthConfig } from "./config.js";
|
|
2
|
+
export interface CodexExitSignal {
|
|
3
|
+
status?: number | null;
|
|
4
|
+
signal?: NodeJS.Signals | null;
|
|
5
|
+
stderr?: string;
|
|
6
|
+
stdout?: string;
|
|
7
|
+
structuredError?: unknown;
|
|
8
|
+
}
|
|
9
|
+
export declare function isQuotaError(signal: CodexExitSignal, config?: Pick<AuthConfig, "quotaPatterns">): boolean;
|
|
10
|
+
//# sourceMappingURL=quota-detector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quota-detector.d.ts","sourceRoot":"","sources":["../../src/auth/quota-detector.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C,MAAM,WAAW,eAAe;IAC9B,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAsBD,wBAAgB,YAAY,CAAC,MAAM,EAAE,eAAe,EAAE,MAAM,CAAC,EAAE,IAAI,CAAC,UAAU,EAAE,eAAe,CAAC,GAAG,OAAO,CAezG"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
const DEFAULT_PATTERNS = [
|
|
2
|
+
/\b429\b/i,
|
|
3
|
+
/\bquota\b/i,
|
|
4
|
+
/rate\s*limit(?:ed|s)?/i,
|
|
5
|
+
/too\s+many\s+requests/i,
|
|
6
|
+
];
|
|
7
|
+
function structuredText(value) {
|
|
8
|
+
if (!value)
|
|
9
|
+
return "";
|
|
10
|
+
if (typeof value === "string")
|
|
11
|
+
return value;
|
|
12
|
+
if (typeof value === "object") {
|
|
13
|
+
const record = value;
|
|
14
|
+
const status = record.status ?? record.statusCode ?? record.code ?? "";
|
|
15
|
+
const type = record.type ?? record.error ?? "";
|
|
16
|
+
const message = record.message ?? "";
|
|
17
|
+
return `${status} ${type} ${message}`;
|
|
18
|
+
}
|
|
19
|
+
return String(value);
|
|
20
|
+
}
|
|
21
|
+
export function isQuotaError(signal, config) {
|
|
22
|
+
const haystack = [
|
|
23
|
+
structuredText(signal.structuredError),
|
|
24
|
+
signal.stderr ?? "",
|
|
25
|
+
signal.stdout ?? "",
|
|
26
|
+
].join("\n");
|
|
27
|
+
if (!haystack.trim())
|
|
28
|
+
return false;
|
|
29
|
+
if (DEFAULT_PATTERNS.some((pattern) => pattern.test(haystack)))
|
|
30
|
+
return true;
|
|
31
|
+
return (config?.quotaPatterns ?? []).some((pattern) => {
|
|
32
|
+
try {
|
|
33
|
+
return new RegExp(pattern, "i").test(haystack);
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
return haystack.toLowerCase().includes(pattern.toLowerCase());
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=quota-detector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quota-detector.js","sourceRoot":"","sources":["../../src/auth/quota-detector.ts"],"names":[],"mappings":"AAUA,MAAM,gBAAgB,GAAG;IACvB,UAAU;IACV,YAAY;IACZ,wBAAwB;IACxB,wBAAwB;CACzB,CAAC;AAEF,SAAS,cAAc,CAAC,KAAc;IACpC,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,CAAC;IACtB,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC5C,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,MAAM,MAAM,GAAG,KAAgC,CAAC;QAChD,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,UAAU,IAAI,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;QACvE,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC;QAC/C,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC;QACrC,OAAO,GAAG,MAAM,IAAI,IAAI,IAAI,OAAO,EAAE,CAAC;IACxC,CAAC;IACD,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;AACvB,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,MAAuB,EAAE,MAA0C;IAC9F,MAAM,QAAQ,GAAG;QACf,cAAc,CAAC,MAAM,CAAC,eAAe,CAAC;QACtC,MAAM,CAAC,MAAM,IAAI,EAAE;QACnB,MAAM,CAAC,MAAM,IAAI,EAAE;KACpB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACb,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE;QAAE,OAAO,KAAK,CAAC;IACnC,IAAI,gBAAgB,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IAC5E,OAAO,CAAC,MAAM,EAAE,aAAa,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE;QACpD,IAAI,CAAC;YACH,OAAO,IAAI,MAAM,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACjD,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,QAAQ,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;QAChE,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redact.d.ts","sourceRoot":"","sources":["../../src/auth/redact.ts"],"names":[],"mappings":"AAUA,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAcxD"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
const JSON_OAUTH_TOKEN_FIELD_PATTERN = /(["'](?:access_token|refresh_token|id_token)["']\s*:\s*)(["'])(?:\\.|(?!\2)[^\\])*\2/gi;
|
|
2
|
+
const SECRET_PATTERNS = [
|
|
3
|
+
JSON_OAUTH_TOKEN_FIELD_PATTERN,
|
|
4
|
+
/\b(?:access|refresh|id)_token\b\s*[:=]\s*["']?[^"'\s,}]+/gi,
|
|
5
|
+
/\bbearer\s+[A-Za-z0-9._~+/=-]+/gi,
|
|
6
|
+
/\bsk-[A-Za-z0-9_-]{8,}\b/g,
|
|
7
|
+
/\b(?:session|auth|api)[_-]?token\b\s*[:=]\s*["']?[^"'\s,}]+/gi,
|
|
8
|
+
];
|
|
9
|
+
export function redactAuthSecrets(value) {
|
|
10
|
+
let text = value instanceof Error ? value.message : String(value);
|
|
11
|
+
for (const pattern of SECRET_PATTERNS) {
|
|
12
|
+
text = text.replace(pattern, (match) => {
|
|
13
|
+
if (pattern === JSON_OAUTH_TOKEN_FIELD_PATTERN) {
|
|
14
|
+
return match.replace(/(:\s*)(["']).*\2$/s, "$1$2[REDACTED]$2");
|
|
15
|
+
}
|
|
16
|
+
const separator = match.match(/[:=]/)?.[0];
|
|
17
|
+
if (separator)
|
|
18
|
+
return `${match.slice(0, match.indexOf(separator) + 1)} [REDACTED]`;
|
|
19
|
+
if (/^bearer\s/i.test(match))
|
|
20
|
+
return "Bearer [REDACTED]";
|
|
21
|
+
return "[REDACTED]";
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
return text;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=redact.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redact.js","sourceRoot":"","sources":["../../src/auth/redact.ts"],"names":[],"mappings":"AAAA,MAAM,8BAA8B,GAAG,wFAAwF,CAAC;AAEhI,MAAM,eAAe,GAAa;IAChC,8BAA8B;IAC9B,4DAA4D;IAC5D,kCAAkC;IAClC,2BAA2B;IAC3B,+DAA+D;CAChE,CAAC;AAEF,MAAM,UAAU,iBAAiB,CAAC,KAAc;IAC9C,IAAI,IAAI,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAClE,KAAK,MAAM,OAAO,IAAI,eAAe,EAAE,CAAC;QACtC,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;YACrC,IAAI,OAAO,KAAK,8BAA8B,EAAE,CAAC;gBAC/C,OAAO,KAAK,CAAC,OAAO,CAAC,oBAAoB,EAAE,kBAAkB,CAAC,CAAC;YACjE,CAAC;YACD,MAAM,SAAS,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;YAC3C,IAAI,SAAS;gBAAE,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,aAAa,CAAC;YACnF,IAAI,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC;gBAAE,OAAO,mBAAmB,CAAC;YACzD,OAAO,YAAY,CAAC;QACtB,CAAC,CAAC,CAAC;IACL,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { AuthConfig } from "./config.js";
|
|
2
|
+
import type { AuthSlotRecord } from "./storage.js";
|
|
3
|
+
export interface RotationPlan {
|
|
4
|
+
mode: AuthConfig["rotation"];
|
|
5
|
+
order: string[];
|
|
6
|
+
}
|
|
7
|
+
export declare function buildRotationPlan(slots: AuthSlotRecord[], config: Pick<AuthConfig, "rotation" | "priority">, currentSlot?: string): RotationPlan;
|
|
8
|
+
export declare function nextSlotAfter(order: string[], current: string | undefined, exhausted: Set<string>): string | undefined;
|
|
9
|
+
//# sourceMappingURL=rotation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rotation.d.ts","sourceRoot":"","sources":["../../src/auth/rotation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAEnD,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,UAAU,CAAC,UAAU,CAAC,CAAC;IAC7B,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,cAAc,EAAE,EACvB,MAAM,EAAE,IAAI,CAAC,UAAU,EAAE,UAAU,GAAG,UAAU,CAAC,EACjD,WAAW,CAAC,EAAE,MAAM,GACnB,YAAY,CAWd;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,MAAM,GAAG,SAAS,EAAE,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,MAAM,GAAG,SAAS,CAQtH"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export function buildRotationPlan(slots, config, currentSlot) {
|
|
2
|
+
const available = slots.map((slot) => slot.slot).sort((a, b) => a.localeCompare(b));
|
|
3
|
+
if (config.rotation === "manual")
|
|
4
|
+
return { mode: "manual", order: currentSlot ? [currentSlot] : available.slice(0, 1) };
|
|
5
|
+
if (config.rotation === "priority") {
|
|
6
|
+
const priority = config.priority.filter((slot) => available.includes(slot));
|
|
7
|
+
const rest = available.filter((slot) => !priority.includes(slot));
|
|
8
|
+
return { mode: "priority", order: [...priority, ...rest] };
|
|
9
|
+
}
|
|
10
|
+
if (!currentSlot || !available.includes(currentSlot))
|
|
11
|
+
return { mode: "round-robin", order: available };
|
|
12
|
+
const index = available.indexOf(currentSlot);
|
|
13
|
+
return { mode: "round-robin", order: [...available.slice(index), ...available.slice(0, index)] };
|
|
14
|
+
}
|
|
15
|
+
export function nextSlotAfter(order, current, exhausted) {
|
|
16
|
+
if (order.length === 0)
|
|
17
|
+
return undefined;
|
|
18
|
+
const start = current && order.includes(current) ? order.indexOf(current) + 1 : 0;
|
|
19
|
+
for (let offset = 0; offset < order.length; offset++) {
|
|
20
|
+
const slot = order[(start + offset) % order.length];
|
|
21
|
+
if (!exhausted.has(slot))
|
|
22
|
+
return slot;
|
|
23
|
+
}
|
|
24
|
+
return undefined;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=rotation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rotation.js","sourceRoot":"","sources":["../../src/auth/rotation.ts"],"names":[],"mappings":"AAQA,MAAM,UAAU,iBAAiB,CAC/B,KAAuB,EACvB,MAAiD,EACjD,WAAoB;IAEpB,MAAM,SAAS,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;IACpF,IAAI,MAAM,CAAC,QAAQ,KAAK,QAAQ;QAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;IACxH,IAAI,MAAM,CAAC,QAAQ,KAAK,UAAU,EAAE,CAAC;QACnC,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;QAC5E,MAAM,IAAI,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;QAClE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,GAAG,QAAQ,EAAE,GAAG,IAAI,CAAC,EAAE,CAAC;IAC7D,CAAC;IACD,IAAI,CAAC,WAAW,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,WAAW,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;IACvG,MAAM,KAAK,GAAG,SAAS,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IAC7C,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,CAAC,GAAG,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC;AACnG,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,KAAe,EAAE,OAA2B,EAAE,SAAsB;IAChG,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IACzC,MAAM,KAAK,GAAG,OAAO,IAAI,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAClF,KAAK,IAAI,MAAM,GAAG,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC;QACrD,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,KAAK,GAAG,MAAM,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC;QACpD,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC;IACxC,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface LatestRolloutSession {
|
|
2
|
+
id: string;
|
|
3
|
+
path: string;
|
|
4
|
+
mtimeMs: number;
|
|
5
|
+
}
|
|
6
|
+
export declare function extractRolloutSessionId(path: string): Promise<string>;
|
|
7
|
+
/**
|
|
8
|
+
* Codex stores resumable conversations as rollout JSONL files under
|
|
9
|
+
* <CODEX_HOME>/sessions/YYYY/MM/DD/rollout-*.jsonl. Hotswap uses the newest
|
|
10
|
+
* rollout by mtime as the best available continuity heuristic after a quota
|
|
11
|
+
* exit, because upstream Codex does not currently expose the active resume id
|
|
12
|
+
* as a stable structured wrapper signal.
|
|
13
|
+
*/
|
|
14
|
+
export declare function findLatestRolloutSession(codexHome: string, fallbackHome?: string): Promise<LatestRolloutSession | null>;
|
|
15
|
+
//# sourceMappingURL=sessions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sessions.d.ts","sourceRoot":"","sources":["../../src/auth/sessions.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAeD,wBAAsB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAY3E;AAED;;;;;;GAMG;AACH,wBAAsB,wBAAwB,CAC5C,SAAS,EAAE,MAAM,EACjB,YAAY,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC,CActC"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { existsSync } from "fs";
|
|
2
|
+
import { readdir, stat, readFile } from "fs/promises";
|
|
3
|
+
import { basename, join } from "path";
|
|
4
|
+
import { resolveDefaultCodexHome } from "./paths.js";
|
|
5
|
+
async function collectRollouts(dir, out) {
|
|
6
|
+
if (!existsSync(dir))
|
|
7
|
+
return;
|
|
8
|
+
const entries = await readdir(dir, { withFileTypes: true }).catch(() => []);
|
|
9
|
+
for (const entry of entries) {
|
|
10
|
+
const path = join(dir, entry.name);
|
|
11
|
+
if (entry.isDirectory()) {
|
|
12
|
+
await collectRollouts(path, out);
|
|
13
|
+
}
|
|
14
|
+
else if (entry.isFile() && /^rollout-.+\.jsonl$/.test(entry.name)) {
|
|
15
|
+
out.push(path);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export async function extractRolloutSessionId(path) {
|
|
20
|
+
const fileMatch = basename(path).match(/^rollout-(.+)\.jsonl$/);
|
|
21
|
+
if (fileMatch?.[1])
|
|
22
|
+
return fileMatch[1];
|
|
23
|
+
const firstLine = (await readFile(path, "utf-8")).split(/\r?\n/, 1)[0] ?? "";
|
|
24
|
+
try {
|
|
25
|
+
const parsed = JSON.parse(firstLine);
|
|
26
|
+
const id = parsed.id ?? parsed.session_id ?? parsed.sessionId;
|
|
27
|
+
if (typeof id === "string" && id.trim())
|
|
28
|
+
return id.trim();
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
// fall through to basename fallback
|
|
32
|
+
}
|
|
33
|
+
return basename(path, ".jsonl").replace(/^rollout-/, "");
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Codex stores resumable conversations as rollout JSONL files under
|
|
37
|
+
* <CODEX_HOME>/sessions/YYYY/MM/DD/rollout-*.jsonl. Hotswap uses the newest
|
|
38
|
+
* rollout by mtime as the best available continuity heuristic after a quota
|
|
39
|
+
* exit, because upstream Codex does not currently expose the active resume id
|
|
40
|
+
* as a stable structured wrapper signal.
|
|
41
|
+
*/
|
|
42
|
+
export async function findLatestRolloutSession(codexHome, fallbackHome) {
|
|
43
|
+
const roots = [join(codexHome, "sessions")];
|
|
44
|
+
const fallback = fallbackHome ? join(resolveDefaultCodexHome(fallbackHome), "sessions") : undefined;
|
|
45
|
+
if (fallback && fallback !== roots[0])
|
|
46
|
+
roots.push(fallback);
|
|
47
|
+
const files = [];
|
|
48
|
+
for (const root of roots)
|
|
49
|
+
await collectRollouts(root, files);
|
|
50
|
+
let latest = null;
|
|
51
|
+
for (const path of files) {
|
|
52
|
+
const info = await stat(path).catch(() => null);
|
|
53
|
+
if (!info?.isFile())
|
|
54
|
+
continue;
|
|
55
|
+
if (!latest || info.mtimeMs > latest.mtimeMs)
|
|
56
|
+
latest = { path, mtimeMs: info.mtimeMs };
|
|
57
|
+
}
|
|
58
|
+
if (!latest)
|
|
59
|
+
return null;
|
|
60
|
+
return { id: await extractRolloutSessionId(latest.path), path: latest.path, mtimeMs: latest.mtimeMs };
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=sessions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sessions.js","sourceRoot":"","sources":["../../src/auth/sessions.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export interface AuthSlotRecord {
|
|
2
|
+
slot: string;
|
|
3
|
+
createdAt: string;
|
|
4
|
+
updatedAt: string;
|
|
5
|
+
lastUsedAt?: string;
|
|
6
|
+
lastQuotaAt?: string;
|
|
7
|
+
exhaustedAt?: string;
|
|
8
|
+
}
|
|
9
|
+
export interface AuthMetadata {
|
|
10
|
+
version: 1;
|
|
11
|
+
currentSlot?: string;
|
|
12
|
+
slots: AuthSlotRecord[];
|
|
13
|
+
}
|
|
14
|
+
export interface AtomicWriteOptions {
|
|
15
|
+
mode?: number;
|
|
16
|
+
beforeRename?: (tempPath: string) => void | Promise<void>;
|
|
17
|
+
}
|
|
18
|
+
export declare function atomicWriteFile(targetPath: string, data: string | Buffer, options?: AtomicWriteOptions): Promise<void>;
|
|
19
|
+
export declare function emptyMetadata(): AuthMetadata;
|
|
20
|
+
export declare function readAuthMetadata(home?: string): Promise<AuthMetadata>;
|
|
21
|
+
export declare function writeAuthMetadata(metadata: AuthMetadata, home?: string): Promise<void>;
|
|
22
|
+
export declare function addSlotFromAuthFile(slot: string, liveAuthPath: string, home?: string, now?: Date): Promise<AuthSlotRecord>;
|
|
23
|
+
export declare function listSlots(home?: string): Promise<AuthSlotRecord[]>;
|
|
24
|
+
export declare function useSlot(slot: string, liveAuthPath: string, home?: string, now?: Date): Promise<AuthSlotRecord>;
|
|
25
|
+
export declare function markSlotQuota(slot: string, home?: string, now?: Date): Promise<AuthMetadata>;
|
|
26
|
+
export declare function clearSlotExhaustion(slot: string, home?: string): Promise<void>;
|
|
27
|
+
//# sourceMappingURL=storage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../src/auth/storage.ts"],"names":[],"mappings":"AAeA,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,CAAC,CAAC;IACX,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,cAAc,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3D;AAED,wBAAsB,eAAe,CACnC,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,GAAG,MAAM,EACrB,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,IAAI,CAAC,CAef;AAED,wBAAgB,aAAa,IAAI,YAAY,CAE5C;AAED,wBAAsB,gBAAgB,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAa3E;AAED,wBAAsB,iBAAiB,CAAC,QAAQ,EAAE,YAAY,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAM5F;AAeD,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,MAAM,EACZ,YAAY,EAAE,MAAM,EACpB,IAAI,CAAC,EAAE,MAAM,EACb,GAAG,OAAa,GACf,OAAO,CAAC,cAAc,CAAC,CAWzB;AAED,wBAAsB,SAAS,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAGxE;AAED,wBAAsB,OAAO,CAC3B,IAAI,EAAE,MAAM,EACZ,YAAY,EAAE,MAAM,EACpB,IAAI,CAAC,EAAE,MAAM,EACb,GAAG,OAAa,GACf,OAAO,CAAC,cAAc,CAAC,CAezB;AAED,wBAAsB,aAAa,CACjC,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE,MAAM,EACb,GAAG,OAAa,GACf,OAAO,CAAC,YAAY,CAAC,CAQvB;AAED,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAOpF"}
|