codex-multi-auth 1.2.0 → 1.2.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 (675) hide show
  1. package/README.md +49 -32
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +910 -1704
  4. package/dist/index.js.map +1 -1
  5. package/dist/lib/auth/index.d.ts +2 -0
  6. package/dist/lib/auth/index.d.ts.map +1 -0
  7. package/dist/lib/auth/index.js +2 -0
  8. package/dist/lib/auth/index.js.map +1 -0
  9. package/dist/lib/codex-cli/index.d.ts +5 -0
  10. package/dist/lib/codex-cli/index.d.ts.map +1 -0
  11. package/dist/lib/codex-cli/index.js +5 -0
  12. package/dist/lib/codex-cli/index.js.map +1 -0
  13. package/dist/lib/codex-manager/auth-commands.d.ts +72 -0
  14. package/dist/lib/codex-manager/auth-commands.d.ts.map +1 -0
  15. package/dist/lib/codex-manager/auth-commands.js +643 -0
  16. package/dist/lib/codex-manager/auth-commands.js.map +1 -0
  17. package/dist/lib/codex-manager/backend-category-entry.d.ts +103 -0
  18. package/dist/lib/codex-manager/backend-category-entry.d.ts.map +1 -0
  19. package/dist/lib/codex-manager/backend-category-entry.js +23 -0
  20. package/dist/lib/codex-manager/backend-category-entry.js.map +1 -0
  21. package/dist/lib/codex-manager/backend-category-helpers.d.ts +10 -0
  22. package/dist/lib/codex-manager/backend-category-helpers.d.ts.map +1 -0
  23. package/dist/lib/codex-manager/backend-category-helpers.js +29 -0
  24. package/dist/lib/codex-manager/backend-category-helpers.js.map +1 -0
  25. package/dist/lib/codex-manager/backend-category-prompt.d.ts +55 -0
  26. package/dist/lib/codex-manager/backend-category-prompt.d.ts.map +1 -0
  27. package/dist/lib/codex-manager/backend-category-prompt.js +178 -0
  28. package/dist/lib/codex-manager/backend-category-prompt.js.map +1 -0
  29. package/dist/lib/codex-manager/backend-settings-controller.d.ts +11 -0
  30. package/dist/lib/codex-manager/backend-settings-controller.d.ts.map +1 -0
  31. package/dist/lib/codex-manager/backend-settings-controller.js +14 -0
  32. package/dist/lib/codex-manager/backend-settings-controller.js.map +1 -0
  33. package/dist/lib/codex-manager/backend-settings-entry.d.ts +20 -0
  34. package/dist/lib/codex-manager/backend-settings-entry.d.ts.map +1 -0
  35. package/dist/lib/codex-manager/backend-settings-entry.js +12 -0
  36. package/dist/lib/codex-manager/backend-settings-entry.js.map +1 -0
  37. package/dist/lib/codex-manager/backend-settings-helpers.d.ts +16 -0
  38. package/dist/lib/codex-manager/backend-settings-helpers.d.ts.map +1 -0
  39. package/dist/lib/codex-manager/backend-settings-helpers.js +102 -0
  40. package/dist/lib/codex-manager/backend-settings-helpers.js.map +1 -0
  41. package/dist/lib/codex-manager/backend-settings-prompt.d.ts +49 -0
  42. package/dist/lib/codex-manager/backend-settings-prompt.d.ts.map +1 -0
  43. package/dist/lib/codex-manager/backend-settings-prompt.js +121 -0
  44. package/dist/lib/codex-manager/backend-settings-prompt.js.map +1 -0
  45. package/dist/lib/codex-manager/backend-settings-schema.d.ts +55 -0
  46. package/dist/lib/codex-manager/backend-settings-schema.d.ts.map +1 -0
  47. package/dist/lib/codex-manager/backend-settings-schema.js +264 -0
  48. package/dist/lib/codex-manager/backend-settings-schema.js.map +1 -0
  49. package/dist/lib/codex-manager/behavior-settings-panel.d.ts +33 -0
  50. package/dist/lib/codex-manager/behavior-settings-panel.d.ts.map +1 -0
  51. package/dist/lib/codex-manager/behavior-settings-panel.js +180 -0
  52. package/dist/lib/codex-manager/behavior-settings-panel.js.map +1 -0
  53. package/dist/lib/codex-manager/best.d.ts +26 -0
  54. package/dist/lib/codex-manager/best.d.ts.map +1 -0
  55. package/dist/lib/codex-manager/best.js +249 -0
  56. package/dist/lib/codex-manager/best.js.map +1 -0
  57. package/dist/lib/codex-manager/commands/best.d.ts +81 -0
  58. package/dist/lib/codex-manager/commands/best.d.ts.map +1 -0
  59. package/dist/lib/codex-manager/commands/best.js +223 -0
  60. package/dist/lib/codex-manager/commands/best.js.map +1 -0
  61. package/dist/lib/codex-manager/commands/check.d.ts +7 -0
  62. package/dist/lib/codex-manager/commands/check.d.ts.map +1 -0
  63. package/dist/lib/codex-manager/commands/check.js +5 -0
  64. package/dist/lib/codex-manager/commands/check.js.map +1 -0
  65. package/dist/lib/codex-manager/commands/config-explain.d.ts +7 -0
  66. package/dist/lib/codex-manager/commands/config-explain.d.ts.map +1 -0
  67. package/dist/lib/codex-manager/commands/config-explain.js +31 -0
  68. package/dist/lib/codex-manager/commands/config-explain.js.map +1 -0
  69. package/dist/lib/codex-manager/commands/debug-bundle.d.ts +28 -0
  70. package/dist/lib/codex-manager/commands/debug-bundle.d.ts.map +1 -0
  71. package/dist/lib/codex-manager/commands/debug-bundle.js +62 -0
  72. package/dist/lib/codex-manager/commands/debug-bundle.js.map +1 -0
  73. package/dist/lib/codex-manager/commands/doctor.d.ts +85 -0
  74. package/dist/lib/codex-manager/commands/doctor.d.ts.map +1 -0
  75. package/dist/lib/codex-manager/commands/doctor.js +424 -0
  76. package/dist/lib/codex-manager/commands/doctor.js.map +1 -0
  77. package/dist/lib/codex-manager/commands/fix.d.ts +92 -0
  78. package/dist/lib/codex-manager/commands/fix.d.ts.map +1 -0
  79. package/dist/lib/codex-manager/commands/fix.js +347 -0
  80. package/dist/lib/codex-manager/commands/fix.js.map +1 -0
  81. package/dist/lib/codex-manager/commands/forecast.d.ts +70 -0
  82. package/dist/lib/codex-manager/commands/forecast.d.ts.map +1 -0
  83. package/dist/lib/codex-manager/commands/forecast.js +281 -0
  84. package/dist/lib/codex-manager/commands/forecast.js.map +1 -0
  85. package/dist/lib/codex-manager/commands/init-config.d.ts +15 -0
  86. package/dist/lib/codex-manager/commands/init-config.d.ts.map +1 -0
  87. package/dist/lib/codex-manager/commands/init-config.js +95 -0
  88. package/dist/lib/codex-manager/commands/init-config.js.map +1 -0
  89. package/dist/lib/codex-manager/commands/report.d.ts +24 -0
  90. package/dist/lib/codex-manager/commands/report.d.ts.map +1 -0
  91. package/dist/lib/codex-manager/commands/report.js +314 -0
  92. package/dist/lib/codex-manager/commands/report.js.map +1 -0
  93. package/dist/lib/codex-manager/commands/status.d.ts +23 -0
  94. package/dist/lib/codex-manager/commands/status.d.ts.map +1 -0
  95. package/dist/lib/codex-manager/commands/status.js +50 -0
  96. package/dist/lib/codex-manager/commands/status.js.map +1 -0
  97. package/dist/lib/codex-manager/commands/switch.d.ts +22 -0
  98. package/dist/lib/codex-manager/commands/switch.d.ts.map +1 -0
  99. package/dist/lib/codex-manager/commands/switch.js +41 -0
  100. package/dist/lib/codex-manager/commands/switch.js.map +1 -0
  101. package/dist/lib/codex-manager/commands/verify-flagged.d.ts +69 -0
  102. package/dist/lib/codex-manager/commands/verify-flagged.d.ts.map +1 -0
  103. package/dist/lib/codex-manager/commands/verify-flagged.js +251 -0
  104. package/dist/lib/codex-manager/commands/verify-flagged.js.map +1 -0
  105. package/dist/lib/codex-manager/config-explain.d.ts +2 -0
  106. package/dist/lib/codex-manager/config-explain.d.ts.map +1 -0
  107. package/dist/lib/codex-manager/config-explain.js +62 -0
  108. package/dist/lib/codex-manager/config-explain.js.map +1 -0
  109. package/dist/lib/codex-manager/config-template.d.ts +2 -0
  110. package/dist/lib/codex-manager/config-template.d.ts.map +1 -0
  111. package/dist/lib/codex-manager/config-template.js +112 -0
  112. package/dist/lib/codex-manager/config-template.js.map +1 -0
  113. package/dist/lib/codex-manager/dashboard-display-panel.d.ts +40 -0
  114. package/dist/lib/codex-manager/dashboard-display-panel.d.ts.map +1 -0
  115. package/dist/lib/codex-manager/dashboard-display-panel.js +187 -0
  116. package/dist/lib/codex-manager/dashboard-display-panel.js.map +1 -0
  117. package/dist/lib/codex-manager/dashboard-formatters.d.ts +6 -0
  118. package/dist/lib/codex-manager/dashboard-formatters.d.ts.map +1 -0
  119. package/dist/lib/codex-manager/dashboard-formatters.js +19 -0
  120. package/dist/lib/codex-manager/dashboard-formatters.js.map +1 -0
  121. package/dist/lib/codex-manager/dashboard-settings-controller.d.ts +12 -0
  122. package/dist/lib/codex-manager/dashboard-settings-controller.d.ts.map +1 -0
  123. package/dist/lib/codex-manager/dashboard-settings-controller.js +17 -0
  124. package/dist/lib/codex-manager/dashboard-settings-controller.js.map +1 -0
  125. package/dist/lib/codex-manager/dashboard-settings-data.d.ts +10 -0
  126. package/dist/lib/codex-manager/dashboard-settings-data.d.ts.map +1 -0
  127. package/dist/lib/codex-manager/dashboard-settings-data.js +95 -0
  128. package/dist/lib/codex-manager/dashboard-settings-data.js.map +1 -0
  129. package/dist/lib/codex-manager/dashboard-settings-entry.d.ts +22 -0
  130. package/dist/lib/codex-manager/dashboard-settings-entry.d.ts.map +1 -0
  131. package/dist/lib/codex-manager/dashboard-settings-entry.js +13 -0
  132. package/dist/lib/codex-manager/dashboard-settings-entry.js.map +1 -0
  133. package/dist/lib/codex-manager/debug-bundle.d.ts +2 -0
  134. package/dist/lib/codex-manager/debug-bundle.d.ts.map +1 -0
  135. package/dist/lib/codex-manager/debug-bundle.js +128 -0
  136. package/dist/lib/codex-manager/debug-bundle.js.map +1 -0
  137. package/dist/lib/codex-manager/doctor.d.ts +20 -0
  138. package/dist/lib/codex-manager/doctor.d.ts.map +1 -0
  139. package/dist/lib/codex-manager/doctor.js +546 -0
  140. package/dist/lib/codex-manager/doctor.js.map +1 -0
  141. package/dist/lib/codex-manager/experimental-settings-entry.d.ts +7 -0
  142. package/dist/lib/codex-manager/experimental-settings-entry.d.ts.map +1 -0
  143. package/dist/lib/codex-manager/experimental-settings-entry.js +30 -0
  144. package/dist/lib/codex-manager/experimental-settings-entry.js.map +1 -0
  145. package/dist/lib/codex-manager/experimental-settings-prompt.d.ts +66 -0
  146. package/dist/lib/codex-manager/experimental-settings-prompt.d.ts.map +1 -0
  147. package/dist/lib/codex-manager/experimental-settings-prompt.js +221 -0
  148. package/dist/lib/codex-manager/experimental-settings-prompt.js.map +1 -0
  149. package/dist/lib/codex-manager/experimental-settings-schema.d.ts +23 -0
  150. package/dist/lib/codex-manager/experimental-settings-schema.d.ts.map +1 -0
  151. package/dist/lib/codex-manager/experimental-settings-schema.js +34 -0
  152. package/dist/lib/codex-manager/experimental-settings-schema.js.map +1 -0
  153. package/dist/lib/codex-manager/experimental-sync-target-entry.d.ts +30 -0
  154. package/dist/lib/codex-manager/experimental-sync-target-entry.d.ts.map +1 -0
  155. package/dist/lib/codex-manager/experimental-sync-target-entry.js +16 -0
  156. package/dist/lib/codex-manager/experimental-sync-target-entry.js.map +1 -0
  157. package/dist/lib/codex-manager/experimental-sync-target.d.ts +23 -0
  158. package/dist/lib/codex-manager/experimental-sync-target.d.ts.map +1 -0
  159. package/dist/lib/codex-manager/experimental-sync-target.js +39 -0
  160. package/dist/lib/codex-manager/experimental-sync-target.js.map +1 -0
  161. package/dist/lib/codex-manager/fix.d.ts +26 -0
  162. package/dist/lib/codex-manager/fix.d.ts.map +1 -0
  163. package/dist/lib/codex-manager/fix.js +366 -0
  164. package/dist/lib/codex-manager/fix.js.map +1 -0
  165. package/dist/lib/codex-manager/forecast-report-commands.d.ts +54 -0
  166. package/dist/lib/codex-manager/forecast-report-commands.d.ts.map +1 -0
  167. package/dist/lib/codex-manager/forecast-report-commands.js +443 -0
  168. package/dist/lib/codex-manager/forecast-report-commands.js.map +1 -0
  169. package/dist/lib/codex-manager/forecast.d.ts +26 -0
  170. package/dist/lib/codex-manager/forecast.d.ts.map +1 -0
  171. package/dist/lib/codex-manager/forecast.js +218 -0
  172. package/dist/lib/codex-manager/forecast.js.map +1 -0
  173. package/dist/lib/codex-manager/help.d.ts +36 -0
  174. package/dist/lib/codex-manager/help.d.ts.map +1 -0
  175. package/dist/lib/codex-manager/help.js +125 -0
  176. package/dist/lib/codex-manager/help.js.map +1 -0
  177. package/dist/lib/codex-manager/info.d.ts +11 -0
  178. package/dist/lib/codex-manager/info.d.ts.map +1 -0
  179. package/dist/lib/codex-manager/info.js +91 -0
  180. package/dist/lib/codex-manager/info.js.map +1 -0
  181. package/dist/lib/codex-manager/login.d.ts +40 -0
  182. package/dist/lib/codex-manager/login.d.ts.map +1 -0
  183. package/dist/lib/codex-manager/login.js +1041 -0
  184. package/dist/lib/codex-manager/login.js.map +1 -0
  185. package/dist/lib/codex-manager/repair-commands.d.ts +70 -0
  186. package/dist/lib/codex-manager/repair-commands.d.ts.map +1 -0
  187. package/dist/lib/codex-manager/repair-commands.js +1671 -0
  188. package/dist/lib/codex-manager/repair-commands.js.map +1 -0
  189. package/dist/lib/codex-manager/report.d.ts +39 -0
  190. package/dist/lib/codex-manager/report.d.ts.map +1 -0
  191. package/dist/lib/codex-manager/report.js +243 -0
  192. package/dist/lib/codex-manager/report.js.map +1 -0
  193. package/dist/lib/codex-manager/settings-hub-entry.d.ts +30 -0
  194. package/dist/lib/codex-manager/settings-hub-entry.d.ts.map +1 -0
  195. package/dist/lib/codex-manager/settings-hub-entry.js +11 -0
  196. package/dist/lib/codex-manager/settings-hub-entry.js.map +1 -0
  197. package/dist/lib/codex-manager/settings-hub-menu.d.ts +30 -0
  198. package/dist/lib/codex-manager/settings-hub-menu.d.ts.map +1 -0
  199. package/dist/lib/codex-manager/settings-hub-menu.js +37 -0
  200. package/dist/lib/codex-manager/settings-hub-menu.js.map +1 -0
  201. package/dist/lib/codex-manager/settings-hub-prompt.d.ts +25 -0
  202. package/dist/lib/codex-manager/settings-hub-prompt.d.ts.map +1 -0
  203. package/dist/lib/codex-manager/settings-hub-prompt.js +23 -0
  204. package/dist/lib/codex-manager/settings-hub-prompt.js.map +1 -0
  205. package/dist/lib/codex-manager/settings-hub.d.ts +10 -29
  206. package/dist/lib/codex-manager/settings-hub.d.ts.map +1 -1
  207. package/dist/lib/codex-manager/settings-hub.js +260 -2168
  208. package/dist/lib/codex-manager/settings-hub.js.map +1 -1
  209. package/dist/lib/codex-manager/settings-panels.d.ts +56 -0
  210. package/dist/lib/codex-manager/settings-panels.d.ts.map +1 -0
  211. package/dist/lib/codex-manager/settings-panels.js +73 -0
  212. package/dist/lib/codex-manager/settings-panels.js.map +1 -0
  213. package/dist/lib/codex-manager/settings-persist-utils.d.ts +9 -0
  214. package/dist/lib/codex-manager/settings-persist-utils.d.ts.map +1 -0
  215. package/dist/lib/codex-manager/settings-persist-utils.js +33 -0
  216. package/dist/lib/codex-manager/settings-persist-utils.js.map +1 -0
  217. package/dist/lib/codex-manager/settings-preview.d.ts +12 -0
  218. package/dist/lib/codex-manager/settings-preview.d.ts.map +1 -0
  219. package/dist/lib/codex-manager/settings-preview.js +118 -0
  220. package/dist/lib/codex-manager/settings-preview.js.map +1 -0
  221. package/dist/lib/codex-manager/settings-write-queue.d.ts +14 -0
  222. package/dist/lib/codex-manager/settings-write-queue.d.ts.map +1 -0
  223. package/dist/lib/codex-manager/settings-write-queue.js +88 -0
  224. package/dist/lib/codex-manager/settings-write-queue.js.map +1 -0
  225. package/dist/lib/codex-manager/statusline-order.d.ts +3 -0
  226. package/dist/lib/codex-manager/statusline-order.d.ts.map +1 -0
  227. package/dist/lib/codex-manager/statusline-order.js +17 -0
  228. package/dist/lib/codex-manager/statusline-order.js.map +1 -0
  229. package/dist/lib/codex-manager/statusline-settings-panel.d.ts +40 -0
  230. package/dist/lib/codex-manager/statusline-settings-panel.d.ts.map +1 -0
  231. package/dist/lib/codex-manager/statusline-settings-panel.js +167 -0
  232. package/dist/lib/codex-manager/statusline-settings-panel.js.map +1 -0
  233. package/dist/lib/codex-manager/switch.d.ts +31 -0
  234. package/dist/lib/codex-manager/switch.d.ts.map +1 -0
  235. package/dist/lib/codex-manager/switch.js +103 -0
  236. package/dist/lib/codex-manager/switch.js.map +1 -0
  237. package/dist/lib/codex-manager/theme-settings-panel.d.ts +26 -0
  238. package/dist/lib/codex-manager/theme-settings-panel.d.ts.map +1 -0
  239. package/dist/lib/codex-manager/theme-settings-panel.js +131 -0
  240. package/dist/lib/codex-manager/theme-settings-panel.js.map +1 -0
  241. package/dist/lib/codex-manager/unified-settings-controller.d.ts +27 -0
  242. package/dist/lib/codex-manager/unified-settings-controller.d.ts.map +1 -0
  243. package/dist/lib/codex-manager/unified-settings-controller.js +50 -0
  244. package/dist/lib/codex-manager/unified-settings-controller.js.map +1 -0
  245. package/dist/lib/codex-manager/unified-settings-entry.d.ts +6 -0
  246. package/dist/lib/codex-manager/unified-settings-entry.d.ts.map +1 -0
  247. package/dist/lib/codex-manager/unified-settings-entry.js +23 -0
  248. package/dist/lib/codex-manager/unified-settings-entry.js.map +1 -0
  249. package/dist/lib/codex-manager/verify-flagged.d.ts +20 -0
  250. package/dist/lib/codex-manager/verify-flagged.d.ts.map +1 -0
  251. package/dist/lib/codex-manager/verify-flagged.js +316 -0
  252. package/dist/lib/codex-manager/verify-flagged.js.map +1 -0
  253. package/dist/lib/codex-manager.d.ts.map +1 -1
  254. package/dist/lib/codex-manager.js +439 -2199
  255. package/dist/lib/codex-manager.js.map +1 -1
  256. package/dist/lib/config.d.ts +38 -0
  257. package/dist/lib/config.d.ts.map +1 -1
  258. package/dist/lib/config.js +371 -9
  259. package/dist/lib/config.js.map +1 -1
  260. package/dist/lib/errors.d.ts +9 -0
  261. package/dist/lib/errors.d.ts.map +1 -1
  262. package/dist/lib/errors.js +13 -0
  263. package/dist/lib/errors.js.map +1 -1
  264. package/dist/lib/forecast.d.ts +17 -0
  265. package/dist/lib/forecast.d.ts.map +1 -1
  266. package/dist/lib/forecast.js +33 -6
  267. package/dist/lib/forecast.js.map +1 -1
  268. package/dist/lib/named-backup-export.js +2 -2
  269. package/dist/lib/named-backup-export.js.map +1 -1
  270. package/dist/lib/prompts/codex.d.ts +8 -3
  271. package/dist/lib/prompts/codex.d.ts.map +1 -1
  272. package/dist/lib/prompts/codex.js +16 -26
  273. package/dist/lib/prompts/codex.js.map +1 -1
  274. package/dist/lib/request/failover-config.d.ts +4 -0
  275. package/dist/lib/request/failover-config.d.ts.map +1 -0
  276. package/dist/lib/request/failover-config.js +15 -0
  277. package/dist/lib/request/failover-config.js.map +1 -0
  278. package/dist/lib/request/fetch-helpers.d.ts +10 -4
  279. package/dist/lib/request/fetch-helpers.d.ts.map +1 -1
  280. package/dist/lib/request/fetch-helpers.js +13 -8
  281. package/dist/lib/request/fetch-helpers.js.map +1 -1
  282. package/dist/lib/request/helpers/model-map.d.ts +49 -12
  283. package/dist/lib/request/helpers/model-map.d.ts.map +1 -1
  284. package/dist/lib/request/helpers/model-map.js +303 -108
  285. package/dist/lib/request/helpers/model-map.js.map +1 -1
  286. package/dist/lib/request/helpers/tool-utils.d.ts +2 -15
  287. package/dist/lib/request/helpers/tool-utils.d.ts.map +1 -1
  288. package/dist/lib/request/helpers/tool-utils.js +40 -27
  289. package/dist/lib/request/helpers/tool-utils.js.map +1 -1
  290. package/dist/lib/request/index.d.ts +5 -0
  291. package/dist/lib/request/index.d.ts.map +1 -0
  292. package/dist/lib/request/index.js +5 -0
  293. package/dist/lib/request/index.js.map +1 -0
  294. package/dist/lib/request/request-init.d.ts +3 -0
  295. package/dist/lib/request/request-init.d.ts.map +1 -0
  296. package/dist/lib/request/request-init.js +50 -0
  297. package/dist/lib/request/request-init.js.map +1 -0
  298. package/dist/lib/request/request-transformer.d.ts +19 -6
  299. package/dist/lib/request/request-transformer.d.ts.map +1 -1
  300. package/dist/lib/request/request-transformer.js +210 -193
  301. package/dist/lib/request/request-transformer.js.map +1 -1
  302. package/dist/lib/request/response-compaction.d.ts +20 -0
  303. package/dist/lib/request/response-compaction.d.ts.map +1 -0
  304. package/dist/lib/request/response-compaction.js +124 -0
  305. package/dist/lib/request/response-compaction.js.map +1 -0
  306. package/dist/lib/request/response-handler.d.ts +2 -0
  307. package/dist/lib/request/response-handler.d.ts.map +1 -1
  308. package/dist/lib/request/response-handler.js +567 -11
  309. package/dist/lib/request/response-handler.js.map +1 -1
  310. package/dist/lib/request/response-metadata.d.ts +3 -0
  311. package/dist/lib/request/response-metadata.d.ts.map +1 -0
  312. package/dist/lib/request/response-metadata.js +61 -0
  313. package/dist/lib/request/response-metadata.js.map +1 -0
  314. package/dist/lib/request/trace-mode.d.ts +9 -0
  315. package/dist/lib/request/trace-mode.d.ts.map +1 -0
  316. package/dist/lib/request/trace-mode.js +14 -0
  317. package/dist/lib/request/trace-mode.js.map +1 -0
  318. package/dist/lib/request/wait-utils.d.ts +14 -0
  319. package/dist/lib/request/wait-utils.d.ts.map +1 -0
  320. package/dist/lib/request/wait-utils.js +44 -0
  321. package/dist/lib/request/wait-utils.js.map +1 -0
  322. package/dist/lib/runtime/account-check-helpers.d.ts +8 -0
  323. package/dist/lib/runtime/account-check-helpers.d.ts.map +1 -0
  324. package/dist/lib/runtime/account-check-helpers.js +30 -0
  325. package/dist/lib/runtime/account-check-helpers.js.map +1 -0
  326. package/dist/lib/runtime/account-check-types.d.ts +18 -0
  327. package/dist/lib/runtime/account-check-types.d.ts.map +1 -0
  328. package/dist/lib/runtime/account-check-types.js +12 -0
  329. package/dist/lib/runtime/account-check-types.js.map +1 -0
  330. package/dist/lib/runtime/account-check.d.ts +48 -0
  331. package/dist/lib/runtime/account-check.d.ts.map +1 -0
  332. package/dist/lib/runtime/account-check.js +202 -0
  333. package/dist/lib/runtime/account-check.js.map +1 -0
  334. package/dist/lib/runtime/account-health-check.d.ts +8 -0
  335. package/dist/lib/runtime/account-health-check.d.ts.map +1 -0
  336. package/dist/lib/runtime/account-health-check.js +30 -0
  337. package/dist/lib/runtime/account-health-check.js.map +1 -0
  338. package/dist/lib/runtime/account-manager-cache-entry.d.ts +25 -0
  339. package/dist/lib/runtime/account-manager-cache-entry.d.ts.map +1 -0
  340. package/dist/lib/runtime/account-manager-cache-entry.js +17 -0
  341. package/dist/lib/runtime/account-manager-cache-entry.js.map +1 -0
  342. package/dist/lib/runtime/account-manager-cache.d.ts +25 -0
  343. package/dist/lib/runtime/account-manager-cache.d.ts.map +1 -0
  344. package/dist/lib/runtime/account-manager-cache.js +44 -0
  345. package/dist/lib/runtime/account-manager-cache.js.map +1 -0
  346. package/dist/lib/runtime/account-pool.d.ts +23 -0
  347. package/dist/lib/runtime/account-pool.d.ts.map +1 -0
  348. package/dist/lib/runtime/account-pool.js +138 -0
  349. package/dist/lib/runtime/account-pool.js.map +1 -0
  350. package/dist/lib/runtime/account-scope.d.ts +10 -0
  351. package/dist/lib/runtime/account-scope.d.ts.map +1 -0
  352. package/dist/lib/runtime/account-scope.js +13 -0
  353. package/dist/lib/runtime/account-scope.js.map +1 -0
  354. package/dist/lib/runtime/account-select-event.d.ts +19 -0
  355. package/dist/lib/runtime/account-select-event.d.ts.map +1 -0
  356. package/dist/lib/runtime/account-select-event.js +53 -0
  357. package/dist/lib/runtime/account-select-event.js.map +1 -0
  358. package/dist/lib/runtime/account-selection.d.ts +28 -0
  359. package/dist/lib/runtime/account-selection.d.ts.map +1 -0
  360. package/dist/lib/runtime/account-selection.js +46 -0
  361. package/dist/lib/runtime/account-selection.js.map +1 -0
  362. package/dist/lib/runtime/account-state.d.ts +13 -0
  363. package/dist/lib/runtime/account-state.d.ts.map +1 -0
  364. package/dist/lib/runtime/account-state.js +38 -0
  365. package/dist/lib/runtime/account-state.js.map +1 -0
  366. package/dist/lib/runtime/account-status.d.ts +13 -0
  367. package/dist/lib/runtime/account-status.d.ts.map +1 -0
  368. package/dist/lib/runtime/account-status.js +37 -0
  369. package/dist/lib/runtime/account-status.js.map +1 -0
  370. package/dist/lib/runtime/account-storage-scope-entry.d.ts +26 -0
  371. package/dist/lib/runtime/account-storage-scope-entry.d.ts.map +1 -0
  372. package/dist/lib/runtime/account-storage-scope-entry.js +15 -0
  373. package/dist/lib/runtime/account-storage-scope-entry.js.map +1 -0
  374. package/dist/lib/runtime/auth-facade.d.ts +51 -0
  375. package/dist/lib/runtime/auth-facade.d.ts.map +1 -0
  376. package/dist/lib/runtime/auth-facade.js +48 -0
  377. package/dist/lib/runtime/auth-facade.js.map +1 -0
  378. package/dist/lib/runtime/browser-oauth-flow.d.ts +32 -0
  379. package/dist/lib/runtime/browser-oauth-flow.d.ts.map +1 -0
  380. package/dist/lib/runtime/browser-oauth-flow.js +31 -0
  381. package/dist/lib/runtime/browser-oauth-flow.js.map +1 -0
  382. package/dist/lib/runtime/capability-boost.d.ts +25 -0
  383. package/dist/lib/runtime/capability-boost.d.ts.map +1 -0
  384. package/dist/lib/runtime/capability-boost.js +26 -0
  385. package/dist/lib/runtime/capability-boost.js.map +1 -0
  386. package/dist/lib/runtime/event-handler.d.ts +53 -0
  387. package/dist/lib/runtime/event-handler.d.ts.map +1 -0
  388. package/dist/lib/runtime/event-handler.js +46 -0
  389. package/dist/lib/runtime/event-handler.js.map +1 -0
  390. package/dist/lib/runtime/flagged-verify-types.d.ts +9 -0
  391. package/dist/lib/runtime/flagged-verify-types.d.ts.map +1 -0
  392. package/dist/lib/runtime/flagged-verify-types.js +7 -0
  393. package/dist/lib/runtime/flagged-verify-types.js.map +1 -0
  394. package/dist/lib/runtime/hydrate-emails.d.ts +13 -0
  395. package/dist/lib/runtime/hydrate-emails.d.ts.map +1 -0
  396. package/dist/lib/runtime/hydrate-emails.js +56 -0
  397. package/dist/lib/runtime/hydrate-emails.js.map +1 -0
  398. package/dist/lib/runtime/live-sync-entry.d.ts +36 -0
  399. package/dist/lib/runtime/live-sync-entry.d.ts.map +1 -0
  400. package/dist/lib/runtime/live-sync-entry.js +14 -0
  401. package/dist/lib/runtime/live-sync-entry.js.map +1 -0
  402. package/dist/lib/runtime/live-sync.d.ts +35 -0
  403. package/dist/lib/runtime/live-sync.d.ts.map +1 -0
  404. package/dist/lib/runtime/live-sync.js +65 -0
  405. package/dist/lib/runtime/live-sync.js.map +1 -0
  406. package/dist/lib/runtime/loader-setup.d.ts +9 -0
  407. package/dist/lib/runtime/loader-setup.d.ts.map +1 -0
  408. package/dist/lib/runtime/loader-setup.js +8 -0
  409. package/dist/lib/runtime/loader-setup.js.map +1 -0
  410. package/dist/lib/runtime/login-menu-accounts.d.ts +29 -0
  411. package/dist/lib/runtime/login-menu-accounts.d.ts.map +1 -0
  412. package/dist/lib/runtime/login-menu-accounts.js +33 -0
  413. package/dist/lib/runtime/login-menu-accounts.js.map +1 -0
  414. package/dist/lib/runtime/manual-oauth-flow.d.ts +40 -0
  415. package/dist/lib/runtime/manual-oauth-flow.d.ts.map +1 -0
  416. package/dist/lib/runtime/manual-oauth-flow.js +71 -0
  417. package/dist/lib/runtime/manual-oauth-flow.js.map +1 -0
  418. package/dist/lib/runtime/metrics.d.ts +29 -0
  419. package/dist/lib/runtime/metrics.d.ts.map +1 -0
  420. package/dist/lib/runtime/metrics.js +97 -0
  421. package/dist/lib/runtime/metrics.js.map +1 -0
  422. package/dist/lib/runtime/oauth-browser-flow.d.ts +9 -0
  423. package/dist/lib/runtime/oauth-browser-flow.d.ts.map +1 -0
  424. package/dist/lib/runtime/oauth-browser-flow.js +34 -0
  425. package/dist/lib/runtime/oauth-browser-flow.js.map +1 -0
  426. package/dist/lib/runtime/preemptive-quota.d.ts +13 -0
  427. package/dist/lib/runtime/preemptive-quota.d.ts.map +1 -0
  428. package/dist/lib/runtime/preemptive-quota.js +9 -0
  429. package/dist/lib/runtime/preemptive-quota.js.map +1 -0
  430. package/dist/lib/runtime/quota-headers.d.ts +12 -0
  431. package/dist/lib/runtime/quota-headers.d.ts.map +1 -0
  432. package/dist/lib/runtime/quota-headers.js +131 -0
  433. package/dist/lib/runtime/quota-headers.js.map +1 -0
  434. package/dist/lib/runtime/quota-probe.d.ts +18 -0
  435. package/dist/lib/runtime/quota-probe.d.ts.map +1 -0
  436. package/dist/lib/runtime/quota-probe.js +82 -0
  437. package/dist/lib/runtime/quota-probe.js.map +1 -0
  438. package/dist/lib/runtime/quota-settings.d.ts +14 -0
  439. package/dist/lib/runtime/quota-settings.d.ts.map +1 -0
  440. package/dist/lib/runtime/quota-settings.js +12 -0
  441. package/dist/lib/runtime/quota-settings.js.map +1 -0
  442. package/dist/lib/runtime/refresh-guardian-entry.d.ts +32 -0
  443. package/dist/lib/runtime/refresh-guardian-entry.d.ts.map +1 -0
  444. package/dist/lib/runtime/refresh-guardian-entry.js +12 -0
  445. package/dist/lib/runtime/refresh-guardian-entry.js.map +1 -0
  446. package/dist/lib/runtime/refresh-guardian.d.ts +24 -0
  447. package/dist/lib/runtime/refresh-guardian.d.ts.map +1 -0
  448. package/dist/lib/runtime/refresh-guardian.js +32 -0
  449. package/dist/lib/runtime/refresh-guardian.js.map +1 -0
  450. package/dist/lib/runtime/request-init.d.ts +5 -0
  451. package/dist/lib/runtime/request-init.d.ts.map +1 -0
  452. package/dist/lib/runtime/request-init.js +50 -0
  453. package/dist/lib/runtime/request-init.js.map +1 -0
  454. package/dist/lib/runtime/runtime-services.d.ts +58 -0
  455. package/dist/lib/runtime/runtime-services.d.ts.map +1 -0
  456. package/dist/lib/runtime/runtime-services.js +87 -0
  457. package/dist/lib/runtime/runtime-services.js.map +1 -0
  458. package/dist/lib/runtime/session-affinity-entry.d.ts +30 -0
  459. package/dist/lib/runtime/session-affinity-entry.d.ts.map +1 -0
  460. package/dist/lib/runtime/session-affinity-entry.js +11 -0
  461. package/dist/lib/runtime/session-affinity-entry.js.map +1 -0
  462. package/dist/lib/runtime/session-affinity.d.ts +13 -0
  463. package/dist/lib/runtime/session-affinity.d.ts.map +1 -0
  464. package/dist/lib/runtime/session-affinity.js +17 -0
  465. package/dist/lib/runtime/session-affinity.js.map +1 -0
  466. package/dist/lib/runtime/session-recovery.d.ts +8 -0
  467. package/dist/lib/runtime/session-recovery.d.ts.map +1 -0
  468. package/dist/lib/runtime/session-recovery.js +7 -0
  469. package/dist/lib/runtime/session-recovery.js.map +1 -0
  470. package/dist/lib/runtime/status-marker.d.ts +3 -0
  471. package/dist/lib/runtime/status-marker.d.ts.map +1 -0
  472. package/dist/lib/runtime/status-marker.js +15 -0
  473. package/dist/lib/runtime/status-marker.js.map +1 -0
  474. package/dist/lib/runtime/storage-scope.d.ts +13 -0
  475. package/dist/lib/runtime/storage-scope.d.ts.map +1 -0
  476. package/dist/lib/runtime/storage-scope.js +14 -0
  477. package/dist/lib/runtime/storage-scope.js.map +1 -0
  478. package/dist/lib/runtime/toast.d.ts +16 -0
  479. package/dist/lib/runtime/toast.d.ts.map +1 -0
  480. package/dist/lib/runtime/toast.js +16 -0
  481. package/dist/lib/runtime/toast.js.map +1 -0
  482. package/dist/lib/runtime/ui-runtime-entry.d.ts +7 -0
  483. package/dist/lib/runtime/ui-runtime-entry.d.ts.map +1 -0
  484. package/dist/lib/runtime/ui-runtime-entry.js +4 -0
  485. package/dist/lib/runtime/ui-runtime-entry.js.map +1 -0
  486. package/dist/lib/runtime/ui-runtime.d.ts +9 -0
  487. package/dist/lib/runtime/ui-runtime.d.ts.map +1 -0
  488. package/dist/lib/runtime/ui-runtime.js +23 -0
  489. package/dist/lib/runtime/ui-runtime.js.map +1 -0
  490. package/dist/lib/runtime/verify-flagged.d.ts +44 -0
  491. package/dist/lib/runtime/verify-flagged.d.ts.map +1 -0
  492. package/dist/lib/runtime/verify-flagged.js +84 -0
  493. package/dist/lib/runtime/verify-flagged.js.map +1 -0
  494. package/dist/lib/schemas.d.ts +2 -0
  495. package/dist/lib/schemas.d.ts.map +1 -1
  496. package/dist/lib/schemas.js +2 -0
  497. package/dist/lib/schemas.js.map +1 -1
  498. package/dist/lib/session-affinity.d.ts +10 -0
  499. package/dist/lib/session-affinity.d.ts.map +1 -1
  500. package/dist/lib/session-affinity.js +53 -6
  501. package/dist/lib/session-affinity.js.map +1 -1
  502. package/dist/lib/storage/account-clear-entry.d.ts +16 -0
  503. package/dist/lib/storage/account-clear-entry.d.ts.map +1 -0
  504. package/dist/lib/storage/account-clear-entry.js +12 -0
  505. package/dist/lib/storage/account-clear-entry.js.map +1 -0
  506. package/dist/lib/storage/account-clear.d.ts +8 -0
  507. package/dist/lib/storage/account-clear.d.ts.map +1 -0
  508. package/dist/lib/storage/account-clear.js +29 -0
  509. package/dist/lib/storage/account-clear.js.map +1 -0
  510. package/dist/lib/storage/account-match-utils.d.ts +9 -0
  511. package/dist/lib/storage/account-match-utils.d.ts.map +1 -0
  512. package/dist/lib/storage/account-match-utils.js +45 -0
  513. package/dist/lib/storage/account-match-utils.js.map +1 -0
  514. package/dist/lib/storage/account-persistence.d.ts +3 -0
  515. package/dist/lib/storage/account-persistence.d.ts.map +1 -0
  516. package/dist/lib/storage/account-persistence.js +12 -0
  517. package/dist/lib/storage/account-persistence.js.map +1 -0
  518. package/dist/lib/storage/account-port.d.ts +50 -0
  519. package/dist/lib/storage/account-port.d.ts.map +1 -0
  520. package/dist/lib/storage/account-port.js +43 -0
  521. package/dist/lib/storage/account-port.js.map +1 -0
  522. package/dist/lib/storage/account-save-entry.d.ts +7 -0
  523. package/dist/lib/storage/account-save-entry.d.ts.map +1 -0
  524. package/dist/lib/storage/account-save-entry.js +6 -0
  525. package/dist/lib/storage/account-save-entry.js.map +1 -0
  526. package/dist/lib/storage/account-save.d.ts +30 -0
  527. package/dist/lib/storage/account-save.d.ts.map +1 -0
  528. package/dist/lib/storage/account-save.js +49 -0
  529. package/dist/lib/storage/account-save.js.map +1 -0
  530. package/dist/lib/storage/account-snapshot.d.ts +25 -0
  531. package/dist/lib/storage/account-snapshot.d.ts.map +1 -0
  532. package/dist/lib/storage/account-snapshot.js +78 -0
  533. package/dist/lib/storage/account-snapshot.js.map +1 -0
  534. package/dist/lib/storage/backup-metadata-builder.d.ts +32 -0
  535. package/dist/lib/storage/backup-metadata-builder.d.ts.map +1 -0
  536. package/dist/lib/storage/backup-metadata-builder.js +77 -0
  537. package/dist/lib/storage/backup-metadata-builder.js.map +1 -0
  538. package/dist/lib/storage/backup-metadata.d.ts +29 -0
  539. package/dist/lib/storage/backup-metadata.d.ts.map +1 -0
  540. package/dist/lib/storage/backup-metadata.js +16 -0
  541. package/dist/lib/storage/backup-metadata.js.map +1 -0
  542. package/dist/lib/storage/backup-paths.d.ts +10 -0
  543. package/dist/lib/storage/backup-paths.d.ts.map +1 -0
  544. package/dist/lib/storage/backup-paths.js +27 -0
  545. package/dist/lib/storage/backup-paths.js.map +1 -0
  546. package/dist/lib/storage/backup-restore.d.ts +11 -0
  547. package/dist/lib/storage/backup-restore.d.ts.map +1 -0
  548. package/dist/lib/storage/backup-restore.js +52 -0
  549. package/dist/lib/storage/backup-restore.js.map +1 -0
  550. package/dist/lib/storage/cache-artifacts.d.ts +2 -0
  551. package/dist/lib/storage/cache-artifacts.d.ts.map +1 -0
  552. package/dist/lib/storage/cache-artifacts.js +4 -0
  553. package/dist/lib/storage/cache-artifacts.js.map +1 -0
  554. package/dist/lib/storage/error-hints.d.ts +10 -0
  555. package/dist/lib/storage/error-hints.d.ts.map +1 -0
  556. package/dist/lib/storage/error-hints.js +36 -0
  557. package/dist/lib/storage/error-hints.js.map +1 -0
  558. package/dist/lib/storage/file-paths.d.ts +6 -0
  559. package/dist/lib/storage/file-paths.d.ts.map +1 -0
  560. package/dist/lib/storage/file-paths.js +17 -0
  561. package/dist/lib/storage/file-paths.js.map +1 -0
  562. package/dist/lib/storage/fixture-guards.d.ts +4 -0
  563. package/dist/lib/storage/fixture-guards.d.ts.map +1 -0
  564. package/dist/lib/storage/fixture-guards.js +27 -0
  565. package/dist/lib/storage/fixture-guards.js.map +1 -0
  566. package/dist/lib/storage/flagged-entry.d.ts +15 -0
  567. package/dist/lib/storage/flagged-entry.d.ts.map +1 -0
  568. package/dist/lib/storage/flagged-entry.js +12 -0
  569. package/dist/lib/storage/flagged-entry.js.map +1 -0
  570. package/dist/lib/storage/flagged-load-entry.d.ts +20 -0
  571. package/dist/lib/storage/flagged-load-entry.d.ts.map +1 -0
  572. package/dist/lib/storage/flagged-load-entry.js +13 -0
  573. package/dist/lib/storage/flagged-load-entry.js.map +1 -0
  574. package/dist/lib/storage/flagged-save-entry.d.ts +7 -0
  575. package/dist/lib/storage/flagged-save-entry.d.ts.map +1 -0
  576. package/dist/lib/storage/flagged-save-entry.js +6 -0
  577. package/dist/lib/storage/flagged-save-entry.js.map +1 -0
  578. package/dist/lib/storage/flagged-storage-file.d.ts +7 -0
  579. package/dist/lib/storage/flagged-storage-file.d.ts.map +1 -0
  580. package/dist/lib/storage/flagged-storage-file.js +25 -0
  581. package/dist/lib/storage/flagged-storage-file.js.map +1 -0
  582. package/dist/lib/storage/flagged-storage-io.d.ts +28 -0
  583. package/dist/lib/storage/flagged-storage-io.d.ts.map +1 -0
  584. package/dist/lib/storage/flagged-storage-io.js +135 -0
  585. package/dist/lib/storage/flagged-storage-io.js.map +1 -0
  586. package/dist/lib/storage/flagged-storage.d.ts +6 -0
  587. package/dist/lib/storage/flagged-storage.d.ts.map +1 -0
  588. package/dist/lib/storage/flagged-storage.js +90 -0
  589. package/dist/lib/storage/flagged-storage.js.map +1 -0
  590. package/dist/lib/storage/gitignore.d.ts +7 -0
  591. package/dist/lib/storage/gitignore.d.ts.map +1 -0
  592. package/dist/lib/storage/gitignore.js +34 -0
  593. package/dist/lib/storage/gitignore.js.map +1 -0
  594. package/dist/lib/storage/hash.d.ts +2 -0
  595. package/dist/lib/storage/hash.d.ts.map +1 -0
  596. package/dist/lib/storage/hash.js +5 -0
  597. package/dist/lib/storage/hash.js.map +1 -0
  598. package/dist/lib/storage/identity.d.ts +15 -0
  599. package/dist/lib/storage/identity.d.ts.map +1 -0
  600. package/dist/lib/storage/identity.js +48 -0
  601. package/dist/lib/storage/identity.js.map +1 -0
  602. package/dist/lib/storage/import-export.d.ts +24 -0
  603. package/dist/lib/storage/import-export.d.ts.map +1 -0
  604. package/dist/lib/storage/import-export.js +108 -0
  605. package/dist/lib/storage/import-export.js.map +1 -0
  606. package/dist/lib/storage/metadata-section.d.ts +16 -0
  607. package/dist/lib/storage/metadata-section.d.ts.map +1 -0
  608. package/dist/lib/storage/metadata-section.js +16 -0
  609. package/dist/lib/storage/metadata-section.js.map +1 -0
  610. package/dist/lib/storage/named-backup-entry.d.ts +15 -0
  611. package/dist/lib/storage/named-backup-entry.d.ts.map +1 -0
  612. package/dist/lib/storage/named-backup-entry.js +7 -0
  613. package/dist/lib/storage/named-backup-entry.js.map +1 -0
  614. package/dist/lib/storage/named-backups-entry.d.ts +19 -0
  615. package/dist/lib/storage/named-backups-entry.d.ts.map +1 -0
  616. package/dist/lib/storage/named-backups-entry.js +7 -0
  617. package/dist/lib/storage/named-backups-entry.js.map +1 -0
  618. package/dist/lib/storage/named-backups.d.ts +15 -0
  619. package/dist/lib/storage/named-backups.d.ts.map +1 -0
  620. package/dist/lib/storage/named-backups.js +68 -0
  621. package/dist/lib/storage/named-backups.js.map +1 -0
  622. package/dist/lib/storage/path-state.d.ts +9 -0
  623. package/dist/lib/storage/path-state.d.ts.map +1 -0
  624. package/dist/lib/storage/path-state.js +20 -0
  625. package/dist/lib/storage/path-state.js.map +1 -0
  626. package/dist/lib/storage/project-migration.d.ts +10 -0
  627. package/dist/lib/storage/project-migration.d.ts.map +1 -0
  628. package/dist/lib/storage/project-migration.js +38 -0
  629. package/dist/lib/storage/project-migration.js.map +1 -0
  630. package/dist/lib/storage/record-utils.d.ts +3 -0
  631. package/dist/lib/storage/record-utils.d.ts.map +1 -0
  632. package/dist/lib/storage/record-utils.js +9 -0
  633. package/dist/lib/storage/record-utils.js.map +1 -0
  634. package/dist/lib/storage/restore-assessment.d.ts +7 -0
  635. package/dist/lib/storage/restore-assessment.d.ts.map +1 -0
  636. package/dist/lib/storage/restore-assessment.js +42 -0
  637. package/dist/lib/storage/restore-assessment.js.map +1 -0
  638. package/dist/lib/storage/restore-backup-entry.d.ts +24 -0
  639. package/dist/lib/storage/restore-backup-entry.d.ts.map +1 -0
  640. package/dist/lib/storage/restore-backup-entry.js +10 -0
  641. package/dist/lib/storage/restore-backup-entry.js.map +1 -0
  642. package/dist/lib/storage/restore-metadata.d.ts +10 -0
  643. package/dist/lib/storage/restore-metadata.d.ts.map +1 -0
  644. package/dist/lib/storage/restore-metadata.js +18 -0
  645. package/dist/lib/storage/restore-metadata.js.map +1 -0
  646. package/dist/lib/storage/restore.d.ts +14 -0
  647. package/dist/lib/storage/restore.d.ts.map +1 -0
  648. package/dist/lib/storage/restore.js +53 -0
  649. package/dist/lib/storage/restore.js.map +1 -0
  650. package/dist/lib/storage/snapshot-inspectors.d.ts +22 -0
  651. package/dist/lib/storage/snapshot-inspectors.d.ts.map +1 -0
  652. package/dist/lib/storage/snapshot-inspectors.js +95 -0
  653. package/dist/lib/storage/snapshot-inspectors.js.map +1 -0
  654. package/dist/lib/storage/storage-parser.d.ts +15 -0
  655. package/dist/lib/storage/storage-parser.d.ts.map +1 -0
  656. package/dist/lib/storage/storage-parser.js +16 -0
  657. package/dist/lib/storage/storage-parser.js.map +1 -0
  658. package/dist/lib/storage/transactions.d.ts +23 -0
  659. package/dist/lib/storage/transactions.d.ts.map +1 -0
  660. package/dist/lib/storage/transactions.js +64 -0
  661. package/dist/lib/storage/transactions.js.map +1 -0
  662. package/dist/lib/storage.d.ts +8 -47
  663. package/dist/lib/storage.d.ts.map +1 -1
  664. package/dist/lib/storage.js +482 -1044
  665. package/dist/lib/storage.js.map +1 -1
  666. package/dist/lib/types.d.ts +80 -1
  667. package/dist/lib/types.d.ts.map +1 -1
  668. package/package.json +41 -4
  669. package/scripts/check-pack-budget-lib.js +114 -0
  670. package/scripts/check-pack-budget.mjs +10 -0
  671. package/scripts/codex-multi-auth.js +34 -10
  672. package/scripts/install-codex-auth-utils.js +54 -14
  673. package/scripts/install-codex-auth.js +62 -33
  674. package/scripts/update-vendor-provenance.mjs +96 -0
  675. package/scripts/verify-vendor-provenance.mjs +53 -0
@@ -1,17 +1,43 @@
1
- import { promises as fs } from "node:fs";
2
1
  import { stdin as input, stdout as output } from "node:process";
3
- import { createInterface } from "node:readline/promises";
4
- import { getDefaultPluginConfig, loadPluginConfig, savePluginConfig, } from "../config.js";
2
+ import { loadPluginConfig, savePluginConfig } from "../config.js";
5
3
  import { DEFAULT_DASHBOARD_DISPLAY_SETTINGS, getDashboardSettingsPath, loadDashboardDisplaySettings, saveDashboardDisplaySettings, } from "../dashboard-settings.js";
6
4
  import { applyOcChatgptSync, planOcChatgptSync, runNamedBackupExport, } from "../oc-chatgpt-orchestrator.js";
7
5
  import { detectOcChatgptMultiAuthTarget } from "../oc-chatgpt-target-detection.js";
8
6
  import { loadAccounts, normalizeAccountStorage } from "../storage.js";
9
- import { ANSI } from "../ui/ansi.js";
10
7
  import { UI_COPY } from "../ui/copy.js";
11
8
  import { getUiRuntimeOptions, setUiRuntimeOptions } from "../ui/runtime.js";
12
9
  import { select } from "../ui/select.js";
13
- import { getUnifiedSettingsPath } from "../unified-settings.js";
14
10
  import { sleep } from "../utils.js";
11
+ import { promptBackendCategorySettingsEntry } from "./backend-category-entry.js";
12
+ import { applyBackendCategoryDefaults, getBackendCategory, getBackendCategoryInitialFocus, resolveFocusedBackendNumberKey, } from "./backend-category-helpers.js";
13
+ import { promptBackendCategorySettingsMenu } from "./backend-category-prompt.js";
14
+ import { configureBackendSettingsController } from "./backend-settings-controller.js";
15
+ import { configureBackendSettingsEntry } from "./backend-settings-entry.js";
16
+ import { backendSettingsEqual, buildBackendConfigPatch, buildBackendSettingsPreview, clampBackendNumberForTests, cloneBackendPluginConfig, formatBackendNumberValue, } from "./backend-settings-helpers.js";
17
+ import { promptBackendSettingsMenu } from "./backend-settings-prompt.js";
18
+ import { BACKEND_CATEGORY_OPTIONS, BACKEND_DEFAULTS, BACKEND_NUMBER_OPTION_BY_KEY, BACKEND_TOGGLE_OPTION_BY_KEY, } from "./backend-settings-schema.js";
19
+ import { promptBehaviorSettingsPanel } from "./behavior-settings-panel.js";
20
+ import { promptDashboardDisplayPanel, } from "./dashboard-display-panel.js";
21
+ import { formatDashboardSettingState, formatMenuLayoutMode, formatMenuQuotaTtl, formatMenuSortMode, } from "./dashboard-formatters.js";
22
+ import { configureDashboardSettingsController } from "./dashboard-settings-controller.js";
23
+ import { cloneDashboardSettingsData, dashboardSettingsDataEqual, } from "./dashboard-settings-data.js";
24
+ import { configureDashboardSettingsEntry } from "./dashboard-settings-entry.js";
25
+ import { promptExperimentalSettingsEntry } from "./experimental-settings-entry.js";
26
+ import { promptExperimentalSettingsMenu } from "./experimental-settings-prompt.js";
27
+ import { getExperimentalSelectOptions, mapExperimentalMenuHotkey, mapExperimentalStatusHotkey, } from "./experimental-settings-schema.js";
28
+ import { loadExperimentalSyncTargetState } from "./experimental-sync-target.js";
29
+ import { loadExperimentalSyncTargetEntry } from "./experimental-sync-target-entry.js";
30
+ import { promptSettingsHubEntry } from "./settings-hub-entry.js";
31
+ import { buildSettingsHubItems, findSettingsHubInitialCursor, } from "./settings-hub-menu.js";
32
+ import { promptSettingsHubMenu } from "./settings-hub-prompt.js";
33
+ import { promptBehaviorSettingsPanelEntry, promptDashboardDisplaySettingsPanelEntry, promptStatuslineSettingsPanelEntry, promptThemeSettingsPanelEntry, reorderStatuslineField, } from "./settings-panels.js";
34
+ import { readFileWithRetry, resolvePluginConfigSavePathKey, warnPersistFailure, } from "./settings-persist-utils.js";
35
+ import { buildAccountListPreview as buildAccountListPreviewBase, buildSummaryPreviewText as buildSummaryPreviewTextBase, highlightPreviewToken, normalizeStatuslineFields, } from "./settings-preview.js";
36
+ import { withQueuedRetry } from "./settings-write-queue.js";
37
+ import { promptStatuslineSettingsPanel } from "./statusline-settings-panel.js";
38
+ import { promptThemeSettingsPanel } from "./theme-settings-panel.js";
39
+ import { configureUnifiedSettingsController, } from "./unified-settings-controller.js";
40
+ import { configureUnifiedSettingsEntry } from "./unified-settings-entry.js";
15
41
  const DASHBOARD_DISPLAY_OPTIONS = [
16
42
  {
17
43
  key: "menuShowStatusBadge",
@@ -64,11 +90,6 @@ const DASHBOARD_DISPLAY_OPTIONS = [
64
90
  description: "Number keys (1-9) follow what you see in the list.",
65
91
  },
66
92
  ];
67
- const DEFAULT_STATUSLINE_FIELDS = [
68
- "last-used",
69
- "limits",
70
- "status",
71
- ];
72
93
  const STATUSLINE_FIELD_OPTIONS = [
73
94
  {
74
95
  key: "last-used",
@@ -95,312 +116,6 @@ const ACCENT_COLOR_OPTIONS = [
95
116
  "blue",
96
117
  "yellow",
97
118
  ];
98
- const PREVIEW_ACCOUNT_EMAIL = "demo@example.com";
99
- const PREVIEW_LAST_USED = "today";
100
- const PREVIEW_STATUS = "active";
101
- const PREVIEW_LIMITS = "5h ██████▒▒▒▒ 62% | 7d █████▒▒▒▒▒ 49%";
102
- const PREVIEW_LIMIT_COOLDOWNS = "5h reset 1h 20m | 7d reset 2d 04h";
103
- function getExperimentalSelectOptions(ui, help, onInput) {
104
- return {
105
- message: UI_COPY.settings.experimentalTitle,
106
- subtitle: UI_COPY.settings.experimentalSubtitle,
107
- help,
108
- clearScreen: true,
109
- theme: ui.theme,
110
- selectedEmphasis: "minimal",
111
- onInput,
112
- };
113
- }
114
- function mapExperimentalMenuHotkey(raw) {
115
- if (raw === "1")
116
- return { type: "sync" };
117
- if (raw === "2")
118
- return { type: "backup" };
119
- if (raw === "3")
120
- return { type: "toggle-refresh-guardian" };
121
- if (raw === "[" || raw === "-")
122
- return { type: "decrease-refresh-interval" };
123
- if (raw === "]" || raw === "+")
124
- return { type: "increase-refresh-interval" };
125
- const lower = raw.toLowerCase();
126
- if (lower === "q")
127
- return { type: "back" };
128
- if (lower === "s")
129
- return { type: "save" };
130
- return undefined;
131
- }
132
- function mapExperimentalStatusHotkey(raw) {
133
- return raw.toLowerCase() === "q" ? { type: "back" } : undefined;
134
- }
135
- const BACKEND_TOGGLE_OPTIONS = [
136
- {
137
- key: "liveAccountSync",
138
- label: "Enable Live Sync",
139
- description: "Keep accounts synced when files change in another window.",
140
- },
141
- {
142
- key: "sessionAffinity",
143
- label: "Enable Session Affinity",
144
- description: "Try to keep each conversation on the same account.",
145
- },
146
- {
147
- key: "proactiveRefreshGuardian",
148
- label: "Enable Token Refresh Guard",
149
- description: "Refresh tokens early in the background.",
150
- },
151
- {
152
- key: "retryAllAccountsRateLimited",
153
- label: "Retry When All Rate-Limited",
154
- description: "If all accounts are limited, wait and try again.",
155
- },
156
- {
157
- key: "parallelProbing",
158
- label: "Enable Parallel Probing",
159
- description: "Check multiple accounts at the same time.",
160
- },
161
- {
162
- key: "storageBackupEnabled",
163
- label: "Enable Storage Backups",
164
- description: "Create a backup before account data changes.",
165
- },
166
- {
167
- key: "preemptiveQuotaEnabled",
168
- label: "Enable Quota Deferral",
169
- description: "Delay requests before limits are fully exhausted.",
170
- },
171
- {
172
- key: "fastSession",
173
- label: "Enable Fast Session Mode",
174
- description: "Use lighter request handling for faster responses.",
175
- },
176
- {
177
- key: "sessionRecovery",
178
- label: "Enable Session Recovery",
179
- description: "Restore recoverable sessions after restart.",
180
- },
181
- {
182
- key: "autoResume",
183
- label: "Enable Auto Resume",
184
- description: "Automatically continue sessions when possible.",
185
- },
186
- {
187
- key: "perProjectAccounts",
188
- label: "Enable Per-Project Accounts",
189
- description: "Keep separate account lists for each project.",
190
- },
191
- ];
192
- const BACKEND_NUMBER_OPTIONS = [
193
- {
194
- key: "liveAccountSyncDebounceMs",
195
- label: "Live Sync Debounce",
196
- description: "Wait this long before applying sync file changes.",
197
- min: 50,
198
- max: 10_000,
199
- step: 50,
200
- unit: "ms",
201
- },
202
- {
203
- key: "liveAccountSyncPollMs",
204
- label: "Live Sync Poll",
205
- description: "How often to check files for account updates.",
206
- min: 500,
207
- max: 60_000,
208
- step: 500,
209
- unit: "ms",
210
- },
211
- {
212
- key: "sessionAffinityTtlMs",
213
- label: "Session Affinity TTL",
214
- description: "How long conversation-to-account mapping is kept.",
215
- min: 1_000,
216
- max: 24 * 60 * 60_000,
217
- step: 60_000,
218
- unit: "ms",
219
- },
220
- {
221
- key: "sessionAffinityMaxEntries",
222
- label: "Session Affinity Max Entries",
223
- description: "Maximum stored conversation mappings.",
224
- min: 8,
225
- max: 4_096,
226
- step: 32,
227
- unit: "count",
228
- },
229
- {
230
- key: "proactiveRefreshIntervalMs",
231
- label: "Refresh Guard Interval",
232
- description: "How often to scan for tokens near expiry.",
233
- min: 5_000,
234
- max: 10 * 60_000,
235
- step: 5_000,
236
- unit: "ms",
237
- },
238
- {
239
- key: "proactiveRefreshBufferMs",
240
- label: "Refresh Guard Buffer",
241
- description: "How early to refresh before expiry.",
242
- min: 30_000,
243
- max: 10 * 60_000,
244
- step: 30_000,
245
- unit: "ms",
246
- },
247
- {
248
- key: "parallelProbingMaxConcurrency",
249
- label: "Parallel Probe Concurrency",
250
- description: "Maximum checks running at once.",
251
- min: 1,
252
- max: 5,
253
- step: 1,
254
- unit: "count",
255
- },
256
- {
257
- key: "fastSessionMaxInputItems",
258
- label: "Fast Session Max Inputs",
259
- description: "Max number of input items kept in fast mode.",
260
- min: 8,
261
- max: 200,
262
- step: 2,
263
- unit: "count",
264
- },
265
- {
266
- key: "networkErrorCooldownMs",
267
- label: "Network Error Cooldown",
268
- description: "Wait time after network errors before retry.",
269
- min: 0,
270
- max: 120_000,
271
- step: 500,
272
- unit: "ms",
273
- },
274
- {
275
- key: "serverErrorCooldownMs",
276
- label: "Server Error Cooldown",
277
- description: "Wait time after server errors before retry.",
278
- min: 0,
279
- max: 120_000,
280
- step: 500,
281
- unit: "ms",
282
- },
283
- {
284
- key: "fetchTimeoutMs",
285
- label: "Request Timeout",
286
- description: "Max time to wait for a request.",
287
- min: 1_000,
288
- max: 10 * 60_000,
289
- step: 5_000,
290
- unit: "ms",
291
- },
292
- {
293
- key: "streamStallTimeoutMs",
294
- label: "Stream Stall Timeout",
295
- description: "Max wait before a stuck stream is retried.",
296
- min: 1_000,
297
- max: 10 * 60_000,
298
- step: 5_000,
299
- unit: "ms",
300
- },
301
- {
302
- key: "tokenRefreshSkewMs",
303
- label: "Token Refresh Buffer",
304
- description: "Refresh this long before token expiry.",
305
- min: 0,
306
- max: 10 * 60_000,
307
- step: 10_000,
308
- unit: "ms",
309
- },
310
- {
311
- key: "preemptiveQuotaRemainingPercent5h",
312
- label: "5h Remaining Threshold",
313
- description: "Start delaying when 5h remaining reaches this percent.",
314
- min: 0,
315
- max: 100,
316
- step: 1,
317
- unit: "percent",
318
- },
319
- {
320
- key: "preemptiveQuotaRemainingPercent7d",
321
- label: "7d Remaining Threshold",
322
- description: "Start delaying when weekly remaining reaches this percent.",
323
- min: 0,
324
- max: 100,
325
- step: 1,
326
- unit: "percent",
327
- },
328
- {
329
- key: "preemptiveQuotaMaxDeferralMs",
330
- label: "Max Preemptive Deferral",
331
- description: "Maximum time allowed for quota-based delay.",
332
- min: 1_000,
333
- max: 24 * 60 * 60_000,
334
- step: 60_000,
335
- unit: "ms",
336
- },
337
- ];
338
- const BACKEND_DEFAULTS = getDefaultPluginConfig();
339
- const BACKEND_TOGGLE_OPTION_BY_KEY = new Map(BACKEND_TOGGLE_OPTIONS.map((option) => [option.key, option]));
340
- const BACKEND_NUMBER_OPTION_BY_KEY = new Map(BACKEND_NUMBER_OPTIONS.map((option) => [option.key, option]));
341
- const BACKEND_CATEGORY_OPTIONS = [
342
- {
343
- key: "session-sync",
344
- label: "Session & Sync",
345
- description: "Sync and session behavior.",
346
- toggleKeys: [
347
- "liveAccountSync",
348
- "sessionAffinity",
349
- "perProjectAccounts",
350
- "sessionRecovery",
351
- "autoResume",
352
- ],
353
- numberKeys: [
354
- "liveAccountSyncDebounceMs",
355
- "liveAccountSyncPollMs",
356
- "sessionAffinityTtlMs",
357
- "sessionAffinityMaxEntries",
358
- ],
359
- },
360
- {
361
- key: "rotation-quota",
362
- label: "Rotation & Quota",
363
- description: "Quota and retry behavior.",
364
- toggleKeys: ["preemptiveQuotaEnabled", "retryAllAccountsRateLimited"],
365
- numberKeys: [
366
- "preemptiveQuotaRemainingPercent5h",
367
- "preemptiveQuotaRemainingPercent7d",
368
- "preemptiveQuotaMaxDeferralMs",
369
- ],
370
- },
371
- {
372
- key: "refresh-recovery",
373
- label: "Refresh & Recovery",
374
- description: "Token refresh and recovery safety.",
375
- toggleKeys: ["storageBackupEnabled"],
376
- numberKeys: ["proactiveRefreshBufferMs", "tokenRefreshSkewMs"],
377
- },
378
- {
379
- key: "performance-timeouts",
380
- label: "Performance & Timeouts",
381
- description: "Speed, probing, and timeout controls.",
382
- toggleKeys: ["fastSession", "parallelProbing"],
383
- numberKeys: [
384
- "fastSessionMaxInputItems",
385
- "parallelProbingMaxConcurrency",
386
- "fetchTimeoutMs",
387
- "streamStallTimeoutMs",
388
- "networkErrorCooldownMs",
389
- "serverErrorCooldownMs",
390
- ],
391
- },
392
- ];
393
- const RETRYABLE_SETTINGS_WRITE_CODES = new Set([
394
- "EBUSY",
395
- "EPERM",
396
- "EAGAIN",
397
- "ENOTEMPTY",
398
- "EACCES",
399
- ]);
400
- const SETTINGS_WRITE_MAX_ATTEMPTS = 4;
401
- const SETTINGS_WRITE_BASE_DELAY_MS = 20;
402
- const SETTINGS_WRITE_MAX_DELAY_MS = 30_000;
403
- const settingsWriteQueues = new Map();
404
119
  const ACCOUNT_LIST_PANEL_KEYS = [
405
120
  "menuShowStatusBadge",
406
121
  "menuShowCurrentBadge",
@@ -430,82 +145,6 @@ const THEME_PANEL_KEYS = [
430
145
  "uiThemePreset",
431
146
  "uiAccentColor",
432
147
  ];
433
- function readErrorNumber(value) {
434
- if (typeof value === "number" && Number.isFinite(value))
435
- return value;
436
- if (typeof value === "string" && value.trim().length > 0) {
437
- const parsed = Number.parseInt(value, 10);
438
- if (Number.isFinite(parsed))
439
- return parsed;
440
- }
441
- return undefined;
442
- }
443
- function getErrorStatusCode(error) {
444
- if (!error || typeof error !== "object")
445
- return undefined;
446
- const record = error;
447
- return readErrorNumber(record.status) ?? readErrorNumber(record.statusCode);
448
- }
449
- function getRetryAfterMs(error) {
450
- if (!error || typeof error !== "object")
451
- return undefined;
452
- const record = error;
453
- return (readErrorNumber(record.retryAfterMs) ??
454
- readErrorNumber(record.retry_after_ms) ??
455
- readErrorNumber(record.retryAfter) ??
456
- readErrorNumber(record.retry_after));
457
- }
458
- function isRetryableSettingsWriteError(error) {
459
- const statusCode = getErrorStatusCode(error);
460
- if (statusCode === 429)
461
- return true;
462
- const code = error?.code;
463
- return typeof code === "string" && RETRYABLE_SETTINGS_WRITE_CODES.has(code);
464
- }
465
- function resolveRetryDelayMs(error, attempt) {
466
- const retryAfterMs = getRetryAfterMs(error);
467
- if (typeof retryAfterMs === "number" &&
468
- Number.isFinite(retryAfterMs) &&
469
- retryAfterMs > 0) {
470
- return Math.max(10, Math.min(SETTINGS_WRITE_MAX_DELAY_MS, Math.round(retryAfterMs)));
471
- }
472
- return Math.min(SETTINGS_WRITE_MAX_DELAY_MS, SETTINGS_WRITE_BASE_DELAY_MS * 2 ** attempt);
473
- }
474
- async function enqueueSettingsWrite(pathKey, task) {
475
- const previous = settingsWriteQueues.get(pathKey) ?? Promise.resolve();
476
- const queued = previous.catch(() => { }).then(task);
477
- const queueTail = queued.then(() => undefined, () => undefined);
478
- settingsWriteQueues.set(pathKey, queueTail);
479
- try {
480
- return await queued;
481
- }
482
- finally {
483
- if (settingsWriteQueues.get(pathKey) === queueTail) {
484
- settingsWriteQueues.delete(pathKey);
485
- }
486
- }
487
- }
488
- async function withQueuedRetry(pathKey, task) {
489
- return enqueueSettingsWrite(pathKey, async () => {
490
- let lastError;
491
- for (let attempt = 0; attempt < SETTINGS_WRITE_MAX_ATTEMPTS; attempt += 1) {
492
- try {
493
- return await task();
494
- }
495
- catch (error) {
496
- lastError = error;
497
- if (!isRetryableSettingsWriteError(error) ||
498
- attempt + 1 >= SETTINGS_WRITE_MAX_ATTEMPTS) {
499
- throw error;
500
- }
501
- await sleep(resolveRetryDelayMs(error, attempt));
502
- }
503
- }
504
- throw lastError instanceof Error
505
- ? lastError
506
- : new Error("settings save retry exhausted");
507
- });
508
- }
509
148
  function copyDashboardSettingValue(target, source, key) {
510
149
  const value = source[key];
511
150
  target[key] = Array.isArray(value)
@@ -527,18 +166,6 @@ function mergeDashboardSettingsForKeys(base, selected, keys) {
527
166
  }
528
167
  return cloneDashboardSettings(next);
529
168
  }
530
- function resolvePluginConfigSavePathKey() {
531
- const envPath = (process.env.CODEX_MULTI_AUTH_CONFIG_PATH ?? "").trim();
532
- return envPath.length > 0 ? envPath : getUnifiedSettingsPath();
533
- }
534
- function formatPersistError(error) {
535
- if (error instanceof Error)
536
- return error.message;
537
- return String(error);
538
- }
539
- function warnPersistFailure(scope, error) {
540
- console.warn(`Settings save failed (${scope}) after retries: ${formatPersistError(error)}`);
541
- }
542
169
  async function persistDashboardSettingsSelection(selected, keys, scope) {
543
170
  const fallback = cloneDashboardSettings(selected);
544
171
  try {
@@ -547,38 +174,19 @@ async function persistDashboardSettingsSelection(selected, keys, scope) {
547
174
  const merged = mergeDashboardSettingsForKeys(latest, selected, keys);
548
175
  await saveDashboardDisplaySettings(merged);
549
176
  return merged;
550
- });
177
+ }, { sleep });
551
178
  }
552
179
  catch (error) {
553
180
  warnPersistFailure(scope, error);
554
181
  return fallback;
555
182
  }
556
183
  }
557
- async function readFileWithRetry(path) {
558
- for (let attempt = 0;; attempt += 1) {
559
- try {
560
- return await fs.readFile(path, "utf-8");
561
- }
562
- catch (error) {
563
- const code = error.code;
564
- if (code === "ENOENT") {
565
- throw error;
566
- }
567
- if (!code ||
568
- !RETRYABLE_SETTINGS_WRITE_CODES.has(code) ||
569
- attempt >= SETTINGS_WRITE_MAX_ATTEMPTS - 1) {
570
- throw error;
571
- }
572
- await sleep(25 * 2 ** attempt);
573
- }
574
- }
575
- }
576
184
  async function persistBackendConfigSelection(selected, scope) {
577
185
  const fallback = cloneBackendPluginConfig(selected);
578
186
  try {
579
187
  await withQueuedRetry(resolvePluginConfigSavePathKey(), async () => {
580
188
  await savePluginConfig(buildBackendConfigPatch(selected));
581
- });
189
+ }, { sleep });
582
190
  return fallback;
583
191
  }
584
192
  catch (error) {
@@ -586,297 +194,27 @@ async function persistBackendConfigSelection(selected, scope) {
586
194
  return fallback;
587
195
  }
588
196
  }
589
- function normalizeStatuslineFields(fields) {
590
- const source = fields ?? DEFAULT_STATUSLINE_FIELDS;
591
- const seen = new Set();
592
- const normalized = [];
593
- for (const field of source) {
594
- if (seen.has(field))
595
- continue;
596
- seen.add(field);
597
- normalized.push(field);
598
- }
599
- if (normalized.length === 0) {
600
- return [...DEFAULT_STATUSLINE_FIELDS];
601
- }
602
- return normalized;
603
- }
604
- function highlightPreviewToken(text, ui) {
605
- if (!output.isTTY)
606
- return text;
607
- if (ui.v2Enabled) {
608
- return `${ui.theme.colors.accent}${ANSI.bold}${text}${ui.theme.colors.reset}`;
609
- }
610
- return `${ANSI.cyan}${ANSI.bold}${text}${ANSI.reset}`;
611
- }
612
- function isLastUsedPreviewFocus(focus) {
613
- return focus === "menuShowLastUsed" || focus === "last-used";
614
- }
615
- function isLimitsPreviewFocus(focus) {
616
- return focus === "menuShowQuotaSummary" || focus === "limits";
617
- }
618
- function isLimitsCooldownPreviewFocus(focus) {
619
- return focus === "menuShowQuotaCooldown";
620
- }
621
- function isStatusPreviewFocus(focus) {
622
- return focus === "menuShowStatusBadge" || focus === "status";
623
- }
624
- function isCurrentBadgePreviewFocus(focus) {
625
- return focus === "menuShowCurrentBadge";
626
- }
627
- function isCurrentRowPreviewFocus(focus) {
628
- return focus === "menuHighlightCurrentRow";
629
- }
630
- function isExpandedRowsPreviewFocus(focus) {
631
- return (focus === "menuShowDetailsForUnselectedRows" || focus === "menuLayoutMode");
632
- }
633
- function buildSummaryPreviewText(settings, ui, focus = null) {
634
- const partsByField = new Map();
635
- if (settings.menuShowLastUsed !== false) {
636
- const part = `last used: ${PREVIEW_LAST_USED}`;
637
- partsByField.set("last-used", isLastUsedPreviewFocus(focus) ? highlightPreviewToken(part, ui) : part);
638
- }
639
- if (settings.menuShowQuotaSummary !== false) {
640
- const limitsText = settings.menuShowQuotaCooldown === false
641
- ? PREVIEW_LIMITS
642
- : `${PREVIEW_LIMITS} | ${PREVIEW_LIMIT_COOLDOWNS}`;
643
- const part = `limits: ${limitsText}`;
644
- partsByField.set("limits", isLimitsPreviewFocus(focus) || isLimitsCooldownPreviewFocus(focus)
645
- ? highlightPreviewToken(part, ui)
646
- : part);
647
- }
648
- if (settings.menuShowStatusBadge === false) {
649
- const part = `status: ${PREVIEW_STATUS}`;
650
- partsByField.set("status", isStatusPreviewFocus(focus) ? highlightPreviewToken(part, ui) : part);
651
- }
652
- const orderedParts = normalizeStatuslineFields(settings.menuStatuslineFields)
653
- .map((field) => partsByField.get(field))
654
- .filter((part) => typeof part === "string" && part.length > 0);
655
- if (orderedParts.length > 0) {
656
- return orderedParts.join(" | ");
657
- }
658
- const showsStatusField = normalizeStatuslineFields(settings.menuStatuslineFields).includes("status");
659
- if (showsStatusField && settings.menuShowStatusBadge !== false) {
660
- const note = "status text appears only when status badges are hidden";
661
- return isStatusPreviewFocus(focus) ? highlightPreviewToken(note, ui) : note;
662
- }
663
- return "no summary text is visible with current account-list settings";
664
- }
665
- function buildAccountListPreview(settings, ui, focus = null) {
666
- const badges = [];
667
- if (settings.menuShowCurrentBadge !== false) {
668
- const currentBadge = "[current]";
669
- badges.push(isCurrentBadgePreviewFocus(focus)
670
- ? highlightPreviewToken(currentBadge, ui)
671
- : currentBadge);
672
- }
673
- if (settings.menuShowStatusBadge !== false) {
674
- const statusBadge = "[active]";
675
- badges.push(isStatusPreviewFocus(focus)
676
- ? highlightPreviewToken(statusBadge, ui)
677
- : statusBadge);
678
- }
679
- const badgeSuffix = badges.length > 0 ? ` ${badges.join(" ")}` : "";
680
- const accountEmail = isCurrentRowPreviewFocus(focus)
681
- ? highlightPreviewToken(PREVIEW_ACCOUNT_EMAIL, ui)
682
- : PREVIEW_ACCOUNT_EMAIL;
683
- const rowDetailMode = resolveMenuLayoutMode(settings) === "expanded-rows"
684
- ? "details shown on all rows"
685
- : "details shown on selected row only";
686
- const detailModeText = isExpandedRowsPreviewFocus(focus)
687
- ? highlightPreviewToken(rowDetailMode, ui)
688
- : rowDetailMode;
689
- return {
690
- label: `1. ${accountEmail}${badgeSuffix}`,
691
- hint: `${buildSummaryPreviewText(settings, ui, focus)}\n${detailModeText}`,
692
- };
693
- }
694
197
  function cloneDashboardSettings(settings) {
695
- const layoutMode = resolveMenuLayoutMode(settings);
696
- return {
697
- showPerAccountRows: settings.showPerAccountRows,
698
- showQuotaDetails: settings.showQuotaDetails,
699
- showForecastReasons: settings.showForecastReasons,
700
- showRecommendations: settings.showRecommendations,
701
- showLiveProbeNotes: settings.showLiveProbeNotes,
702
- actionAutoReturnMs: settings.actionAutoReturnMs ?? 2_000,
703
- actionPauseOnKey: settings.actionPauseOnKey ?? true,
704
- menuAutoFetchLimits: settings.menuAutoFetchLimits ?? true,
705
- menuSortEnabled: settings.menuSortEnabled ??
706
- DEFAULT_DASHBOARD_DISPLAY_SETTINGS.menuSortEnabled ??
707
- true,
708
- menuSortMode: settings.menuSortMode ??
709
- DEFAULT_DASHBOARD_DISPLAY_SETTINGS.menuSortMode ??
710
- "ready-first",
711
- menuSortPinCurrent: settings.menuSortPinCurrent ??
712
- DEFAULT_DASHBOARD_DISPLAY_SETTINGS.menuSortPinCurrent ??
713
- false,
714
- menuSortQuickSwitchVisibleRow: settings.menuSortQuickSwitchVisibleRow ?? true,
715
- uiThemePreset: settings.uiThemePreset ?? "green",
716
- uiAccentColor: settings.uiAccentColor ?? "green",
717
- menuShowStatusBadge: settings.menuShowStatusBadge ?? true,
718
- menuShowCurrentBadge: settings.menuShowCurrentBadge ?? true,
719
- menuShowLastUsed: settings.menuShowLastUsed ?? true,
720
- menuShowQuotaSummary: settings.menuShowQuotaSummary ?? true,
721
- menuShowQuotaCooldown: settings.menuShowQuotaCooldown ?? true,
722
- menuShowFetchStatus: settings.menuShowFetchStatus ?? true,
723
- menuShowDetailsForUnselectedRows: layoutMode === "expanded-rows",
724
- menuLayoutMode: layoutMode,
725
- menuQuotaTtlMs: settings.menuQuotaTtlMs ?? 5 * 60_000,
726
- menuFocusStyle: settings.menuFocusStyle ?? "row-invert",
727
- menuHighlightCurrentRow: settings.menuHighlightCurrentRow ?? true,
728
- menuStatuslineFields: [
729
- ...normalizeStatuslineFields(settings.menuStatuslineFields),
730
- ],
731
- };
198
+ return cloneDashboardSettingsData(settings, {
199
+ resolveMenuLayoutMode,
200
+ normalizeStatuslineFields,
201
+ });
732
202
  }
733
203
  function dashboardSettingsEqual(left, right) {
734
- return (left.showPerAccountRows === right.showPerAccountRows &&
735
- left.showQuotaDetails === right.showQuotaDetails &&
736
- left.showForecastReasons === right.showForecastReasons &&
737
- left.showRecommendations === right.showRecommendations &&
738
- left.showLiveProbeNotes === right.showLiveProbeNotes &&
739
- (left.actionAutoReturnMs ?? 2_000) ===
740
- (right.actionAutoReturnMs ?? 2_000) &&
741
- (left.actionPauseOnKey ?? true) === (right.actionPauseOnKey ?? true) &&
742
- (left.menuAutoFetchLimits ?? true) ===
743
- (right.menuAutoFetchLimits ?? true) &&
744
- (left.menuSortEnabled ??
745
- DEFAULT_DASHBOARD_DISPLAY_SETTINGS.menuSortEnabled ??
746
- true) ===
747
- (right.menuSortEnabled ??
748
- DEFAULT_DASHBOARD_DISPLAY_SETTINGS.menuSortEnabled ??
749
- true) &&
750
- (left.menuSortMode ??
751
- DEFAULT_DASHBOARD_DISPLAY_SETTINGS.menuSortMode ??
752
- "ready-first") ===
753
- (right.menuSortMode ??
754
- DEFAULT_DASHBOARD_DISPLAY_SETTINGS.menuSortMode ??
755
- "ready-first") &&
756
- (left.menuSortPinCurrent ??
757
- DEFAULT_DASHBOARD_DISPLAY_SETTINGS.menuSortPinCurrent ??
758
- false) ===
759
- (right.menuSortPinCurrent ??
760
- DEFAULT_DASHBOARD_DISPLAY_SETTINGS.menuSortPinCurrent ??
761
- false) &&
762
- (left.menuSortQuickSwitchVisibleRow ?? true) ===
763
- (right.menuSortQuickSwitchVisibleRow ?? true) &&
764
- (left.uiThemePreset ?? "green") === (right.uiThemePreset ?? "green") &&
765
- (left.uiAccentColor ?? "green") === (right.uiAccentColor ?? "green") &&
766
- (left.menuShowStatusBadge ?? true) ===
767
- (right.menuShowStatusBadge ?? true) &&
768
- (left.menuShowCurrentBadge ?? true) ===
769
- (right.menuShowCurrentBadge ?? true) &&
770
- (left.menuShowLastUsed ?? true) === (right.menuShowLastUsed ?? true) &&
771
- (left.menuShowQuotaSummary ?? true) ===
772
- (right.menuShowQuotaSummary ?? true) &&
773
- (left.menuShowQuotaCooldown ?? true) ===
774
- (right.menuShowQuotaCooldown ?? true) &&
775
- (left.menuShowFetchStatus ?? true) ===
776
- (right.menuShowFetchStatus ?? true) &&
777
- resolveMenuLayoutMode(left) === resolveMenuLayoutMode(right) &&
778
- (left.menuQuotaTtlMs ?? 5 * 60_000) ===
779
- (right.menuQuotaTtlMs ?? 5 * 60_000) &&
780
- (left.menuFocusStyle ?? "row-invert") ===
781
- (right.menuFocusStyle ?? "row-invert") &&
782
- (left.menuHighlightCurrentRow ?? true) ===
783
- (right.menuHighlightCurrentRow ?? true) &&
784
- JSON.stringify(normalizeStatuslineFields(left.menuStatuslineFields)) ===
785
- JSON.stringify(normalizeStatuslineFields(right.menuStatuslineFields)));
786
- }
787
- function cloneBackendPluginConfig(config) {
788
- const fallbackChain = config.unsupportedCodexFallbackChain;
789
- return {
790
- ...BACKEND_DEFAULTS,
791
- ...config,
792
- unsupportedCodexFallbackChain: fallbackChain && typeof fallbackChain === "object"
793
- ? { ...fallbackChain }
794
- : {},
795
- };
796
- }
797
- function backendSettingsSnapshot(config) {
798
- const snapshot = {};
799
- for (const option of BACKEND_TOGGLE_OPTIONS) {
800
- snapshot[option.key] =
801
- config[option.key] ?? BACKEND_DEFAULTS[option.key] ?? false;
802
- }
803
- for (const option of BACKEND_NUMBER_OPTIONS) {
804
- snapshot[option.key] =
805
- config[option.key] ?? BACKEND_DEFAULTS[option.key] ?? option.min;
806
- }
807
- return snapshot;
204
+ return dashboardSettingsDataEqual(left, right, {
205
+ resolveMenuLayoutMode,
206
+ normalizeStatuslineFields,
207
+ });
808
208
  }
809
- function backendSettingsEqual(left, right) {
810
- return (JSON.stringify(backendSettingsSnapshot(left)) ===
811
- JSON.stringify(backendSettingsSnapshot(right)));
209
+ function buildSummaryPreviewText(settings, ui, focus = null) {
210
+ return buildSummaryPreviewTextBase(settings, ui, resolveMenuLayoutMode, focus);
812
211
  }
813
- function formatBackendNumberValue(option, value) {
814
- if (option.unit === "percent")
815
- return `${Math.round(value)}%`;
816
- if (option.unit === "count")
817
- return `${Math.round(value)}`;
818
- if (value >= 60_000 && value % 60_000 === 0) {
819
- return `${Math.round(value / 60_000)}m`;
820
- }
821
- if (value >= 1_000 && value % 1_000 === 0) {
822
- return `${Math.round(value / 1_000)}s`;
823
- }
824
- return `${Math.round(value)}ms`;
212
+ function buildAccountListPreview(settings, ui, focus = null) {
213
+ return buildAccountListPreviewBase(settings, ui, resolveMenuLayoutMode, focus);
825
214
  }
826
215
  function clampBackendNumber(option, value) {
827
216
  return Math.max(option.min, Math.min(option.max, Math.round(value)));
828
217
  }
829
- function buildBackendSettingsPreview(config, ui, focus = null) {
830
- const liveSync = config.liveAccountSync ?? BACKEND_DEFAULTS.liveAccountSync ?? true;
831
- const affinity = config.sessionAffinity ?? BACKEND_DEFAULTS.sessionAffinity ?? true;
832
- const preemptive = config.preemptiveQuotaEnabled ??
833
- BACKEND_DEFAULTS.preemptiveQuotaEnabled ??
834
- true;
835
- const threshold5h = config.preemptiveQuotaRemainingPercent5h ??
836
- BACKEND_DEFAULTS.preemptiveQuotaRemainingPercent5h ??
837
- 5;
838
- const threshold7d = config.preemptiveQuotaRemainingPercent7d ??
839
- BACKEND_DEFAULTS.preemptiveQuotaRemainingPercent7d ??
840
- 5;
841
- const fetchTimeout = config.fetchTimeoutMs ?? BACKEND_DEFAULTS.fetchTimeoutMs ?? 60_000;
842
- const stallTimeout = config.streamStallTimeoutMs ??
843
- BACKEND_DEFAULTS.streamStallTimeoutMs ??
844
- 45_000;
845
- const fetchTimeoutOption = BACKEND_NUMBER_OPTION_BY_KEY.get("fetchTimeoutMs");
846
- const stallTimeoutOption = BACKEND_NUMBER_OPTION_BY_KEY.get("streamStallTimeoutMs");
847
- const highlightIfFocused = (key, text) => {
848
- if (focus !== key)
849
- return text;
850
- return highlightPreviewToken(text, ui);
851
- };
852
- const label = [
853
- `live sync ${highlightIfFocused("liveAccountSync", liveSync ? "on" : "off")}`,
854
- `affinity ${highlightIfFocused("sessionAffinity", affinity ? "on" : "off")}`,
855
- `preemptive ${highlightIfFocused("preemptiveQuotaEnabled", preemptive ? "on" : "off")}`,
856
- ].join(" | ");
857
- const hint = [
858
- `thresholds 5h<=${highlightIfFocused("preemptiveQuotaRemainingPercent5h", `${threshold5h}%`)}`,
859
- `7d<=${highlightIfFocused("preemptiveQuotaRemainingPercent7d", `${threshold7d}%`)}`,
860
- `timeouts ${highlightIfFocused("fetchTimeoutMs", fetchTimeoutOption ? formatBackendNumberValue(fetchTimeoutOption, fetchTimeout) : `${fetchTimeout}ms`)}/${highlightIfFocused("streamStallTimeoutMs", stallTimeoutOption ? formatBackendNumberValue(stallTimeoutOption, stallTimeout) : `${stallTimeout}ms`)}`,
861
- ].join(" | ");
862
- return { label, hint };
863
- }
864
- function buildBackendConfigPatch(config) {
865
- const patch = {};
866
- for (const option of BACKEND_TOGGLE_OPTIONS) {
867
- const value = config[option.key];
868
- if (typeof value === "boolean") {
869
- patch[option.key] = value;
870
- }
871
- }
872
- for (const option of BACKEND_NUMBER_OPTIONS) {
873
- const value = config[option.key];
874
- if (typeof value === "number" && Number.isFinite(value)) {
875
- patch[option.key] = clampBackendNumber(option, value);
876
- }
877
- }
878
- return patch;
879
- }
880
218
  function applyUiThemeFromDashboardSettings(settings) {
881
219
  const current = getUiRuntimeOptions();
882
220
  setUiRuntimeOptions({
@@ -887,12 +225,6 @@ function applyUiThemeFromDashboardSettings(settings) {
887
225
  accent: settings.uiAccentColor ?? "green",
888
226
  });
889
227
  }
890
- function formatDashboardSettingState(value) {
891
- return value ? "[x]" : "[ ]";
892
- }
893
- function formatMenuSortMode(mode) {
894
- return mode === "ready-first" ? "Ready-First" : "Manual";
895
- }
896
228
  function resolveMenuLayoutMode(settings) {
897
229
  if (settings.menuLayoutMode === "expanded-rows") {
898
230
  return "expanded-rows";
@@ -904,27 +236,8 @@ function resolveMenuLayoutMode(settings) {
904
236
  ? "expanded-rows"
905
237
  : "compact-details";
906
238
  }
907
- function formatMenuLayoutMode(mode) {
908
- return mode === "expanded-rows" ? "Expanded Rows" : "Compact + Details Pane";
909
- }
910
- function formatMenuQuotaTtl(ttlMs) {
911
- if (ttlMs >= 60_000 && ttlMs % 60_000 === 0) {
912
- return `${Math.round(ttlMs / 60_000)}m`;
913
- }
914
- if (ttlMs >= 1_000 && ttlMs % 1_000 === 0) {
915
- return `${Math.round(ttlMs / 1_000)}s`;
916
- }
917
- return `${ttlMs}ms`;
918
- }
919
- function clampBackendNumberForTests(settingKey, value) {
920
- const option = BACKEND_NUMBER_OPTION_BY_KEY.get(settingKey);
921
- if (!option) {
922
- throw new Error(`Unknown backend numeric setting key: ${settingKey}`);
923
- }
924
- return clampBackendNumber(option, value);
925
- }
926
239
  async function withQueuedRetryForTests(pathKey, task) {
927
- return withQueuedRetry(pathKey, task);
240
+ return withQueuedRetry(pathKey, task, { sleep });
928
241
  }
929
242
  async function persistDashboardSettingsSelectionForTests(selected, keys, scope) {
930
243
  return persistDashboardSettingsSelection(selected, keys, scope);
@@ -946,7 +259,7 @@ const __testOnly = {
946
259
  buildAccountListPreview,
947
260
  buildSummaryPreviewText,
948
261
  normalizeStatuslineFields,
949
- reorderField,
262
+ reorderField: reorderStatuslineField,
950
263
  promptDashboardDisplaySettings,
951
264
  promptStatuslineSettings,
952
265
  promptBehaviorSettings,
@@ -955,1470 +268,249 @@ const __testOnly = {
955
268
  };
956
269
  /* c8 ignore start - interactive prompt flows are covered by integration tests */
957
270
  async function promptDashboardDisplaySettings(initial) {
958
- if (!input.isTTY || !output.isTTY) {
959
- return null;
960
- }
961
- const ui = getUiRuntimeOptions();
962
- let draft = cloneDashboardSettings(initial);
963
- let focusKey = DASHBOARD_DISPLAY_OPTIONS[0]?.key ?? "menuShowStatusBadge";
964
- while (true) {
965
- const preview = buildAccountListPreview(draft, ui, focusKey);
966
- const optionItems = DASHBOARD_DISPLAY_OPTIONS.map((option, index) => {
967
- const enabled = draft[option.key] ?? true;
968
- const label = `${formatDashboardSettingState(enabled)} ${index + 1}. ${option.label}`;
969
- const color = enabled
970
- ? "green"
971
- : "yellow";
972
- return {
973
- label,
974
- hint: option.description,
975
- value: { type: "toggle", key: option.key },
976
- color,
977
- };
978
- });
979
- const sortMode = draft.menuSortMode ??
980
- DEFAULT_DASHBOARD_DISPLAY_SETTINGS.menuSortMode ??
981
- "ready-first";
982
- const sortModeItem = {
983
- label: `Sort mode: ${formatMenuSortMode(sortMode)}`,
984
- hint: "Applies when smart sort is enabled.",
985
- value: { type: "cycle-sort-mode" },
986
- color: sortMode === "ready-first" ? "green" : "yellow",
987
- };
988
- const layoutMode = resolveMenuLayoutMode(draft);
989
- const layoutModeItem = {
990
- label: `Layout: ${formatMenuLayoutMode(layoutMode)}`,
991
- hint: "Compact shows one-line rows with a selected details pane.",
992
- value: { type: "cycle-layout-mode" },
993
- color: layoutMode === "compact-details" ? "green" : "yellow",
994
- };
995
- const items = [
996
- {
997
- label: UI_COPY.settings.previewHeading,
998
- value: { type: "cancel" },
999
- kind: "heading",
1000
- },
1001
- {
1002
- label: preview.label,
1003
- hint: preview.hint,
1004
- value: { type: "cancel" },
1005
- color: "green",
1006
- disabled: true,
1007
- hideUnavailableSuffix: true,
1008
- },
1009
- { label: "", value: { type: "cancel" }, separator: true },
1010
- {
1011
- label: UI_COPY.settings.displayHeading,
1012
- value: { type: "cancel" },
1013
- kind: "heading",
1014
- },
1015
- ...optionItems,
1016
- sortModeItem,
1017
- layoutModeItem,
1018
- { label: "", value: { type: "cancel" }, separator: true },
1019
- {
1020
- label: UI_COPY.settings.resetDefault,
1021
- value: { type: "reset" },
1022
- color: "yellow",
1023
- },
1024
- {
1025
- label: UI_COPY.settings.saveAndBack,
1026
- value: { type: "save" },
1027
- color: "green",
1028
- },
1029
- {
1030
- label: UI_COPY.settings.backNoSave,
1031
- value: { type: "cancel" },
1032
- color: "red",
1033
- },
1034
- ];
1035
- const initialCursor = items.findIndex((item) => (item.value.type === "toggle" && item.value.key === focusKey) ||
1036
- (item.value.type === "cycle-sort-mode" &&
1037
- focusKey === "menuSortMode") ||
1038
- (item.value.type === "cycle-layout-mode" &&
1039
- focusKey === "menuLayoutMode"));
1040
- const updateFocusedPreview = (cursor) => {
1041
- const focusedItem = items[cursor];
1042
- const focusedKey = focusedItem?.value.type === "toggle"
1043
- ? focusedItem.value.key
1044
- : focusedItem?.value.type === "cycle-sort-mode"
1045
- ? "menuSortMode"
1046
- : focusedItem?.value.type === "cycle-layout-mode"
1047
- ? "menuLayoutMode"
1048
- : focusKey;
1049
- const nextPreview = buildAccountListPreview(draft, ui, focusedKey);
1050
- const previewItem = items[1];
1051
- if (!previewItem)
1052
- return;
1053
- previewItem.label = nextPreview.label;
1054
- previewItem.hint = nextPreview.hint;
1055
- };
1056
- const result = await select(items, {
1057
- message: UI_COPY.settings.accountListTitle,
1058
- subtitle: UI_COPY.settings.accountListSubtitle,
1059
- help: UI_COPY.settings.accountListHelp,
1060
- clearScreen: true,
1061
- theme: ui.theme,
1062
- selectedEmphasis: "minimal",
1063
- initialCursor: initialCursor >= 0 ? initialCursor : undefined,
1064
- onCursorChange: ({ cursor }) => {
1065
- const focusedItem = items[cursor];
1066
- if (focusedItem?.value.type === "toggle") {
1067
- focusKey = focusedItem.value.key;
1068
- }
1069
- else if (focusedItem?.value.type === "cycle-sort-mode") {
1070
- focusKey = "menuSortMode";
1071
- }
1072
- else if (focusedItem?.value.type === "cycle-layout-mode") {
1073
- focusKey = "menuLayoutMode";
1074
- }
1075
- updateFocusedPreview(cursor);
1076
- },
1077
- onInput: (raw) => {
1078
- const lower = raw.toLowerCase();
1079
- if (lower === "q")
1080
- return { type: "cancel" };
1081
- if (lower === "s")
1082
- return { type: "save" };
1083
- if (lower === "r")
1084
- return { type: "reset" };
1085
- if (lower === "m")
1086
- return { type: "cycle-sort-mode" };
1087
- if (lower === "l")
1088
- return { type: "cycle-layout-mode" };
1089
- const parsed = Number.parseInt(raw, 10);
1090
- if (Number.isFinite(parsed) &&
1091
- parsed >= 1 &&
1092
- parsed <= DASHBOARD_DISPLAY_OPTIONS.length) {
1093
- const target = DASHBOARD_DISPLAY_OPTIONS[parsed - 1];
1094
- if (target) {
1095
- return { type: "toggle", key: target.key };
1096
- }
1097
- }
1098
- if (parsed === DASHBOARD_DISPLAY_OPTIONS.length + 1) {
1099
- return { type: "cycle-sort-mode" };
1100
- }
1101
- if (parsed === DASHBOARD_DISPLAY_OPTIONS.length + 2) {
1102
- return { type: "cycle-layout-mode" };
1103
- }
1104
- return undefined;
1105
- },
1106
- });
1107
- if (!result || result.type === "cancel") {
1108
- return null;
1109
- }
1110
- if (result.type === "save") {
1111
- return draft;
1112
- }
1113
- if (result.type === "reset") {
1114
- draft = applyDashboardDefaultsForKeys(draft, ACCOUNT_LIST_PANEL_KEYS);
1115
- focusKey = DASHBOARD_DISPLAY_OPTIONS[0]?.key ?? focusKey;
1116
- continue;
1117
- }
1118
- if (result.type === "cycle-sort-mode") {
1119
- const currentMode = draft.menuSortMode ??
1120
- DEFAULT_DASHBOARD_DISPLAY_SETTINGS.menuSortMode ??
1121
- "ready-first";
1122
- const nextMode = currentMode === "ready-first" ? "manual" : "ready-first";
1123
- draft = {
1124
- ...draft,
1125
- menuSortMode: nextMode,
1126
- menuSortEnabled: nextMode === "ready-first"
1127
- ? true
1128
- : (draft.menuSortEnabled ??
1129
- DEFAULT_DASHBOARD_DISPLAY_SETTINGS.menuSortEnabled ??
1130
- true),
1131
- };
1132
- focusKey = "menuSortMode";
1133
- continue;
1134
- }
1135
- if (result.type === "cycle-layout-mode") {
1136
- const currentLayout = resolveMenuLayoutMode(draft);
1137
- const nextLayout = currentLayout === "compact-details"
1138
- ? "expanded-rows"
1139
- : "compact-details";
1140
- draft = {
1141
- ...draft,
1142
- menuLayoutMode: nextLayout,
1143
- menuShowDetailsForUnselectedRows: nextLayout === "expanded-rows",
1144
- };
1145
- focusKey = "menuLayoutMode";
1146
- continue;
1147
- }
1148
- focusKey = result.key;
1149
- draft = {
1150
- ...draft,
1151
- [result.key]: !draft[result.key],
1152
- };
1153
- }
271
+ return promptDashboardDisplaySettingsPanelEntry({
272
+ initial,
273
+ promptDashboardDisplayPanel,
274
+ cloneDashboardSettings,
275
+ buildAccountListPreview,
276
+ formatDashboardSettingState,
277
+ formatMenuSortMode,
278
+ resolveMenuLayoutMode: (settings = DEFAULT_DASHBOARD_DISPLAY_SETTINGS) => resolveMenuLayoutMode(settings),
279
+ formatMenuLayoutMode,
280
+ applyDashboardDefaultsForKeys,
281
+ DASHBOARD_DISPLAY_OPTIONS,
282
+ ACCOUNT_LIST_PANEL_KEYS,
283
+ UI_COPY,
284
+ });
1154
285
  }
1155
286
  async function configureDashboardDisplaySettings(currentSettings) {
1156
- const current = currentSettings ?? (await loadDashboardDisplaySettings());
1157
- if (!input.isTTY || !output.isTTY) {
1158
- console.log("Settings require interactive mode.");
1159
- console.log(`Settings file: ${getDashboardSettingsPath()}`);
1160
- return current;
1161
- }
1162
- const selected = await promptDashboardDisplaySettings(current);
1163
- if (!selected)
1164
- return current;
1165
- if (dashboardSettingsEqual(current, selected))
1166
- return current;
1167
- const merged = await persistDashboardSettingsSelection(selected, ACCOUNT_LIST_PANEL_KEYS, "account-list");
1168
- applyUiThemeFromDashboardSettings(merged);
1169
- return merged;
1170
- }
1171
- function reorderField(fields, key, direction) {
1172
- const index = fields.indexOf(key);
1173
- if (index < 0)
1174
- return fields;
1175
- const target = index + direction;
1176
- if (target < 0 || target >= fields.length)
1177
- return fields;
1178
- const next = [...fields];
1179
- const current = next[index];
1180
- const swap = next[target];
1181
- if (!current || !swap)
1182
- return fields;
1183
- next[index] = swap;
1184
- next[target] = current;
1185
- return next;
287
+ return configureDashboardSettingsEntry(currentSettings, {
288
+ configureDashboardSettingsController,
289
+ loadDashboardDisplaySettings,
290
+ promptSettings: promptDashboardDisplaySettings,
291
+ settingsEqual: dashboardSettingsEqual,
292
+ persistSelection: (selected) => persistDashboardSettingsSelection(selected, ACCOUNT_LIST_PANEL_KEYS, "account-list"),
293
+ applyUiThemeFromDashboardSettings,
294
+ isInteractive: () => input.isTTY && output.isTTY,
295
+ getDashboardSettingsPath,
296
+ writeLine: (message) => {
297
+ console.log(message);
298
+ },
299
+ });
1186
300
  }
1187
301
  async function promptStatuslineSettings(initial) {
1188
- if (!input.isTTY || !output.isTTY) {
1189
- return null;
1190
- }
1191
- const ui = getUiRuntimeOptions();
1192
- let draft = cloneDashboardSettings(initial);
1193
- let focusKey = draft.menuStatuslineFields?.[0] ?? "last-used";
1194
- while (true) {
1195
- const preview = buildAccountListPreview(draft, ui, focusKey);
1196
- const selectedSet = new Set(normalizeStatuslineFields(draft.menuStatuslineFields));
1197
- const ordered = normalizeStatuslineFields(draft.menuStatuslineFields);
1198
- const orderMap = new Map();
1199
- for (let index = 0; index < ordered.length; index += 1) {
1200
- const key = ordered[index];
1201
- if (key)
1202
- orderMap.set(key, index + 1);
1203
- }
1204
- const optionItems = STATUSLINE_FIELD_OPTIONS.map((option, index) => {
1205
- const enabled = selectedSet.has(option.key);
1206
- const rank = orderMap.get(option.key);
1207
- const label = `${formatDashboardSettingState(enabled)} ${index + 1}. ${option.label}${rank ? ` (order ${rank})` : ""}`;
1208
- return {
1209
- label,
1210
- hint: option.description,
1211
- value: { type: "toggle", key: option.key },
1212
- color: enabled ? "green" : "yellow",
1213
- };
1214
- });
1215
- const items = [
1216
- {
1217
- label: UI_COPY.settings.previewHeading,
1218
- value: { type: "cancel" },
1219
- kind: "heading",
1220
- },
1221
- {
1222
- label: preview.label,
1223
- hint: preview.hint,
1224
- value: { type: "cancel" },
1225
- color: "green",
1226
- disabled: true,
1227
- hideUnavailableSuffix: true,
1228
- },
1229
- { label: "", value: { type: "cancel" }, separator: true },
1230
- {
1231
- label: UI_COPY.settings.displayHeading,
1232
- value: { type: "cancel" },
1233
- kind: "heading",
1234
- },
1235
- ...optionItems,
1236
- { label: "", value: { type: "cancel" }, separator: true },
1237
- {
1238
- label: UI_COPY.settings.moveUp,
1239
- value: { type: "move-up", key: focusKey },
1240
- color: "green",
1241
- },
1242
- {
1243
- label: UI_COPY.settings.moveDown,
1244
- value: { type: "move-down", key: focusKey },
1245
- color: "green",
1246
- },
1247
- { label: "", value: { type: "cancel" }, separator: true },
1248
- {
1249
- label: UI_COPY.settings.resetDefault,
1250
- value: { type: "reset" },
1251
- color: "yellow",
1252
- },
1253
- {
1254
- label: UI_COPY.settings.saveAndBack,
1255
- value: { type: "save" },
1256
- color: "green",
1257
- },
1258
- {
1259
- label: UI_COPY.settings.backNoSave,
1260
- value: { type: "cancel" },
1261
- color: "red",
1262
- },
1263
- ];
1264
- const initialCursor = items.findIndex((item) => item.value.type === "toggle" && item.value.key === focusKey);
1265
- const updateFocusedPreview = (cursor) => {
1266
- const focusedItem = items[cursor];
1267
- const focusedKey = focusedItem?.value.type === "toggle" ? focusedItem.value.key : focusKey;
1268
- const nextPreview = buildAccountListPreview(draft, ui, focusedKey);
1269
- const previewItem = items[1];
1270
- if (!previewItem)
1271
- return;
1272
- previewItem.label = nextPreview.label;
1273
- previewItem.hint = nextPreview.hint;
1274
- };
1275
- const result = await select(items, {
1276
- message: UI_COPY.settings.summaryTitle,
1277
- subtitle: UI_COPY.settings.summarySubtitle,
1278
- help: UI_COPY.settings.summaryHelp,
1279
- clearScreen: true,
1280
- theme: ui.theme,
1281
- selectedEmphasis: "minimal",
1282
- initialCursor: initialCursor >= 0 ? initialCursor : undefined,
1283
- onCursorChange: ({ cursor }) => {
1284
- const focusedItem = items[cursor];
1285
- if (focusedItem?.value.type === "toggle") {
1286
- focusKey = focusedItem.value.key;
1287
- }
1288
- updateFocusedPreview(cursor);
1289
- },
1290
- onInput: (raw) => {
1291
- const lower = raw.toLowerCase();
1292
- if (lower === "q")
1293
- return { type: "cancel" };
1294
- if (lower === "s")
1295
- return { type: "save" };
1296
- if (lower === "r")
1297
- return { type: "reset" };
1298
- if (lower === "[")
1299
- return { type: "move-up", key: focusKey };
1300
- if (lower === "]")
1301
- return { type: "move-down", key: focusKey };
1302
- const parsed = Number.parseInt(raw, 10);
1303
- if (Number.isFinite(parsed) &&
1304
- parsed >= 1 &&
1305
- parsed <= STATUSLINE_FIELD_OPTIONS.length) {
1306
- const target = STATUSLINE_FIELD_OPTIONS[parsed - 1];
1307
- if (target) {
1308
- return { type: "toggle", key: target.key };
1309
- }
1310
- }
1311
- return undefined;
1312
- },
1313
- });
1314
- if (!result || result.type === "cancel") {
1315
- return null;
1316
- }
1317
- if (result.type === "save") {
1318
- return draft;
1319
- }
1320
- if (result.type === "reset") {
1321
- draft = applyDashboardDefaultsForKeys(draft, STATUSLINE_PANEL_KEYS);
1322
- focusKey = draft.menuStatuslineFields?.[0] ?? "last-used";
1323
- continue;
1324
- }
1325
- if (result.type === "move-up") {
1326
- draft = {
1327
- ...draft,
1328
- menuStatuslineFields: reorderField(normalizeStatuslineFields(draft.menuStatuslineFields), result.key, -1),
1329
- };
1330
- focusKey = result.key;
1331
- continue;
1332
- }
1333
- if (result.type === "move-down") {
1334
- draft = {
1335
- ...draft,
1336
- menuStatuslineFields: reorderField(normalizeStatuslineFields(draft.menuStatuslineFields), result.key, 1),
1337
- };
1338
- focusKey = result.key;
1339
- continue;
1340
- }
1341
- focusKey = result.key;
1342
- const fields = normalizeStatuslineFields(draft.menuStatuslineFields);
1343
- const isEnabled = fields.includes(result.key);
1344
- if (isEnabled) {
1345
- const next = fields.filter((field) => field !== result.key);
1346
- draft = {
1347
- ...draft,
1348
- menuStatuslineFields: next.length > 0 ? next : [result.key],
1349
- };
1350
- }
1351
- else {
1352
- draft = {
1353
- ...draft,
1354
- menuStatuslineFields: [...fields, result.key],
1355
- };
1356
- }
1357
- }
302
+ return promptStatuslineSettingsPanelEntry({
303
+ initial,
304
+ promptStatuslineSettingsPanel,
305
+ cloneDashboardSettings,
306
+ buildAccountListPreview,
307
+ normalizeStatuslineFields,
308
+ formatDashboardSettingState,
309
+ applyDashboardDefaultsForKeys,
310
+ STATUSLINE_FIELD_OPTIONS,
311
+ STATUSLINE_PANEL_KEYS,
312
+ UI_COPY,
313
+ });
1358
314
  }
1359
315
  async function configureStatuslineSettings(currentSettings) {
1360
- const current = currentSettings ?? (await loadDashboardDisplaySettings());
1361
- if (!input.isTTY || !output.isTTY) {
1362
- console.log("Settings require interactive mode.");
1363
- console.log(`Settings file: ${getDashboardSettingsPath()}`);
1364
- return current;
1365
- }
1366
- const selected = await promptStatuslineSettings(current);
1367
- if (!selected)
1368
- return current;
1369
- if (dashboardSettingsEqual(current, selected))
1370
- return current;
1371
- const merged = await persistDashboardSettingsSelection(selected, STATUSLINE_PANEL_KEYS, "summary-fields");
1372
- applyUiThemeFromDashboardSettings(merged);
1373
- return merged;
1374
- }
1375
- function formatDelayLabel(delayMs) {
1376
- return delayMs <= 0
1377
- ? "Instant return"
1378
- : `${Math.round(delayMs / 1000)}s auto-return`;
316
+ return configureDashboardSettingsEntry(currentSettings, {
317
+ configureDashboardSettingsController,
318
+ loadDashboardDisplaySettings,
319
+ promptSettings: promptStatuslineSettings,
320
+ settingsEqual: dashboardSettingsEqual,
321
+ persistSelection: (selected) => persistDashboardSettingsSelection(selected, STATUSLINE_PANEL_KEYS, "summary-fields"),
322
+ applyUiThemeFromDashboardSettings,
323
+ isInteractive: () => input.isTTY && output.isTTY,
324
+ getDashboardSettingsPath,
325
+ writeLine: (message) => {
326
+ console.log(message);
327
+ },
328
+ });
1379
329
  }
1380
330
  async function promptBehaviorSettings(initial) {
1381
- if (!input.isTTY || !output.isTTY)
1382
- return null;
1383
- const ui = getUiRuntimeOptions();
1384
- let draft = cloneDashboardSettings(initial);
1385
- let focus = {
1386
- type: "set-delay",
1387
- delayMs: draft.actionAutoReturnMs ?? 2_000,
1388
- };
1389
- while (true) {
1390
- const currentDelay = draft.actionAutoReturnMs ?? 2_000;
1391
- const pauseOnKey = draft.actionPauseOnKey ?? true;
1392
- const autoFetchLimits = draft.menuAutoFetchLimits ?? true;
1393
- const fetchStatusVisible = draft.menuShowFetchStatus ?? true;
1394
- const menuQuotaTtlMs = draft.menuQuotaTtlMs ?? 5 * 60_000;
1395
- const delayItems = AUTO_RETURN_OPTIONS_MS.map((delayMs) => {
1396
- const color = currentDelay === delayMs ? "green" : "yellow";
1397
- return {
1398
- label: `${currentDelay === delayMs ? "[x]" : "[ ]"} ${formatDelayLabel(delayMs)}`,
1399
- hint: delayMs === 1_000
1400
- ? "Fastest loop for frequent actions."
1401
- : delayMs === 2_000
1402
- ? "Balanced default for most users."
1403
- : "More time to read action output.",
1404
- value: { type: "set-delay", delayMs },
1405
- color,
1406
- };
1407
- });
1408
- const pauseColor = pauseOnKey
1409
- ? "green"
1410
- : "yellow";
1411
- const items = [
1412
- {
1413
- label: UI_COPY.settings.actionTiming,
1414
- value: { type: "cancel" },
1415
- kind: "heading",
1416
- },
1417
- ...delayItems,
1418
- { label: "", value: { type: "cancel" }, separator: true },
1419
- {
1420
- label: `${pauseOnKey ? "[x]" : "[ ]"} Pause on key press`,
1421
- hint: "Press any key to stop auto-return.",
1422
- value: { type: "toggle-pause" },
1423
- color: pauseColor,
1424
- },
1425
- {
1426
- label: `${autoFetchLimits ? "[x]" : "[ ]"} Auto-fetch limits on menu open (5m cache)`,
1427
- hint: "Refreshes account limits automatically when opening the menu.",
1428
- value: { type: "toggle-menu-limit-fetch" },
1429
- color: autoFetchLimits ? "green" : "yellow",
1430
- },
1431
- {
1432
- label: `${fetchStatusVisible ? "[x]" : "[ ]"} Show limit refresh status`,
1433
- hint: "Shows background fetch progress like [2/7] in menu subtitle.",
1434
- value: { type: "toggle-menu-fetch-status" },
1435
- color: fetchStatusVisible ? "green" : "yellow",
1436
- },
1437
- {
1438
- label: `Limit cache TTL: ${formatMenuQuotaTtl(menuQuotaTtlMs)}`,
1439
- hint: "How fresh cached quota data must be before refresh runs.",
1440
- value: { type: "set-menu-quota-ttl", ttlMs: menuQuotaTtlMs },
1441
- color: "yellow",
1442
- },
1443
- { label: "", value: { type: "cancel" }, separator: true },
1444
- {
1445
- label: UI_COPY.settings.resetDefault,
1446
- value: { type: "reset" },
1447
- color: "yellow",
1448
- },
1449
- {
1450
- label: UI_COPY.settings.saveAndBack,
1451
- value: { type: "save" },
1452
- color: "green",
1453
- },
1454
- {
1455
- label: UI_COPY.settings.backNoSave,
1456
- value: { type: "cancel" },
1457
- color: "red",
1458
- },
1459
- ];
1460
- const initialCursor = items.findIndex((item) => {
1461
- const value = item.value;
1462
- if (value.type !== focus.type)
1463
- return false;
1464
- if (value.type === "set-delay" && focus.type === "set-delay") {
1465
- return value.delayMs === focus.delayMs;
1466
- }
1467
- return true;
1468
- });
1469
- const result = await select(items, {
1470
- message: UI_COPY.settings.behaviorTitle,
1471
- subtitle: UI_COPY.settings.behaviorSubtitle,
1472
- help: UI_COPY.settings.behaviorHelp,
1473
- clearScreen: true,
1474
- theme: ui.theme,
1475
- selectedEmphasis: "minimal",
1476
- initialCursor: initialCursor >= 0 ? initialCursor : undefined,
1477
- onCursorChange: ({ cursor }) => {
1478
- const item = items[cursor];
1479
- if (item && !item.separator && item.kind !== "heading") {
1480
- focus = item.value;
1481
- }
1482
- },
1483
- onInput: (raw) => {
1484
- const lower = raw.toLowerCase();
1485
- if (lower === "q")
1486
- return { type: "cancel" };
1487
- if (lower === "s")
1488
- return { type: "save" };
1489
- if (lower === "r")
1490
- return { type: "reset" };
1491
- if (lower === "p")
1492
- return { type: "toggle-pause" };
1493
- if (lower === "l")
1494
- return { type: "toggle-menu-limit-fetch" };
1495
- if (lower === "f")
1496
- return { type: "toggle-menu-fetch-status" };
1497
- if (lower === "t")
1498
- return { type: "set-menu-quota-ttl", ttlMs: menuQuotaTtlMs };
1499
- const parsed = Number.parseInt(raw, 10);
1500
- if (Number.isFinite(parsed) &&
1501
- parsed >= 1 &&
1502
- parsed <= AUTO_RETURN_OPTIONS_MS.length) {
1503
- const delayMs = AUTO_RETURN_OPTIONS_MS[parsed - 1];
1504
- if (typeof delayMs === "number")
1505
- return { type: "set-delay", delayMs };
1506
- }
1507
- return undefined;
1508
- },
1509
- });
1510
- if (!result || result.type === "cancel")
1511
- return null;
1512
- if (result.type === "save")
1513
- return draft;
1514
- if (result.type === "reset") {
1515
- draft = applyDashboardDefaultsForKeys(draft, BEHAVIOR_PANEL_KEYS);
1516
- focus = { type: "set-delay", delayMs: draft.actionAutoReturnMs ?? 2_000 };
1517
- continue;
1518
- }
1519
- if (result.type === "toggle-pause") {
1520
- draft = {
1521
- ...draft,
1522
- actionPauseOnKey: !(draft.actionPauseOnKey ?? true),
1523
- };
1524
- focus = result;
1525
- continue;
1526
- }
1527
- if (result.type === "toggle-menu-limit-fetch") {
1528
- draft = {
1529
- ...draft,
1530
- menuAutoFetchLimits: !(draft.menuAutoFetchLimits ?? true),
1531
- };
1532
- focus = result;
1533
- continue;
1534
- }
1535
- if (result.type === "toggle-menu-fetch-status") {
1536
- draft = {
1537
- ...draft,
1538
- menuShowFetchStatus: !(draft.menuShowFetchStatus ?? true),
1539
- };
1540
- focus = result;
1541
- continue;
1542
- }
1543
- if (result.type === "set-menu-quota-ttl") {
1544
- const currentIndex = MENU_QUOTA_TTL_OPTIONS_MS.findIndex((value) => value === menuQuotaTtlMs);
1545
- const nextIndex = currentIndex < 0
1546
- ? 0
1547
- : (currentIndex + 1) % MENU_QUOTA_TTL_OPTIONS_MS.length;
1548
- const nextTtl = MENU_QUOTA_TTL_OPTIONS_MS[nextIndex] ??
1549
- MENU_QUOTA_TTL_OPTIONS_MS[0] ??
1550
- menuQuotaTtlMs;
1551
- draft = {
1552
- ...draft,
1553
- menuQuotaTtlMs: nextTtl,
1554
- };
1555
- focus = { type: "set-menu-quota-ttl", ttlMs: nextTtl };
1556
- continue;
1557
- }
1558
- draft = {
1559
- ...draft,
1560
- actionAutoReturnMs: result.delayMs,
1561
- };
1562
- focus = result;
1563
- }
331
+ return promptBehaviorSettingsPanelEntry({
332
+ initial,
333
+ promptBehaviorSettingsPanel,
334
+ cloneDashboardSettings,
335
+ applyDashboardDefaultsForKeys,
336
+ formatMenuQuotaTtl,
337
+ AUTO_RETURN_OPTIONS_MS,
338
+ MENU_QUOTA_TTL_OPTIONS_MS,
339
+ BEHAVIOR_PANEL_KEYS,
340
+ UI_COPY,
341
+ });
1564
342
  }
1565
343
  async function promptThemeSettings(initial) {
1566
- if (!input.isTTY || !output.isTTY)
1567
- return null;
1568
- const baseline = cloneDashboardSettings(initial);
1569
- let draft = cloneDashboardSettings(initial);
1570
- let focus = {
1571
- type: "set-palette",
1572
- palette: draft.uiThemePreset ?? "green",
1573
- };
1574
- while (true) {
1575
- const ui = getUiRuntimeOptions();
1576
- const palette = draft.uiThemePreset ?? "green";
1577
- const accent = draft.uiAccentColor ?? "green";
1578
- const paletteItems = THEME_PRESET_OPTIONS.map((candidate, index) => {
1579
- const color = palette === candidate ? "green" : "yellow";
1580
- return {
1581
- label: `${palette === candidate ? "[x]" : "[ ]"} ${index + 1}. ${candidate === "green" ? "Green base" : "Blue base"}`,
1582
- hint: candidate === "green"
1583
- ? "High-contrast default."
1584
- : "Codex-style blue look.",
1585
- value: { type: "set-palette", palette: candidate },
1586
- color,
1587
- };
1588
- });
1589
- const accentItems = ACCENT_COLOR_OPTIONS.map((candidate) => {
1590
- const color = accent === candidate ? "green" : "yellow";
1591
- return {
1592
- label: `${accent === candidate ? "[x]" : "[ ]"} ${candidate}`,
1593
- value: { type: "set-accent", accent: candidate },
1594
- color,
1595
- };
1596
- });
1597
- const items = [
1598
- {
1599
- label: UI_COPY.settings.baseTheme,
1600
- value: { type: "cancel" },
1601
- kind: "heading",
1602
- },
1603
- ...paletteItems,
1604
- { label: "", value: { type: "cancel" }, separator: true },
1605
- {
1606
- label: UI_COPY.settings.accentColor,
1607
- value: { type: "cancel" },
1608
- kind: "heading",
1609
- },
1610
- ...accentItems,
1611
- { label: "", value: { type: "cancel" }, separator: true },
1612
- {
1613
- label: UI_COPY.settings.resetDefault,
1614
- value: { type: "reset" },
1615
- color: "yellow",
1616
- },
1617
- {
1618
- label: UI_COPY.settings.saveAndBack,
1619
- value: { type: "save" },
1620
- color: "green",
1621
- },
1622
- {
1623
- label: UI_COPY.settings.backNoSave,
1624
- value: { type: "cancel" },
1625
- color: "red",
1626
- },
1627
- ];
1628
- const initialCursor = items.findIndex((item) => {
1629
- const value = item.value;
1630
- if (value.type !== focus.type)
1631
- return false;
1632
- if (value.type === "set-palette" && focus.type === "set-palette") {
1633
- return value.palette === focus.palette;
1634
- }
1635
- if (value.type === "set-accent" && focus.type === "set-accent") {
1636
- return value.accent === focus.accent;
1637
- }
1638
- return true;
1639
- });
1640
- const result = await select(items, {
1641
- message: UI_COPY.settings.themeTitle,
1642
- subtitle: UI_COPY.settings.themeSubtitle,
1643
- help: UI_COPY.settings.themeHelp,
1644
- clearScreen: true,
1645
- theme: ui.theme,
1646
- selectedEmphasis: "minimal",
1647
- initialCursor: initialCursor >= 0 ? initialCursor : undefined,
1648
- onCursorChange: ({ cursor }) => {
1649
- const item = items[cursor];
1650
- if (item && !item.separator && item.kind !== "heading") {
1651
- focus = item.value;
1652
- }
1653
- },
1654
- onInput: (raw) => {
1655
- const lower = raw.toLowerCase();
1656
- if (lower === "q")
1657
- return { type: "cancel" };
1658
- if (lower === "s")
1659
- return { type: "save" };
1660
- if (lower === "r")
1661
- return { type: "reset" };
1662
- if (raw === "1")
1663
- return { type: "set-palette", palette: "green" };
1664
- if (raw === "2")
1665
- return { type: "set-palette", palette: "blue" };
1666
- return undefined;
1667
- },
1668
- });
1669
- if (!result || result.type === "cancel") {
1670
- applyUiThemeFromDashboardSettings(baseline);
1671
- return null;
1672
- }
1673
- if (result.type === "save")
1674
- return draft;
1675
- if (result.type === "reset") {
1676
- draft = applyDashboardDefaultsForKeys(draft, THEME_PANEL_KEYS);
1677
- focus = { type: "set-palette", palette: draft.uiThemePreset ?? "green" };
1678
- applyUiThemeFromDashboardSettings(draft);
1679
- continue;
1680
- }
1681
- if (result.type === "set-palette") {
1682
- draft = { ...draft, uiThemePreset: result.palette };
1683
- focus = result;
1684
- applyUiThemeFromDashboardSettings(draft);
1685
- continue;
1686
- }
1687
- draft = { ...draft, uiAccentColor: result.accent };
1688
- focus = result;
1689
- applyUiThemeFromDashboardSettings(draft);
1690
- }
1691
- }
1692
- function resolveFocusedBackendNumberKey(focus, numberOptions = BACKEND_NUMBER_OPTIONS) {
1693
- const numberKeys = new Set(numberOptions.map((option) => option.key));
1694
- if (focus && numberKeys.has(focus)) {
1695
- return focus;
1696
- }
1697
- return numberOptions[0]?.key ?? "fetchTimeoutMs";
1698
- }
1699
- function getBackendCategory(key) {
1700
- return (BACKEND_CATEGORY_OPTIONS.find((category) => category.key === key) ?? null);
1701
- }
1702
- function getBackendCategoryInitialFocus(category) {
1703
- const firstToggle = category.toggleKeys[0];
1704
- if (firstToggle)
1705
- return firstToggle;
1706
- return category.numberKeys[0] ?? null;
1707
- }
1708
- function applyBackendCategoryDefaults(draft, category) {
1709
- const next = { ...draft };
1710
- for (const key of category.toggleKeys) {
1711
- next[key] = BACKEND_DEFAULTS[key] ?? false;
1712
- }
1713
- for (const key of category.numberKeys) {
1714
- const option = BACKEND_NUMBER_OPTION_BY_KEY.get(key);
1715
- const fallback = option?.min ?? 0;
1716
- next[key] = BACKEND_DEFAULTS[key] ?? fallback;
1717
- }
1718
- return next;
344
+ return promptThemeSettingsPanelEntry({
345
+ initial,
346
+ promptThemeSettingsPanel,
347
+ cloneDashboardSettings,
348
+ applyDashboardDefaultsForKeys,
349
+ applyUiThemeFromDashboardSettings,
350
+ THEME_PRESET_OPTIONS,
351
+ ACCENT_COLOR_OPTIONS,
352
+ THEME_PANEL_KEYS,
353
+ UI_COPY,
354
+ });
1719
355
  }
1720
356
  async function promptBackendCategorySettings(initial, category, initialFocus) {
1721
- const ui = getUiRuntimeOptions();
1722
- let draft = cloneBackendPluginConfig(initial);
1723
- let focusKey = initialFocus;
1724
- if (!focusKey ||
1725
- (!category.toggleKeys.includes(focusKey) &&
1726
- !category.numberKeys.includes(focusKey))) {
1727
- focusKey = getBackendCategoryInitialFocus(category);
1728
- }
1729
- const toggleOptions = category.toggleKeys
1730
- .map((key) => BACKEND_TOGGLE_OPTION_BY_KEY.get(key))
1731
- .filter((option) => !!option);
1732
- const numberOptions = category.numberKeys
1733
- .map((key) => BACKEND_NUMBER_OPTION_BY_KEY.get(key))
1734
- .filter((option) => !!option);
1735
- while (true) {
1736
- const preview = buildBackendSettingsPreview(draft, ui, focusKey);
1737
- const toggleItems = toggleOptions.map((option, index) => {
1738
- const enabled = draft[option.key] ?? BACKEND_DEFAULTS[option.key] ?? false;
1739
- return {
1740
- label: `${formatDashboardSettingState(enabled)} ${index + 1}. ${option.label}`,
1741
- hint: option.description,
1742
- value: { type: "toggle", key: option.key },
1743
- color: enabled ? "green" : "yellow",
1744
- };
1745
- });
1746
- const numberItems = numberOptions.map((option) => {
1747
- const rawValue = draft[option.key] ?? BACKEND_DEFAULTS[option.key] ?? option.min;
1748
- const numericValue = typeof rawValue === "number" && Number.isFinite(rawValue)
1749
- ? rawValue
1750
- : option.min;
1751
- const clampedValue = clampBackendNumber(option, numericValue);
1752
- const valueLabel = formatBackendNumberValue(option, clampedValue);
1753
- return {
1754
- label: `${option.label}: ${valueLabel}`,
1755
- hint: `${option.description} Step ${formatBackendNumberValue(option, option.step)}.`,
1756
- value: { type: "bump", key: option.key, direction: 1 },
1757
- color: "yellow",
1758
- };
1759
- });
1760
- const focusedNumberKey = resolveFocusedBackendNumberKey(focusKey, numberOptions);
1761
- const items = [
1762
- {
1763
- label: UI_COPY.settings.previewHeading,
1764
- value: { type: "back" },
1765
- kind: "heading",
1766
- },
1767
- {
1768
- label: preview.label,
1769
- hint: preview.hint,
1770
- value: { type: "back" },
1771
- disabled: true,
1772
- color: "green",
1773
- hideUnavailableSuffix: true,
1774
- },
1775
- { label: "", value: { type: "back" }, separator: true },
1776
- {
1777
- label: UI_COPY.settings.backendToggleHeading,
1778
- value: { type: "back" },
1779
- kind: "heading",
1780
- },
1781
- ...toggleItems,
1782
- { label: "", value: { type: "back" }, separator: true },
1783
- {
1784
- label: UI_COPY.settings.backendNumberHeading,
1785
- value: { type: "back" },
1786
- kind: "heading",
1787
- },
1788
- ...numberItems,
1789
- ];
1790
- if (numberOptions.length > 0) {
1791
- items.push({ label: "", value: { type: "back" }, separator: true });
1792
- items.push({
1793
- label: UI_COPY.settings.backendDecrease,
1794
- value: { type: "bump", key: focusedNumberKey, direction: -1 },
1795
- color: "yellow",
1796
- });
1797
- items.push({
1798
- label: UI_COPY.settings.backendIncrease,
1799
- value: { type: "bump", key: focusedNumberKey, direction: 1 },
1800
- color: "green",
1801
- });
1802
- }
1803
- items.push({ label: "", value: { type: "back" }, separator: true });
1804
- items.push({
1805
- label: UI_COPY.settings.backendResetCategory,
1806
- value: { type: "reset-category" },
1807
- color: "yellow",
1808
- });
1809
- items.push({
1810
- label: UI_COPY.settings.backendBackToCategories,
1811
- value: { type: "back" },
1812
- color: "red",
1813
- });
1814
- const initialCursor = items.findIndex((item) => {
1815
- if (item.separator || item.disabled || item.kind === "heading")
1816
- return false;
1817
- if (item.value.type === "toggle" && focusKey === item.value.key)
1818
- return true;
1819
- if (item.value.type === "bump" && focusKey === item.value.key)
1820
- return true;
1821
- return false;
1822
- });
1823
- const result = await select(items, {
1824
- message: `${UI_COPY.settings.backendCategoryTitle}: ${category.label}`,
1825
- subtitle: category.description,
1826
- help: UI_COPY.settings.backendCategoryHelp,
1827
- clearScreen: true,
1828
- theme: ui.theme,
1829
- selectedEmphasis: "minimal",
1830
- initialCursor: initialCursor >= 0 ? initialCursor : undefined,
1831
- onCursorChange: ({ cursor }) => {
1832
- const focusedItem = items[cursor];
1833
- if (focusedItem?.value.type === "toggle" ||
1834
- focusedItem?.value.type === "bump") {
1835
- focusKey = focusedItem.value.key;
1836
- }
1837
- },
1838
- onInput: (raw) => {
1839
- const lower = raw.toLowerCase();
1840
- if (lower === "q")
1841
- return { type: "back" };
1842
- if (lower === "r")
1843
- return { type: "reset-category" };
1844
- if (numberOptions.length > 0 &&
1845
- (lower === "+" || lower === "=" || lower === "]" || lower === "d")) {
1846
- return {
1847
- type: "bump",
1848
- key: resolveFocusedBackendNumberKey(focusKey, numberOptions),
1849
- direction: 1,
1850
- };
1851
- }
1852
- if (numberOptions.length > 0 &&
1853
- (lower === "-" || lower === "[" || lower === "a")) {
1854
- return {
1855
- type: "bump",
1856
- key: resolveFocusedBackendNumberKey(focusKey, numberOptions),
1857
- direction: -1,
1858
- };
1859
- }
1860
- const parsed = Number.parseInt(raw, 10);
1861
- if (Number.isFinite(parsed) &&
1862
- parsed >= 1 &&
1863
- parsed <= toggleOptions.length) {
1864
- const target = toggleOptions[parsed - 1];
1865
- if (target)
1866
- return { type: "toggle", key: target.key };
1867
- }
1868
- return undefined;
1869
- },
1870
- });
1871
- if (!result || result.type === "back") {
1872
- return { draft, focusKey };
1873
- }
1874
- if (result.type === "reset-category") {
1875
- draft = applyBackendCategoryDefaults(draft, category);
1876
- focusKey = getBackendCategoryInitialFocus(category);
1877
- continue;
1878
- }
1879
- if (result.type === "toggle") {
1880
- const currentValue = draft[result.key] ?? BACKEND_DEFAULTS[result.key] ?? false;
1881
- draft = { ...draft, [result.key]: !currentValue };
1882
- focusKey = result.key;
1883
- continue;
1884
- }
1885
- const option = BACKEND_NUMBER_OPTION_BY_KEY.get(result.key);
1886
- if (!option)
1887
- continue;
1888
- const currentValue = draft[result.key] ?? BACKEND_DEFAULTS[result.key] ?? option.min;
1889
- const numericCurrent = typeof currentValue === "number" && Number.isFinite(currentValue)
1890
- ? currentValue
1891
- : option.min;
1892
- draft = {
1893
- ...draft,
1894
- [result.key]: clampBackendNumber(option, numericCurrent + option.step * result.direction),
1895
- };
1896
- focusKey = result.key;
1897
- }
357
+ return promptBackendCategorySettingsEntry({
358
+ initial,
359
+ category,
360
+ initialFocus,
361
+ promptBackendCategorySettingsMenu,
362
+ ui: getUiRuntimeOptions(),
363
+ cloneBackendPluginConfig,
364
+ buildBackendSettingsPreview,
365
+ highlightPreviewToken,
366
+ resolveFocusedBackendNumberKey,
367
+ clampBackendNumber,
368
+ formatBackendNumberValue,
369
+ formatDashboardSettingState,
370
+ applyBackendCategoryDefaults: (config, selectedCategory) => applyBackendCategoryDefaults(config, selectedCategory, {
371
+ backendDefaults: BACKEND_DEFAULTS,
372
+ numberOptionByKey: BACKEND_NUMBER_OPTION_BY_KEY,
373
+ }),
374
+ getBackendCategoryInitialFocus,
375
+ backendDefaults: BACKEND_DEFAULTS,
376
+ toggleOptionByKey: BACKEND_TOGGLE_OPTION_BY_KEY,
377
+ numberOptionByKey: BACKEND_NUMBER_OPTION_BY_KEY,
378
+ select,
379
+ copy: UI_COPY.settings,
380
+ });
1898
381
  }
1899
382
  async function promptBackendSettings(initial) {
1900
- if (!input.isTTY || !output.isTTY)
383
+ const interactive = input.isTTY && output.isTTY;
384
+ if (!interactive) {
1901
385
  return null;
1902
- const ui = getUiRuntimeOptions();
1903
- let draft = cloneBackendPluginConfig(initial);
1904
- let activeCategory = BACKEND_CATEGORY_OPTIONS[0]?.key ?? "session-sync";
1905
- const focusByCategory = {};
1906
- for (const category of BACKEND_CATEGORY_OPTIONS) {
1907
- focusByCategory[category.key] = getBackendCategoryInitialFocus(category);
1908
- }
1909
- while (true) {
1910
- const previewFocus = focusByCategory[activeCategory] ?? null;
1911
- const preview = buildBackendSettingsPreview(draft, ui, previewFocus);
1912
- const categoryItems = BACKEND_CATEGORY_OPTIONS.map((category, index) => {
1913
- return {
1914
- label: `${index + 1}. ${category.label}`,
1915
- hint: category.description,
1916
- value: { type: "open-category", key: category.key },
1917
- color: "green",
1918
- };
1919
- });
1920
- const items = [
1921
- {
1922
- label: UI_COPY.settings.previewHeading,
1923
- value: { type: "cancel" },
1924
- kind: "heading",
1925
- },
1926
- {
1927
- label: preview.label,
1928
- hint: preview.hint,
1929
- value: { type: "cancel" },
1930
- disabled: true,
1931
- color: "green",
1932
- hideUnavailableSuffix: true,
1933
- },
1934
- { label: "", value: { type: "cancel" }, separator: true },
1935
- {
1936
- label: UI_COPY.settings.backendCategoriesHeading,
1937
- value: { type: "cancel" },
1938
- kind: "heading",
1939
- },
1940
- ...categoryItems,
1941
- { label: "", value: { type: "cancel" }, separator: true },
1942
- {
1943
- label: UI_COPY.settings.resetDefault,
1944
- value: { type: "reset" },
1945
- color: "yellow",
1946
- },
1947
- {
1948
- label: UI_COPY.settings.saveAndBack,
1949
- value: { type: "save" },
1950
- color: "green",
1951
- },
1952
- {
1953
- label: UI_COPY.settings.backNoSave,
1954
- value: { type: "cancel" },
1955
- color: "red",
1956
- },
1957
- ];
1958
- const initialCursor = items.findIndex((item) => {
1959
- if (item.separator || item.disabled || item.kind === "heading")
1960
- return false;
1961
- return (item.value.type === "open-category" && item.value.key === activeCategory);
1962
- });
1963
- const result = await select(items, {
1964
- message: UI_COPY.settings.backendTitle,
1965
- subtitle: UI_COPY.settings.backendSubtitle,
1966
- help: UI_COPY.settings.backendHelp,
1967
- clearScreen: true,
1968
- theme: ui.theme,
1969
- selectedEmphasis: "minimal",
1970
- initialCursor: initialCursor >= 0 ? initialCursor : undefined,
1971
- onCursorChange: ({ cursor }) => {
1972
- const focusedItem = items[cursor];
1973
- if (focusedItem?.value.type === "open-category") {
1974
- activeCategory = focusedItem.value.key;
1975
- }
1976
- },
1977
- onInput: (raw) => {
1978
- const lower = raw.toLowerCase();
1979
- if (lower === "q")
1980
- return { type: "cancel" };
1981
- if (lower === "s")
1982
- return { type: "save" };
1983
- if (lower === "r")
1984
- return { type: "reset" };
1985
- const parsed = Number.parseInt(raw, 10);
1986
- if (Number.isFinite(parsed) &&
1987
- parsed >= 1 &&
1988
- parsed <= BACKEND_CATEGORY_OPTIONS.length) {
1989
- const target = BACKEND_CATEGORY_OPTIONS[parsed - 1];
1990
- if (target)
1991
- return { type: "open-category", key: target.key };
1992
- }
1993
- return undefined;
1994
- },
1995
- });
1996
- if (!result || result.type === "cancel")
1997
- return null;
1998
- if (result.type === "save")
1999
- return draft;
2000
- if (result.type === "reset") {
2001
- draft = cloneBackendPluginConfig(BACKEND_DEFAULTS);
2002
- for (const category of BACKEND_CATEGORY_OPTIONS) {
2003
- focusByCategory[category.key] =
2004
- getBackendCategoryInitialFocus(category);
2005
- }
2006
- activeCategory = BACKEND_CATEGORY_OPTIONS[0]?.key ?? activeCategory;
2007
- continue;
2008
- }
2009
- const category = getBackendCategory(result.key);
2010
- if (!category)
2011
- continue;
2012
- activeCategory = category.key;
2013
- const categoryResult = await promptBackendCategorySettings(draft, category, focusByCategory[category.key] ?? getBackendCategoryInitialFocus(category));
2014
- draft = categoryResult.draft;
2015
- focusByCategory[category.key] = categoryResult.focusKey;
2016
386
  }
387
+ return promptBackendSettingsMenu({
388
+ initial,
389
+ isInteractive: () => interactive,
390
+ ui: getUiRuntimeOptions(),
391
+ cloneBackendPluginConfig,
392
+ backendCategoryOptions: BACKEND_CATEGORY_OPTIONS,
393
+ getBackendCategoryInitialFocus,
394
+ buildBackendSettingsPreview,
395
+ highlightPreviewToken,
396
+ select,
397
+ getBackendCategory,
398
+ promptBackendCategorySettings,
399
+ backendDefaults: BACKEND_DEFAULTS,
400
+ copy: UI_COPY.settings,
401
+ });
2017
402
  }
2018
403
  async function loadExperimentalSyncTarget() {
2019
- const detection = detectOcChatgptMultiAuthTarget();
2020
- if (detection.kind === "ambiguous") {
2021
- return { kind: "blocked-ambiguous", detection };
2022
- }
2023
- if (detection.kind === "none") {
2024
- return { kind: "blocked-none", detection };
2025
- }
2026
- try {
2027
- const raw = JSON.parse(await readFileWithRetry(detection.descriptor.accountPath));
2028
- const normalized = normalizeAccountStorage(raw);
2029
- if (!normalized) {
2030
- return {
2031
- kind: "error",
2032
- message: "Invalid target account storage format",
2033
- };
2034
- }
2035
- return { kind: "target", detection, destination: normalized };
2036
- }
2037
- catch (error) {
2038
- const code = error.code;
2039
- if (code === "ENOENT") {
2040
- return { kind: "target", detection, destination: null };
2041
- }
2042
- return {
2043
- kind: "error",
2044
- message: error instanceof Error ? error.message : String(error),
2045
- };
2046
- }
404
+ return loadExperimentalSyncTargetEntry({
405
+ loadExperimentalSyncTargetState,
406
+ detectTarget: detectOcChatgptMultiAuthTarget,
407
+ readFileWithRetry,
408
+ normalizeAccountStorage,
409
+ sleep,
410
+ });
2047
411
  }
2048
412
  async function promptExperimentalSettings(initialConfig) {
2049
- if (!input.isTTY || !output.isTTY)
2050
- return null;
2051
- const ui = getUiRuntimeOptions();
2052
- let draft = cloneBackendPluginConfig(initialConfig);
2053
- while (true) {
2054
- const action = await select([
2055
- {
2056
- label: UI_COPY.settings.experimentalSync,
2057
- value: { type: "sync" },
2058
- color: "yellow",
2059
- },
2060
- {
2061
- label: UI_COPY.settings.experimentalBackup,
2062
- value: { type: "backup" },
2063
- color: "green",
2064
- },
2065
- {
2066
- label: `${formatDashboardSettingState(draft.proactiveRefreshGuardian ?? false)} ${UI_COPY.settings.experimentalRefreshGuard}`,
2067
- value: { type: "toggle-refresh-guardian" },
2068
- color: "yellow",
2069
- },
2070
- {
2071
- label: `${UI_COPY.settings.experimentalRefreshInterval}: ${Math.round((draft.proactiveRefreshIntervalMs ?? 60000) / 60000)} min`,
2072
- value: { type: "back" },
2073
- disabled: true,
2074
- hideUnavailableSuffix: true,
2075
- color: "green",
2076
- },
2077
- {
2078
- label: UI_COPY.settings.experimentalDecreaseInterval,
2079
- value: { type: "decrease-refresh-interval" },
2080
- color: "yellow",
2081
- },
2082
- {
2083
- label: UI_COPY.settings.experimentalIncreaseInterval,
2084
- value: { type: "increase-refresh-interval" },
2085
- color: "green",
2086
- },
2087
- {
2088
- label: UI_COPY.settings.saveAndBack,
2089
- value: { type: "save" },
2090
- color: "green",
2091
- },
2092
- {
2093
- label: UI_COPY.settings.backNoSave,
2094
- value: { type: "back" },
2095
- color: "red",
2096
- },
2097
- ], getExperimentalSelectOptions(ui, UI_COPY.settings.experimentalHelpMenu, mapExperimentalMenuHotkey));
2098
- if (!action || action.type === "back")
2099
- return null;
2100
- if (action.type === "save")
2101
- return draft;
2102
- if (action.type === "toggle-refresh-guardian") {
2103
- draft = {
2104
- ...draft,
2105
- proactiveRefreshGuardian: !(draft.proactiveRefreshGuardian ?? false),
2106
- };
2107
- continue;
2108
- }
2109
- if (action.type === "decrease-refresh-interval") {
2110
- draft = {
2111
- ...draft,
2112
- proactiveRefreshIntervalMs: Math.max(60_000, (draft.proactiveRefreshIntervalMs ?? 60000) - 60000),
2113
- };
2114
- continue;
2115
- }
2116
- if (action.type === "increase-refresh-interval") {
2117
- draft = {
2118
- ...draft,
2119
- proactiveRefreshIntervalMs: Math.min(600000, (draft.proactiveRefreshIntervalMs ?? 60000) + 60000),
2120
- };
2121
- continue;
2122
- }
2123
- if (action.type === "backup") {
2124
- const prompt = createInterface({ input, output });
2125
- try {
2126
- const backupName = (await prompt.question(UI_COPY.settings.experimentalBackupPrompt)).trim();
2127
- if (!backupName || backupName.toLowerCase() === "q") {
2128
- continue;
2129
- }
2130
- try {
2131
- const backupResult = await runNamedBackupExport({ name: backupName });
2132
- const backupLabel = backupResult.kind === "exported"
2133
- ? `Saved backup to ${backupResult.path}`
2134
- : backupResult.kind === "collision"
2135
- ? `Backup already exists: ${backupResult.path}`
2136
- : backupResult.error instanceof Error
2137
- ? backupResult.error.message
2138
- : String(backupResult.error);
2139
- await select([
2140
- {
2141
- label: backupLabel,
2142
- value: { type: "back" },
2143
- disabled: true,
2144
- hideUnavailableSuffix: true,
2145
- color: backupResult.kind === "exported" ? "green" : "yellow",
2146
- },
2147
- {
2148
- label: UI_COPY.settings.back,
2149
- value: { type: "back" },
2150
- color: "red",
2151
- },
2152
- ], getExperimentalSelectOptions(ui, UI_COPY.settings.experimentalHelpStatus, mapExperimentalStatusHotkey));
2153
- }
2154
- catch (error) {
2155
- const message = error instanceof Error ? error.message : String(error);
2156
- await select([
2157
- {
2158
- label: message,
2159
- value: { type: "back" },
2160
- disabled: true,
2161
- hideUnavailableSuffix: true,
2162
- color: "yellow",
2163
- },
2164
- {
2165
- label: UI_COPY.settings.back,
2166
- value: { type: "back" },
2167
- color: "red",
2168
- },
2169
- ], getExperimentalSelectOptions(ui, UI_COPY.settings.experimentalHelpStatus, mapExperimentalStatusHotkey));
2170
- }
2171
- }
2172
- finally {
2173
- prompt.close();
2174
- }
2175
- continue;
2176
- }
2177
- const source = await loadAccounts();
2178
- const targetState = await loadExperimentalSyncTarget();
2179
- if (targetState.kind === "error") {
2180
- await select([
2181
- {
2182
- label: targetState.message,
2183
- value: { type: "back" },
2184
- disabled: true,
2185
- hideUnavailableSuffix: true,
2186
- color: "yellow",
2187
- },
2188
- {
2189
- label: UI_COPY.settings.back,
2190
- value: { type: "back" },
2191
- color: "red",
2192
- },
2193
- ], getExperimentalSelectOptions(ui, UI_COPY.settings.experimentalHelpStatus, mapExperimentalStatusHotkey));
2194
- continue;
2195
- }
2196
- const plan = await planOcChatgptSync({
2197
- source,
2198
- destination: targetState.kind === "target" ? targetState.destination : null,
2199
- dependencies: targetState.kind === "target"
2200
- ? { detectTarget: () => targetState.detection }
2201
- : undefined,
2202
- });
2203
- if (plan.kind !== "ready") {
2204
- await select([
2205
- {
2206
- label: plan.kind === "blocked-ambiguous"
2207
- ? `Sync blocked: ${plan.detection.reason}`
2208
- : `Sync unavailable: ${plan.detection.reason}`,
2209
- value: { type: "back" },
2210
- disabled: true,
2211
- hideUnavailableSuffix: true,
2212
- color: "yellow",
2213
- },
2214
- {
2215
- label: UI_COPY.settings.back,
2216
- value: { type: "back" },
2217
- color: "red",
2218
- },
2219
- ], getExperimentalSelectOptions(ui, UI_COPY.settings.experimentalHelpStatus, mapExperimentalStatusHotkey));
2220
- continue;
2221
- }
2222
- const review = await select([
2223
- {
2224
- label: `Preview: add ${plan.preview.toAdd.length} | update ${plan.preview.toUpdate.length} | skip ${plan.preview.toSkip.length}`,
2225
- value: { type: "back" },
2226
- disabled: true,
2227
- hideUnavailableSuffix: true,
2228
- color: "green",
2229
- },
2230
- {
2231
- label: `Preserve destination-only: ${plan.preview.unchangedDestinationOnly.length}`,
2232
- value: { type: "back" },
2233
- disabled: true,
2234
- hideUnavailableSuffix: true,
2235
- color: "green",
2236
- },
2237
- {
2238
- label: `Active selection: ${plan.preview.activeSelectionBehavior}`,
2239
- value: { type: "back" },
2240
- disabled: true,
2241
- hideUnavailableSuffix: true,
2242
- color: "green",
2243
- },
2244
- {
2245
- label: UI_COPY.settings.experimentalApplySync,
2246
- value: { type: "apply" },
2247
- color: "green",
2248
- },
2249
- {
2250
- label: UI_COPY.settings.backNoSave,
2251
- value: { type: "back" },
2252
- color: "red",
2253
- },
2254
- ], getExperimentalSelectOptions(ui, UI_COPY.settings.experimentalHelpPreview, (raw) => {
2255
- const lower = raw.toLowerCase();
2256
- if (lower === "q")
2257
- return { type: "back" };
2258
- if (lower === "a")
2259
- return { type: "apply" };
2260
- return undefined;
2261
- }));
2262
- if (!review || review.type === "back")
2263
- continue;
2264
- const applied = await applyOcChatgptSync({
2265
- source,
2266
- destination: targetState.kind === "target" ? targetState.destination : undefined,
2267
- dependencies: targetState.kind === "target"
2268
- ? { detectTarget: () => targetState.detection }
2269
- : undefined,
2270
- });
2271
- await select([
2272
- {
2273
- label: applied.kind === "applied"
2274
- ? `Applied sync to ${applied.target.accountPath}`
2275
- : applied.kind === "error"
2276
- ? applied.error instanceof Error
2277
- ? applied.error.message
2278
- : String(applied.error)
413
+ return promptExperimentalSettingsEntry({
414
+ initialConfig,
415
+ promptExperimentalSettingsMenu,
416
+ isInteractive: () => input.isTTY && output.isTTY,
417
+ ui: getUiRuntimeOptions(),
418
+ cloneBackendPluginConfig,
419
+ select,
420
+ getExperimentalSelectOptions,
421
+ mapExperimentalMenuHotkey,
422
+ mapExperimentalStatusHotkey,
423
+ formatDashboardSettingState,
424
+ copy: UI_COPY.settings,
425
+ input,
426
+ output,
427
+ runNamedBackupExport,
428
+ loadAccounts,
429
+ loadExperimentalSyncTarget,
430
+ planOcChatgptSync,
431
+ applyOcChatgptSync,
432
+ getTargetKind: (targetState) => targetState.kind,
433
+ getTargetDestination: (targetState) => targetState.destination ?? null,
434
+ getTargetDetection: (targetState) => targetState.detection,
435
+ getTargetErrorMessage: (targetState) => targetState.kind === "error"
436
+ ? (targetState.message ?? "Unknown error")
437
+ : null,
438
+ getPlanKind: (plan) => plan.kind,
439
+ getPlanBlockedReason: (plan) => {
440
+ const candidate = plan;
441
+ return candidate.kind === "blocked-ambiguous"
442
+ ? `Sync blocked: ${candidate.detection?.reason ?? "unknown"}`
443
+ : `Sync unavailable: ${candidate.detection?.reason ?? "unknown"}`;
444
+ },
445
+ getPlanPreview: (plan) => plan.preview,
446
+ getAppliedLabel: (applied) => {
447
+ const candidate = applied;
448
+ return {
449
+ label: candidate.kind === "applied"
450
+ ? `Applied sync to ${candidate.target?.accountPath ?? "target"}`
451
+ : candidate.kind === "error"
452
+ ? candidate.error instanceof Error
453
+ ? candidate.error.message
454
+ : String(candidate.error)
2279
455
  : "Sync did not apply",
2280
- value: { type: "back" },
2281
- disabled: true,
2282
- hideUnavailableSuffix: true,
2283
- color: applied.kind === "applied" ? "green" : "yellow",
2284
- },
2285
- { label: UI_COPY.settings.back, value: { type: "back" }, color: "red" },
2286
- ], getExperimentalSelectOptions(ui, UI_COPY.settings.experimentalHelpStatus, mapExperimentalStatusHotkey));
2287
- }
456
+ color: candidate.kind === "applied" ? "green" : "yellow",
457
+ };
458
+ },
459
+ });
2288
460
  }
2289
461
  async function configureBackendSettings(currentConfig) {
2290
- const current = cloneBackendPluginConfig(currentConfig ?? loadPluginConfig());
2291
- if (!input.isTTY || !output.isTTY) {
2292
- console.log("Settings require interactive mode.");
2293
- return current;
2294
- }
2295
- const selected = await promptBackendSettings(current);
2296
- if (!selected)
2297
- return current;
2298
- if (backendSettingsEqual(current, selected))
2299
- return current;
2300
- return persistBackendConfigSelection(selected, "backend");
2301
- }
2302
- async function promptSettingsHub(initialFocus = "account-list") {
2303
- if (!input.isTTY || !output.isTTY)
2304
- return null;
2305
- const ui = getUiRuntimeOptions();
2306
- const items = [
2307
- {
2308
- label: UI_COPY.settings.sectionTitle,
2309
- value: { type: "back" },
2310
- kind: "heading",
2311
- },
2312
- {
2313
- label: UI_COPY.settings.accountList,
2314
- value: { type: "account-list" },
2315
- color: "green",
2316
- },
2317
- {
2318
- label: UI_COPY.settings.summaryFields,
2319
- value: { type: "summary-fields" },
2320
- color: "green",
2321
- },
2322
- {
2323
- label: UI_COPY.settings.behavior,
2324
- value: { type: "behavior" },
2325
- color: "green",
2326
- },
2327
- { label: UI_COPY.settings.theme, value: { type: "theme" }, color: "green" },
2328
- { label: "", value: { type: "back" }, separator: true },
2329
- {
2330
- label: UI_COPY.settings.advancedTitle,
2331
- value: { type: "back" },
2332
- kind: "heading",
462
+ return configureBackendSettingsEntry(currentConfig, {
463
+ configureBackendSettingsController,
464
+ cloneBackendPluginConfig,
465
+ loadPluginConfig,
466
+ promptBackendSettings,
467
+ backendSettingsEqual,
468
+ persistBackendConfigSelection,
469
+ isInteractive: () => input.isTTY && output.isTTY,
470
+ writeLine: (message) => {
471
+ console.log(message);
2333
472
  },
2334
- {
2335
- label: UI_COPY.settings.experimental,
2336
- value: { type: "experimental" },
2337
- color: "yellow",
2338
- },
2339
- {
2340
- label: UI_COPY.settings.backend,
2341
- value: { type: "backend" },
2342
- color: "green",
2343
- },
2344
- { label: "", value: { type: "back" }, separator: true },
2345
- {
2346
- label: UI_COPY.settings.exitTitle,
2347
- value: { type: "back" },
2348
- kind: "heading",
2349
- },
2350
- { label: UI_COPY.settings.back, value: { type: "back" }, color: "red" },
2351
- ];
2352
- const initialCursor = items.findIndex((item) => {
2353
- if (item.separator || item.disabled || item.kind === "heading")
2354
- return false;
2355
- return item.value.type === initialFocus;
2356
473
  });
2357
- return select(items, {
2358
- message: UI_COPY.settings.title,
2359
- subtitle: UI_COPY.settings.subtitle,
2360
- help: UI_COPY.settings.help,
2361
- clearScreen: true,
2362
- theme: ui.theme,
2363
- selectedEmphasis: "minimal",
2364
- initialCursor: initialCursor >= 0 ? initialCursor : undefined,
2365
- onInput: (raw) => {
2366
- const lower = raw.toLowerCase();
2367
- if (lower === "q")
2368
- return { type: "back" };
2369
- return undefined;
474
+ }
475
+ async function promptSettingsHub(initialFocus = "account-list") {
476
+ return promptSettingsHubEntry({
477
+ initialFocus,
478
+ promptSettingsHubMenu,
479
+ isInteractive: () => input.isTTY && output.isTTY,
480
+ getUiRuntimeOptions,
481
+ buildItems: () => buildSettingsHubItems(UI_COPY.settings),
482
+ findInitialCursor: findSettingsHubInitialCursor,
483
+ select,
484
+ copy: {
485
+ title: UI_COPY.settings.title,
486
+ subtitle: UI_COPY.settings.subtitle,
487
+ help: UI_COPY.settings.help,
2370
488
  },
2371
489
  });
2372
490
  }
2373
491
  /* c8 ignore stop */
2374
492
  async function configureUnifiedSettings(initialSettings) {
2375
- let current = cloneDashboardSettings(initialSettings ?? (await loadDashboardDisplaySettings()));
2376
- let backendConfig = cloneBackendPluginConfig(loadPluginConfig());
2377
- applyUiThemeFromDashboardSettings(current);
2378
- let hubFocus = "account-list";
2379
- while (true) {
2380
- const action = await promptSettingsHub(hubFocus);
2381
- if (!action || action.type === "back") {
2382
- return current;
2383
- }
2384
- hubFocus = action.type;
2385
- if (action.type === "account-list") {
2386
- current = await configureDashboardDisplaySettings(current);
2387
- continue;
2388
- }
2389
- if (action.type === "summary-fields") {
2390
- current = await configureStatuslineSettings(current);
2391
- continue;
2392
- }
2393
- if (action.type === "behavior") {
2394
- const selected = await promptBehaviorSettings(current);
2395
- if (selected && !dashboardSettingsEqual(current, selected)) {
2396
- current = await persistDashboardSettingsSelection(selected, BEHAVIOR_PANEL_KEYS, "behavior");
2397
- }
2398
- continue;
2399
- }
2400
- if (action.type === "theme") {
2401
- const selected = await promptThemeSettings(current);
2402
- if (selected && !dashboardSettingsEqual(current, selected)) {
2403
- current = await persistDashboardSettingsSelection(selected, THEME_PANEL_KEYS, "theme");
2404
- applyUiThemeFromDashboardSettings(current);
2405
- }
2406
- continue;
2407
- }
2408
- if (action.type === "experimental") {
2409
- const selected = await promptExperimentalSettings(backendConfig);
2410
- if (selected && !backendSettingsEqual(backendConfig, selected)) {
2411
- backendConfig = await persistBackendConfigSelection(selected, "experimental");
2412
- }
2413
- else if (selected) {
2414
- backendConfig = selected;
2415
- }
2416
- continue;
2417
- }
2418
- if (action.type === "backend") {
2419
- backendConfig = await configureBackendSettings(backendConfig);
2420
- }
2421
- }
493
+ return configureUnifiedSettingsEntry(initialSettings, {
494
+ configureUnifiedSettingsController,
495
+ cloneDashboardSettings,
496
+ cloneBackendPluginConfig,
497
+ loadDashboardDisplaySettings,
498
+ loadPluginConfig,
499
+ applyUiThemeFromDashboardSettings,
500
+ promptSettingsHub: async (focus) => promptSettingsHub(focus),
501
+ configureDashboardDisplaySettings,
502
+ configureStatuslineSettings,
503
+ promptBehaviorSettings,
504
+ promptThemeSettings,
505
+ dashboardSettingsEqual,
506
+ persistDashboardSettingsSelection,
507
+ promptExperimentalSettings,
508
+ backendSettingsEqual,
509
+ persistBackendConfigSelection,
510
+ configureBackendSettings,
511
+ BEHAVIOR_PANEL_KEYS,
512
+ THEME_PANEL_KEYS,
513
+ });
2422
514
  }
2423
515
  export { configureUnifiedSettings, applyUiThemeFromDashboardSettings, resolveMenuLayoutMode, __testOnly, };
2424
516
  //# sourceMappingURL=settings-hub.js.map