codex-multi-auth 0.1.5 → 0.1.8
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/LICENSE +21 -1
- package/README.md +19 -6
- package/assets/readme-hero.svg +31 -31
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/lib/codex-cli/state.js +4 -4
- package/dist/lib/codex-cli/state.js.map +1 -1
- package/dist/lib/codex-cli/sync.d.ts +9 -16
- package/dist/lib/codex-cli/sync.d.ts.map +1 -1
- package/dist/lib/codex-cli/sync.js +51 -284
- package/dist/lib/codex-cli/sync.js.map +1 -1
- package/dist/lib/codex-cli/writer.d.ts.map +1 -1
- package/dist/lib/codex-cli/writer.js +62 -5
- package/dist/lib/codex-cli/writer.js.map +1 -1
- package/dist/lib/codex-manager/settings-hub.d.ts +44 -2
- package/dist/lib/codex-manager/settings-hub.d.ts.map +1 -1
- package/dist/lib/codex-manager/settings-hub.js +746 -117
- package/dist/lib/codex-manager/settings-hub.js.map +1 -1
- package/dist/lib/codex-manager.d.ts.map +1 -1
- package/dist/lib/codex-manager.js +3 -8
- package/dist/lib/codex-manager.js.map +1 -1
- package/dist/lib/context-overflow.js +10 -10
- package/dist/lib/named-backup-export.d.ts +69 -0
- package/dist/lib/named-backup-export.d.ts.map +1 -0
- package/dist/lib/named-backup-export.js +207 -0
- package/dist/lib/named-backup-export.js.map +1 -0
- package/dist/lib/oauth-success.html +66 -210
- package/dist/lib/oc-chatgpt-import-adapter.d.ts +64 -0
- package/dist/lib/oc-chatgpt-import-adapter.d.ts.map +1 -0
- package/dist/lib/oc-chatgpt-import-adapter.js +506 -0
- package/dist/lib/oc-chatgpt-import-adapter.js.map +1 -0
- package/dist/lib/oc-chatgpt-orchestrator.d.ts +80 -0
- package/dist/lib/oc-chatgpt-orchestrator.d.ts.map +1 -0
- package/dist/lib/oc-chatgpt-orchestrator.js +130 -0
- package/dist/lib/oc-chatgpt-orchestrator.js.map +1 -0
- package/dist/lib/oc-chatgpt-target-detection.d.ts +59 -0
- package/dist/lib/oc-chatgpt-target-detection.d.ts.map +1 -0
- package/dist/lib/oc-chatgpt-target-detection.js +327 -0
- package/dist/lib/oc-chatgpt-target-detection.js.map +1 -0
- package/dist/lib/prompts/codex.js +2 -2
- package/dist/lib/runtime-paths.d.ts.map +1 -1
- package/dist/lib/runtime-paths.js +44 -2
- package/dist/lib/runtime-paths.js.map +1 -1
- package/dist/lib/storage.d.ts +42 -3
- package/dist/lib/storage.d.ts.map +1 -1
- package/dist/lib/storage.js +634 -49
- package/dist/lib/storage.js.map +1 -1
- package/dist/lib/ui/auth-menu.d.ts.map +1 -1
- package/dist/lib/ui/auth-menu.js +13 -1
- package/dist/lib/ui/auth-menu.js.map +1 -1
- package/dist/lib/ui/copy.d.ts +15 -1
- package/dist/lib/ui/copy.d.ts.map +1 -1
- package/dist/lib/ui/copy.js +15 -1
- package/dist/lib/ui/copy.js.map +1 -1
- package/node_modules/@codex-ai/plugin/dist/index.d.ts +1 -1
- package/node_modules/@codex-ai/plugin/dist/tool.d.ts +41 -41
- package/node_modules/@codex-ai/plugin/dist/tool.js +28 -28
- package/package.json +132 -133
- package/scripts/bench-format/hashline-v2.mjs +642 -642
- package/scripts/bench-format/render.mjs +496 -496
- package/scripts/bench-format/stats.mjs +54 -54
- package/scripts/bench-format/tasks.mjs +151 -151
- package/scripts/benchmark-render-dashboard.mjs +49 -49
- package/scripts/codex-multi-auth.js +12 -0
- package/scripts/codex.js +315 -2
- package/scripts/install-codex-auth.js +9 -9
- package/scripts/test-all-models.sh +7 -7
- package/scripts/test-model-matrix.js +247 -148
- package/scripts/validate-model-map.sh +7 -7
- package/vendor/codex-ai-plugin/dist/index.d.ts +1 -1
- package/vendor/codex-ai-plugin/dist/tool.d.ts +41 -41
- package/vendor/codex-ai-plugin/dist/tool.js +28 -28
- package/vendor/codex-ai-sdk/dist/index.d.ts +3 -3
|
@@ -32,16 +32,16 @@ export function isContextOverflowError(status, bodyText) {
|
|
|
32
32
|
/**
|
|
33
33
|
* The message shown to users when context overflow occurs
|
|
34
34
|
*/
|
|
35
|
-
const CONTEXT_OVERFLOW_MESSAGE = `[Plugin Notice] Context is too long for this model.
|
|
36
|
-
|
|
37
|
-
Please use one of these commands to reduce context size:
|
|
38
|
-
|
|
39
|
-
• **/compact** - Compress conversation history (recommended)
|
|
40
|
-
• **/clear** - Start fresh with empty context
|
|
41
|
-
• **/undo** - Remove recent messages
|
|
42
|
-
|
|
43
|
-
Then retry your request.
|
|
44
|
-
|
|
35
|
+
const CONTEXT_OVERFLOW_MESSAGE = `[Plugin Notice] Context is too long for this model.
|
|
36
|
+
|
|
37
|
+
Please use one of these commands to reduce context size:
|
|
38
|
+
|
|
39
|
+
• **/compact** - Compress conversation history (recommended)
|
|
40
|
+
• **/clear** - Start fresh with empty context
|
|
41
|
+
• **/undo** - Remove recent messages
|
|
42
|
+
|
|
43
|
+
Then retry your request.
|
|
44
|
+
|
|
45
45
|
Alternatively, you can switch to a model with a larger context window.`;
|
|
46
46
|
/**
|
|
47
47
|
* Creates a synthetic SSE response for context overflow errors.
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
export interface NamedBackupExportDependencies {
|
|
2
|
+
getStoragePath: () => string;
|
|
3
|
+
exportAccounts: (filePath: string, force?: boolean, beforeCommit?: (resolvedPath: string) => Promise<void> | void) => Promise<void>;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Validate and normalize a user-provided backup name into a safe `<name>.json` filename.
|
|
7
|
+
*
|
|
8
|
+
* Performs trimming, rejects path separators and traversal tokens, forbids rotation-style
|
|
9
|
+
* substrings and temporary suffixes, and enforces that the base name contains only
|
|
10
|
+
* letters, numbers, hyphens, and underscores. Checks that a resulting base name is non-empty
|
|
11
|
+
* and returns the base name with a `.json` extension appended.
|
|
12
|
+
*
|
|
13
|
+
* Notes:
|
|
14
|
+
* - Validation checks that are sensitive to case are performed using a lowercased form;
|
|
15
|
+
* this mirrors Windows case-insensitive filesystem behavior for prohibited patterns.
|
|
16
|
+
* - The function is synchronous and safe for concurrent use (pure string validation/normalization).
|
|
17
|
+
* - Token redaction: traversal tokens (`..`), path separators, rotation-style substrings,
|
|
18
|
+
* and temporary suffixes are rejected rather than sanitized.
|
|
19
|
+
*
|
|
20
|
+
* @param name - The user-provided filename or identifier (may include a `.json` extension)
|
|
21
|
+
* @returns The validated filename with a `.json` extension appended
|
|
22
|
+
* @throws Error if the name is empty, contains separators or traversal tokens, contains
|
|
23
|
+
* prohibited substrings, ends with an invalid temporary suffix, contains disallowed
|
|
24
|
+
* characters, or would result in an empty base name
|
|
25
|
+
*/
|
|
26
|
+
export declare function normalizeNamedBackupFileName(name: string): string;
|
|
27
|
+
/**
|
|
28
|
+
* Compute the absolute path for the "backups" directory placed alongside the given storage path.
|
|
29
|
+
*
|
|
30
|
+
* This performs only path resolution and string manipulation; it does not access the filesystem and is insensitive to concurrent filesystem changes. It does not redact or sanitize tokens or sensitive substrings in `storagePath`. Note: other functions in this module handle Windows case-insensitive comparisons when validating paths.
|
|
31
|
+
*
|
|
32
|
+
* @param storagePath - Storage file or directory path (may be relative or absolute)
|
|
33
|
+
* @returns The resolved path to the backups directory adjacent to `storagePath` (i.e. dirname(storagePath)/backups)
|
|
34
|
+
*/
|
|
35
|
+
export declare function getNamedBackupRoot(storagePath: string): string;
|
|
36
|
+
/**
|
|
37
|
+
* Resolve and validate a safe backup file path for a named backup inside the storage path's backups directory.
|
|
38
|
+
*
|
|
39
|
+
* @param name - User-provided backup name; will be normalized and validated (disallows path separators, `..`, prohibited substrings, and invalid suffixes such as `.tmp`/`.wal`) and the canonical filename (`*.json`) will be produced.
|
|
40
|
+
* @param storagePath - Base storage path used to locate the backups directory; path comparisons treat Windows paths case-insensitively.
|
|
41
|
+
* @returns The absolute, validated path to the backup file within the backups directory.
|
|
42
|
+
*
|
|
43
|
+
* Concurrency: this function only computes and validates the path and does not create files or directories; callers must handle concurrent filesystem operations (e.g., directory creation or file writes).
|
|
44
|
+
*/
|
|
45
|
+
export declare function resolveNamedBackupPath(name: string, storagePath: string): string;
|
|
46
|
+
/**
|
|
47
|
+
* Create a named backup file inside the storage path's backups directory and return its resolved path.
|
|
48
|
+
*
|
|
49
|
+
* The provided `name` is validated and normalized (suffix, allowed characters, and prohibited substrings) and the
|
|
50
|
+
* backup root directory is created if missing. The export operation will be asked to write to the resolved path; a
|
|
51
|
+
* safety check ensures the final resolved path stays within the backups root.
|
|
52
|
+
* The delegated `beforeCommit` hook re-validates containment immediately before
|
|
53
|
+
* the storage layer commits the final rename, but callers should still serialize
|
|
54
|
+
* backup-root mutations rather than relying on path checks alone.
|
|
55
|
+
*
|
|
56
|
+
* Concurrency: callers should avoid concurrent exports that target the same `name` as behavior is unspecified.
|
|
57
|
+
* Windows behavior: file-name/path comparisons are case-insensitive and names are normalized to lowercase.
|
|
58
|
+
* Token rules: input `name` is checked to prevent path traversal, separators, rotation-style substrings, and certain
|
|
59
|
+
* invalid suffixes (e.g., `.tmp`, `.wal`); the final returned path always includes the `.json` extension.
|
|
60
|
+
*
|
|
61
|
+
* @param name - The desired backup file name (validated and normalized).
|
|
62
|
+
* @param dependencies - Object providing storage path resolution and the exportAccounts implementation.
|
|
63
|
+
* @param options.force - When true, request overwriting an existing backup.
|
|
64
|
+
* @returns The absolute path to the created backup file (including `.json`).
|
|
65
|
+
*/
|
|
66
|
+
export declare function exportNamedBackupFile(name: string, dependencies: NamedBackupExportDependencies, options?: {
|
|
67
|
+
force?: boolean;
|
|
68
|
+
}): Promise<string>;
|
|
69
|
+
//# sourceMappingURL=named-backup-export.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"named-backup-export.d.ts","sourceRoot":"","sources":["../../lib/named-backup-export.ts"],"names":[],"mappings":"AAoBA,MAAM,WAAW,6BAA6B;IAC7C,cAAc,EAAE,MAAM,MAAM,CAAC;IAC7B,cAAc,EAAE,CACf,QAAQ,EAAE,MAAM,EAChB,KAAK,CAAC,EAAE,OAAO,EACf,YAAY,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,KACzD,OAAO,CAAC,IAAI,CAAC,CAAC;CACnB;AA6ED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAwCjE;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAK9D;AAED;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CACrC,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,GACjB,MAAM,CAMR;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,qBAAqB,CAC1C,IAAI,EAAE,MAAM,EACZ,YAAY,EAAE,6BAA6B,EAC3C,OAAO,CAAC,EAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,GAC3B,OAAO,CAAC,MAAM,CAAC,CAuBjB"}
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import { existsSync, promises as fs, lstatSync, realpathSync } from "node:fs";
|
|
2
|
+
import { basename, dirname, isAbsolute, join, relative, resolve, } from "node:path";
|
|
3
|
+
import { resolvePath } from "./storage/paths.js";
|
|
4
|
+
const BACKUP_EXPORT_DIR_NAME = "backups";
|
|
5
|
+
const BACKUP_FILE_EXTENSION = ".json";
|
|
6
|
+
const BACKUP_SAFE_NAME_REGEX = /^[a-zA-Z0-9_-]+$/;
|
|
7
|
+
const BACKUP_WINDOWS_RESERVED_NAME_REGEX = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])$/i;
|
|
8
|
+
const BACKUP_INVALID_SUFFIXES = [".tmp", ".wal"];
|
|
9
|
+
const BACKUP_PROHIBITED_SUBSTRINGS = [".rotate."];
|
|
10
|
+
const inFlightNamedBackupExports = new Set();
|
|
11
|
+
/**
|
|
12
|
+
* Compute a canonical, comparison-ready filesystem path for the given input.
|
|
13
|
+
*
|
|
14
|
+
* Resolves the input to an absolute path, resolves symlinks (realpath) if the path exists, and on Windows converts the resulting canonical path to lowercase for case-insensitive comparisons. The function does not mask or redact any sensitive tokens contained in the path. Note: the returned value may become stale if the filesystem changes after this call (race conditions are possible).
|
|
15
|
+
*
|
|
16
|
+
* @param pathValue - The input filesystem path to normalize.
|
|
17
|
+
* @returns The canonicalized path suitable for equality or containment comparisons; on Windows the result is returned in lowercase.
|
|
18
|
+
*/
|
|
19
|
+
function normalizePathForComparison(pathValue) {
|
|
20
|
+
const resolvedPath = resolve(pathValue);
|
|
21
|
+
const canonicalPath = existsSync(resolvedPath)
|
|
22
|
+
? realpathSync(resolvedPath)
|
|
23
|
+
: resolvedPath;
|
|
24
|
+
return process.platform === "win32"
|
|
25
|
+
? canonicalPath.toLowerCase()
|
|
26
|
+
: canonicalPath;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Ensures the resolved target path is located inside the resolved base directory.
|
|
30
|
+
*
|
|
31
|
+
* Validates that `baseDir` is not a symbolic link and that the canonical/resolved
|
|
32
|
+
* forms of `baseDir` and `targetPath` keep `targetPath` rooted under `baseDir`.
|
|
33
|
+
* On Windows, comparisons are performed in a case-insensitive manner via the
|
|
34
|
+
* normalization helper. Errors do not include the original path values.
|
|
35
|
+
*
|
|
36
|
+
* Concurrency: callers must avoid concurrently mutating the filesystem (for example
|
|
37
|
+
* creating/removing/moving symlinks or directories) between calling this function
|
|
38
|
+
* and any subsequent operations that rely on its result. `exportNamedBackupFile`
|
|
39
|
+
* performs a second containment check through the `beforeCommit` hook, but that
|
|
40
|
+
* revalidation narrows rather than eliminates time-of-check/time-of-use windows.
|
|
41
|
+
*
|
|
42
|
+
* @param baseDir - The directory to treat as the backup root; must remain stable during validation.
|
|
43
|
+
* @param targetPath - The candidate target file path that must reside within `baseDir`.
|
|
44
|
+
* @throws Error with message "Named backup path escapes the backup root" if `baseDir` is a symlink,
|
|
45
|
+
* if the canonical and resolved base paths differ, or if `targetPath` is not contained
|
|
46
|
+
* within `baseDir`.
|
|
47
|
+
*/
|
|
48
|
+
function assertWithinDirectory(baseDir, targetPath) {
|
|
49
|
+
const resolvedBase = resolve(baseDir);
|
|
50
|
+
let baseStat = null;
|
|
51
|
+
try {
|
|
52
|
+
baseStat = lstatSync(resolvedBase);
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
const code = error.code;
|
|
56
|
+
if (code !== "ENOENT") {
|
|
57
|
+
throw error;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
if (baseStat) {
|
|
61
|
+
if (baseStat.isSymbolicLink()) {
|
|
62
|
+
throw new Error("Named backup path escapes the backup root");
|
|
63
|
+
}
|
|
64
|
+
const canonicalBase = realpathSync(resolvedBase);
|
|
65
|
+
const comparableCanonicalBase = process.platform === "win32"
|
|
66
|
+
? canonicalBase.toLowerCase()
|
|
67
|
+
: canonicalBase;
|
|
68
|
+
const comparableResolvedBase = process.platform === "win32" ? resolvedBase.toLowerCase() : resolvedBase;
|
|
69
|
+
if (comparableCanonicalBase !== comparableResolvedBase) {
|
|
70
|
+
throw new Error("Named backup path escapes the backup root");
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
const normalizedBase = normalizePathForComparison(baseDir);
|
|
74
|
+
const targetParent = dirname(targetPath);
|
|
75
|
+
const normalizedTargetParent = normalizePathForComparison(targetParent);
|
|
76
|
+
const normalizedTarget = join(normalizedTargetParent, basename(targetPath));
|
|
77
|
+
const rel = relative(normalizedBase, normalizedTarget);
|
|
78
|
+
if (rel === "" || (!rel.startsWith("..") && !isAbsolute(rel))) {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
throw new Error("Named backup path escapes the backup root");
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Validate and normalize a user-provided backup name into a safe `<name>.json` filename.
|
|
85
|
+
*
|
|
86
|
+
* Performs trimming, rejects path separators and traversal tokens, forbids rotation-style
|
|
87
|
+
* substrings and temporary suffixes, and enforces that the base name contains only
|
|
88
|
+
* letters, numbers, hyphens, and underscores. Checks that a resulting base name is non-empty
|
|
89
|
+
* and returns the base name with a `.json` extension appended.
|
|
90
|
+
*
|
|
91
|
+
* Notes:
|
|
92
|
+
* - Validation checks that are sensitive to case are performed using a lowercased form;
|
|
93
|
+
* this mirrors Windows case-insensitive filesystem behavior for prohibited patterns.
|
|
94
|
+
* - The function is synchronous and safe for concurrent use (pure string validation/normalization).
|
|
95
|
+
* - Token redaction: traversal tokens (`..`), path separators, rotation-style substrings,
|
|
96
|
+
* and temporary suffixes are rejected rather than sanitized.
|
|
97
|
+
*
|
|
98
|
+
* @param name - The user-provided filename or identifier (may include a `.json` extension)
|
|
99
|
+
* @returns The validated filename with a `.json` extension appended
|
|
100
|
+
* @throws Error if the name is empty, contains separators or traversal tokens, contains
|
|
101
|
+
* prohibited substrings, ends with an invalid temporary suffix, contains disallowed
|
|
102
|
+
* characters, or would result in an empty base name
|
|
103
|
+
*/
|
|
104
|
+
export function normalizeNamedBackupFileName(name) {
|
|
105
|
+
const trimmed = (name ?? "").trim();
|
|
106
|
+
if (trimmed.length === 0) {
|
|
107
|
+
throw new Error("Named backup requires a non-empty filename");
|
|
108
|
+
}
|
|
109
|
+
if (/[\\/]/.test(trimmed)) {
|
|
110
|
+
throw new Error("Backup filename must not contain path separators");
|
|
111
|
+
}
|
|
112
|
+
if (trimmed.includes("..")) {
|
|
113
|
+
throw new Error("Backup filename must not contain traversal tokens");
|
|
114
|
+
}
|
|
115
|
+
const lower = trimmed.toLowerCase();
|
|
116
|
+
if (BACKUP_PROHIBITED_SUBSTRINGS.some((value) => lower.includes(value))) {
|
|
117
|
+
throw new Error("Backup filename may not contain rotation-style sequences");
|
|
118
|
+
}
|
|
119
|
+
const hasJsonExtension = lower.endsWith(BACKUP_FILE_EXTENSION);
|
|
120
|
+
const baseName = hasJsonExtension
|
|
121
|
+
? trimmed.slice(0, trimmed.length - BACKUP_FILE_EXTENSION.length)
|
|
122
|
+
: trimmed;
|
|
123
|
+
if (baseName.length === 0) {
|
|
124
|
+
throw new Error("Backup filename cannot be just an extension");
|
|
125
|
+
}
|
|
126
|
+
const baseLower = baseName.toLowerCase();
|
|
127
|
+
if (BACKUP_INVALID_SUFFIXES.some((value) => baseLower.endsWith(value))) {
|
|
128
|
+
throw new Error("Backup filename may not end with temporary suffixes");
|
|
129
|
+
}
|
|
130
|
+
if (BACKUP_WINDOWS_RESERVED_NAME_REGEX.test(baseName)) {
|
|
131
|
+
throw new Error("Backup filename may not use a reserved Windows device name");
|
|
132
|
+
}
|
|
133
|
+
if (!BACKUP_SAFE_NAME_REGEX.test(baseName)) {
|
|
134
|
+
throw new Error("Backup filename may only contain letters, numbers, hyphens, and underscores; dots (.) are not allowed");
|
|
135
|
+
}
|
|
136
|
+
return `${baseName}${BACKUP_FILE_EXTENSION}`;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Compute the absolute path for the "backups" directory placed alongside the given storage path.
|
|
140
|
+
*
|
|
141
|
+
* This performs only path resolution and string manipulation; it does not access the filesystem and is insensitive to concurrent filesystem changes. It does not redact or sanitize tokens or sensitive substrings in `storagePath`. Note: other functions in this module handle Windows case-insensitive comparisons when validating paths.
|
|
142
|
+
*
|
|
143
|
+
* @param storagePath - Storage file or directory path (may be relative or absolute)
|
|
144
|
+
* @returns The resolved path to the backups directory adjacent to `storagePath` (i.e. dirname(storagePath)/backups)
|
|
145
|
+
*/
|
|
146
|
+
export function getNamedBackupRoot(storagePath) {
|
|
147
|
+
const resolvedStoragePath = resolvePath(storagePath);
|
|
148
|
+
return resolvePath(join(dirname(resolvedStoragePath), BACKUP_EXPORT_DIR_NAME));
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Resolve and validate a safe backup file path for a named backup inside the storage path's backups directory.
|
|
152
|
+
*
|
|
153
|
+
* @param name - User-provided backup name; will be normalized and validated (disallows path separators, `..`, prohibited substrings, and invalid suffixes such as `.tmp`/`.wal`) and the canonical filename (`*.json`) will be produced.
|
|
154
|
+
* @param storagePath - Base storage path used to locate the backups directory; path comparisons treat Windows paths case-insensitively.
|
|
155
|
+
* @returns The absolute, validated path to the backup file within the backups directory.
|
|
156
|
+
*
|
|
157
|
+
* Concurrency: this function only computes and validates the path and does not create files or directories; callers must handle concurrent filesystem operations (e.g., directory creation or file writes).
|
|
158
|
+
*/
|
|
159
|
+
export function resolveNamedBackupPath(name, storagePath) {
|
|
160
|
+
const fileName = normalizeNamedBackupFileName(name);
|
|
161
|
+
const backupRoot = getNamedBackupRoot(storagePath);
|
|
162
|
+
const candidate = resolvePath(join(backupRoot, fileName));
|
|
163
|
+
assertWithinDirectory(backupRoot, candidate);
|
|
164
|
+
return candidate;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Create a named backup file inside the storage path's backups directory and return its resolved path.
|
|
168
|
+
*
|
|
169
|
+
* The provided `name` is validated and normalized (suffix, allowed characters, and prohibited substrings) and the
|
|
170
|
+
* backup root directory is created if missing. The export operation will be asked to write to the resolved path; a
|
|
171
|
+
* safety check ensures the final resolved path stays within the backups root.
|
|
172
|
+
* The delegated `beforeCommit` hook re-validates containment immediately before
|
|
173
|
+
* the storage layer commits the final rename, but callers should still serialize
|
|
174
|
+
* backup-root mutations rather than relying on path checks alone.
|
|
175
|
+
*
|
|
176
|
+
* Concurrency: callers should avoid concurrent exports that target the same `name` as behavior is unspecified.
|
|
177
|
+
* Windows behavior: file-name/path comparisons are case-insensitive and names are normalized to lowercase.
|
|
178
|
+
* Token rules: input `name` is checked to prevent path traversal, separators, rotation-style substrings, and certain
|
|
179
|
+
* invalid suffixes (e.g., `.tmp`, `.wal`); the final returned path always includes the `.json` extension.
|
|
180
|
+
*
|
|
181
|
+
* @param name - The desired backup file name (validated and normalized).
|
|
182
|
+
* @param dependencies - Object providing storage path resolution and the exportAccounts implementation.
|
|
183
|
+
* @param options.force - When true, request overwriting an existing backup.
|
|
184
|
+
* @returns The absolute path to the created backup file (including `.json`).
|
|
185
|
+
*/
|
|
186
|
+
export async function exportNamedBackupFile(name, dependencies, options) {
|
|
187
|
+
const storagePath = dependencies.getStoragePath();
|
|
188
|
+
const destination = resolveNamedBackupPath(name, storagePath);
|
|
189
|
+
const backupRoot = getNamedBackupRoot(storagePath);
|
|
190
|
+
const exportKey = normalizePathForComparison(destination);
|
|
191
|
+
if (!options?.force && inFlightNamedBackupExports.has(exportKey)) {
|
|
192
|
+
throw new Error(`File already exists: ${destination}`);
|
|
193
|
+
}
|
|
194
|
+
assertWithinDirectory(dirname(backupRoot), backupRoot);
|
|
195
|
+
await fs.mkdir(backupRoot, { recursive: true });
|
|
196
|
+
inFlightNamedBackupExports.add(exportKey);
|
|
197
|
+
try {
|
|
198
|
+
await dependencies.exportAccounts(destination, options?.force === true, (resolvedPath) => {
|
|
199
|
+
assertWithinDirectory(backupRoot, resolvedPath);
|
|
200
|
+
});
|
|
201
|
+
return destination;
|
|
202
|
+
}
|
|
203
|
+
finally {
|
|
204
|
+
inFlightNamedBackupExports.delete(exportKey);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
//# sourceMappingURL=named-backup-export.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"named-backup-export.js","sourceRoot":"","sources":["../../lib/named-backup-export.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,21 +2,17 @@
|
|
|
2
2
|
<html lang="en">
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="utf-8" />
|
|
5
|
-
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
|
6
|
-
<title>
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
6
|
+
<title>Codex Sign-In Complete</title>
|
|
7
7
|
<style>
|
|
8
|
-
/* Space Grotesk import removed to avoid CSP font-src violations; rely on system stack. */
|
|
9
|
-
|
|
10
8
|
:root {
|
|
11
|
-
|
|
12
|
-
--
|
|
13
|
-
--
|
|
14
|
-
--
|
|
15
|
-
--
|
|
16
|
-
--
|
|
17
|
-
--
|
|
18
|
-
--accent: #49f1a8;
|
|
19
|
-
--accent-soft: rgba(73, 241, 168, 0.15);
|
|
9
|
+
color-scheme: dark;
|
|
10
|
+
--bg: #0b0b0b;
|
|
11
|
+
--panel: #111111;
|
|
12
|
+
--text: #f2f2f2;
|
|
13
|
+
--muted: #a3a3a3;
|
|
14
|
+
--line: #232323;
|
|
15
|
+
--ok: #7cf0a6;
|
|
20
16
|
}
|
|
21
17
|
|
|
22
18
|
* {
|
|
@@ -26,245 +22,105 @@
|
|
|
26
22
|
body {
|
|
27
23
|
margin: 0;
|
|
28
24
|
min-height: 100vh;
|
|
29
|
-
font-family: "Segoe UI", system-ui, -apple-system, "IBM Plex Sans", sans-serif;
|
|
30
|
-
background: radial-gradient(circle at top, rgba(73, 241, 168, 0.12), transparent 55%),
|
|
31
|
-
linear-gradient(180deg, var(--bg), var(--bg2));
|
|
32
|
-
color: var(--text);
|
|
33
25
|
display: grid;
|
|
34
26
|
place-items: center;
|
|
35
|
-
|
|
27
|
+
background: var(--bg);
|
|
28
|
+
color: var(--text);
|
|
29
|
+
font-family: "Geist Mono", "GeistMono", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
|
30
|
+
padding: 24px;
|
|
36
31
|
}
|
|
37
32
|
|
|
38
33
|
main {
|
|
39
|
-
width: min(
|
|
40
|
-
background: var(--
|
|
41
|
-
border
|
|
42
|
-
border:
|
|
43
|
-
padding:
|
|
44
|
-
box-shadow: 0 24px 60px rgba(0, 0, 0, 0.55);
|
|
45
|
-
display: flex;
|
|
46
|
-
flex-direction: column;
|
|
47
|
-
gap: 18px;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
.eyebrow {
|
|
51
|
-
font-size: 12px;
|
|
52
|
-
text-transform: uppercase;
|
|
53
|
-
letter-spacing: 0.22em;
|
|
54
|
-
color: var(--muted);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
.icon {
|
|
58
|
-
width: 64px;
|
|
59
|
-
height: 64px;
|
|
60
|
-
border-radius: 16px;
|
|
61
|
-
border: 1px solid var(--border);
|
|
62
|
-
background: var(--accent-soft);
|
|
34
|
+
width: min(520px, 100%);
|
|
35
|
+
background: var(--panel);
|
|
36
|
+
border: 1px solid var(--line);
|
|
37
|
+
border-radius: 12px;
|
|
38
|
+
padding: 20px;
|
|
63
39
|
display: grid;
|
|
64
|
-
|
|
65
|
-
color: var(--accent);
|
|
66
|
-
margin: 4px 0 6px;
|
|
67
|
-
position: relative;
|
|
68
|
-
animation: fade 1s ease both;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
.icon::after {
|
|
72
|
-
content: "";
|
|
73
|
-
width: 20px;
|
|
74
|
-
height: 12px;
|
|
75
|
-
border-left: 3px solid currentColor;
|
|
76
|
-
border-bottom: 3px solid currentColor;
|
|
77
|
-
transform: rotate(-45deg);
|
|
40
|
+
gap: 14px;
|
|
78
41
|
}
|
|
79
42
|
|
|
80
43
|
h1 {
|
|
81
44
|
margin: 0;
|
|
82
|
-
font-size:
|
|
45
|
+
font-size: 20px;
|
|
46
|
+
font-weight: 600;
|
|
83
47
|
letter-spacing: -0.02em;
|
|
84
48
|
}
|
|
85
49
|
|
|
86
|
-
|
|
50
|
+
p {
|
|
87
51
|
margin: 0;
|
|
88
52
|
color: var(--muted);
|
|
89
|
-
font-size: 15px;
|
|
90
|
-
line-height: 1.6;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
.state {
|
|
94
|
-
display: flex;
|
|
95
|
-
align-items: baseline;
|
|
96
|
-
justify-content: space-between;
|
|
97
|
-
padding: 16px 18px;
|
|
98
|
-
border-radius: 16px;
|
|
99
|
-
background: rgba(8, 14, 11, 0.75);
|
|
100
|
-
border: 1px solid var(--border);
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
.state span {
|
|
104
|
-
font-size: 13px;
|
|
105
|
-
text-transform: uppercase;
|
|
106
|
-
letter-spacing: 0.15em;
|
|
107
|
-
color: var(--muted);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
.state strong {
|
|
111
|
-
font-size: 20px;
|
|
112
|
-
color: var(--accent);
|
|
113
|
-
font-weight: 600;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
.status-list {
|
|
117
|
-
list-style: none;
|
|
118
|
-
margin: 8px 0 0;
|
|
119
|
-
padding: 0;
|
|
120
|
-
display: flex;
|
|
121
|
-
flex-direction: column;
|
|
122
|
-
gap: 10px;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
.status-list li {
|
|
126
|
-
display: flex;
|
|
127
|
-
align-items: center;
|
|
128
|
-
justify-content: space-between;
|
|
129
|
-
border-bottom: 1px solid var(--divider);
|
|
130
|
-
padding-bottom: 8px;
|
|
131
53
|
font-size: 14px;
|
|
54
|
+
line-height: 1.5;
|
|
132
55
|
}
|
|
133
56
|
|
|
134
|
-
.status
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
.status-list span {
|
|
140
|
-
color: var(--muted);
|
|
57
|
+
.status {
|
|
58
|
+
display: inline-flex;
|
|
59
|
+
align-items: center;
|
|
60
|
+
gap: 8px;
|
|
61
|
+
color: var(--ok);
|
|
141
62
|
font-size: 13px;
|
|
142
|
-
letter-spacing: 0.02em;
|
|
143
63
|
}
|
|
144
64
|
|
|
145
|
-
.
|
|
146
|
-
|
|
147
|
-
|
|
65
|
+
.dot {
|
|
66
|
+
width: 8px;
|
|
67
|
+
height: 8px;
|
|
68
|
+
border-radius: 50%;
|
|
69
|
+
background: currentColor;
|
|
148
70
|
}
|
|
149
71
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
padding-top: 14px;
|
|
72
|
+
dl {
|
|
73
|
+
margin: 0;
|
|
153
74
|
display: grid;
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
.meta-row {
|
|
158
|
-
display: flex;
|
|
159
|
-
justify-content: space-between;
|
|
160
|
-
align-items: baseline;
|
|
75
|
+
grid-template-columns: 120px 1fr;
|
|
76
|
+
gap: 8px 12px;
|
|
161
77
|
font-size: 13px;
|
|
162
|
-
color: var(--muted);
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
.meta-row code {
|
|
166
|
-
font-family: "Segoe UI", system-ui, -apple-system, "SFMono-Regular", Menlo, monospace;
|
|
167
|
-
background: rgba(255, 255, 255, 0.04);
|
|
168
|
-
border-radius: 8px;
|
|
169
|
-
padding: 4px 8px;
|
|
170
|
-
color: var(--text);
|
|
171
78
|
}
|
|
172
79
|
|
|
173
|
-
|
|
174
|
-
margin: 0;
|
|
175
|
-
font-size: 13px;
|
|
80
|
+
dt {
|
|
176
81
|
color: var(--muted);
|
|
177
|
-
border-top: 1px solid var(--divider);
|
|
178
|
-
padding-top: 14px;
|
|
179
82
|
}
|
|
180
83
|
|
|
181
|
-
|
|
84
|
+
dd {
|
|
85
|
+
margin: 0;
|
|
182
86
|
color: var(--text);
|
|
87
|
+
word-break: break-word;
|
|
183
88
|
}
|
|
184
89
|
|
|
185
|
-
|
|
90
|
+
code {
|
|
91
|
+
background: #171717;
|
|
92
|
+
border: 1px solid var(--line);
|
|
93
|
+
border-radius: 6px;
|
|
94
|
+
padding: 2px 6px;
|
|
95
|
+
font-family: inherit;
|
|
186
96
|
font-size: 12px;
|
|
187
|
-
color: var(--muted);
|
|
188
|
-
text-align: center;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
@keyframes fade {
|
|
192
|
-
from { opacity: 0; transform: translateY(6px); }
|
|
193
|
-
to { opacity: 1; transform: translateY(0); }
|
|
194
97
|
}
|
|
195
98
|
|
|
196
|
-
@media (
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
@media (max-width: 480px) {
|
|
203
|
-
main {
|
|
204
|
-
padding: 24px;
|
|
205
|
-
border-radius: 18px;
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
.state {
|
|
209
|
-
flex-direction: column;
|
|
210
|
-
align-items: flex-start;
|
|
211
|
-
gap: 4px;
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
.status-list li {
|
|
215
|
-
flex-direction: column;
|
|
216
|
-
align-items: flex-start;
|
|
217
|
-
gap: 2px;
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
.meta-row {
|
|
221
|
-
flex-direction: column;
|
|
222
|
-
gap: 4px;
|
|
99
|
+
@media (max-width: 520px) {
|
|
100
|
+
dl {
|
|
101
|
+
grid-template-columns: 1fr;
|
|
223
102
|
}
|
|
224
103
|
}
|
|
225
104
|
</style>
|
|
226
105
|
</head>
|
|
227
106
|
<body>
|
|
228
107
|
<main role="main" aria-label="OAuth callback received">
|
|
229
|
-
<
|
|
230
|
-
<
|
|
231
|
-
|
|
232
|
-
<
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
<strong>Processing</strong>
|
|
108
|
+
<h1>Sign-in complete</h1>
|
|
109
|
+
<p>Return to your terminal to finish Codex login.</p>
|
|
110
|
+
|
|
111
|
+
<div class="status" aria-live="polite">
|
|
112
|
+
<span class="dot" aria-hidden="true"></span>
|
|
113
|
+
Callback received
|
|
236
114
|
</div>
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
</
|
|
242
|
-
<
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
<li>
|
|
247
|
-
<span>Credentials</span>
|
|
248
|
-
<span>persisting after terminal completes</span>
|
|
249
|
-
</li>
|
|
250
|
-
<li>
|
|
251
|
-
<span>Session</span>
|
|
252
|
-
<span>activating in terminal</span>
|
|
253
|
-
</li>
|
|
254
|
-
</ul>
|
|
255
|
-
<section class="meta" aria-label="Callback summary">
|
|
256
|
-
<div class="meta-row">
|
|
257
|
-
<span>Callback</span>
|
|
258
|
-
<!-- Port 1455 is fixed by design via REDIRECT_URI -->
|
|
259
|
-
<code>localhost:1455</code>
|
|
260
|
-
</div>
|
|
261
|
-
<div class="meta-row">
|
|
262
|
-
<span>Tip</span>
|
|
263
|
-
<span>Close this tab when you are done.</span>
|
|
264
|
-
</div>
|
|
265
|
-
</section>
|
|
266
|
-
<p class="tip"><strong>Next:</strong> return to the terminal window to continue.</p>
|
|
267
|
-
<footer>Back to terminal to continue.</footer>
|
|
115
|
+
|
|
116
|
+
<dl>
|
|
117
|
+
<dt>Endpoint</dt>
|
|
118
|
+
<dd><code>localhost:1455</code></dd>
|
|
119
|
+
<dt>Flow</dt>
|
|
120
|
+
<dd>OAuth callback captured</dd>
|
|
121
|
+
<dt>Next</dt>
|
|
122
|
+
<dd>Close this tab and continue in terminal</dd>
|
|
123
|
+
</dl>
|
|
268
124
|
</main>
|
|
269
125
|
</body>
|
|
270
|
-
</html>
|
|
126
|
+
</html>
|