codex-multi-auth 2.3.0-beta.2 → 2.3.0-beta.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/.codex-plugin/plugin.json +2 -1
- package/README.md +1 -1
- package/dist/lib/account-policy.d.ts.map +1 -1
- package/dist/lib/account-policy.js +2 -1
- package/dist/lib/audit.d.ts +0 -9
- package/dist/lib/audit.d.ts.map +1 -1
- package/dist/lib/auth/device-auth.d.ts +1 -6
- package/dist/lib/auth/device-auth.d.ts.map +1 -1
- package/dist/lib/auth/device-auth.js +5 -5
- package/dist/lib/budget-guard.d.ts.map +1 -1
- package/dist/lib/budget-guard.js +2 -1
- package/dist/lib/codex-cli/writer.d.ts.map +1 -1
- package/dist/lib/codex-cli/writer.js +2 -1
- package/dist/lib/codex-manager/backend-settings-helpers.d.ts +0 -1
- package/dist/lib/codex-manager/backend-settings-helpers.d.ts.map +1 -1
- package/dist/lib/codex-manager/backend-settings-helpers.js +1 -1
- package/dist/lib/codex-manager/behavior-settings-panel.d.ts +0 -19
- package/dist/lib/codex-manager/behavior-settings-panel.d.ts.map +1 -1
- package/dist/lib/codex-manager/commands/report.d.ts.map +1 -1
- package/dist/lib/codex-manager/commands/report.js +2 -1
- package/dist/lib/codex-manager/commands/uninstall.d.ts +2 -2
- package/dist/lib/codex-manager/commands/uninstall.d.ts.map +1 -1
- package/dist/lib/codex-manager/commands/uninstall.js +1 -1
- package/dist/lib/codex-manager/commands/usage.d.ts.map +1 -1
- package/dist/lib/codex-manager/commands/usage.js +2 -1
- package/dist/lib/codex-manager/commands/verify.d.ts +2 -2
- package/dist/lib/codex-manager/commands/verify.d.ts.map +1 -1
- package/dist/lib/codex-manager/commands/why-selected.d.ts +1 -22
- package/dist/lib/codex-manager/commands/why-selected.d.ts.map +1 -1
- package/dist/lib/codex-manager/dashboard-display-panel.d.ts +0 -14
- package/dist/lib/codex-manager/dashboard-display-panel.d.ts.map +1 -1
- package/dist/lib/codex-manager/experimental-settings-prompt.d.ts +2 -1
- package/dist/lib/codex-manager/experimental-settings-prompt.d.ts.map +1 -1
- package/dist/lib/codex-manager/forecast-report-shared.d.ts +2 -2
- package/dist/lib/codex-manager/forecast-report-shared.d.ts.map +1 -1
- package/dist/lib/codex-manager/forecast-report-shared.js +2 -2
- package/dist/lib/codex-manager/formatters/quota-formatters.d.ts +0 -2
- package/dist/lib/codex-manager/formatters/quota-formatters.d.ts.map +1 -1
- package/dist/lib/codex-manager/formatters/quota-formatters.js +2 -2
- package/dist/lib/codex-manager/help.d.ts +2 -1
- package/dist/lib/codex-manager/help.d.ts.map +1 -1
- package/dist/lib/codex-manager/repair-commands.d.ts +0 -15
- package/dist/lib/codex-manager/repair-commands.d.ts.map +1 -1
- package/dist/lib/codex-manager/repair-commands.js +5 -5
- package/dist/lib/codex-manager/settings-hub/backend.d.ts +0 -5
- package/dist/lib/codex-manager/settings-hub/backend.d.ts.map +1 -1
- package/dist/lib/codex-manager/settings-hub/backend.js +1 -1
- package/dist/lib/codex-manager/settings-hub/dashboard.d.ts +1 -14
- package/dist/lib/codex-manager/settings-hub/dashboard.d.ts.map +1 -1
- package/dist/lib/codex-manager/settings-hub/dashboard.js +8 -8
- package/dist/lib/codex-manager/settings-write-queue.d.ts +0 -10
- package/dist/lib/codex-manager/settings-write-queue.d.ts.map +1 -1
- package/dist/lib/codex-manager/settings-write-queue.js +10 -10
- package/dist/lib/codex-manager/statusline-settings-panel.d.ts +2 -17
- package/dist/lib/codex-manager/statusline-settings-panel.d.ts.map +1 -1
- package/dist/lib/codex-manager/theme-settings-panel.d.ts +0 -13
- package/dist/lib/codex-manager/theme-settings-panel.d.ts.map +1 -1
- package/dist/lib/config.d.ts +0 -13
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +22 -19
- package/dist/lib/dashboard-settings.d.ts +3 -3
- package/dist/lib/dashboard-settings.d.ts.map +1 -1
- package/dist/lib/dashboard-settings.js +0 -1
- package/dist/lib/errors.d.ts +0 -1
- package/dist/lib/errors.d.ts.map +1 -1
- package/dist/lib/forecast.d.ts +4 -3
- package/dist/lib/forecast.d.ts.map +1 -1
- package/dist/lib/fs-retry.d.ts +0 -3
- package/dist/lib/fs-retry.d.ts.map +1 -1
- package/dist/lib/fs-retry.js +3 -3
- package/dist/lib/index.d.ts +1 -0
- package/dist/lib/index.d.ts.map +1 -1
- package/dist/lib/index.js +1 -0
- package/dist/lib/local-client-tokens.d.ts.map +1 -1
- package/dist/lib/local-client-tokens.js +2 -1
- package/dist/lib/oc-chatgpt-import-adapter.d.ts +1 -1
- package/dist/lib/oc-chatgpt-import-adapter.d.ts.map +1 -1
- package/dist/lib/oc-chatgpt-orchestrator.d.ts.map +1 -1
- package/dist/lib/oc-chatgpt-orchestrator.js +2 -1
- package/dist/lib/oc-chatgpt-target-detection.d.ts +1 -1
- package/dist/lib/oc-chatgpt-target-detection.d.ts.map +1 -1
- package/dist/lib/prompts/codex-host-bridge.d.ts +0 -8
- package/dist/lib/prompts/codex-host-bridge.d.ts.map +1 -1
- package/dist/lib/prompts/codex-host-bridge.js +0 -20
- package/dist/lib/prompts/codex.d.ts.map +1 -1
- package/dist/lib/prompts/codex.js +2 -1
- package/dist/lib/prompts/fetch-utils.d.ts +0 -2
- package/dist/lib/prompts/fetch-utils.d.ts.map +1 -1
- package/dist/lib/prompts/fetch-utils.js +2 -2
- package/dist/lib/prompts/host-codex-prompt.d.ts.map +1 -1
- package/dist/lib/prompts/host-codex-prompt.js +2 -1
- package/dist/lib/quota-cache.d.ts.map +1 -1
- package/dist/lib/quota-cache.js +2 -1
- package/dist/lib/recovery/storage.d.ts.map +1 -1
- package/dist/lib/recovery/storage.js +5 -3
- package/dist/lib/recovery/types.d.ts +4 -12
- package/dist/lib/recovery/types.d.ts.map +1 -1
- package/dist/lib/recovery.d.ts +2 -2
- package/dist/lib/recovery.d.ts.map +1 -1
- package/dist/lib/request/response-compaction.d.ts +2 -1
- package/dist/lib/request/response-compaction.d.ts.map +1 -1
- package/dist/lib/request/stream-failover-runtime.d.ts.map +1 -1
- package/dist/lib/request/stream-failover-runtime.js +23 -1
- package/dist/lib/rotation.d.ts +1 -3
- package/dist/lib/rotation.d.ts.map +1 -1
- package/dist/lib/rotation.js +1 -2
- package/dist/lib/routing-profiles.d.ts.map +1 -1
- package/dist/lib/routing-profiles.js +2 -1
- package/dist/lib/runtime/config-toml.d.ts +0 -6
- package/dist/lib/runtime/config-toml.d.ts.map +1 -1
- package/dist/lib/runtime/config-toml.js +6 -6
- package/dist/lib/runtime/event-handler.d.ts +0 -31
- package/dist/lib/runtime/event-handler.d.ts.map +1 -1
- package/dist/lib/runtime/event-handler.js +0 -22
- package/dist/lib/runtime/first-run.d.ts +3 -5
- package/dist/lib/runtime/first-run.d.ts.map +1 -1
- package/dist/lib/runtime/first-run.js +2 -2
- package/dist/lib/runtime/quota-headers.d.ts +1 -6
- package/dist/lib/runtime/quota-headers.d.ts.map +1 -1
- package/dist/lib/runtime/quota-headers.js +5 -5
- package/dist/lib/runtime/runtime-current-account.d.ts +3 -3
- package/dist/lib/runtime/runtime-current-account.d.ts.map +1 -1
- package/dist/lib/runtime/runtime-current-account.js +1 -1
- package/dist/lib/runtime/runtime-observability.d.ts +2 -2
- package/dist/lib/runtime/runtime-observability.d.ts.map +1 -1
- package/dist/lib/runtime/runtime-observability.js +0 -4
- package/dist/lib/runtime-rotation-proxy.d.ts.map +1 -1
- package/dist/lib/runtime-rotation-proxy.js +4 -3
- package/dist/lib/schemas.d.ts +3 -91
- package/dist/lib/schemas.d.ts.map +1 -1
- package/dist/lib/schemas.js +8 -8
- package/dist/lib/storage/file-paths.d.ts +2 -2
- package/dist/lib/storage/file-paths.d.ts.map +1 -1
- package/dist/lib/storage/file-paths.js +2 -2
- package/dist/lib/storage/flagged-storage-io.d.ts.map +1 -1
- package/dist/lib/storage/flagged-storage-io.js +2 -2
- package/dist/lib/storage/import-export.d.ts.map +1 -1
- package/dist/lib/storage/import-export.js +2 -2
- package/dist/lib/storage/migrations.d.ts +2 -1
- package/dist/lib/storage/migrations.d.ts.map +1 -1
- package/dist/lib/storage.d.ts.map +1 -1
- package/dist/lib/storage.js +30 -23
- package/dist/lib/temp-path.d.ts +26 -0
- package/dist/lib/temp-path.d.ts.map +1 -0
- package/dist/lib/temp-path.js +30 -0
- package/dist/lib/ui/theme.d.ts +3 -2
- package/dist/lib/ui/theme.d.ts.map +1 -1
- package/dist/lib/unified-settings.d.ts.map +1 -1
- package/dist/lib/unified-settings.js +2 -1
- package/dist/lib/update-notice.d.ts.map +1 -1
- package/dist/lib/update-notice.js +2 -1
- package/package.json +1 -2
package/dist/lib/schemas.js
CHANGED
|
@@ -85,7 +85,7 @@ export const PluginConfigSchema = z.object({
|
|
|
85
85
|
/**
|
|
86
86
|
* Source of the accountId used for ChatGPT requests.
|
|
87
87
|
*/
|
|
88
|
-
|
|
88
|
+
const AccountIdSourceSchema = z.enum([
|
|
89
89
|
"token",
|
|
90
90
|
"id_token",
|
|
91
91
|
"org",
|
|
@@ -94,7 +94,7 @@ export const AccountIdSourceSchema = z.enum([
|
|
|
94
94
|
/**
|
|
95
95
|
* Cooldown reason for temporary account suspension.
|
|
96
96
|
*/
|
|
97
|
-
|
|
97
|
+
const CooldownReasonSchema = z.enum([
|
|
98
98
|
"auth-failure",
|
|
99
99
|
"network-error",
|
|
100
100
|
"server-error",
|
|
@@ -103,7 +103,7 @@ export const CooldownReasonSchema = z.enum([
|
|
|
103
103
|
/**
|
|
104
104
|
* Last switch reason for account rotation tracking.
|
|
105
105
|
*/
|
|
106
|
-
|
|
106
|
+
const SwitchReasonSchema = z.enum([
|
|
107
107
|
"rate-limit",
|
|
108
108
|
"initial",
|
|
109
109
|
"rotation",
|
|
@@ -125,14 +125,14 @@ export const PersistedSwitchReasonSchema = z.enum([
|
|
|
125
125
|
/**
|
|
126
126
|
* Rate limit state - maps model family to reset timestamp.
|
|
127
127
|
*/
|
|
128
|
-
|
|
128
|
+
const RateLimitStateV3Schema = z.record(z.string(), z.number().optional());
|
|
129
129
|
/**
|
|
130
130
|
* Workspace entry within an account. Supports a single OpenAI/Google account
|
|
131
131
|
* that belongs to multiple ChatGPT workspaces (e.g. personal Plus + a
|
|
132
132
|
* business/team workspace), each a distinct quota pool keyed by its org_id
|
|
133
133
|
* (`id`). Mirrors the `Workspace` TS interface in `lib/accounts.ts`. See #491.
|
|
134
134
|
*/
|
|
135
|
-
|
|
135
|
+
const WorkspaceSchema = z.object({
|
|
136
136
|
id: z.string(),
|
|
137
137
|
name: z.string().optional(),
|
|
138
138
|
enabled: z.boolean(),
|
|
@@ -170,7 +170,7 @@ const modelFamilyEntries = MODEL_FAMILIES.map((family) => [
|
|
|
170
170
|
family,
|
|
171
171
|
z.number().optional(),
|
|
172
172
|
]);
|
|
173
|
-
|
|
173
|
+
const ActiveIndexByFamilySchema = z
|
|
174
174
|
.object(Object.fromEntries(modelFamilyEntries))
|
|
175
175
|
.partial();
|
|
176
176
|
/**
|
|
@@ -187,7 +187,7 @@ export const AccountStorageV3Schema = z.object({
|
|
|
187
187
|
/**
|
|
188
188
|
* Legacy V1 account metadata for migration support.
|
|
189
189
|
*/
|
|
190
|
-
|
|
190
|
+
const AccountMetadataV1Schema = z.object({
|
|
191
191
|
accountId: z.string().optional(),
|
|
192
192
|
accountIdSource: AccountIdSourceSchema.optional(),
|
|
193
193
|
accountLabel: z.string().optional(),
|
|
@@ -259,7 +259,7 @@ export const AccountsJournalEntrySchema = z.object({
|
|
|
259
259
|
/**
|
|
260
260
|
* Token failure reason codes.
|
|
261
261
|
*/
|
|
262
|
-
|
|
262
|
+
const TokenFailureReasonSchema = z.enum([
|
|
263
263
|
"http_error",
|
|
264
264
|
"invalid_response",
|
|
265
265
|
"network_error",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ACCOUNTS_BACKUP_SUFFIX, ACCOUNTS_WAL_SUFFIX, getAccountsBackupPath,
|
|
2
|
-
export { ACCOUNTS_BACKUP_SUFFIX, ACCOUNTS_WAL_SUFFIX, getAccountsBackupPath,
|
|
1
|
+
import { ACCOUNTS_BACKUP_SUFFIX, ACCOUNTS_WAL_SUFFIX, getAccountsBackupPath, getAccountsWalPath, getIntentionalResetMarkerPath, RESET_MARKER_SUFFIX } from "./backup-paths.js";
|
|
2
|
+
export { ACCOUNTS_BACKUP_SUFFIX, ACCOUNTS_WAL_SUFFIX, getAccountsBackupPath, getAccountsWalPath, getIntentionalResetMarkerPath, RESET_MARKER_SUFFIX, };
|
|
3
3
|
export declare function getAccountsBackupRecoveryCandidates(path: string): string[];
|
|
4
4
|
export declare function getFlaggedAccountsPath(storagePath: string, fileName: string): string;
|
|
5
5
|
export declare function getLegacyFlaggedAccountsPath(storagePath: string, legacyFileName: string): string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-paths.d.ts","sourceRoot":"","sources":["../../../lib/storage/file-paths.ts"],"names":[],"mappings":"AACA,OAAO,EACN,sBAAsB,EACtB,mBAAmB,EACnB,qBAAqB,
|
|
1
|
+
{"version":3,"file":"file-paths.d.ts","sourceRoot":"","sources":["../../../lib/storage/file-paths.ts"],"names":[],"mappings":"AACA,OAAO,EACN,sBAAsB,EACtB,mBAAmB,EACnB,qBAAqB,EAErB,kBAAkB,EAClB,6BAA6B,EAC7B,mBAAmB,EACnB,MAAM,mBAAmB,CAAC;AAI3B,OAAO,EACN,sBAAsB,EACtB,mBAAmB,EACnB,qBAAqB,EACrB,kBAAkB,EAClB,6BAA6B,EAC7B,mBAAmB,GACnB,CAAC;AAEF,wBAAgB,mCAAmC,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAE1E;AAED,wBAAgB,sBAAsB,CACrC,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,GACd,MAAM,CAER;AAMD,wBAAgB,4BAA4B,CAC3C,WAAW,EAAE,MAAM,EACnB,cAAc,EAAE,MAAM,GACpB,MAAM,CAER"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { dirname, join } from "node:path";
|
|
2
|
-
import { ACCOUNTS_BACKUP_SUFFIX, ACCOUNTS_WAL_SUFFIX, getAccountsBackupPath,
|
|
2
|
+
import { ACCOUNTS_BACKUP_SUFFIX, ACCOUNTS_WAL_SUFFIX, getAccountsBackupPath, getAccountsBackupRecoveryCandidates as getBackupRecoveryCandidates, getAccountsWalPath, getIntentionalResetMarkerPath, RESET_MARKER_SUFFIX, } from "./backup-paths.js";
|
|
3
3
|
const ACCOUNTS_BACKUP_HISTORY_DEPTH = 3;
|
|
4
|
-
export { ACCOUNTS_BACKUP_SUFFIX, ACCOUNTS_WAL_SUFFIX, getAccountsBackupPath,
|
|
4
|
+
export { ACCOUNTS_BACKUP_SUFFIX, ACCOUNTS_WAL_SUFFIX, getAccountsBackupPath, getAccountsWalPath, getIntentionalResetMarkerPath, RESET_MARKER_SUFFIX, };
|
|
5
5
|
export function getAccountsBackupRecoveryCandidates(path) {
|
|
6
6
|
return getBackupRecoveryCandidates(path, ACCOUNTS_BACKUP_HISTORY_DEPTH);
|
|
7
7
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flagged-storage-io.d.ts","sourceRoot":"","sources":["../../../lib/storage/flagged-storage-io.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"flagged-storage-io.d.ts","sourceRoot":"","sources":["../../../lib/storage/flagged-storage-io.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AA4EjE,wBAAsB,wBAAwB,CAAC,MAAM,EAAE;IACtD,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,uBAAuB,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,uBAAuB,CAAC;IACpE,sBAAsB,EAAE,CACvB,OAAO,EAAE,uBAAuB,EAChC,eAAe,EAAE,MAAM,KACnB,OAAO,CAAC,OAAO,CAAC,CAAC;IACtB,mBAAmB,EAAE,CAAC,OAAO,EAAE,uBAAuB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACzE,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IACtE,OAAO,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;CACrE,GAAG,OAAO,CAAC,uBAAuB,CAAC,CA0InC;AAED,wBAAsB,iCAAiC,CACtD,OAAO,EAAE,uBAAuB,EAChC,MAAM,EAAE;IACP,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,uBAAuB,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,uBAAuB,CAAC;IACpE,iBAAiB,EAAE,CAClB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,OAAO,CAAC,EAAE;QAAE,kBAAkB,CAAC,EAAE,OAAO,CAAA;KAAE,KACtC,OAAO,CAAC,IAAI,CAAC,CAAC;IACnB,mBAAmB,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5E,OAAO,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IACrE,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;CACtE,GACC,OAAO,CAAC,IAAI,CAAC,CAyCf;AAED,wBAAsB,0BAA0B,CAAC,MAAM,EAAE;IACxD,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;CACtE,GAAG,OAAO,CAAC,IAAI,CAAC,CA8ChB"}
|
|
@@ -3,6 +3,7 @@ import { dirname } from "node:path";
|
|
|
3
3
|
import { FlaggedAccountStorageV1Schema, safeParseJson } from "../schemas.js";
|
|
4
4
|
import { readFileWithRetry } from "./flagged-storage-file.js";
|
|
5
5
|
import { FILE_RETRY_CODES } from "../fs-retry.js";
|
|
6
|
+
import { tempPathFor } from "../temp-path.js";
|
|
6
7
|
// storage-07: align with the single shared retryable-code set (adds ENOTEMPTY/
|
|
7
8
|
// EACCES) instead of a local subset.
|
|
8
9
|
const RETRYABLE_UNLINK_CODES = FILE_RETRY_CODES;
|
|
@@ -183,8 +184,7 @@ export async function loadFlaggedAccountsState(params) {
|
|
|
183
184
|
}
|
|
184
185
|
}
|
|
185
186
|
export async function saveFlaggedAccountsUnlockedToDisk(storage, params) {
|
|
186
|
-
const
|
|
187
|
-
const tempPath = `${params.path}.${uniqueSuffix}.tmp`;
|
|
187
|
+
const tempPath = tempPathFor(params.path);
|
|
188
188
|
try {
|
|
189
189
|
await fs.mkdir(dirname(params.path), { recursive: true });
|
|
190
190
|
if (existsSync(params.path)) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"import-export.d.ts","sourceRoot":"","sources":["../../../lib/storage/import-export.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"import-export.d.ts","sourceRoot":"","sources":["../../../lib/storage/import-export.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAsD1D,wBAAsB,oBAAoB,CAAC,MAAM,EAAE;IAClD,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACjC,YAAY,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAC9D,OAAO,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;CACrE,GAAG,OAAO,CAAC,IAAI,CAAC,CAuChB;AAED,wBAAsB,cAAc,CAAC,MAAM,EAAE;IAC5C,YAAY,EAAE,MAAM,CAAC;IACrB,uBAAuB,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,gBAAgB,GAAG,IAAI,CAAC;CACrE,GAAG,OAAO,CAAC,gBAAgB,CAAC,CA8C5B;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE;IAC7C,QAAQ,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAClC,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,mBAAmB,EAAE,CACpB,QAAQ,EAAE,gBAAgB,CAAC,UAAU,CAAC,KAClC,gBAAgB,CAAC,UAAU,CAAC,CAAC;CAClC,GAAG;IACH,UAAU,EAAE,gBAAgB,CAAC;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CAChB,CAgCA"}
|
|
@@ -2,6 +2,7 @@ import { existsSync, promises as fs } from "node:fs";
|
|
|
2
2
|
import { dirname } from "node:path";
|
|
3
3
|
import { AnyAccountStorageSchema, safeParseJson } from "../schemas.js";
|
|
4
4
|
import { shouldRetryFileOperation } from "../fs-retry.js";
|
|
5
|
+
import { tempPathFor } from "../temp-path.js";
|
|
5
6
|
const EXPORT_RENAME_MAX_ATTEMPTS = 4;
|
|
6
7
|
const EXPORT_RENAME_BASE_DELAY_MS = 25;
|
|
7
8
|
const MAX_IMPORT_BYTES = 4 * 1024 * 1024;
|
|
@@ -64,8 +65,7 @@ export async function exportAccountsToFile(params) {
|
|
|
64
65
|
activeIndex: params.storage.activeIndex,
|
|
65
66
|
activeIndexByFamily: params.storage.activeIndexByFamily,
|
|
66
67
|
}, null, 2);
|
|
67
|
-
const
|
|
68
|
-
const tempPath = `${params.resolvedPath}.${uniqueSuffix}.tmp`;
|
|
68
|
+
const tempPath = tempPathFor(params.resolvedPath);
|
|
69
69
|
try {
|
|
70
70
|
await fs.writeFile(tempPath, content, {
|
|
71
71
|
encoding: "utf-8",
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import type { AccountIdSource } from "../types.js";
|
|
10
10
|
import type { AccountStorageV3, CooldownReason } from "./public-types.js";
|
|
11
|
-
|
|
11
|
+
interface AccountMetadataV1 {
|
|
12
12
|
accountId?: string;
|
|
13
13
|
accountIdSource?: AccountIdSource;
|
|
14
14
|
accountLabel?: string;
|
|
@@ -32,4 +32,5 @@ export interface AccountStorageV1 {
|
|
|
32
32
|
activeIndex: number;
|
|
33
33
|
}
|
|
34
34
|
export declare function migrateV1ToV3(v1: AccountStorageV1): AccountStorageV3;
|
|
35
|
+
export {};
|
|
35
36
|
//# sourceMappingURL=migrations.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"migrations.d.ts","sourceRoot":"","sources":["../../../lib/storage/migrations.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,KAAK,EACX,gBAAgB,EAChB,cAAc,EAEd,MAAM,mBAAmB,CAAC;AAE3B,
|
|
1
|
+
{"version":3,"file":"migrations.d.ts","sourceRoot":"","sources":["../../../lib/storage/migrations.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,KAAK,EACX,gBAAgB,EAChB,cAAc,EAEd,MAAM,mBAAmB,CAAC;AAE3B,UAAU,iBAAiB;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,uDAAuD;IACvD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,+DAA+D;IAC/D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,CAAC,EACd,YAAY,GACZ,SAAS,GACT,UAAU,GACV,MAAM,GACN,SAAS,GACT,QAAQ,CAAC;IACZ,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,cAAc,CAAC,EAAE,cAAc,CAAC;CAChC;AAED,MAAM,WAAW,gBAAgB;IAChC,OAAO,EAAE,CAAC,CAAC;IACX,QAAQ,EAAE,iBAAiB,EAAE,CAAC;IAC9B,WAAW,EAAE,MAAM,CAAC;CACpB;AAMD,wBAAgB,aAAa,CAAC,EAAE,EAAE,gBAAgB,GAAG,gBAAgB,CAiCpE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../lib/storage.ts"],"names":[],"mappings":"AA+BA,OAAO,EACN,KAAK,cAAc,EAGnB,KAAK,iBAAiB,EAEtB,MAAM,8BAA8B,CAAC;AAkBtC,OAAO,EAEN,KAAK,oBAAoB,EACzB,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../lib/storage.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/storage.js
CHANGED
|
@@ -31,6 +31,7 @@ import { computeSha256 } from "./storage/hash.js";
|
|
|
31
31
|
import { ensureCodexGitignoreEntry } from "./storage/gitignore.js";
|
|
32
32
|
import { exportAccountsToFile, mergeImportedAccounts, readImportFile, } from "./storage/import-export.js";
|
|
33
33
|
import { formatStorageErrorHint } from "./storage/error-hints.js";
|
|
34
|
+
import { tempFileNonce, tempPathFor } from "./temp-path.js";
|
|
34
35
|
export { StorageError } from "./errors.js";
|
|
35
36
|
export { formatStorageErrorHint, toStorageError, } from "./storage/error-hints.js";
|
|
36
37
|
export { getAccountIdentityKey, normalizeEmailKey, } from "./storage/identity.js";
|
|
@@ -143,7 +144,7 @@ function renameFileWithRetry(sourcePath, destinationPath) {
|
|
|
143
144
|
}
|
|
144
145
|
async function createRotatingAccountsBackup(path) {
|
|
145
146
|
const candidates = getAccountsBackupRecoveryCandidates(path, ACCOUNTS_BACKUP_HISTORY_DEPTH);
|
|
146
|
-
const rotationNonce =
|
|
147
|
+
const rotationNonce = tempFileNonce();
|
|
147
148
|
const stagedWrites = [];
|
|
148
149
|
const buildStagedPath = (targetPath, label) => `${targetPath}.rotate.${rotationNonce}.${label}.tmp`;
|
|
149
150
|
try {
|
|
@@ -731,7 +732,7 @@ export function resolveAccountSelectionIndex(accounts, candidate, fallbackIndex
|
|
|
731
732
|
return matchedIndex;
|
|
732
733
|
return clampIndex(fallbackIndex, accounts.length);
|
|
733
734
|
}
|
|
734
|
-
function
|
|
735
|
+
function deduplicateAccountsByIdentityPass(accounts) {
|
|
735
736
|
const deduplicated = [];
|
|
736
737
|
for (const account of accounts) {
|
|
737
738
|
if (!account)
|
|
@@ -745,6 +746,21 @@ function deduplicateAccountsByIdentity(accounts) {
|
|
|
745
746
|
}
|
|
746
747
|
return deduplicated;
|
|
747
748
|
}
|
|
749
|
+
function deduplicateAccountsByIdentity(accounts) {
|
|
750
|
+
// A single pass is not a fixpoint: a newest-wins merge can replace a kept
|
|
751
|
+
// entry with an account that itself duplicates an earlier survivor through
|
|
752
|
+
// a different matching tier (e.g. an email-tier merge installs an account
|
|
753
|
+
// whose accountId + refresh token already match a record that carried no
|
|
754
|
+
// email). Re-run until stable; every merge strictly shrinks the array, so
|
|
755
|
+
// this terminates after at most accounts.length passes.
|
|
756
|
+
let current = deduplicateAccountsByIdentityPass(accounts);
|
|
757
|
+
for (;;) {
|
|
758
|
+
const next = deduplicateAccountsByIdentityPass(current);
|
|
759
|
+
if (next.length === current.length)
|
|
760
|
+
return next;
|
|
761
|
+
current = next;
|
|
762
|
+
}
|
|
763
|
+
}
|
|
748
764
|
/**
|
|
749
765
|
* Removes duplicate accounts, keeping the most recently used entry for each
|
|
750
766
|
* safely matched identity.
|
|
@@ -1390,26 +1406,17 @@ async function saveAccountsUnlocked(storage) {
|
|
|
1390
1406
|
},
|
|
1391
1407
|
writeTemp: (tempPath, content) => withFileOperationRetry(() => fs.writeFile(tempPath, content, { encoding: "utf-8", mode: 0o600 })),
|
|
1392
1408
|
statTemp: (tempPath) => fs.stat(tempPath),
|
|
1393
|
-
renameTempToPath:
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
await new Promise((r) => setTimeout(r, 10 * 2 ** attempt));
|
|
1405
|
-
continue;
|
|
1406
|
-
}
|
|
1407
|
-
throw renameError;
|
|
1408
|
-
}
|
|
1409
|
-
}
|
|
1410
|
-
if (lastError)
|
|
1411
|
-
throw lastError;
|
|
1412
|
-
},
|
|
1409
|
+
renameTempToPath: (tempPath) =>
|
|
1410
|
+
// Windows can hold the destination briefly (AV/indexer); retry only the
|
|
1411
|
+
// lock codes rename actually surfaces there, on the original
|
|
1412
|
+
// 10ms-doubling schedule. (The hand-rolled loop this replaces also
|
|
1413
|
+
// slept once more after the final failure; withRetry rethrows
|
|
1414
|
+
// immediately instead.)
|
|
1415
|
+
withRetry(() => fs.rename(tempPath, path), {
|
|
1416
|
+
maxAttempts: 5,
|
|
1417
|
+
backoffMs: (attempt) => 10 * 2 ** (attempt - 1),
|
|
1418
|
+
retryableCodes: ["EPERM", "EBUSY"],
|
|
1419
|
+
}),
|
|
1413
1420
|
cleanupResetMarker: async () => {
|
|
1414
1421
|
try {
|
|
1415
1422
|
await fs.unlink(resetMarkerPath);
|
|
@@ -1453,7 +1460,7 @@ async function saveAccountsUnlocked(storage) {
|
|
|
1453
1460
|
return new StorageError(`Failed to save accounts: ${err?.message || "Unknown error"}`, code, path, hint, err instanceof Error ? err : undefined);
|
|
1454
1461
|
},
|
|
1455
1462
|
backupPath: getAccountsBackupPath(path),
|
|
1456
|
-
createTempPath: () =>
|
|
1463
|
+
createTempPath: () => tempPathFor(path),
|
|
1457
1464
|
});
|
|
1458
1465
|
}
|
|
1459
1466
|
function cloneFlaggedStorageForPersistence(storage) {
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unpredictable nonce for temp/staging file names: `<pid>.<epochMs>.<hex8>`.
|
|
3
|
+
*
|
|
4
|
+
* The random component comes from `crypto.randomBytes` instead of
|
|
5
|
+
* `Math.random()`. `Math.random()` output is predictable once its internal
|
|
6
|
+
* state is known, so a local attacker who can observe one staged path could
|
|
7
|
+
* predict the next one and pre-create (or symlink) it before the atomic
|
|
8
|
+
* write-then-rename lands. An 8-hex-char CSPRNG suffix removes that
|
|
9
|
+
* predictability while keeping names short and `endsWith(".tmp")`-sweepable.
|
|
10
|
+
*
|
|
11
|
+
* Assumes the process CSPRNG is available: `randomBytes` throws on entropy
|
|
12
|
+
* failure (e.g. misconfigured FIPS builds), which is the correct outcome here —
|
|
13
|
+
* the same crypto primitives back the OAuth flow itself, so staging a token
|
|
14
|
+
* file with weaker randomness instead would be strictly worse.
|
|
15
|
+
*/
|
|
16
|
+
export declare function tempFileNonce(): string;
|
|
17
|
+
/**
|
|
18
|
+
* Staging path for an atomic write-then-rename of `targetPath`:
|
|
19
|
+
* `<targetPath>.<pid>.<epochMs>.<hex8>.tmp`.
|
|
20
|
+
*
|
|
21
|
+
* Keeps the trailing `.tmp` extension so existing stale-artifact sweepers
|
|
22
|
+
* (`entry.name.endsWith(".tmp")` in lib/storage.ts, lib/runtime-paths.ts,
|
|
23
|
+
* lib/oc-chatgpt-target-detection.ts) continue to skip/collect staged files.
|
|
24
|
+
*/
|
|
25
|
+
export declare function tempPathFor(targetPath: string): string;
|
|
26
|
+
//# sourceMappingURL=temp-path.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"temp-path.d.ts","sourceRoot":"","sources":["../../lib/temp-path.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAEtD"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { randomBytes } from "node:crypto";
|
|
2
|
+
/**
|
|
3
|
+
* Unpredictable nonce for temp/staging file names: `<pid>.<epochMs>.<hex8>`.
|
|
4
|
+
*
|
|
5
|
+
* The random component comes from `crypto.randomBytes` instead of
|
|
6
|
+
* `Math.random()`. `Math.random()` output is predictable once its internal
|
|
7
|
+
* state is known, so a local attacker who can observe one staged path could
|
|
8
|
+
* predict the next one and pre-create (or symlink) it before the atomic
|
|
9
|
+
* write-then-rename lands. An 8-hex-char CSPRNG suffix removes that
|
|
10
|
+
* predictability while keeping names short and `endsWith(".tmp")`-sweepable.
|
|
11
|
+
*
|
|
12
|
+
* Assumes the process CSPRNG is available: `randomBytes` throws on entropy
|
|
13
|
+
* failure (e.g. misconfigured FIPS builds), which is the correct outcome here —
|
|
14
|
+
* the same crypto primitives back the OAuth flow itself, so staging a token
|
|
15
|
+
* file with weaker randomness instead would be strictly worse.
|
|
16
|
+
*/
|
|
17
|
+
export function tempFileNonce() {
|
|
18
|
+
return `${process.pid}.${Date.now()}.${randomBytes(4).toString("hex")}`;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Staging path for an atomic write-then-rename of `targetPath`:
|
|
22
|
+
* `<targetPath>.<pid>.<epochMs>.<hex8>.tmp`.
|
|
23
|
+
*
|
|
24
|
+
* Keeps the trailing `.tmp` extension so existing stale-artifact sweepers
|
|
25
|
+
* (`entry.name.endsWith(".tmp")` in lib/storage.ts, lib/runtime-paths.ts,
|
|
26
|
+
* lib/oc-chatgpt-target-detection.ts) continue to skip/collect staged files.
|
|
27
|
+
*/
|
|
28
|
+
export function tempPathFor(targetPath) {
|
|
29
|
+
return `${targetPath}.${tempFileNonce()}.tmp`;
|
|
30
|
+
}
|
package/dist/lib/ui/theme.d.ts
CHANGED
|
@@ -5,14 +5,14 @@ export type UiColorProfile = "ansi16" | "ansi256" | "truecolor";
|
|
|
5
5
|
export type UiGlyphMode = "ascii" | "unicode" | "auto";
|
|
6
6
|
export type UiPalette = "green" | "blue";
|
|
7
7
|
export type UiAccent = "green" | "cyan" | "blue" | "yellow";
|
|
8
|
-
|
|
8
|
+
interface UiGlyphSet {
|
|
9
9
|
selected: string;
|
|
10
10
|
unselected: string;
|
|
11
11
|
bullet: string;
|
|
12
12
|
check: string;
|
|
13
13
|
cross: string;
|
|
14
14
|
}
|
|
15
|
-
|
|
15
|
+
interface UiThemeColors {
|
|
16
16
|
reset: string;
|
|
17
17
|
dim: string;
|
|
18
18
|
muted: string;
|
|
@@ -66,4 +66,5 @@ export declare function createUiTheme(options?: {
|
|
|
66
66
|
accent?: UiAccent;
|
|
67
67
|
disableColor?: boolean;
|
|
68
68
|
}): UiTheme;
|
|
69
|
+
export {};
|
|
69
70
|
//# sourceMappingURL=theme.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"theme.d.ts","sourceRoot":"","sources":["../../../lib/ui/theme.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,SAAS,GAAG,WAAW,CAAC;AAChE,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;AACvD,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,MAAM,CAAC;AACzC,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,QAAQ,CAAC;AAE5D,
|
|
1
|
+
{"version":3,"file":"theme.d.ts","sourceRoot":"","sources":["../../../lib/ui/theme.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,SAAS,GAAG,WAAW,CAAC;AAChE,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;AACvD,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,MAAM,CAAC;AACzC,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,QAAQ,CAAC;AAE5D,UAAU,UAAU;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACd;AAED,UAAU,aAAa;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,OAAO;IACvB,OAAO,EAAE,cAAc,CAAC;IACxB,SAAS,EAAE,WAAW,CAAC;IACvB,MAAM,EAAE,UAAU,CAAC;IACnB,MAAM,EAAE,aAAa,CAAC;CACtB;AAiKD;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CACjC,GAAG,GAAE,MAAM,CAAC,UAAwB,EACpC,KAAK,GAAE,OAAwC,GAC7C,OAAO,CAMT;AAWD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,aAAa,CAAC,OAAO,CAAC,EAAE;IACvC,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,SAAS,CAAC,EAAE,WAAW,CAAC;IACxB,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,MAAM,CAAC,EAAE,QAAQ,CAAC;IAClB,YAAY,CAAC,EAAE,OAAO,CAAC;CACvB,GAAG,OAAO,CAgBV"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"unified-settings.d.ts","sourceRoot":"","sources":["../../lib/unified-settings.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"unified-settings.d.ts","sourceRoot":"","sources":["../../lib/unified-settings.ts"],"names":[],"mappings":"AAeA,KAAK,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAE1C,eAAO,MAAM,wBAAwB,EAAG,CAAU,CAAC;AA2bnD;;;;;;GAMG;AACH,wBAAgB,sBAAsB,IAAI,MAAM,CAE/C;AAED;;;;;;;;GAQG;AACH,wBAAgB,2BAA2B,IAAI,UAAU,GAAG,IAAI,CAQ/D;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,2BAA2B,CAAC,YAAY,EAAE,UAAU,GAAG,IAAI,CAO1E;AAED;;;;;;;;;GASG;AACH,wBAAsB,uBAAuB,CAAC,YAAY,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAsBrF;AAED;;;;;;;;GAQG;AACH,wBAAsB,4BAA4B,IAAI,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAQ/E;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,4BAA4B,CACjD,wBAAwB,EAAE,UAAU,GAClC,OAAO,CAAC,IAAI,CAAC,CAsBf"}
|
|
@@ -2,6 +2,7 @@ import { copyFileSync, existsSync, mkdirSync, renameSync, readFileSync, unlinkSy
|
|
|
2
2
|
import { join } from "node:path";
|
|
3
3
|
import { getCodexMultiAuthDir } from "./runtime-paths.js";
|
|
4
4
|
import { sleep } from "./utils.js";
|
|
5
|
+
import { tempPathFor } from "./temp-path.js";
|
|
5
6
|
export const UNIFIED_SETTINGS_VERSION = 1;
|
|
6
7
|
const UNIFIED_SETTINGS_PATH = join(getCodexMultiAuthDir(), "settings.json");
|
|
7
8
|
const UNIFIED_SETTINGS_BACKUP_PATH = `${UNIFIED_SETTINGS_PATH}.bak`;
|
|
@@ -341,7 +342,7 @@ async function writeSettingsRecordAsync(record, options) {
|
|
|
341
342
|
await fs.mkdir(getCodexMultiAuthDir(), { recursive: true });
|
|
342
343
|
const payload = normalizeForWrite(record);
|
|
343
344
|
const data = `${JSON.stringify(payload, null, 2)}\n`;
|
|
344
|
-
const tempPath =
|
|
345
|
+
const tempPath = tempPathFor(UNIFIED_SETTINGS_PATH);
|
|
345
346
|
await trySnapshotUnifiedSettingsBackupAsync({
|
|
346
347
|
skipBecauseBackupRead: options?.skipBackupSnapshot,
|
|
347
348
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"update-notice.d.ts","sourceRoot":"","sources":["../../lib/update-notice.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"update-notice.d.ts","sourceRoot":"","sources":["../../lib/update-notice.ts"],"names":[],"mappings":"AA2CA,MAAM,WAAW,iBAAiB;IACjC,SAAS,EAAE,OAAO,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,aAAa,EAAE,MAAM,CAAC;CACtB;AA+DD,wBAAgB,+BAA+B,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAmBzE;AA0JD,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM,CAM1E;AAED,wBAAsB,eAAe,CACpC,KAAK,UAAQ,EACb,cAAc,SAA0B,GACtC,OAAO,CAAC,iBAAiB,CAAC,CAwC5B;AAED,wBAAsB,cAAc,CACnC,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,SAAS,KAAK,OAAO,CAAC,IAAI,CAAC,GACzE,OAAO,CAAC,IAAI,CAAC,CAoBf;AAED,wBAAgB,gBAAgB,IAAI,IAAI,CAUvC"}
|
|
@@ -3,6 +3,7 @@ import { dirname, join } from "node:path";
|
|
|
3
3
|
import { fileURLToPath } from "node:url";
|
|
4
4
|
import { createLogger } from "./logger.js";
|
|
5
5
|
import { getCodexCacheDir } from "./runtime-paths.js";
|
|
6
|
+
import { tempPathFor } from "./temp-path.js";
|
|
6
7
|
const log = createLogger("update-notice");
|
|
7
8
|
const PACKAGE_NAME = "codex-multi-auth";
|
|
8
9
|
const NPM_REGISTRY_URL = `https://registry.npmjs.org/${PACKAGE_NAME}/latest`;
|
|
@@ -34,7 +35,7 @@ async function writeCacheContents(serialized) {
|
|
|
34
35
|
if (!existsSync(CACHE_DIR)) {
|
|
35
36
|
mkdirSync(CACHE_DIR, { recursive: true });
|
|
36
37
|
}
|
|
37
|
-
tempPath =
|
|
38
|
+
tempPath = tempPathFor(CACHE_FILE);
|
|
38
39
|
let lastError = null;
|
|
39
40
|
for (let attempt = 0; attempt < 4; attempt++) {
|
|
40
41
|
try {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codex-multi-auth",
|
|
3
|
-
"version": "2.3.0-beta.
|
|
3
|
+
"version": "2.3.0-beta.3",
|
|
4
4
|
"description": "Codex CLI multi-account OAuth manager with account switching, health checks, runtime rotation, diagnostics, and recovery tools for @openai/codex",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -156,7 +156,6 @@
|
|
|
156
156
|
"node": ">=18.17.0"
|
|
157
157
|
},
|
|
158
158
|
"devDependencies": {
|
|
159
|
-
"@fast-check/vitest": "^0.2.4",
|
|
160
159
|
"@types/node": "^20.19.42",
|
|
161
160
|
"@typescript-eslint/eslint-plugin": "^8.56.0",
|
|
162
161
|
"@typescript-eslint/parser": "^8.56.0",
|