@slkiser/opencode-quota 5.0.3 → 6.0.0-beta.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 (794) hide show
  1. package/README.md +30 -44
  2. package/dist/agent-tools.d.ts +24 -0
  3. package/dist/agent-tools.d.ts.map +1 -0
  4. package/dist/agent-tools.js +578 -0
  5. package/dist/agent-tools.js.map +1 -0
  6. package/dist/bin/opencode-quota.d.ts.map +1 -1
  7. package/dist/bin/opencode-quota.js +1 -32
  8. package/dist/bin/opencode-quota.js.map +1 -1
  9. package/dist/core/errors.d.ts +12 -0
  10. package/dist/core/errors.d.ts.map +1 -0
  11. package/dist/core/errors.js +141 -0
  12. package/dist/core/errors.js.map +1 -0
  13. package/dist/core/pace.d.ts +13 -0
  14. package/dist/core/pace.d.ts.map +1 -0
  15. package/dist/core/pace.js +52 -0
  16. package/dist/core/pace.js.map +1 -0
  17. package/dist/core/persist.d.ts +44 -0
  18. package/dist/core/persist.d.ts.map +1 -0
  19. package/dist/core/persist.js +210 -0
  20. package/dist/core/persist.js.map +1 -0
  21. package/dist/core/provider-source.d.ts +40 -0
  22. package/dist/core/provider-source.d.ts.map +1 -0
  23. package/dist/core/provider-source.js +210 -0
  24. package/dist/core/provider-source.js.map +1 -0
  25. package/dist/core/redact.d.ts +17 -0
  26. package/dist/core/redact.d.ts.map +1 -0
  27. package/dist/core/redact.js +217 -0
  28. package/dist/core/redact.js.map +1 -0
  29. package/dist/core/rows.d.ts +20 -0
  30. package/dist/core/rows.d.ts.map +1 -0
  31. package/dist/core/rows.js +142 -0
  32. package/dist/core/rows.js.map +1 -0
  33. package/dist/core/selection.d.ts +15 -0
  34. package/dist/core/selection.d.ts.map +1 -0
  35. package/dist/core/selection.js +43 -0
  36. package/dist/core/selection.js.map +1 -0
  37. package/dist/core/snapshot-publisher.d.ts +15 -0
  38. package/dist/core/snapshot-publisher.d.ts.map +1 -0
  39. package/dist/core/snapshot-publisher.js +57 -0
  40. package/dist/core/snapshot-publisher.js.map +1 -0
  41. package/dist/core/store.d.ts +93 -0
  42. package/dist/core/store.d.ts.map +1 -0
  43. package/dist/core/store.js +563 -0
  44. package/dist/core/store.js.map +1 -0
  45. package/dist/core/types.d.ts +186 -0
  46. package/dist/core/types.d.ts.map +1 -0
  47. package/dist/core/types.js +2 -0
  48. package/dist/core/types.js.map +1 -0
  49. package/dist/core/usage-ranges.d.ts +46 -0
  50. package/dist/core/usage-ranges.d.ts.map +1 -0
  51. package/dist/core/usage-ranges.js +72 -0
  52. package/dist/core/usage-ranges.js.map +1 -0
  53. package/dist/core/usage.d.ts +100 -0
  54. package/dist/core/usage.d.ts.map +1 -0
  55. package/dist/core/usage.js +373 -0
  56. package/dist/core/usage.js.map +1 -0
  57. package/dist/core/validate.d.ts +8 -0
  58. package/dist/core/validate.d.ts.map +1 -0
  59. package/dist/core/validate.js +167 -0
  60. package/dist/core/validate.js.map +1 -0
  61. package/dist/core/windows.d.ts +24 -0
  62. package/dist/core/windows.d.ts.map +1 -0
  63. package/dist/core/windows.js +43 -0
  64. package/dist/core/windows.js.map +1 -0
  65. package/dist/index.d.ts +2 -1
  66. package/dist/index.d.ts.map +1 -1
  67. package/dist/index.js.map +1 -1
  68. package/dist/lib/accounting-format.d.ts +2 -52
  69. package/dist/lib/accounting-format.d.ts.map +1 -1
  70. package/dist/lib/accounting-format.js +6 -255
  71. package/dist/lib/accounting-format.js.map +1 -1
  72. package/dist/lib/alibaba-auth.d.ts +14 -21
  73. package/dist/lib/alibaba-auth.d.ts.map +1 -1
  74. package/dist/lib/alibaba-auth.js +36 -149
  75. package/dist/lib/alibaba-auth.js.map +1 -1
  76. package/dist/lib/alibaba-coding-plan-local-quota.d.ts +1 -6
  77. package/dist/lib/alibaba-coding-plan-local-quota.d.ts.map +1 -1
  78. package/dist/lib/alibaba-coding-plan-local-quota.js +1 -1
  79. package/dist/lib/alibaba-coding-plan-local-quota.js.map +1 -1
  80. package/dist/lib/alibaba-token-plan.d.ts +18 -27
  81. package/dist/lib/alibaba-token-plan.d.ts.map +1 -1
  82. package/dist/lib/alibaba-token-plan.js +121 -285
  83. package/dist/lib/alibaba-token-plan.js.map +1 -1
  84. package/dist/lib/anthropic-auth.d.ts +3 -5
  85. package/dist/lib/anthropic-auth.d.ts.map +1 -1
  86. package/dist/lib/anthropic-auth.js +6 -9
  87. package/dist/lib/anthropic-auth.js.map +1 -1
  88. package/dist/lib/anthropic.d.ts +12 -37
  89. package/dist/lib/anthropic.d.ts.map +1 -1
  90. package/dist/lib/anthropic.js +348 -698
  91. package/dist/lib/anthropic.js.map +1 -1
  92. package/dist/lib/api-key-resolver.d.ts +165 -192
  93. package/dist/lib/api-key-resolver.d.ts.map +1 -1
  94. package/dist/lib/api-key-resolver.js +208 -234
  95. package/dist/lib/api-key-resolver.js.map +1 -1
  96. package/dist/lib/atomic-json.d.ts +4 -1
  97. package/dist/lib/atomic-json.d.ts.map +1 -1
  98. package/dist/lib/atomic-json.js +2 -3
  99. package/dist/lib/atomic-json.js.map +1 -1
  100. package/dist/lib/calendar-date.d.ts +15 -0
  101. package/dist/lib/calendar-date.d.ts.map +1 -0
  102. package/dist/lib/calendar-date.js +21 -0
  103. package/dist/lib/calendar-date.js.map +1 -0
  104. package/dist/lib/chutes.d.ts +0 -1
  105. package/dist/lib/chutes.d.ts.map +1 -1
  106. package/dist/lib/chutes.js +2 -4
  107. package/dist/lib/chutes.js.map +1 -1
  108. package/dist/lib/cli-reports.d.ts +15 -11
  109. package/dist/lib/cli-reports.d.ts.map +1 -1
  110. package/dist/lib/cli-reports.js +34 -107
  111. package/dist/lib/cli-reports.js.map +1 -1
  112. package/dist/lib/cli-show.d.ts +9 -22
  113. package/dist/lib/cli-show.d.ts.map +1 -1
  114. package/dist/lib/cli-show.js +104 -75
  115. package/dist/lib/cli-show.js.map +1 -1
  116. package/dist/lib/config-file-utils.d.ts +3 -15
  117. package/dist/lib/config-file-utils.d.ts.map +1 -1
  118. package/dist/lib/config-file-utils.js +4 -63
  119. package/dist/lib/config-file-utils.js.map +1 -1
  120. package/dist/lib/config-write-target.d.ts +4 -7
  121. package/dist/lib/config-write-target.d.ts.map +1 -1
  122. package/dist/lib/config-write-target.js +4 -18
  123. package/dist/lib/config-write-target.js.map +1 -1
  124. package/dist/lib/copilot.d.ts +29 -20
  125. package/dist/lib/copilot.d.ts.map +1 -1
  126. package/dist/lib/copilot.js +392 -649
  127. package/dist/lib/copilot.js.map +1 -1
  128. package/dist/lib/cursor-detection.d.ts +3 -3
  129. package/dist/lib/cursor-detection.d.ts.map +1 -1
  130. package/dist/lib/cursor-detection.js +44 -88
  131. package/dist/lib/cursor-detection.js.map +1 -1
  132. package/dist/lib/cursor-pricing.d.ts +71 -8
  133. package/dist/lib/cursor-pricing.d.ts.map +1 -1
  134. package/dist/lib/cursor-pricing.js +33 -125
  135. package/dist/lib/cursor-pricing.js.map +1 -1
  136. package/dist/lib/cursor-usage.d.ts +6 -4
  137. package/dist/lib/cursor-usage.d.ts.map +1 -1
  138. package/dist/lib/cursor-usage.js +27 -40
  139. package/dist/lib/cursor-usage.js.map +1 -1
  140. package/dist/lib/deepseek.d.ts +9 -17
  141. package/dist/lib/deepseek.d.ts.map +1 -1
  142. package/dist/lib/deepseek.js +24 -54
  143. package/dist/lib/deepseek.js.map +1 -1
  144. package/dist/lib/display-sanitize.d.ts +0 -8
  145. package/dist/lib/display-sanitize.d.ts.map +1 -1
  146. package/dist/lib/display-sanitize.js +0 -139
  147. package/dist/lib/display-sanitize.js.map +1 -1
  148. package/dist/lib/entries.d.ts +13 -239
  149. package/dist/lib/entries.d.ts.map +1 -1
  150. package/dist/lib/entries.js +1 -46
  151. package/dist/lib/entries.js.map +1 -1
  152. package/dist/lib/file-lock.d.ts +23 -0
  153. package/dist/lib/file-lock.d.ts.map +1 -0
  154. package/dist/lib/file-lock.js +122 -0
  155. package/dist/lib/file-lock.js.map +1 -0
  156. package/dist/lib/format-utils.d.ts +2 -82
  157. package/dist/lib/format-utils.d.ts.map +1 -1
  158. package/dist/lib/format-utils.js +2 -191
  159. package/dist/lib/format-utils.js.map +1 -1
  160. package/dist/lib/glm-coding-plan.d.ts +6 -5
  161. package/dist/lib/glm-coding-plan.d.ts.map +1 -1
  162. package/dist/lib/glm-coding-plan.js +19 -1
  163. package/dist/lib/glm-coding-plan.js.map +1 -1
  164. package/dist/lib/google-agy.d.ts +8 -40
  165. package/dist/lib/google-agy.d.ts.map +1 -1
  166. package/dist/lib/google-agy.js +88 -519
  167. package/dist/lib/google-agy.js.map +1 -1
  168. package/dist/lib/google-companion-credentials.d.ts +9 -40
  169. package/dist/lib/google-companion-credentials.d.ts.map +1 -1
  170. package/dist/lib/google-companion-credentials.js +167 -224
  171. package/dist/lib/google-companion-credentials.js.map +1 -1
  172. package/dist/lib/google-gemini-cli.d.ts +5 -38
  173. package/dist/lib/google-gemini-cli.d.ts.map +1 -1
  174. package/dist/lib/google-gemini-cli.js +71 -442
  175. package/dist/lib/google-gemini-cli.js.map +1 -1
  176. package/dist/lib/google-oauth-quota.d.ts +76 -0
  177. package/dist/lib/google-oauth-quota.d.ts.map +1 -0
  178. package/dist/lib/google-oauth-quota.js +297 -0
  179. package/dist/lib/google-oauth-quota.js.map +1 -0
  180. package/dist/lib/google-token-cache.d.ts +3 -5
  181. package/dist/lib/google-token-cache.d.ts.map +1 -1
  182. package/dist/lib/google-token-cache.js +2 -14
  183. package/dist/lib/google-token-cache.js.map +1 -1
  184. package/dist/lib/home-dir-display.d.ts.map +1 -1
  185. package/dist/lib/home-dir-display.js +21 -39
  186. package/dist/lib/home-dir-display.js.map +1 -1
  187. package/dist/lib/http.d.ts +4 -1
  188. package/dist/lib/http.d.ts.map +1 -1
  189. package/dist/lib/http.js +2 -1
  190. package/dist/lib/http.js.map +1 -1
  191. package/dist/lib/json-guards.d.ts +11 -0
  192. package/dist/lib/json-guards.d.ts.map +1 -0
  193. package/dist/lib/json-guards.js +25 -0
  194. package/dist/lib/json-guards.js.map +1 -0
  195. package/dist/lib/kilo.d.ts +0 -2
  196. package/dist/lib/kilo.d.ts.map +1 -1
  197. package/dist/lib/kilo.js +33 -116
  198. package/dist/lib/kilo.js.map +1 -1
  199. package/dist/lib/kimi-endpoints.d.ts +2 -2
  200. package/dist/lib/kimi-endpoints.d.ts.map +1 -1
  201. package/dist/lib/kimi-endpoints.js +1 -1
  202. package/dist/lib/kimi-endpoints.js.map +1 -1
  203. package/dist/lib/kimi.d.ts.map +1 -1
  204. package/dist/lib/kimi.js +40 -86
  205. package/dist/lib/kimi.js.map +1 -1
  206. package/dist/lib/maintainer-announcements.d.ts +4 -17
  207. package/dist/lib/maintainer-announcements.d.ts.map +1 -1
  208. package/dist/lib/maintainer-announcements.js +7 -44
  209. package/dist/lib/maintainer-announcements.js.map +1 -1
  210. package/dist/lib/maintainer-home-notice.d.ts +19 -0
  211. package/dist/lib/maintainer-home-notice.d.ts.map +1 -0
  212. package/dist/lib/maintainer-home-notice.js +92 -0
  213. package/dist/lib/maintainer-home-notice.js.map +1 -0
  214. package/dist/lib/mimo-config.d.ts +6 -9
  215. package/dist/lib/mimo-config.d.ts.map +1 -1
  216. package/dist/lib/mimo-config.js +43 -74
  217. package/dist/lib/mimo-config.js.map +1 -1
  218. package/dist/lib/mimo.d.ts +2 -5
  219. package/dist/lib/mimo.d.ts.map +1 -1
  220. package/dist/lib/mimo.js +57 -109
  221. package/dist/lib/mimo.js.map +1 -1
  222. package/dist/lib/minimax-endpoints.d.ts +2 -2
  223. package/dist/lib/minimax-endpoints.d.ts.map +1 -1
  224. package/dist/lib/minimax-endpoints.js +1 -1
  225. package/dist/lib/minimax-endpoints.js.map +1 -1
  226. package/dist/lib/modelsdev-pricing.d.ts +22 -16
  227. package/dist/lib/modelsdev-pricing.d.ts.map +1 -1
  228. package/dist/lib/modelsdev-pricing.js +279 -560
  229. package/dist/lib/modelsdev-pricing.js.map +1 -1
  230. package/dist/lib/nanogpt.d.ts +6 -6
  231. package/dist/lib/nanogpt.d.ts.map +1 -1
  232. package/dist/lib/nanogpt.js +19 -72
  233. package/dist/lib/nanogpt.js.map +1 -1
  234. package/dist/lib/ollama-cloud.d.ts +3 -6
  235. package/dist/lib/ollama-cloud.d.ts.map +1 -1
  236. package/dist/lib/ollama-cloud.js +26 -37
  237. package/dist/lib/ollama-cloud.js.map +1 -1
  238. package/dist/lib/openai.d.ts +18 -29
  239. package/dist/lib/openai.d.ts.map +1 -1
  240. package/dist/lib/openai.js +108 -182
  241. package/dist/lib/openai.js.map +1 -1
  242. package/dist/lib/opencode-auth-sqlite.d.ts.map +1 -1
  243. package/dist/lib/opencode-auth-sqlite.js +22 -23
  244. package/dist/lib/opencode-auth-sqlite.js.map +1 -1
  245. package/dist/lib/opencode-auth.d.ts +17 -11
  246. package/dist/lib/opencode-auth.d.ts.map +1 -1
  247. package/dist/lib/opencode-auth.js +39 -46
  248. package/dist/lib/opencode-auth.js.map +1 -1
  249. package/dist/lib/opencode-config-editor.d.ts +3 -34
  250. package/dist/lib/opencode-config-editor.d.ts.map +1 -1
  251. package/dist/lib/opencode-config-editor.js +23 -142
  252. package/dist/lib/opencode-config-editor.js.map +1 -1
  253. package/dist/lib/opencode-config-providers.d.ts +4 -3
  254. package/dist/lib/opencode-config-providers.d.ts.map +1 -1
  255. package/dist/lib/opencode-config-providers.js +7 -11
  256. package/dist/lib/opencode-config-providers.js.map +1 -1
  257. package/dist/lib/opencode-config-read.d.ts +2 -1
  258. package/dist/lib/opencode-config-read.d.ts.map +1 -1
  259. package/dist/lib/opencode-config-read.js +3 -2
  260. package/dist/lib/opencode-config-read.js.map +1 -1
  261. package/dist/lib/opencode-console-auth.d.ts +2 -3
  262. package/dist/lib/opencode-console-auth.d.ts.map +1 -1
  263. package/dist/lib/opencode-console-auth.js +2 -2
  264. package/dist/lib/opencode-console-auth.js.map +1 -1
  265. package/dist/lib/opencode-go.d.ts.map +1 -1
  266. package/dist/lib/opencode-go.js +51 -79
  267. package/dist/lib/opencode-go.js.map +1 -1
  268. package/dist/lib/opencode-storage.d.ts +18 -3
  269. package/dist/lib/opencode-storage.d.ts.map +1 -1
  270. package/dist/lib/opencode-storage.js +134 -2
  271. package/dist/lib/opencode-storage.js.map +1 -1
  272. package/dist/lib/opencode-zen.d.ts +15 -12
  273. package/dist/lib/opencode-zen.d.ts.map +1 -1
  274. package/dist/lib/opencode-zen.js +139 -147
  275. package/dist/lib/opencode-zen.js.map +1 -1
  276. package/dist/lib/openrouter.d.ts.map +1 -1
  277. package/dist/lib/openrouter.js +1 -13
  278. package/dist/lib/openrouter.js.map +1 -1
  279. package/dist/lib/pricing-key.d.ts +48 -0
  280. package/dist/lib/pricing-key.d.ts.map +1 -0
  281. package/dist/lib/pricing-key.js +371 -0
  282. package/dist/lib/pricing-key.js.map +1 -0
  283. package/dist/lib/provider-metadata.d.ts +16 -20
  284. package/dist/lib/provider-metadata.d.ts.map +1 -1
  285. package/dist/lib/provider-metadata.js +69 -69
  286. package/dist/lib/provider-metadata.js.map +1 -1
  287. package/dist/lib/provider-model-matching.d.ts +2 -1
  288. package/dist/lib/provider-model-matching.d.ts.map +1 -1
  289. package/dist/lib/provider-registration.d.ts +1 -177
  290. package/dist/lib/provider-registration.d.ts.map +1 -1
  291. package/dist/lib/provider-registration.js +1 -163
  292. package/dist/lib/provider-registration.js.map +1 -1
  293. package/dist/lib/quota-dialog-commands.d.ts +87 -53
  294. package/dist/lib/quota-dialog-commands.d.ts.map +1 -1
  295. package/dist/lib/quota-dialog-commands.js +259 -519
  296. package/dist/lib/quota-dialog-commands.js.map +1 -1
  297. package/dist/lib/quota-export-types.d.ts +29 -23
  298. package/dist/lib/quota-export-types.d.ts.map +1 -1
  299. package/dist/lib/quota-export.d.ts +16 -26
  300. package/dist/lib/quota-export.d.ts.map +1 -1
  301. package/dist/lib/quota-export.js +105 -147
  302. package/dist/lib/quota-export.js.map +1 -1
  303. package/dist/lib/quota-providers-local.d.ts +12 -8
  304. package/dist/lib/quota-providers-local.d.ts.map +1 -1
  305. package/dist/lib/quota-providers-local.js +150 -223
  306. package/dist/lib/quota-providers-local.js.map +1 -1
  307. package/dist/lib/quota-providers-remote.d.ts +3 -8
  308. package/dist/lib/quota-providers-remote.d.ts.map +1 -1
  309. package/dist/lib/quota-providers-remote.js +309 -449
  310. package/dist/lib/quota-providers-remote.js.map +1 -1
  311. package/dist/lib/quota-providers.d.ts +57 -15
  312. package/dist/lib/quota-providers.d.ts.map +1 -1
  313. package/dist/lib/quota-providers.js +157 -64
  314. package/dist/lib/quota-providers.js.map +1 -1
  315. package/dist/lib/quota-report-message.d.ts +23 -10
  316. package/dist/lib/quota-report-message.d.ts.map +1 -1
  317. package/dist/lib/quota-report-message.js +37 -13
  318. package/dist/lib/quota-report-message.js.map +1 -1
  319. package/dist/lib/quota-retry-wait.d.ts +14 -6
  320. package/dist/lib/quota-retry-wait.d.ts.map +1 -1
  321. package/dist/lib/quota-retry-wait.js +37 -39
  322. package/dist/lib/quota-retry-wait.js.map +1 -1
  323. package/dist/lib/quota-status.d.ts +50 -33
  324. package/dist/lib/quota-status.d.ts.map +1 -1
  325. package/dist/lib/quota-status.js +1113 -773
  326. package/dist/lib/quota-status.js.map +1 -1
  327. package/dist/lib/quota-telemetry.d.ts +7 -14
  328. package/dist/lib/quota-telemetry.d.ts.map +1 -1
  329. package/dist/lib/quota-telemetry.js +46 -97
  330. package/dist/lib/quota-telemetry.js.map +1 -1
  331. package/dist/lib/report-document.d.ts +5 -65
  332. package/dist/lib/report-document.d.ts.map +1 -1
  333. package/dist/lib/report-document.js +14 -167
  334. package/dist/lib/report-document.js.map +1 -1
  335. package/dist/lib/resolved-auth-identity.d.ts +1 -2
  336. package/dist/lib/resolved-auth-identity.d.ts.map +1 -1
  337. package/dist/lib/resolved-auth-identity.js +0 -4
  338. package/dist/lib/resolved-auth-identity.js.map +1 -1
  339. package/dist/lib/session-tokens.d.ts +19 -19
  340. package/dist/lib/session-tokens.d.ts.map +1 -1
  341. package/dist/lib/session-tokens.js +58 -44
  342. package/dist/lib/session-tokens.js.map +1 -1
  343. package/dist/lib/synthetic.d.ts +0 -1
  344. package/dist/lib/synthetic.d.ts.map +1 -1
  345. package/dist/lib/synthetic.js +43 -94
  346. package/dist/lib/synthetic.js.map +1 -1
  347. package/dist/lib/token-buckets.d.ts +0 -1
  348. package/dist/lib/token-buckets.d.ts.map +1 -1
  349. package/dist/lib/token-buckets.js +0 -3
  350. package/dist/lib/token-buckets.js.map +1 -1
  351. package/dist/lib/token-cost.d.ts +2 -1
  352. package/dist/lib/token-cost.d.ts.map +1 -1
  353. package/dist/lib/types.d.ts +25 -333
  354. package/dist/lib/types.d.ts.map +1 -1
  355. package/dist/lib/types.js +2 -70
  356. package/dist/lib/types.js.map +1 -1
  357. package/dist/lib/xai.d.ts +6 -6
  358. package/dist/lib/xai.d.ts.map +1 -1
  359. package/dist/lib/xai.js +51 -90
  360. package/dist/lib/xai.js.map +1 -1
  361. package/dist/plugin.d.ts +6 -3
  362. package/dist/plugin.d.ts.map +1 -1
  363. package/dist/plugin.js +315 -90
  364. package/dist/plugin.js.map +1 -1
  365. package/dist/providers/alibaba-coding-plan.d.ts +4 -0
  366. package/dist/providers/alibaba-coding-plan.d.ts.map +1 -1
  367. package/dist/providers/alibaba-coding-plan.js +47 -77
  368. package/dist/providers/alibaba-coding-plan.js.map +1 -1
  369. package/dist/providers/alibaba-token-plan.d.ts.map +1 -1
  370. package/dist/providers/alibaba-token-plan.js +34 -46
  371. package/dist/providers/alibaba-token-plan.js.map +1 -1
  372. package/dist/providers/anthropic.d.ts +2 -4
  373. package/dist/providers/anthropic.d.ts.map +1 -1
  374. package/dist/providers/anthropic.js +80 -162
  375. package/dist/providers/anthropic.js.map +1 -1
  376. package/dist/providers/cache-policies.d.ts +0 -2
  377. package/dist/providers/cache-policies.d.ts.map +1 -1
  378. package/dist/providers/cache-policies.js +38 -88
  379. package/dist/providers/cache-policies.js.map +1 -1
  380. package/dist/providers/chutes.d.ts +0 -3
  381. package/dist/providers/chutes.d.ts.map +1 -1
  382. package/dist/providers/chutes.js +16 -28
  383. package/dist/providers/chutes.js.map +1 -1
  384. package/dist/providers/contract.d.ts +128 -0
  385. package/dist/providers/contract.d.ts.map +1 -0
  386. package/dist/providers/contract.js +101 -0
  387. package/dist/providers/contract.js.map +1 -0
  388. package/dist/providers/copilot.d.ts.map +1 -1
  389. package/dist/providers/copilot.js +171 -175
  390. package/dist/providers/copilot.js.map +1 -1
  391. package/dist/providers/cursor.d.ts.map +1 -1
  392. package/dist/providers/cursor.js +56 -109
  393. package/dist/providers/cursor.js.map +1 -1
  394. package/dist/providers/deepseek.d.ts +1 -6
  395. package/dist/providers/deepseek.d.ts.map +1 -1
  396. package/dist/providers/deepseek.js +46 -81
  397. package/dist/providers/deepseek.js.map +1 -1
  398. package/dist/providers/glm-coding-plan.d.ts +8 -0
  399. package/dist/providers/glm-coding-plan.d.ts.map +1 -0
  400. package/dist/providers/glm-coding-plan.js +106 -0
  401. package/dist/providers/glm-coding-plan.js.map +1 -0
  402. package/dist/providers/google-agy.d.ts +0 -1
  403. package/dist/providers/google-agy.d.ts.map +1 -1
  404. package/dist/providers/google-agy.js +41 -192
  405. package/dist/providers/google-agy.js.map +1 -1
  406. package/dist/providers/google-gemini-cli.d.ts.map +1 -1
  407. package/dist/providers/google-gemini-cli.js +51 -151
  408. package/dist/providers/google-gemini-cli.js.map +1 -1
  409. package/dist/providers/google-oauth-provider.d.ts +39 -0
  410. package/dist/providers/google-oauth-provider.d.ts.map +1 -0
  411. package/dist/providers/google-oauth-provider.js +161 -0
  412. package/dist/providers/google-oauth-provider.js.map +1 -0
  413. package/dist/providers/kilo.d.ts +0 -3
  414. package/dist/providers/kilo.d.ts.map +1 -1
  415. package/dist/providers/kilo.js +69 -123
  416. package/dist/providers/kilo.js.map +1 -1
  417. package/dist/providers/kimi-code.d.ts +5 -0
  418. package/dist/providers/kimi-code.d.ts.map +1 -1
  419. package/dist/providers/kimi-code.js +91 -136
  420. package/dist/providers/kimi-code.js.map +1 -1
  421. package/dist/providers/mimo.d.ts.map +1 -1
  422. package/dist/providers/mimo.js +55 -94
  423. package/dist/providers/mimo.js.map +1 -1
  424. package/dist/providers/minimax-coding-plan.d.ts +2 -23
  425. package/dist/providers/minimax-coding-plan.d.ts.map +1 -1
  426. package/dist/providers/minimax-coding-plan.js +161 -277
  427. package/dist/providers/minimax-coding-plan.js.map +1 -1
  428. package/dist/providers/nanogpt.d.ts +0 -3
  429. package/dist/providers/nanogpt.d.ts.map +1 -1
  430. package/dist/providers/nanogpt.js +61 -95
  431. package/dist/providers/nanogpt.js.map +1 -1
  432. package/dist/providers/ollama-cloud.d.ts +0 -6
  433. package/dist/providers/ollama-cloud.d.ts.map +1 -1
  434. package/dist/providers/ollama-cloud.js +86 -112
  435. package/dist/providers/ollama-cloud.js.map +1 -1
  436. package/dist/providers/openai.d.ts.map +1 -1
  437. package/dist/providers/openai.js +144 -166
  438. package/dist/providers/openai.js.map +1 -1
  439. package/dist/providers/opencode-go.d.ts.map +1 -1
  440. package/dist/providers/opencode-go.js +157 -199
  441. package/dist/providers/opencode-go.js.map +1 -1
  442. package/dist/providers/opencode-zen.d.ts.map +1 -1
  443. package/dist/providers/opencode-zen.js +100 -150
  444. package/dist/providers/opencode-zen.js.map +1 -1
  445. package/dist/providers/openrouter.d.ts +0 -3
  446. package/dist/providers/openrouter.d.ts.map +1 -1
  447. package/dist/providers/openrouter.js +26 -13
  448. package/dist/providers/openrouter.js.map +1 -1
  449. package/dist/providers/quota-providers.d.ts +7 -3
  450. package/dist/providers/quota-providers.d.ts.map +1 -1
  451. package/dist/providers/quota-providers.js +111 -217
  452. package/dist/providers/quota-providers.js.map +1 -1
  453. package/dist/providers/registry.d.ts.map +1 -1
  454. package/dist/providers/registry.js +1 -2
  455. package/dist/providers/registry.js.map +1 -1
  456. package/dist/providers/result-helpers.d.ts +10 -37
  457. package/dist/providers/result-helpers.d.ts.map +1 -1
  458. package/dist/providers/result-helpers.js +23 -56
  459. package/dist/providers/result-helpers.js.map +1 -1
  460. package/dist/providers/synthetic.d.ts +0 -3
  461. package/dist/providers/synthetic.d.ts.map +1 -1
  462. package/dist/providers/synthetic.js +16 -58
  463. package/dist/providers/synthetic.js.map +1 -1
  464. package/dist/providers/xai.d.ts +2 -1
  465. package/dist/providers/xai.d.ts.map +1 -1
  466. package/dist/providers/xai.js +49 -71
  467. package/dist/providers/xai.js.map +1 -1
  468. package/dist/rpc.d.ts +110 -38
  469. package/dist/rpc.d.ts.map +1 -1
  470. package/dist/rpc.js +125 -37
  471. package/dist/rpc.js.map +1 -1
  472. package/dist/settings/convert.d.ts +60 -0
  473. package/dist/settings/convert.d.ts.map +1 -0
  474. package/dist/settings/convert.js +473 -0
  475. package/dist/settings/convert.js.map +1 -0
  476. package/dist/settings/file.d.ts +89 -0
  477. package/dist/settings/file.d.ts.map +1 -0
  478. package/dist/settings/file.js +452 -0
  479. package/dist/settings/file.js.map +1 -0
  480. package/dist/settings/index.d.ts +10 -0
  481. package/dist/settings/index.d.ts.map +1 -0
  482. package/dist/settings/index.js +3 -0
  483. package/dist/settings/index.js.map +1 -0
  484. package/dist/settings/schema.d.ts +607 -0
  485. package/dist/settings/schema.d.ts.map +1 -0
  486. package/dist/settings/schema.js +479 -0
  487. package/dist/settings/schema.js.map +1 -0
  488. package/dist/tui/client.d.ts +86 -0
  489. package/dist/tui/client.d.ts.map +1 -0
  490. package/dist/tui/client.js +229 -0
  491. package/dist/tui/client.js.map +1 -0
  492. package/dist/tui/display.d.ts +127 -0
  493. package/dist/tui/display.d.ts.map +1 -0
  494. package/dist/tui/display.js +474 -0
  495. package/dist/tui/display.js.map +1 -0
  496. package/dist/tui/index.d.ts +21 -0
  497. package/dist/tui/index.d.ts.map +1 -0
  498. package/dist/tui/index.js +305 -0
  499. package/dist/tui/server-settings.d.ts +43 -0
  500. package/dist/tui/server-settings.d.ts.map +1 -0
  501. package/dist/tui/server-settings.js +233 -0
  502. package/dist/tui/server-settings.js.map +1 -0
  503. package/dist/tui/sidebar.d.ts +41 -0
  504. package/dist/tui/sidebar.d.ts.map +1 -0
  505. package/dist/tui/sidebar.js +148 -0
  506. package/dist/tui/status-line.d.ts +14 -0
  507. package/dist/tui/status-line.d.ts.map +1 -0
  508. package/dist/tui/status-line.js +225 -0
  509. package/dist/tui/theme.d.ts +41 -0
  510. package/dist/tui/theme.d.ts.map +1 -0
  511. package/dist/tui/theme.js +52 -0
  512. package/dist/tui/theme.js.map +1 -0
  513. package/dist/tui/toast-colors.d.ts +37 -0
  514. package/dist/tui/toast-colors.d.ts.map +1 -0
  515. package/dist/tui/toast-colors.js +77 -0
  516. package/dist/tui/toasts.d.ts +59 -0
  517. package/dist/tui/toasts.d.ts.map +1 -0
  518. package/dist/tui/toasts.js +148 -0
  519. package/dist/tui/toasts.js.map +1 -0
  520. package/dist/tui/window/drag.d.ts +26 -0
  521. package/dist/tui/window/drag.d.ts.map +1 -0
  522. package/dist/tui/window/drag.js +80 -0
  523. package/dist/tui/window/drag.js.map +1 -0
  524. package/dist/tui/window/limits.d.ts +15 -0
  525. package/dist/tui/window/limits.d.ts.map +1 -0
  526. package/dist/tui/window/limits.js +227 -0
  527. package/dist/tui/window/limits.js.map +1 -0
  528. package/dist/tui/window/rail.d.ts +21 -0
  529. package/dist/tui/window/rail.d.ts.map +1 -0
  530. package/dist/tui/window/rail.js +81 -0
  531. package/dist/tui/window/settings.d.ts +164 -0
  532. package/dist/tui/window/settings.d.ts.map +1 -0
  533. package/dist/tui/window/settings.js +1679 -0
  534. package/dist/tui/window/shell.d.ts +108 -0
  535. package/dist/tui/window/shell.d.ts.map +1 -0
  536. package/dist/tui/window/shell.js +1003 -0
  537. package/dist/tui/window/usage.d.ts +75 -0
  538. package/dist/tui/window/usage.d.ts.map +1 -0
  539. package/dist/tui/window/usage.js +928 -0
  540. package/dist/tui/window/views.d.ts +61 -0
  541. package/dist/tui/window/views.d.ts.map +1 -0
  542. package/dist/tui/window/views.js +242 -0
  543. package/dist/tui.d.ts +1 -5
  544. package/dist/tui.js +1 -894
  545. package/dist/view/columns.d.ts +15 -0
  546. package/dist/view/columns.d.ts.map +1 -0
  547. package/dist/view/columns.js +48 -0
  548. package/dist/view/columns.js.map +1 -0
  549. package/dist/view/format.d.ts +82 -0
  550. package/dist/view/format.d.ts.map +1 -0
  551. package/dist/view/format.js +201 -0
  552. package/dist/view/format.js.map +1 -0
  553. package/dist/view/quick-look.d.ts +28 -0
  554. package/dist/view/quick-look.d.ts.map +1 -0
  555. package/dist/view/quick-look.js +150 -0
  556. package/dist/view/quick-look.js.map +1 -0
  557. package/dist/view/select.d.ts +67 -0
  558. package/dist/view/select.d.ts.map +1 -0
  559. package/dist/view/select.js +87 -0
  560. package/dist/view/select.js.map +1 -0
  561. package/dist/view/text.d.ts +153 -0
  562. package/dist/view/text.d.ts.map +1 -0
  563. package/dist/view/text.js +642 -0
  564. package/dist/view/text.js.map +1 -0
  565. package/dist/view/usage.d.ts +86 -0
  566. package/dist/view/usage.d.ts.map +1 -0
  567. package/dist/view/usage.js +724 -0
  568. package/dist/view/usage.js.map +1 -0
  569. package/package.json +4 -6
  570. package/dist/lib/chutes-config.d.ts +0 -15
  571. package/dist/lib/chutes-config.d.ts.map +0 -1
  572. package/dist/lib/chutes-config.js +0 -28
  573. package/dist/lib/chutes-config.js.map +0 -1
  574. package/dist/lib/cli-status.d.ts +0 -8
  575. package/dist/lib/cli-status.d.ts.map +0 -1
  576. package/dist/lib/cli-status.js +0 -98
  577. package/dist/lib/cli-status.js.map +0 -1
  578. package/dist/lib/command-parsing.d.ts +0 -43
  579. package/dist/lib/command-parsing.d.ts.map +0 -1
  580. package/dist/lib/command-parsing.js +0 -103
  581. package/dist/lib/command-parsing.js.map +0 -1
  582. package/dist/lib/config.d.ts +0 -63
  583. package/dist/lib/config.d.ts.map +0 -1
  584. package/dist/lib/config.js +0 -1092
  585. package/dist/lib/config.js.map +0 -1
  586. package/dist/lib/deepseek-auth.d.ts +0 -15
  587. package/dist/lib/deepseek-auth.d.ts.map +0 -1
  588. package/dist/lib/deepseek-auth.js +0 -28
  589. package/dist/lib/deepseek-auth.js.map +0 -1
  590. package/dist/lib/format.d.ts +0 -25
  591. package/dist/lib/format.d.ts.map +0 -1
  592. package/dist/lib/format.js +0 -300
  593. package/dist/lib/format.js.map +0 -1
  594. package/dist/lib/google-agy-companion.d.ts +0 -8
  595. package/dist/lib/google-agy-companion.d.ts.map +0 -1
  596. package/dist/lib/google-agy-companion.js +0 -64
  597. package/dist/lib/google-agy-companion.js.map +0 -1
  598. package/dist/lib/google-gemini-cli-companion.d.ts +0 -8
  599. package/dist/lib/google-gemini-cli-companion.d.ts.map +0 -1
  600. package/dist/lib/google-gemini-cli-companion.js +0 -64
  601. package/dist/lib/google-gemini-cli-companion.js.map +0 -1
  602. package/dist/lib/grouped-entry-normalization.d.ts +0 -12
  603. package/dist/lib/grouped-entry-normalization.d.ts.map +0 -1
  604. package/dist/lib/grouped-entry-normalization.js +0 -124
  605. package/dist/lib/grouped-entry-normalization.js.map +0 -1
  606. package/dist/lib/grouped-header-format.d.ts +0 -5
  607. package/dist/lib/grouped-header-format.d.ts.map +0 -1
  608. package/dist/lib/grouped-header-format.js +0 -16
  609. package/dist/lib/grouped-header-format.js.map +0 -1
  610. package/dist/lib/init-installer.d.ts +0 -123
  611. package/dist/lib/init-installer.d.ts.map +0 -1
  612. package/dist/lib/init-installer.js +0 -1111
  613. package/dist/lib/init-installer.js.map +0 -1
  614. package/dist/lib/jsonc.d.ts +0 -17
  615. package/dist/lib/jsonc.d.ts.map +0 -1
  616. package/dist/lib/jsonc.js +0 -23
  617. package/dist/lib/jsonc.js.map +0 -1
  618. package/dist/lib/kilo-config.d.ts +0 -15
  619. package/dist/lib/kilo-config.d.ts.map +0 -1
  620. package/dist/lib/kilo-config.js +0 -27
  621. package/dist/lib/kilo-config.js.map +0 -1
  622. package/dist/lib/kimi-auth.d.ts +0 -49
  623. package/dist/lib/kimi-auth.d.ts.map +0 -1
  624. package/dist/lib/kimi-auth.js +0 -82
  625. package/dist/lib/kimi-auth.js.map +0 -1
  626. package/dist/lib/markdown-table.d.ts +0 -51
  627. package/dist/lib/markdown-table.d.ts.map +0 -1
  628. package/dist/lib/markdown-table.js +0 -179
  629. package/dist/lib/markdown-table.js.map +0 -1
  630. package/dist/lib/minimax-auth.d.ts +0 -62
  631. package/dist/lib/minimax-auth.d.ts.map +0 -1
  632. package/dist/lib/minimax-auth.js +0 -206
  633. package/dist/lib/minimax-auth.js.map +0 -1
  634. package/dist/lib/nanogpt-config.d.ts +0 -15
  635. package/dist/lib/nanogpt-config.d.ts.map +0 -1
  636. package/dist/lib/nanogpt-config.js +0 -31
  637. package/dist/lib/nanogpt-config.js.map +0 -1
  638. package/dist/lib/ollama-cloud-config.d.ts +0 -15
  639. package/dist/lib/ollama-cloud-config.d.ts.map +0 -1
  640. package/dist/lib/ollama-cloud-config.js +0 -27
  641. package/dist/lib/ollama-cloud-config.js.map +0 -1
  642. package/dist/lib/opencode-go-auth.d.ts +0 -16
  643. package/dist/lib/opencode-go-auth.d.ts.map +0 -1
  644. package/dist/lib/opencode-go-auth.js +0 -42
  645. package/dist/lib/opencode-go-auth.js.map +0 -1
  646. package/dist/lib/opencode-version.d.ts +0 -6
  647. package/dist/lib/opencode-version.d.ts.map +0 -1
  648. package/dist/lib/opencode-version.js +0 -26
  649. package/dist/lib/opencode-version.js.map +0 -1
  650. package/dist/lib/provider-add-command.d.ts +0 -35
  651. package/dist/lib/provider-add-command.d.ts.map +0 -1
  652. package/dist/lib/provider-add-command.js +0 -204
  653. package/dist/lib/provider-add-command.js.map +0 -1
  654. package/dist/lib/provider-add-json-v1-questionnaire.d.ts +0 -32
  655. package/dist/lib/provider-add-json-v1-questionnaire.d.ts.map +0 -1
  656. package/dist/lib/provider-add-json-v1-questionnaire.js +0 -336
  657. package/dist/lib/provider-add-json-v1-questionnaire.js.map +0 -1
  658. package/dist/lib/provider-add.d.ts +0 -21
  659. package/dist/lib/provider-add.d.ts.map +0 -1
  660. package/dist/lib/provider-add.js +0 -219
  661. package/dist/lib/provider-add.js.map +0 -1
  662. package/dist/lib/quota-accounting-projection.d.ts +0 -9
  663. package/dist/lib/quota-accounting-projection.d.ts.map +0 -1
  664. package/dist/lib/quota-accounting-projection.js +0 -254
  665. package/dist/lib/quota-accounting-projection.js.map +0 -1
  666. package/dist/lib/quota-columns.d.ts +0 -38
  667. package/dist/lib/quota-columns.d.ts.map +0 -1
  668. package/dist/lib/quota-columns.js +0 -129
  669. package/dist/lib/quota-columns.js.map +0 -1
  670. package/dist/lib/quota-command-format.d.ts +0 -34
  671. package/dist/lib/quota-command-format.d.ts.map +0 -1
  672. package/dist/lib/quota-command-format.js +0 -240
  673. package/dist/lib/quota-command-format.js.map +0 -1
  674. package/dist/lib/quota-dialog-command-specs.d.ts +0 -63
  675. package/dist/lib/quota-dialog-command-specs.d.ts.map +0 -1
  676. package/dist/lib/quota-dialog-command-specs.js +0 -145
  677. package/dist/lib/quota-dialog-command-specs.js.map +0 -1
  678. package/dist/lib/quota-entry-display.d.ts +0 -7
  679. package/dist/lib/quota-entry-display.d.ts.map +0 -1
  680. package/dist/lib/quota-entry-display.js +0 -59
  681. package/dist/lib/quota-entry-display.js.map +0 -1
  682. package/dist/lib/quota-exhaustion-projection.d.ts +0 -11
  683. package/dist/lib/quota-exhaustion-projection.d.ts.map +0 -1
  684. package/dist/lib/quota-exhaustion-projection.js +0 -105
  685. package/dist/lib/quota-exhaustion-projection.js.map +0 -1
  686. package/dist/lib/quota-format-style.d.ts +0 -21
  687. package/dist/lib/quota-format-style.d.ts.map +0 -1
  688. package/dist/lib/quota-format-style.js +0 -38
  689. package/dist/lib/quota-format-style.js.map +0 -1
  690. package/dist/lib/quota-render-data.d.ts +0 -102
  691. package/dist/lib/quota-render-data.d.ts.map +0 -1
  692. package/dist/lib/quota-render-data.js +0 -419
  693. package/dist/lib/quota-render-data.js.map +0 -1
  694. package/dist/lib/quota-reset-notifications.d.ts +0 -20
  695. package/dist/lib/quota-reset-notifications.d.ts.map +0 -1
  696. package/dist/lib/quota-reset-notifications.js +0 -331
  697. package/dist/lib/quota-reset-notifications.js.map +0 -1
  698. package/dist/lib/quota-runtime-context.d.ts +0 -54
  699. package/dist/lib/quota-runtime-context.d.ts.map +0 -1
  700. package/dist/lib/quota-runtime-context.js +0 -110
  701. package/dist/lib/quota-runtime-context.js.map +0 -1
  702. package/dist/lib/quota-state-codec.d.ts +0 -16
  703. package/dist/lib/quota-state-codec.d.ts.map +0 -1
  704. package/dist/lib/quota-state-codec.js +0 -412
  705. package/dist/lib/quota-state-codec.js.map +0 -1
  706. package/dist/lib/quota-state.d.ts +0 -28
  707. package/dist/lib/quota-state.d.ts.map +0 -1
  708. package/dist/lib/quota-state.js +0 -473
  709. package/dist/lib/quota-state.js.map +0 -1
  710. package/dist/lib/quota-stats-format.d.ts +0 -29
  711. package/dist/lib/quota-stats-format.d.ts.map +0 -1
  712. package/dist/lib/quota-stats-format.js +0 -459
  713. package/dist/lib/quota-stats-format.js.map +0 -1
  714. package/dist/lib/quota-stats.d.ts +0 -126
  715. package/dist/lib/quota-stats.d.ts.map +0 -1
  716. package/dist/lib/quota-stats.js +0 -695
  717. package/dist/lib/quota-stats.js.map +0 -1
  718. package/dist/lib/quota-surface-data.d.ts +0 -21
  719. package/dist/lib/quota-surface-data.d.ts.map +0 -1
  720. package/dist/lib/quota-surface-data.js +0 -362
  721. package/dist/lib/quota-surface-data.js.map +0 -1
  722. package/dist/lib/scoped-update-migration.d.ts +0 -103
  723. package/dist/lib/scoped-update-migration.d.ts.map +0 -1
  724. package/dist/lib/scoped-update-migration.js +0 -344
  725. package/dist/lib/scoped-update-migration.js.map +0 -1
  726. package/dist/lib/scoped-update.d.ts +0 -77
  727. package/dist/lib/scoped-update.d.ts.map +0 -1
  728. package/dist/lib/scoped-update.js +0 -590
  729. package/dist/lib/scoped-update.js.map +0 -1
  730. package/dist/lib/session-tokens-format.d.ts +0 -36
  731. package/dist/lib/session-tokens-format.d.ts.map +0 -1
  732. package/dist/lib/session-tokens-format.js +0 -111
  733. package/dist/lib/session-tokens-format.js.map +0 -1
  734. package/dist/lib/synthetic-config.d.ts +0 -15
  735. package/dist/lib/synthetic-config.d.ts.map +0 -1
  736. package/dist/lib/synthetic-config.js +0 -28
  737. package/dist/lib/synthetic-config.js.map +0 -1
  738. package/dist/lib/toast-format-grouped.d.ts +0 -25
  739. package/dist/lib/toast-format-grouped.d.ts.map +0 -1
  740. package/dist/lib/toast-format-grouped.js +0 -296
  741. package/dist/lib/toast-format-grouped.js.map +0 -1
  742. package/dist/lib/tui-compact-format.d.ts +0 -10
  743. package/dist/lib/tui-compact-format.d.ts.map +0 -1
  744. package/dist/lib/tui-compact-format.js +0 -460
  745. package/dist/lib/tui-compact-format.js.map +0 -1
  746. package/dist/lib/tui-panel-state.d.ts +0 -15
  747. package/dist/lib/tui-panel-state.d.ts.map +0 -1
  748. package/dist/lib/tui-panel-state.js +0 -2
  749. package/dist/lib/tui-panel-state.js.map +0 -1
  750. package/dist/lib/tui-prompt-bar-format.d.ts +0 -25
  751. package/dist/lib/tui-prompt-bar-format.d.ts.map +0 -1
  752. package/dist/lib/tui-prompt-bar-format.js +0 -206
  753. package/dist/lib/tui-prompt-bar-format.js.map +0 -1
  754. package/dist/lib/tui-sidebar-format.d.ts +0 -13
  755. package/dist/lib/tui-sidebar-format.d.ts.map +0 -1
  756. package/dist/lib/tui-sidebar-format.js +0 -34
  757. package/dist/lib/tui-sidebar-format.js.map +0 -1
  758. package/dist/lib/zai-auth.d.ts +0 -15
  759. package/dist/lib/zai-auth.d.ts.map +0 -1
  760. package/dist/lib/zai-auth.js +0 -37
  761. package/dist/lib/zai-auth.js.map +0 -1
  762. package/dist/lib/zai.d.ts +0 -5
  763. package/dist/lib/zai.d.ts.map +0 -1
  764. package/dist/lib/zai.js +0 -14
  765. package/dist/lib/zai.js.map +0 -1
  766. package/dist/lib/zhipu-auth.d.ts +0 -15
  767. package/dist/lib/zhipu-auth.d.ts.map +0 -1
  768. package/dist/lib/zhipu-auth.js +0 -42
  769. package/dist/lib/zhipu-auth.js.map +0 -1
  770. package/dist/lib/zhipu.d.ts +0 -5
  771. package/dist/lib/zhipu.d.ts.map +0 -1
  772. package/dist/lib/zhipu.js +0 -13
  773. package/dist/lib/zhipu.js.map +0 -1
  774. package/dist/providers/glm-coding-plan-provider.d.ts +0 -56
  775. package/dist/providers/glm-coding-plan-provider.d.ts.map +0 -1
  776. package/dist/providers/glm-coding-plan-provider.js +0 -115
  777. package/dist/providers/glm-coding-plan-provider.js.map +0 -1
  778. package/dist/providers/google-account-format.d.ts +0 -7
  779. package/dist/providers/google-account-format.d.ts.map +0 -1
  780. package/dist/providers/google-account-format.js +0 -52
  781. package/dist/providers/google-account-format.js.map +0 -1
  782. package/dist/providers/zai.d.ts +0 -2
  783. package/dist/providers/zai.d.ts.map +0 -1
  784. package/dist/providers/zai.js +0 -24
  785. package/dist/providers/zai.js.map +0 -1
  786. package/dist/providers/zhipu.d.ts +0 -2
  787. package/dist/providers/zhipu.d.ts.map +0 -1
  788. package/dist/providers/zhipu.js +0 -21
  789. package/dist/providers/zhipu.js.map +0 -1
  790. package/dist/tui-v2.d.ts +0 -5
  791. package/dist/tui-v2.d.ts.map +0 -1
  792. package/dist/tui-v2.jsx +0 -624
  793. package/dist/tui-v2.jsx.map +0 -1
  794. package/dist/tui.d.ts.map +0 -1
@@ -0,0 +1,1679 @@
1
+ import { use as _$use } from "@opentui/solid";
2
+ import { createTextNode as _$createTextNode } from "@opentui/solid";
3
+ import { insertNode as _$insertNode } from "@opentui/solid";
4
+ import { memo as _$memo } from "@opentui/solid";
5
+ import { createComponent as _$createComponent } from "@opentui/solid";
6
+ import { effect as _$effect } from "@opentui/solid";
7
+ import { insert as _$insert } from "@opentui/solid";
8
+ import { setProp as _$setProp } from "@opentui/solid";
9
+ import { createElement as _$createElement } from "@opentui/solid";
10
+ /** @jsxImportSource @opentui/solid */
11
+ /**
12
+ * The Settings tabs edit settings.jsonc; surfaces preview saved settings with draft changes.
13
+ * Layout's pages are a list left of the body (`Pages`), like Usage's ranges. When a page shows,
14
+ * the list has the keyboard: ↑↓ change the page, → or enter go to the page's first line, and ↑
15
+ * on that line goes back to the list.
16
+ */
17
+ import { RGBA, TextAttributes } from "@opentui/core";
18
+ import { createEffect, createMemo, createSignal, For, on, Show } from "solid-js";
19
+ import { describeError } from "../../core/errors.js";
20
+ import { ALL_PROVIDERS, WINDOWS } from "../../core/windows.js";
21
+ import { CHANGED_SINCE_REVIEW } from "../../settings/schema.js";
22
+ import { columnsOf } from "../../view/columns.js";
23
+ import { DEFAULT_WORDS, fit, percentText, resetText, rowValueText } from "../../view/format.js";
24
+ import { pickRow, windowFor } from "../../view/select.js";
25
+ import { rpcErrorMessage } from "../client.js";
26
+ import { COLOR_NAMES, FIELDS, isSurfaceTab, PRESETS, presetChoice, presetValues, renameRow, resetTab, setIn, stepIn, typedColor, typedNumber } from "../display.js";
27
+ import { foundProviderIds, isTicked, PROVIDERS_KEY, withTick } from "../server-settings.js";
28
+ import { namedColor, roleColor } from "../theme.js";
29
+ import { plainMessage, quotaToastLines } from "../toasts.js";
30
+ import { draggedTo, movedBy, surfaceTree } from "./drag.js";
31
+ import { Rail, railRoom } from "./rail.js";
32
+ export const SETTINGS_TABS = [{
33
+ tab: "layout",
34
+ title: "All places",
35
+ watchesSidebar: true
36
+ }, {
37
+ tab: "sidebar",
38
+ title: "Sidebar",
39
+ switchTitle: "Show the Quota panel in the session sidebar",
40
+ watchesSidebar: true
41
+ }, {
42
+ tab: "collapsed",
43
+ title: "Collapsed",
44
+ switchTitle: "When the panel is collapsed, show one line per provider",
45
+ watchesSidebar: true
46
+ }, {
47
+ tab: "statusLine",
48
+ title: "Status line",
49
+ switchTitle: "Show the quota line under the message box",
50
+ watchesSidebar: false
51
+ }, {
52
+ tab: "toast",
53
+ title: "Toast",
54
+ switchTitle: "Show quota toasts",
55
+ watchesSidebar: false
56
+ }, {
57
+ tab: "colors",
58
+ title: "Colors",
59
+ watchesSidebar: true
60
+ }, {
61
+ tab: "providers",
62
+ title: "Providers",
63
+ watchesSidebar: true
64
+ }];
65
+
66
+ /**
67
+ * The Settings tabs of the window's tab bar, each with its pages: Layout has All places, then one
68
+ * per place; the others are one page each.
69
+ */
70
+ export const SETTINGS_GROUPS = [{
71
+ title: "Layout",
72
+ pages: ["layout", "sidebar", "collapsed", "statusLine", "toast"]
73
+ }, {
74
+ title: "Colors",
75
+ pages: ["colors"]
76
+ }, {
77
+ title: "Providers",
78
+ pages: ["providers"]
79
+ }];
80
+ export function isSettingsTab(tab) {
81
+ return SETTINGS_TABS.some(item => item.tab === tab);
82
+ }
83
+
84
+ /** The pages of `tab`'s Settings tab when it has more than one, for the list left of the body. */
85
+ function pagesOf(tab) {
86
+ const pages = SETTINGS_GROUPS.find(group => group.pages.includes(tab))?.pages ?? [];
87
+ return pages.length > 1 ? pages : undefined;
88
+ }
89
+ function pageTitle(tab) {
90
+ return SETTINGS_TABS.find(item => item.tab === tab)?.title ?? tab;
91
+ }
92
+
93
+ /** What the window keeps left of a Settings tab's body: Layout's page list, else nothing. */
94
+ export function pagesRoom(tab) {
95
+ const pages = isSettingsTab(tab) ? pagesOf(tab) : undefined;
96
+ return pages ? railRoom(PAGE_LIST_GAP) : 0;
97
+ }
98
+
99
+ /** "Reset page" on Layout's pages, which reset only their own lines; "Reset tab" elsewhere. */
100
+ function resetLabel(tab) {
101
+ return pagesOf(tab) ? "Reset page" : "Reset tab";
102
+ }
103
+
104
+ /** A line ↑↓ select: ‹ value › steps through values, value ▸ runs a button; some take typing. */
105
+
106
+ /** What a line takes when you type into it (e, or a double-click). */
107
+
108
+ /** A line of a surface tab's tree. One object per line, so <For> keeps its view while it moves. */
109
+
110
+ const KEYS = "Quota window";
111
+ const TRANSPARENT = RGBA.fromInts(0, 0, 0, 0);
112
+ /** The id of a surface tab's switch line. */
113
+ const SWITCH_ID = "surface";
114
+ /** The selection id of Layout's page list: the list has the keyboard. */
115
+ const PAGES_ID = "pages";
116
+ /** The body starts right after the page list's line: its lines carry their own indent. */
117
+ const PAGE_LIST_GAP = 0;
118
+ const DOUBLE_CLICK_MS = 400;
119
+ /** A line's columns besides its title and value: the 3 spaces, the title's space, "‹ " and " ›". */
120
+ const LINE_FRAME = 8;
121
+ const TITLE_WIDTH = 26;
122
+ const TITLE_MIN = 12;
123
+ const VALUE_WIDTH = 24;
124
+ const VALUE_MIN = 6;
125
+
126
+ /**
127
+ * A line's title and value widths in `width` columns: 26 and the value's own width when both
128
+ * fit; else the title gives way first (down to 12 columns), then the value (down to 6).
129
+ */
130
+ export function lineColumns(width, valueWidth = VALUE_WIDTH) {
131
+ if (width === undefined) return {
132
+ title: TITLE_WIDTH,
133
+ value: valueWidth
134
+ };
135
+ const room = width - LINE_FRAME;
136
+ const title = Math.max(TITLE_MIN, Math.min(TITLE_WIDTH, room - valueWidth));
137
+ const value = Math.max(Math.min(VALUE_MIN, valueWidth), Math.min(valueWidth, room - title));
138
+ return {
139
+ title,
140
+ value
141
+ };
142
+ }
143
+
144
+ /** Selection id of a tree line; a row id could equal a setting's path. */
145
+ function lineKey(id) {
146
+ return `line:${id}`;
147
+ }
148
+
149
+ /** Renderable id of a line, so the list can scroll it into view. */
150
+ function boxId(id) {
151
+ return `quota-settings.${id}`;
152
+ }
153
+
154
+ /** Renderable id of a page in Layout's page list. */
155
+ function pageId(tab) {
156
+ return `quota-layout-page-${tab}`;
157
+ }
158
+
159
+ /** The windows ‹ › steps through: those of the provider's rows not hidden on the page. */
160
+ function windowChoices(provider, hidden) {
161
+ const windows = provider.rows.flatMap(row => row.window && row.percentRemaining !== undefined && !hidden.includes(row.id) ? [row.window] : []);
162
+ const unique = [...new Set(windows)];
163
+ return unique.length > 1 ? ["lowest", ...unique] : [];
164
+ }
165
+ function windowTitle(choice) {
166
+ return choice === "lowest" ? "lowest left" : WINDOWS[choice].short;
167
+ }
168
+
169
+ /**
170
+ * What a provider's ‹ › shows without a pick of its own: the pick for all providers when the
171
+ * provider has that window (one of its `choices`), else lowest.
172
+ */
173
+ function inheritedWindow(windows, choices) {
174
+ const all = windows[ALL_PROVIDERS];
175
+ return all !== undefined && choices.includes(all) ? all : "lowest";
176
+ }
177
+
178
+ /**
179
+ * One-line text that keeps its width, unless `shrink` lets it give way. With `wrap` (notes,
180
+ * details) it goes on to more lines between words instead of being cut.
181
+ */
182
+ export function Cell(props) {
183
+ return (() => {
184
+ var _el$ = _$createElement("text");
185
+ _$setProp(_el$, "selectable", false);
186
+ _$insert(_el$, () => props.children);
187
+ _$effect(_p$ => {
188
+ var _v$ = props.fg,
189
+ _v$2 = props.bold ? TextAttributes.BOLD : TextAttributes.NONE,
190
+ _v$3 = props.wrap ? "word" : "none",
191
+ _v$4 = props.shrink ? 1 : 0,
192
+ _v$5 = props.onUp;
193
+ _v$ !== _p$.e && (_p$.e = _$setProp(_el$, "fg", _v$, _p$.e));
194
+ _v$2 !== _p$.t && (_p$.t = _$setProp(_el$, "attributes", _v$2, _p$.t));
195
+ _v$3 !== _p$.a && (_p$.a = _$setProp(_el$, "wrapMode", _v$3, _p$.a));
196
+ _v$4 !== _p$.o && (_p$.o = _$setProp(_el$, "flexShrink", _v$4, _p$.o));
197
+ _v$5 !== _p$.i && (_p$.i = _$setProp(_el$, "onMouseUp", _v$5, _p$.i));
198
+ return _p$;
199
+ }, {
200
+ e: undefined,
201
+ t: undefined,
202
+ a: undefined,
203
+ o: undefined,
204
+ i: undefined
205
+ });
206
+ return _el$;
207
+ })();
208
+ }
209
+
210
+ /** A window tab's option line: title, ‹ value ›, value ▸ or a tick, color swatches, then a note. */
211
+ export function OptionRow(props) {
212
+ const line = props.line;
213
+ const fg = () => props.active ? props.theme.text.action.primary.focused : props.theme.text.base;
214
+ const arrow = () => props.active ? fg() : props.theme.text.action.primary.selected;
215
+ const note = () => line.note?.() ?? "";
216
+ const columns = () => lineColumns(props.width, props.valueWidth);
217
+ /** Where the value starts: past the 3 spaces, the title, its space and the "‹ ". */
218
+ const valueColumn = () => 3 + columns().title + 1 + 2;
219
+ const noteInline = () => {
220
+ if (props.width === undefined) return true;
221
+ const swatches = 3 * (line.swatches?.() ?? []).length;
222
+ const end = valueColumn() + columns().value + 2 + swatches;
223
+ return end + 3 + columnsOf(note()) <= props.width;
224
+ };
225
+ const indent = " ".repeat(line.depth ?? 0);
226
+ // A tick without a word has the value's room too, so a long name shows whole.
227
+ const titleWidth = () => line.tick && !line.value() ? columns().title + 2 + columns().value : columns().title;
228
+ /** On the selected line's highlight, the highlight's text color; under it, its own color. */
229
+ const noteColor = onHighlight => props.active && onHighlight ? fg() : line.warning ? props.theme.text.feedback.warning.base : props.theme.text.muted;
230
+ return [_$createComponent(Show, {
231
+ get when() {
232
+ return line.group;
233
+ },
234
+ get children() {
235
+ var _el$2 = _$createElement("box");
236
+ _$insert(_el$2, _$createComponent(Cell, {
237
+ get fg() {
238
+ return props.theme.text.action.primary.selected;
239
+ },
240
+ bold: true,
241
+ get children() {
242
+ return ` ${line.group}`;
243
+ }
244
+ }));
245
+ _$effect(_$p => _$setProp(_el$2, "paddingTop", props.first ? 0 : 1, _$p));
246
+ return _el$2;
247
+ }
248
+ }), _$createComponent(Show, {
249
+ get when() {
250
+ return line.gap;
251
+ },
252
+ get children() {
253
+ var _el$3 = _$createElement("box");
254
+ _$setProp(_el$3, "height", 1);
255
+ return _el$3;
256
+ }
257
+ }), (() => {
258
+ var _el$4 = _$createElement("box");
259
+ _$setProp(_el$4, "flexDirection", "row");
260
+ _$insert(_el$4, _$createComponent(Cell, {
261
+ get fg() {
262
+ return fg();
263
+ },
264
+ get onUp() {
265
+ return _$memo(() => !!line.tick)() ? props.click(props.use) : undefined;
266
+ },
267
+ get children() {
268
+ return ` ${indent}${fit(line.title, titleWidth() - indent.length)} `;
269
+ }
270
+ }), null);
271
+ _$insert(_el$4, _$createComponent(Cell, {
272
+ get fg() {
273
+ return arrow();
274
+ },
275
+ get onUp() {
276
+ return props.click(() => line.cycle?.(-1));
277
+ },
278
+ get children() {
279
+ return line.cycle && !line.tick ? "‹ " : " ";
280
+ }
281
+ }), null);
282
+ _$insert(_el$4, _$createComponent(Show, {
283
+ get when() {
284
+ return props.input;
285
+ },
286
+ get fallback() {
287
+ return _$createComponent(Cell, {
288
+ get fg() {
289
+ return _$memo(() => !!line.tick)() ? noteColor(true) : fg();
290
+ },
291
+ get onUp() {
292
+ return props.click(props.use);
293
+ },
294
+ get children() {
295
+ return fit(line.value(), columns().value);
296
+ }
297
+ });
298
+ },
299
+ get children() {
300
+ return props.input?.(columns().value);
301
+ }
302
+ }), null);
303
+ _$insert(_el$4, _$createComponent(Cell, {
304
+ get fg() {
305
+ return arrow();
306
+ },
307
+ get onUp() {
308
+ return props.click(props.use);
309
+ },
310
+ get children() {
311
+ return _$memo(() => !!line.run)() ? " ▸" : line.cycle && !line.tick ? " ›" : " ";
312
+ }
313
+ }), null);
314
+ _$insert(_el$4, _$createComponent(Show, {
315
+ get when() {
316
+ return line.swatches;
317
+ },
318
+ get children() {
319
+ return _$createComponent(Cell, {
320
+ get children() {
321
+ return (line.swatches?.() ?? []).map(color => (() => {
322
+ var _el$8 = _$createElement("span");
323
+ _$insertNode(_el$8, _$createTextNode(` ██`));
324
+ _$setProp(_el$8, "style", {
325
+ fg: color
326
+ });
327
+ return _el$8;
328
+ })());
329
+ }
330
+ });
331
+ }
332
+ }), null);
333
+ _$insert(_el$4, _$createComponent(Show, {
334
+ get when() {
335
+ return _$memo(() => !!note())() && noteInline();
336
+ },
337
+ get children() {
338
+ var _el$5 = _$createElement("box");
339
+ _$setProp(_el$5, "paddingLeft", 3);
340
+ _$setProp(_el$5, "flexShrink", 1);
341
+ _$insert(_el$5, _$createComponent(Cell, {
342
+ get fg() {
343
+ return noteColor(true);
344
+ },
345
+ shrink: true,
346
+ wrap: true,
347
+ get children() {
348
+ return note();
349
+ }
350
+ }));
351
+ return _el$5;
352
+ }
353
+ }), null);
354
+ _$effect(_p$ => {
355
+ var _v$6 = boxId(line.id),
356
+ _v$7 = props.active ? props.theme.background.action.primary.focused : TRANSPARENT,
357
+ _v$8 = props.press;
358
+ _v$6 !== _p$.e && (_p$.e = _$setProp(_el$4, "id", _v$6, _p$.e));
359
+ _v$7 !== _p$.t && (_p$.t = _$setProp(_el$4, "backgroundColor", _v$7, _p$.t));
360
+ _v$8 !== _p$.a && (_p$.a = _$setProp(_el$4, "onMouseDown", _v$8, _p$.a));
361
+ return _p$;
362
+ }, {
363
+ e: undefined,
364
+ t: undefined,
365
+ a: undefined
366
+ });
367
+ return _el$4;
368
+ })(), _$createComponent(Show, {
369
+ get when() {
370
+ return _$memo(() => !!note())() && !noteInline();
371
+ },
372
+ get children() {
373
+ var _el$6 = _$createElement("box");
374
+ _$insert(_el$6, _$createComponent(Cell, {
375
+ get fg() {
376
+ return noteColor(false);
377
+ },
378
+ shrink: true,
379
+ wrap: true,
380
+ get children() {
381
+ return note();
382
+ }
383
+ }));
384
+ _$effect(_p$ => {
385
+ var _v$9 = valueColumn(),
386
+ _v$0 = props.width;
387
+ _v$9 !== _p$.e && (_p$.e = _$setProp(_el$6, "paddingLeft", _v$9, _p$.e));
388
+ _v$0 !== _p$.t && (_p$.t = _$setProp(_el$6, "width", _v$0, _p$.t));
389
+ return _p$;
390
+ }, {
391
+ e: undefined,
392
+ t: undefined
393
+ });
394
+ return _el$6;
395
+ }
396
+ }), _$createComponent(Show, {
397
+ get when() {
398
+ return line.detail;
399
+ },
400
+ get children() {
401
+ var _el$7 = _$createElement("box");
402
+ _$insert(_el$7, _$createComponent(Cell, {
403
+ get fg() {
404
+ return props.theme.text.muted;
405
+ },
406
+ shrink: true,
407
+ wrap: true,
408
+ get children() {
409
+ return line.detail;
410
+ }
411
+ }));
412
+ _$effect(_p$ => {
413
+ var _v$1 = valueColumn(),
414
+ _v$10 = props.width;
415
+ _v$1 !== _p$.e && (_p$.e = _$setProp(_el$7, "paddingLeft", _v$1, _p$.e));
416
+ _v$10 !== _p$.t && (_p$.t = _$setProp(_el$7, "width", _v$10, _p$.t));
417
+ return _p$;
418
+ }, {
419
+ e: undefined,
420
+ t: undefined
421
+ });
422
+ return _el$7;
423
+ }
424
+ })];
425
+ }
426
+ export function createSettingsEditor(api, display, showToast) {
427
+ const [tab, setTabNow] = createSignal();
428
+ const [selected, setSelected] = createSignal("");
429
+ const [typing, setTyping] = createSignal();
430
+ const [confirming, setConfirming] = createSignal(false);
431
+ const [sidebars, setSidebars] = createSignal(0);
432
+ const [dragging, setDragging] = createSignal();
433
+ let draggedSincePress = false;
434
+ let lastPress = {
435
+ id: "",
436
+ atMs: 0
437
+ };
438
+ /** The inline input while a line takes typing; its keys work only while it has the keyboard. */
439
+ let typingInput;
440
+ const treeLines = new Map();
441
+ const theme = () => api.theme;
442
+ const shown = () => display.shown();
443
+ const server = display.server;
444
+ const dirty = server.dirty;
445
+ const discard = server.discard;
446
+ const lineValue = path => server.value(path);
447
+ function setValues(values) {
448
+ for (const [path, value] of Object.entries(values)) server.set(path, value);
449
+ }
450
+ function resetTabLines(settingsTab) {
451
+ display.edit(settings => resetTab(settings, settingsTab));
452
+ if (settingsTab === "providers") server.set(PROVIDERS_KEY, []);
453
+ }
454
+
455
+ /** `run` as a click handler that skips the click OpenCode sends right after a drag. */
456
+ const click = run => () => {
457
+ if (!draggedSincePress) run();
458
+ };
459
+
460
+ /** Two presses on the same line within 400 ms. */
461
+ function isDoubleClick(id) {
462
+ const now = Date.now();
463
+ const double = lastPress.id === id && now - lastPress.atMs < DOUBLE_CLICK_MS;
464
+ lastPress = double ? {
465
+ id: "",
466
+ atMs: 0
467
+ } : {
468
+ id,
469
+ atMs: now
470
+ };
471
+ return double;
472
+ }
473
+ function editSurface(surface, change) {
474
+ const rows = change(shown().surfaces[surface]);
475
+ server.set(`${surface}.show`, rows.enabled);
476
+ server.set(`${surface}.hidden`, rows.hidden);
477
+ server.set(`${surface}.providerOrder`, rows.providerOrder);
478
+ server.set(`${surface}.rowOrder`, rows.rowOrder);
479
+ }
480
+ function toggleSurface(surface) {
481
+ editSurface(surface, rows => ({
482
+ ...rows,
483
+ enabled: !rows.enabled
484
+ }));
485
+ }
486
+
487
+ /** What typing into a line does: a color for a color line, a number for a server number. */
488
+ function typedValue(field, role) {
489
+ if (role) {
490
+ return {
491
+ placeholder: "#rrggbb",
492
+ hint: "Type a color like #89b4fa, then enter · enter with nothing typed = the theme's color · esc stop",
493
+ apply: text => display.edit(settings => typedColor(settings, field, text))
494
+ };
495
+ }
496
+ const placeholder = field.placeholder;
497
+ if (!placeholder) return undefined;
498
+ return {
499
+ placeholder,
500
+ hint: `Type ${placeholder}, then enter · enter with nothing typed = ${field.show(null)} · esc stop`,
501
+ apply: text => {
502
+ const value = typedNumber(field, text);
503
+ if (value !== undefined) server.set(field.path, value);
504
+ }
505
+ };
506
+ }
507
+
508
+ /** A field's line: ‹ › step through its values, or you type one. */
509
+ function fieldLine(field) {
510
+ const role = field.color ? field.path.slice("colors.".length) : undefined;
511
+ const value = () => lineValue(field.path);
512
+ return {
513
+ id: field.path,
514
+ group: field.group,
515
+ title: field.title,
516
+ depth: field.provider ? 1 : 0,
517
+ value: () => field.show(value()),
518
+ cycle: field.values.length > 0 ? delta => {
519
+ const values = field.choices?.(shown()) ?? field.values;
520
+ setValues({
521
+ [field.path]: stepIn(values, value(), delta)
522
+ });
523
+ } : undefined,
524
+ typed: typedValue(field, role),
525
+ note: () => field.preset && presetChoice(field.preset, lineValue) !== undefined ? "from the preset" : field.note ?? "",
526
+ swatches: role ? () => [roleColor(theme(), shown(), role, 60)] : undefined
527
+ };
528
+ }
529
+ function presetLine(name) {
530
+ const choice = () => presetChoice(name, lineValue);
531
+ return {
532
+ id: `preset.${name}`,
533
+ title: PRESETS[name].title,
534
+ value: () => choice() ?? "your own",
535
+ cycle: delta => setValues(presetValues(name, choice(), delta)),
536
+ note: () => `sets ${PRESETS[name].drives}`
537
+ };
538
+ }
539
+
540
+ /**
541
+ * OpenCode's own theme list and light/dark switch; quota's colors follow them. `refocus` gives
542
+ * the window the keyboard again.
543
+ */
544
+ function themeLines(refocus) {
545
+ return [{
546
+ id: "theme",
547
+ group: "OpenCode theme",
548
+ title: "Theme",
549
+ value: () => "open the theme list",
550
+ run: () => api.keymap.dispatch("theme.switch"),
551
+ swatches: () => COLOR_NAMES.map(name => namedColor(theme(), name)),
552
+ note: () => "↑↓ shows each theme live · enter keeps it · esc puts it back"
553
+ }, {
554
+ id: "themeMode",
555
+ title: "Light or dark",
556
+ value: () => api.themeMode ?? "dark",
557
+ cycle: () => {
558
+ api.keymap.dispatch("theme.switch_mode");
559
+ // OpenCode's switch also closes its dialogs, which gives the keyboard to whatever had
560
+ // it before the last dialog opened (the message box); take it back after that.
561
+ setTimeout(refocus, 50);
562
+ },
563
+ note: () => "some themes have only one"
564
+ }];
565
+ }
566
+
567
+ /**
568
+ * A custom provider's switch, its web address and the key it would send; marked when the server
569
+ * would not switch it on because it changed since the window showed it.
570
+ */
571
+ function customLine(entry, first) {
572
+ const on = () => server.customOn(entry.id);
573
+ const request = entry.request;
574
+ const changed = server.changedSinceReview(entry.id);
575
+ const where = !request ? "a local estimate: sends nothing" : request.insecure ? `${request.url} plain http: the key travels unencrypted` : request.url;
576
+ return {
577
+ id: `custom.${entry.id}`,
578
+ group: first ? "Custom providers (added in settings.jsonc)" : undefined,
579
+ gap: !first,
580
+ title: entry.label,
581
+ value: () => on() ? "on" : "off",
582
+ cycle: () => server.switchCustom(entry.id, !on()),
583
+ note: () => changed ? `${CHANGED_SINCE_REVIEW} · ${where}` : where,
584
+ warning: changed || request?.insecure,
585
+ detail: request ? `key: ${request.key}` : undefined
586
+ };
587
+ }
588
+
589
+ /**
590
+ * The custom providers' switches (on top: an agent sends the user here to switch one on), which
591
+ * providers quota checks (ticks, with Cursor's and OpenCode Zen's settings nested; the ones
592
+ * quota found first), then the other groups.
593
+ */
594
+ function providerLines(snapshot) {
595
+ const loaded = server.saved();
596
+ if (!loaded) return [];
597
+ const found = foundProviderIds(snapshot);
598
+ const off = () => server.value(PROVIDERS_KEY);
599
+ const savedOff = loaded.values[PROVIDERS_KEY];
600
+ const ordered = [...loaded.providers.filter(({
601
+ id
602
+ }) => found.includes(id)), ...loaded.providers.filter(({
603
+ id
604
+ }) => !found.includes(id))];
605
+ const ticks = ordered.flatMap(({
606
+ id,
607
+ label
608
+ }) => {
609
+ const ticked = isTicked(off(), id);
610
+ const tick = {
611
+ id: `provider.${id}`,
612
+ group: id === ordered[0]?.id ? "Which providers" : undefined,
613
+ title: `${ticked ? "[x]" : "[ ]"} ${label}`,
614
+ tick: true,
615
+ warning: true,
616
+ // The tick says on or off; only a saved tick quota can't use says more (a tick not
617
+ // saved yet is not checked yet).
618
+ value: () => ticked && isTicked(savedOff, id) && snapshot && !found.includes(id) ? "not set up" : "",
619
+ cycle: () => server.set(PROVIDERS_KEY, withTick(off(), id, !ticked))
620
+ };
621
+ const nested = ticked ? FIELDS.filter(field => field.provider === id) : [];
622
+ return [tick, ...nested.map(fieldLine)];
623
+ });
624
+ return [...loaded.custom.map((entry, index) => customLine(entry, index === 0)), ...ticks, ...FIELDS.filter(field => field.tab === "providers" && !field.provider).map(fieldLine)];
625
+ }
626
+
627
+ /**
628
+ * Collapsed's and Status line's window for every provider without its own pick in the list
629
+ * below. ‹ › step through lowest and the windows the providers have.
630
+ */
631
+ function allProvidersLine(surface, snapshot) {
632
+ const current = () => shown()[surface].window[ALL_PROVIDERS] ?? "lowest";
633
+ const choices = () => {
634
+ const found = new Set((snapshot?.providers ?? []).flatMap(provider => provider.rows.flatMap(row => row.window && row.percentRemaining !== undefined ? [row.window] : [])));
635
+ const windows = Object.keys(WINDOWS).filter(window => found.has(window) || window === current());
636
+ return ["lowest", ...windows];
637
+ };
638
+ return {
639
+ id: `${surface}.window.${ALL_PROVIDERS}`,
640
+ group: "Window",
641
+ title: "For all providers",
642
+ value: () => windowTitle(current()),
643
+ cycle: delta => {
644
+ const next = stepIn(choices(), current(), delta);
645
+ display.edit(settings => setIn(settings, [surface, "window", ALL_PROVIDERS], next === "lowest" ? undefined : next));
646
+ },
647
+ note: () => "a pick below wins; a provider without it shows its lowest"
648
+ };
649
+ }
650
+
651
+ /**
652
+ * A Settings page's lines. A preset sits above the line it names, under that line's heading,
653
+ * or else first, under "Preset". `refocus` gives the window the keyboard again.
654
+ */
655
+ function optionLines(settingsTab, snapshot, refocus = () => {}) {
656
+ if (settingsTab === "providers") return providerLines(snapshot);
657
+ if (!server.saved()) return [];
658
+ const presets = Object.keys(PRESETS).filter(name => PRESETS[name].tab === settingsTab);
659
+ const fields = FIELDS.filter(field => field.tab === settingsTab).flatMap(field => {
660
+ const line = fieldLine(field);
661
+ const preset = presets.find(name => PRESETS[name].before === field.path);
662
+ return preset ? [{
663
+ ...presetLine(preset),
664
+ group: line.group
665
+ }, {
666
+ ...line,
667
+ group: undefined
668
+ }] : [line];
669
+ });
670
+ return [...presets.filter(name => PRESETS[name].before === undefined).map(name => ({
671
+ ...presetLine(name),
672
+ group: "Preset"
673
+ })), ...(settingsTab === "colors" ? themeLines(refocus) : []), ...fields, ...(settingsTab === "collapsed" || settingsTab === "statusLine" ? [allProvidersLine(settingsTab, snapshot)] : [])];
674
+ }
675
+ function firstLine(settingsTab) {
676
+ if (settingsTab === undefined) return "";
677
+ if (pagesOf(settingsTab)) return PAGES_ID;
678
+ return isSurfaceTab(settingsTab) ? SWITCH_ID : optionLines(settingsTab)[0]?.id ?? "";
679
+ }
680
+
681
+ /** Reads the file settings each time a Settings tab shows. */
682
+ async function loadServer(settingsTab) {
683
+ try {
684
+ await server.load();
685
+ } catch (error) {
686
+ api.ui.toast.show({
687
+ variant: "error",
688
+ title: "Quota settings not loaded",
689
+ message: rpcErrorMessage(error)
690
+ });
691
+ return;
692
+ }
693
+ if (tab() === settingsTab && selected() === "") setSelected(firstLine(settingsTab));
694
+ }
695
+ function Button(props) {
696
+ const {
697
+ text,
698
+ background
699
+ } = theme();
700
+ return (() => {
701
+ var _el$0 = _$createElement("box");
702
+ _$setProp(_el$0, "paddingLeft", 2);
703
+ _$setProp(_el$0, "paddingRight", 2);
704
+ _$setProp(_el$0, "flexShrink", 0);
705
+ _$setProp(_el$0, "alignSelf", "flex-start");
706
+ _$insert(_el$0, _$createComponent(Cell, {
707
+ get fg() {
708
+ return _$memo(() => !!props.primary)() ? text.action.primary.focused : text.base;
709
+ },
710
+ get children() {
711
+ return props.label;
712
+ }
713
+ }));
714
+ _$effect(_p$ => {
715
+ var _v$11 = props.primary ? background.action.primary.focused : background.raised.high,
716
+ _v$12 = click(props.run);
717
+ _v$11 !== _p$.e && (_p$.e = _$setProp(_el$0, "backgroundColor", _v$11, _p$.e));
718
+ _v$12 !== _p$.t && (_p$.t = _$setProp(_el$0, "onMouseUp", _v$12, _p$.t));
719
+ return _p$;
720
+ }, {
721
+ e: undefined,
722
+ t: undefined
723
+ });
724
+ return _el$0;
725
+ })();
726
+ }
727
+ function previewToast(host, sessionID) {
728
+ const settings = shown();
729
+ const snapshot = host.quota.snapshot(sessionID);
730
+ if (!snapshot || !settings.surfaces.toast.enabled) return;
731
+ const lines = quotaToastLines(snapshot, settings, Date.now(), api.renderer.width);
732
+ const message = plainMessage(lines);
733
+ if (!message) return;
734
+ const duration = settings.toast.seconds * 1000;
735
+ showToast({
736
+ variant: "info",
737
+ message,
738
+ duration
739
+ }, lines);
740
+ }
741
+
742
+ /**
743
+ * Layout's pages, left of the body (`rail.tsx`). A click shows a page and gives the list the
744
+ * keyboard.
745
+ */
746
+ function Pages(props) {
747
+ return _$createComponent(Show, {
748
+ get when() {
749
+ return pagesOf(props.tab);
750
+ },
751
+ children: pages => _$createComponent(Rail, {
752
+ get items() {
753
+ return pages().map(page => ({
754
+ key: page,
755
+ label: pageTitle(page),
756
+ id: pageId(page)
757
+ }));
758
+ },
759
+ get chosen() {
760
+ return props.tab;
761
+ },
762
+ get theme() {
763
+ return theme();
764
+ },
765
+ gap: PAGE_LIST_GAP,
766
+ pick: page => click(() => {
767
+ props.showPage(page);
768
+ setSelected(PAGES_ID);
769
+ })()
770
+ })
771
+ });
772
+ }
773
+
774
+ /**
775
+ * Above a Settings tab's scrolling body: the surface switch under its "Enable/disable" heading,
776
+ * and a warning when the sidebar is hidden.
777
+ */
778
+ function Header(props) {
779
+ const info = () => SETTINGS_TABS.find(item => item.tab === props.tab) ?? SETTINGS_TABS[0];
780
+ const surface = () => isSurfaceTab(props.tab) ? props.tab : undefined;
781
+ const surfaceOn = () => {
782
+ const current = surface();
783
+ return current === undefined || shown().surfaces[current].enabled;
784
+ };
785
+ const sidebarHidden = () => info().watchesSidebar && sidebars() === 0;
786
+ const active = () => selected() === SWITCH_ID;
787
+ return _$createComponent(Show, {
788
+ get when() {
789
+ return surface() || sidebarHidden();
790
+ },
791
+ get children() {
792
+ var _el$1 = _$createElement("box");
793
+ _$setProp(_el$1, "flexDirection", "column");
794
+ _$setProp(_el$1, "flexShrink", 0);
795
+ _$setProp(_el$1, "marginBottom", 1);
796
+ _$insert(_el$1, _$createComponent(Show, {
797
+ get when() {
798
+ return surface();
799
+ },
800
+ get children() {
801
+ return _$createComponent(Cell, {
802
+ get fg() {
803
+ return theme().text.action.primary.selected;
804
+ },
805
+ bold: true,
806
+ children: " Enable/disable"
807
+ });
808
+ }
809
+ }), null);
810
+ _$insert(_el$1, _$createComponent(Show, {
811
+ get when() {
812
+ return surface();
813
+ },
814
+ children: current => (() => {
815
+ var _el$13 = _$createElement("box");
816
+ _$setProp(_el$13, "flexShrink", 0);
817
+ _$setProp(_el$13, "onMouseDown", () => setSelected(SWITCH_ID));
818
+ _$insert(_el$13, _$createComponent(Cell, {
819
+ get fg() {
820
+ return _$memo(() => !!active())() ? theme().text.action.primary.focused : theme().text.base;
821
+ },
822
+ bold: true,
823
+ get children() {
824
+ return ` ${surfaceOn() ? "[x]" : "[ ]"} ${info().switchTitle}`;
825
+ }
826
+ }));
827
+ _$effect(_p$ => {
828
+ var _v$13 = boxId(SWITCH_ID),
829
+ _v$14 = active() ? theme().background.action.primary.focused : TRANSPARENT,
830
+ _v$15 = click(() => toggleSurface(current()));
831
+ _v$13 !== _p$.e && (_p$.e = _$setProp(_el$13, "id", _v$13, _p$.e));
832
+ _v$14 !== _p$.t && (_p$.t = _$setProp(_el$13, "backgroundColor", _v$14, _p$.t));
833
+ _v$15 !== _p$.a && (_p$.a = _$setProp(_el$13, "onMouseUp", _v$15, _p$.a));
834
+ return _p$;
835
+ }, {
836
+ e: undefined,
837
+ t: undefined,
838
+ a: undefined
839
+ });
840
+ return _el$13;
841
+ })()
842
+ }), null);
843
+ _$insert(_el$1, _$createComponent(Show, {
844
+ get when() {
845
+ return sidebarHidden();
846
+ },
847
+ get children() {
848
+ var _el$10 = _$createElement("box"),
849
+ _el$11 = _$createElement("text");
850
+ _$insertNode(_el$10, _el$11);
851
+ _$setProp(_el$10, "paddingLeft", 3);
852
+ _$setProp(_el$10, "flexDirection", "row");
853
+ _$setProp(_el$10, "gap", 2);
854
+ _$setProp(_el$10, "flexShrink", 0);
855
+ _$insertNode(_el$11, _$createTextNode(`The sidebar is hidden, so there is nothing to watch here.`));
856
+ _$setProp(_el$11, "wrapMode", "word");
857
+ _$setProp(_el$11, "selectable", false);
858
+ _$setProp(_el$11, "flexShrink", 1);
859
+ _$insert(_el$10, _$createComponent(Button, {
860
+ label: "Show sidebar",
861
+ run: () => {
862
+ api.keymap.dispatch("session.sidebar.toggle");
863
+ setTimeout(props.refocus, 50);
864
+ }
865
+ }), null);
866
+ _$effect(_$p => _$setProp(_el$11, "fg", theme().text.feedback.warning.base, _$p));
867
+ return _el$10;
868
+ }
869
+ }), null);
870
+ return _el$1;
871
+ }
872
+ });
873
+ }
874
+
875
+ /**
876
+ * A Settings tab's lines: its options, then the surface's providers (and rows) as a tree.
877
+ * `showPage` shows another of Layout's pages.
878
+ */
879
+ function Body(props) {
880
+ /** The box with only the tree lines, so the drag math counts lines from its top. */
881
+ let list;
882
+ let dragId;
883
+ const surface = () => isSurfaceTab(props.tab) ? props.tab : undefined;
884
+ const withRows = () => props.tab === "sidebar" || props.tab === "toast";
885
+ const snapshot = () => props.host.quota.snapshot(props.sessionID);
886
+ const words = () => snapshot()?.words ?? DEFAULT_WORDS;
887
+ /** The picked windows of Collapsed or Status line. */
888
+ const windows = () => shown()[props.tab === "statusLine" ? "statusLine" : "collapsed"].window;
889
+ /** The providers and rows hidden on this page. */
890
+ const hiddenIds = () => {
891
+ const current = surface();
892
+ return current ? shown().surfaces[current].hidden : [];
893
+ };
894
+ const tree = () => {
895
+ const current = surface();
896
+ const loaded = snapshot();
897
+ return current && loaded ? surfaceTree(loaded, shown().surfaces[current]) : [];
898
+ };
899
+ const options = createMemo(() => optionLines(props.tab, snapshot(), () => props.box()?.focus()));
900
+ const lines = createMemo(() => tree().flatMap(({
901
+ provider,
902
+ rowIds
903
+ }) => [treeLine(provider.providerId, provider.providerId, false), ...(withRows() ? rowIds.map(id => treeLine(id, provider.providerId, true)) : [])]));
904
+ const selectedOption = () => options().find(line => line.id === selected());
905
+ const selectedLine = () => lines().find(line => lineKey(line.id) === selected());
906
+ function treeLine(id, providerId, row) {
907
+ const key = `${row ? "row" : "provider"}:${id}`;
908
+ const line = treeLines.get(key) ?? {
909
+ id,
910
+ providerId,
911
+ row
912
+ };
913
+ treeLines.set(key, line);
914
+ return line;
915
+ }
916
+
917
+ /**
918
+ * ↑↓ select the next line; past the first or last one they scroll. In Layout's page list
919
+ * they show the page above or below.
920
+ */
921
+ function select(delta) {
922
+ if (selected() === PAGES_ID) {
923
+ stepPage(delta);
924
+ return;
925
+ }
926
+ const ids = [...(pagesOf(props.tab) ? [PAGES_ID] : []), ...(surface() ? [SWITCH_ID] : []), ...options().map(line => line.id), ...lines().map(line => lineKey(line.id))];
927
+ const next = ids.indexOf(selected()) + delta;
928
+ if (next < 0 || next >= ids.length) props.scroll()?.scrollBy(delta);else setSelected(ids[next]);
929
+ }
930
+ function toggleHidden(id) {
931
+ const current = surface();
932
+ if (!current) return;
933
+ editSurface(current, rows => {
934
+ const hidden = rows.hidden.includes(id);
935
+ return {
936
+ ...rows,
937
+ hidden: hidden ? rows.hidden.filter(item => item !== id) : [...rows.hidden, id]
938
+ };
939
+ });
940
+ }
941
+ function cycleWindow(providerId, delta) {
942
+ const provider = tree().find(item => item.provider.providerId === providerId)?.provider;
943
+ const choices = provider ? windowChoices(provider, hiddenIds()) : [];
944
+ if (choices.length === 0) return;
945
+ const inherited = inheritedWindow(windows(), choices);
946
+ const next = stepIn(choices, windows()[providerId] ?? inherited, delta);
947
+ // The window it would show anyway is no pick of its own, so it follows "For all providers".
948
+ display.edit(settings => setIn(settings, [props.tab === "statusLine" ? "statusLine" : "collapsed", "window", providerId], next === inherited ? undefined : next));
949
+ }
950
+ function move(delta) {
951
+ const current = surface();
952
+ const line = selectedLine();
953
+ if (current && line) editSurface(current, rows => movedBy(tree(), rows, line.id, delta));
954
+ }
955
+ function ownRow(line) {
956
+ return tree().find(item => item.provider.providerId === line.providerId)?.provider.rows.find(row => row.id === line.id);
957
+ }
958
+
959
+ /** e or a double-click: type a color, or rename a row. */
960
+ function startTyping() {
961
+ const option = selectedOption();
962
+ if (option?.typed) {
963
+ setTyping({
964
+ id: option.id,
965
+ value: "",
966
+ ...option.typed
967
+ });
968
+ return;
969
+ }
970
+ const line = selectedLine();
971
+ const row = line?.row ? ownRow(line) : undefined;
972
+ if (!line || !row) return;
973
+ setTyping({
974
+ id: lineKey(line.id),
975
+ value: "",
976
+ placeholder: shown()[props.tab === "toast" ? "toast" : "sidebar"].names[line.id] ?? row.label,
977
+ hint: `Type a new name, then enter · enter with nothing typed = its own name ("${row.label}") · esc stop`,
978
+ apply: text => display.edit(settings => renameRow(settings, props.tab === "toast" ? "toast" : "sidebar", line.id, text))
979
+ });
980
+ }
981
+ function stopTyping() {
982
+ setTyping(undefined);
983
+ props.box()?.focus();
984
+ }
985
+ function commitTyping() {
986
+ const current = typing();
987
+ current?.apply(current.value);
988
+ stopTyping();
989
+ }
990
+
991
+ /** ↑↓ in Layout's page list: the page above or below this one, shown at once. */
992
+ function stepPage(delta) {
993
+ const pages = pagesOf(props.tab) ?? [];
994
+ const next = pages[pages.indexOf(props.tab) + delta];
995
+ if (next) props.showPage(next);
996
+ }
997
+
998
+ /** →, enter or space in Layout's page list: the page's first line, its switch or first option. */
999
+ function toFirstLine() {
1000
+ const first = surface() ? SWITCH_ID : options()[0]?.id;
1001
+ if (first) setSelected(first);
1002
+ }
1003
+
1004
+ /**
1005
+ * Space or enter: to the page's lines from the page list, flip a switch, run a button, next
1006
+ * value, or show/hide a line.
1007
+ */
1008
+ function activate() {
1009
+ const current = surface();
1010
+ const option = selectedOption();
1011
+ const line = selectedLine();
1012
+ if (selected() === PAGES_ID) toFirstLine();else if (selected() === SWITCH_ID && current) toggleSurface(current);else if (option) useOption(option);else if (line) toggleHidden(line.id);
1013
+ }
1014
+
1015
+ /** A click on an option's value: run its button, its next value, or start typing. */
1016
+ function useOption(option) {
1017
+ if (option.run) option.run();else if (option.cycle) option.cycle(1);else startTyping();
1018
+ }
1019
+
1020
+ /** ←/→ change the selected line's value; → in the page list goes to the page's lines. */
1021
+ function sideways(delta) {
1022
+ const option = selectedOption();
1023
+ const line = selectedLine();
1024
+ if (selected() === PAGES_ID) {
1025
+ if (delta > 0) toFirstLine();
1026
+ } else if (option) option.cycle?.(delta);else if (line && !line.row) cycleWindow(line.providerId, delta);
1027
+ }
1028
+
1029
+ /** A provider moves with all its rows; a row moves only among its own provider's rows. */
1030
+ function onDrag(event) {
1031
+ const current = surface();
1032
+ const id = dragId;
1033
+ if (!current || !id || !list || typing()) return;
1034
+ draggedSincePress = true;
1035
+ setDragging(id);
1036
+ // Dragging onto the top or bottom line of a list that scrolls moves it one line.
1037
+ const scroll = props.scroll();
1038
+ if (scroll && event.y <= scroll.y) scroll.scrollBy(-1);else if (scroll && event.y >= scroll.y + scroll.height - 1) scroll.scrollBy(1);
1039
+ // list.y already includes the scroll offset, so this counts lines from the first line.
1040
+ const pointer = event.y - list.y;
1041
+ editSurface(current, rows => draggedTo(tree(), rows, id, pointer, withRows()));
1042
+ }
1043
+
1044
+ // On the Toast tab the real toast shows again after every change of what it shows.
1045
+ createEffect(on(() => {
1046
+ return props.tab === "toast" && JSON.stringify(shown().toast);
1047
+ }, key => {
1048
+ if (key) previewToast(props.host, props.sessionID);
1049
+ }));
1050
+ // Keep the selected line in view when the list is taller than its room.
1051
+ createEffect(on(selected, id => {
1052
+ queueMicrotask(() => props.scroll()?.scrollChildIntoView(boxId(id)));
1053
+ }));
1054
+
1055
+ // Keys work only while the window has the keyboard; they win over the window's own.
1056
+ api.keymap.layer(() => ({
1057
+ target: props.box,
1058
+ priority: 11,
1059
+ enabled: () => typing() === undefined && !confirming(),
1060
+ commands: [{
1061
+ bind: "up",
1062
+ title: "Previous line",
1063
+ group: KEYS,
1064
+ run: () => select(-1)
1065
+ }, {
1066
+ bind: "down",
1067
+ title: "Next line",
1068
+ group: KEYS,
1069
+ run: () => select(1)
1070
+ }, {
1071
+ bind: "shift+up",
1072
+ title: "Move up",
1073
+ group: KEYS,
1074
+ run: () => move(-1)
1075
+ }, {
1076
+ bind: "shift+down",
1077
+ title: "Move down",
1078
+ group: KEYS,
1079
+ run: () => move(1)
1080
+ }, {
1081
+ bind: "alt+up",
1082
+ title: "Move up",
1083
+ group: KEYS,
1084
+ run: () => move(-1)
1085
+ }, {
1086
+ bind: "alt+down",
1087
+ title: "Move down",
1088
+ group: KEYS,
1089
+ run: () => move(1)
1090
+ }, {
1091
+ bind: "space",
1092
+ title: "Use the line",
1093
+ group: KEYS,
1094
+ run: activate
1095
+ }, {
1096
+ bind: "return",
1097
+ title: "Use the line",
1098
+ group: KEYS,
1099
+ run: activate
1100
+ }, {
1101
+ bind: "e",
1102
+ title: "Type a value or rename a row",
1103
+ group: KEYS,
1104
+ run: startTyping
1105
+ }, {
1106
+ bind: "left",
1107
+ title: "Previous value",
1108
+ group: KEYS,
1109
+ run: () => sideways(-1)
1110
+ }, {
1111
+ bind: "right",
1112
+ title: "Next value",
1113
+ group: KEYS,
1114
+ run: () => sideways(1)
1115
+ }, {
1116
+ bind: "ctrl+r",
1117
+ title: "Reset this tab or page",
1118
+ group: KEYS,
1119
+ run: () => resetTabLines(props.tab)
1120
+ }]
1121
+ }));
1122
+ // While typing, the input has the keyboard: Esc only stops typing, Enter keeps the text.
1123
+ api.keymap.layer(() => ({
1124
+ target: () => typingInput,
1125
+ priority: 20,
1126
+ enabled: () => typing() !== undefined,
1127
+ commands: [{
1128
+ bind: "escape",
1129
+ title: "Stop typing",
1130
+ group: KEYS,
1131
+ run: stopTyping
1132
+ }, {
1133
+ bind: "return",
1134
+ title: "Keep it",
1135
+ group: KEYS,
1136
+ run: commitTyping
1137
+ }]
1138
+ }));
1139
+ function TypingInput(inputProps) {
1140
+ return (() => {
1141
+ var _el$14 = _$createElement("input");
1142
+ _$use(element => {
1143
+ typingInput = element;
1144
+ }, _el$14);
1145
+ _$setProp(_el$14, "flexShrink", 0);
1146
+ _$setProp(_el$14, "value", "");
1147
+ _$setProp(_el$14, "focused", true);
1148
+ _$setProp(_el$14, "onInput", value => {
1149
+ const current = typing();
1150
+ if (current) setTyping({
1151
+ ...current,
1152
+ value
1153
+ });
1154
+ });
1155
+ _$setProp(_el$14, "onSubmit", commitTyping);
1156
+ _$effect(_p$ => {
1157
+ var _v$16 = inputProps.width,
1158
+ _v$17 = inputProps.placeholder;
1159
+ _v$16 !== _p$.e && (_p$.e = _$setProp(_el$14, "width", _v$16, _p$.e));
1160
+ _v$17 !== _p$.t && (_p$.t = _$setProp(_el$14, "placeholder", _v$17, _p$.t));
1161
+ return _p$;
1162
+ }, {
1163
+ e: undefined,
1164
+ t: undefined
1165
+ });
1166
+ return _el$14;
1167
+ })();
1168
+ }
1169
+ function TreeRow(rowProps) {
1170
+ const line = rowProps.line;
1171
+ const key = lineKey(line.id);
1172
+ const entry = () => tree().find(item => item.provider.providerId === line.providerId);
1173
+ const rows = () => shown().surfaces[surface()];
1174
+ const active = () => selected() === key;
1175
+ // Dragging a provider carries its rows, so they light up with it.
1176
+ const lit = () => active() || dragging() === line.id || line.row && dragging() === line.providerId;
1177
+ const hidden = () => rows().hidden.includes(line.id);
1178
+ const {
1179
+ text
1180
+ } = theme();
1181
+ const fg = () => lit() ? text.action.primary.focused : !rows().enabled || hidden() || line.row && rows().hidden.includes(line.providerId) ? text.muted : text.base;
1182
+ /** Tree lines show which provider a row belongs to: ├ for a middle row, └ for the last. */
1183
+ const branch = () => {
1184
+ const rowIds = entry()?.rowIds ?? [];
1185
+ return !line.row ? "" : rowIds[rowIds.length - 1] === line.id ? " └ " : " ├ ";
1186
+ };
1187
+ const own = () => line.row ? ownRow(line) : undefined;
1188
+ const label = () => line.row ? shown()[props.tab === "toast" ? "toast" : "sidebar"].names[line.id] ?? own()?.label ?? line.id : entry()?.provider.label ?? line.id;
1189
+ const summary = row => {
1190
+ if (row.percentRemaining === undefined) return rowValueText(row);
1191
+ const reset = resetText(row, Date.now(), words());
1192
+ return `${percentText(words(), row.percentRemaining, true)}${reset ? ` · ${reset}` : ""}`;
1193
+ };
1194
+ const detail = () => {
1195
+ const provider = entry()?.provider;
1196
+ const row = own();
1197
+ if (row && shown()[props.tab === "toast" ? "toast" : "sidebar"].names[line.id] !== undefined) return `was "${row.label}"`;
1198
+ if (row?.prominence === "supplementary" && words().detail !== "detailed") {
1199
+ return "only with all rows";
1200
+ }
1201
+ if (row) return summary(row);
1202
+ if (!provider) return "";
1203
+ if (provider.error && provider.rows.length === 0) {
1204
+ return describeError(provider.error, provider.label, Date.now());
1205
+ }
1206
+ if (withRows()) return "";
1207
+ const rows = provider.rows.filter(item => !hiddenIds().includes(item.id));
1208
+ const picked = pickRow({
1209
+ rows: rows.map(item => ({
1210
+ row: item,
1211
+ label: item.label,
1212
+ named: false
1213
+ }))
1214
+ }, windowFor(windows(), provider.providerId));
1215
+ return picked ? summary(picked.row) : "";
1216
+ };
1217
+ const choices = () => {
1218
+ const provider = entry()?.provider;
1219
+ return !line.row && !withRows() && provider ? windowChoices(provider, hiddenIds()) : [];
1220
+ };
1221
+ /** Rows sit 4 columns further right, so their names get 4 fewer; the details line up. */
1222
+ const labelWidth = line.row ? 24 : 28;
1223
+ return (() => {
1224
+ var _el$15 = _$createElement("box");
1225
+ _$setProp(_el$15, "flexDirection", "row");
1226
+ _$setProp(_el$15, "onMouseDown", event => {
1227
+ if (event.button !== 0 || typing()) return;
1228
+ setSelected(key);
1229
+ dragId = line.id;
1230
+ if (line.row && isDoubleClick(key)) startTyping();
1231
+ });
1232
+ _$insert(_el$15, _$createComponent(Cell, {
1233
+ get fg() {
1234
+ return text.muted;
1235
+ },
1236
+ get children() {
1237
+ return ` ${branch()}`;
1238
+ }
1239
+ }), null);
1240
+ _$insert(_el$15, _$createComponent(Cell, {
1241
+ get fg() {
1242
+ return _$memo(() => !!lit())() ? fg() : text.action.primary.selected;
1243
+ },
1244
+ get children() {
1245
+ return api.renderer.useMouse === false ? "" : "⠿ ";
1246
+ }
1247
+ }), null);
1248
+ _$insert(_el$15, _$createComponent(Cell, {
1249
+ get fg() {
1250
+ return fg();
1251
+ },
1252
+ get onUp() {
1253
+ return click(() => toggleHidden(line.id));
1254
+ },
1255
+ get children() {
1256
+ return hidden() ? "[ ] " : "[x] ";
1257
+ }
1258
+ }), null);
1259
+ _$insert(_el$15, _$createComponent(Show, {
1260
+ get when() {
1261
+ return typing()?.id === key;
1262
+ },
1263
+ get fallback() {
1264
+ return _$createComponent(Cell, {
1265
+ get fg() {
1266
+ return fg();
1267
+ },
1268
+ get bold() {
1269
+ return !line.row;
1270
+ },
1271
+ get children() {
1272
+ return fit(label(), labelWidth);
1273
+ }
1274
+ });
1275
+ },
1276
+ get children() {
1277
+ return _$createComponent(TypingInput, {
1278
+ width: labelWidth,
1279
+ get placeholder() {
1280
+ return label();
1281
+ }
1282
+ });
1283
+ }
1284
+ }), null);
1285
+ _$insert(_el$15, _$createComponent(Show, {
1286
+ get when() {
1287
+ return choices().length > 0;
1288
+ },
1289
+ get fallback() {
1290
+ return _$createComponent(Cell, {
1291
+ get children() {
1292
+ return _$memo(() => !!withRows())() ? " " : " ".repeat(17);
1293
+ }
1294
+ });
1295
+ },
1296
+ get children() {
1297
+ return _$createComponent(Cell, {
1298
+ get fg() {
1299
+ return _$memo(() => !!active())() ? fg() : text.action.primary.selected;
1300
+ },
1301
+ get onUp() {
1302
+ return click(() => cycleWindow(line.providerId, 1));
1303
+ },
1304
+ get children() {
1305
+ return ` ‹ ${fit(windowTitle(windows()[line.providerId] ?? inheritedWindow(windows(), choices())), 11)} › `;
1306
+ }
1307
+ });
1308
+ }
1309
+ }), null);
1310
+ _$insert(_el$15, _$createComponent(Cell, {
1311
+ get fg() {
1312
+ return _$memo(() => !!lit())() ? fg() : text.muted;
1313
+ },
1314
+ shrink: true,
1315
+ get children() {
1316
+ return fit(detail(), 24);
1317
+ }
1318
+ }), null);
1319
+ _$effect(_p$ => {
1320
+ var _v$18 = boxId(key),
1321
+ _v$19 = lit() ? theme().background.action.primary.focused : TRANSPARENT;
1322
+ _v$18 !== _p$.e && (_p$.e = _$setProp(_el$15, "id", _v$18, _p$.e));
1323
+ _v$19 !== _p$.t && (_p$.t = _$setProp(_el$15, "backgroundColor", _v$19, _p$.t));
1324
+ return _p$;
1325
+ }, {
1326
+ e: undefined,
1327
+ t: undefined
1328
+ });
1329
+ return _el$15;
1330
+ })();
1331
+ }
1332
+ return (() => {
1333
+ var _el$16 = _$createElement("box"),
1334
+ _el$18 = _$createElement("box");
1335
+ _$insertNode(_el$16, _el$18);
1336
+ _$setProp(_el$16, "flexDirection", "column");
1337
+ _$insert(_el$16, _$createComponent(For, {
1338
+ get each() {
1339
+ return options();
1340
+ },
1341
+ children: (line, index) => _$createComponent(OptionRow, {
1342
+ line: line,
1343
+ get theme() {
1344
+ return theme();
1345
+ },
1346
+ get active() {
1347
+ return selected() === line.id;
1348
+ },
1349
+ get first() {
1350
+ return index() === 0;
1351
+ },
1352
+ get width() {
1353
+ return props.width;
1354
+ },
1355
+ click: click,
1356
+ press: event => {
1357
+ if (event.button !== 0 || typing()) return;
1358
+ setSelected(line.id);
1359
+ if (line.typed && isDoubleClick(line.id)) startTyping();
1360
+ },
1361
+ use: () => useOption(line),
1362
+ get input() {
1363
+ return typing()?.id === line.id ? width => _$createComponent(TypingInput, {
1364
+ width: width,
1365
+ get placeholder() {
1366
+ return line.typed?.placeholder ?? "";
1367
+ }
1368
+ }) : undefined;
1369
+ }
1370
+ })
1371
+ }), _el$18);
1372
+ _$insert(_el$16, _$createComponent(Show, {
1373
+ get when() {
1374
+ return _$memo(() => !!surface())() && !snapshot();
1375
+ },
1376
+ get children() {
1377
+ return _$createComponent(Cell, {
1378
+ get fg() {
1379
+ return theme().text.muted;
1380
+ },
1381
+ children: " Loading quota…"
1382
+ });
1383
+ }
1384
+ }), _el$18);
1385
+ _$insert(_el$16, _$createComponent(Show, {
1386
+ get when() {
1387
+ return !server.saved();
1388
+ },
1389
+ get children() {
1390
+ return _$createComponent(Cell, {
1391
+ get fg() {
1392
+ return theme().text.muted;
1393
+ },
1394
+ children: " Loading settings…"
1395
+ });
1396
+ }
1397
+ }), _el$18);
1398
+ _$insert(_el$16, _$createComponent(Show, {
1399
+ get when() {
1400
+ return _$memo(() => options().length > 0)() && lines().length > 0;
1401
+ },
1402
+ get children() {
1403
+ var _el$17 = _$createElement("box");
1404
+ _$setProp(_el$17, "height", 1);
1405
+ return _el$17;
1406
+ }
1407
+ }), _el$18);
1408
+ _$use(element => {
1409
+ list = element;
1410
+ }, _el$18);
1411
+ _$setProp(_el$18, "flexDirection", "column");
1412
+ _$setProp(_el$18, "onMouseDrag", onDrag);
1413
+ _$setProp(_el$18, "onMouseDragEnd", () => setDragging(undefined));
1414
+ _$setProp(_el$18, "onMouseUp", () => {
1415
+ dragId = undefined;
1416
+ });
1417
+ _$insert(_el$18, _$createComponent(For, {
1418
+ get each() {
1419
+ return lines();
1420
+ },
1421
+ children: line => _$createComponent(TreeRow, {
1422
+ line: line
1423
+ })
1424
+ }));
1425
+ _$effect(_$p => _$setProp(_el$16, "width", props.width, _$p));
1426
+ return _el$16;
1427
+ })();
1428
+ }
1429
+
1430
+ /**
1431
+ * The bottom bar of a Settings tab: Close, or Save and Discard, or the "Keep your changes?"
1432
+ * question, which also shows on the other tabs when closing asks it.
1433
+ */
1434
+ function Buttons(props) {
1435
+ const settingsTab = () => isSettingsTab(props.tab) ? props.tab : undefined;
1436
+ const warning = () => theme().text.feedback.warning.base;
1437
+ async function save() {
1438
+ try {
1439
+ await server.save();
1440
+ } catch (error) {
1441
+ const message = rpcErrorMessage(error);
1442
+ api.ui.toast.show({
1443
+ variant: "error",
1444
+ title: "Quota settings not saved",
1445
+ message
1446
+ });
1447
+ return;
1448
+ }
1449
+ setConfirming(false);
1450
+ props.close();
1451
+ api.ui.toast.show({
1452
+ variant: "success",
1453
+ title: "Quota settings saved",
1454
+ message: "Every open OpenCode window uses them now, and they stay after a restart.",
1455
+ duration: 4_000
1456
+ });
1457
+ }
1458
+ /** Drops the changes; from the "Keep your changes?" question it also closes the window. */
1459
+ const discardChanges = () => {
1460
+ discard();
1461
+ if (!confirming()) return;
1462
+ setConfirming(false);
1463
+ props.close();
1464
+ };
1465
+ api.keymap.layer(() => ({
1466
+ target: props.box,
1467
+ priority: 12,
1468
+ enabled: () => typing() === undefined && (settingsTab() !== undefined || dirty()),
1469
+ commands: [{
1470
+ bind: "ctrl+s",
1471
+ title: "Save",
1472
+ group: KEYS,
1473
+ run: () => void save()
1474
+ }]
1475
+ }));
1476
+ // While the bottom bar asks about unsaved changes: d drops them, Esc goes back to editing.
1477
+ api.keymap.layer(() => ({
1478
+ target: props.box,
1479
+ priority: 15,
1480
+ enabled: () => confirming() && typing() === undefined,
1481
+ commands: [{
1482
+ bind: "d",
1483
+ title: "Discard the changes",
1484
+ group: KEYS,
1485
+ run: discardChanges
1486
+ }, {
1487
+ bind: "escape",
1488
+ title: "Keep editing",
1489
+ group: KEYS,
1490
+ run: () => setConfirming(false)
1491
+ }]
1492
+ }));
1493
+ return _$createComponent(Show, {
1494
+ get when() {
1495
+ return settingsTab() !== undefined || confirming();
1496
+ },
1497
+ get children() {
1498
+ return _$createComponent(Show, {
1499
+ get when() {
1500
+ return !confirming();
1501
+ },
1502
+ get fallback() {
1503
+ return [_$createComponent(Cell, {
1504
+ get fg() {
1505
+ return warning();
1506
+ },
1507
+ bold: true,
1508
+ children: "Keep your changes?"
1509
+ }), _$createComponent(Button, {
1510
+ label: "Save",
1511
+ primary: true,
1512
+ run: () => void save()
1513
+ }), _$createComponent(Button, {
1514
+ label: "Discard",
1515
+ run: discardChanges
1516
+ }), _$createComponent(Button, {
1517
+ label: "Keep editing",
1518
+ run: () => setConfirming(false)
1519
+ })];
1520
+ },
1521
+ get children() {
1522
+ return [_$createComponent(Show, {
1523
+ get when() {
1524
+ return dirty();
1525
+ },
1526
+ get fallback() {
1527
+ return _$createComponent(Button, {
1528
+ label: "Close",
1529
+ primary: true,
1530
+ get run() {
1531
+ return props.close;
1532
+ }
1533
+ });
1534
+ },
1535
+ get children() {
1536
+ return [_$createComponent(Button, {
1537
+ label: "Save",
1538
+ primary: true,
1539
+ run: () => void save()
1540
+ }), _$createComponent(Button, {
1541
+ label: "Discard",
1542
+ run: discardChanges
1543
+ })];
1544
+ }
1545
+ }), _$createComponent(Show, {
1546
+ get when() {
1547
+ return settingsTab();
1548
+ },
1549
+ children: current => _$createComponent(Button, {
1550
+ get label() {
1551
+ return resetLabel(current());
1552
+ },
1553
+ run: () => resetTabLines(current())
1554
+ })
1555
+ }), _$createComponent(Show, {
1556
+ get when() {
1557
+ return _$memo(() => settingsTab() === "toast")() && shown().surfaces.toast.enabled;
1558
+ },
1559
+ get children() {
1560
+ return _$createComponent(Button, {
1561
+ label: "Show toast",
1562
+ run: () => previewToast(props.host, props.sessionID)
1563
+ });
1564
+ }
1565
+ }), _$createComponent(Cell, {
1566
+ get fg() {
1567
+ return warning();
1568
+ },
1569
+ get children() {
1570
+ return dirty() ? " unsaved changes" : "";
1571
+ }
1572
+ })];
1573
+ }
1574
+ });
1575
+ }
1576
+ });
1577
+ }
1578
+ return {
1579
+ /** The tree line selected on `surface`'s tab, which that surface marks. */
1580
+ marked(surface) {
1581
+ const id = selected();
1582
+ return tab() === surface && id.startsWith("line:") ? id.slice("line:".length) : undefined;
1583
+ },
1584
+ /** Sidebar shows the panel expanded and Collapsed collapsed; undefined = as the user left it. */
1585
+ panelOpen() {
1586
+ if (tab() === "sidebar") return true;
1587
+ return tab() === "collapsed" ? false : undefined;
1588
+ },
1589
+ /** A sidebar panel mounts; the returned function unmounts it. */
1590
+ sidebarShown() {
1591
+ setSidebars(count => count + 1);
1592
+ return () => setSidebars(count => count - 1);
1593
+ },
1594
+ statusLineShown() {
1595
+ const settings = shown();
1596
+ if (!settings.surfaces.statusLine.enabled) return false;
1597
+ const sidebarQuota = sidebars() > 0 && settings.surfaces.sidebar.enabled;
1598
+ return tab() === "statusLine" || settings.statusLine.withSidebar || !sidebarQuota;
1599
+ },
1600
+ /** A line takes typing, so the window's own keys rest. */
1601
+ typing: () => typing() !== undefined,
1602
+ /** A Plugin switch's saved value (`system.exportFile`); undefined until the server answers. */
1603
+ savedSwitch(key) {
1604
+ return server.saved() ? server.value(key) === true : undefined;
1605
+ },
1606
+ /** Saves a Plugin switch straight away; Plugin has no draft and no Save. */
1607
+ saveSwitch: (key, on) => server.saveNow(key, on),
1608
+ /** Reads the saved settings again, for Plugin's switches. */
1609
+ loadSaved: () => server.load(),
1610
+ /** The snapshot with All places' unsaved words, which every surface shows while you edit. */
1611
+ withDraftWords(snapshot) {
1612
+ const words = server.draftWords();
1613
+ if (!snapshot || Object.keys(words).length === 0) return snapshot;
1614
+ return {
1615
+ ...snapshot,
1616
+ words: {
1617
+ ...(snapshot.words ?? DEFAULT_WORDS),
1618
+ ...words
1619
+ }
1620
+ };
1621
+ },
1622
+ /**
1623
+ * The window shows `next`; undefined when it closed, which drops the changes. Any tab
1624
+ * change stops typing, so the window gets its keys back.
1625
+ */
1626
+ setTab(next) {
1627
+ setTyping(undefined);
1628
+ typingInput = undefined;
1629
+ if (next === undefined) {
1630
+ discard();
1631
+ setConfirming(false);
1632
+ }
1633
+ const settingsTab = isSettingsTab(next) ? next : undefined;
1634
+ if (settingsTab !== tab()) setSelected(firstLine(settingsTab));
1635
+ setTabNow(settingsTab);
1636
+ if (settingsTab) void loadServer(settingsTab);
1637
+ },
1638
+ /** Esc or Close: true while there are unsaved changes; the bottom bar then asks about them. */
1639
+ askBeforeClose() {
1640
+ if (!dirty()) return false;
1641
+ setConfirming(true);
1642
+ return true;
1643
+ },
1644
+ /** A press anywhere in the window: clicks count again after a drag, and typing goes on. */
1645
+ pressed() {
1646
+ draggedSincePress = false;
1647
+ if (typing()) typingInput?.focus();
1648
+ },
1649
+ click,
1650
+ /** The keyboard hint, or undefined for the window's own. */
1651
+ hint(windowTab, hasKeyboard) {
1652
+ const current = typing();
1653
+ if (current) return current.hint;
1654
+ if (!hasKeyboard) return undefined;
1655
+ if (confirming()) return "ctrl+s save · d discard the changes · esc keep editing";
1656
+ if (!isSettingsTab(windowTab)) return undefined;
1657
+ const reset = `ctrl+r ${resetLabel(windowTab).toLowerCase()}`;
1658
+ const end = `↑↓ select · tab next tab · ctrl+s save · ${reset} · esc close`;
1659
+ if (selected() === PAGES_ID) {
1660
+ return `↑↓ page · → or enter the page's lines · tab next tab · ctrl+s save · ${reset} · esc close`;
1661
+ }
1662
+ if (windowTab === "layout") return `‹ › or ←/→ change · ${end}`;
1663
+ if (windowTab === "providers") {
1664
+ return `‹ › or ←/→ change · space ticks a provider or flips a switch · double-click a number (or e) to type it · ${end}`;
1665
+ }
1666
+ if (!isSurfaceTab(windowTab)) {
1667
+ return `‹ › or ←/→ change · double-click a color (or e) to type your own · ${end}`;
1668
+ }
1669
+ const rowsTab = windowTab === "sidebar" || windowTab === "toast";
1670
+ const moving = api.renderer.useMouse === false ? "shift+↑↓ move" : `drag ⠿ or shift+↑↓ to move${rowsTab ? " (a provider takes its rows along)" : ""}`;
1671
+ const naming = rowsTab ? "double-click a row (or e) to rename it" : "‹ › pick a window";
1672
+ return `${moving} · [x] or space show/hide · ${naming} · ${end}`;
1673
+ },
1674
+ Pages,
1675
+ Header,
1676
+ Body,
1677
+ Buttons
1678
+ };
1679
+ }