open-multi-agent-kit 0.80.6 → 0.80.7

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 (981) hide show
  1. package/CHANGELOG.md +11 -1
  2. package/README.md +22 -14
  3. package/dist/cli/config-selector.d.ts +1 -1
  4. package/dist/cli/config-selector.d.ts.map +1 -1
  5. package/dist/cli/config-selector.js +1 -1
  6. package/dist/cli/config-selector.js.map +1 -1
  7. package/dist/config.d.ts +1 -0
  8. package/dist/config.d.ts.map +1 -1
  9. package/dist/config.js +9 -8
  10. package/dist/config.js.map +1 -1
  11. package/dist/core/agent-session.d.ts +45 -6
  12. package/dist/core/agent-session.d.ts.map +1 -1
  13. package/dist/core/agent-session.js +197 -13
  14. package/dist/core/agent-session.js.map +1 -1
  15. package/dist/core/auth-storage.d.ts +4 -1
  16. package/dist/core/auth-storage.d.ts.map +1 -1
  17. package/dist/core/auth-storage.js +5 -5
  18. package/dist/core/auth-storage.js.map +1 -1
  19. package/dist/core/bash-executor.d.ts.map +1 -1
  20. package/dist/core/bash-executor.js +1 -1
  21. package/dist/core/bash-executor.js.map +1 -1
  22. package/dist/core/command-safety.d.ts +11 -0
  23. package/dist/core/command-safety.d.ts.map +1 -0
  24. package/dist/core/command-safety.js +528 -0
  25. package/dist/core/command-safety.js.map +1 -0
  26. package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  27. package/dist/core/compaction/branch-summarization.js +14 -4
  28. package/dist/core/compaction/branch-summarization.js.map +1 -1
  29. package/dist/core/compaction/compaction.d.ts +18 -1
  30. package/dist/core/compaction/compaction.d.ts.map +1 -1
  31. package/dist/core/compaction/compaction.js +80 -42
  32. package/dist/core/compaction/compaction.js.map +1 -1
  33. package/dist/core/compaction/pruner-policy.d.ts +84 -0
  34. package/dist/core/compaction/pruner-policy.d.ts.map +1 -0
  35. package/dist/core/compaction/pruner-policy.js +273 -0
  36. package/dist/core/compaction/pruner-policy.js.map +1 -0
  37. package/dist/core/context-graph-identity-resolution.d.ts +114 -0
  38. package/dist/core/context-graph-identity-resolution.d.ts.map +1 -0
  39. package/dist/core/context-graph-identity-resolution.js +127 -0
  40. package/dist/core/context-graph-identity-resolution.js.map +1 -0
  41. package/dist/core/context-graph-memory-store.d.ts +153 -0
  42. package/dist/core/context-graph-memory-store.d.ts.map +1 -0
  43. package/dist/core/context-graph-memory-store.js +377 -0
  44. package/dist/core/context-graph-memory-store.js.map +1 -0
  45. package/dist/core/context-graph-ontology-generation.d.ts +104 -0
  46. package/dist/core/context-graph-ontology-generation.d.ts.map +1 -0
  47. package/dist/core/context-graph-ontology-generation.js +135 -0
  48. package/dist/core/context-graph-ontology-generation.js.map +1 -0
  49. package/dist/core/context-graph-ontology-registry.d.ts +766 -0
  50. package/dist/core/context-graph-ontology-registry.d.ts.map +1 -0
  51. package/dist/core/context-graph-ontology-registry.js +1133 -0
  52. package/dist/core/context-graph-ontology-registry.js.map +1 -0
  53. package/dist/core/context-graph-policy.d.ts +68 -0
  54. package/dist/core/context-graph-policy.d.ts.map +1 -0
  55. package/dist/core/context-graph-policy.js +221 -0
  56. package/dist/core/context-graph-policy.js.map +1 -0
  57. package/dist/core/context-graph-reasoning.d.ts +130 -0
  58. package/dist/core/context-graph-reasoning.d.ts.map +1 -0
  59. package/dist/core/context-graph-reasoning.js +442 -0
  60. package/dist/core/context-graph-reasoning.js.map +1 -0
  61. package/dist/core/context-graph-retrieval.d.ts +120 -0
  62. package/dist/core/context-graph-retrieval.d.ts.map +1 -0
  63. package/dist/core/context-graph-retrieval.js +288 -0
  64. package/dist/core/context-graph-retrieval.js.map +1 -0
  65. package/dist/core/contract-verification.d.ts +78 -0
  66. package/dist/core/contract-verification.d.ts.map +1 -0
  67. package/dist/core/contract-verification.js +110 -0
  68. package/dist/core/contract-verification.js.map +1 -0
  69. package/dist/core/exact-cache-policy.d.ts +100 -0
  70. package/dist/core/exact-cache-policy.d.ts.map +1 -0
  71. package/dist/core/exact-cache-policy.js +175 -0
  72. package/dist/core/exact-cache-policy.js.map +1 -0
  73. package/dist/core/exec.d.ts +2 -0
  74. package/dist/core/exec.d.ts.map +1 -1
  75. package/dist/core/exec.js +1 -0
  76. package/dist/core/exec.js.map +1 -1
  77. package/dist/core/export-html/template.js +2 -2
  78. package/dist/core/extensions/builtin/command-safety-gate.d.ts +77 -0
  79. package/dist/core/extensions/builtin/command-safety-gate.d.ts.map +1 -0
  80. package/dist/core/extensions/builtin/command-safety-gate.js +147 -0
  81. package/dist/core/extensions/builtin/command-safety-gate.js.map +1 -0
  82. package/dist/core/extensions/loader.d.ts +4 -4
  83. package/dist/core/extensions/loader.d.ts.map +1 -1
  84. package/dist/core/extensions/loader.js +94 -56
  85. package/dist/core/extensions/loader.js.map +1 -1
  86. package/dist/core/extensions/runner.d.ts.map +1 -1
  87. package/dist/core/extensions/runner.js +1 -1
  88. package/dist/core/extensions/runner.js.map +1 -1
  89. package/dist/core/extensions/types.d.ts +38 -10
  90. package/dist/core/extensions/types.d.ts.map +1 -1
  91. package/dist/core/extensions/types.js.map +1 -1
  92. package/dist/core/freedom/banner.d.ts +14 -0
  93. package/dist/core/freedom/banner.d.ts.map +1 -0
  94. package/dist/core/freedom/banner.js +22 -0
  95. package/dist/core/freedom/banner.js.map +1 -0
  96. package/dist/core/freedom/config.d.ts +27 -0
  97. package/dist/core/freedom/config.d.ts.map +1 -0
  98. package/dist/core/freedom/config.js +216 -0
  99. package/dist/core/freedom/config.js.map +1 -0
  100. package/dist/core/freedom/index.d.ts +23 -0
  101. package/dist/core/freedom/index.d.ts.map +1 -0
  102. package/dist/core/freedom/index.js +19 -0
  103. package/dist/core/freedom/index.js.map +1 -0
  104. package/dist/core/freedom/policy.d.ts +42 -0
  105. package/dist/core/freedom/policy.d.ts.map +1 -0
  106. package/dist/core/freedom/policy.js +47 -0
  107. package/dist/core/freedom/policy.js.map +1 -0
  108. package/dist/core/freedom/safety-floor.d.ts +73 -0
  109. package/dist/core/freedom/safety-floor.d.ts.map +1 -0
  110. package/dist/core/freedom/safety-floor.js +275 -0
  111. package/dist/core/freedom/safety-floor.js.map +1 -0
  112. package/dist/core/harness-control-events.d.ts +13 -1
  113. package/dist/core/harness-control-events.d.ts.map +1 -1
  114. package/dist/core/harness-control-events.js +216 -41
  115. package/dist/core/harness-control-events.js.map +1 -1
  116. package/dist/core/harness-control-replay.d.ts +7 -2
  117. package/dist/core/harness-control-replay.d.ts.map +1 -1
  118. package/dist/core/harness-control-replay.js +36 -4
  119. package/dist/core/harness-control-replay.js.map +1 -1
  120. package/dist/core/headroom-middleware.d.ts +35 -0
  121. package/dist/core/headroom-middleware.d.ts.map +1 -0
  122. package/dist/core/headroom-middleware.js +166 -0
  123. package/dist/core/headroom-middleware.js.map +1 -0
  124. package/dist/core/hook-inventory.d.ts +23 -0
  125. package/dist/core/hook-inventory.d.ts.map +1 -0
  126. package/dist/core/hook-inventory.js +50 -0
  127. package/dist/core/hook-inventory.js.map +1 -0
  128. package/dist/core/lean-context-middleware.d.ts +12 -0
  129. package/dist/core/lean-context-middleware.d.ts.map +1 -0
  130. package/dist/core/lean-context-middleware.js +87 -0
  131. package/dist/core/lean-context-middleware.js.map +1 -0
  132. package/dist/core/lean-context-policy.d.ts +45 -0
  133. package/dist/core/lean-context-policy.d.ts.map +1 -0
  134. package/dist/core/lean-context-policy.js +108 -0
  135. package/dist/core/lean-context-policy.js.map +1 -0
  136. package/dist/core/loadout-access-policy.d.ts +41 -0
  137. package/dist/core/loadout-access-policy.d.ts.map +1 -0
  138. package/dist/core/loadout-access-policy.js +182 -0
  139. package/dist/core/loadout-access-policy.js.map +1 -0
  140. package/dist/core/loadout-runtime.d.ts +84 -0
  141. package/dist/core/loadout-runtime.d.ts.map +1 -0
  142. package/dist/core/loadout-runtime.js +157 -0
  143. package/dist/core/loadout-runtime.js.map +1 -0
  144. package/dist/core/loadouts.d.ts +147 -0
  145. package/dist/core/loadouts.d.ts.map +1 -0
  146. package/dist/core/loadouts.js +442 -0
  147. package/dist/core/loadouts.js.map +1 -0
  148. package/dist/core/mcp-inventory.d.ts +34 -0
  149. package/dist/core/mcp-inventory.d.ts.map +1 -1
  150. package/dist/core/mcp-inventory.js +53 -1
  151. package/dist/core/mcp-inventory.js.map +1 -1
  152. package/dist/core/mcp-presets.d.ts +57 -0
  153. package/dist/core/mcp-presets.d.ts.map +1 -0
  154. package/dist/core/mcp-presets.js +81 -0
  155. package/dist/core/mcp-presets.js.map +1 -0
  156. package/dist/core/model-registry.d.ts +1 -0
  157. package/dist/core/model-registry.d.ts.map +1 -1
  158. package/dist/core/model-registry.js +40 -17
  159. package/dist/core/model-registry.js.map +1 -1
  160. package/dist/core/model-resolver.d.ts.map +1 -1
  161. package/dist/core/model-resolver.js +1 -0
  162. package/dist/core/model-resolver.js.map +1 -1
  163. package/dist/core/native-adoption-benchmark.d.ts +166 -0
  164. package/dist/core/native-adoption-benchmark.d.ts.map +1 -0
  165. package/dist/core/native-adoption-benchmark.js +624 -0
  166. package/dist/core/native-adoption-benchmark.js.map +1 -0
  167. package/dist/core/observability-trace.d.ts +80 -0
  168. package/dist/core/observability-trace.d.ts.map +1 -0
  169. package/dist/core/observability-trace.js +140 -0
  170. package/dist/core/observability-trace.js.map +1 -0
  171. package/dist/core/orchestration/checkpoint.d.ts +83 -0
  172. package/dist/core/orchestration/checkpoint.d.ts.map +1 -0
  173. package/dist/core/orchestration/checkpoint.js +152 -0
  174. package/dist/core/orchestration/checkpoint.js.map +1 -0
  175. package/dist/core/orchestration/errors.d.ts +74 -0
  176. package/dist/core/orchestration/errors.d.ts.map +1 -0
  177. package/dist/core/orchestration/errors.js +52 -0
  178. package/dist/core/orchestration/errors.js.map +1 -0
  179. package/dist/core/orchestration/merge-queue.d.ts +121 -0
  180. package/dist/core/orchestration/merge-queue.d.ts.map +1 -0
  181. package/dist/core/orchestration/merge-queue.js +149 -0
  182. package/dist/core/orchestration/merge-queue.js.map +1 -0
  183. package/dist/core/orchestration/recovery.d.ts +106 -0
  184. package/dist/core/orchestration/recovery.d.ts.map +1 -0
  185. package/dist/core/orchestration/recovery.js +110 -0
  186. package/dist/core/orchestration/recovery.js.map +1 -0
  187. package/dist/core/orchestration/replay-ledger.d.ts +76 -0
  188. package/dist/core/orchestration/replay-ledger.d.ts.map +1 -0
  189. package/dist/core/orchestration/replay-ledger.js +395 -0
  190. package/dist/core/orchestration/replay-ledger.js.map +1 -0
  191. package/dist/core/orchestration/scheduler-state.d.ts +78 -0
  192. package/dist/core/orchestration/scheduler-state.d.ts.map +1 -0
  193. package/dist/core/orchestration/scheduler-state.js +185 -0
  194. package/dist/core/orchestration/scheduler-state.js.map +1 -0
  195. package/dist/core/orchestration/scheduler-store.d.ts +309 -0
  196. package/dist/core/orchestration/scheduler-store.d.ts.map +1 -0
  197. package/dist/core/orchestration/scheduler-store.js +368 -0
  198. package/dist/core/orchestration/scheduler-store.js.map +1 -0
  199. package/dist/core/orchestration/sqlite-scheduler-store.d.ts +57 -0
  200. package/dist/core/orchestration/sqlite-scheduler-store.d.ts.map +1 -0
  201. package/dist/core/orchestration/sqlite-scheduler-store.js +528 -0
  202. package/dist/core/orchestration/sqlite-scheduler-store.js.map +1 -0
  203. package/dist/core/orchestration/transaction-coordinator.d.ts +217 -0
  204. package/dist/core/orchestration/transaction-coordinator.d.ts.map +1 -0
  205. package/dist/core/orchestration/transaction-coordinator.js +281 -0
  206. package/dist/core/orchestration/transaction-coordinator.js.map +1 -0
  207. package/dist/core/orchestration/verification-contract.d.ts +197 -0
  208. package/dist/core/orchestration/verification-contract.d.ts.map +1 -0
  209. package/dist/core/orchestration/verification-contract.js +145 -0
  210. package/dist/core/orchestration/verification-contract.js.map +1 -0
  211. package/dist/core/package-composition.d.ts +68 -0
  212. package/dist/core/package-composition.d.ts.map +1 -0
  213. package/dist/core/package-composition.js +304 -0
  214. package/dist/core/package-composition.js.map +1 -0
  215. package/dist/core/package-gallery.d.ts +124 -0
  216. package/dist/core/package-gallery.d.ts.map +1 -0
  217. package/dist/core/package-gallery.js +392 -0
  218. package/dist/core/package-gallery.js.map +1 -0
  219. package/dist/core/package-manager.d.ts +69 -0
  220. package/dist/core/package-manager.d.ts.map +1 -1
  221. package/dist/core/package-manager.js +367 -69
  222. package/dist/core/package-manager.js.map +1 -1
  223. package/dist/core/package-procurement.d.ts +268 -0
  224. package/dist/core/package-procurement.d.ts.map +1 -0
  225. package/dist/core/package-procurement.js +697 -0
  226. package/dist/core/package-procurement.js.map +1 -0
  227. package/dist/core/package-trial-runtime.d.ts +75 -0
  228. package/dist/core/package-trial-runtime.d.ts.map +1 -0
  229. package/dist/core/package-trial-runtime.js +73 -0
  230. package/dist/core/package-trial-runtime.js.map +1 -0
  231. package/dist/core/package-trial-sandbox.d.ts +27 -0
  232. package/dist/core/package-trial-sandbox.d.ts.map +1 -0
  233. package/dist/core/package-trial-sandbox.js +102 -0
  234. package/dist/core/package-trial-sandbox.js.map +1 -0
  235. package/dist/core/policy-overlays-runtime.d.ts +141 -0
  236. package/dist/core/policy-overlays-runtime.d.ts.map +1 -0
  237. package/dist/core/policy-overlays-runtime.js +720 -0
  238. package/dist/core/policy-overlays-runtime.js.map +1 -0
  239. package/dist/core/read-anchor-registry.d.ts +27 -0
  240. package/dist/core/read-anchor-registry.d.ts.map +1 -0
  241. package/dist/core/read-anchor-registry.js +103 -0
  242. package/dist/core/read-anchor-registry.js.map +1 -0
  243. package/dist/core/read-anchors.d.ts +110 -0
  244. package/dist/core/read-anchors.d.ts.map +1 -0
  245. package/dist/core/read-anchors.js +193 -0
  246. package/dist/core/read-anchors.js.map +1 -0
  247. package/dist/core/read-content-cache.d.ts +22 -0
  248. package/dist/core/read-content-cache.d.ts.map +1 -0
  249. package/dist/core/read-content-cache.js +79 -0
  250. package/dist/core/read-content-cache.js.map +1 -0
  251. package/dist/core/recovery-checkpoint.d.ts +196 -0
  252. package/dist/core/recovery-checkpoint.d.ts.map +1 -0
  253. package/dist/core/recovery-checkpoint.js +382 -0
  254. package/dist/core/recovery-checkpoint.js.map +1 -0
  255. package/dist/core/resolve-config-value.d.ts +1 -1
  256. package/dist/core/resolve-config-value.d.ts.map +1 -1
  257. package/dist/core/resolve-config-value.js +30 -2
  258. package/dist/core/resolve-config-value.js.map +1 -1
  259. package/dist/core/resource-loader.d.ts +23 -21
  260. package/dist/core/resource-loader.d.ts.map +1 -1
  261. package/dist/core/resource-loader.js +93 -15
  262. package/dist/core/resource-loader.js.map +1 -1
  263. package/dist/core/sandbox/backend.d.ts +25 -0
  264. package/dist/core/sandbox/backend.d.ts.map +1 -0
  265. package/dist/core/sandbox/backend.js +150 -0
  266. package/dist/core/sandbox/backend.js.map +1 -0
  267. package/dist/core/sandbox/env.d.ts +6 -0
  268. package/dist/core/sandbox/env.d.ts.map +1 -0
  269. package/dist/core/sandbox/env.js +46 -0
  270. package/dist/core/sandbox/env.js.map +1 -0
  271. package/dist/core/sandbox/path-resolver.d.ts +4 -0
  272. package/dist/core/sandbox/path-resolver.d.ts.map +1 -0
  273. package/dist/core/sandbox/path-resolver.js +44 -0
  274. package/dist/core/sandbox/path-resolver.js.map +1 -0
  275. package/dist/core/sandbox/policy.d.ts +87 -0
  276. package/dist/core/sandbox/policy.d.ts.map +1 -0
  277. package/dist/core/sandbox/policy.js +280 -0
  278. package/dist/core/sandbox/policy.js.map +1 -0
  279. package/dist/core/sandbox/spawn.d.ts +20 -0
  280. package/dist/core/sandbox/spawn.d.ts.map +1 -0
  281. package/dist/core/sandbox/spawn.js +80 -0
  282. package/dist/core/sandbox/spawn.js.map +1 -0
  283. package/dist/core/sdk.d.ts +83 -4
  284. package/dist/core/sdk.d.ts.map +1 -1
  285. package/dist/core/sdk.js +143 -55
  286. package/dist/core/sdk.js.map +1 -1
  287. package/dist/core/semantic-cache-policy.d.ts +45 -0
  288. package/dist/core/semantic-cache-policy.d.ts.map +1 -0
  289. package/dist/core/semantic-cache-policy.js +220 -0
  290. package/dist/core/semantic-cache-policy.js.map +1 -0
  291. package/dist/core/session-digest.d.ts +57 -0
  292. package/dist/core/session-digest.d.ts.map +1 -0
  293. package/dist/core/session-digest.js +193 -0
  294. package/dist/core/session-digest.js.map +1 -0
  295. package/dist/core/session-manager.d.ts +2 -2
  296. package/dist/core/session-manager.d.ts.map +1 -1
  297. package/dist/core/session-manager.js +5 -4
  298. package/dist/core/session-manager.js.map +1 -1
  299. package/dist/core/settings-manager.d.ts +14 -0
  300. package/dist/core/settings-manager.d.ts.map +1 -1
  301. package/dist/core/settings-manager.js +43 -2
  302. package/dist/core/settings-manager.js.map +1 -1
  303. package/dist/core/system-prompt.d.ts.map +1 -1
  304. package/dist/core/system-prompt.js +25 -7
  305. package/dist/core/system-prompt.js.map +1 -1
  306. package/dist/core/telemetry.d.ts.map +1 -1
  307. package/dist/core/telemetry.js +1 -1
  308. package/dist/core/telemetry.js.map +1 -1
  309. package/dist/core/timings.d.ts +1 -1
  310. package/dist/core/timings.d.ts.map +1 -1
  311. package/dist/core/timings.js +2 -2
  312. package/dist/core/timings.js.map +1 -1
  313. package/dist/core/tools/bash.d.ts +28 -3
  314. package/dist/core/tools/bash.d.ts.map +1 -1
  315. package/dist/core/tools/bash.js +53 -10
  316. package/dist/core/tools/bash.js.map +1 -1
  317. package/dist/core/tools/edit.d.ts +12 -0
  318. package/dist/core/tools/edit.d.ts.map +1 -1
  319. package/dist/core/tools/edit.js +24 -0
  320. package/dist/core/tools/edit.js.map +1 -1
  321. package/dist/core/tools/find.d.ts +3 -0
  322. package/dist/core/tools/find.d.ts.map +1 -1
  323. package/dist/core/tools/find.js +3 -0
  324. package/dist/core/tools/find.js.map +1 -1
  325. package/dist/core/tools/grep.d.ts +3 -0
  326. package/dist/core/tools/grep.d.ts.map +1 -1
  327. package/dist/core/tools/grep.js +4 -1
  328. package/dist/core/tools/grep.js.map +1 -1
  329. package/dist/core/tools/index.d.ts +1 -1
  330. package/dist/core/tools/index.d.ts.map +1 -1
  331. package/dist/core/tools/index.js.map +1 -1
  332. package/dist/core/tools/ls.d.ts +3 -0
  333. package/dist/core/tools/ls.d.ts.map +1 -1
  334. package/dist/core/tools/ls.js +3 -0
  335. package/dist/core/tools/ls.js.map +1 -1
  336. package/dist/core/tools/output-accumulator.d.ts.map +1 -1
  337. package/dist/core/tools/output-accumulator.js +1 -1
  338. package/dist/core/tools/output-accumulator.js.map +1 -1
  339. package/dist/core/tools/read.d.ts +13 -0
  340. package/dist/core/tools/read.d.ts.map +1 -1
  341. package/dist/core/tools/read.js +29 -2
  342. package/dist/core/tools/read.js.map +1 -1
  343. package/dist/core/tools/write.d.ts +3 -0
  344. package/dist/core/tools/write.d.ts.map +1 -1
  345. package/dist/core/tools/write.js +3 -0
  346. package/dist/core/tools/write.js.map +1 -1
  347. package/dist/index.d.ts +19 -4
  348. package/dist/index.d.ts.map +1 -1
  349. package/dist/index.js +17 -2
  350. package/dist/index.js.map +1 -1
  351. package/dist/main.d.ts.map +1 -1
  352. package/dist/main.js +4 -6
  353. package/dist/main.js.map +1 -1
  354. package/dist/migrations.d.ts.map +1 -1
  355. package/dist/migrations.js +1 -1
  356. package/dist/migrations.js.map +1 -1
  357. package/dist/modes/interactive/components/control-panel-gradient-motion.d.ts +28 -0
  358. package/dist/modes/interactive/components/control-panel-gradient-motion.d.ts.map +1 -0
  359. package/dist/modes/interactive/components/control-panel-gradient-motion.js +146 -0
  360. package/dist/modes/interactive/components/control-panel-gradient-motion.js.map +1 -0
  361. package/dist/modes/interactive/components/control-panel-gradient.d.ts +27 -0
  362. package/dist/modes/interactive/components/control-panel-gradient.d.ts.map +1 -0
  363. package/dist/modes/interactive/components/control-panel-gradient.js +127 -0
  364. package/dist/modes/interactive/components/control-panel-gradient.js.map +1 -0
  365. package/dist/modes/interactive/components/control-panel.d.ts +28 -1
  366. package/dist/modes/interactive/components/control-panel.d.ts.map +1 -1
  367. package/dist/modes/interactive/components/control-panel.js +153 -3
  368. package/dist/modes/interactive/components/control-panel.js.map +1 -1
  369. package/dist/modes/interactive/components/earendil-announcement.d.ts.map +1 -1
  370. package/dist/modes/interactive/components/earendil-announcement.js +1 -1
  371. package/dist/modes/interactive/components/earendil-announcement.js.map +1 -1
  372. package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
  373. package/dist/modes/interactive/components/extension-editor.js +1 -1
  374. package/dist/modes/interactive/components/extension-editor.js.map +1 -1
  375. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  376. package/dist/modes/interactive/components/footer.js +8 -0
  377. package/dist/modes/interactive/components/footer.js.map +1 -1
  378. package/dist/modes/interactive/components/mcp-selector.d.ts +2 -0
  379. package/dist/modes/interactive/components/mcp-selector.d.ts.map +1 -1
  380. package/dist/modes/interactive/components/mcp-selector.js +18 -1
  381. package/dist/modes/interactive/components/mcp-selector.js.map +1 -1
  382. package/dist/modes/interactive/components/model-selector-state.d.ts +101 -0
  383. package/dist/modes/interactive/components/model-selector-state.d.ts.map +1 -0
  384. package/dist/modes/interactive/components/model-selector-state.js +261 -0
  385. package/dist/modes/interactive/components/model-selector-state.js.map +1 -0
  386. package/dist/modes/interactive/components/model-selector.d.ts +44 -10
  387. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  388. package/dist/modes/interactive/components/model-selector.js +163 -110
  389. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  390. package/dist/modes/interactive/components/theme-selector.d.ts +1 -0
  391. package/dist/modes/interactive/components/theme-selector.d.ts.map +1 -1
  392. package/dist/modes/interactive/components/theme-selector.js +10 -1
  393. package/dist/modes/interactive/components/theme-selector.js.map +1 -1
  394. package/dist/modes/interactive/interactive-mode.d.ts +4 -2
  395. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  396. package/dist/modes/interactive/interactive-mode.js +61 -13
  397. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  398. package/dist/modes/interactive/theme/omk-blackboard.json +91 -0
  399. package/dist/modes/interactive/theme/omk-freedom-grid.json +91 -0
  400. package/dist/modes/interactive/theme/omk-neon-ops.json +90 -0
  401. package/dist/modes/interactive/theme/omk-slate-light.json +91 -0
  402. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  403. package/dist/modes/interactive/theme/theme.js +14 -0
  404. package/dist/modes/interactive/theme/theme.js.map +1 -1
  405. package/dist/modes/print-mode.d.ts +2 -2
  406. package/dist/modes/print-mode.d.ts.map +1 -1
  407. package/dist/modes/print-mode.js +2 -2
  408. package/dist/modes/print-mode.js.map +1 -1
  409. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  410. package/dist/modes/rpc/rpc-mode.js +4 -0
  411. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  412. package/dist/package-manager-cli.d.ts.map +1 -1
  413. package/dist/package-manager-cli.js +114 -49
  414. package/dist/package-manager-cli.js.map +1 -1
  415. package/dist/utils/clipboard-image.d.ts.map +1 -1
  416. package/dist/utils/clipboard-image.js +1 -1
  417. package/dist/utils/clipboard-image.js.map +1 -1
  418. package/dist/utils/omk-user-agent.d.ts +2 -0
  419. package/dist/utils/omk-user-agent.d.ts.map +1 -0
  420. package/dist/utils/{pi-user-agent.js → omk-user-agent.js} +2 -2
  421. package/dist/utils/omk-user-agent.js.map +1 -0
  422. package/dist/utils/tools-manager.d.ts.map +1 -1
  423. package/dist/utils/tools-manager.js +1 -1
  424. package/dist/utils/tools-manager.js.map +1 -1
  425. package/dist/utils/version-check.d.ts +5 -5
  426. package/dist/utils/version-check.d.ts.map +1 -1
  427. package/dist/utils/version-check.js +8 -11
  428. package/dist/utils/version-check.js.map +1 -1
  429. package/dist/utils/windows-self-update.d.ts.map +1 -1
  430. package/dist/utils/windows-self-update.js +1 -1
  431. package/dist/utils/windows-self-update.js.map +1 -1
  432. package/docs/packages.md +47 -6
  433. package/docs/prompt-templates.md +2 -0
  434. package/docs/usage.md +16 -6
  435. package/examples/README.md +1 -1
  436. package/examples/extensions/README.md +11 -11
  437. package/examples/extensions/auto-commit-on-exit.ts +6 -6
  438. package/examples/extensions/bash-spawn-hook.ts +4 -4
  439. package/examples/extensions/bookmark.ts +5 -5
  440. package/examples/extensions/border-status-editor.ts +7 -7
  441. package/examples/extensions/built-in-tool-renderer.ts +6 -6
  442. package/examples/extensions/claude-rules.ts +4 -4
  443. package/examples/extensions/commands.ts +5 -5
  444. package/examples/extensions/confirm-destructive.ts +3 -3
  445. package/examples/extensions/custom-compaction.ts +3 -3
  446. package/examples/extensions/custom-footer.ts +2 -2
  447. package/examples/extensions/custom-header.ts +5 -5
  448. package/examples/extensions/custom-provider-anthropic/index.ts +4 -4
  449. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  450. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  451. package/examples/extensions/custom-provider-gitlab-duo/index.ts +3 -3
  452. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  453. package/examples/extensions/dirty-repo-guard.ts +7 -7
  454. package/examples/extensions/doom-overlay/README.md +3 -3
  455. package/examples/extensions/doom-overlay/doom/build.sh +2 -2
  456. package/examples/extensions/doom-overlay/doom/doomgeneric_pi.c +1 -1
  457. package/examples/extensions/doom-overlay/index.ts +3 -3
  458. package/examples/extensions/dynamic-resources/dynamic.json +1 -1
  459. package/examples/extensions/dynamic-resources/index.ts +2 -2
  460. package/examples/extensions/dynamic-tools.ts +4 -4
  461. package/examples/extensions/event-bus.ts +8 -8
  462. package/examples/extensions/file-trigger.ts +3 -3
  463. package/examples/extensions/git-checkpoint.ts +7 -7
  464. package/examples/extensions/git-merge-and-resolve.ts +14 -14
  465. package/examples/extensions/github-issue-autocomplete.ts +6 -6
  466. package/examples/extensions/gondolin/index.ts +16 -16
  467. package/examples/extensions/gondolin/package-lock.json +2 -2
  468. package/examples/extensions/gondolin/package.json +1 -1
  469. package/examples/extensions/handoff.ts +2 -2
  470. package/examples/extensions/hello.ts +2 -2
  471. package/examples/extensions/hidden-thinking-label.ts +4 -4
  472. package/examples/extensions/inline-bash.ts +5 -5
  473. package/examples/extensions/input-transform-streaming.ts +5 -5
  474. package/examples/extensions/input-transform.ts +5 -5
  475. package/examples/extensions/interactive-shell.ts +3 -3
  476. package/examples/extensions/mac-system-theme.ts +5 -5
  477. package/examples/extensions/message-renderer.ts +4 -4
  478. package/examples/extensions/minimal-mode.ts +9 -9
  479. package/examples/extensions/modal-editor.ts +3 -3
  480. package/examples/extensions/model-status.ts +3 -3
  481. package/examples/extensions/notify.ts +5 -5
  482. package/examples/extensions/overlay-qa-tests.ts +20 -20
  483. package/examples/extensions/overlay-test.ts +3 -3
  484. package/examples/extensions/permission-gate.ts +2 -2
  485. package/examples/extensions/pirate.ts +4 -4
  486. package/examples/extensions/plan-mode/index.ts +22 -22
  487. package/examples/extensions/preset.ts +30 -30
  488. package/examples/extensions/prompt-customizer.ts +3 -3
  489. package/examples/extensions/protected-paths.ts +2 -2
  490. package/examples/extensions/provider-payload.ts +5 -5
  491. package/examples/extensions/qna.ts +2 -2
  492. package/examples/extensions/question.ts +2 -2
  493. package/examples/extensions/questionnaire.ts +2 -2
  494. package/examples/extensions/rainbow-editor.ts +3 -3
  495. package/examples/extensions/reload-runtime.ts +4 -4
  496. package/examples/extensions/rpc-demo.ts +10 -10
  497. package/examples/extensions/sandbox/index.ts +17 -17
  498. package/examples/extensions/sandbox/package-lock.json +2 -2
  499. package/examples/extensions/sandbox/package.json +1 -1
  500. package/examples/extensions/send-user-message.ts +13 -13
  501. package/examples/extensions/session-name.ts +4 -4
  502. package/examples/extensions/shutdown-command.ts +10 -10
  503. package/examples/extensions/snake.ts +3 -3
  504. package/examples/extensions/space-invaders.ts +3 -3
  505. package/examples/extensions/ssh.ts +12 -12
  506. package/examples/extensions/status-line.ts +4 -4
  507. package/examples/extensions/structured-output.ts +2 -2
  508. package/examples/extensions/subagent/README.md +13 -13
  509. package/examples/extensions/subagent/agents.ts +2 -2
  510. package/examples/extensions/subagent/index.ts +53 -21
  511. package/examples/extensions/summarize.ts +2 -2
  512. package/examples/extensions/system-prompt-header.ts +3 -3
  513. package/examples/extensions/tic-tac-toe.ts +15 -15
  514. package/examples/extensions/timed-confirm.ts +4 -4
  515. package/examples/extensions/titlebar-spinner.ts +9 -9
  516. package/examples/extensions/todo.ts +5 -5
  517. package/examples/extensions/tool-override.ts +5 -5
  518. package/examples/extensions/tools.ts +10 -10
  519. package/examples/extensions/trigger-compact.ts +3 -3
  520. package/examples/extensions/truncated-tool.ts +3 -3
  521. package/examples/extensions/widget-placement.ts +2 -2
  522. package/examples/extensions/with-deps/index.ts +2 -2
  523. package/examples/extensions/with-deps/package-lock.json +2 -2
  524. package/examples/extensions/with-deps/package.json +1 -1
  525. package/examples/extensions/working-indicator.ts +7 -7
  526. package/examples/extensions/working-message-test.ts +3 -3
  527. package/examples/sdk/01-minimal.ts +1 -1
  528. package/examples/sdk/03-custom-prompt.ts +1 -1
  529. package/examples/sdk/04-skills.ts +1 -1
  530. package/examples/sdk/05-tools.ts +1 -1
  531. package/examples/sdk/06-extensions.ts +11 -11
  532. package/examples/sdk/07-context-files.ts +2 -0
  533. package/examples/sdk/08-prompt-templates.ts +1 -1
  534. package/examples/sdk/09-api-keys-and-oauth.ts +2 -2
  535. package/examples/sdk/README.md +2 -2
  536. package/node_modules/@earendil-works/omk-agent-core/README.md +488 -0
  537. package/node_modules/@earendil-works/omk-agent-core/dist/agent-loop.d.ts +24 -0
  538. package/node_modules/@earendil-works/omk-agent-core/dist/agent-loop.d.ts.map +1 -0
  539. package/node_modules/@earendil-works/omk-agent-core/dist/agent-loop.js +553 -0
  540. package/node_modules/@earendil-works/omk-agent-core/dist/agent-loop.js.map +1 -0
  541. package/node_modules/@earendil-works/omk-agent-core/dist/agent.d.ts +118 -0
  542. package/node_modules/@earendil-works/omk-agent-core/dist/agent.d.ts.map +1 -0
  543. package/node_modules/@earendil-works/omk-agent-core/dist/agent.js +402 -0
  544. package/node_modules/@earendil-works/omk-agent-core/dist/agent.js.map +1 -0
  545. package/node_modules/@earendil-works/omk-agent-core/dist/harness/agent-harness.d.ts +95 -0
  546. package/node_modules/@earendil-works/omk-agent-core/dist/harness/agent-harness.d.ts.map +1 -0
  547. package/node_modules/@earendil-works/omk-agent-core/dist/harness/agent-harness.js +996 -0
  548. package/node_modules/@earendil-works/omk-agent-core/dist/harness/agent-harness.js.map +1 -0
  549. package/node_modules/@earendil-works/omk-agent-core/dist/harness/compaction/branch-summarization.d.ts +53 -0
  550. package/node_modules/@earendil-works/omk-agent-core/dist/harness/compaction/branch-summarization.d.ts.map +1 -0
  551. package/node_modules/@earendil-works/omk-agent-core/dist/harness/compaction/branch-summarization.js +175 -0
  552. package/node_modules/@earendil-works/omk-agent-core/dist/harness/compaction/branch-summarization.js.map +1 -0
  553. package/node_modules/@earendil-works/omk-agent-core/dist/harness/compaction/compaction.d.ts +117 -0
  554. package/node_modules/@earendil-works/omk-agent-core/dist/harness/compaction/compaction.d.ts.map +1 -0
  555. package/node_modules/@earendil-works/omk-agent-core/dist/harness/compaction/compaction.js +568 -0
  556. package/node_modules/@earendil-works/omk-agent-core/dist/harness/compaction/compaction.js.map +1 -0
  557. package/node_modules/@earendil-works/omk-agent-core/dist/harness/compaction/utils.d.ts +25 -0
  558. package/node_modules/@earendil-works/omk-agent-core/dist/harness/compaction/utils.d.ts.map +1 -0
  559. package/node_modules/@earendil-works/omk-agent-core/dist/harness/compaction/utils.js +131 -0
  560. package/node_modules/@earendil-works/omk-agent-core/dist/harness/compaction/utils.js.map +1 -0
  561. package/node_modules/@earendil-works/omk-agent-core/dist/harness/env/nodejs.d.ts +51 -0
  562. package/node_modules/@earendil-works/omk-agent-core/dist/harness/env/nodejs.d.ts.map +1 -0
  563. package/node_modules/@earendil-works/omk-agent-core/dist/harness/env/nodejs.js +510 -0
  564. package/node_modules/@earendil-works/omk-agent-core/dist/harness/env/nodejs.js.map +1 -0
  565. package/node_modules/@earendil-works/omk-agent-core/dist/harness/messages.d.ts +51 -0
  566. package/node_modules/@earendil-works/omk-agent-core/dist/harness/messages.d.ts.map +1 -0
  567. package/node_modules/@earendil-works/omk-agent-core/dist/harness/messages.js +102 -0
  568. package/node_modules/@earendil-works/omk-agent-core/dist/harness/messages.js.map +1 -0
  569. package/node_modules/@earendil-works/omk-agent-core/dist/harness/prompt-templates.d.ts +48 -0
  570. package/node_modules/@earendil-works/omk-agent-core/dist/harness/prompt-templates.d.ts.map +1 -0
  571. package/node_modules/@earendil-works/omk-agent-core/dist/harness/prompt-templates.js +230 -0
  572. package/node_modules/@earendil-works/omk-agent-core/dist/harness/prompt-templates.js.map +1 -0
  573. package/node_modules/@earendil-works/omk-agent-core/dist/harness/session/jsonl-repo.d.ts +26 -0
  574. package/node_modules/@earendil-works/omk-agent-core/dist/harness/session/jsonl-repo.d.ts.map +1 -0
  575. package/node_modules/@earendil-works/omk-agent-core/dist/harness/session/jsonl-repo.js +101 -0
  576. package/node_modules/@earendil-works/omk-agent-core/dist/harness/session/jsonl-repo.js.map +1 -0
  577. package/node_modules/@earendil-works/omk-agent-core/dist/harness/session/jsonl-storage.d.ts +36 -0
  578. package/node_modules/@earendil-works/omk-agent-core/dist/harness/session/jsonl-storage.d.ts.map +1 -0
  579. package/node_modules/@earendil-works/omk-agent-core/dist/harness/session/jsonl-storage.js +273 -0
  580. package/node_modules/@earendil-works/omk-agent-core/dist/harness/session/jsonl-storage.js.map +1 -0
  581. package/node_modules/@earendil-works/omk-agent-core/dist/harness/session/memory-repo.d.ts +18 -0
  582. package/node_modules/@earendil-works/omk-agent-core/dist/harness/session/memory-repo.d.ts.map +1 -0
  583. package/node_modules/@earendil-works/omk-agent-core/dist/harness/session/memory-repo.js +42 -0
  584. package/node_modules/@earendil-works/omk-agent-core/dist/harness/session/memory-repo.js.map +1 -0
  585. package/node_modules/@earendil-works/omk-agent-core/dist/harness/session/memory-storage.d.ts +25 -0
  586. package/node_modules/@earendil-works/omk-agent-core/dist/harness/session/memory-storage.d.ts.map +1 -0
  587. package/node_modules/@earendil-works/omk-agent-core/dist/harness/session/memory-storage.js +114 -0
  588. package/node_modules/@earendil-works/omk-agent-core/dist/harness/session/memory-storage.js.map +1 -0
  589. package/node_modules/@earendil-works/omk-agent-core/dist/harness/session/repo-utils.d.ts +11 -0
  590. package/node_modules/@earendil-works/omk-agent-core/dist/harness/session/repo-utils.d.ts.map +1 -0
  591. package/node_modules/@earendil-works/omk-agent-core/dist/harness/session/repo-utils.js +39 -0
  592. package/node_modules/@earendil-works/omk-agent-core/dist/harness/session/repo-utils.js.map +1 -0
  593. package/node_modules/@earendil-works/omk-agent-core/dist/harness/session/session.d.ts +33 -0
  594. package/node_modules/@earendil-works/omk-agent-core/dist/harness/session/session.d.ts.map +1 -0
  595. package/node_modules/@earendil-works/omk-agent-core/dist/harness/session/session.js +210 -0
  596. package/node_modules/@earendil-works/omk-agent-core/dist/harness/session/session.js.map +1 -0
  597. package/node_modules/@earendil-works/omk-agent-core/dist/harness/session/uuid.d.ts +2 -0
  598. package/node_modules/@earendil-works/omk-agent-core/dist/harness/session/uuid.d.ts.map +1 -0
  599. package/node_modules/@earendil-works/omk-agent-core/dist/harness/session/uuid.js +50 -0
  600. package/node_modules/@earendil-works/omk-agent-core/dist/harness/session/uuid.js.map +1 -0
  601. package/node_modules/@earendil-works/omk-agent-core/dist/harness/skills.d.ts +44 -0
  602. package/node_modules/@earendil-works/omk-agent-core/dist/harness/skills.d.ts.map +1 -0
  603. package/node_modules/@earendil-works/omk-agent-core/dist/harness/skills.js +311 -0
  604. package/node_modules/@earendil-works/omk-agent-core/dist/harness/skills.js.map +1 -0
  605. package/node_modules/@earendil-works/omk-agent-core/dist/harness/system-prompt.d.ts +3 -0
  606. package/node_modules/@earendil-works/omk-agent-core/dist/harness/system-prompt.d.ts.map +1 -0
  607. package/node_modules/@earendil-works/omk-agent-core/dist/harness/system-prompt.js +30 -0
  608. package/node_modules/@earendil-works/omk-agent-core/dist/harness/system-prompt.js.map +1 -0
  609. package/node_modules/@earendil-works/omk-agent-core/dist/harness/types.d.ts +616 -0
  610. package/node_modules/@earendil-works/omk-agent-core/dist/harness/types.d.ts.map +1 -0
  611. package/node_modules/@earendil-works/omk-agent-core/dist/harness/types.js +94 -0
  612. package/node_modules/@earendil-works/omk-agent-core/dist/harness/types.js.map +1 -0
  613. package/node_modules/@earendil-works/omk-agent-core/dist/harness/utils/shell-output.d.ts +14 -0
  614. package/node_modules/@earendil-works/omk-agent-core/dist/harness/utils/shell-output.d.ts.map +1 -0
  615. package/node_modules/@earendil-works/omk-agent-core/dist/harness/utils/shell-output.js +126 -0
  616. package/node_modules/@earendil-works/omk-agent-core/dist/harness/utils/shell-output.js.map +1 -0
  617. package/node_modules/@earendil-works/omk-agent-core/dist/harness/utils/truncate.d.ts +70 -0
  618. package/node_modules/@earendil-works/omk-agent-core/dist/harness/utils/truncate.d.ts.map +1 -0
  619. package/node_modules/@earendil-works/omk-agent-core/dist/harness/utils/truncate.js +297 -0
  620. package/node_modules/@earendil-works/omk-agent-core/dist/harness/utils/truncate.js.map +1 -0
  621. package/node_modules/@earendil-works/omk-agent-core/dist/index.d.ts +20 -0
  622. package/node_modules/@earendil-works/omk-agent-core/dist/index.d.ts.map +1 -0
  623. package/node_modules/@earendil-works/omk-agent-core/dist/index.js +25 -0
  624. package/node_modules/@earendil-works/omk-agent-core/dist/index.js.map +1 -0
  625. package/node_modules/@earendil-works/omk-agent-core/dist/node.d.ts +3 -0
  626. package/node_modules/@earendil-works/omk-agent-core/dist/node.d.ts.map +1 -0
  627. package/node_modules/@earendil-works/omk-agent-core/dist/node.js +3 -0
  628. package/node_modules/@earendil-works/omk-agent-core/dist/node.js.map +1 -0
  629. package/node_modules/@earendil-works/omk-agent-core/dist/proxy.d.ts +69 -0
  630. package/node_modules/@earendil-works/omk-agent-core/dist/proxy.d.ts.map +1 -0
  631. package/node_modules/@earendil-works/omk-agent-core/dist/proxy.js +278 -0
  632. package/node_modules/@earendil-works/omk-agent-core/dist/proxy.js.map +1 -0
  633. package/node_modules/@earendil-works/omk-agent-core/dist/types.d.ts +393 -0
  634. package/node_modules/@earendil-works/omk-agent-core/dist/types.d.ts.map +1 -0
  635. package/node_modules/@earendil-works/omk-agent-core/dist/types.js +2 -0
  636. package/node_modules/@earendil-works/omk-agent-core/dist/types.js.map +1 -0
  637. package/node_modules/@earendil-works/omk-agent-core/package.json +60 -0
  638. package/node_modules/@earendil-works/omk-ai/README.md +1389 -0
  639. package/node_modules/@earendil-works/omk-ai/dist/api-registry.d.ts +20 -0
  640. package/node_modules/@earendil-works/omk-ai/dist/api-registry.d.ts.map +1 -0
  641. package/node_modules/@earendil-works/omk-ai/dist/api-registry.js +44 -0
  642. package/node_modules/@earendil-works/omk-ai/dist/api-registry.js.map +1 -0
  643. package/node_modules/@earendil-works/omk-ai/dist/bedrock-provider.d.ts +5 -0
  644. package/node_modules/@earendil-works/omk-ai/dist/bedrock-provider.d.ts.map +1 -0
  645. package/node_modules/@earendil-works/omk-ai/dist/bedrock-provider.js +6 -0
  646. package/node_modules/@earendil-works/omk-ai/dist/bedrock-provider.js.map +1 -0
  647. package/node_modules/@earendil-works/omk-ai/dist/cli.d.ts +3 -0
  648. package/node_modules/@earendil-works/omk-ai/dist/cli.d.ts.map +1 -0
  649. package/node_modules/@earendil-works/omk-ai/dist/cli.js +130 -0
  650. package/node_modules/@earendil-works/omk-ai/dist/cli.js.map +1 -0
  651. package/node_modules/@earendil-works/omk-ai/dist/env-api-keys.d.ts +20 -0
  652. package/node_modules/@earendil-works/omk-ai/dist/env-api-keys.d.ts.map +1 -0
  653. package/node_modules/@earendil-works/omk-ai/dist/env-api-keys.js +199 -0
  654. package/node_modules/@earendil-works/omk-ai/dist/env-api-keys.js.map +1 -0
  655. package/node_modules/@earendil-works/omk-ai/dist/image-models.d.ts +10 -0
  656. package/node_modules/@earendil-works/omk-ai/dist/image-models.d.ts.map +1 -0
  657. package/node_modules/@earendil-works/omk-ai/dist/image-models.generated.d.ts +515 -0
  658. package/node_modules/@earendil-works/omk-ai/dist/image-models.generated.d.ts.map +1 -0
  659. package/node_modules/@earendil-works/omk-ai/dist/image-models.generated.js +517 -0
  660. package/node_modules/@earendil-works/omk-ai/dist/image-models.generated.js.map +1 -0
  661. package/node_modules/@earendil-works/omk-ai/dist/image-models.js +23 -0
  662. package/node_modules/@earendil-works/omk-ai/dist/image-models.js.map +1 -0
  663. package/node_modules/@earendil-works/omk-ai/dist/images-api-registry.d.ts +14 -0
  664. package/node_modules/@earendil-works/omk-ai/dist/images-api-registry.d.ts.map +1 -0
  665. package/node_modules/@earendil-works/omk-ai/dist/images-api-registry.js +22 -0
  666. package/node_modules/@earendil-works/omk-ai/dist/images-api-registry.js.map +1 -0
  667. package/node_modules/@earendil-works/omk-ai/dist/images.d.ts +4 -0
  668. package/node_modules/@earendil-works/omk-ai/dist/images.d.ts.map +1 -0
  669. package/node_modules/@earendil-works/omk-ai/dist/images.js +16 -0
  670. package/node_modules/@earendil-works/omk-ai/dist/images.js.map +1 -0
  671. package/node_modules/@earendil-works/omk-ai/dist/index.d.ts +33 -0
  672. package/node_modules/@earendil-works/omk-ai/dist/index.d.ts.map +1 -0
  673. package/node_modules/@earendil-works/omk-ai/dist/index.js +21 -0
  674. package/node_modules/@earendil-works/omk-ai/dist/index.js.map +1 -0
  675. package/node_modules/@earendil-works/omk-ai/dist/models.d.ts +18 -0
  676. package/node_modules/@earendil-works/omk-ai/dist/models.d.ts.map +1 -0
  677. package/node_modules/@earendil-works/omk-ai/dist/models.generated.d.ts +18762 -0
  678. package/node_modules/@earendil-works/omk-ai/dist/models.generated.d.ts.map +1 -0
  679. package/node_modules/@earendil-works/omk-ai/dist/models.generated.js +17197 -0
  680. package/node_modules/@earendil-works/omk-ai/dist/models.generated.js.map +1 -0
  681. package/node_modules/@earendil-works/omk-ai/dist/models.js +78 -0
  682. package/node_modules/@earendil-works/omk-ai/dist/models.js.map +1 -0
  683. package/node_modules/@earendil-works/omk-ai/dist/oauth.d.ts +2 -0
  684. package/node_modules/@earendil-works/omk-ai/dist/oauth.d.ts.map +1 -0
  685. package/node_modules/@earendil-works/omk-ai/dist/oauth.js +2 -0
  686. package/node_modules/@earendil-works/omk-ai/dist/oauth.js.map +1 -0
  687. package/node_modules/@earendil-works/omk-ai/dist/provider-network.d.ts +39 -0
  688. package/node_modules/@earendil-works/omk-ai/dist/provider-network.d.ts.map +1 -0
  689. package/node_modules/@earendil-works/omk-ai/dist/provider-network.js +170 -0
  690. package/node_modules/@earendil-works/omk-ai/dist/provider-network.js.map +1 -0
  691. package/node_modules/@earendil-works/omk-ai/dist/providers/amazon-bedrock.d.ts +38 -0
  692. package/node_modules/@earendil-works/omk-ai/dist/providers/amazon-bedrock.d.ts.map +1 -0
  693. package/node_modules/@earendil-works/omk-ai/dist/providers/amazon-bedrock.js +826 -0
  694. package/node_modules/@earendil-works/omk-ai/dist/providers/amazon-bedrock.js.map +1 -0
  695. package/node_modules/@earendil-works/omk-ai/dist/providers/anthropic.d.ts +77 -0
  696. package/node_modules/@earendil-works/omk-ai/dist/providers/anthropic.d.ts.map +1 -0
  697. package/node_modules/@earendil-works/omk-ai/dist/providers/anthropic.js +1123 -0
  698. package/node_modules/@earendil-works/omk-ai/dist/providers/anthropic.js.map +1 -0
  699. package/node_modules/@earendil-works/omk-ai/dist/providers/azure-openai-responses.d.ts +15 -0
  700. package/node_modules/@earendil-works/omk-ai/dist/providers/azure-openai-responses.d.ts.map +1 -0
  701. package/node_modules/@earendil-works/omk-ai/dist/providers/azure-openai-responses.js +221 -0
  702. package/node_modules/@earendil-works/omk-ai/dist/providers/azure-openai-responses.js.map +1 -0
  703. package/node_modules/@earendil-works/omk-ai/dist/providers/cloudflare.d.ts +13 -0
  704. package/node_modules/@earendil-works/omk-ai/dist/providers/cloudflare.d.ts.map +1 -0
  705. package/node_modules/@earendil-works/omk-ai/dist/providers/cloudflare.js +26 -0
  706. package/node_modules/@earendil-works/omk-ai/dist/providers/cloudflare.js.map +1 -0
  707. package/node_modules/@earendil-works/omk-ai/dist/providers/faux.d.ts +56 -0
  708. package/node_modules/@earendil-works/omk-ai/dist/providers/faux.d.ts.map +1 -0
  709. package/node_modules/@earendil-works/omk-ai/dist/providers/faux.js +368 -0
  710. package/node_modules/@earendil-works/omk-ai/dist/providers/faux.js.map +1 -0
  711. package/node_modules/@earendil-works/omk-ai/dist/providers/github-copilot-headers.d.ts +8 -0
  712. package/node_modules/@earendil-works/omk-ai/dist/providers/github-copilot-headers.d.ts.map +1 -0
  713. package/node_modules/@earendil-works/omk-ai/dist/providers/github-copilot-headers.js +29 -0
  714. package/node_modules/@earendil-works/omk-ai/dist/providers/github-copilot-headers.js.map +1 -0
  715. package/node_modules/@earendil-works/omk-ai/dist/providers/google-shared.d.ts +70 -0
  716. package/node_modules/@earendil-works/omk-ai/dist/providers/google-shared.d.ts.map +1 -0
  717. package/node_modules/@earendil-works/omk-ai/dist/providers/google-shared.js +331 -0
  718. package/node_modules/@earendil-works/omk-ai/dist/providers/google-shared.js.map +1 -0
  719. package/node_modules/@earendil-works/omk-ai/dist/providers/google-vertex.d.ts +15 -0
  720. package/node_modules/@earendil-works/omk-ai/dist/providers/google-vertex.d.ts.map +1 -0
  721. package/node_modules/@earendil-works/omk-ai/dist/providers/google-vertex.js +442 -0
  722. package/node_modules/@earendil-works/omk-ai/dist/providers/google-vertex.js.map +1 -0
  723. package/node_modules/@earendil-works/omk-ai/dist/providers/google.d.ts +13 -0
  724. package/node_modules/@earendil-works/omk-ai/dist/providers/google.d.ts.map +1 -0
  725. package/node_modules/@earendil-works/omk-ai/dist/providers/google.js +402 -0
  726. package/node_modules/@earendil-works/omk-ai/dist/providers/google.js.map +1 -0
  727. package/node_modules/@earendil-works/omk-ai/dist/providers/images/openrouter.d.ts +3 -0
  728. package/node_modules/@earendil-works/omk-ai/dist/providers/images/openrouter.d.ts.map +1 -0
  729. package/node_modules/@earendil-works/omk-ai/dist/providers/images/openrouter.js +128 -0
  730. package/node_modules/@earendil-works/omk-ai/dist/providers/images/openrouter.js.map +1 -0
  731. package/node_modules/@earendil-works/omk-ai/dist/providers/images/register-builtins.d.ts +4 -0
  732. package/node_modules/@earendil-works/omk-ai/dist/providers/images/register-builtins.d.ts.map +1 -0
  733. package/node_modules/@earendil-works/omk-ai/dist/providers/images/register-builtins.js +34 -0
  734. package/node_modules/@earendil-works/omk-ai/dist/providers/images/register-builtins.js.map +1 -0
  735. package/node_modules/@earendil-works/omk-ai/dist/providers/mistral.d.ts +25 -0
  736. package/node_modules/@earendil-works/omk-ai/dist/providers/mistral.d.ts.map +1 -0
  737. package/node_modules/@earendil-works/omk-ai/dist/providers/mistral.js +534 -0
  738. package/node_modules/@earendil-works/omk-ai/dist/providers/mistral.js.map +1 -0
  739. package/node_modules/@earendil-works/omk-ai/dist/providers/openai-codex-responses.d.ts +30 -0
  740. package/node_modules/@earendil-works/omk-ai/dist/providers/openai-codex-responses.d.ts.map +1 -0
  741. package/node_modules/@earendil-works/omk-ai/dist/providers/openai-codex-responses.js +1171 -0
  742. package/node_modules/@earendil-works/omk-ai/dist/providers/openai-codex-responses.js.map +1 -0
  743. package/node_modules/@earendil-works/omk-ai/dist/providers/openai-completions.d.ts +19 -0
  744. package/node_modules/@earendil-works/omk-ai/dist/providers/openai-completions.d.ts.map +1 -0
  745. package/node_modules/@earendil-works/omk-ai/dist/providers/openai-completions.js +977 -0
  746. package/node_modules/@earendil-works/omk-ai/dist/providers/openai-completions.js.map +1 -0
  747. package/node_modules/@earendil-works/omk-ai/dist/providers/openai-prompt-cache.d.ts +11 -0
  748. package/node_modules/@earendil-works/omk-ai/dist/providers/openai-prompt-cache.d.ts.map +1 -0
  749. package/node_modules/@earendil-works/omk-ai/dist/providers/openai-prompt-cache.js +22 -0
  750. package/node_modules/@earendil-works/omk-ai/dist/providers/openai-prompt-cache.js.map +1 -0
  751. package/node_modules/@earendil-works/omk-ai/dist/providers/openai-responses-shared.d.ts +18 -0
  752. package/node_modules/@earendil-works/omk-ai/dist/providers/openai-responses-shared.d.ts.map +1 -0
  753. package/node_modules/@earendil-works/omk-ai/dist/providers/openai-responses-shared.js +496 -0
  754. package/node_modules/@earendil-works/omk-ai/dist/providers/openai-responses-shared.js.map +1 -0
  755. package/node_modules/@earendil-works/omk-ai/dist/providers/openai-responses.d.ts +13 -0
  756. package/node_modules/@earendil-works/omk-ai/dist/providers/openai-responses.d.ts.map +1 -0
  757. package/node_modules/@earendil-works/omk-ai/dist/providers/openai-responses.js +233 -0
  758. package/node_modules/@earendil-works/omk-ai/dist/providers/openai-responses.js.map +1 -0
  759. package/node_modules/@earendil-works/omk-ai/dist/providers/register-builtins.d.ts +35 -0
  760. package/node_modules/@earendil-works/omk-ai/dist/providers/register-builtins.d.ts.map +1 -0
  761. package/node_modules/@earendil-works/omk-ai/dist/providers/register-builtins.js +254 -0
  762. package/node_modules/@earendil-works/omk-ai/dist/providers/register-builtins.js.map +1 -0
  763. package/node_modules/@earendil-works/omk-ai/dist/providers/simple-options.d.ts +8 -0
  764. package/node_modules/@earendil-works/omk-ai/dist/providers/simple-options.d.ts.map +1 -0
  765. package/node_modules/@earendil-works/omk-ai/dist/providers/simple-options.js +42 -0
  766. package/node_modules/@earendil-works/omk-ai/dist/providers/simple-options.js.map +1 -0
  767. package/node_modules/@earendil-works/omk-ai/dist/providers/tool-schema.d.ts +13 -0
  768. package/node_modules/@earendil-works/omk-ai/dist/providers/tool-schema.d.ts.map +1 -0
  769. package/node_modules/@earendil-works/omk-ai/dist/providers/tool-schema.js +82 -0
  770. package/node_modules/@earendil-works/omk-ai/dist/providers/tool-schema.js.map +1 -0
  771. package/node_modules/@earendil-works/omk-ai/dist/providers/transform-messages.d.ts +8 -0
  772. package/node_modules/@earendil-works/omk-ai/dist/providers/transform-messages.d.ts.map +1 -0
  773. package/node_modules/@earendil-works/omk-ai/dist/providers/transform-messages.js +184 -0
  774. package/node_modules/@earendil-works/omk-ai/dist/providers/transform-messages.js.map +1 -0
  775. package/node_modules/@earendil-works/omk-ai/dist/session-resources.d.ts +4 -0
  776. package/node_modules/@earendil-works/omk-ai/dist/session-resources.d.ts.map +1 -0
  777. package/node_modules/@earendil-works/omk-ai/dist/session-resources.js +22 -0
  778. package/node_modules/@earendil-works/omk-ai/dist/session-resources.js.map +1 -0
  779. package/node_modules/@earendil-works/omk-ai/dist/stream.d.ts +8 -0
  780. package/node_modules/@earendil-works/omk-ai/dist/stream.d.ts.map +1 -0
  781. package/node_modules/@earendil-works/omk-ai/dist/stream.js +77 -0
  782. package/node_modules/@earendil-works/omk-ai/dist/stream.js.map +1 -0
  783. package/node_modules/@earendil-works/omk-ai/dist/types.d.ts +570 -0
  784. package/node_modules/@earendil-works/omk-ai/dist/types.d.ts.map +1 -0
  785. package/node_modules/@earendil-works/omk-ai/dist/types.js +2 -0
  786. package/node_modules/@earendil-works/omk-ai/dist/types.js.map +1 -0
  787. package/node_modules/@earendil-works/omk-ai/dist/utils/abort-signals.d.ts +6 -0
  788. package/node_modules/@earendil-works/omk-ai/dist/utils/abort-signals.d.ts.map +1 -0
  789. package/node_modules/@earendil-works/omk-ai/dist/utils/abort-signals.js +34 -0
  790. package/node_modules/@earendil-works/omk-ai/dist/utils/abort-signals.js.map +1 -0
  791. package/node_modules/@earendil-works/omk-ai/dist/utils/diagnostics.d.ts +19 -0
  792. package/node_modules/@earendil-works/omk-ai/dist/utils/diagnostics.d.ts.map +1 -0
  793. package/node_modules/@earendil-works/omk-ai/dist/utils/diagnostics.js +25 -0
  794. package/node_modules/@earendil-works/omk-ai/dist/utils/diagnostics.js.map +1 -0
  795. package/node_modules/@earendil-works/omk-ai/dist/utils/event-stream.d.ts +21 -0
  796. package/node_modules/@earendil-works/omk-ai/dist/utils/event-stream.d.ts.map +1 -0
  797. package/node_modules/@earendil-works/omk-ai/dist/utils/event-stream.js +81 -0
  798. package/node_modules/@earendil-works/omk-ai/dist/utils/event-stream.js.map +1 -0
  799. package/node_modules/@earendil-works/omk-ai/dist/utils/hash.d.ts +3 -0
  800. package/node_modules/@earendil-works/omk-ai/dist/utils/hash.d.ts.map +1 -0
  801. package/node_modules/@earendil-works/omk-ai/dist/utils/hash.js +14 -0
  802. package/node_modules/@earendil-works/omk-ai/dist/utils/hash.js.map +1 -0
  803. package/node_modules/@earendil-works/omk-ai/dist/utils/headers.d.ts +2 -0
  804. package/node_modules/@earendil-works/omk-ai/dist/utils/headers.d.ts.map +1 -0
  805. package/node_modules/@earendil-works/omk-ai/dist/utils/headers.js +8 -0
  806. package/node_modules/@earendil-works/omk-ai/dist/utils/headers.js.map +1 -0
  807. package/node_modules/@earendil-works/omk-ai/dist/utils/json-parse.d.ts +16 -0
  808. package/node_modules/@earendil-works/omk-ai/dist/utils/json-parse.d.ts.map +1 -0
  809. package/node_modules/@earendil-works/omk-ai/dist/utils/json-parse.js +113 -0
  810. package/node_modules/@earendil-works/omk-ai/dist/utils/json-parse.js.map +1 -0
  811. package/node_modules/@earendil-works/omk-ai/dist/utils/node-http-proxy.d.ts +10 -0
  812. package/node_modules/@earendil-works/omk-ai/dist/utils/node-http-proxy.d.ts.map +1 -0
  813. package/node_modules/@earendil-works/omk-ai/dist/utils/node-http-proxy.js +97 -0
  814. package/node_modules/@earendil-works/omk-ai/dist/utils/node-http-proxy.js.map +1 -0
  815. package/node_modules/@earendil-works/omk-ai/dist/utils/oauth/anthropic.d.ts +25 -0
  816. package/node_modules/@earendil-works/omk-ai/dist/utils/oauth/anthropic.d.ts.map +1 -0
  817. package/node_modules/@earendil-works/omk-ai/dist/utils/oauth/anthropic.js +335 -0
  818. package/node_modules/@earendil-works/omk-ai/dist/utils/oauth/anthropic.js.map +1 -0
  819. package/node_modules/@earendil-works/omk-ai/dist/utils/oauth/device-code.d.ts +21 -0
  820. package/node_modules/@earendil-works/omk-ai/dist/utils/oauth/device-code.d.ts.map +1 -0
  821. package/node_modules/@earendil-works/omk-ai/dist/utils/oauth/device-code.js +56 -0
  822. package/node_modules/@earendil-works/omk-ai/dist/utils/oauth/device-code.js.map +1 -0
  823. package/node_modules/@earendil-works/omk-ai/dist/utils/oauth/github-copilot.d.ts +30 -0
  824. package/node_modules/@earendil-works/omk-ai/dist/utils/oauth/github-copilot.d.ts.map +1 -0
  825. package/node_modules/@earendil-works/omk-ai/dist/utils/oauth/github-copilot.js +280 -0
  826. package/node_modules/@earendil-works/omk-ai/dist/utils/oauth/github-copilot.js.map +1 -0
  827. package/node_modules/@earendil-works/omk-ai/dist/utils/oauth/index.d.ts +58 -0
  828. package/node_modules/@earendil-works/omk-ai/dist/utils/oauth/index.d.ts.map +1 -0
  829. package/node_modules/@earendil-works/omk-ai/dist/utils/oauth/index.js +122 -0
  830. package/node_modules/@earendil-works/omk-ai/dist/utils/oauth/index.js.map +1 -0
  831. package/node_modules/@earendil-works/omk-ai/dist/utils/oauth/oauth-page.d.ts +3 -0
  832. package/node_modules/@earendil-works/omk-ai/dist/utils/oauth/oauth-page.d.ts.map +1 -0
  833. package/node_modules/@earendil-works/omk-ai/dist/utils/oauth/oauth-page.js +105 -0
  834. package/node_modules/@earendil-works/omk-ai/dist/utils/oauth/oauth-page.js.map +1 -0
  835. package/node_modules/@earendil-works/omk-ai/dist/utils/oauth/openai-codex.d.ts +43 -0
  836. package/node_modules/@earendil-works/omk-ai/dist/utils/oauth/openai-codex.d.ts.map +1 -0
  837. package/node_modules/@earendil-works/omk-ai/dist/utils/oauth/openai-codex.js +487 -0
  838. package/node_modules/@earendil-works/omk-ai/dist/utils/oauth/openai-codex.js.map +1 -0
  839. package/node_modules/@earendil-works/omk-ai/dist/utils/oauth/pkce.d.ts +13 -0
  840. package/node_modules/@earendil-works/omk-ai/dist/utils/oauth/pkce.d.ts.map +1 -0
  841. package/node_modules/@earendil-works/omk-ai/dist/utils/oauth/pkce.js +31 -0
  842. package/node_modules/@earendil-works/omk-ai/dist/utils/oauth/pkce.js.map +1 -0
  843. package/node_modules/@earendil-works/omk-ai/dist/utils/oauth/types.d.ts +64 -0
  844. package/node_modules/@earendil-works/omk-ai/dist/utils/oauth/types.d.ts.map +1 -0
  845. package/node_modules/@earendil-works/omk-ai/dist/utils/oauth/types.js +2 -0
  846. package/node_modules/@earendil-works/omk-ai/dist/utils/oauth/types.js.map +1 -0
  847. package/node_modules/@earendil-works/omk-ai/dist/utils/overflow.d.ts +57 -0
  848. package/node_modules/@earendil-works/omk-ai/dist/utils/overflow.d.ts.map +1 -0
  849. package/node_modules/@earendil-works/omk-ai/dist/utils/overflow.js +154 -0
  850. package/node_modules/@earendil-works/omk-ai/dist/utils/overflow.js.map +1 -0
  851. package/node_modules/@earendil-works/omk-ai/dist/utils/sanitize-unicode.d.ts +22 -0
  852. package/node_modules/@earendil-works/omk-ai/dist/utils/sanitize-unicode.d.ts.map +1 -0
  853. package/node_modules/@earendil-works/omk-ai/dist/utils/sanitize-unicode.js +26 -0
  854. package/node_modules/@earendil-works/omk-ai/dist/utils/sanitize-unicode.js.map +1 -0
  855. package/node_modules/@earendil-works/omk-ai/dist/utils/typebox-helpers.d.ts +17 -0
  856. package/node_modules/@earendil-works/omk-ai/dist/utils/typebox-helpers.d.ts.map +1 -0
  857. package/node_modules/@earendil-works/omk-ai/dist/utils/typebox-helpers.js +21 -0
  858. package/node_modules/@earendil-works/omk-ai/dist/utils/typebox-helpers.js.map +1 -0
  859. package/node_modules/@earendil-works/omk-ai/dist/utils/validation.d.ts +18 -0
  860. package/node_modules/@earendil-works/omk-ai/dist/utils/validation.d.ts.map +1 -0
  861. package/node_modules/@earendil-works/omk-ai/dist/utils/validation.js +281 -0
  862. package/node_modules/@earendil-works/omk-ai/dist/utils/validation.js.map +1 -0
  863. package/node_modules/@earendil-works/omk-ai/package.json +106 -0
  864. package/node_modules/@earendil-works/omk-tui/README.md +791 -0
  865. package/node_modules/@earendil-works/omk-tui/dist/autocomplete.d.ts +54 -0
  866. package/node_modules/@earendil-works/omk-tui/dist/autocomplete.d.ts.map +1 -0
  867. package/node_modules/@earendil-works/omk-tui/dist/autocomplete.js +632 -0
  868. package/node_modules/@earendil-works/omk-tui/dist/autocomplete.js.map +1 -0
  869. package/node_modules/@earendil-works/omk-tui/dist/components/box.d.ts +22 -0
  870. package/node_modules/@earendil-works/omk-tui/dist/components/box.d.ts.map +1 -0
  871. package/node_modules/@earendil-works/omk-tui/dist/components/box.js +104 -0
  872. package/node_modules/@earendil-works/omk-tui/dist/components/box.js.map +1 -0
  873. package/node_modules/@earendil-works/omk-tui/dist/components/cancellable-loader.d.ts +22 -0
  874. package/node_modules/@earendil-works/omk-tui/dist/components/cancellable-loader.d.ts.map +1 -0
  875. package/node_modules/@earendil-works/omk-tui/dist/components/cancellable-loader.js +35 -0
  876. package/node_modules/@earendil-works/omk-tui/dist/components/cancellable-loader.js.map +1 -0
  877. package/node_modules/@earendil-works/omk-tui/dist/components/editor.d.ts +249 -0
  878. package/node_modules/@earendil-works/omk-tui/dist/components/editor.d.ts.map +1 -0
  879. package/node_modules/@earendil-works/omk-tui/dist/components/editor.js +1857 -0
  880. package/node_modules/@earendil-works/omk-tui/dist/components/editor.js.map +1 -0
  881. package/node_modules/@earendil-works/omk-tui/dist/components/image.d.ts +28 -0
  882. package/node_modules/@earendil-works/omk-tui/dist/components/image.d.ts.map +1 -0
  883. package/node_modules/@earendil-works/omk-tui/dist/components/image.js +89 -0
  884. package/node_modules/@earendil-works/omk-tui/dist/components/image.js.map +1 -0
  885. package/node_modules/@earendil-works/omk-tui/dist/components/input.d.ts +37 -0
  886. package/node_modules/@earendil-works/omk-tui/dist/components/input.d.ts.map +1 -0
  887. package/node_modules/@earendil-works/omk-tui/dist/components/input.js +378 -0
  888. package/node_modules/@earendil-works/omk-tui/dist/components/input.js.map +1 -0
  889. package/node_modules/@earendil-works/omk-tui/dist/components/loader.d.ts +31 -0
  890. package/node_modules/@earendil-works/omk-tui/dist/components/loader.d.ts.map +1 -0
  891. package/node_modules/@earendil-works/omk-tui/dist/components/loader.js +69 -0
  892. package/node_modules/@earendil-works/omk-tui/dist/components/loader.js.map +1 -0
  893. package/node_modules/@earendil-works/omk-tui/dist/components/markdown.d.ts +96 -0
  894. package/node_modules/@earendil-works/omk-tui/dist/components/markdown.d.ts.map +1 -0
  895. package/node_modules/@earendil-works/omk-tui/dist/components/markdown.js +644 -0
  896. package/node_modules/@earendil-works/omk-tui/dist/components/markdown.js.map +1 -0
  897. package/node_modules/@earendil-works/omk-tui/dist/components/select-list.d.ts +50 -0
  898. package/node_modules/@earendil-works/omk-tui/dist/components/select-list.d.ts.map +1 -0
  899. package/node_modules/@earendil-works/omk-tui/dist/components/select-list.js +159 -0
  900. package/node_modules/@earendil-works/omk-tui/dist/components/select-list.js.map +1 -0
  901. package/node_modules/@earendil-works/omk-tui/dist/components/settings-list.d.ts +50 -0
  902. package/node_modules/@earendil-works/omk-tui/dist/components/settings-list.d.ts.map +1 -0
  903. package/node_modules/@earendil-works/omk-tui/dist/components/settings-list.js +185 -0
  904. package/node_modules/@earendil-works/omk-tui/dist/components/settings-list.js.map +1 -0
  905. package/node_modules/@earendil-works/omk-tui/dist/components/spacer.d.ts +12 -0
  906. package/node_modules/@earendil-works/omk-tui/dist/components/spacer.d.ts.map +1 -0
  907. package/node_modules/@earendil-works/omk-tui/dist/components/spacer.js +23 -0
  908. package/node_modules/@earendil-works/omk-tui/dist/components/spacer.js.map +1 -0
  909. package/node_modules/@earendil-works/omk-tui/dist/components/text.d.ts +19 -0
  910. package/node_modules/@earendil-works/omk-tui/dist/components/text.d.ts.map +1 -0
  911. package/node_modules/@earendil-works/omk-tui/dist/components/text.js +89 -0
  912. package/node_modules/@earendil-works/omk-tui/dist/components/text.js.map +1 -0
  913. package/node_modules/@earendil-works/omk-tui/dist/components/truncated-text.d.ts +13 -0
  914. package/node_modules/@earendil-works/omk-tui/dist/components/truncated-text.d.ts.map +1 -0
  915. package/node_modules/@earendil-works/omk-tui/dist/components/truncated-text.js +51 -0
  916. package/node_modules/@earendil-works/omk-tui/dist/components/truncated-text.js.map +1 -0
  917. package/node_modules/@earendil-works/omk-tui/dist/editor-component.d.ts +39 -0
  918. package/node_modules/@earendil-works/omk-tui/dist/editor-component.d.ts.map +1 -0
  919. package/node_modules/@earendil-works/omk-tui/dist/editor-component.js +2 -0
  920. package/node_modules/@earendil-works/omk-tui/dist/editor-component.js.map +1 -0
  921. package/node_modules/@earendil-works/omk-tui/dist/fuzzy.d.ts +16 -0
  922. package/node_modules/@earendil-works/omk-tui/dist/fuzzy.d.ts.map +1 -0
  923. package/node_modules/@earendil-works/omk-tui/dist/fuzzy.js +110 -0
  924. package/node_modules/@earendil-works/omk-tui/dist/fuzzy.js.map +1 -0
  925. package/node_modules/@earendil-works/omk-tui/dist/index.d.ts +23 -0
  926. package/node_modules/@earendil-works/omk-tui/dist/index.d.ts.map +1 -0
  927. package/node_modules/@earendil-works/omk-tui/dist/index.js +32 -0
  928. package/node_modules/@earendil-works/omk-tui/dist/index.js.map +1 -0
  929. package/node_modules/@earendil-works/omk-tui/dist/keybindings.d.ts +212 -0
  930. package/node_modules/@earendil-works/omk-tui/dist/keybindings.d.ts.map +1 -0
  931. package/node_modules/@earendil-works/omk-tui/dist/keybindings.js +252 -0
  932. package/node_modules/@earendil-works/omk-tui/dist/keybindings.js.map +1 -0
  933. package/node_modules/@earendil-works/omk-tui/dist/keys.d.ts +184 -0
  934. package/node_modules/@earendil-works/omk-tui/dist/keys.d.ts.map +1 -0
  935. package/node_modules/@earendil-works/omk-tui/dist/keys.js +1173 -0
  936. package/node_modules/@earendil-works/omk-tui/dist/keys.js.map +1 -0
  937. package/node_modules/@earendil-works/omk-tui/dist/kill-ring.d.ts +28 -0
  938. package/node_modules/@earendil-works/omk-tui/dist/kill-ring.d.ts.map +1 -0
  939. package/node_modules/@earendil-works/omk-tui/dist/kill-ring.js +44 -0
  940. package/node_modules/@earendil-works/omk-tui/dist/kill-ring.js.map +1 -0
  941. package/node_modules/@earendil-works/omk-tui/dist/native-modifiers.d.ts +3 -0
  942. package/node_modules/@earendil-works/omk-tui/dist/native-modifiers.d.ts.map +1 -0
  943. package/node_modules/@earendil-works/omk-tui/dist/native-modifiers.js +53 -0
  944. package/node_modules/@earendil-works/omk-tui/dist/native-modifiers.js.map +1 -0
  945. package/node_modules/@earendil-works/omk-tui/dist/stdin-buffer.d.ts +50 -0
  946. package/node_modules/@earendil-works/omk-tui/dist/stdin-buffer.d.ts.map +1 -0
  947. package/node_modules/@earendil-works/omk-tui/dist/stdin-buffer.js +361 -0
  948. package/node_modules/@earendil-works/omk-tui/dist/stdin-buffer.js.map +1 -0
  949. package/node_modules/@earendil-works/omk-tui/dist/terminal-image.d.ts +90 -0
  950. package/node_modules/@earendil-works/omk-tui/dist/terminal-image.d.ts.map +1 -0
  951. package/node_modules/@earendil-works/omk-tui/dist/terminal-image.js +366 -0
  952. package/node_modules/@earendil-works/omk-tui/dist/terminal-image.js.map +1 -0
  953. package/node_modules/@earendil-works/omk-tui/dist/terminal.d.ts +113 -0
  954. package/node_modules/@earendil-works/omk-tui/dist/terminal.d.ts.map +1 -0
  955. package/node_modules/@earendil-works/omk-tui/dist/terminal.js +472 -0
  956. package/node_modules/@earendil-works/omk-tui/dist/terminal.js.map +1 -0
  957. package/node_modules/@earendil-works/omk-tui/dist/tui.d.ts +242 -0
  958. package/node_modules/@earendil-works/omk-tui/dist/tui.d.ts.map +1 -0
  959. package/node_modules/@earendil-works/omk-tui/dist/tui.js +1221 -0
  960. package/node_modules/@earendil-works/omk-tui/dist/tui.js.map +1 -0
  961. package/node_modules/@earendil-works/omk-tui/dist/undo-stack.d.ts +17 -0
  962. package/node_modules/@earendil-works/omk-tui/dist/undo-stack.d.ts.map +1 -0
  963. package/node_modules/@earendil-works/omk-tui/dist/undo-stack.js +25 -0
  964. package/node_modules/@earendil-works/omk-tui/dist/undo-stack.js.map +1 -0
  965. package/node_modules/@earendil-works/omk-tui/dist/utils.d.ts +84 -0
  966. package/node_modules/@earendil-works/omk-tui/dist/utils.d.ts.map +1 -0
  967. package/node_modules/@earendil-works/omk-tui/dist/utils.js +1032 -0
  968. package/node_modules/@earendil-works/omk-tui/dist/utils.js.map +1 -0
  969. package/node_modules/@earendil-works/omk-tui/dist/word-navigation.d.ts +25 -0
  970. package/node_modules/@earendil-works/omk-tui/dist/word-navigation.d.ts.map +1 -0
  971. package/node_modules/@earendil-works/omk-tui/dist/word-navigation.js +96 -0
  972. package/node_modules/@earendil-works/omk-tui/dist/word-navigation.js.map +1 -0
  973. package/node_modules/@earendil-works/omk-tui/native/darwin/prebuilds/darwin-arm64/darwin-modifiers.node +0 -0
  974. package/node_modules/@earendil-works/omk-tui/native/darwin/prebuilds/darwin-x64/darwin-modifiers.node +0 -0
  975. package/node_modules/@earendil-works/omk-tui/native/win32/prebuilds/win32-arm64/win32-console-mode.node +0 -0
  976. package/node_modules/@earendil-works/omk-tui/native/win32/prebuilds/win32-x64/win32-console-mode.node +0 -0
  977. package/node_modules/@earendil-works/omk-tui/package.json +47 -0
  978. package/package.json +22 -6
  979. package/dist/utils/pi-user-agent.d.ts +0 -2
  980. package/dist/utils/pi-user-agent.d.ts.map +0 -1
  981. package/dist/utils/pi-user-agent.js.map +0 -1
@@ -0,0 +1,261 @@
1
+ import { fuzzyFilter } from "@earendil-works/omk-tui";
2
+ export const ALL_PROVIDER_TAB = "all";
3
+ /**
4
+ * Preferred display order for first-party providers. Anything outside this list
5
+ * is treated as a custom provider and sorted lexicographically after the known
6
+ * providers (see {@link buildProviderTabs}).
7
+ */
8
+ export const KNOWN_PROVIDER_ORDER = [
9
+ "anthropic",
10
+ "openai",
11
+ "google",
12
+ "deepseek",
13
+ "kimi",
14
+ "openrouter",
15
+ "mistral",
16
+ "xai",
17
+ "groq",
18
+ "zai",
19
+ "together",
20
+ "fireworks",
21
+ ];
22
+ export function modelSelectorModelKey(model) {
23
+ return `${model.provider}/${model.id}`;
24
+ }
25
+ function isKnownProvider(provider) {
26
+ return KNOWN_PROVIDER_ORDER.includes(provider);
27
+ }
28
+ /**
29
+ * Build the provider tab ring: `all` first, then known providers in their
30
+ * canonical order, then any custom providers sorted lexicographically.
31
+ */
32
+ export function buildProviderTabs(models) {
33
+ const providerIds = Array.from(new Set(models.map((model) => model.provider)));
34
+ const ordered = KNOWN_PROVIDER_ORDER.filter((provider) => providerIds.includes(provider));
35
+ const extras = providerIds.filter((provider) => !isKnownProvider(provider)).sort((a, b) => a.localeCompare(b));
36
+ return [ALL_PROVIDER_TAB, ...ordered, ...extras];
37
+ }
38
+ function filterByProvider(models, activeProvider) {
39
+ if (activeProvider === ALL_PROVIDER_TAB)
40
+ return models;
41
+ return models.filter((model) => model.provider === activeProvider);
42
+ }
43
+ function applySearch(models, query) {
44
+ if (!query)
45
+ return models;
46
+ return fuzzyFilter([...models], query, ({ id, provider }) => `${id} ${provider} ${provider}/${id} ${provider} ${id}`);
47
+ }
48
+ function clampIndex(index, length) {
49
+ if (length === 0)
50
+ return 0;
51
+ return Math.min(Math.max(index, 0), length - 1);
52
+ }
53
+ export function createInitialModelSelectorState(options = {}) {
54
+ return {
55
+ scope: options.scope ?? "all",
56
+ activeProvider: options.activeProvider ?? ALL_PROVIDER_TAB,
57
+ providerIds: [ALL_PROVIDER_TAB],
58
+ query: options.query ?? "",
59
+ selectedIndex: 0,
60
+ visibleModelKeys: [],
61
+ allModels: [],
62
+ scopedModels: [],
63
+ currentModelKey: undefined,
64
+ };
65
+ }
66
+ /**
67
+ * Recompute provider tabs, the validated active provider, and the visible model
68
+ * list for the given corpus/scope/query, then resolve the selected index with
69
+ * the supplied strategy. Centralizing this keeps every transition consistent
70
+ * with the contract invariants.
71
+ */
72
+ function project(overrides) {
73
+ const corpus = overrides.scope === "scoped" ? overrides.scopedModels : overrides.allModels;
74
+ const providerIds = buildProviderTabs(corpus);
75
+ const activeProvider = providerIds.includes(overrides.desiredProvider)
76
+ ? overrides.desiredProvider
77
+ : ALL_PROVIDER_TAB;
78
+ const providerFiltered = filterByProvider(corpus, activeProvider);
79
+ const visible = applySearch(providerFiltered, overrides.query);
80
+ const visibleModelKeys = visible.map(modelSelectorModelKey);
81
+ const selectedIndex = clampIndex(overrides.select({
82
+ visibleKeys: visibleModelKeys,
83
+ providerFilteredKeys: providerFiltered.map(modelSelectorModelKey),
84
+ }), visibleModelKeys.length);
85
+ return {
86
+ scope: overrides.scope,
87
+ activeProvider,
88
+ providerIds,
89
+ query: overrides.query,
90
+ selectedIndex,
91
+ visibleModelKeys,
92
+ allModels: overrides.allModels,
93
+ scopedModels: overrides.scopedModels,
94
+ currentModelKey: overrides.currentModelKey,
95
+ };
96
+ }
97
+ export function modelSelectorReducer(state, action) {
98
+ switch (action.type) {
99
+ case "REFRESH_MODELS":
100
+ return project({
101
+ scope: state.scope,
102
+ allModels: action.allModels,
103
+ scopedModels: action.scopedModels,
104
+ query: state.query,
105
+ currentModelKey: action.currentModelKey,
106
+ desiredProvider: state.activeProvider,
107
+ select: ({ visibleKeys }) => {
108
+ const currentIndex = action.currentModelKey ? visibleKeys.indexOf(action.currentModelKey) : -1;
109
+ return currentIndex >= 0
110
+ ? currentIndex
111
+ : Math.min(state.selectedIndex, Math.max(0, visibleKeys.length - 1));
112
+ },
113
+ });
114
+ case "NEXT_PROVIDER":
115
+ case "PREVIOUS_PROVIDER": {
116
+ if (state.providerIds.length === 0)
117
+ return state;
118
+ const direction = action.type === "NEXT_PROVIDER" ? 1 : -1;
119
+ const currentIndex = Math.max(0, state.providerIds.indexOf(state.activeProvider));
120
+ const nextIndex = (currentIndex + direction + state.providerIds.length) % state.providerIds.length;
121
+ const desiredProvider = state.providerIds[nextIndex] ?? ALL_PROVIDER_TAB;
122
+ return project({
123
+ scope: state.scope,
124
+ allModels: state.allModels,
125
+ scopedModels: state.scopedModels,
126
+ query: state.query,
127
+ currentModelKey: state.currentModelKey,
128
+ desiredProvider,
129
+ select: () => 0,
130
+ });
131
+ }
132
+ case "TOGGLE_SCOPE_FORWARD":
133
+ case "TOGGLE_SCOPE_BACKWARD": {
134
+ // Scope is a two-state toggle (all <-> scoped); both directions flip it.
135
+ // Without scoped models there is nothing to toggle into.
136
+ if (state.scopedModels.length === 0)
137
+ return state;
138
+ const scope = state.scope === "all" ? "scoped" : "all";
139
+ return project({
140
+ scope,
141
+ allModels: state.allModels,
142
+ scopedModels: state.scopedModels,
143
+ query: state.query,
144
+ currentModelKey: state.currentModelKey,
145
+ desiredProvider: state.activeProvider,
146
+ select: ({ providerFilteredKeys }) => {
147
+ const currentIndex = state.currentModelKey ? providerFilteredKeys.indexOf(state.currentModelKey) : -1;
148
+ return currentIndex >= 0 ? currentIndex : 0;
149
+ },
150
+ });
151
+ }
152
+ case "SEARCH":
153
+ return project({
154
+ scope: state.scope,
155
+ allModels: state.allModels,
156
+ scopedModels: state.scopedModels,
157
+ query: action.query,
158
+ currentModelKey: state.currentModelKey,
159
+ desiredProvider: state.activeProvider,
160
+ select: () => state.selectedIndex,
161
+ });
162
+ case "MOVE_SELECTION": {
163
+ const length = state.visibleModelKeys.length;
164
+ if (length === 0)
165
+ return state;
166
+ const selectedIndex = action.delta === -1
167
+ ? state.selectedIndex === 0
168
+ ? length - 1
169
+ : state.selectedIndex - 1
170
+ : state.selectedIndex === length - 1
171
+ ? 0
172
+ : state.selectedIndex + 1;
173
+ return { ...state, selectedIndex };
174
+ }
175
+ }
176
+ }
177
+ /** Resolve the selected model key, if any, for the current visible list. */
178
+ export function selectedModelKey(state) {
179
+ return state.visibleModelKeys[state.selectedIndex];
180
+ }
181
+ function providerStripWidth(indices, tabWidths, separatorWidth, ellipsisWidth) {
182
+ if (indices.length === 0)
183
+ return 0;
184
+ let total = 0;
185
+ let gaps = 0;
186
+ for (let k = 0; k < indices.length; k++) {
187
+ const current = indices[k] ?? 0;
188
+ total += tabWidths[current] ?? 0;
189
+ if (k > 0) {
190
+ total += separatorWidth;
191
+ if (current - (indices[k - 1] ?? 0) > 1)
192
+ gaps += 1;
193
+ }
194
+ }
195
+ const last = indices[indices.length - 1] ?? 0;
196
+ const trailing = last < tabWidths.length - 1 ? 1 : 0;
197
+ // Each ellipsis renders as its own segment joined by a separator, so it costs
198
+ // a separator in addition to the ellipsis glyph.
199
+ return total + (ellipsisWidth + separatorWidth) * (gaps + trailing);
200
+ }
201
+ /**
202
+ * Window a provider tab strip into a visible-column budget so the row never
203
+ * overflows the terminal while always keeping the "all" anchor (index 0) and the
204
+ * active tab visible. When the full strip fits, every tab is shown. Otherwise a
205
+ * contiguous window is grown around the active tab (right-biased, then left),
206
+ * with a single leading ellipsis for a hidden middle and a trailing ellipsis for
207
+ * hidden tail tabs.
208
+ *
209
+ * Pure and presentation-agnostic: callers pass the visible width of each themed
210
+ * tab label (via omk-tui `visibleWidth`) plus the separator/ellipsis widths.
211
+ * If the budget cannot even hold the mandatory {all, active} tabs, those are
212
+ * still returned (the caller may then hard-truncate).
213
+ */
214
+ export function fitProviderStrip(tabWidths, activeIndex, budget, separatorWidth, ellipsisWidth) {
215
+ const n = tabWidths.length;
216
+ if (n === 0)
217
+ return { indices: [], ellipsisAfterFirst: false, trailingEllipsis: false };
218
+ const allIndices = Array.from({ length: n }, (_, i) => i);
219
+ if (providerStripWidth(allIndices, tabWidths, separatorWidth, ellipsisWidth) <= budget) {
220
+ return { indices: allIndices, ellipsisAfterFirst: false, trailingEllipsis: false };
221
+ }
222
+ const active = Math.max(0, Math.min(activeIndex, n - 1));
223
+ const shown = new Set([0, active]);
224
+ const sortedShown = () => [...shown].sort((a, b) => a - b);
225
+ let low = active;
226
+ let high = active;
227
+ let progressed = true;
228
+ while (progressed) {
229
+ progressed = false;
230
+ if (high + 1 < n && !shown.has(high + 1)) {
231
+ shown.add(high + 1);
232
+ if (providerStripWidth(sortedShown(), tabWidths, separatorWidth, ellipsisWidth) <= budget) {
233
+ high += 1;
234
+ progressed = true;
235
+ }
236
+ else {
237
+ shown.delete(high + 1);
238
+ }
239
+ }
240
+ if (low - 1 > 0 && !shown.has(low - 1)) {
241
+ shown.add(low - 1);
242
+ if (providerStripWidth(sortedShown(), tabWidths, separatorWidth, ellipsisWidth) <= budget) {
243
+ low -= 1;
244
+ progressed = true;
245
+ }
246
+ else {
247
+ shown.delete(low - 1);
248
+ }
249
+ }
250
+ }
251
+ const indices = sortedShown();
252
+ const first = indices[0] ?? 0;
253
+ const second = indices[1] ?? first;
254
+ const last = indices[indices.length - 1] ?? 0;
255
+ return {
256
+ indices,
257
+ ellipsisAfterFirst: indices.length > 1 && second - first > 1,
258
+ trailingEllipsis: last < n - 1,
259
+ };
260
+ }
261
+ //# sourceMappingURL=model-selector-state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-selector-state.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/model-selector-state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAgBtD,MAAM,CAAC,MAAM,gBAAgB,GAAG,KAAc,CAAC;AAE/C;;;;GAIG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG;IACnC,WAAW;IACX,QAAQ;IACR,QAAQ;IACR,UAAU;IACV,MAAM;IACN,YAAY;IACZ,SAAS;IACT,KAAK;IACL,MAAM;IACN,KAAK;IACL,UAAU;IACV,WAAW;CACF,CAAC;AAwCX,MAAM,UAAU,qBAAqB,CAAC,KAAyD,EAAU;IACxG,OAAO,GAAG,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,EAAE,EAAE,CAAC;AAAA,CACvC;AAED,SAAS,eAAe,CAAC,QAAgB,EAAW;IACnD,OAAQ,oBAA0C,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;AAAA,CACtE;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,MAAqC,EAAiB;IACvF,MAAM,WAAW,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;IAC/E,MAAM,OAAO,GAAG,oBAAoB,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,WAAW,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC1F,MAAM,MAAM,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/G,OAAO,CAAC,gBAAgB,EAAE,GAAG,OAAO,EAAE,GAAG,MAAM,CAAC,CAAC;AAAA,CACjD;AAED,SAAS,gBAAgB,CACxB,MAAqC,EACrC,cAA2B,EACK;IAChC,IAAI,cAAc,KAAK,gBAAgB;QAAE,OAAO,MAAM,CAAC;IACvD,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,KAAK,cAAc,CAAC,CAAC;AAAA,CACnE;AAED,SAAS,WAAW,CAAC,MAAqC,EAAE,KAAa,EAAiC;IACzG,IAAI,CAAC,KAAK;QAAE,OAAO,MAAM,CAAC;IAC1B,OAAO,WAAW,CACjB,CAAC,GAAG,MAAM,CAAC,EACX,KAAK,EACL,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,GAAG,EAAE,IAAI,QAAQ,IAAI,QAAQ,IAAI,EAAE,IAAI,QAAQ,IAAI,EAAE,EAAE,CAC7E,CAAC;AAAA,CACF;AAED,SAAS,UAAU,CAAC,KAAa,EAAE,MAAc,EAAU;IAC1D,IAAI,MAAM,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IAC3B,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,CAAC;AAAA,CAChD;AAQD,MAAM,UAAU,+BAA+B,CAAC,OAAO,GAAyB,EAAE,EAAsB;IACvG,OAAO;QACN,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,KAAK;QAC7B,cAAc,EAAE,OAAO,CAAC,cAAc,IAAI,gBAAgB;QAC1D,WAAW,EAAE,CAAC,gBAAgB,CAAC;QAC/B,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,EAAE;QAC1B,aAAa,EAAE,CAAC;QAChB,gBAAgB,EAAE,EAAE;QACpB,SAAS,EAAE,EAAE;QACb,YAAY,EAAE,EAAE;QAChB,eAAe,EAAE,SAAS;KAC1B,CAAC;AAAA,CACF;AAED;;;;;GAKG;AACH,SAAS,OAAO,CAAC,SAWhB,EAAsB;IACtB,MAAM,MAAM,GAAG,SAAS,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC;IAC3F,MAAM,WAAW,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAC9C,MAAM,cAAc,GAAG,WAAW,CAAC,QAAQ,CAAC,SAAS,CAAC,eAAe,CAAC;QACrE,CAAC,CAAC,SAAS,CAAC,eAAe;QAC3B,CAAC,CAAC,gBAAgB,CAAC;IACpB,MAAM,gBAAgB,GAAG,gBAAgB,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAClE,MAAM,OAAO,GAAG,WAAW,CAAC,gBAAgB,EAAE,SAAS,CAAC,KAAK,CAAC,CAAC;IAC/D,MAAM,gBAAgB,GAAG,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC;IAC5D,MAAM,aAAa,GAAG,UAAU,CAC/B,SAAS,CAAC,MAAM,CAAC;QAChB,WAAW,EAAE,gBAAgB;QAC7B,oBAAoB,EAAE,gBAAgB,CAAC,GAAG,CAAC,qBAAqB,CAAC;KACjE,CAAC,EACF,gBAAgB,CAAC,MAAM,CACvB,CAAC;IACF,OAAO;QACN,KAAK,EAAE,SAAS,CAAC,KAAK;QACtB,cAAc;QACd,WAAW;QACX,KAAK,EAAE,SAAS,CAAC,KAAK;QACtB,aAAa;QACb,gBAAgB;QAChB,SAAS,EAAE,SAAS,CAAC,SAAS;QAC9B,YAAY,EAAE,SAAS,CAAC,YAAY;QACpC,eAAe,EAAE,SAAS,CAAC,eAAe;KAC1C,CAAC;AAAA,CACF;AAED,MAAM,UAAU,oBAAoB,CAAC,KAAyB,EAAE,MAA2B,EAAsB;IAChH,QAAQ,MAAM,CAAC,IAAI,EAAE,CAAC;QACrB,KAAK,gBAAgB;YACpB,OAAO,OAAO,CAAC;gBACd,KAAK,EAAE,KAAK,CAAC,KAAK;gBAClB,SAAS,EAAE,MAAM,CAAC,SAAS;gBAC3B,YAAY,EAAE,MAAM,CAAC,YAAY;gBACjC,KAAK,EAAE,KAAK,CAAC,KAAK;gBAClB,eAAe,EAAE,MAAM,CAAC,eAAe;gBACvC,eAAe,EAAE,KAAK,CAAC,cAAc;gBACrC,MAAM,EAAE,CAAC,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC;oBAC5B,MAAM,YAAY,GAAG,MAAM,CAAC,eAAe,CAAC,CAAC,CAAC,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;oBAC/F,OAAO,YAAY,IAAI,CAAC;wBACvB,CAAC,CAAC,YAAY;wBACd,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,aAAa,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;gBAAA,CACtE;aACD,CAAC,CAAC;QAEJ,KAAK,eAAe,CAAC;QACrB,KAAK,mBAAmB,EAAE,CAAC;YAC1B,IAAI,KAAK,CAAC,WAAW,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO,KAAK,CAAC;YACjD,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,KAAK,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC3D,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,WAAW,CAAC,OAAO,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC;YAClF,MAAM,SAAS,GAAG,CAAC,YAAY,GAAG,SAAS,GAAG,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,GAAG,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC;YACnG,MAAM,eAAe,GAAG,KAAK,CAAC,WAAW,CAAC,SAAS,CAAC,IAAI,gBAAgB,CAAC;YACzE,OAAO,OAAO,CAAC;gBACd,KAAK,EAAE,KAAK,CAAC,KAAK;gBAClB,SAAS,EAAE,KAAK,CAAC,SAAS;gBAC1B,YAAY,EAAE,KAAK,CAAC,YAAY;gBAChC,KAAK,EAAE,KAAK,CAAC,KAAK;gBAClB,eAAe,EAAE,KAAK,CAAC,eAAe;gBACtC,eAAe;gBACf,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;aACf,CAAC,CAAC;QACJ,CAAC;QAED,KAAK,sBAAsB,CAAC;QAC5B,KAAK,uBAAuB,EAAE,CAAC;YAC9B,yEAAyE;YACzE,yDAAyD;YACzD,IAAI,KAAK,CAAC,YAAY,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO,KAAK,CAAC;YAClD,MAAM,KAAK,GAAe,KAAK,CAAC,KAAK,KAAK,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC;YACnE,OAAO,OAAO,CAAC;gBACd,KAAK;gBACL,SAAS,EAAE,KAAK,CAAC,SAAS;gBAC1B,YAAY,EAAE,KAAK,CAAC,YAAY;gBAChC,KAAK,EAAE,KAAK,CAAC,KAAK;gBAClB,eAAe,EAAE,KAAK,CAAC,eAAe;gBACtC,eAAe,EAAE,KAAK,CAAC,cAAc;gBACrC,MAAM,EAAE,CAAC,EAAE,oBAAoB,EAAE,EAAE,EAAE,CAAC;oBACrC,MAAM,YAAY,GAAG,KAAK,CAAC,eAAe,CAAC,CAAC,CAAC,oBAAoB,CAAC,OAAO,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;oBACtG,OAAO,YAAY,IAAI,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;gBAAA,CAC5C;aACD,CAAC,CAAC;QACJ,CAAC;QAED,KAAK,QAAQ;YACZ,OAAO,OAAO,CAAC;gBACd,KAAK,EAAE,KAAK,CAAC,KAAK;gBAClB,SAAS,EAAE,KAAK,CAAC,SAAS;gBAC1B,YAAY,EAAE,KAAK,CAAC,YAAY;gBAChC,KAAK,EAAE,MAAM,CAAC,KAAK;gBACnB,eAAe,EAAE,KAAK,CAAC,eAAe;gBACtC,eAAe,EAAE,KAAK,CAAC,cAAc;gBACrC,MAAM,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,aAAa;aACjC,CAAC,CAAC;QAEJ,KAAK,gBAAgB,EAAE,CAAC;YACvB,MAAM,MAAM,GAAG,KAAK,CAAC,gBAAgB,CAAC,MAAM,CAAC;YAC7C,IAAI,MAAM,KAAK,CAAC;gBAAE,OAAO,KAAK,CAAC;YAC/B,MAAM,aAAa,GAClB,MAAM,CAAC,KAAK,KAAK,CAAC,CAAC;gBAClB,CAAC,CAAC,KAAK,CAAC,aAAa,KAAK,CAAC;oBAC1B,CAAC,CAAC,MAAM,GAAG,CAAC;oBACZ,CAAC,CAAC,KAAK,CAAC,aAAa,GAAG,CAAC;gBAC1B,CAAC,CAAC,KAAK,CAAC,aAAa,KAAK,MAAM,GAAG,CAAC;oBACnC,CAAC,CAAC,CAAC;oBACH,CAAC,CAAC,KAAK,CAAC,aAAa,GAAG,CAAC,CAAC;YAC7B,OAAO,EAAE,GAAG,KAAK,EAAE,aAAa,EAAE,CAAC;QACpC,CAAC;IACF,CAAC;AAAA,CACD;AAED,4EAA4E;AAC5E,MAAM,UAAU,gBAAgB,CAAC,KAAyB,EAAsB;IAC/E,OAAO,KAAK,CAAC,gBAAgB,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;AAAA,CACnD;AAWD,SAAS,kBAAkB,CAC1B,OAA0B,EAC1B,SAA4B,EAC5B,cAAsB,EACtB,aAAqB,EACZ;IACT,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IACnC,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACzC,MAAM,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAChC,KAAK,IAAI,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACjC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YACX,KAAK,IAAI,cAAc,CAAC;YACxB,IAAI,OAAO,GAAG,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC;gBAAE,IAAI,IAAI,CAAC,CAAC;QACpD,CAAC;IACF,CAAC;IACD,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;IAC9C,MAAM,QAAQ,GAAG,IAAI,GAAG,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACrD,8EAA8E;IAC9E,iDAAiD;IACjD,OAAO,KAAK,GAAG,CAAC,aAAa,GAAG,cAAc,CAAC,GAAG,CAAC,IAAI,GAAG,QAAQ,CAAC,CAAC;AAAA,CACpE;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,gBAAgB,CAC/B,SAA4B,EAC5B,WAAmB,EACnB,MAAc,EACd,cAAsB,EACtB,aAAqB,EACC;IACtB,MAAM,CAAC,GAAG,SAAS,CAAC,MAAM,CAAC;IAC3B,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,kBAAkB,EAAE,KAAK,EAAE,gBAAgB,EAAE,KAAK,EAAE,CAAC;IAExF,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;IAC1D,IAAI,kBAAkB,CAAC,UAAU,EAAE,SAAS,EAAE,cAAc,EAAE,aAAa,CAAC,IAAI,MAAM,EAAE,CAAC;QACxF,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,KAAK,EAAE,gBAAgB,EAAE,KAAK,EAAE,CAAC;IACpF,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IACzD,MAAM,KAAK,GAAG,IAAI,GAAG,CAAS,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;IAC3C,MAAM,WAAW,GAAG,GAAa,EAAE,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAErE,IAAI,GAAG,GAAG,MAAM,CAAC;IACjB,IAAI,IAAI,GAAG,MAAM,CAAC;IAClB,IAAI,UAAU,GAAG,IAAI,CAAC;IACtB,OAAO,UAAU,EAAE,CAAC;QACnB,UAAU,GAAG,KAAK,CAAC;QACnB,IAAI,IAAI,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,EAAE,CAAC;YAC1C,KAAK,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC;YACpB,IAAI,kBAAkB,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,cAAc,EAAE,aAAa,CAAC,IAAI,MAAM,EAAE,CAAC;gBAC3F,IAAI,IAAI,CAAC,CAAC;gBACV,UAAU,GAAG,IAAI,CAAC;YACnB,CAAC;iBAAM,CAAC;gBACP,KAAK,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC;YACxB,CAAC;QACF,CAAC;QACD,IAAI,GAAG,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC,EAAE,CAAC;YACxC,KAAK,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;YACnB,IAAI,kBAAkB,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,cAAc,EAAE,aAAa,CAAC,IAAI,MAAM,EAAE,CAAC;gBAC3F,GAAG,IAAI,CAAC,CAAC;gBACT,UAAU,GAAG,IAAI,CAAC;YACnB,CAAC;iBAAM,CAAC;gBACP,KAAK,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;YACvB,CAAC;QACF,CAAC;IACF,CAAC;IAED,MAAM,OAAO,GAAG,WAAW,EAAE,CAAC;IAC9B,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAC9B,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC;IACnC,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;IAC9C,OAAO;QACN,OAAO;QACP,kBAAkB,EAAE,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,MAAM,GAAG,KAAK,GAAG,CAAC;QAC5D,gBAAgB,EAAE,IAAI,GAAG,CAAC,GAAG,CAAC;KAC9B,CAAC;AAAA,CACF","sourcesContent":["import { fuzzyFilter } from \"@earendil-works/omk-tui\";\n\n/**\n * Pure, render-free state machine for the `/model` selector.\n *\n * The interactive {@link ModelSelectorComponent} is a thin view/controller that\n * delegates every state transition to {@link modelSelectorReducer}. Keeping the\n * decision logic here makes the `/model` contract testable without a TUI and\n * shrinks the blast radius of theme/rendering refactors: presentation can change\n * freely as long as this reducer keeps its semantic guarantees.\n */\n\nexport type ModelScope = \"all\" | \"scoped\";\n\nexport type ProviderTab = \"all\" | string;\n\nexport const ALL_PROVIDER_TAB = \"all\" as const;\n\n/**\n * Preferred display order for first-party providers. Anything outside this list\n * is treated as a custom provider and sorted lexicographically after the known\n * providers (see {@link buildProviderTabs}).\n */\nexport const KNOWN_PROVIDER_ORDER = [\n\t\"anthropic\",\n\t\"openai\",\n\t\"google\",\n\t\"deepseek\",\n\t\"kimi\",\n\t\"openrouter\",\n\t\"mistral\",\n\t\"xai\",\n\t\"groq\",\n\t\"zai\",\n\t\"together\",\n\t\"fireworks\",\n] as const;\n\n/**\n * Minimal model projection the reducer needs. The component maps its richer\n * `ModelItem` (with the full `Model` object) down to this shape and keeps a\n * key -> item map for rendering and selection.\n */\nexport interface ModelSelectorModel {\n\treadonly provider: string;\n\treadonly id: string;\n\treadonly name: string;\n}\n\nexport interface ModelSelectorState {\n\treadonly scope: ModelScope;\n\treadonly activeProvider: ProviderTab;\n\treadonly providerIds: readonly ProviderTab[];\n\treadonly query: string;\n\treadonly selectedIndex: number;\n\treadonly visibleModelKeys: readonly string[];\n\t/** Full corpus retained so transitions stay pure functions of (state, action). */\n\treadonly allModels: readonly ModelSelectorModel[];\n\treadonly scopedModels: readonly ModelSelectorModel[];\n\treadonly currentModelKey?: string;\n}\n\nexport type ModelSelectorAction =\n\t| { type: \"NEXT_PROVIDER\" }\n\t| { type: \"PREVIOUS_PROVIDER\" }\n\t| { type: \"TOGGLE_SCOPE_FORWARD\" }\n\t| { type: \"TOGGLE_SCOPE_BACKWARD\" }\n\t| { type: \"SEARCH\"; query: string }\n\t| { type: \"MOVE_SELECTION\"; delta: 1 | -1 }\n\t| {\n\t\t\ttype: \"REFRESH_MODELS\";\n\t\t\tallModels: readonly ModelSelectorModel[];\n\t\t\tscopedModels: readonly ModelSelectorModel[];\n\t\t\tcurrentModelKey?: string;\n\t };\n\nexport function modelSelectorModelKey(model: { readonly provider: string; readonly id: string }): string {\n\treturn `${model.provider}/${model.id}`;\n}\n\nfunction isKnownProvider(provider: string): boolean {\n\treturn (KNOWN_PROVIDER_ORDER as readonly string[]).includes(provider);\n}\n\n/**\n * Build the provider tab ring: `all` first, then known providers in their\n * canonical order, then any custom providers sorted lexicographically.\n */\nexport function buildProviderTabs(models: readonly ModelSelectorModel[]): ProviderTab[] {\n\tconst providerIds = Array.from(new Set(models.map((model) => model.provider)));\n\tconst ordered = KNOWN_PROVIDER_ORDER.filter((provider) => providerIds.includes(provider));\n\tconst extras = providerIds.filter((provider) => !isKnownProvider(provider)).sort((a, b) => a.localeCompare(b));\n\treturn [ALL_PROVIDER_TAB, ...ordered, ...extras];\n}\n\nfunction filterByProvider(\n\tmodels: readonly ModelSelectorModel[],\n\tactiveProvider: ProviderTab,\n): readonly ModelSelectorModel[] {\n\tif (activeProvider === ALL_PROVIDER_TAB) return models;\n\treturn models.filter((model) => model.provider === activeProvider);\n}\n\nfunction applySearch(models: readonly ModelSelectorModel[], query: string): readonly ModelSelectorModel[] {\n\tif (!query) return models;\n\treturn fuzzyFilter(\n\t\t[...models],\n\t\tquery,\n\t\t({ id, provider }) => `${id} ${provider} ${provider}/${id} ${provider} ${id}`,\n\t);\n}\n\nfunction clampIndex(index: number, length: number): number {\n\tif (length === 0) return 0;\n\treturn Math.min(Math.max(index, 0), length - 1);\n}\n\nexport interface CreateInitialOptions {\n\treadonly scope?: ModelScope;\n\treadonly activeProvider?: ProviderTab;\n\treadonly query?: string;\n}\n\nexport function createInitialModelSelectorState(options: CreateInitialOptions = {}): ModelSelectorState {\n\treturn {\n\t\tscope: options.scope ?? \"all\",\n\t\tactiveProvider: options.activeProvider ?? ALL_PROVIDER_TAB,\n\t\tproviderIds: [ALL_PROVIDER_TAB],\n\t\tquery: options.query ?? \"\",\n\t\tselectedIndex: 0,\n\t\tvisibleModelKeys: [],\n\t\tallModels: [],\n\t\tscopedModels: [],\n\t\tcurrentModelKey: undefined,\n\t};\n}\n\n/**\n * Recompute provider tabs, the validated active provider, and the visible model\n * list for the given corpus/scope/query, then resolve the selected index with\n * the supplied strategy. Centralizing this keeps every transition consistent\n * with the contract invariants.\n */\nfunction project(overrides: {\n\treadonly scope: ModelScope;\n\treadonly allModels: readonly ModelSelectorModel[];\n\treadonly scopedModels: readonly ModelSelectorModel[];\n\treadonly query: string;\n\treadonly currentModelKey?: string;\n\treadonly desiredProvider: ProviderTab;\n\treadonly select: (input: {\n\t\treadonly visibleKeys: readonly string[];\n\t\treadonly providerFilteredKeys: readonly string[];\n\t}) => number;\n}): ModelSelectorState {\n\tconst corpus = overrides.scope === \"scoped\" ? overrides.scopedModels : overrides.allModels;\n\tconst providerIds = buildProviderTabs(corpus);\n\tconst activeProvider = providerIds.includes(overrides.desiredProvider)\n\t\t? overrides.desiredProvider\n\t\t: ALL_PROVIDER_TAB;\n\tconst providerFiltered = filterByProvider(corpus, activeProvider);\n\tconst visible = applySearch(providerFiltered, overrides.query);\n\tconst visibleModelKeys = visible.map(modelSelectorModelKey);\n\tconst selectedIndex = clampIndex(\n\t\toverrides.select({\n\t\t\tvisibleKeys: visibleModelKeys,\n\t\t\tproviderFilteredKeys: providerFiltered.map(modelSelectorModelKey),\n\t\t}),\n\t\tvisibleModelKeys.length,\n\t);\n\treturn {\n\t\tscope: overrides.scope,\n\t\tactiveProvider,\n\t\tproviderIds,\n\t\tquery: overrides.query,\n\t\tselectedIndex,\n\t\tvisibleModelKeys,\n\t\tallModels: overrides.allModels,\n\t\tscopedModels: overrides.scopedModels,\n\t\tcurrentModelKey: overrides.currentModelKey,\n\t};\n}\n\nexport function modelSelectorReducer(state: ModelSelectorState, action: ModelSelectorAction): ModelSelectorState {\n\tswitch (action.type) {\n\t\tcase \"REFRESH_MODELS\":\n\t\t\treturn project({\n\t\t\t\tscope: state.scope,\n\t\t\t\tallModels: action.allModels,\n\t\t\t\tscopedModels: action.scopedModels,\n\t\t\t\tquery: state.query,\n\t\t\t\tcurrentModelKey: action.currentModelKey,\n\t\t\t\tdesiredProvider: state.activeProvider,\n\t\t\t\tselect: ({ visibleKeys }) => {\n\t\t\t\t\tconst currentIndex = action.currentModelKey ? visibleKeys.indexOf(action.currentModelKey) : -1;\n\t\t\t\t\treturn currentIndex >= 0\n\t\t\t\t\t\t? currentIndex\n\t\t\t\t\t\t: Math.min(state.selectedIndex, Math.max(0, visibleKeys.length - 1));\n\t\t\t\t},\n\t\t\t});\n\n\t\tcase \"NEXT_PROVIDER\":\n\t\tcase \"PREVIOUS_PROVIDER\": {\n\t\t\tif (state.providerIds.length === 0) return state;\n\t\t\tconst direction = action.type === \"NEXT_PROVIDER\" ? 1 : -1;\n\t\t\tconst currentIndex = Math.max(0, state.providerIds.indexOf(state.activeProvider));\n\t\t\tconst nextIndex = (currentIndex + direction + state.providerIds.length) % state.providerIds.length;\n\t\t\tconst desiredProvider = state.providerIds[nextIndex] ?? ALL_PROVIDER_TAB;\n\t\t\treturn project({\n\t\t\t\tscope: state.scope,\n\t\t\t\tallModels: state.allModels,\n\t\t\t\tscopedModels: state.scopedModels,\n\t\t\t\tquery: state.query,\n\t\t\t\tcurrentModelKey: state.currentModelKey,\n\t\t\t\tdesiredProvider,\n\t\t\t\tselect: () => 0,\n\t\t\t});\n\t\t}\n\n\t\tcase \"TOGGLE_SCOPE_FORWARD\":\n\t\tcase \"TOGGLE_SCOPE_BACKWARD\": {\n\t\t\t// Scope is a two-state toggle (all <-> scoped); both directions flip it.\n\t\t\t// Without scoped models there is nothing to toggle into.\n\t\t\tif (state.scopedModels.length === 0) return state;\n\t\t\tconst scope: ModelScope = state.scope === \"all\" ? \"scoped\" : \"all\";\n\t\t\treturn project({\n\t\t\t\tscope,\n\t\t\t\tallModels: state.allModels,\n\t\t\t\tscopedModels: state.scopedModels,\n\t\t\t\tquery: state.query,\n\t\t\t\tcurrentModelKey: state.currentModelKey,\n\t\t\t\tdesiredProvider: state.activeProvider,\n\t\t\t\tselect: ({ providerFilteredKeys }) => {\n\t\t\t\t\tconst currentIndex = state.currentModelKey ? providerFilteredKeys.indexOf(state.currentModelKey) : -1;\n\t\t\t\t\treturn currentIndex >= 0 ? currentIndex : 0;\n\t\t\t\t},\n\t\t\t});\n\t\t}\n\n\t\tcase \"SEARCH\":\n\t\t\treturn project({\n\t\t\t\tscope: state.scope,\n\t\t\t\tallModels: state.allModels,\n\t\t\t\tscopedModels: state.scopedModels,\n\t\t\t\tquery: action.query,\n\t\t\t\tcurrentModelKey: state.currentModelKey,\n\t\t\t\tdesiredProvider: state.activeProvider,\n\t\t\t\tselect: () => state.selectedIndex,\n\t\t\t});\n\n\t\tcase \"MOVE_SELECTION\": {\n\t\t\tconst length = state.visibleModelKeys.length;\n\t\t\tif (length === 0) return state;\n\t\t\tconst selectedIndex =\n\t\t\t\taction.delta === -1\n\t\t\t\t\t? state.selectedIndex === 0\n\t\t\t\t\t\t? length - 1\n\t\t\t\t\t\t: state.selectedIndex - 1\n\t\t\t\t\t: state.selectedIndex === length - 1\n\t\t\t\t\t\t? 0\n\t\t\t\t\t\t: state.selectedIndex + 1;\n\t\t\treturn { ...state, selectedIndex };\n\t\t}\n\t}\n}\n\n/** Resolve the selected model key, if any, for the current visible list. */\nexport function selectedModelKey(state: ModelSelectorState): string | undefined {\n\treturn state.visibleModelKeys[state.selectedIndex];\n}\n\nexport interface ProviderStripLayout {\n\t/** Tab indices to render, in ascending order. Always includes 0 and the active index. */\n\treadonly indices: readonly number[];\n\t/** Render an ellipsis between the first tab (\"all\") and the rest (hidden middle). */\n\treadonly ellipsisAfterFirst: boolean;\n\t/** Render a trailing ellipsis (tabs hidden after the last shown). */\n\treadonly trailingEllipsis: boolean;\n}\n\nfunction providerStripWidth(\n\tindices: readonly number[],\n\ttabWidths: readonly number[],\n\tseparatorWidth: number,\n\tellipsisWidth: number,\n): number {\n\tif (indices.length === 0) return 0;\n\tlet total = 0;\n\tlet gaps = 0;\n\tfor (let k = 0; k < indices.length; k++) {\n\t\tconst current = indices[k] ?? 0;\n\t\ttotal += tabWidths[current] ?? 0;\n\t\tif (k > 0) {\n\t\t\ttotal += separatorWidth;\n\t\t\tif (current - (indices[k - 1] ?? 0) > 1) gaps += 1;\n\t\t}\n\t}\n\tconst last = indices[indices.length - 1] ?? 0;\n\tconst trailing = last < tabWidths.length - 1 ? 1 : 0;\n\t// Each ellipsis renders as its own segment joined by a separator, so it costs\n\t// a separator in addition to the ellipsis glyph.\n\treturn total + (ellipsisWidth + separatorWidth) * (gaps + trailing);\n}\n\n/**\n * Window a provider tab strip into a visible-column budget so the row never\n * overflows the terminal while always keeping the \"all\" anchor (index 0) and the\n * active tab visible. When the full strip fits, every tab is shown. Otherwise a\n * contiguous window is grown around the active tab (right-biased, then left),\n * with a single leading ellipsis for a hidden middle and a trailing ellipsis for\n * hidden tail tabs.\n *\n * Pure and presentation-agnostic: callers pass the visible width of each themed\n * tab label (via omk-tui `visibleWidth`) plus the separator/ellipsis widths.\n * If the budget cannot even hold the mandatory {all, active} tabs, those are\n * still returned (the caller may then hard-truncate).\n */\nexport function fitProviderStrip(\n\ttabWidths: readonly number[],\n\tactiveIndex: number,\n\tbudget: number,\n\tseparatorWidth: number,\n\tellipsisWidth: number,\n): ProviderStripLayout {\n\tconst n = tabWidths.length;\n\tif (n === 0) return { indices: [], ellipsisAfterFirst: false, trailingEllipsis: false };\n\n\tconst allIndices = Array.from({ length: n }, (_, i) => i);\n\tif (providerStripWidth(allIndices, tabWidths, separatorWidth, ellipsisWidth) <= budget) {\n\t\treturn { indices: allIndices, ellipsisAfterFirst: false, trailingEllipsis: false };\n\t}\n\n\tconst active = Math.max(0, Math.min(activeIndex, n - 1));\n\tconst shown = new Set<number>([0, active]);\n\tconst sortedShown = (): number[] => [...shown].sort((a, b) => a - b);\n\n\tlet low = active;\n\tlet high = active;\n\tlet progressed = true;\n\twhile (progressed) {\n\t\tprogressed = false;\n\t\tif (high + 1 < n && !shown.has(high + 1)) {\n\t\t\tshown.add(high + 1);\n\t\t\tif (providerStripWidth(sortedShown(), tabWidths, separatorWidth, ellipsisWidth) <= budget) {\n\t\t\t\thigh += 1;\n\t\t\t\tprogressed = true;\n\t\t\t} else {\n\t\t\t\tshown.delete(high + 1);\n\t\t\t}\n\t\t}\n\t\tif (low - 1 > 0 && !shown.has(low - 1)) {\n\t\t\tshown.add(low - 1);\n\t\t\tif (providerStripWidth(sortedShown(), tabWidths, separatorWidth, ellipsisWidth) <= budget) {\n\t\t\t\tlow -= 1;\n\t\t\t\tprogressed = true;\n\t\t\t} else {\n\t\t\t\tshown.delete(low - 1);\n\t\t\t}\n\t\t}\n\t}\n\n\tconst indices = sortedShown();\n\tconst first = indices[0] ?? 0;\n\tconst second = indices[1] ?? first;\n\tconst last = indices[indices.length - 1] ?? 0;\n\treturn {\n\t\tindices,\n\t\tellipsisAfterFirst: indices.length > 1 && second - first > 1,\n\t\ttrailingEllipsis: last < n - 1,\n\t};\n}\n"]}
@@ -2,10 +2,22 @@ import { type Model } from "@earendil-works/omk-ai";
2
2
  import { Container, type Focusable, Input, type TUI } from "@earendil-works/omk-tui";
3
3
  import type { ModelRegistry } from "../../../core/model-registry.ts";
4
4
  import type { SettingsManager } from "../../../core/settings-manager.ts";
5
+ import { ALL_PROVIDER_TAB, type ModelScope, type ProviderTab } from "./model-selector-state.ts";
6
+ export { ALL_PROVIDER_TAB };
7
+ export type { ModelScope, ProviderTab };
5
8
  interface ScopedModelItem {
6
9
  model: Model<any>;
7
10
  thinkingLevel?: string;
8
11
  }
12
+ export interface ModelSelectorSemanticState {
13
+ readonly scope: ModelScope;
14
+ readonly activeProvider: ProviderTab;
15
+ readonly providerIds: readonly ProviderTab[];
16
+ readonly query: string;
17
+ readonly selectedIndex: number;
18
+ readonly selectedModelKey?: string;
19
+ readonly visibleModelKeys: readonly string[];
20
+ }
9
21
  /**
10
22
  * Component that renders a model selector with search and provider tabs.
11
23
  */
@@ -15,12 +27,12 @@ export declare class ModelSelectorComponent extends Container implements Focusab
15
27
  get focused(): boolean;
16
28
  set focused(value: boolean);
17
29
  private listContainer;
18
- private allModels;
19
- private scopedModelItems;
20
- private activeModels;
21
30
  private filteredModels;
22
31
  private selectedIndex;
23
32
  private currentModel?;
33
+ private currentModelKey?;
34
+ private itemsByKey;
35
+ private state;
24
36
  private modelRegistry;
25
37
  private onSelectCallback;
26
38
  private onCancelCallback;
@@ -34,23 +46,45 @@ export declare class ModelSelectorComponent extends Container implements Focusab
34
46
  private providerHintText;
35
47
  private scopeText?;
36
48
  private scopeHintText?;
37
- constructor(tui: TUI, currentModel: Model<any> | undefined, _settingsManager: SettingsManager, modelRegistry: ModelRegistry, scopedModels: ReadonlyArray<ScopedModelItem>, onSelect: (model: Model<any>) => void, onCancel: () => void, initialSearchInput?: string);
49
+ onProviderTabChange?: (tab: ProviderTab) => void;
50
+ constructor(tui: TUI, currentModel: Model<any> | undefined, _settingsManager: SettingsManager, modelRegistry: ModelRegistry, scopedModels: ReadonlyArray<ScopedModelItem>, onSelect: (model: Model<any>) => void, onCancel: () => void, initialSearchInput?: string, initialProviderTab?: ProviderTab);
38
51
  private loadModels;
52
+ private resolveCurrentModelKey;
39
53
  private sortModels;
40
54
  private isProviderAuthenticated;
55
+ private providerTabLabel;
56
+ private themedProviderTab;
57
+ /**
58
+ * Build the provider tab row. When a render width is supplied, the strip is
59
+ * windowed with fitProviderStrip() so it always fits the terminal while keeping
60
+ * the "all" anchor and the active tab visible; otherwise every tab is shown
61
+ * (used for non-render measurement contexts).
62
+ */
41
63
  private getProviderText;
42
64
  private getProviderHintText;
43
65
  private getScopeText;
44
66
  private getScopeHintText;
45
- private setScope;
46
- private rebuildProviderTabs;
47
- private getProviderFilteredModels;
48
- private cycleProvider;
49
- private filterModels;
67
+ private applyAction;
68
+ /**
69
+ * Mirror the reducer's semantic state into the fields the renderer reads.
70
+ * The reducer is the single source of truth; these fields are a derived view
71
+ * kept in sync after every transition.
72
+ */
73
+ private syncRenderState;
50
74
  private updateList;
51
75
  handleInput(keyData: string): void;
52
76
  private handleSelect;
77
+ /**
78
+ * Structured /model contract state. Tests and future reducer/property
79
+ * harnesses should assert this semantic snapshot instead of parsing themed
80
+ * presentation text or reaching into private fields.
81
+ */
82
+ getSemanticState(): ModelSelectorSemanticState;
83
+ /**
84
+ * Width-aware render: recompute the provider row for the actual terminal width
85
+ * so the strip fits without wrapping, then delegate to the container renderer.
86
+ */
87
+ render(width: number): string[];
53
88
  getSearchInput(): Input;
54
89
  }
55
- export {};
56
90
  //# sourceMappingURL=model-selector.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"model-selector.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/model-selector.ts"],"names":[],"mappings":"AAAA,OAAO,EAA8B,KAAK,KAAK,EAAkB,MAAM,wBAAwB,CAAC;AAChG,OAAO,EACN,SAAS,EACT,KAAK,SAAS,EAGd,KAAK,EAGL,KAAK,GAAG,EACR,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AACrE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AAuBzE,UAAU,eAAe;IACxB,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;CACvB;AA8BD;;GAEG;AACH,qBAAa,sBAAuB,SAAQ,SAAU,YAAW,SAAS;IACzE,OAAO,CAAC,WAAW,CAAQ;IAG3B,OAAO,CAAC,QAAQ,CAAS;IACzB,IAAI,OAAO,IAAI,OAAO,CAErB;IACD,IAAI,OAAO,CAAC,KAAK,EAAE,OAAO,EAGzB;IACD,OAAO,CAAC,aAAa,CAAY;IACjC,OAAO,CAAC,SAAS,CAAmB;IACpC,OAAO,CAAC,gBAAgB,CAAmB;IAC3C,OAAO,CAAC,YAAY,CAAmB;IACvC,OAAO,CAAC,cAAc,CAAmB;IACzC,OAAO,CAAC,aAAa,CAAa;IAClC,OAAO,CAAC,YAAY,CAAC,CAAa;IAClC,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,gBAAgB,CAA8B;IACtD,OAAO,CAAC,gBAAgB,CAAa;IACrC,OAAO,CAAC,YAAY,CAAC,CAAS;IAC9B,OAAO,CAAC,GAAG,CAAM;IACjB,OAAO,CAAC,YAAY,CAAiC;IACrD,OAAO,CAAC,KAAK,CAAqB;IAClC,OAAO,CAAC,YAAY,CAAqC;IACzD,OAAO,CAAC,iBAAiB,CAAiC;IAC1D,OAAO,CAAC,YAAY,CAAO;IAC3B,OAAO,CAAC,gBAAgB,CAAO;IAC/B,OAAO,CAAC,SAAS,CAAC,CAAO;IACzB,OAAO,CAAC,aAAa,CAAC,CAAO;IAE7B,YACC,GAAG,EAAE,GAAG,EACR,YAAY,EAAE,KAAK,CAAC,GAAG,CAAC,GAAG,SAAS,EACpC,gBAAgB,EAAE,eAAe,EACjC,aAAa,EAAE,aAAa,EAC5B,YAAY,EAAE,aAAa,CAAC,eAAe,CAAC,EAC5C,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,KAAK,IAAI,EACrC,QAAQ,EAAE,MAAM,IAAI,EACpB,kBAAkB,CAAC,EAAE,MAAM,EAmE3B;YAEa,UAAU;IA+CxB,OAAO,CAAC,UAAU;IAalB,OAAO,CAAC,uBAAuB;IAM/B,OAAO,CAAC,eAAe;IAWvB,OAAO,CAAC,mBAAmB;IAQ3B,OAAO,CAAC,YAAY;IAMpB,OAAO,CAAC,gBAAgB;IAIxB,OAAO,CAAC,QAAQ;IAkBhB,OAAO,CAAC,mBAAmB;IAS3B,OAAO,CAAC,yBAAyB;IAOjC,OAAO,CAAC,aAAa;IAUrB,OAAO,CAAC,YAAY;IAapB,OAAO,CAAC,UAAU;IAwDlB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CA8CjC;IAED,OAAO,CAAC,YAAY;IAIpB,cAAc,IAAI,KAAK,CAEtB;CACD","sourcesContent":["import { getSupportedThinkingLevels, type Model, modelsAreEqual } from \"@earendil-works/omk-ai\";\nimport {\n\tContainer,\n\ttype Focusable,\n\tfuzzyFilter,\n\tgetKeybindings,\n\tInput,\n\tSpacer,\n\tText,\n\ttype TUI,\n} from \"@earendil-works/omk-tui\";\nimport type { ModelRegistry } from \"../../../core/model-registry.ts\";\nimport type { SettingsManager } from \"../../../core/settings-manager.ts\";\n\nfunction formatThinkingBadge(model: Model<any>): string {\n\tconst levels = getSupportedThinkingLevels(model) as string[];\n\tif (!levels || levels.length === 0) return \"think:-\";\n\tif (levels.length === 1) return `think:${levels[0]}`;\n\treturn `think:${levels[0]}…${levels[levels.length - 1]}`;\n}\n\nfunction providerAuthGlyph(authConfigured: boolean): string {\n\treturn authConfigured ? \"✓\" : \"✗\";\n}\n\nimport { theme } from \"../theme/theme.ts\";\nimport { DynamicBorder } from \"./dynamic-border.ts\";\nimport { keyHint } from \"./keybinding-hints.ts\";\n\ninterface ModelItem {\n\tprovider: string;\n\tid: string;\n\tmodel: Model<any>;\n}\n\ninterface ScopedModelItem {\n\tmodel: Model<any>;\n\tthinkingLevel?: string;\n}\n\ntype ModelScope = \"all\" | \"scoped\";\ntype ProviderTab = \"all\" | string;\n\nconst ALL_PROVIDER_TAB = \"all\" as const;\nconst PROVIDER_TAB_ORDER = [\n\t\"anthropic\",\n\t\"openai\",\n\t\"google\",\n\t\"deepseek\",\n\t\"kimi\",\n\t\"openrouter\",\n\t\"mistral\",\n\t\"xai\",\n\t\"groq\",\n\t\"zai\",\n\t\"together\",\n\t\"fireworks\",\n] as const;\n\nfunction buildProviderTabs(models: readonly ModelItem[]): ProviderTab[] {\n\tconst providerIds = Array.from(new Set(models.map((model) => model.provider)));\n\tconst ordered = PROVIDER_TAB_ORDER.filter((provider) => providerIds.includes(provider));\n\tconst extras = providerIds\n\t\t.filter((provider) => !PROVIDER_TAB_ORDER.includes(provider as (typeof PROVIDER_TAB_ORDER)[number]))\n\t\t.sort((a, b) => a.localeCompare(b));\n\treturn [ALL_PROVIDER_TAB, ...ordered, ...extras];\n}\n\n/**\n * Component that renders a model selector with search and provider tabs.\n */\nexport class ModelSelectorComponent extends Container implements Focusable {\n\tprivate searchInput: Input;\n\n\t// Focusable implementation - propagate to searchInput for IME cursor positioning\n\tprivate _focused = false;\n\tget focused(): boolean {\n\t\treturn this._focused;\n\t}\n\tset focused(value: boolean) {\n\t\tthis._focused = value;\n\t\tthis.searchInput.focused = value;\n\t}\n\tprivate listContainer: Container;\n\tprivate allModels: ModelItem[] = [];\n\tprivate scopedModelItems: ModelItem[] = [];\n\tprivate activeModels: ModelItem[] = [];\n\tprivate filteredModels: ModelItem[] = [];\n\tprivate selectedIndex: number = 0;\n\tprivate currentModel?: Model<any>;\n\tprivate modelRegistry: ModelRegistry;\n\tprivate onSelectCallback: (model: Model<any>) => void;\n\tprivate onCancelCallback: () => void;\n\tprivate errorMessage?: string;\n\tprivate tui: TUI;\n\tprivate scopedModels: ReadonlyArray<ScopedModelItem>;\n\tprivate scope: ModelScope = \"all\";\n\tprivate providerTabs: ProviderTab[] = [ALL_PROVIDER_TAB];\n\tprivate activeProviderTab: ProviderTab = ALL_PROVIDER_TAB;\n\tprivate providerText: Text;\n\tprivate providerHintText: Text;\n\tprivate scopeText?: Text;\n\tprivate scopeHintText?: Text;\n\n\tconstructor(\n\t\ttui: TUI,\n\t\tcurrentModel: Model<any> | undefined,\n\t\t_settingsManager: SettingsManager,\n\t\tmodelRegistry: ModelRegistry,\n\t\tscopedModels: ReadonlyArray<ScopedModelItem>,\n\t\tonSelect: (model: Model<any>) => void,\n\t\tonCancel: () => void,\n\t\tinitialSearchInput?: string,\n\t) {\n\t\tsuper();\n\n\t\tthis.tui = tui;\n\t\tthis.currentModel = currentModel;\n\t\tthis.modelRegistry = modelRegistry;\n\t\tthis.scopedModels = scopedModels;\n\t\tthis.scope = scopedModels.length > 0 ? \"scoped\" : \"all\";\n\t\tthis.onSelectCallback = onSelect;\n\t\tthis.onCancelCallback = onCancel;\n\n\t\t// Add top border\n\t\tthis.addChild(new DynamicBorder());\n\t\tthis.addChild(new Spacer(1));\n\n\t\tthis.providerText = new Text(this.getProviderText(), 0, 0);\n\t\tthis.addChild(this.providerText);\n\t\tthis.providerHintText = new Text(this.getProviderHintText(), 0, 0);\n\t\tthis.addChild(this.providerHintText);\n\n\t\t// Add hint about model filtering\n\t\tif (scopedModels.length > 0) {\n\t\t\tthis.scopeText = new Text(this.getScopeText(), 0, 0);\n\t\t\tthis.addChild(this.scopeText);\n\t\t\tthis.scopeHintText = new Text(this.getScopeHintText(), 0, 0);\n\t\t\tthis.addChild(this.scopeHintText);\n\t\t} else {\n\t\t\tconst hintText = \"Only showing models from configured providers. Use /login to add providers.\";\n\t\t\tthis.addChild(new Text(theme.fg(\"warning\", hintText), 0, 0));\n\t\t}\n\t\tthis.addChild(new Spacer(1));\n\n\t\t// Create search input\n\t\tthis.searchInput = new Input();\n\t\tif (initialSearchInput) {\n\t\t\tthis.searchInput.setValue(initialSearchInput);\n\t\t}\n\t\tthis.searchInput.onSubmit = () => {\n\t\t\t// Enter on search input selects the first filtered item\n\t\t\tif (this.filteredModels[this.selectedIndex]) {\n\t\t\t\tthis.handleSelect(this.filteredModels[this.selectedIndex].model);\n\t\t\t}\n\t\t};\n\t\tthis.addChild(this.searchInput);\n\n\t\tthis.addChild(new Spacer(1));\n\n\t\t// Create list container\n\t\tthis.listContainer = new Container();\n\t\tthis.addChild(this.listContainer);\n\n\t\tthis.addChild(new Spacer(1));\n\n\t\t// Add bottom border\n\t\tthis.addChild(new DynamicBorder());\n\n\t\t// Load models and do initial render\n\t\tthis.loadModels().then(() => {\n\t\t\tif (initialSearchInput) {\n\t\t\t\tthis.filterModels(initialSearchInput);\n\t\t\t} else {\n\t\t\t\tthis.updateList();\n\t\t\t}\n\t\t\t// Request re-render after models are loaded\n\t\t\tthis.tui.requestRender();\n\t\t});\n\t}\n\n\tprivate async loadModels(): Promise<void> {\n\t\tlet models: ModelItem[];\n\n\t\t// Refresh to pick up any changes to models.json\n\t\tthis.modelRegistry.refresh();\n\n\t\t// Check for models.json errors\n\t\tconst loadError = this.modelRegistry.getError();\n\t\tif (loadError) {\n\t\t\tthis.errorMessage = loadError;\n\t\t}\n\n\t\t// Load available models (built-in models still work even if models.json failed)\n\t\ttry {\n\t\t\tconst availableModels = await this.modelRegistry.getAvailable();\n\t\t\tmodels = availableModels.map((model: Model<any>) => ({\n\t\t\t\tprovider: model.provider,\n\t\t\t\tid: model.id,\n\t\t\t\tmodel,\n\t\t\t}));\n\t\t} catch (error) {\n\t\t\tthis.allModels = [];\n\t\t\tthis.scopedModelItems = [];\n\t\t\tthis.activeModels = [];\n\t\t\tthis.filteredModels = [];\n\t\t\tthis.errorMessage = error instanceof Error ? error.message : String(error);\n\t\t\treturn;\n\t\t}\n\n\t\tthis.allModels = this.sortModels(models);\n\t\tthis.scopedModels = this.scopedModels.map((scoped) => {\n\t\t\tconst refreshed = this.modelRegistry.find(scoped.model.provider, scoped.model.id);\n\t\t\treturn refreshed ? { ...scoped, model: refreshed } : scoped;\n\t\t});\n\t\tthis.scopedModelItems = this.scopedModels.map((scoped) => ({\n\t\t\tprovider: scoped.model.provider,\n\t\t\tid: scoped.model.id,\n\t\t\tmodel: scoped.model,\n\t\t}));\n\t\tthis.activeModels = this.scope === \"scoped\" ? this.scopedModelItems : this.allModels;\n\t\tthis.rebuildProviderTabs();\n\t\tthis.filteredModels = this.getProviderFilteredModels();\n\t\tconst currentIndex = this.filteredModels.findIndex((item) => modelsAreEqual(this.currentModel, item.model));\n\t\tthis.selectedIndex =\n\t\t\tcurrentIndex >= 0 ? currentIndex : Math.min(this.selectedIndex, Math.max(0, this.filteredModels.length - 1));\n\t}\n\n\tprivate sortModels(models: ModelItem[]): ModelItem[] {\n\t\tconst sorted = [...models];\n\t\t// Sort: current model first, then by provider\n\t\tsorted.sort((a, b) => {\n\t\t\tconst aIsCurrent = modelsAreEqual(this.currentModel, a.model);\n\t\t\tconst bIsCurrent = modelsAreEqual(this.currentModel, b.model);\n\t\t\tif (aIsCurrent && !bIsCurrent) return -1;\n\t\t\tif (!aIsCurrent && bIsCurrent) return 1;\n\t\t\treturn a.provider.localeCompare(b.provider);\n\t\t});\n\t\treturn sorted;\n\t}\n\n\tprivate isProviderAuthenticated(provider: string): boolean {\n\t\tif (provider === ALL_PROVIDER_TAB) return true;\n\t\tconst status = this.modelRegistry.authStorage.getAuthStatus(provider);\n\t\treturn status.configured || status.source !== undefined;\n\t}\n\n\tprivate getProviderText(): string {\n\t\tconst tabs = this.providerTabs.map((provider) => {\n\t\t\tconst auth = this.isProviderAuthenticated(provider);\n\t\t\tconst glyph = provider === ALL_PROVIDER_TAB ? \"\" : ` ${providerAuthGlyph(auth)}`;\n\t\t\tconst label = `${provider}${glyph}`;\n\t\t\tif (provider === this.activeProviderTab) return theme.fg(\"accent\", label);\n\t\t\treturn auth ? theme.fg(\"muted\", label) : theme.fg(\"dim\", label);\n\t\t});\n\t\treturn `${theme.fg(\"muted\", \"Provider: \")}${tabs.join(theme.fg(\"dim\", \" | \"))}`;\n\t}\n\n\tprivate getProviderHintText(): string {\n\t\treturn (\n\t\t\tkeyHint(\"tui.input.tab\", \"provider\") +\n\t\t\ttheme.fg(\"muted\", \" · \") +\n\t\t\tkeyHint(\"app.model.providerPrevious\", \"previous provider\")\n\t\t);\n\t}\n\n\tprivate getScopeText(): string {\n\t\tconst allText = this.scope === \"all\" ? theme.fg(\"accent\", \"all\") : theme.fg(\"muted\", \"all\");\n\t\tconst scopedText = this.scope === \"scoped\" ? theme.fg(\"accent\", \"scoped\") : theme.fg(\"muted\", \"scoped\");\n\t\treturn `${theme.fg(\"muted\", \"Scope: \")}${allText}${theme.fg(\"muted\", \" | \")}${scopedText}`;\n\t}\n\n\tprivate getScopeHintText(): string {\n\t\treturn keyHint(\"app.model.cycleForward\", \"scope\") + theme.fg(\"muted\", \" (all/scoped)\");\n\t}\n\n\tprivate setScope(scope: ModelScope): void {\n\t\tif (this.scope === scope) return;\n\t\tthis.scope = scope;\n\t\tthis.activeModels = this.scope === \"scoped\" ? this.scopedModelItems : this.allModels;\n\t\tthis.rebuildProviderTabs();\n\t\tconst currentIndex = this.getProviderFilteredModels().findIndex((item) =>\n\t\t\tmodelsAreEqual(this.currentModel, item.model),\n\t\t);\n\t\tthis.selectedIndex = currentIndex >= 0 ? currentIndex : 0;\n\t\tthis.filterModels(this.searchInput.getValue());\n\t\tif (this.scopeText) {\n\t\t\tthis.scopeText.setText(this.getScopeText());\n\t\t}\n\t\tif (this.scopeHintText) {\n\t\t\tthis.scopeHintText.setText(this.getScopeHintText());\n\t\t}\n\t}\n\n\tprivate rebuildProviderTabs(): void {\n\t\tthis.providerTabs = buildProviderTabs(this.activeModels);\n\t\tif (!this.providerTabs.includes(this.activeProviderTab)) {\n\t\t\tthis.activeProviderTab = ALL_PROVIDER_TAB;\n\t\t}\n\t\tthis.providerText.setText(this.getProviderText());\n\t\tthis.providerHintText.setText(this.getProviderHintText());\n\t}\n\n\tprivate getProviderFilteredModels(): ModelItem[] {\n\t\tif (this.activeProviderTab === ALL_PROVIDER_TAB) {\n\t\t\treturn this.activeModels;\n\t\t}\n\t\treturn this.activeModels.filter((item) => item.provider === this.activeProviderTab);\n\t}\n\n\tprivate cycleProvider(direction: 1 | -1): void {\n\t\tif (this.providerTabs.length === 0) return;\n\t\tconst currentIndex = Math.max(0, this.providerTabs.indexOf(this.activeProviderTab));\n\t\tconst nextIndex = (currentIndex + direction + this.providerTabs.length) % this.providerTabs.length;\n\t\tthis.activeProviderTab = this.providerTabs[nextIndex] ?? ALL_PROVIDER_TAB;\n\t\tthis.providerText.setText(this.getProviderText());\n\t\tthis.selectedIndex = 0;\n\t\tthis.filterModels(this.searchInput.getValue());\n\t}\n\n\tprivate filterModels(query: string): void {\n\t\tconst providerModels = this.getProviderFilteredModels();\n\t\tthis.filteredModels = query\n\t\t\t? fuzzyFilter(\n\t\t\t\t\tproviderModels,\n\t\t\t\t\tquery,\n\t\t\t\t\t({ id, provider }) => `${id} ${provider} ${provider}/${id} ${provider} ${id}`,\n\t\t\t\t)\n\t\t\t: providerModels;\n\t\tthis.selectedIndex = Math.min(this.selectedIndex, Math.max(0, this.filteredModels.length - 1));\n\t\tthis.updateList();\n\t}\n\n\tprivate updateList(): void {\n\t\tthis.listContainer.clear();\n\n\t\tconst maxVisible = 10;\n\t\tconst startIndex = Math.max(\n\t\t\t0,\n\t\t\tMath.min(this.selectedIndex - Math.floor(maxVisible / 2), this.filteredModels.length - maxVisible),\n\t\t);\n\t\tconst endIndex = Math.min(startIndex + maxVisible, this.filteredModels.length);\n\n\t\t// Show visible slice of filtered models\n\t\tfor (let i = startIndex; i < endIndex; i++) {\n\t\t\tconst item = this.filteredModels[i];\n\t\t\tif (!item) continue;\n\n\t\t\tconst isSelected = i === this.selectedIndex;\n\t\t\tconst isCurrent = modelsAreEqual(this.currentModel, item.model);\n\t\t\tconst providerAuthed = this.isProviderAuthenticated(item.provider);\n\t\t\tconst providerLabel = `[${item.provider}${providerAuthed ? \"\" : \" no-auth\"}]`;\n\t\t\tconst providerBadge = providerAuthed ? theme.fg(\"muted\", providerLabel) : theme.fg(\"warning\", providerLabel);\n\t\t\tconst thinkingBadge = theme.fg(\"dim\", ` · ${formatThinkingBadge(item.model)}`);\n\t\t\tconst checkmark = isCurrent ? theme.fg(\"success\", \" ✓\") : \"\";\n\n\t\t\tlet line = \"\";\n\t\t\tif (isSelected) {\n\t\t\t\tconst prefix = theme.fg(\"accent\", \"→ \");\n\t\t\t\tline = `${prefix + theme.fg(\"accent\", item.id)} ${providerBadge}${thinkingBadge}${checkmark}`;\n\t\t\t} else {\n\t\t\t\tline = ` ${item.id} ${providerBadge}${thinkingBadge}${checkmark}`;\n\t\t\t}\n\n\t\t\tthis.listContainer.addChild(new Text(line, 0, 0));\n\t\t}\n\n\t\t// Add scroll indicator if needed\n\t\tif (startIndex > 0 || endIndex < this.filteredModels.length) {\n\t\t\tconst scrollInfo = theme.fg(\"muted\", ` (${this.selectedIndex + 1}/${this.filteredModels.length})`);\n\t\t\tthis.listContainer.addChild(new Text(scrollInfo, 0, 0));\n\t\t}\n\n\t\t// Show error message or \"no results\" if empty\n\t\tif (this.errorMessage) {\n\t\t\t// Show error in red\n\t\t\tconst errorLines = this.errorMessage.split(\"\\n\");\n\t\t\tfor (const line of errorLines) {\n\t\t\t\tthis.listContainer.addChild(new Text(theme.fg(\"error\", line), 0, 0));\n\t\t\t}\n\t\t} else if (this.filteredModels.length === 0) {\n\t\t\tthis.listContainer.addChild(new Text(theme.fg(\"muted\", \" No matching models\"), 0, 0));\n\t\t} else {\n\t\t\tconst selected = this.filteredModels[this.selectedIndex];\n\t\t\tthis.listContainer.addChild(new Spacer(1));\n\t\t\tthis.listContainer.addChild(new Text(theme.fg(\"muted\", ` Model Name: ${selected.model.name}`), 0, 0));\n\t\t}\n\t}\n\n\thandleInput(keyData: string): void {\n\t\tconst kb = getKeybindings();\n\t\tif (kb.matches(keyData, \"tui.input.tab\")) {\n\t\t\tthis.cycleProvider(1);\n\t\t\treturn;\n\t\t}\n\t\tif (kb.matches(keyData, \"app.model.providerPrevious\")) {\n\t\t\tthis.cycleProvider(-1);\n\t\t\treturn;\n\t\t}\n\t\tif (\n\t\t\t(kb.matches(keyData, \"app.model.cycleForward\") || kb.matches(keyData, \"app.model.cycleBackward\")) &&\n\t\t\tthis.scopedModelItems.length > 0\n\t\t) {\n\t\t\tconst nextScope: ModelScope = this.scope === \"all\" ? \"scoped\" : \"all\";\n\t\t\tthis.setScope(nextScope);\n\t\t\treturn;\n\t\t}\n\t\t// Up arrow - wrap to bottom when at top\n\t\tif (kb.matches(keyData, \"tui.select.up\")) {\n\t\t\tif (this.filteredModels.length === 0) return;\n\t\t\tthis.selectedIndex = this.selectedIndex === 0 ? this.filteredModels.length - 1 : this.selectedIndex - 1;\n\t\t\tthis.updateList();\n\t\t}\n\t\t// Down arrow - wrap to top when at bottom\n\t\telse if (kb.matches(keyData, \"tui.select.down\")) {\n\t\t\tif (this.filteredModels.length === 0) return;\n\t\t\tthis.selectedIndex = this.selectedIndex === this.filteredModels.length - 1 ? 0 : this.selectedIndex + 1;\n\t\t\tthis.updateList();\n\t\t}\n\t\t// Enter\n\t\telse if (kb.matches(keyData, \"tui.select.confirm\")) {\n\t\t\tconst selectedModel = this.filteredModels[this.selectedIndex];\n\t\t\tif (selectedModel) {\n\t\t\t\tthis.handleSelect(selectedModel.model);\n\t\t\t}\n\t\t}\n\t\t// Escape or Ctrl+C\n\t\telse if (kb.matches(keyData, \"tui.select.cancel\")) {\n\t\t\tthis.onCancelCallback();\n\t\t}\n\t\t// Pass everything else to search input\n\t\telse {\n\t\t\tthis.searchInput.handleInput(keyData);\n\t\t\tthis.filterModels(this.searchInput.getValue());\n\t\t}\n\t}\n\n\tprivate handleSelect(model: Model<any>): void {\n\t\tthis.onSelectCallback(model);\n\t}\n\n\tgetSearchInput(): Input {\n\t\treturn this.searchInput;\n\t}\n}\n"]}
1
+ {"version":3,"file":"model-selector.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/model-selector.ts"],"names":[],"mappings":"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","sourcesContent":["import { getSupportedThinkingLevels, type Model, modelsAreEqual } from \"@earendil-works/omk-ai\";\nimport {\n\tContainer,\n\ttype Focusable,\n\tgetKeybindings,\n\tInput,\n\tSpacer,\n\tText,\n\ttype TUI,\n\tvisibleWidth,\n} from \"@earendil-works/omk-tui\";\nimport type { ModelRegistry } from \"../../../core/model-registry.ts\";\nimport type { SettingsManager } from \"../../../core/settings-manager.ts\";\n\nfunction formatThinkingBadge(model: Model<any>): string {\n\tconst levels = getSupportedThinkingLevels(model) as string[];\n\tif (!levels || levels.length === 0) return \"think:-\";\n\tif (levels.length === 1) return `think:${levels[0]}`;\n\treturn `think:${levels[0]}…${levels[levels.length - 1]}`;\n}\n\nfunction providerAuthGlyph(authConfigured: boolean): string {\n\treturn authConfigured ? \"✓\" : \"✗\";\n}\n\nimport { theme } from \"../theme/theme.ts\";\nimport { DynamicBorder } from \"./dynamic-border.ts\";\nimport { keyHint } from \"./keybinding-hints.ts\";\nimport {\n\tALL_PROVIDER_TAB,\n\tcreateInitialModelSelectorState,\n\tfitProviderStrip,\n\ttype ModelScope,\n\ttype ModelSelectorAction,\n\ttype ModelSelectorModel,\n\ttype ModelSelectorState,\n\tmodelSelectorModelKey,\n\tmodelSelectorReducer,\n\ttype ProviderTab,\n\tselectedModelKey,\n} from \"./model-selector-state.ts\";\n\nexport { ALL_PROVIDER_TAB };\nexport type { ModelScope, ProviderTab };\n\ninterface ModelItem {\n\tprovider: string;\n\tid: string;\n\tmodel: Model<any>;\n}\n\ninterface ScopedModelItem {\n\tmodel: Model<any>;\n\tthinkingLevel?: string;\n}\n\nexport interface ModelSelectorSemanticState {\n\treadonly scope: ModelScope;\n\treadonly activeProvider: ProviderTab;\n\treadonly providerIds: readonly ProviderTab[];\n\treadonly query: string;\n\treadonly selectedIndex: number;\n\treadonly selectedModelKey?: string;\n\treadonly visibleModelKeys: readonly string[];\n}\n\nfunction toSelectorModel(item: ModelItem): ModelSelectorModel {\n\treturn { provider: item.provider, id: item.id, name: item.model.name };\n}\n\n/**\n * Component that renders a model selector with search and provider tabs.\n */\nexport class ModelSelectorComponent extends Container implements Focusable {\n\tprivate searchInput: Input;\n\n\t// Focusable implementation - propagate to searchInput for IME cursor positioning\n\tprivate _focused = false;\n\tget focused(): boolean {\n\t\treturn this._focused;\n\t}\n\tset focused(value: boolean) {\n\t\tthis._focused = value;\n\t\tthis.searchInput.focused = value;\n\t}\n\tprivate listContainer: Container;\n\tprivate filteredModels: ModelItem[] = [];\n\tprivate selectedIndex: number = 0;\n\tprivate currentModel?: Model<any>;\n\tprivate currentModelKey?: string;\n\tprivate itemsByKey = new Map<string, ModelItem>();\n\tprivate state: ModelSelectorState = createInitialModelSelectorState();\n\tprivate modelRegistry: ModelRegistry;\n\tprivate onSelectCallback: (model: Model<any>) => void;\n\tprivate onCancelCallback: () => void;\n\tprivate errorMessage?: string;\n\tprivate tui: TUI;\n\tprivate scopedModels: ReadonlyArray<ScopedModelItem>;\n\tprivate scope: ModelScope = \"all\";\n\tprivate providerTabs: ProviderTab[] = [ALL_PROVIDER_TAB];\n\tprivate activeProviderTab: ProviderTab = ALL_PROVIDER_TAB;\n\tprivate providerText: Text;\n\tprivate providerHintText: Text;\n\tprivate scopeText?: Text;\n\tprivate scopeHintText?: Text;\n\n\tonProviderTabChange?: (tab: ProviderTab) => void;\n\n\tconstructor(\n\t\ttui: TUI,\n\t\tcurrentModel: Model<any> | undefined,\n\t\t_settingsManager: SettingsManager,\n\t\tmodelRegistry: ModelRegistry,\n\t\tscopedModels: ReadonlyArray<ScopedModelItem>,\n\t\tonSelect: (model: Model<any>) => void,\n\t\tonCancel: () => void,\n\t\tinitialSearchInput?: string,\n\t\tinitialProviderTab?: ProviderTab,\n\t) {\n\t\tsuper();\n\n\t\tthis.tui = tui;\n\t\tthis.currentModel = currentModel;\n\t\tthis.modelRegistry = modelRegistry;\n\t\tthis.scopedModels = scopedModels;\n\t\tthis.scope = scopedModels.length > 0 ? \"scoped\" : \"all\";\n\t\tthis.onSelectCallback = onSelect;\n\t\tthis.onCancelCallback = onCancel;\n\t\tif (initialProviderTab) {\n\t\t\t// Restored across showModelSelector() invocations so the user does not\n\t\t\t// lose the provider tab they picked last time. REFRESH_MODELS will\n\t\t\t// downgrade this to ALL_PROVIDER_TAB if the tab no longer exists after\n\t\t\t// models are loaded (e.g. provider deauthenticated or scoped).\n\t\t\tthis.activeProviderTab = initialProviderTab;\n\t\t}\n\t\tthis.state = createInitialModelSelectorState({ scope: this.scope, activeProvider: this.activeProviderTab });\n\n\t\t// Add top border\n\t\tthis.addChild(new DynamicBorder());\n\t\tthis.addChild(new Spacer(1));\n\n\t\tthis.providerText = new Text(this.getProviderText(), 0, 0);\n\t\tthis.addChild(this.providerText);\n\t\tthis.providerHintText = new Text(this.getProviderHintText(), 0, 0);\n\t\tthis.addChild(this.providerHintText);\n\n\t\t// Add hint about model filtering\n\t\tif (scopedModels.length > 0) {\n\t\t\tthis.scopeText = new Text(this.getScopeText(), 0, 0);\n\t\t\tthis.addChild(this.scopeText);\n\t\t\tthis.scopeHintText = new Text(this.getScopeHintText(), 0, 0);\n\t\t\tthis.addChild(this.scopeHintText);\n\t\t} else {\n\t\t\tconst hintText = \"Only showing models from configured providers. Use /login to add providers.\";\n\t\t\tthis.addChild(new Text(theme.fg(\"warning\", hintText), 0, 0));\n\t\t}\n\t\tthis.addChild(new Spacer(1));\n\n\t\t// Create search input\n\t\tthis.searchInput = new Input();\n\t\tif (initialSearchInput) {\n\t\t\tthis.searchInput.setValue(initialSearchInput);\n\t\t}\n\t\tthis.searchInput.onSubmit = () => {\n\t\t\t// Enter on search input selects the first filtered item\n\t\t\tif (this.filteredModels[this.selectedIndex]) {\n\t\t\t\tthis.handleSelect(this.filteredModels[this.selectedIndex].model);\n\t\t\t}\n\t\t};\n\t\tthis.addChild(this.searchInput);\n\n\t\tthis.addChild(new Spacer(1));\n\n\t\t// Create list container\n\t\tthis.listContainer = new Container();\n\t\tthis.addChild(this.listContainer);\n\n\t\tthis.addChild(new Spacer(1));\n\n\t\t// Add bottom border\n\t\tthis.addChild(new DynamicBorder());\n\n\t\t// Load models and do initial render\n\t\tthis.loadModels().then(() => {\n\t\t\tif (initialSearchInput) {\n\t\t\t\tthis.applyAction({ type: \"SEARCH\", query: initialSearchInput });\n\t\t\t}\n\t\t\t// Request re-render after models are loaded\n\t\t\tthis.tui.requestRender();\n\t\t});\n\t}\n\n\tprivate async loadModels(): Promise<void> {\n\t\tlet models: ModelItem[];\n\n\t\t// Refresh to pick up any changes to models.json\n\t\tthis.modelRegistry.refresh();\n\n\t\t// Check for models.json errors\n\t\tconst loadError = this.modelRegistry.getError();\n\t\tif (loadError) {\n\t\t\tthis.errorMessage = loadError;\n\t\t}\n\n\t\t// Load available models (built-in models still work even if models.json failed)\n\t\ttry {\n\t\t\tconst availableModels = await this.modelRegistry.getAvailable();\n\t\t\tmodels = availableModels.map((model: Model<any>) => ({\n\t\t\t\tprovider: model.provider,\n\t\t\t\tid: model.id,\n\t\t\t\tmodel,\n\t\t\t}));\n\t\t} catch (error) {\n\t\t\tthis.errorMessage = error instanceof Error ? error.message : String(error);\n\t\t\tthis.itemsByKey.clear();\n\t\t\tthis.currentModelKey = undefined;\n\t\t\tthis.applyAction({ type: \"REFRESH_MODELS\", allModels: [], scopedModels: [], currentModelKey: undefined });\n\t\t\treturn;\n\t\t}\n\n\t\tconst allItems = this.sortModels(models);\n\t\tthis.scopedModels = this.scopedModels.map((scoped) => {\n\t\t\tconst refreshed = this.modelRegistry.find(scoped.model.provider, scoped.model.id);\n\t\t\treturn refreshed ? { ...scoped, model: refreshed } : scoped;\n\t\t});\n\t\tconst scopedItems: ModelItem[] = this.scopedModels.map((scoped) => ({\n\t\t\tprovider: scoped.model.provider,\n\t\t\tid: scoped.model.id,\n\t\t\tmodel: scoped.model,\n\t\t}));\n\n\t\tthis.itemsByKey.clear();\n\t\tfor (const item of allItems) {\n\t\t\tthis.itemsByKey.set(modelSelectorModelKey(item), item);\n\t\t}\n\t\tfor (const item of scopedItems) {\n\t\t\tthis.itemsByKey.set(modelSelectorModelKey(item), item);\n\t\t}\n\n\t\tthis.currentModelKey = this.resolveCurrentModelKey(allItems, scopedItems);\n\t\tthis.applyAction({\n\t\t\ttype: \"REFRESH_MODELS\",\n\t\t\tallModels: allItems.map(toSelectorModel),\n\t\t\tscopedModels: scopedItems.map(toSelectorModel),\n\t\t\tcurrentModelKey: this.currentModelKey,\n\t\t});\n\t}\n\n\tprivate resolveCurrentModelKey(\n\t\tallItems: readonly ModelItem[],\n\t\tscopedItems: readonly ModelItem[],\n\t): string | undefined {\n\t\tif (!this.currentModel) return undefined;\n\t\tconst match =\n\t\t\tallItems.find((item) => modelsAreEqual(this.currentModel, item.model)) ??\n\t\t\tscopedItems.find((item) => modelsAreEqual(this.currentModel, item.model));\n\t\treturn match ? modelSelectorModelKey(match) : undefined;\n\t}\n\n\tprivate sortModels(models: ModelItem[]): ModelItem[] {\n\t\tconst sorted = [...models];\n\t\t// Sort: current model first, then by provider\n\t\tsorted.sort((a, b) => {\n\t\t\tconst aIsCurrent = modelsAreEqual(this.currentModel, a.model);\n\t\t\tconst bIsCurrent = modelsAreEqual(this.currentModel, b.model);\n\t\t\tif (aIsCurrent && !bIsCurrent) return -1;\n\t\t\tif (!aIsCurrent && bIsCurrent) return 1;\n\t\t\treturn a.provider.localeCompare(b.provider);\n\t\t});\n\t\treturn sorted;\n\t}\n\n\tprivate isProviderAuthenticated(provider: string): boolean {\n\t\tif (provider === ALL_PROVIDER_TAB) return true;\n\t\tconst status = this.modelRegistry.authStorage.getAuthStatus(provider);\n\t\treturn status.configured || status.source !== undefined;\n\t}\n\n\tprivate providerTabLabel(provider: ProviderTab): string {\n\t\tconst auth = this.isProviderAuthenticated(provider);\n\t\tconst glyph = provider === ALL_PROVIDER_TAB ? \"\" : ` ${providerAuthGlyph(auth)}`;\n\t\treturn `${provider}${glyph}`;\n\t}\n\n\tprivate themedProviderTab(provider: ProviderTab): string {\n\t\tconst label = this.providerTabLabel(provider);\n\t\tif (provider === this.activeProviderTab) return theme.fg(\"accent\", label);\n\t\treturn this.isProviderAuthenticated(provider) ? theme.fg(\"muted\", label) : theme.fg(\"dim\", label);\n\t}\n\n\t/**\n\t * Build the provider tab row. When a render width is supplied, the strip is\n\t * windowed with fitProviderStrip() so it always fits the terminal while keeping\n\t * the \"all\" anchor and the active tab visible; otherwise every tab is shown\n\t * (used for non-render measurement contexts).\n\t */\n\tprivate getProviderText(width?: number): string {\n\t\tconst prefix = theme.fg(\"muted\", \"Provider: \");\n\t\tif (this.providerTabs.length === 0) return prefix;\n\t\tconst separator = theme.fg(\"dim\", \" | \");\n\t\tconst ellipsis = theme.fg(\"dim\", \"…\");\n\n\t\tlet indices: readonly number[];\n\t\tlet leadingEllipsis = false;\n\t\tlet trailingEllipsis = false;\n\t\tif (width === undefined) {\n\t\t\tindices = this.providerTabs.map((_, index) => index);\n\t\t} else {\n\t\t\tconst budget = Math.max(0, width - visibleWidth(\"Provider: \"));\n\t\t\tconst tabWidths = this.providerTabs.map((provider) => visibleWidth(this.providerTabLabel(provider)));\n\t\t\tconst activeIndex = Math.max(0, this.providerTabs.indexOf(this.activeProviderTab));\n\t\t\tconst layout = fitProviderStrip(tabWidths, activeIndex, budget, visibleWidth(\" | \"), visibleWidth(\"…\"));\n\t\t\tindices = layout.indices;\n\t\t\tleadingEllipsis = layout.ellipsisAfterFirst;\n\t\t\ttrailingEllipsis = layout.trailingEllipsis;\n\t\t}\n\n\t\tconst segments: string[] = [];\n\t\tfor (let position = 0; position < indices.length; position++) {\n\t\t\tif (position === 1 && leadingEllipsis) segments.push(ellipsis);\n\t\t\tconst tabIndex = indices[position];\n\t\t\tif (tabIndex === undefined) continue;\n\t\t\tconst provider = this.providerTabs[tabIndex];\n\t\t\tif (provider !== undefined) segments.push(this.themedProviderTab(provider));\n\t\t}\n\t\tif (trailingEllipsis) segments.push(ellipsis);\n\t\treturn `${prefix}${segments.join(separator)}`;\n\t}\n\n\tprivate getProviderHintText(): string {\n\t\treturn (\n\t\t\tkeyHint(\"tui.input.tab\", \"provider\") +\n\t\t\ttheme.fg(\"muted\", \" · \") +\n\t\t\tkeyHint(\"app.model.providerPrevious\", \"previous provider\")\n\t\t);\n\t}\n\n\tprivate getScopeText(): string {\n\t\tconst allText = this.scope === \"all\" ? theme.fg(\"accent\", \"all\") : theme.fg(\"muted\", \"all\");\n\t\tconst scopedText = this.scope === \"scoped\" ? theme.fg(\"accent\", \"scoped\") : theme.fg(\"muted\", \"scoped\");\n\t\treturn `${theme.fg(\"muted\", \"Scope: \")}${allText}${theme.fg(\"muted\", \" | \")}${scopedText}`;\n\t}\n\n\tprivate getScopeHintText(): string {\n\t\treturn keyHint(\"app.model.cycleForward\", \"scope\") + theme.fg(\"muted\", \" (all/scoped)\");\n\t}\n\n\tprivate applyAction(action: ModelSelectorAction): void {\n\t\tconst previousProvider = this.state.activeProvider;\n\t\tthis.state = modelSelectorReducer(this.state, action);\n\t\tthis.syncRenderState();\n\t\tthis.updateList();\n\t\tif (this.state.activeProvider !== previousProvider) {\n\t\t\tthis.onProviderTabChange?.(this.state.activeProvider);\n\t\t}\n\t}\n\n\t/**\n\t * Mirror the reducer's semantic state into the fields the renderer reads.\n\t * The reducer is the single source of truth; these fields are a derived view\n\t * kept in sync after every transition.\n\t */\n\tprivate syncRenderState(): void {\n\t\tthis.scope = this.state.scope;\n\t\tthis.activeProviderTab = this.state.activeProvider;\n\t\tthis.providerTabs = [...this.state.providerIds];\n\t\tthis.selectedIndex = this.state.selectedIndex;\n\n\t\tconst visibleItems: ModelItem[] = [];\n\t\tfor (const modelKey of this.state.visibleModelKeys) {\n\t\t\tconst item = this.itemsByKey.get(modelKey);\n\t\t\tif (item) visibleItems.push(item);\n\t\t}\n\t\tthis.filteredModels = visibleItems;\n\n\t\tthis.providerText.setText(this.getProviderText());\n\t\tthis.providerHintText.setText(this.getProviderHintText());\n\t\tif (this.scopeText) {\n\t\t\tthis.scopeText.setText(this.getScopeText());\n\t\t}\n\t\tif (this.scopeHintText) {\n\t\t\tthis.scopeHintText.setText(this.getScopeHintText());\n\t\t}\n\t}\n\n\tprivate updateList(): void {\n\t\tthis.listContainer.clear();\n\n\t\tconst maxVisible = 10;\n\t\tconst startIndex = Math.max(\n\t\t\t0,\n\t\t\tMath.min(this.selectedIndex - Math.floor(maxVisible / 2), this.filteredModels.length - maxVisible),\n\t\t);\n\t\tconst endIndex = Math.min(startIndex + maxVisible, this.filteredModels.length);\n\n\t\t// Show visible slice of filtered models\n\t\tfor (let i = startIndex; i < endIndex; i++) {\n\t\t\tconst item = this.filteredModels[i];\n\t\t\tif (!item) continue;\n\n\t\t\tconst isSelected = i === this.selectedIndex;\n\t\t\tconst isCurrent = modelsAreEqual(this.currentModel, item.model);\n\t\t\tconst providerAuthed = this.isProviderAuthenticated(item.provider);\n\t\t\tconst providerLabel = `[${item.provider}${providerAuthed ? \"\" : \" no-auth\"}]`;\n\t\t\tconst providerBadge = providerAuthed ? theme.fg(\"muted\", providerLabel) : theme.fg(\"warning\", providerLabel);\n\t\t\tconst thinkingBadge = theme.fg(\"dim\", ` · ${formatThinkingBadge(item.model)}`);\n\t\t\tconst checkmark = isCurrent ? theme.fg(\"success\", \" ✓\") : \"\";\n\n\t\t\tlet line = \"\";\n\t\t\tif (isSelected) {\n\t\t\t\tconst prefix = theme.fg(\"accent\", \"→ \");\n\t\t\t\tline = `${prefix + theme.fg(\"accent\", item.id)} ${providerBadge}${thinkingBadge}${checkmark}`;\n\t\t\t} else {\n\t\t\t\tline = ` ${item.id} ${providerBadge}${thinkingBadge}${checkmark}`;\n\t\t\t}\n\n\t\t\tthis.listContainer.addChild(new Text(line, 0, 0));\n\t\t}\n\n\t\t// Add scroll indicator if needed\n\t\tif (startIndex > 0 || endIndex < this.filteredModels.length) {\n\t\t\tconst scrollInfo = theme.fg(\"muted\", ` (${this.selectedIndex + 1}/${this.filteredModels.length})`);\n\t\t\tthis.listContainer.addChild(new Text(scrollInfo, 0, 0));\n\t\t}\n\n\t\t// Show error message or \"no results\" if empty\n\t\tif (this.errorMessage) {\n\t\t\t// Show error in red\n\t\t\tconst errorLines = this.errorMessage.split(\"\\n\");\n\t\t\tfor (const line of errorLines) {\n\t\t\t\tthis.listContainer.addChild(new Text(theme.fg(\"error\", line), 0, 0));\n\t\t\t}\n\t\t} else if (this.filteredModels.length === 0) {\n\t\t\tthis.listContainer.addChild(new Text(theme.fg(\"muted\", \" No matching models\"), 0, 0));\n\t\t} else {\n\t\t\tconst selected = this.filteredModels[this.selectedIndex];\n\t\t\tthis.listContainer.addChild(new Spacer(1));\n\t\t\tthis.listContainer.addChild(new Text(theme.fg(\"muted\", ` Model Name: ${selected.model.name}`), 0, 0));\n\t\t}\n\t}\n\n\thandleInput(keyData: string): void {\n\t\tconst kb = getKeybindings();\n\t\tif (kb.matches(keyData, \"tui.input.tab\")) {\n\t\t\tthis.applyAction({ type: \"NEXT_PROVIDER\" });\n\t\t\treturn;\n\t\t}\n\t\tif (kb.matches(keyData, \"app.model.providerPrevious\")) {\n\t\t\tthis.applyAction({ type: \"PREVIOUS_PROVIDER\" });\n\t\t\treturn;\n\t\t}\n\t\tif (this.state.scopedModels.length > 0) {\n\t\t\tif (kb.matches(keyData, \"app.model.cycleForward\")) {\n\t\t\t\tthis.applyAction({ type: \"TOGGLE_SCOPE_FORWARD\" });\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (kb.matches(keyData, \"app.model.cycleBackward\")) {\n\t\t\t\tthis.applyAction({ type: \"TOGGLE_SCOPE_BACKWARD\" });\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\t// Up arrow - wrap to bottom when at top\n\t\tif (kb.matches(keyData, \"tui.select.up\")) {\n\t\t\tthis.applyAction({ type: \"MOVE_SELECTION\", delta: -1 });\n\t\t}\n\t\t// Down arrow - wrap to top when at bottom\n\t\telse if (kb.matches(keyData, \"tui.select.down\")) {\n\t\t\tthis.applyAction({ type: \"MOVE_SELECTION\", delta: 1 });\n\t\t}\n\t\t// Enter\n\t\telse if (kb.matches(keyData, \"tui.select.confirm\")) {\n\t\t\tconst selectedModel = this.filteredModels[this.selectedIndex];\n\t\t\tif (selectedModel) {\n\t\t\t\tthis.handleSelect(selectedModel.model);\n\t\t\t}\n\t\t}\n\t\t// Escape or Ctrl+C\n\t\telse if (kb.matches(keyData, \"tui.select.cancel\")) {\n\t\t\tthis.onCancelCallback();\n\t\t}\n\t\t// Pass everything else to search input\n\t\telse {\n\t\t\tthis.searchInput.handleInput(keyData);\n\t\t\tthis.applyAction({ type: \"SEARCH\", query: this.searchInput.getValue() });\n\t\t}\n\t}\n\n\tprivate handleSelect(model: Model<any>): void {\n\t\tthis.onSelectCallback(model);\n\t}\n\n\t/**\n\t * Structured /model contract state. Tests and future reducer/property\n\t * harnesses should assert this semantic snapshot instead of parsing themed\n\t * presentation text or reaching into private fields.\n\t */\n\tgetSemanticState(): ModelSelectorSemanticState {\n\t\treturn {\n\t\t\tscope: this.state.scope,\n\t\t\tactiveProvider: this.state.activeProvider,\n\t\t\tproviderIds: [...this.state.providerIds],\n\t\t\tquery: this.state.query,\n\t\t\tselectedIndex: this.state.selectedIndex,\n\t\t\tselectedModelKey: selectedModelKey(this.state),\n\t\t\tvisibleModelKeys: [...this.state.visibleModelKeys],\n\t\t};\n\t}\n\n\t/**\n\t * Width-aware render: recompute the provider row for the actual terminal width\n\t * so the strip fits without wrapping, then delegate to the container renderer.\n\t */\n\trender(width: number): string[] {\n\t\tthis.providerText.setText(this.getProviderText(width));\n\t\treturn super.render(width);\n\t}\n\n\tgetSearchInput(): Input {\n\t\treturn this.searchInput;\n\t}\n}\n"]}