oc-codex-multi-auth 6.0.0 → 6.1.1

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 (284) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +56 -18
  3. package/assets/readme-hero.svg +10 -10
  4. package/config/README.md +1 -1
  5. package/config/minimal-opencode.json +1 -1
  6. package/config/opencode-legacy.json +1 -1
  7. package/config/opencode-modern.json +1 -1
  8. package/dist/index.d.ts +1 -1
  9. package/dist/index.d.ts.map +1 -1
  10. package/dist/index.js +112 -2525
  11. package/dist/index.js.map +1 -1
  12. package/dist/lib/accounts/persistence.d.ts +34 -0
  13. package/dist/lib/accounts/persistence.d.ts.map +1 -0
  14. package/dist/lib/accounts/persistence.js +153 -0
  15. package/dist/lib/accounts/persistence.js.map +1 -0
  16. package/dist/lib/accounts/recovery.d.ts +59 -0
  17. package/dist/lib/accounts/recovery.d.ts.map +1 -0
  18. package/dist/lib/accounts/recovery.js +229 -0
  19. package/dist/lib/accounts/recovery.js.map +1 -0
  20. package/dist/lib/accounts/rotation.d.ts +40 -0
  21. package/dist/lib/accounts/rotation.d.ts.map +1 -0
  22. package/dist/lib/accounts/rotation.js +204 -0
  23. package/dist/lib/accounts/rotation.js.map +1 -0
  24. package/dist/lib/accounts/state.d.ts +92 -0
  25. package/dist/lib/accounts/state.d.ts.map +1 -0
  26. package/dist/lib/accounts/state.js +366 -0
  27. package/dist/lib/accounts/state.js.map +1 -0
  28. package/dist/lib/accounts.d.ts +48 -91
  29. package/dist/lib/accounts.d.ts.map +1 -1
  30. package/dist/lib/accounts.js +121 -699
  31. package/dist/lib/accounts.js.map +1 -1
  32. package/dist/lib/auth/auth.d.ts +1 -1
  33. package/dist/lib/auth/auth.d.ts.map +1 -1
  34. package/dist/lib/auth/auth.js +5 -2
  35. package/dist/lib/auth/auth.js.map +1 -1
  36. package/dist/lib/auth/login-runner.d.ts +32 -0
  37. package/dist/lib/auth/login-runner.d.ts.map +1 -1
  38. package/dist/lib/auth/login-runner.js +79 -64
  39. package/dist/lib/auth/login-runner.js.map +1 -1
  40. package/dist/lib/auth/server.d.ts.map +1 -1
  41. package/dist/lib/auth/server.js +3 -8
  42. package/dist/lib/auth/server.js.map +1 -1
  43. package/dist/lib/circuit-breaker.d.ts +53 -2
  44. package/dist/lib/circuit-breaker.d.ts.map +1 -1
  45. package/dist/lib/circuit-breaker.js +65 -6
  46. package/dist/lib/circuit-breaker.js.map +1 -1
  47. package/dist/lib/config.d.ts.map +1 -1
  48. package/dist/lib/config.js +77 -32
  49. package/dist/lib/config.js.map +1 -1
  50. package/dist/lib/error-sentinels.d.ts +20 -0
  51. package/dist/lib/error-sentinels.d.ts.map +1 -0
  52. package/dist/lib/error-sentinels.js +28 -0
  53. package/dist/lib/error-sentinels.js.map +1 -0
  54. package/dist/lib/errors.d.ts +100 -1
  55. package/dist/lib/errors.d.ts.map +1 -1
  56. package/dist/lib/errors.js +116 -1
  57. package/dist/lib/errors.js.map +1 -1
  58. package/dist/lib/logger.d.ts +14 -1
  59. package/dist/lib/logger.d.ts.map +1 -1
  60. package/dist/lib/logger.js +65 -5
  61. package/dist/lib/logger.js.map +1 -1
  62. package/dist/lib/oauth-constants.d.ts +18 -0
  63. package/dist/lib/oauth-constants.d.ts.map +1 -0
  64. package/dist/lib/oauth-constants.js +18 -0
  65. package/dist/lib/oauth-constants.js.map +1 -0
  66. package/dist/lib/oauth-success.d.ts +2 -0
  67. package/dist/lib/oauth-success.d.ts.map +1 -0
  68. package/dist/lib/oauth-success.html +711 -711
  69. package/dist/lib/oauth-success.js +714 -0
  70. package/dist/lib/oauth-success.js.map +1 -0
  71. package/dist/lib/prompts/codex.d.ts.map +1 -1
  72. package/dist/lib/prompts/codex.js +12 -3
  73. package/dist/lib/prompts/codex.js.map +1 -1
  74. package/dist/lib/prompts/opencode-codex.d.ts.map +1 -1
  75. package/dist/lib/prompts/opencode-codex.js +3 -2
  76. package/dist/lib/prompts/opencode-codex.js.map +1 -1
  77. package/dist/lib/recovery/hook.d.ts +43 -0
  78. package/dist/lib/recovery/hook.d.ts.map +1 -0
  79. package/dist/lib/recovery/hook.js +325 -0
  80. package/dist/lib/recovery/hook.js.map +1 -0
  81. package/dist/lib/recovery/index.d.ts +1 -0
  82. package/dist/lib/recovery/index.d.ts.map +1 -1
  83. package/dist/lib/recovery/index.js +1 -0
  84. package/dist/lib/recovery/index.js.map +1 -1
  85. package/dist/lib/recovery/storage.d.ts.map +1 -1
  86. package/dist/lib/recovery/storage.js +5 -1
  87. package/dist/lib/recovery/storage.js.map +1 -1
  88. package/dist/lib/recovery.d.ts +15 -30
  89. package/dist/lib/recovery.d.ts.map +1 -1
  90. package/dist/lib/recovery.js +14 -312
  91. package/dist/lib/recovery.js.map +1 -1
  92. package/dist/lib/request/fetch-helpers.d.ts +1 -0
  93. package/dist/lib/request/fetch-helpers.d.ts.map +1 -1
  94. package/dist/lib/request/fetch-helpers.js +58 -10
  95. package/dist/lib/request/fetch-helpers.js.map +1 -1
  96. package/dist/lib/request/response-handler.d.ts.map +1 -1
  97. package/dist/lib/request/response-handler.js +8 -2
  98. package/dist/lib/request/response-handler.js.map +1 -1
  99. package/dist/lib/runtime.d.ts +101 -0
  100. package/dist/lib/runtime.d.ts.map +1 -0
  101. package/dist/lib/runtime.js +77 -0
  102. package/dist/lib/runtime.js.map +1 -0
  103. package/dist/lib/schemas.d.ts +164 -1
  104. package/dist/lib/schemas.d.ts.map +1 -1
  105. package/dist/lib/schemas.js +251 -0
  106. package/dist/lib/schemas.js.map +1 -1
  107. package/dist/lib/storage/atomic-write.d.ts +31 -0
  108. package/dist/lib/storage/atomic-write.d.ts.map +1 -0
  109. package/dist/lib/storage/atomic-write.js +75 -0
  110. package/dist/lib/storage/atomic-write.js.map +1 -0
  111. package/dist/lib/storage/backup.d.ts +13 -0
  112. package/dist/lib/storage/backup.d.ts.map +1 -0
  113. package/dist/lib/storage/backup.js +59 -0
  114. package/dist/lib/storage/backup.js.map +1 -0
  115. package/dist/lib/storage/errors.d.ts +17 -0
  116. package/dist/lib/storage/errors.d.ts.map +1 -0
  117. package/dist/lib/storage/errors.js +38 -0
  118. package/dist/lib/storage/errors.js.map +1 -0
  119. package/dist/lib/storage/export-import.d.ts +84 -0
  120. package/dist/lib/storage/export-import.d.ts.map +1 -0
  121. package/dist/lib/storage/export-import.js +222 -0
  122. package/dist/lib/storage/export-import.js.map +1 -0
  123. package/dist/lib/storage/flagged.d.ts +29 -0
  124. package/dist/lib/storage/flagged.d.ts.map +1 -0
  125. package/dist/lib/storage/flagged.js +207 -0
  126. package/dist/lib/storage/flagged.js.map +1 -0
  127. package/dist/lib/storage/identity.d.ts +72 -0
  128. package/dist/lib/storage/identity.d.ts.map +1 -0
  129. package/dist/lib/storage/identity.js +230 -0
  130. package/dist/lib/storage/identity.js.map +1 -0
  131. package/dist/lib/storage/keychain.d.ts +146 -0
  132. package/dist/lib/storage/keychain.d.ts.map +1 -0
  133. package/dist/lib/storage/keychain.js +278 -0
  134. package/dist/lib/storage/keychain.js.map +1 -0
  135. package/dist/lib/storage/load-save.d.ts +61 -0
  136. package/dist/lib/storage/load-save.d.ts.map +1 -0
  137. package/dist/lib/storage/load-save.js +606 -0
  138. package/dist/lib/storage/load-save.js.map +1 -0
  139. package/dist/lib/storage/migrations.d.ts +35 -0
  140. package/dist/lib/storage/migrations.d.ts.map +1 -1
  141. package/dist/lib/storage/migrations.js +37 -0
  142. package/dist/lib/storage/migrations.js.map +1 -1
  143. package/dist/lib/storage/normalize.d.ts +22 -0
  144. package/dist/lib/storage/normalize.d.ts.map +1 -0
  145. package/dist/lib/storage/normalize.js +114 -0
  146. package/dist/lib/storage/normalize.js.map +1 -0
  147. package/dist/lib/storage/paths.d.ts.map +1 -1
  148. package/dist/lib/storage/paths.js +2 -1
  149. package/dist/lib/storage/paths.js.map +1 -1
  150. package/dist/lib/storage/state.d.ts +46 -0
  151. package/dist/lib/storage/state.d.ts.map +1 -0
  152. package/dist/lib/storage/state.js +100 -0
  153. package/dist/lib/storage/state.js.map +1 -0
  154. package/dist/lib/storage/worktree-lock.d.ts +79 -0
  155. package/dist/lib/storage/worktree-lock.d.ts.map +1 -0
  156. package/dist/lib/storage/worktree-lock.js +265 -0
  157. package/dist/lib/storage/worktree-lock.js.map +1 -0
  158. package/dist/lib/storage.d.ts +21 -155
  159. package/dist/lib/storage.d.ts.map +1 -1
  160. package/dist/lib/storage.js +24 -1167
  161. package/dist/lib/storage.js.map +1 -1
  162. package/dist/lib/tools/_shared.d.ts +16 -0
  163. package/dist/lib/tools/_shared.d.ts.map +1 -0
  164. package/dist/lib/tools/_shared.js +21 -0
  165. package/dist/lib/tools/_shared.js.map +1 -0
  166. package/dist/lib/tools/codex-dashboard.d.ts +8 -0
  167. package/dist/lib/tools/codex-dashboard.d.ts.map +1 -0
  168. package/dist/lib/tools/codex-dashboard.js +176 -0
  169. package/dist/lib/tools/codex-dashboard.js.map +1 -0
  170. package/dist/lib/tools/codex-diag.d.ts +19 -0
  171. package/dist/lib/tools/codex-diag.d.ts.map +1 -0
  172. package/dist/lib/tools/codex-diag.js +139 -0
  173. package/dist/lib/tools/codex-diag.js.map +1 -0
  174. package/dist/lib/tools/codex-diff.d.ts +44 -0
  175. package/dist/lib/tools/codex-diff.d.ts.map +1 -0
  176. package/dist/lib/tools/codex-diff.js +284 -0
  177. package/dist/lib/tools/codex-diff.js.map +1 -0
  178. package/dist/lib/tools/codex-doctor.d.ts +8 -0
  179. package/dist/lib/tools/codex-doctor.d.ts.map +1 -0
  180. package/dist/lib/tools/codex-doctor.js +284 -0
  181. package/dist/lib/tools/codex-doctor.js.map +1 -0
  182. package/dist/lib/tools/codex-export.d.ts +8 -0
  183. package/dist/lib/tools/codex-export.d.ts.map +1 -0
  184. package/dist/lib/tools/codex-export.js +63 -0
  185. package/dist/lib/tools/codex-export.js.map +1 -0
  186. package/dist/lib/tools/codex-health.d.ts +8 -0
  187. package/dist/lib/tools/codex-health.d.ts.map +1 -0
  188. package/dist/lib/tools/codex-health.js +124 -0
  189. package/dist/lib/tools/codex-health.js.map +1 -0
  190. package/dist/lib/tools/codex-help.d.ts +8 -0
  191. package/dist/lib/tools/codex-help.d.ts.map +1 -0
  192. package/dist/lib/tools/codex-help.js +127 -0
  193. package/dist/lib/tools/codex-help.js.map +1 -0
  194. package/dist/lib/tools/codex-import.d.ts +8 -0
  195. package/dist/lib/tools/codex-import.d.ts.map +1 -0
  196. package/dist/lib/tools/codex-import.js +97 -0
  197. package/dist/lib/tools/codex-import.js.map +1 -0
  198. package/dist/lib/tools/codex-keychain.d.ts +36 -0
  199. package/dist/lib/tools/codex-keychain.d.ts.map +1 -0
  200. package/dist/lib/tools/codex-keychain.js +289 -0
  201. package/dist/lib/tools/codex-keychain.js.map +1 -0
  202. package/dist/lib/tools/codex-label.d.ts +8 -0
  203. package/dist/lib/tools/codex-label.d.ts.map +1 -0
  204. package/dist/lib/tools/codex-label.js +143 -0
  205. package/dist/lib/tools/codex-label.js.map +1 -0
  206. package/dist/lib/tools/codex-limits.d.ts +8 -0
  207. package/dist/lib/tools/codex-limits.d.ts.map +1 -0
  208. package/dist/lib/tools/codex-limits.js +497 -0
  209. package/dist/lib/tools/codex-limits.js.map +1 -0
  210. package/dist/lib/tools/codex-list.d.ts +8 -0
  211. package/dist/lib/tools/codex-list.d.ts.map +1 -0
  212. package/dist/lib/tools/codex-list.js +260 -0
  213. package/dist/lib/tools/codex-list.js.map +1 -0
  214. package/dist/lib/tools/codex-metrics.d.ts +8 -0
  215. package/dist/lib/tools/codex-metrics.d.ts.map +1 -0
  216. package/dist/lib/tools/codex-metrics.js +180 -0
  217. package/dist/lib/tools/codex-metrics.js.map +1 -0
  218. package/dist/lib/tools/codex-next.d.ts +8 -0
  219. package/dist/lib/tools/codex-next.d.ts.map +1 -0
  220. package/dist/lib/tools/codex-next.js +54 -0
  221. package/dist/lib/tools/codex-next.js.map +1 -0
  222. package/dist/lib/tools/codex-note.d.ts +8 -0
  223. package/dist/lib/tools/codex-note.d.ts.map +1 -0
  224. package/dist/lib/tools/codex-note.js +79 -0
  225. package/dist/lib/tools/codex-note.js.map +1 -0
  226. package/dist/lib/tools/codex-refresh.d.ts +8 -0
  227. package/dist/lib/tools/codex-refresh.d.ts.map +1 -0
  228. package/dist/lib/tools/codex-refresh.js +78 -0
  229. package/dist/lib/tools/codex-refresh.js.map +1 -0
  230. package/dist/lib/tools/codex-remove.d.ts +8 -0
  231. package/dist/lib/tools/codex-remove.d.ts.map +1 -0
  232. package/dist/lib/tools/codex-remove.js +184 -0
  233. package/dist/lib/tools/codex-remove.js.map +1 -0
  234. package/dist/lib/tools/codex-setup.d.ts +8 -0
  235. package/dist/lib/tools/codex-setup.d.ts.map +1 -0
  236. package/dist/lib/tools/codex-setup.js +26 -0
  237. package/dist/lib/tools/codex-setup.js.map +1 -0
  238. package/dist/lib/tools/codex-status.d.ts +8 -0
  239. package/dist/lib/tools/codex-status.d.ts.map +1 -0
  240. package/dist/lib/tools/codex-status.js +263 -0
  241. package/dist/lib/tools/codex-status.js.map +1 -0
  242. package/dist/lib/tools/codex-switch.d.ts +8 -0
  243. package/dist/lib/tools/codex-switch.d.ts.map +1 -0
  244. package/dist/lib/tools/codex-switch.js +122 -0
  245. package/dist/lib/tools/codex-switch.js.map +1 -0
  246. package/dist/lib/tools/codex-tag.d.ts +8 -0
  247. package/dist/lib/tools/codex-tag.d.ts.map +1 -0
  248. package/dist/lib/tools/codex-tag.js +101 -0
  249. package/dist/lib/tools/codex-tag.js.map +1 -0
  250. package/dist/lib/tools/index.d.ts +143 -0
  251. package/dist/lib/tools/index.d.ts.map +1 -0
  252. package/dist/lib/tools/index.js +67 -0
  253. package/dist/lib/tools/index.js.map +1 -0
  254. package/dist/lib/ui/format.d.ts.map +1 -1
  255. package/dist/lib/ui/format.js +5 -0
  256. package/dist/lib/ui/format.js.map +1 -1
  257. package/dist/lib/ui/runtime.d.ts +10 -0
  258. package/dist/lib/ui/runtime.d.ts.map +1 -1
  259. package/dist/lib/ui/runtime.js +16 -11
  260. package/dist/lib/ui/runtime.js.map +1 -1
  261. package/dist/lib/ui/select.d.ts.map +1 -1
  262. package/dist/lib/ui/select.js +12 -3
  263. package/dist/lib/ui/select.js.map +1 -1
  264. package/dist/lib/ui/theme.d.ts +19 -0
  265. package/dist/lib/ui/theme.d.ts.map +1 -1
  266. package/dist/lib/ui/theme.js +27 -0
  267. package/dist/lib/ui/theme.js.map +1 -1
  268. package/package.json +24 -16
  269. package/scripts/copy-oauth-success.js +16 -6
  270. package/scripts/install-oc-codex-multi-auth-core.js +462 -381
  271. package/scripts/install-oc-codex-multi-auth.js +15 -15
  272. package/scripts/test-all-models.sh +1 -1
  273. package/dist/lib/audit.d.ts +0 -45
  274. package/dist/lib/audit.d.ts.map +0 -1
  275. package/dist/lib/audit.js +0 -154
  276. package/dist/lib/audit.js.map +0 -1
  277. package/dist/lib/auth-rate-limit.d.ts +0 -20
  278. package/dist/lib/auth-rate-limit.d.ts.map +0 -1
  279. package/dist/lib/auth-rate-limit.js +0 -91
  280. package/dist/lib/auth-rate-limit.js.map +0 -1
  281. package/dist/lib/runtime-contracts.d.ts +0 -16
  282. package/dist/lib/runtime-contracts.d.ts.map +0 -1
  283. package/dist/lib/runtime-contracts.js +0 -24
  284. package/dist/lib/runtime-contracts.js.map +0 -1
@@ -0,0 +1,606 @@
1
+ /**
2
+ * Account storage load/save pipeline.
3
+ *
4
+ * Split out of `lib/storage.ts` in RC-2. This module owns:
5
+ * - the `.gitignore` side-effect when writing into a project repo,
6
+ * - the legacy project + global storage migrations triggered on ENOENT,
7
+ * - the project-global fallback seed flow,
8
+ * - the atomic write (temp file + rename + EEMPTY guard),
9
+ * - and the `withAccountStorageTransaction` read-modify-write primitive
10
+ * that every mutating caller above the storage layer uses.
11
+ *
12
+ * The error-handling contract is subtle and load-bearing: forward-compat
13
+ * (`UNSUPPORTED_SCHEMA_VERSION`) and unknown-V2 failures MUST reach the
14
+ * caller. Swallowing either would overwrite future-schema credentials or
15
+ * silently discard a user's V2 file, which is exactly the class of bug the
16
+ * audit flagged.
17
+ */
18
+ import { promises as fs, existsSync } from "node:fs";
19
+ import { dirname, join } from "node:path";
20
+ import { ACCOUNTS_FILE_NAME, LEGACY_ACCOUNTS_FILE_NAME } from "../constants.js";
21
+ import { createLogger } from "../logger.js";
22
+ import { AnyAccountStorageSchema, getValidationErrors } from "../schemas.js";
23
+ import { renameWithWindowsRetry } from "./atomic-write.js";
24
+ import { formatStorageErrorHint, StorageError } from "./errors.js";
25
+ import { normalizeAccountStorage } from "./normalize.js";
26
+ import { getConfigDir } from "./paths.js";
27
+ import { getCurrentLegacyProjectStoragePath, getCurrentProjectRoot, getCurrentProjectStorageKey, getCurrentStoragePath, getStoragePath, withStorageLock, } from "./state.js";
28
+ import { buildV2RecoveryHint, UNKNOWN_V2_FORMAT_CODE, } from "./migrations.js";
29
+ import { acquireOrDetectLock } from "./worktree-lock.js";
30
+ import { isKeychainOptInEnabled, readFromKeychain, writeToKeychain, deleteFromKeychain, } from "./keychain.js";
31
+ import os from "node:os";
32
+ const log = createLogger("storage");
33
+ /**
34
+ * Probes the worktree lock for the currently active storage path and surfaces
35
+ * any foreign live lock as a non-fatal warning. The lock check is advisory:
36
+ * Phase 4 F2 deliberately chose warn-over-block so a user with two legitimate
37
+ * OpenCode sessions on the same project (separate worktrees, IDE + CLI) is
38
+ * never stranded. The warning still carries enough detail (pid, host, cwd)
39
+ * for the user to reconcile state manually if a rotation was lost to a race.
40
+ *
41
+ * Failure modes:
42
+ * - Storage path is not resolvable (no project, no global dir set): skip
43
+ * silently, the actual storage call will surface the real error.
44
+ * - Lock file unreadable (disk full, EACCES): log at debug so it cannot
45
+ * drown the normal "collision detected" warning, then continue. A broken
46
+ * sidecar must never gate auth-critical reads/writes.
47
+ */
48
+ async function checkWorktreeLockForCurrentStorage(operation) {
49
+ let path;
50
+ try {
51
+ path = getStoragePath();
52
+ }
53
+ catch (error) {
54
+ log.debug("Skipping worktree lock check: storage path unavailable", {
55
+ error: String(error),
56
+ });
57
+ return;
58
+ }
59
+ try {
60
+ const result = await acquireOrDetectLock(path);
61
+ if (!result.acquired && result.foreign) {
62
+ log.warn("Multi-worktree collision detected on account storage", {
63
+ operation,
64
+ storagePath: path,
65
+ foreignPid: result.foreign.pid,
66
+ foreignHost: result.foreign.hostname,
67
+ foreignCwd: result.foreign.cwd,
68
+ foreignLastActive: result.foreign.lastActive,
69
+ ourPid: process.pid,
70
+ ourHost: os.hostname(),
71
+ ourCwd: process.cwd(),
72
+ });
73
+ }
74
+ }
75
+ catch (error) {
76
+ log.debug("Worktree lock probe failed", {
77
+ operation,
78
+ storagePath: path,
79
+ error: String(error),
80
+ });
81
+ }
82
+ }
83
+ async function ensureGitignore(storagePath) {
84
+ if (!getCurrentStoragePath())
85
+ return;
86
+ const configDir = dirname(storagePath);
87
+ const inferredProjectRoot = dirname(configDir);
88
+ const candidateRoots = [getCurrentProjectRoot(), inferredProjectRoot].filter((root) => typeof root === "string" && root.length > 0);
89
+ const projectRoot = candidateRoots.find((root) => existsSync(join(root, ".git")));
90
+ if (!projectRoot)
91
+ return;
92
+ const gitignorePath = join(projectRoot, ".gitignore");
93
+ try {
94
+ let content = "";
95
+ if (existsSync(gitignorePath)) {
96
+ content = await fs.readFile(gitignorePath, "utf-8");
97
+ const lines = content.split("\n").map((l) => l.trim());
98
+ if (lines.includes(".opencode") || lines.includes(".opencode/") || lines.includes("/.opencode") || lines.includes("/.opencode/")) {
99
+ return;
100
+ }
101
+ }
102
+ const newContent = content.endsWith("\n") || content === "" ? content : content + "\n";
103
+ await fs.writeFile(gitignorePath, newContent + ".opencode/\n", "utf-8");
104
+ log.debug("Added .opencode to .gitignore", { path: gitignorePath });
105
+ }
106
+ catch (error) {
107
+ log.warn("Failed to update .gitignore", { error: String(error) });
108
+ }
109
+ }
110
+ async function migrateStorageFileIfNeeded(legacyPath, nextPath, persist, label) {
111
+ if (!legacyPath || legacyPath === nextPath || !existsSync(legacyPath)) {
112
+ return null;
113
+ }
114
+ try {
115
+ const legacyContent = await fs.readFile(legacyPath, "utf-8");
116
+ const legacyData = JSON.parse(legacyContent);
117
+ const normalized = normalizeAccountStorage(legacyData, legacyPath);
118
+ if (!normalized)
119
+ return null;
120
+ await persist(normalized);
121
+ try {
122
+ await fs.unlink(legacyPath);
123
+ log.info(`Removed legacy ${label} after migration`, { path: legacyPath });
124
+ }
125
+ catch (unlinkError) {
126
+ const code = unlinkError.code;
127
+ if (code !== "ENOENT") {
128
+ log.warn(`Failed to remove legacy ${label} after migration`, {
129
+ path: legacyPath,
130
+ error: String(unlinkError),
131
+ });
132
+ }
133
+ }
134
+ log.info(`Migrated legacy ${label}`, {
135
+ from: legacyPath,
136
+ to: nextPath,
137
+ accounts: normalized.accounts.length,
138
+ });
139
+ return normalized;
140
+ }
141
+ catch (error) {
142
+ // Forward-compat failures should not be masked as migration warnings.
143
+ if (error instanceof StorageError && error.code === "UNSUPPORTED_SCHEMA_VERSION") {
144
+ throw error;
145
+ }
146
+ log.warn(`Failed to migrate legacy ${label}`, {
147
+ from: legacyPath,
148
+ to: nextPath,
149
+ error: String(error),
150
+ });
151
+ return null;
152
+ }
153
+ }
154
+ async function migrateLegacyProjectStorageIfNeeded(persist = saveAccounts) {
155
+ return migrateStorageFileIfNeeded(getCurrentLegacyProjectStoragePath(), getStoragePath(), persist, "project account storage");
156
+ }
157
+ /**
158
+ * Resolves the global (non-project) account storage path.
159
+ */
160
+ function getGlobalAccountsStoragePath() {
161
+ return join(getConfigDir(), ACCOUNTS_FILE_NAME);
162
+ }
163
+ function getLegacyGlobalAccountsStoragePath() {
164
+ return join(getConfigDir(), LEGACY_ACCOUNTS_FILE_NAME);
165
+ }
166
+ async function migrateLegacyGlobalStorageIfNeeded() {
167
+ const nextPath = getGlobalAccountsStoragePath();
168
+ const persistGlobalStorage = async (storage) => {
169
+ await writeAccountsToPathUnlocked(nextPath, storage);
170
+ };
171
+ return migrateStorageFileIfNeeded(getLegacyGlobalAccountsStoragePath(), nextPath, persistGlobalStorage, "global account storage");
172
+ }
173
+ /**
174
+ * Returns true when project-scoped storage is active and a global fallback is meaningful.
175
+ */
176
+ function shouldUseProjectGlobalFallback() {
177
+ return Boolean(getCurrentStoragePath() && getCurrentProjectRoot());
178
+ }
179
+ /**
180
+ * Loads account data from global storage as a fallback when project storage is missing.
181
+ * Returns null for missing/unusable global storage and never throws to callers.
182
+ */
183
+ async function loadGlobalAccountsFallback() {
184
+ const currentStoragePath = getCurrentStoragePath();
185
+ if (!shouldUseProjectGlobalFallback() || !currentStoragePath) {
186
+ return null;
187
+ }
188
+ const migrated = await migrateLegacyGlobalStorageIfNeeded();
189
+ if (migrated) {
190
+ return migrated;
191
+ }
192
+ const globalStoragePath = getGlobalAccountsStoragePath();
193
+ if (globalStoragePath === currentStoragePath) {
194
+ return null;
195
+ }
196
+ try {
197
+ const content = await fs.readFile(globalStoragePath, "utf-8");
198
+ const data = JSON.parse(content);
199
+ const schemaErrors = getValidationErrors(AnyAccountStorageSchema, data);
200
+ if (schemaErrors.length > 0) {
201
+ log.warn("Global account storage schema validation warnings", {
202
+ path: globalStoragePath,
203
+ errors: schemaErrors.slice(0, 5),
204
+ });
205
+ }
206
+ const normalized = normalizeAccountStorage(data, globalStoragePath);
207
+ if (!normalized)
208
+ return null;
209
+ log.info("Loaded global account storage as project fallback", {
210
+ from: globalStoragePath,
211
+ to: currentStoragePath,
212
+ accounts: normalized.accounts.length,
213
+ });
214
+ return normalized;
215
+ }
216
+ catch (error) {
217
+ // Propagate forward-compat failures so the caller can surface them to the
218
+ // user instead of silently falling back to an empty global pool.
219
+ if (error instanceof StorageError && error.code === "UNSUPPORTED_SCHEMA_VERSION") {
220
+ throw error;
221
+ }
222
+ const code = error.code;
223
+ if (code !== "ENOENT") {
224
+ log.warn("Failed to load global fallback account storage", {
225
+ from: globalStoragePath,
226
+ to: currentStoragePath,
227
+ error: String(error),
228
+ });
229
+ }
230
+ return null;
231
+ }
232
+ }
233
+ /**
234
+ * Core account-loading routine shared by normal reads and transactional storage handlers.
235
+ * Handles schema normalization, legacy migration, and optional fallback seeding.
236
+ */
237
+ async function loadAccountsInternal(persistMigration) {
238
+ // Advisory: surface multi-worktree collisions before the read but never
239
+ // block. Must come before the try/catch so a genuine storage error still
240
+ // takes precedence over any lock-related log output below.
241
+ await checkWorktreeLockForCurrentStorage("load");
242
+ // Opt-in keychain backend. When `CODEX_KEYCHAIN=1` is set, the keychain
243
+ // holds the authoritative V3 JSON blob and the on-disk file (if any) is
244
+ // only kept as a post-migration rollback artefact. If the keychain lookup
245
+ // fails for any reason (native module missing, keychain locked, no entry
246
+ // yet) we fall through to the existing JSON load path so the plugin never
247
+ // silently loses credentials. This preserves the default-off contract
248
+ // documented in docs/audits/13-phased-roadmap.md#phase-4-f1.
249
+ if (isKeychainOptInEnabled()) {
250
+ const projectKey = getCurrentProjectStorageKey();
251
+ try {
252
+ const blob = await readFromKeychain(projectKey);
253
+ if (blob !== null) {
254
+ try {
255
+ const parsed = JSON.parse(blob);
256
+ const normalized = normalizeAccountStorage(parsed, "<keychain>");
257
+ if (normalized)
258
+ return normalized;
259
+ }
260
+ catch (parseErr) {
261
+ // Corrupt keychain entry: log but fall through to JSON so the
262
+ // user can recover from their on-disk backup.
263
+ log.warn("keychain: stored payload failed to parse; falling back to JSON", {
264
+ error: String(parseErr),
265
+ });
266
+ }
267
+ }
268
+ else {
269
+ log.info("keychain: no entry found; falling back to JSON read");
270
+ }
271
+ }
272
+ catch (err) {
273
+ log.warn("keychain: read failed; falling back to JSON", {
274
+ error: String(err),
275
+ });
276
+ }
277
+ }
278
+ try {
279
+ const path = getStoragePath();
280
+ const content = await fs.readFile(path, "utf-8");
281
+ const data = JSON.parse(content);
282
+ const schemaErrors = getValidationErrors(AnyAccountStorageSchema, data);
283
+ if (schemaErrors.length > 0) {
284
+ log.warn("Account storage schema validation warnings", { errors: schemaErrors.slice(0, 5) });
285
+ }
286
+ const normalized = normalizeAccountStorage(data, path);
287
+ const storedVersion = data && typeof data === "object" && !Array.isArray(data)
288
+ ? data.version
289
+ : undefined;
290
+ if (normalized && storedVersion !== normalized.version) {
291
+ log.info("Migrating account storage to v3", { from: storedVersion, to: normalized.version });
292
+ if (persistMigration) {
293
+ try {
294
+ await persistMigration(normalized);
295
+ }
296
+ catch (saveError) {
297
+ log.warn("Failed to persist migrated storage", { error: String(saveError) });
298
+ }
299
+ }
300
+ }
301
+ return normalized;
302
+ }
303
+ catch (error) {
304
+ // Forward-compat failures must reach the caller instead of being silently
305
+ // downgraded to an empty load, which would clobber the user's future-format
306
+ // credentials on the next save.
307
+ if (error instanceof StorageError && error.code === "UNSUPPORTED_SCHEMA_VERSION") {
308
+ throw error;
309
+ }
310
+ // Unknown-V2 detection must NOT be silently dropped: the catch below
311
+ // swallows generic errors by design (keeps an unreadable file from
312
+ // crashing the whole plugin), but V2 is a specific, recoverable case
313
+ // where the user needs to know their credentials were quarantined.
314
+ // Re-throw so the UI/CLI layer can render the recovery hint.
315
+ if (error instanceof StorageError && error.code === UNKNOWN_V2_FORMAT_CODE) {
316
+ // Annotate with the concrete storage path that triggered the reject
317
+ // so the recovery hint points at the real file.
318
+ const concretePath = (() => {
319
+ try {
320
+ return getStoragePath();
321
+ }
322
+ catch {
323
+ return "";
324
+ }
325
+ })();
326
+ if (concretePath) {
327
+ throw new StorageError(error.message, UNKNOWN_V2_FORMAT_CODE, concretePath, buildV2RecoveryHint(concretePath), error);
328
+ }
329
+ throw error;
330
+ }
331
+ const code = error.code;
332
+ if (code === "ENOENT") {
333
+ const migrated = persistMigration
334
+ ? await migrateLegacyProjectStorageIfNeeded(persistMigration)
335
+ : null;
336
+ if (migrated)
337
+ return migrated;
338
+ if (!shouldUseProjectGlobalFallback()) {
339
+ const migratedGlobal = persistMigration
340
+ ? await migrateLegacyGlobalStorageIfNeeded()
341
+ : null;
342
+ if (migratedGlobal)
343
+ return migratedGlobal;
344
+ return null;
345
+ }
346
+ const globalFallback = await loadGlobalAccountsFallback();
347
+ if (!globalFallback)
348
+ return null;
349
+ if (persistMigration) {
350
+ const seedPath = getStoragePath();
351
+ try {
352
+ await fs.access(seedPath);
353
+ return globalFallback;
354
+ }
355
+ catch (accessError) {
356
+ const accessCode = accessError.code;
357
+ if (accessCode !== "ENOENT") {
358
+ log.warn("Failed to inspect project seed path before fallback seeding", {
359
+ path: seedPath,
360
+ error: String(accessError),
361
+ });
362
+ return globalFallback;
363
+ }
364
+ // File is missing; proceed with seed write.
365
+ }
366
+ try {
367
+ await persistMigration(globalFallback);
368
+ log.info("Seeded project account storage from global fallback", {
369
+ path: seedPath,
370
+ accounts: globalFallback.accounts.length,
371
+ });
372
+ }
373
+ catch (persistError) {
374
+ log.warn("Failed to seed project storage from global fallback", {
375
+ path: seedPath,
376
+ error: String(persistError),
377
+ });
378
+ }
379
+ }
380
+ return globalFallback;
381
+ }
382
+ log.error("Failed to load account storage", { error: String(error) });
383
+ return null;
384
+ }
385
+ }
386
+ /**
387
+ * Writes account storage without acquiring the outer storage mutex.
388
+ * Callers must already be inside withStorageLock when using this helper directly.
389
+ */
390
+ async function writeAccountsToPathUnlocked(path, storage) {
391
+ const uniqueSuffix = `${Date.now()}.${Math.random().toString(36).slice(2, 8)}`;
392
+ const tempPath = `${path}.${uniqueSuffix}.tmp`;
393
+ try {
394
+ await fs.mkdir(dirname(path), { recursive: true });
395
+ await ensureGitignore(path);
396
+ // Normalize before persisting so every write path enforces dedup semantics
397
+ // (exact identity dedupe plus legacy email dedupe for identity-less records).
398
+ const normalizedStorage = normalizeAccountStorage(storage) ?? storage;
399
+ const content = JSON.stringify(normalizedStorage, null, 2);
400
+ await fs.writeFile(tempPath, content, { encoding: "utf-8", mode: 0o600 });
401
+ const stats = await fs.stat(tempPath);
402
+ if (stats.size === 0) {
403
+ const emptyError = Object.assign(new Error("File written but size is 0"), { code: "EEMPTY" });
404
+ throw emptyError;
405
+ }
406
+ await renameWithWindowsRetry(tempPath, path);
407
+ }
408
+ catch (error) {
409
+ try {
410
+ await fs.unlink(tempPath);
411
+ }
412
+ catch {
413
+ // Ignore cleanup failure.
414
+ }
415
+ const err = error;
416
+ const code = err?.code || "UNKNOWN";
417
+ const hint = formatStorageErrorHint(error, path);
418
+ log.error("Failed to save accounts", {
419
+ path,
420
+ code,
421
+ message: err?.message,
422
+ hint,
423
+ });
424
+ throw new StorageError(`Failed to save accounts: ${err?.message || "Unknown error"}`, code, path, hint, err instanceof Error ? err : undefined);
425
+ }
426
+ }
427
+ /**
428
+ * Post-keychain-write migration helper: if a legacy on-disk JSON file still
429
+ * exists for the current storage path, rename it with a timestamped
430
+ * `.migrated-to-keychain.<ts>` suffix instead of deleting it. Preserving the
431
+ * original file as a rollback artefact is load-bearing: it is the user's
432
+ * explicit escape hatch if the keychain backend turns out to be unreliable
433
+ * on their platform.
434
+ *
435
+ * Atomicity across a partial migration window (F1 post-merge HIGH finding):
436
+ * if the rename fails (EACCES, EBUSY on Windows, disk full, parent dir
437
+ * permission drift) the file at `path` would otherwise hold a stale-but-valid
438
+ * V3 blob while the keychain holds the authoritative fresh blob. This is
439
+ * safe while the opt-in is on (keychain wins at load time) but silently
440
+ * resurrects stale credentials if the user later unsets `CODEX_KEYCHAIN`.
441
+ * We resolve this by overwriting the file with the fresh normalized blob
442
+ * when the rename fails so both sides agree, at the cost of losing that
443
+ * one rollback artefact. This matches the "rollback invariant" documented
444
+ * in the F1 post-merge review (option (a)).
445
+ */
446
+ async function migrateOnDiskJsonToKeychainBackup(path, freshStorage) {
447
+ try {
448
+ await fs.access(path);
449
+ }
450
+ catch {
451
+ return; // No legacy file to migrate.
452
+ }
453
+ const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
454
+ const backup = `${path}.migrated-to-keychain.${timestamp}`;
455
+ try {
456
+ await fs.rename(path, backup);
457
+ // Re-apply 0o600 after rename (F1 post-merge LOW finding). POSIX
458
+ // preserves mode across a rename in-place, but if the filesystem layer
459
+ // or a prior process ever changed the mode (cp from a world-readable
460
+ // source, umask drift on a foreign mount, manual `touch`) the backup
461
+ // could end up group/world-readable. Re-chmod is a cheap belt-and-
462
+ // braces guard. Windows ignores POSIX mode bits, so skip there.
463
+ if (process.platform !== "win32") {
464
+ try {
465
+ await fs.chmod(backup, 0o600);
466
+ }
467
+ catch (chmodErr) {
468
+ log.warn("keychain: failed to chmod backup to 0o600 after rename", {
469
+ backup,
470
+ error: String(chmodErr),
471
+ });
472
+ }
473
+ }
474
+ log.info("keychain: migrated on-disk JSON to keychain; original preserved for rollback", {
475
+ from: path,
476
+ backup,
477
+ });
478
+ }
479
+ catch (err) {
480
+ log.warn("keychain: failed to rename on-disk JSON after successful keychain write; overwriting on-disk copy with fresh blob to prevent stale-rollback-on-opt-out", {
481
+ path,
482
+ error: String(err),
483
+ });
484
+ try {
485
+ await writeAccountsToPathUnlocked(path, freshStorage);
486
+ }
487
+ catch (writeErr) {
488
+ // Last-resort: on-disk refresh also failed. The keychain still
489
+ // holds the authoritative blob so current operation succeeds, but
490
+ // a subsequent opt-in toggle off would now surface the stale
491
+ // file. Log at error so the operator can reconcile manually.
492
+ log.error("keychain: failed to refresh stale on-disk JSON after rename failure; opt-in toggle off may surface stale credentials", {
493
+ path,
494
+ error: String(writeErr),
495
+ });
496
+ }
497
+ }
498
+ }
499
+ async function saveAccountsUnlocked(storage) {
500
+ // Refresh our lock (or surface a collision) on every write. This also
501
+ // bumps `lastActive`, which is the stale-detection timestamp read by
502
+ // other worktrees on their next acquire.
503
+ await checkWorktreeLockForCurrentStorage("save");
504
+ if (isKeychainOptInEnabled()) {
505
+ // Normalize before serializing so the keychain receives the same shape
506
+ // the JSON backend would have written. Using the same JSON format keeps
507
+ // migration and rollback symmetric: a rolled-back JSON file is valid
508
+ // input for a future opt-in migration in either direction.
509
+ const normalizedStorage = normalizeAccountStorage(storage) ?? storage;
510
+ const blob = JSON.stringify(normalizedStorage, null, 2);
511
+ const projectKey = getCurrentProjectStorageKey();
512
+ const result = await writeToKeychain(projectKey, blob);
513
+ if (result.ok) {
514
+ await migrateOnDiskJsonToKeychainBackup(getStoragePath(), normalizedStorage);
515
+ return;
516
+ }
517
+ log.warn("keychain: write failed; falling back to JSON for this save", {
518
+ error: result.error,
519
+ });
520
+ }
521
+ await writeAccountsToPathUnlocked(getStoragePath(), storage);
522
+ }
523
+ /**
524
+ * Loads OAuth accounts from disk storage.
525
+ * Automatically migrates v1 storage to v3 format if needed.
526
+ * @returns AccountStorageV3 if file exists and is valid, null otherwise
527
+ * @throws StorageError (code `UNSUPPORTED_SCHEMA_VERSION`) when the on-disk
528
+ * `version` field is greater than the newest format this plugin understands.
529
+ * Surfacing the error stops a downgraded plugin from overwriting the user's
530
+ * future-schema credentials with a stale or empty payload.
531
+ */
532
+ export async function loadAccounts() {
533
+ return withStorageLock(async () => loadAccountsInternal(saveAccountsUnlocked));
534
+ }
535
+ /**
536
+ * Executes a read-modify-write transaction under the storage lock and exposes
537
+ * an unlocked persist callback so nested save operations do not deadlock.
538
+ */
539
+ export async function withAccountStorageTransaction(handler) {
540
+ return withStorageLock(async () => {
541
+ const current = await loadAccountsInternal(saveAccountsUnlocked);
542
+ return handler(current, saveAccountsUnlocked);
543
+ });
544
+ }
545
+ /**
546
+ * Persists account storage to disk using atomic write (temp file + rename).
547
+ * Creates the .opencode directory if it doesn't exist.
548
+ * Verifies file was written correctly and provides detailed error messages.
549
+ * @param storage - Account storage data to save
550
+ * @throws StorageError with platform-aware hints on failure
551
+ */
552
+ export async function saveAccounts(storage) {
553
+ return withStorageLock(async () => {
554
+ await saveAccountsUnlocked(storage);
555
+ });
556
+ }
557
+ /**
558
+ * Deletes the account storage file from disk.
559
+ * Silently ignores if file doesn't exist.
560
+ *
561
+ * Ordering (F1 post-merge MEDIUM finding): unlink the on-disk JSON FIRST,
562
+ * then delete the keychain entry. If we cleared the keychain first and the
563
+ * unlink failed for a non-ENOENT reason (EACCES, EBUSY, filesystem drift),
564
+ * a subsequent load with opt-in still on would take the "no keychain entry,
565
+ * fall back to JSON" branch (see `loadAccountsInternal`) and resurrect the
566
+ * credentials from the still-present JSON file. Callers typically run
567
+ * `clearAccounts` to recover from a compromised token, so a silent
568
+ * resurrection is a meaningful failure mode.
569
+ *
570
+ * Fail-safe invariant: if the JSON unlink fails (non-ENOENT), we skip the
571
+ * keychain delete and log at `error`. Both copies remain in sync so the
572
+ * caller can retry safely. The operation is still best-effort (never
573
+ * throws) to preserve the existing contract above the storage layer.
574
+ */
575
+ export async function clearAccounts() {
576
+ return withStorageLock(async () => {
577
+ let jsonCleared = true;
578
+ try {
579
+ const path = getStoragePath();
580
+ await fs.unlink(path);
581
+ }
582
+ catch (error) {
583
+ const code = error.code;
584
+ if (code !== "ENOENT") {
585
+ jsonCleared = false;
586
+ log.error("Failed to clear account storage; skipping keychain delete to keep storage sides in sync. Caller should retry.", { error: String(error) });
587
+ }
588
+ }
589
+ // Only delete the keychain entry after the on-disk copy is gone (or
590
+ // was already absent). This preserves atomicity-enough semantics: a
591
+ // partial failure leaves both sides present rather than clearing
592
+ // one side and letting a subsequent load rehydrate from the other.
593
+ if (jsonCleared && isKeychainOptInEnabled()) {
594
+ try {
595
+ const projectKey = getCurrentProjectStorageKey();
596
+ await deleteFromKeychain(projectKey);
597
+ }
598
+ catch (err) {
599
+ log.warn("keychain: delete during clearAccounts failed", {
600
+ error: String(err),
601
+ });
602
+ }
603
+ }
604
+ });
605
+ }
606
+ //# sourceMappingURL=load-save.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"load-save.js","sourceRoot":"","sources":["../../../lib/storage/load-save.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,kBAAkB,EAAE,yBAAyB,EAAE,MAAM,iBAAiB,CAAC;AAChF,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,uBAAuB,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAC7E,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,EAAE,sBAAsB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACnE,OAAO,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EACL,kCAAkC,EAClC,qBAAqB,EACrB,2BAA2B,EAC3B,qBAAqB,EACrB,cAAc,EACd,eAAe,GAChB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,mBAAmB,EACnB,sBAAsB,GAEvB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EACL,sBAAsB,EACtB,gBAAgB,EAChB,eAAe,EACf,kBAAkB,GACnB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,MAAM,SAAS,CAAC;AAEzB,MAAM,GAAG,GAAG,YAAY,CAAC,SAAS,CAAC,CAAC;AAEpC;;;;;;;;;;;;;;GAcG;AACH,KAAK,UAAU,kCAAkC,CAC/C,SAA0B;IAE1B,IAAI,IAAY,CAAC;IACjB,IAAI,CAAC;QACH,IAAI,GAAG,cAAc,EAAE,CAAC;IAC1B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,GAAG,CAAC,KAAK,CAAC,wDAAwD,EAAE;YAClE,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC;SACrB,CAAC,CAAC;QACH,OAAO;IACT,CAAC;IACD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,mBAAmB,CAAC,IAAI,CAAC,CAAC;QAC/C,IAAI,CAAC,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACvC,GAAG,CAAC,IAAI,CAAC,sDAAsD,EAAE;gBAC/D,SAAS;gBACT,WAAW,EAAE,IAAI;gBACjB,UAAU,EAAE,MAAM,CAAC,OAAO,CAAC,GAAG;gBAC9B,WAAW,EAAE,MAAM,CAAC,OAAO,CAAC,QAAQ;gBACpC,UAAU,EAAE,MAAM,CAAC,OAAO,CAAC,GAAG;gBAC9B,iBAAiB,EAAE,MAAM,CAAC,OAAO,CAAC,UAAU;gBAC5C,MAAM,EAAE,OAAO,CAAC,GAAG;gBACnB,OAAO,EAAE,EAAE,CAAC,QAAQ,EAAE;gBACtB,MAAM,EAAE,OAAO,CAAC,GAAG,EAAE;aACtB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,GAAG,CAAC,KAAK,CAAC,4BAA4B,EAAE;YACtC,SAAS;YACT,WAAW,EAAE,IAAI;YACjB,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC;SACrB,CAAC,CAAC;IACL,CAAC;AACH,CAAC;AAED,KAAK,UAAU,eAAe,CAAC,WAAmB;IAChD,IAAI,CAAC,qBAAqB,EAAE;QAAE,OAAO;IAErC,MAAM,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IACvC,MAAM,mBAAmB,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;IAC/C,MAAM,cAAc,GAAG,CAAC,qBAAqB,EAAE,EAAE,mBAAmB,CAAC,CAAC,MAAM,CAC1E,CAAC,IAAI,EAAkB,EAAE,CAAC,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,CACtE,CAAC;IACF,MAAM,WAAW,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;IAClF,IAAI,CAAC,WAAW;QAAE,OAAO;IACzB,MAAM,aAAa,GAAG,IAAI,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;IAEtD,IAAI,CAAC;QACH,IAAI,OAAO,GAAG,EAAE,CAAC;QACjB,IAAI,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;YAC9B,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;YACpD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;YACvD,IAAI,KAAK,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;gBACjI,OAAO;YACT,CAAC;QACH,CAAC;QAED,MAAM,UAAU,GAAG,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,GAAG,IAAI,CAAC;QACvF,MAAM,EAAE,CAAC,SAAS,CAAC,aAAa,EAAE,UAAU,GAAG,cAAc,EAAE,OAAO,CAAC,CAAC;QACxE,GAAG,CAAC,KAAK,CAAC,+BAA+B,EAAE,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC,CAAC;IACtE,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,GAAG,CAAC,IAAI,CAAC,6BAA6B,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACpE,CAAC;AACH,CAAC;AAED,KAAK,UAAU,0BAA0B,CACvC,UAAyB,EACzB,QAAgB,EAChB,OAAqD,EACrD,KAAa;IAEb,IAAI,CAAC,UAAU,IAAI,UAAU,KAAK,QAAQ,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QACtE,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,CAAC;QACH,MAAM,aAAa,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QAC7D,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,aAAa,CAAY,CAAC;QACxD,MAAM,UAAU,GAAG,uBAAuB,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;QACnE,IAAI,CAAC,UAAU;YAAE,OAAO,IAAI,CAAC;QAE7B,MAAM,OAAO,CAAC,UAAU,CAAC,CAAC;QAC1B,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;YAC5B,GAAG,CAAC,IAAI,CAAC,kBAAkB,KAAK,kBAAkB,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC;QAC5E,CAAC;QAAC,OAAO,WAAW,EAAE,CAAC;YACrB,MAAM,IAAI,GAAI,WAAqC,CAAC,IAAI,CAAC;YACzD,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACtB,GAAG,CAAC,IAAI,CAAC,2BAA2B,KAAK,kBAAkB,EAAE;oBAC3D,IAAI,EAAE,UAAU;oBAChB,KAAK,EAAE,MAAM,CAAC,WAAW,CAAC;iBAC3B,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QACD,GAAG,CAAC,IAAI,CAAC,mBAAmB,KAAK,EAAE,EAAE;YACnC,IAAI,EAAE,UAAU;YAChB,EAAE,EAAE,QAAQ;YACZ,QAAQ,EAAE,UAAU,CAAC,QAAQ,CAAC,MAAM;SACrC,CAAC,CAAC;QACH,OAAO,UAAU,CAAC;IACpB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,sEAAsE;QACtE,IAAI,KAAK,YAAY,YAAY,IAAI,KAAK,CAAC,IAAI,KAAK,4BAA4B,EAAE,CAAC;YACjF,MAAM,KAAK,CAAC;QACd,CAAC;QACD,GAAG,CAAC,IAAI,CAAC,4BAA4B,KAAK,EAAE,EAAE;YAC5C,IAAI,EAAE,UAAU;YAChB,EAAE,EAAE,QAAQ;YACZ,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC;SACrB,CAAC,CAAC;QACH,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,KAAK,UAAU,mCAAmC,CAChD,UAAwD,YAAY;IAEpE,OAAO,0BAA0B,CAC/B,kCAAkC,EAAE,EACpC,cAAc,EAAE,EAChB,OAAO,EACP,yBAAyB,CAC1B,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAS,4BAA4B;IACnC,OAAO,IAAI,CAAC,YAAY,EAAE,EAAE,kBAAkB,CAAC,CAAC;AAClD,CAAC;AAED,SAAS,kCAAkC;IACzC,OAAO,IAAI,CAAC,YAAY,EAAE,EAAE,yBAAyB,CAAC,CAAC;AACzD,CAAC;AAED,KAAK,UAAU,kCAAkC;IAC/C,MAAM,QAAQ,GAAG,4BAA4B,EAAE,CAAC;IAChD,MAAM,oBAAoB,GAAG,KAAK,EAAE,OAAyB,EAAiB,EAAE;QAC9E,MAAM,2BAA2B,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IACvD,CAAC,CAAC;IAEF,OAAO,0BAA0B,CAC/B,kCAAkC,EAAE,EACpC,QAAQ,EACR,oBAAoB,EACpB,wBAAwB,CACzB,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAS,8BAA8B;IACrC,OAAO,OAAO,CAAC,qBAAqB,EAAE,IAAI,qBAAqB,EAAE,CAAC,CAAC;AACrE,CAAC;AAED;;;GAGG;AACH,KAAK,UAAU,0BAA0B;IACvC,MAAM,kBAAkB,GAAG,qBAAqB,EAAE,CAAC;IACnD,IAAI,CAAC,8BAA8B,EAAE,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAC7D,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,kCAAkC,EAAE,CAAC;IAC5D,IAAI,QAAQ,EAAE,CAAC;QACb,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,MAAM,iBAAiB,GAAG,4BAA4B,EAAE,CAAC;IACzD,IAAI,iBAAiB,KAAK,kBAAkB,EAAE,CAAC;QAC7C,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,iBAAiB,EAAE,OAAO,CAAC,CAAC;QAC9D,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAY,CAAC;QAE5C,MAAM,YAAY,GAAG,mBAAmB,CAAC,uBAAuB,EAAE,IAAI,CAAC,CAAC;QACxE,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC5B,GAAG,CAAC,IAAI,CAAC,mDAAmD,EAAE;gBAC5D,IAAI,EAAE,iBAAiB;gBACvB,MAAM,EAAE,YAAY,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;aACjC,CAAC,CAAC;QACL,CAAC;QAED,MAAM,UAAU,GAAG,uBAAuB,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;QACpE,IAAI,CAAC,UAAU;YAAE,OAAO,IAAI,CAAC;QAE7B,GAAG,CAAC,IAAI,CAAC,mDAAmD,EAAE;YAC5D,IAAI,EAAE,iBAAiB;YACvB,EAAE,EAAE,kBAAkB;YACtB,QAAQ,EAAE,UAAU,CAAC,QAAQ,CAAC,MAAM;SACrC,CAAC,CAAC;QACH,OAAO,UAAU,CAAC;IACpB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,0EAA0E;QAC1E,iEAAiE;QACjE,IAAI,KAAK,YAAY,YAAY,IAAI,KAAK,CAAC,IAAI,KAAK,4BAA4B,EAAE,CAAC;YACjF,MAAM,KAAK,CAAC;QACd,CAAC;QACD,MAAM,IAAI,GAAI,KAA+B,CAAC,IAAI,CAAC;QACnD,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;YACtB,GAAG,CAAC,IAAI,CAAC,gDAAgD,EAAE;gBACzD,IAAI,EAAE,iBAAiB;gBACvB,EAAE,EAAE,kBAAkB;gBACtB,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC;aACrB,CAAC,CAAC;QACL,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,KAAK,UAAU,oBAAoB,CACjC,gBAAuE;IAEvE,wEAAwE;IACxE,yEAAyE;IACzE,2DAA2D;IAC3D,MAAM,kCAAkC,CAAC,MAAM,CAAC,CAAC;IAEjD,wEAAwE;IACxE,wEAAwE;IACxE,0EAA0E;IAC1E,yEAAyE;IACzE,0EAA0E;IAC1E,sEAAsE;IACtE,6DAA6D;IAC7D,IAAI,sBAAsB,EAAE,EAAE,CAAC;QAC7B,MAAM,UAAU,GAAG,2BAA2B,EAAE,CAAC;QACjD,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,gBAAgB,CAAC,UAAU,CAAC,CAAC;YAChD,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;gBAClB,IAAI,CAAC;oBACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAY,CAAC;oBAC3C,MAAM,UAAU,GAAG,uBAAuB,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;oBACjE,IAAI,UAAU;wBAAE,OAAO,UAAU,CAAC;gBACpC,CAAC;gBAAC,OAAO,QAAQ,EAAE,CAAC;oBAClB,8DAA8D;oBAC9D,8CAA8C;oBAC9C,GAAG,CAAC,IAAI,CAAC,gEAAgE,EAAE;wBACzE,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC;qBACxB,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,GAAG,CAAC,IAAI,CAAC,qDAAqD,CAAC,CAAC;YAClE,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,GAAG,CAAC,IAAI,CAAC,6CAA6C,EAAE;gBACtD,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC;aACnB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,cAAc,EAAE,CAAC;QAC9B,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACjD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAY,CAAC;QAE5C,MAAM,YAAY,GAAG,mBAAmB,CAAC,uBAAuB,EAAE,IAAI,CAAC,CAAC;QACxE,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC5B,GAAG,CAAC,IAAI,CAAC,4CAA4C,EAAE,EAAE,MAAM,EAAE,YAAY,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;QAC/F,CAAC;QAED,MAAM,UAAU,GAAG,uBAAuB,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAEvD,MAAM,aAAa,GACjB,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC;YACtD,CAAC,CAAE,IAA8B,CAAC,OAAO;YACzC,CAAC,CAAC,SAAS,CAAC;QAChB,IAAI,UAAU,IAAI,aAAa,KAAK,UAAU,CAAC,OAAO,EAAE,CAAC;YACvD,GAAG,CAAC,IAAI,CAAC,iCAAiC,EAAE,EAAE,IAAI,EAAE,aAAa,EAAE,EAAE,EAAE,UAAU,CAAC,OAAO,EAAE,CAAC,CAAC;YAC7F,IAAI,gBAAgB,EAAE,CAAC;gBACrB,IAAI,CAAC;oBACH,MAAM,gBAAgB,CAAC,UAAU,CAAC,CAAC;gBACrC,CAAC;gBAAC,OAAO,SAAS,EAAE,CAAC;oBACnB,GAAG,CAAC,IAAI,CAAC,oCAAoC,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;gBAC/E,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,UAAU,CAAC;IACpB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,0EAA0E;QAC1E,4EAA4E;QAC5E,gCAAgC;QAChC,IAAI,KAAK,YAAY,YAAY,IAAI,KAAK,CAAC,IAAI,KAAK,4BAA4B,EAAE,CAAC;YACjF,MAAM,KAAK,CAAC;QACd,CAAC;QACD,qEAAqE;QACrE,mEAAmE;QACnE,qEAAqE;QACrE,mEAAmE;QACnE,6DAA6D;QAC7D,IAAI,KAAK,YAAY,YAAY,IAAI,KAAK,CAAC,IAAI,KAAK,sBAAsB,EAAE,CAAC;YAC3E,oEAAoE;YACpE,gDAAgD;YAChD,MAAM,YAAY,GAAG,CAAC,GAAG,EAAE;gBACzB,IAAI,CAAC;oBACH,OAAO,cAAc,EAAE,CAAC;gBAC1B,CAAC;gBAAC,MAAM,CAAC;oBACP,OAAO,EAAE,CAAC;gBACZ,CAAC;YACH,CAAC,CAAC,EAAE,CAAC;YACL,IAAI,YAAY,EAAE,CAAC;gBACjB,MAAM,IAAI,YAAY,CACpB,KAAK,CAAC,OAAO,EACb,sBAAsB,EACtB,YAAY,EACZ,mBAAmB,CAAC,YAAY,CAAC,EACjC,KAAK,CACN,CAAC;YACJ,CAAC;YACD,MAAM,KAAK,CAAC;QACd,CAAC;QACD,MAAM,IAAI,GAAI,KAA+B,CAAC,IAAI,CAAC;QACnD,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;YACtB,MAAM,QAAQ,GAAG,gBAAgB;gBAC/B,CAAC,CAAC,MAAM,mCAAmC,CAAC,gBAAgB,CAAC;gBAC7D,CAAC,CAAC,IAAI,CAAC;YACT,IAAI,QAAQ;gBAAE,OAAO,QAAQ,CAAC;YAC9B,IAAI,CAAC,8BAA8B,EAAE,EAAE,CAAC;gBACtC,MAAM,cAAc,GAAG,gBAAgB;oBACrC,CAAC,CAAC,MAAM,kCAAkC,EAAE;oBAC5C,CAAC,CAAC,IAAI,CAAC;gBACT,IAAI,cAAc;oBAAE,OAAO,cAAc,CAAC;gBAC1C,OAAO,IAAI,CAAC;YACd,CAAC;YACD,MAAM,cAAc,GAAG,MAAM,0BAA0B,EAAE,CAAC;YAC1D,IAAI,CAAC,cAAc;gBAAE,OAAO,IAAI,CAAC;YAEjC,IAAI,gBAAgB,EAAE,CAAC;gBACrB,MAAM,QAAQ,GAAG,cAAc,EAAE,CAAC;gBAClC,IAAI,CAAC;oBACH,MAAM,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;oBAC1B,OAAO,cAAc,CAAC;gBACxB,CAAC;gBAAC,OAAO,WAAW,EAAE,CAAC;oBACrB,MAAM,UAAU,GAAI,WAAqC,CAAC,IAAI,CAAC;oBAC/D,IAAI,UAAU,KAAK,QAAQ,EAAE,CAAC;wBAC5B,GAAG,CAAC,IAAI,CAAC,6DAA6D,EAAE;4BACtE,IAAI,EAAE,QAAQ;4BACd,KAAK,EAAE,MAAM,CAAC,WAAW,CAAC;yBAC3B,CAAC,CAAC;wBACH,OAAO,cAAc,CAAC;oBACxB,CAAC;oBACD,4CAA4C;gBAC9C,CAAC;gBAED,IAAI,CAAC;oBACH,MAAM,gBAAgB,CAAC,cAAc,CAAC,CAAC;oBACvC,GAAG,CAAC,IAAI,CAAC,qDAAqD,EAAE;wBAC9D,IAAI,EAAE,QAAQ;wBACd,QAAQ,EAAE,cAAc,CAAC,QAAQ,CAAC,MAAM;qBACzC,CAAC,CAAC;gBACL,CAAC;gBAAC,OAAO,YAAY,EAAE,CAAC;oBACtB,GAAG,CAAC,IAAI,CAAC,qDAAqD,EAAE;wBAC9D,IAAI,EAAE,QAAQ;wBACd,KAAK,EAAE,MAAM,CAAC,YAAY,CAAC;qBAC5B,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;YAED,OAAO,cAAc,CAAC;QACxB,CAAC;QACD,GAAG,CAAC,KAAK,CAAC,gCAAgC,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACtE,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,KAAK,UAAU,2BAA2B,CAAC,IAAY,EAAE,OAAyB;IAChF,MAAM,YAAY,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;IAC/E,MAAM,QAAQ,GAAG,GAAG,IAAI,IAAI,YAAY,MAAM,CAAC;IAE/C,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACnD,MAAM,eAAe,CAAC,IAAI,CAAC,CAAC;QAE5B,2EAA2E;QAC3E,8EAA8E;QAC9E,MAAM,iBAAiB,GAAG,uBAAuB,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC;QACtE,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,iBAAiB,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QAC3D,MAAM,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QAE1E,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACtC,IAAI,KAAK,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;YACrB,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,4BAA4B,CAAC,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;YAC9F,MAAM,UAAU,CAAC;QACnB,CAAC;QAED,MAAM,sBAAsB,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IAC/C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC5B,CAAC;QAAC,MAAM,CAAC;YACP,0BAA0B;QAC5B,CAAC;QAED,MAAM,GAAG,GAAG,KAA8B,CAAC;QAC3C,MAAM,IAAI,GAAG,GAAG,EAAE,IAAI,IAAI,SAAS,CAAC;QACpC,MAAM,IAAI,GAAG,sBAAsB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QAEjD,GAAG,CAAC,KAAK,CAAC,yBAAyB,EAAE;YACnC,IAAI;YACJ,IAAI;YACJ,OAAO,EAAE,GAAG,EAAE,OAAO;YACrB,IAAI;SACL,CAAC,CAAC;QAEH,MAAM,IAAI,YAAY,CACpB,4BAA4B,GAAG,EAAE,OAAO,IAAI,eAAe,EAAE,EAC7D,IAAI,EACJ,IAAI,EACJ,IAAI,EACJ,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CACvC,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,KAAK,UAAU,iCAAiC,CAC9C,IAAY,EACZ,YAA8B;IAE9B,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACxB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,6BAA6B;IACvC,CAAC;IACD,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;IACjE,MAAM,MAAM,GAAG,GAAG,IAAI,yBAAyB,SAAS,EAAE,CAAC;IAC3D,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAC9B,iEAAiE;QACjE,uEAAuE;QACvE,qEAAqE;QACrE,qEAAqE;QACrE,mEAAmE;QACnE,gEAAgE;QAChE,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;YACjC,IAAI,CAAC;gBACH,MAAM,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;YAChC,CAAC;YAAC,OAAO,QAAQ,EAAE,CAAC;gBAClB,GAAG,CAAC,IAAI,CAAC,wDAAwD,EAAE;oBACjE,MAAM;oBACN,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC;iBACxB,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QACD,GAAG,CAAC,IAAI,CAAC,8EAA8E,EAAE;YACvF,IAAI,EAAE,IAAI;YACV,MAAM;SACP,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,GAAG,CAAC,IAAI,CACN,wJAAwJ,EACxJ;YACE,IAAI;YACJ,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC;SACnB,CACF,CAAC;QACF,IAAI,CAAC;YACH,MAAM,2BAA2B,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;QACxD,CAAC;QAAC,OAAO,QAAQ,EAAE,CAAC;YAClB,+DAA+D;YAC/D,kEAAkE;YAClE,6DAA6D;YAC7D,6DAA6D;YAC7D,GAAG,CAAC,KAAK,CACP,sHAAsH,EACtH;gBACE,IAAI;gBACJ,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC;aACxB,CACF,CAAC;QACJ,CAAC;IACH,CAAC;AACH,CAAC;AAED,KAAK,UAAU,oBAAoB,CAAC,OAAyB;IAC3D,sEAAsE;IACtE,qEAAqE;IACrE,yCAAyC;IACzC,MAAM,kCAAkC,CAAC,MAAM,CAAC,CAAC;IAEjD,IAAI,sBAAsB,EAAE,EAAE,CAAC;QAC7B,uEAAuE;QACvE,wEAAwE;QACxE,qEAAqE;QACrE,2DAA2D;QAC3D,MAAM,iBAAiB,GAAG,uBAAuB,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC;QACtE,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,iBAAiB,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QACxD,MAAM,UAAU,GAAG,2BAA2B,EAAE,CAAC;QACjD,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;QACvD,IAAI,MAAM,CAAC,EAAE,EAAE,CAAC;YACd,MAAM,iCAAiC,CAAC,cAAc,EAAE,EAAE,iBAAiB,CAAC,CAAC;YAC7E,OAAO;QACT,CAAC;QACD,GAAG,CAAC,IAAI,CAAC,4DAA4D,EAAE;YACrE,KAAK,EAAE,MAAM,CAAC,KAAK;SACpB,CAAC,CAAC;IACL,CAAC;IAED,MAAM,2BAA2B,CAAC,cAAc,EAAE,EAAE,OAAO,CAAC,CAAC;AAC/D,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY;IAChC,OAAO,eAAe,CAAC,KAAK,IAAI,EAAE,CAAC,oBAAoB,CAAC,oBAAoB,CAAC,CAAC,CAAC;AACjF,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,6BAA6B,CACjD,OAGe;IAEf,OAAO,eAAe,CAAC,KAAK,IAAI,EAAE;QAChC,MAAM,OAAO,GAAG,MAAM,oBAAoB,CAAC,oBAAoB,CAAC,CAAC;QACjE,OAAO,OAAO,CAAC,OAAO,EAAE,oBAAoB,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,OAAyB;IAC1D,OAAO,eAAe,CAAC,KAAK,IAAI,EAAE;QAChC,MAAM,oBAAoB,CAAC,OAAO,CAAC,CAAC;IACtC,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,OAAO,eAAe,CAAC,KAAK,IAAI,EAAE;QAChC,IAAI,WAAW,GAAG,IAAI,CAAC;QACvB,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,cAAc,EAAE,CAAC;YAC9B,MAAM,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACxB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,GAAI,KAA+B,CAAC,IAAI,CAAC;YACnD,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACtB,WAAW,GAAG,KAAK,CAAC;gBACpB,GAAG,CAAC,KAAK,CACP,+GAA+G,EAC/G,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,CACzB,CAAC;YACJ,CAAC;QACH,CAAC;QAED,oEAAoE;QACpE,oEAAoE;QACpE,iEAAiE;QACjE,mEAAmE;QACnE,IAAI,WAAW,IAAI,sBAAsB,EAAE,EAAE,CAAC;YAC5C,IAAI,CAAC;gBACH,MAAM,UAAU,GAAG,2BAA2B,EAAE,CAAC;gBACjD,MAAM,kBAAkB,CAAC,UAAU,CAAC,CAAC;YACvC,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,GAAG,CAAC,IAAI,CAAC,8CAA8C,EAAE;oBACvD,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC;iBACnB,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -5,6 +5,41 @@
5
5
  import { type ModelFamily } from "../prompts/codex.js";
6
6
  import type { AccountIdSource } from "../types.js";
7
7
  export type CooldownReason = "auth-failure" | "network-error";
8
+ /**
9
+ * StorageError code emitted when a `version: 2` account file is loaded.
10
+ *
11
+ * V2 is an intermediate account schema produced by legacy 4.x plugin builds
12
+ * that never shipped with a documented shape nor a forward-migrator to V3.
13
+ * The safe behaviour is to refuse to load V2 explicitly so the user's
14
+ * credentials are not silently discarded; callers surface this code to the
15
+ * user alongside a recovery hint.
16
+ */
17
+ export declare const UNKNOWN_V2_FORMAT_CODE = "UNKNOWN_V2_FORMAT";
18
+ /**
19
+ * Minimal detection shape for V2 account storage.
20
+ *
21
+ * The full V2 schema was never documented and no V2 migrator shipped, so this
22
+ * type is intentionally coarse: it only captures the fields needed to detect
23
+ * that a file claims `version: 2` and contains something account-shaped. Do
24
+ * not extend this shape without evidence of the real V2 layout - inventing
25
+ * fields risks producing a silently-wrong migration.
26
+ */
27
+ export interface AccountStorageV2Detected {
28
+ version: 2;
29
+ accounts?: unknown[];
30
+ }
31
+ /**
32
+ * Diagnostic message shown when the loader refuses a V2 storage file.
33
+ * Pulled into a helper so storage.ts, import paths, and tests produce
34
+ * identical copy without drifting.
35
+ */
36
+ export declare function buildV2RejectionMessage(): string;
37
+ /**
38
+ * Recovery hint shown alongside the V2 rejection message.
39
+ * @param path - Absolute path of the offending storage file, or a placeholder
40
+ * when the caller cannot determine the source (e.g. in-memory normalization).
41
+ */
42
+ export declare function buildV2RecoveryHint(path: string): string;
8
43
  export interface RateLimitStateV3 {
9
44
  [key: string]: number | undefined;
10
45
  }