codex-multi-auth 0.1.7 → 0.1.9

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.
Files changed (64) hide show
  1. package/LICENSE +21 -1
  2. package/README.md +16 -3
  3. package/assets/readme-hero.svg +31 -31
  4. package/dist/index.d.ts +1 -1
  5. package/dist/index.d.ts.map +1 -1
  6. package/dist/index.js +38 -65
  7. package/dist/index.js.map +1 -1
  8. package/dist/lib/accounts.d.ts.map +1 -1
  9. package/dist/lib/accounts.js +29 -10
  10. package/dist/lib/accounts.js.map +1 -1
  11. package/dist/lib/codex-cli/sync.d.ts +9 -16
  12. package/dist/lib/codex-cli/sync.d.ts.map +1 -1
  13. package/dist/lib/codex-cli/sync.js +51 -284
  14. package/dist/lib/codex-cli/sync.js.map +1 -1
  15. package/dist/lib/codex-manager/settings-hub.d.ts +44 -2
  16. package/dist/lib/codex-manager/settings-hub.d.ts.map +1 -1
  17. package/dist/lib/codex-manager/settings-hub.js +746 -117
  18. package/dist/lib/codex-manager/settings-hub.js.map +1 -1
  19. package/dist/lib/codex-manager.d.ts.map +1 -1
  20. package/dist/lib/codex-manager.js +240 -216
  21. package/dist/lib/codex-manager.js.map +1 -1
  22. package/dist/lib/context-overflow.js +10 -10
  23. package/dist/lib/entitlement-cache.d.ts +8 -5
  24. package/dist/lib/entitlement-cache.d.ts.map +1 -1
  25. package/dist/lib/entitlement-cache.js +24 -9
  26. package/dist/lib/entitlement-cache.js.map +1 -1
  27. package/dist/lib/named-backup-export.d.ts +69 -0
  28. package/dist/lib/named-backup-export.d.ts.map +1 -0
  29. package/dist/lib/named-backup-export.js +207 -0
  30. package/dist/lib/named-backup-export.js.map +1 -0
  31. package/dist/lib/oc-chatgpt-import-adapter.d.ts +64 -0
  32. package/dist/lib/oc-chatgpt-import-adapter.d.ts.map +1 -0
  33. package/dist/lib/oc-chatgpt-import-adapter.js +522 -0
  34. package/dist/lib/oc-chatgpt-import-adapter.js.map +1 -0
  35. package/dist/lib/oc-chatgpt-orchestrator.d.ts +80 -0
  36. package/dist/lib/oc-chatgpt-orchestrator.d.ts.map +1 -0
  37. package/dist/lib/oc-chatgpt-orchestrator.js +130 -0
  38. package/dist/lib/oc-chatgpt-orchestrator.js.map +1 -0
  39. package/dist/lib/oc-chatgpt-target-detection.d.ts +59 -0
  40. package/dist/lib/oc-chatgpt-target-detection.d.ts.map +1 -0
  41. package/dist/lib/oc-chatgpt-target-detection.js +327 -0
  42. package/dist/lib/oc-chatgpt-target-detection.js.map +1 -0
  43. package/dist/lib/prompts/codex.js +2 -2
  44. package/dist/lib/runtime-paths.d.ts.map +1 -1
  45. package/dist/lib/runtime-paths.js +21 -1
  46. package/dist/lib/runtime-paths.js.map +1 -1
  47. package/dist/lib/storage.d.ts +67 -16
  48. package/dist/lib/storage.d.ts.map +1 -1
  49. package/dist/lib/storage.js +797 -169
  50. package/dist/lib/storage.js.map +1 -1
  51. package/dist/lib/ui/copy.d.ts +15 -1
  52. package/dist/lib/ui/copy.d.ts.map +1 -1
  53. package/dist/lib/ui/copy.js +15 -1
  54. package/dist/lib/ui/copy.js.map +1 -1
  55. package/package.json +130 -131
  56. package/scripts/bench-format/hashline-v2.mjs +642 -642
  57. package/scripts/bench-format/render.mjs +496 -496
  58. package/scripts/bench-format/stats.mjs +54 -54
  59. package/scripts/bench-format/tasks.mjs +151 -151
  60. package/scripts/benchmark-render-dashboard.mjs +49 -49
  61. package/scripts/install-codex-auth.js +9 -9
  62. package/scripts/test-all-models.sh +7 -7
  63. package/scripts/test-model-matrix.js +138 -46
  64. package/scripts/validate-model-map.sh +7 -7
@@ -0,0 +1,522 @@
1
+ import { MODEL_FAMILIES } from "./prompts/codex.js";
2
+ import { findMatchingAccountIndex, getAccountIdentityKey, normalizeEmailKey, } from "./storage.js";
3
+ /**
4
+ * Clamp a numeric index to the valid range for an array of the given length.
5
+ *
6
+ * @param index - Desired index; non-finite values are treated as 0
7
+ * @param length - Array length; lengths less than or equal to 0 produce 0
8
+ * @returns A safe index between 0 and `length - 1` (or 0 when `length <= 0` or `index` is not finite)
9
+ */
10
+ function clampIndex(index, length) {
11
+ if (length <= 0)
12
+ return 0;
13
+ if (!Number.isFinite(index))
14
+ return 0;
15
+ return Math.max(0, Math.min(index, length - 1));
16
+ }
17
+ /**
18
+ * Selects the newer of two timestamped records.
19
+ *
20
+ * Compares `lastUsed` first (larger wins); if equal, compares `addedAt` (larger wins); ties prefer `current`.
21
+ *
22
+ * @param current - The current record to compare.
23
+ * @param candidate - The candidate record to compare against `current`.
24
+ * @returns The record considered newer: `candidate` if it is newer by `lastUsed` or `addedAt`, otherwise `current`.
25
+ */
26
+ function pickNewest(current, candidate) {
27
+ const currentLastUsed = Number.isFinite(current.lastUsed)
28
+ ? current.lastUsed
29
+ : 0;
30
+ const candidateLastUsed = Number.isFinite(candidate.lastUsed)
31
+ ? candidate.lastUsed
32
+ : 0;
33
+ if (candidateLastUsed > currentLastUsed)
34
+ return candidate;
35
+ if (candidateLastUsed < currentLastUsed)
36
+ return current;
37
+ const currentAdded = Number.isFinite(current.addedAt)
38
+ ? current.addedAt
39
+ : 0;
40
+ const candidateAdded = Number.isFinite(candidate.addedAt)
41
+ ? candidate.addedAt
42
+ : 0;
43
+ return candidateAdded > currentAdded ? candidate : current;
44
+ }
45
+ /**
46
+ * Sanitize and normalize an AccountMetadataV3, returning null when the refresh token is missing or empty.
47
+ *
48
+ * Trims string fields (`refreshToken`, `accountId`, `email`, `accountLabel`), coercing empty trimmed values to `undefined` for optional fields.
49
+ * Ensures `addedAt` and `lastUsed` are finite numbers, defaulting to `0` when not.
50
+ * The refresh token is preserved (trimmed) for downstream use; callers are responsible for any redaction or secure handling.
51
+ * This function has no filesystem or concurrency side effects.
52
+ *
53
+ * @param account - The account metadata to sanitize
54
+ * @returns A normalized AccountMetadataV3 with trimmed fields and numeric timestamps, or `null` if the refresh token is empty after trimming
55
+ */
56
+ function sanitizeAccount(account) {
57
+ const refreshToken = typeof account.refreshToken === "string" ? account.refreshToken.trim() : "";
58
+ if (!refreshToken)
59
+ return null;
60
+ const accountId = typeof account.accountId === "string"
61
+ ? account.accountId.trim()
62
+ : undefined;
63
+ const email = typeof account.email === "string" ? account.email.trim() : undefined;
64
+ const accountLabel = typeof account.accountLabel === "string"
65
+ ? account.accountLabel.trim()
66
+ : undefined;
67
+ return {
68
+ ...account,
69
+ accountId: accountId || undefined,
70
+ email: email || undefined,
71
+ accountLabel: accountLabel || undefined,
72
+ refreshToken,
73
+ addedAt: Number.isFinite(account.addedAt) ? account.addedAt : 0,
74
+ lastUsed: Number.isFinite(account.lastUsed)
75
+ ? account.lastUsed
76
+ : 0,
77
+ };
78
+ }
79
+ /**
80
+ * Produce a redacted 4-character representation of a refresh token for display.
81
+ *
82
+ * @param token - The raw token string to redact
83
+ * @returns The last four characters of the trimmed token, or a string of asterisks equal to the token length if the trimmed token has four or fewer characters
84
+ */
85
+ function tokenLast4(token) {
86
+ const trimmed = token.trim();
87
+ if (trimmed.length <= 4)
88
+ return "*".repeat(trimmed.length);
89
+ return trimmed.slice(-4);
90
+ }
91
+ /**
92
+ * Create a preview-safe account reference with a masked refresh token.
93
+ *
94
+ * @param account - The account metadata to summarize; its `refreshToken` is read and masked.
95
+ * @returns An `OcChatgptAccountRef` containing `accountId`, `email`, and `refreshTokenLast4` (the last four characters of the trimmed token; if the token length is 4 or fewer characters, a string of asterisks of equal length is returned).
96
+ *
97
+ * Note: This function is pure and has no concurrency or Windows filesystem side effects. Token redaction follows the rule above to avoid exposing full tokens.
98
+ */
99
+ function summarizeAccount(account) {
100
+ return {
101
+ accountId: account.accountId,
102
+ email: account.email,
103
+ refreshTokenLast4: tokenLast4(account.refreshToken),
104
+ };
105
+ }
106
+ /**
107
+ * Build a preview payload summarizing storage for display in an import preview.
108
+ *
109
+ * Produces a versioned payload containing the active index(s) and a list of account references with refresh tokens redacted to their last four characters. No concurrency guarantees are provided by this pure data transformation. This function has no special filesystem behavior on Windows.
110
+ *
111
+ * @param storage - Account storage to summarize into a preview payload
112
+ * @returns A preview payload (version 3) with `activeIndex`, optional `activeIndexByFamily`, and an array of account summaries where refresh tokens are masked to their last four characters
113
+ */
114
+ function buildPreviewPayload(storage) {
115
+ return {
116
+ version: 3,
117
+ activeIndex: storage.activeIndex,
118
+ activeIndexByFamily: storage.activeIndexByFamily
119
+ ? { ...storage.activeIndexByFamily }
120
+ : undefined,
121
+ accounts: storage.accounts.map(summarizeAccount),
122
+ };
123
+ }
124
+ /**
125
+ * Finds the index of an account in `accounts` that corresponds to `target` using normalized matching rules.
126
+ *
127
+ * Matching precedence:
128
+ * 1. Exact `accountId + email` match when both are present.
129
+ * 2. Safe shared matcher fallback, which only uses bare `accountId` when it is unique.
130
+ * 3. Caller fallback to the original position when no safe match exists.
131
+ *
132
+ * @param accounts - The list of normalized destination accounts to search.
133
+ * @param target - The account to match against `accounts`.
134
+ * @returns The index of a matching account in `accounts`, or `null` if no match is found.
135
+ */
136
+ function findNormalizedAccountIndex(accounts, target) {
137
+ if (!target)
138
+ return null;
139
+ return findMatchingAccountIndex(accounts, target) ?? null;
140
+ }
141
+ /**
142
+ * Map an active account index from an original accounts list to the corresponding index in a normalized accounts list.
143
+ *
144
+ * Remaps the provided originalIndex by locating the same account (by id/email/refresh token) in normalizedAccounts; if not found, clamps the original position into the valid range of normalizedAccounts. Concurrency: function is pure and has no side effects. Windows filesystem: not applicable. Token redaction: refresh tokens are not exposed by this function.
145
+ *
146
+ * @param originalAccounts - The source account array that contains the original active index; may be undefined.
147
+ * @param originalIndex - The active index within originalAccounts; may be undefined.
148
+ * @param normalizedAccounts - The target account array after normalization to map into.
149
+ * @returns The index within normalizedAccounts that corresponds to the original active position, clamped to [0, normalizedAccounts.length - 1].
150
+ */
151
+ function remapActiveIndex(originalAccounts, originalIndex, normalizedAccounts) {
152
+ if (!originalAccounts || originalAccounts.length === 0)
153
+ return clampIndex(0, normalizedAccounts.length);
154
+ const safeOriginalIndex = clampIndex(originalIndex ?? 0, originalAccounts.length);
155
+ const originalActive = originalAccounts[safeOriginalIndex];
156
+ const remapped = findNormalizedAccountIndex(normalizedAccounts, originalActive);
157
+ if (remapped !== null)
158
+ return remapped;
159
+ return clampIndex(safeOriginalIndex, normalizedAccounts.length);
160
+ }
161
+ /**
162
+ * Map per-model-family active indices from the original account list to the normalized account list.
163
+ *
164
+ * @param activeIndexByFamily - Optional mapping of model family keys to active account indices from the original storage.
165
+ * @param originalAccounts - The original array of accounts corresponding to `activeIndexByFamily`, used as the source index space.
166
+ * @param normalizedAccounts - The normalized array of accounts to which indices should be remapped.
167
+ * @returns A mapping of model family keys to remapped indices aligned with `normalizedAccounts`, or `undefined` if no valid mappings exist.
168
+ */
169
+ function normalizeActiveIndexByFamily(activeIndexByFamily, originalAccounts, normalizedAccounts) {
170
+ if (!activeIndexByFamily)
171
+ return undefined;
172
+ const normalized = {};
173
+ for (const family of MODEL_FAMILIES) {
174
+ const raw = activeIndexByFamily[family];
175
+ if (typeof raw !== "number" || !Number.isFinite(raw))
176
+ continue;
177
+ normalized[family] = remapActiveIndex(originalAccounts, raw, normalizedAccounts);
178
+ }
179
+ return Object.keys(normalized).length > 0 ? normalized : undefined;
180
+ }
181
+ /**
182
+ * Normalize and de-duplicate a list of account metadata for import into a target store.
183
+ *
184
+ * Processes input accounts by sanitizing entries, removing invalid refresh tokens, and
185
+ * de-duplicating with the following precedence: `accountId + email`, normalized email,
186
+ * then refreshToken. Bare `accountId` rows without an email stay on the refresh-token
187
+ * path so distinct business accounts are not collapsed by a shared workspace id.
188
+ * When duplicates are found the most recently used/added account is kept and the other is recorded
189
+ * in `skipped` with a reason code.
190
+ *
191
+ * Concurrency: this function is synchronous and not safe for concurrent mutation of the same
192
+ * input arrays; callers should handle synchronization. Token redaction: skipped entries include
193
+ * masked token previews (`refreshTokenLast4`) rather than full refresh tokens. No filesystem or
194
+ * Windows-specific behavior is performed here.
195
+ *
196
+ * @param accounts - Array of AccountMetadataV3 to normalize (may contain untrimmed or invalid fields)
197
+ * @returns An object with:
198
+ * - `accounts`: sanitized, de-duplicated AccountMetadataV3 in order of precedence
199
+ * (by `accountId + email`, unique bare `accountId`, by email, by refreshToken)
200
+ * - `skipped`: array of sources summarized as OcChatgptAccountRef with a `reason` string; possible reasons include
201
+ * "invalid-refresh-token", "duplicate-account-id", "duplicate-email", and "duplicate-refresh-token"
202
+ */
203
+ function normalizeAccountsForTarget(accounts) {
204
+ const skipped = [];
205
+ const valid = [];
206
+ for (const candidate of accounts) {
207
+ const sanitized = sanitizeAccount(candidate);
208
+ if (!sanitized) {
209
+ skipped.push({
210
+ source: summarizeAccount({
211
+ ...candidate,
212
+ refreshToken: candidate.refreshToken ?? "",
213
+ }),
214
+ reason: "invalid-refresh-token",
215
+ });
216
+ continue;
217
+ }
218
+ valid.push(sanitized);
219
+ }
220
+ const byAccountIdentity = new Map();
221
+ const withoutAccountId = [];
222
+ for (const account of valid) {
223
+ if (account.accountId && normalizeEmailKey(account.email)) {
224
+ const identityKey = getAccountIdentityKey(account);
225
+ if (!identityKey) {
226
+ withoutAccountId.push(account);
227
+ continue;
228
+ }
229
+ const existing = byAccountIdentity.get(identityKey);
230
+ if (!existing) {
231
+ byAccountIdentity.set(identityKey, account);
232
+ continue;
233
+ }
234
+ const newest = pickNewest(existing, account);
235
+ if (newest === account) {
236
+ byAccountIdentity.set(identityKey, account);
237
+ skipped.push({
238
+ source: summarizeAccount(existing),
239
+ reason: "duplicate-account-id",
240
+ });
241
+ }
242
+ else {
243
+ skipped.push({
244
+ source: summarizeAccount(account),
245
+ reason: "duplicate-account-id",
246
+ });
247
+ }
248
+ continue;
249
+ }
250
+ withoutAccountId.push(account);
251
+ }
252
+ const byEmail = new Map();
253
+ const withoutIdentity = [];
254
+ for (const account of withoutAccountId) {
255
+ const normalizedEmail = normalizeEmailKey(account.email);
256
+ if (normalizedEmail) {
257
+ const existing = byEmail.get(normalizedEmail);
258
+ if (!existing) {
259
+ byEmail.set(normalizedEmail, account);
260
+ continue;
261
+ }
262
+ const newest = pickNewest(existing, account);
263
+ if (newest === account) {
264
+ byEmail.set(normalizedEmail, account);
265
+ skipped.push({
266
+ source: summarizeAccount(existing),
267
+ reason: "duplicate-email",
268
+ });
269
+ }
270
+ else {
271
+ skipped.push({
272
+ source: summarizeAccount(account),
273
+ reason: "duplicate-email",
274
+ });
275
+ }
276
+ continue;
277
+ }
278
+ withoutIdentity.push(account);
279
+ }
280
+ const byRefreshToken = new Map();
281
+ for (const account of withoutIdentity) {
282
+ const key = account.refreshToken;
283
+ const existing = byRefreshToken.get(key);
284
+ if (!existing) {
285
+ byRefreshToken.set(key, account);
286
+ continue;
287
+ }
288
+ const newest = pickNewest(existing, account);
289
+ if (newest === account) {
290
+ byRefreshToken.set(key, account);
291
+ skipped.push({
292
+ source: summarizeAccount(existing),
293
+ reason: "duplicate-refresh-token",
294
+ });
295
+ }
296
+ else {
297
+ skipped.push({
298
+ source: summarizeAccount(account),
299
+ reason: "duplicate-refresh-token",
300
+ });
301
+ }
302
+ }
303
+ return {
304
+ accounts: [
305
+ ...byAccountIdentity.values(),
306
+ ...byEmail.values(),
307
+ ...byRefreshToken.values(),
308
+ ],
309
+ skipped,
310
+ };
311
+ }
312
+ /**
313
+ * Normalize an AccountStorageV3 (or null/undefined) for a target by sanitizing and deduplicating accounts, and remapping active indices.
314
+ *
315
+ * @param storage - Source storage to normalize; if null/undefined it is treated as empty storage
316
+ * @returns An object containing `storage` (a normalized `AccountStorageV3` with sanitized accounts, remapped `activeIndex` and optional `activeIndexByFamily`) and `skipped` (array of account summaries with reasons for omission). Tokens in resulting summaries are redacted (last-4 visible); no filesystem or concurrency side effects occur.
317
+ */
318
+ function normalizeStorageForTarget(storage) {
319
+ const { accounts, skipped } = normalizeAccountsForTarget(storage?.accounts ?? []);
320
+ const activeIndex = remapActiveIndex(storage?.accounts, storage?.activeIndex, accounts);
321
+ const activeIndexByFamily = normalizeActiveIndexByFamily(storage?.activeIndexByFamily, storage?.accounts, accounts);
322
+ return {
323
+ storage: {
324
+ version: 3,
325
+ accounts: accounts.map((account) => ({ ...account })),
326
+ activeIndex,
327
+ activeIndexByFamily,
328
+ },
329
+ skipped,
330
+ };
331
+ }
332
+ /**
333
+ * Produce a shallow-cloned copy of an AccountStorageV3 suitable for independent mutation.
334
+ *
335
+ * The returned storage has a new array and new objects for each account (shallow copy of account fields),
336
+ * preserves primitive fields verbatim, and shallow-copies `activeIndexByFamily` if present.
337
+ *
338
+ * @param storage - The source storage to clone; the source is not mutated.
339
+ * @returns A cloned AccountStorageV3 whose accounts and top-level objects can be mutated without affecting the original.
340
+ *
341
+ * Concurrency: safe to use for concurrent reads; concurrent mutations to the original and the clone are not synchronized.
342
+ * Filesystem: this function performs no filesystem I/O and is unaffected by OS-specific filesystem semantics (e.g., Windows).
343
+ * Token handling: refresh tokens and other sensitive fields are copied as-is and are not redacted or transformed.
344
+ */
345
+ function cloneStorage(storage) {
346
+ return {
347
+ version: 3,
348
+ accounts: storage.accounts.map((account) => ({ ...account })),
349
+ activeIndex: storage.activeIndex,
350
+ activeIndexByFamily: storage.activeIndexByFamily
351
+ ? { ...storage.activeIndexByFamily }
352
+ : undefined,
353
+ };
354
+ }
355
+ /**
356
+ * Finds a destination account that corresponds to the given source account by matching
357
+ * in the order: exact `accountId + email`, unique bare `accountId`, normalized `email` (only against destination entries
358
+ * without an `accountId`), then exact `refreshToken` equality across any remaining destination entry.
359
+ *
360
+ * Concurrency: caller must manage concurrent access to the destination array and `usedIndexes`.
361
+ * Filesystem: no filesystem interactions or Windows-specific behavior.
362
+ * Token handling: refresh tokens are compared as stored; any redaction for display occurs elsewhere.
363
+ *
364
+ * @param source - The source account to find a match for; `accountId` is trimmed and `email` is normalized.
365
+ * @param destination - Array of destination accounts to search; entries in `usedIndexes` are ignored.
366
+ * @param usedIndexes - Indexes in `destination` that have already been matched and should be skipped.
367
+ * @returns An object with `index` of the matching destination entry and `matchedBy` indicating the match strategy,
368
+ * or `null` if no match was found.
369
+ */
370
+ function matchDestination(source, destination, usedIndexes) {
371
+ const sourceAccountId = source.accountId?.trim();
372
+ const sourceEmail = normalizeEmailKey(source.email);
373
+ if (sourceAccountId && sourceEmail) {
374
+ const sourceIdentityKey = getAccountIdentityKey(source);
375
+ const idx = destination.findIndex((account, i) => !usedIndexes.has(i) &&
376
+ getAccountIdentityKey(account) === sourceIdentityKey);
377
+ if (idx >= 0)
378
+ return { index: idx, matchedBy: "accountId" };
379
+ }
380
+ if (sourceAccountId) {
381
+ let idx = null;
382
+ let matchedEmail;
383
+ for (let i = 0; i < destination.length; i += 1) {
384
+ if (usedIndexes.has(i))
385
+ continue;
386
+ const account = destination[i];
387
+ if (!account)
388
+ continue;
389
+ if (account.accountId?.trim() !== sourceAccountId)
390
+ continue;
391
+ if (idx !== null) {
392
+ idx = null;
393
+ break;
394
+ }
395
+ idx = i;
396
+ matchedEmail = normalizeEmailKey(account.email);
397
+ }
398
+ if (idx !== null &&
399
+ (!sourceEmail || !matchedEmail || matchedEmail === sourceEmail)) {
400
+ return { index: idx, matchedBy: "accountId" };
401
+ }
402
+ }
403
+ if (sourceEmail) {
404
+ const idx = destination.findIndex((account, i) => {
405
+ if (usedIndexes.has(i))
406
+ return false;
407
+ if (account.accountId)
408
+ return false;
409
+ return normalizeEmailKey(account.email) === sourceEmail;
410
+ });
411
+ if (idx >= 0)
412
+ return { index: idx, matchedBy: "email" };
413
+ }
414
+ const idx = destination.findIndex((account, i) => {
415
+ if (usedIndexes.has(i))
416
+ return false;
417
+ if (account.accountId)
418
+ return false;
419
+ if (normalizeEmailKey(account.email))
420
+ return false;
421
+ return account.refreshToken === source.refreshToken;
422
+ });
423
+ if (idx >= 0)
424
+ return { index: idx, matchedBy: "refreshToken" };
425
+ return null;
426
+ }
427
+ /**
428
+ * Produce a normalized AccountStorageV3 payload suitable for OC ChatGPT import.
429
+ *
430
+ * Normalizes and sanitizes the provided source storage for the target importer.
431
+ *
432
+ * @param source - The source AccountStorageV3 to normalize, or `null` to normalize an empty input.
433
+ * @returns A normalized AccountStorageV3 ready for import. WARNING: this object may include raw `refreshToken` values; redact or mask tokens before logging, persisting to logs, or transmitting to external systems.
434
+ *
435
+ * Concurrency notes: the function does not perform synchronization; callers are responsible for coordinating concurrent access to the source data.
436
+ *
437
+ * Filesystem note: the function performs in-memory transformations only and has no special behavior for Windows filesystem semantics.
438
+ */
439
+ export function buildOcChatgptImportPayload(source) {
440
+ const { storage } = normalizeStorageForTarget(source ?? null);
441
+ return storage;
442
+ }
443
+ /**
444
+ * Produces a detailed merge preview and merged storage that reconciles a source and destination AccountStorageV3.
445
+ *
446
+ * Normalizes source and destination inputs, identifies accounts to add, update, or skip (with reasons), preserves
447
+ * destination-only unchanged accounts, and returns a merged AccountStorageV3 plus a preview payload. Refresh tokens
448
+ * in preview entries are redacted (masked to last four characters). The function is synchronous, stateless, performs
449
+ * no filesystem I/O (no Windows-specific behavior), and is safe to call concurrently from multiple callers.
450
+ *
451
+ * @param options.source - Source storage to import from; may be `null`.
452
+ * @param options.destination - Destination storage to merge into; may be `null`.
453
+ * @returns An OcChatgptMergePreview describing the normalized source preview (`payload`), the resulting merged storage
454
+ * (`merged`), lists of accounts to add (`toAdd`), accounts updated with previous/next summaries (`toUpdate`),
455
+ * skipped accounts with reasons (`toSkip`), destination-only unchanged accounts (`unchangedDestinationOnly`),
456
+ * and an `activeSelectionBehavior` hint.
457
+ */
458
+ export function previewOcChatgptImportMerge(options) {
459
+ const sourceNormalized = normalizeStorageForTarget(options.source);
460
+ const destinationNormalized = normalizeStorageForTarget(options.destination);
461
+ const merged = cloneStorage(destinationNormalized.storage);
462
+ const destinationAccounts = merged.accounts.slice(0, destinationNormalized.storage.accounts.length);
463
+ const usedDestinationIndexes = new Set();
464
+ const toAdd = [];
465
+ const toUpdate = [];
466
+ const toSkip = [
467
+ ...sourceNormalized.skipped,
468
+ ...destinationNormalized.skipped.map(({ source, reason }) => ({
469
+ source,
470
+ reason: `destination-${reason}`,
471
+ })),
472
+ ];
473
+ for (const account of sourceNormalized.storage.accounts) {
474
+ const match = matchDestination(account, destinationAccounts, usedDestinationIndexes);
475
+ if (!match) {
476
+ merged.accounts.push({ ...account });
477
+ toAdd.push(summarizeAccount(account));
478
+ continue;
479
+ }
480
+ const current = merged.accounts[match.index];
481
+ if (!current) {
482
+ merged.accounts[match.index] = { ...account };
483
+ toAdd.push(summarizeAccount(account));
484
+ continue;
485
+ }
486
+ const newest = pickNewest(current, account);
487
+ usedDestinationIndexes.add(match.index);
488
+ if (newest === current) {
489
+ toSkip.push({
490
+ source: summarizeAccount(account),
491
+ reason: "unchanged-or-older-than-destination",
492
+ });
493
+ continue;
494
+ }
495
+ merged.accounts[match.index] = { ...newest };
496
+ toUpdate.push({
497
+ previous: summarizeAccount(current),
498
+ next: summarizeAccount(newest),
499
+ matchedBy: match.matchedBy,
500
+ });
501
+ }
502
+ const destinationLength = destinationNormalized.storage.accounts.length;
503
+ const unchangedDestinationOnly = [];
504
+ for (let i = 0; i < destinationLength; i += 1) {
505
+ if (usedDestinationIndexes.has(i))
506
+ continue;
507
+ const account = destinationNormalized.storage.accounts[i];
508
+ if (!account)
509
+ continue;
510
+ unchangedDestinationOnly.push(summarizeAccount(account));
511
+ }
512
+ return {
513
+ payload: buildPreviewPayload(sourceNormalized.storage),
514
+ merged,
515
+ toAdd,
516
+ toUpdate,
517
+ toSkip,
518
+ unchangedDestinationOnly,
519
+ activeSelectionBehavior: "preserve-destination",
520
+ };
521
+ }
522
+ //# sourceMappingURL=oc-chatgpt-import-adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oc-chatgpt-import-adapter.js","sourceRoot":"","sources":["../../lib/oc-chatgpt-import-adapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,80 @@
1
+ import { type OcChatgptMergePreview, type OcChatgptPreviewPayload, previewOcChatgptImportMerge } from "./oc-chatgpt-import-adapter.js";
2
+ import { detectOcChatgptMultiAuthTarget, type OcChatgptTargetAmbiguous, type OcChatgptTargetDescriptor, type OcChatgptTargetNone } from "./oc-chatgpt-target-detection.js";
3
+ import { type AccountStorageV3, exportNamedBackup } from "./storage.js";
4
+ type BlockedAmbiguous = {
5
+ kind: "blocked-ambiguous";
6
+ detection: OcChatgptTargetAmbiguous;
7
+ };
8
+ type BlockedNone = {
9
+ kind: "blocked-none";
10
+ detection: OcChatgptTargetNone;
11
+ };
12
+ type BlockedDetection = BlockedAmbiguous | BlockedNone;
13
+ type OcChatgptSyncPlanReady = {
14
+ kind: "ready";
15
+ target: OcChatgptTargetDescriptor;
16
+ preview: OcChatgptMergePreview;
17
+ payload: OcChatgptPreviewPayload;
18
+ destination: AccountStorageV3 | null;
19
+ };
20
+ export type OcChatgptSyncPlanResult = OcChatgptSyncPlanReady | BlockedDetection;
21
+ type DetectOptions = {
22
+ explicitRoot?: string | null;
23
+ projectRoot?: string | null;
24
+ };
25
+ type PlanDependencies = {
26
+ detectTarget?: typeof detectOcChatgptMultiAuthTarget;
27
+ previewMerge?: typeof previewOcChatgptImportMerge;
28
+ loadTargetStorage?: (target: OcChatgptTargetDescriptor) => Promise<AccountStorageV3 | null>;
29
+ };
30
+ export type PlanOcChatgptSyncOptions = {
31
+ source: AccountStorageV3 | null;
32
+ destination?: AccountStorageV3 | null;
33
+ detectOptions?: DetectOptions;
34
+ dependencies?: PlanDependencies;
35
+ };
36
+ export declare function planOcChatgptSync(options: PlanOcChatgptSyncOptions): Promise<OcChatgptSyncPlanResult>;
37
+ type ApplyDependencies = PlanDependencies & {
38
+ persistMerged?: (target: OcChatgptTargetDescriptor, merged: AccountStorageV3) => Promise<string | void>;
39
+ };
40
+ export type ApplyOcChatgptSyncOptions = {
41
+ source: AccountStorageV3 | null;
42
+ destination?: AccountStorageV3 | null;
43
+ detectOptions?: DetectOptions;
44
+ dependencies?: ApplyDependencies;
45
+ };
46
+ export type OcChatgptSyncApplyResult = BlockedDetection | {
47
+ kind: "applied";
48
+ target: OcChatgptTargetDescriptor;
49
+ preview: OcChatgptMergePreview;
50
+ merged: AccountStorageV3;
51
+ destination: AccountStorageV3 | null;
52
+ persistedPath?: string | void;
53
+ } | {
54
+ kind: "error";
55
+ target: OcChatgptTargetDescriptor;
56
+ error: unknown;
57
+ };
58
+ export declare function applyOcChatgptSync(options: ApplyOcChatgptSyncOptions): Promise<OcChatgptSyncApplyResult>;
59
+ type BackupDependencies = {
60
+ exportBackup?: typeof exportNamedBackup;
61
+ };
62
+ export type RunNamedBackupExportOptions = {
63
+ name: string;
64
+ force?: boolean;
65
+ dependencies?: BackupDependencies;
66
+ };
67
+ export type RunNamedBackupExportResult = {
68
+ kind: "exported";
69
+ path: string;
70
+ } | {
71
+ kind: "collision";
72
+ path: string;
73
+ } | {
74
+ kind: "error";
75
+ path?: string;
76
+ error: unknown;
77
+ };
78
+ export declare function runNamedBackupExport(options: RunNamedBackupExportOptions): Promise<RunNamedBackupExportResult>;
79
+ export {};
80
+ //# sourceMappingURL=oc-chatgpt-orchestrator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oc-chatgpt-orchestrator.d.ts","sourceRoot":"","sources":["../../lib/oc-chatgpt-orchestrator.ts"],"names":[],"mappings":"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"}