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