okengine 0.18.4 → 0.19.0

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 (512) hide show
  1. package/AGENTS.md +18 -10
  2. package/README.md +2 -2
  3. package/package.json +51 -50
  4. package/site/content/docs/ai/index.mdx +25 -6
  5. package/site/content/docs/ai/llms-txt.mdx +1 -1
  6. package/site/content/docs/ai/meta.json +1 -1
  7. package/site/content/docs/ai/skills.mdx +4 -1
  8. package/site/content/docs/ai/try-it.mdx +58 -0
  9. package/site/content/docs/client/auth.mdx +208 -0
  10. package/site/content/docs/client/calling.mdx +451 -0
  11. package/site/content/docs/client/index.mdx +209 -0
  12. package/site/content/docs/client/live.mdx +234 -0
  13. package/site/content/docs/client/meta.json +5 -0
  14. package/site/content/docs/client/react.mdx +249 -0
  15. package/site/content/docs/elements/ai/agents.mdx +232 -0
  16. package/site/content/docs/elements/ai/index.mdx +341 -0
  17. package/site/content/docs/elements/ai/mcp.mdx +275 -0
  18. package/site/content/docs/elements/ai/meta.json +5 -0
  19. package/site/content/docs/elements/ai/models.mdx +283 -0
  20. package/site/content/docs/elements/ai/prompts.mdx +256 -0
  21. package/site/content/docs/elements/channel/email.mdx +266 -0
  22. package/site/content/docs/elements/channel/index.mdx +344 -0
  23. package/site/content/docs/elements/channel/meta.json +5 -0
  24. package/site/content/docs/elements/channel/push.mdx +218 -0
  25. package/site/content/docs/elements/channel/receipts.mdx +206 -0
  26. package/site/content/docs/elements/channel/sms.mdx +264 -0
  27. package/site/content/docs/elements/channel/whatsapp.mdx +220 -0
  28. package/site/content/docs/elements/clock/index.mdx +300 -0
  29. package/site/content/docs/elements/clock/meta.json +5 -0
  30. package/site/content/docs/elements/clock/schedules.mdx +508 -0
  31. package/site/content/docs/elements/clock/sleep.mdx +445 -0
  32. package/site/content/docs/elements/flow/consumers.mdx +707 -0
  33. package/site/content/docs/elements/flow/http.mdx +1080 -0
  34. package/site/content/docs/elements/flow/index.mdx +618 -0
  35. package/site/content/docs/elements/flow/meta.json +5 -0
  36. package/site/content/docs/elements/flow/routing.mdx +559 -0
  37. package/site/content/docs/elements/flow/workflows.mdx +640 -0
  38. package/site/content/docs/elements/gate/auth.mdx +371 -0
  39. package/site/content/docs/elements/gate/authorization.mdx +298 -0
  40. package/site/content/docs/elements/gate/index.mdx +418 -0
  41. package/site/content/docs/elements/gate/meta.json +5 -0
  42. package/site/content/docs/elements/gate/rate-limits.mdx +365 -0
  43. package/site/content/docs/elements/gate/rls.mdx +303 -0
  44. package/site/content/docs/elements/gate/tenancy.mdx +372 -0
  45. package/site/content/docs/elements/index.mdx +52 -11
  46. package/site/content/docs/elements/signal/broadcast.mdx +517 -0
  47. package/site/content/docs/elements/signal/index.mdx +352 -0
  48. package/site/content/docs/elements/signal/live.mdx +590 -0
  49. package/site/content/docs/elements/signal/meta.json +5 -0
  50. package/site/content/docs/elements/signal/once.mdx +596 -0
  51. package/site/content/docs/elements/store/files.mdx +659 -0
  52. package/site/content/docs/elements/store/index.mdx +310 -0
  53. package/site/content/docs/elements/store/kv.mdx +629 -0
  54. package/site/content/docs/elements/store/meta.json +5 -0
  55. package/site/content/docs/elements/store/search.mdx +946 -0
  56. package/site/content/docs/elements/store/sql.mdx +937 -0
  57. package/site/content/docs/elements/vault/config.mdx +256 -0
  58. package/site/content/docs/elements/vault/index.mdx +356 -0
  59. package/site/content/docs/elements/vault/meta.json +5 -0
  60. package/site/content/docs/elements/vault/rotation.mdx +273 -0
  61. package/site/content/docs/elements/vault/secrets.mdx +285 -0
  62. package/site/content/docs/index.mdx +78 -30
  63. package/site/content/docs/meta.json +11 -8
  64. package/site/content/docs/plugins/cors.mdx +2 -1
  65. package/site/content/docs/plugins/csrf.mdx +4 -1
  66. package/site/content/docs/plugins/headers.mdx +2 -1
  67. package/site/content/docs/plugins/ip-allowlist.mdx +2 -1
  68. package/site/content/docs/plugins/magic-link.mdx +6 -0
  69. package/site/content/docs/plugins/maintenance-mode.mdx +2 -1
  70. package/site/content/docs/plugins/oauth.mdx +1 -1
  71. package/site/content/docs/plugins/otp.mdx +12 -1
  72. package/site/content/docs/plugins/passkey.mdx +39 -15
  73. package/site/content/docs/plugins/two-factor.mdx +91 -34
  74. package/site/content/docs/plugins/username.mdx +1 -1
  75. package/site/content/docs/recipes/caddy.mdx +3 -3
  76. package/site/content/docs/recipes/index.mdx +18 -28
  77. package/site/content/docs/recipes/mailpit.mdx +1 -1
  78. package/site/content/docs/recipes/meilisearch.mdx +3 -3
  79. package/site/content/docs/recipes/meta.json +1 -4
  80. package/site/content/docs/recipes/nginx.mdx +2 -2
  81. package/site/content/docs/recipes/openrouter.mdx +283 -0
  82. package/site/content/docs/recipes/pgdog.mdx +3 -3
  83. package/site/content/docs/recipes/postgres.mdx +1 -2
  84. package/site/content/docs/recipes/rustfs.mdx +2 -2
  85. package/site/content/docs/recipes/traefik.mdx +3 -3
  86. package/site/content/docs/reference/cli.mdx +231 -0
  87. package/site/content/docs/reference/configuration.mdx +30 -10
  88. package/site/content/docs/reference/environment-variables.mdx +93 -20
  89. package/site/content/docs/reference/errors.mdx +132 -29
  90. package/site/content/docs/reference/fx.mdx +137 -73
  91. package/site/content/docs/reference/index.mdx +13 -21
  92. package/site/content/docs/reference/meta.json +4 -5
  93. package/site/content/docs/reference/okid.mdx +42 -17
  94. package/site/content/docs/reference/plugins.mdx +4 -3
  95. package/site/content/docs/reference/security.mdx +197 -0
  96. package/site/content/docs/understand/meta.json +5 -0
  97. package/site/content/docs/understand/the-anatomy.mdx +132 -0
  98. package/site/content/docs/understand/the-model.mdx +32 -0
  99. package/site/content/docs/understand/the-problem.mdx +74 -0
  100. package/site/content/docs/understand/the-vocabulary.mdx +26 -0
  101. package/src/auth/api-keys.ts +2 -1
  102. package/src/auth/bindings.ts +64 -16
  103. package/src/auth/gate-auth.test.ts +6 -1
  104. package/src/auth/identity.ts +152 -5
  105. package/src/auth/index.ts +29 -0
  106. package/src/auth/invites.ts +2 -1
  107. package/src/auth/method-context.ts +41 -0
  108. package/src/auth/oauth-as/crypto.ts +2 -1
  109. package/src/auth/oauth-as/stores.ts +2 -1
  110. package/src/auth/operator.ts +2 -1
  111. package/src/auth/sessions-jwt.test.ts +77 -0
  112. package/src/auth/sessions.ts +20 -4
  113. package/src/auth/tenants.ts +3 -2
  114. package/src/auth/two-factor-challenge.test.ts +61 -0
  115. package/src/auth/two-factor-challenge.ts +284 -0
  116. package/src/auth/verification.ts +5 -0
  117. package/src/bench/REPORT.md +49 -0
  118. package/src/bench/g03-signal-once.bench.ts +1 -1
  119. package/src/bench/g10-observability-contention.bench.ts +1 -1
  120. package/src/bench/g17-hybrid-search.bench.ts +572 -0
  121. package/src/bench/load-app.ts +2 -10
  122. package/src/cli/ai-setup/ai-setup.test.ts +331 -42
  123. package/src/cli/ai-setup/apply.ts +294 -52
  124. package/src/cli/ai-setup/catalog.ts +238 -1342
  125. package/src/cli/ai-setup/index.ts +14 -99
  126. package/src/cli/ai-setup/prompts.ts +60 -443
  127. package/src/cli/ask-seed.test.ts +96 -0
  128. package/src/cli/ask-seed.ts +82 -0
  129. package/src/cli/ask-vault-gaps.test.ts +84 -0
  130. package/src/cli/ask-vault-gaps.ts +146 -0
  131. package/src/cli/build.ts +2 -2
  132. package/src/cli/client-add.test.ts +26 -1
  133. package/src/cli/client-add.ts +106 -27
  134. package/src/cli/competitor-mention-removal.test.ts +1 -1
  135. package/src/cli/db-seed.ts +2 -0
  136. package/src/cli/db.ts +150 -11
  137. package/src/cli/dev.ts +119 -211
  138. package/src/cli/docker-clean.ts +2 -2
  139. package/src/cli/docker-cli.test.ts +1 -1
  140. package/src/cli/doctor-diff.ts +4 -2
  141. package/src/cli/doctor-pii.test.ts +1 -1
  142. package/src/cli/doctor.ts +14 -1
  143. package/src/cli/hero-meta.test.ts +4 -2
  144. package/src/cli/load-config.images.test.ts +8 -10
  145. package/src/cli/load-config.ts +1 -1
  146. package/src/cli/registry.ts +22 -10
  147. package/src/cli/replay.ts +3 -1
  148. package/src/cli/start.ts +1 -1
  149. package/src/cli/tui/keys.ts +2 -3
  150. package/src/client/auth/cookies.ts +74 -0
  151. package/src/client/auth/create-auth-client.ts +636 -0
  152. package/src/client/auth/denials.ts +99 -0
  153. package/src/client/auth/session.ts +283 -0
  154. package/src/client/auth.test.ts +251 -0
  155. package/src/client/auth.ts +39 -114
  156. package/src/client/create-with-session.ts +245 -0
  157. package/src/client/create.ts +51 -5
  158. package/src/client/index.ts +11 -1
  159. package/src/client/live.ts +11 -79
  160. package/src/client/notes-contract.test.ts +5 -10
  161. package/src/client/sse.ts +137 -0
  162. package/src/client/stream.ts +147 -0
  163. package/src/client/transport.test.ts +32 -0
  164. package/src/client/transport.ts +123 -26
  165. package/src/client/types.ts +118 -14
  166. package/src/client-react/index.ts +185 -24
  167. package/src/client-react/use-live-query.ts +13 -3
  168. package/src/compiler/aot.test.ts +7 -4
  169. package/src/compiler/effects-embed.test.ts +56 -0
  170. package/src/compiler/effects-fetch.test.ts +43 -0
  171. package/src/compiler/effects-infer.ts +58 -2
  172. package/src/compiler/extract.test.ts +258 -44
  173. package/src/compiler/extract.ts +566 -48
  174. package/src/compiler/fixtures/skyport/src/flows/bookings/index.ts +7 -4
  175. package/src/compiler/fixtures/skyport/src/flows/bookings/signals.ts +2 -8
  176. package/src/compiler/fixtures/skyport.expected.json +4 -4
  177. package/src/compiler/fixtures/triggers/five-triggers.ts +14 -10
  178. package/src/compiler/response.ts +2 -2
  179. package/src/compiler/search-writer-isolation.test.ts +40 -0
  180. package/src/config/index.ts +11 -0
  181. package/src/console/server/app.ts +17 -23
  182. package/src/console/server/bind.ts +4 -0
  183. package/src/console/server/console.test.ts +2 -2
  184. package/src/console/server/flows-invoke.test.ts +50 -34
  185. package/src/console/server/flows.ts +436 -255
  186. package/src/console/server/runs-ingest.test.ts +6 -3
  187. package/src/console/server/serve.ts +1 -1
  188. package/src/console/server/signals.test.ts +1 -5
  189. package/src/console/server/signals.ts +8 -6
  190. package/src/console/server/state.ts +6 -1
  191. package/src/console/server/store.ts +1 -1
  192. package/src/console/ui-next/dist/assets/FileExportIcon-Ck-5od4R.js +1 -0
  193. package/src/console/ui-next/dist/assets/MoreHorizontalCircle01Icon-gMNGsE37.js +1 -0
  194. package/src/console/ui-next/dist/assets/PlusSignIcon-CwG3nxfu.js +1 -0
  195. package/src/console/ui-next/dist/assets/UnavailableIcon-D9cvHVPr.js +1 -0
  196. package/src/console/ui-next/dist/assets/UserIcon-DaE2PB5_.js +1 -0
  197. package/src/console/ui-next/dist/assets/access-page-DFeymU07.js +4 -0
  198. package/src/console/ui-next/dist/assets/agent-disclosure-U1rdfblp.js +1 -0
  199. package/src/console/ui-next/dist/assets/cache-glyph-BeFJeqBG.js +1 -0
  200. package/src/console/ui-next/dist/assets/call-pii-button-CVAONPii.js +1 -0
  201. package/src/console/ui-next/dist/assets/collapsible-D2A6NJ-3.js +1 -0
  202. package/src/console/ui-next/dist/assets/copy-inline-button-CAYD18cr.js +1 -0
  203. package/src/console/ui-next/dist/assets/dagre.esm-B1_XeuLP.js +1 -0
  204. package/src/console/ui-next/dist/assets/detail-header-DVWNjWjg.js +1 -0
  205. package/src/console/ui-next/dist/assets/dropdown-menu-4h2LOVXM.js +1 -0
  206. package/src/console/ui-next/dist/assets/duration-tone-Cgk_h5ja.js +9 -0
  207. package/src/console/ui-next/dist/assets/element-icons-BI8cJgdh.js +1 -0
  208. package/src/console/ui-next/dist/assets/explorer-empty-CJs5A-wm.js +1 -0
  209. package/src/console/ui-next/dist/assets/flows-page-Dss7941e.js +1 -0
  210. package/src/console/ui-next/dist/assets/highlighted-json-MYZQtRnw.js +154 -0
  211. package/src/console/ui-next/dist/assets/http-method-Jrh39p7A.js +1 -0
  212. package/src/console/ui-next/dist/assets/index-D0zS5rKO.css +2 -0
  213. package/src/console/ui-next/dist/assets/index-DXP2dBIF.js +63 -0
  214. package/src/console/ui-next/dist/assets/observability-page-HvolXxTI.js +4 -0
  215. package/src/console/ui-next/dist/assets/react-dom-Ddte4I-Q.js +9 -0
  216. package/src/console/ui-next/dist/assets/replica-lag-CSh2dzrb.js +18 -0
  217. package/src/console/ui-next/dist/assets/request-meta-BatF8KrK.js +1 -0
  218. package/src/console/ui-next/dist/assets/shortcut-keys-3ILd8oGn.js +1 -0
  219. package/src/console/ui-next/dist/assets/{sql-BskegiFM.js → sql-BsFa4tDR.js} +1 -1
  220. package/src/console/ui-next/dist/assets/store-page-eiKiHnNe.js +41 -0
  221. package/src/console/ui-next/dist/assets/trace-detail-sheet-CZkMeKS-.js +2 -0
  222. package/src/console/ui-next/dist/assets/tree-expand-toggle-CW8y5A2h.js +55 -0
  223. package/src/console/ui-next/dist/assets/units-page-B_RWJrEO.js +1 -0
  224. package/src/console/ui-next/dist/assets/{use-vault-list-uk4WVboC.js → use-vault-list-CT4-gajj.js} +1 -1
  225. package/src/console/ui-next/dist/assets/vault-page-CWrg-A68.js +2 -0
  226. package/src/console/ui-next/dist/assets/xyflow-CSyC6ryz.css +1 -0
  227. package/src/console/ui-next/dist/assets/xyflow-yApv7D4e.js +7 -0
  228. package/src/console/ui-next/dist/index.html +6 -13
  229. package/src/console/ui-next/seed-invoke-host.ts +21 -18
  230. package/src/console/ui-next/src/client.ts +7 -2
  231. package/src/console/ui-next/src/features/flows/graph/element-map.ts +2 -0
  232. package/src/console/ui-next/src/features/flows/traces/effect-kind.ts +12 -2
  233. package/src/console/ui-next/src/features/flows/traces/effect-summary.ts +4 -0
  234. package/src/console/ui-next/src/features/flows/traces/trace-detail-sheet.tsx +8 -0
  235. package/src/console/ui-next/src/features/flows/traces/waterfall-bars.ts +4 -0
  236. package/src/console/ui-next/src/features/flows/traces/waterfall-tooltip.ts +9 -3
  237. package/src/console/ui-next/src/features/store/detail/reveal-cell.tsx +7 -11
  238. package/src/console/ui-next/src/features/store/detail/store-row-detail-sheet.tsx +2 -2
  239. package/src/console/ui-next/src/features/store/lib/fields-from-table.ts +2 -0
  240. package/src/console/ui-next/src/features/store/lib/grid-model.test.ts +25 -1
  241. package/src/console/ui-next/src/features/store/lib/grid-model.ts +36 -1
  242. package/src/console/ui-next/src/features/store/query/query-results.tsx +3 -3
  243. package/src/console/ui-next/src/features/units/detail/effects-summary.tsx +2 -0
  244. package/src/console/ui-next/src/features/units/lib/call-read-safe.ts +3 -1
  245. package/src/console/ui-next/src/features/units/lib/fields-from-schema.ts +6 -0
  246. package/src/docker/ai-model-status.test.ts +1 -12
  247. package/src/docker/ai-model-status.ts +10 -38
  248. package/src/docker/compose-up.test.ts +100 -0
  249. package/src/docker/compose-up.ts +292 -0
  250. package/src/docker/compose.ts +4 -14
  251. package/src/docker/derive.ts +9 -34
  252. package/src/docker/docker.test.ts +16 -261
  253. package/src/docker/images-config.test.ts +13 -25
  254. package/src/docker/index.ts +1 -24
  255. package/src/docker/recipes/index.ts +0 -23
  256. package/src/docker/recipes/pgdog.ts +6 -4
  257. package/src/docker/stack-id.test.ts +2 -2
  258. package/src/docker/stack-id.ts +0 -1
  259. package/src/docker/types.ts +2 -2
  260. package/src/drivers/ai-anthropic.ts +10 -0
  261. package/src/drivers/ai-openai-compatible.ts +34 -7
  262. package/src/drivers/ai-providers.test.ts +0 -107
  263. package/src/drivers/ai-stream.test.ts +0 -34
  264. package/src/drivers/ai-types.ts +17 -8
  265. package/src/drivers/channel-fcm.ts +6 -1
  266. package/src/drivers/channel-msegat.ts +6 -1
  267. package/src/drivers/channel-resend.ts +5 -1
  268. package/src/drivers/channel-smtp.ts +5 -1
  269. package/src/drivers/channel-sndr.ts +10 -1
  270. package/src/drivers/channel-taqnyat-mail.ts +5 -1
  271. package/src/drivers/channel-taqnyat-whatsapp.ts +6 -1
  272. package/src/drivers/channel-taqnyat.ts +6 -1
  273. package/src/drivers/channel-types.ts +10 -0
  274. package/src/drivers/channel-unifonic.ts +6 -1
  275. package/src/drivers/channel-wa-cloud.ts +6 -1
  276. package/src/drivers/channel-webpush.ts +6 -1
  277. package/src/drivers/external.ts +33 -0
  278. package/src/drivers/index.ts +0 -10
  279. package/src/drivers/meilisearch.ts +6 -0
  280. package/src/drivers/oauth-types.ts +4 -0
  281. package/src/drivers/postgres.test.ts +74 -3
  282. package/src/drivers/postgres.ts +175 -6
  283. package/src/drivers/signal-types.ts +5 -5
  284. package/src/drivers/types.ts +7 -0
  285. package/src/drivers/vault-types.ts +5 -0
  286. package/src/elements/ai/declare.ts +17 -4
  287. package/src/elements/ai/eval.ts +1 -1
  288. package/src/elements/ai/mcp-http.ts +1 -1
  289. package/src/elements/ai/pii.ts +1 -1
  290. package/src/elements/ai/providers.test.ts +289 -0
  291. package/src/elements/ai/providers.ts +169 -0
  292. package/src/elements/ai/runtime.ts +68 -5
  293. package/src/elements/ai/schema.ts +2 -2
  294. package/src/elements/ai.test.ts +7 -7
  295. package/src/elements/ai.ts +17 -1
  296. package/src/elements/channel/runtime.ts +105 -12
  297. package/src/elements/clock/cron-fields.test.ts +144 -0
  298. package/src/elements/clock/cron-fields.ts +185 -0
  299. package/src/elements/clock/declare.ts +247 -3
  300. package/src/elements/clock.ts +21 -1
  301. package/src/elements/index.ts +15 -0
  302. package/src/elements/signal/chaos-child.ts +1 -2
  303. package/src/elements/signal/declare.ts +65 -37
  304. package/src/elements/signal/delivery-modes.test.ts +11 -31
  305. package/src/elements/signal/dry-run-replay.test.ts +1 -7
  306. package/src/elements/signal/dry-run-write-isolation.test.ts +1 -7
  307. package/src/elements/signal/key-ordering.test.ts +6 -26
  308. package/src/elements/signal/lease-reclaim.test.ts +2 -6
  309. package/src/elements/signal/optional-emit.test.ts +6 -9
  310. package/src/elements/signal/order-lifecycle.test.ts +4 -17
  311. package/src/elements/signal/orphan-messages.test.ts +4 -15
  312. package/src/elements/signal/reconcile.test.ts +2 -2
  313. package/src/elements/signal/runtime.ts +1 -1
  314. package/src/elements/signal/schema-emit.test.ts +4 -8
  315. package/src/elements/signal.test.ts +24 -49
  316. package/src/elements/signal.ts +9 -2
  317. package/src/elements/store/domain-ddl.test.ts +1 -1
  318. package/src/elements/store/live-http.test.ts +9 -4
  319. package/src/elements/store/prepare-row.test.ts +123 -0
  320. package/src/elements/store/resource.ts +43 -12
  321. package/src/elements/store/schema-decl.ts +117 -0
  322. package/src/elements/store/search-backfill.ts +205 -0
  323. package/src/elements/store/search-bind.ts +66 -0
  324. package/src/elements/store/search-bm25.ts +78 -0
  325. package/src/elements/store/search-ddl.ts +156 -0
  326. package/src/elements/store/search-embed-flow.ts +141 -0
  327. package/src/elements/store/search-errors.ts +34 -0
  328. package/src/elements/store/search-fusion.ts +112 -0
  329. package/src/elements/store/search-lsh.ts +179 -0
  330. package/src/elements/store/search-runtime.ts +300 -0
  331. package/src/elements/store/search.test.ts +144 -0
  332. package/src/elements/store/sql-session.test.ts +1 -0
  333. package/src/elements/store/sql-session.ts +83 -3
  334. package/src/elements/store/table.ts +23 -2
  335. package/src/elements/store/upsert-app.test.ts +1 -3
  336. package/src/elements/store.ts +50 -0
  337. package/src/full.ts +4 -2
  338. package/src/http.ts +4 -1
  339. package/src/i18n/catalogs/ar.ts +14 -6
  340. package/src/i18n/catalogs/en.ts +14 -6
  341. package/src/index.ts +6 -1
  342. package/src/kernel/adopt-barrel-fresh.test.ts +7 -7
  343. package/src/kernel/adopt-routes.ts +9 -1
  344. package/src/kernel/app-auth.ts +5 -0
  345. package/src/kernel/app.ts +102 -9
  346. package/src/kernel/auto-cache.test.ts +6 -12
  347. package/src/kernel/auto-registry.test.ts +3 -3
  348. package/src/kernel/boot-bind/ai.test.ts +22 -19
  349. package/src/kernel/boot-bind/ai.ts +5 -43
  350. package/src/kernel/boot-bind/clock.ts +23 -5
  351. package/src/kernel/boot-bind/honor-config.test.ts +4 -4
  352. package/src/kernel/boot.test.ts +11 -6
  353. package/src/kernel/boot.ts +66 -16
  354. package/src/kernel/boundary-contract.ts +93 -0
  355. package/src/kernel/budget.test.ts +1 -1
  356. package/src/kernel/call.ts +89 -0
  357. package/src/kernel/capability.ts +6 -0
  358. package/src/kernel/client-descriptor.ts +123 -0
  359. package/src/kernel/clock-timezone.test.ts +80 -0
  360. package/src/kernel/correlation.test.ts +1 -1
  361. package/src/kernel/dry-run.ts +11 -8
  362. package/src/kernel/effects-stamping.test.ts +42 -9
  363. package/src/kernel/effects.test.ts +4 -2
  364. package/src/kernel/effects.ts +51 -9
  365. package/src/kernel/errors-channel.ts +17 -0
  366. package/src/kernel/errors-live-resume.ts +3 -2
  367. package/src/kernel/errors-tenant.ts +7 -4
  368. package/src/kernel/errors.registry-helpers.ts +96 -0
  369. package/src/kernel/errors.registry.test.ts +139 -25
  370. package/src/kernel/errors.ts +102 -23
  371. package/src/kernel/external-effects.test.ts +196 -0
  372. package/src/kernel/flow.test.ts +13 -4
  373. package/src/kernel/flow.ts +69 -71
  374. package/src/kernel/fx-ask-telemetry.test.ts +2 -2
  375. package/src/kernel/fx-dead-letters.test.ts +3 -3
  376. package/src/kernel/fx-fetch.ts +55 -0
  377. package/src/kernel/fx-live-stream.ts +2 -2
  378. package/src/kernel/fx-live.test.ts +8 -8
  379. package/src/kernel/fx.test.ts +17 -11
  380. package/src/kernel/fx.ts +180 -57
  381. package/src/kernel/horizontal-child.ts +1 -1
  382. package/src/kernel/http-query.test.ts +3 -6
  383. package/src/kernel/index.ts +13 -3
  384. package/src/kernel/instance-id.ts +1 -1
  385. package/src/kernel/instances.test.ts +40 -0
  386. package/src/kernel/instances.ts +47 -9
  387. package/src/kernel/live-http.test.ts +6 -7
  388. package/src/kernel/live-http.ts +6 -2
  389. package/src/kernel/live-resume.test.ts +1 -1
  390. package/src/kernel/mcp-tool.test.ts +3 -3
  391. package/src/kernel/on.ts +98 -4
  392. package/src/kernel/pipeline.test.ts +12 -15
  393. package/src/kernel/plugin-elements.test.ts +1 -1
  394. package/src/kernel/stamp-http.test.ts +3 -3
  395. package/src/kernel/triggers.ts +210 -95
  396. package/src/kernel-entry.ts +0 -1
  397. package/src/manifest/diff.ts +11 -1
  398. package/src/manifest/fixtures/skyport.excerpt.json +1 -1
  399. package/src/manifest/types.ts +46 -2
  400. package/src/mcp/docs-index.ts +3 -3
  401. package/src/mcp/docs-mcp.test.ts +2 -2
  402. package/src/mcp/docs-tools.ts +1 -1
  403. package/src/okid.test.ts +56 -0
  404. package/src/okid.ts +55 -11
  405. package/src/plugins/anonymous.ts +8 -4
  406. package/src/plugins/auth/shared.ts +27 -3
  407. package/src/plugins/auth-delivery.mailpit.integration.test.ts +1 -1
  408. package/src/plugins/auth-methods.security.test.ts +561 -23
  409. package/src/plugins/config-source.ts +1 -1
  410. package/src/plugins/csrf.test.ts +65 -0
  411. package/src/plugins/index.ts +2 -0
  412. package/src/plugins/magic-link.ts +36 -16
  413. package/src/plugins/oauth/shared.ts +3 -1
  414. package/src/plugins/oauth.ts +22 -14
  415. package/src/plugins/otp.ts +37 -21
  416. package/src/plugins/passkey-webauthn.ts +9 -6
  417. package/src/plugins/passkey.ts +98 -26
  418. package/src/plugins/pre-account-hijack.test.ts +223 -0
  419. package/src/plugins/two-factor.ts +466 -37
  420. package/src/plugins/username.ts +19 -7
  421. package/src/release/build-lib.ts +1 -0
  422. package/src/release/limits.ts +2 -2
  423. package/src/release/measure.ts +1 -1
  424. package/src/runs/collect.test.ts +0 -2
  425. package/src/runtime/json-code-block.test.ts +250 -20
  426. package/src/runtime/json-code-block.ts +1261 -41
  427. package/src/term.test.ts +1 -1
  428. package/src/test/create-test-app.test.ts +12 -12
  429. package/src/test/live-signals.test.ts +6 -6
  430. package/src/test/provisions.integration.test.ts +10 -14
  431. package/src/test/reset-element-registries.ts +1 -1
  432. package/src/test/tenant-isolation.test.ts +12 -6
  433. package/site/content/docs/deployment/docker-swarm.mdx +0 -164
  434. package/site/content/docs/deployment/docker.mdx +0 -227
  435. package/site/content/docs/deployment/index.mdx +0 -83
  436. package/site/content/docs/deployment/kubernetes.mdx +0 -176
  437. package/site/content/docs/deployment/meta.json +0 -5
  438. package/site/content/docs/deployment/reverse-proxy.mdx +0 -234
  439. package/site/content/docs/elements/ai.mdx +0 -385
  440. package/site/content/docs/elements/channel.mdx +0 -346
  441. package/site/content/docs/elements/clock.mdx +0 -244
  442. package/site/content/docs/elements/flow.mdx +0 -420
  443. package/site/content/docs/elements/gate.mdx +0 -436
  444. package/site/content/docs/elements/signal.mdx +0 -380
  445. package/site/content/docs/elements/store.mdx +0 -1099
  446. package/site/content/docs/elements/vault.mdx +0 -405
  447. package/site/content/docs/get-started/basic-usage.mdx +0 -173
  448. package/site/content/docs/get-started/index.mdx +0 -43
  449. package/site/content/docs/get-started/installation.mdx +0 -220
  450. package/site/content/docs/get-started/introduction.mdx +0 -132
  451. package/site/content/docs/get-started/meta.json +0 -13
  452. package/site/content/docs/get-started/project-structure.mdx +0 -925
  453. package/site/content/docs/get-started/testing.mdx +0 -328
  454. package/site/content/docs/get-started/why.mdx +0 -162
  455. package/site/content/docs/recipes/llama-cpp.mdx +0 -151
  456. package/site/content/docs/recipes/ollama.mdx +0 -142
  457. package/site/content/docs/recipes/sglang.mdx +0 -105
  458. package/site/content/docs/recipes/vllm.mdx +0 -106
  459. package/site/content/docs/reference/cli.md +0 -232
  460. package/site/content/docs/reference/client.mdx +0 -469
  461. package/site/content/docs/reference/security.md +0 -74
  462. package/src/cli/ai-setup/detect-ollama.ts +0 -213
  463. package/src/cli/ai-setup/recommend.test.ts +0 -225
  464. package/src/cli/ai-setup/recommend.ts +0 -225
  465. package/src/cli/dev-controls.test.ts +0 -122
  466. package/src/cli/dev-controls.ts +0 -164
  467. package/src/cli/tui/DevLive.tsx +0 -126
  468. package/src/console/ui-next/dist/assets/access-page-De7Lc2JC.js +0 -4
  469. package/src/console/ui-next/dist/assets/agent-disclosure-BP0Y0Sux.js +0 -1
  470. package/src/console/ui-next/dist/assets/cache-glyph-B5X-NM0-.js +0 -1
  471. package/src/console/ui-next/dist/assets/call-pii-button-ChAUiLo9.js +0 -1
  472. package/src/console/ui-next/dist/assets/collapsible-DGnOM2ph.js +0 -1
  473. package/src/console/ui-next/dist/assets/copy-inline-button-DBHhgHKP.js +0 -1
  474. package/src/console/ui-next/dist/assets/dagre.esm-ZwcdTuZZ.js +0 -1
  475. package/src/console/ui-next/dist/assets/detail-header-DhHM1iaZ.js +0 -1
  476. package/src/console/ui-next/dist/assets/dropdown-menu-_NjTEo5_.js +0 -1
  477. package/src/console/ui-next/dist/assets/duration-tone-sC3lGABz.js +0 -9
  478. package/src/console/ui-next/dist/assets/element-icons-BVXtRyd3.js +0 -1
  479. package/src/console/ui-next/dist/assets/explorer-empty-2uIhBu0_.js +0 -1
  480. package/src/console/ui-next/dist/assets/flows-page-RGy7VEA_.js +0 -1
  481. package/src/console/ui-next/dist/assets/highlighted-json-Awq7gYdu.js +0 -154
  482. package/src/console/ui-next/dist/assets/http-method-_UHM2ODJ.js +0 -1
  483. package/src/console/ui-next/dist/assets/index-Ck88Jmv8.css +0 -2
  484. package/src/console/ui-next/dist/assets/index-_rgpdVzo.js +0 -66
  485. package/src/console/ui-next/dist/assets/link-BX6Vqztd.js +0 -1
  486. package/src/console/ui-next/dist/assets/observability-page-Ds6pcnh-.js +0 -4
  487. package/src/console/ui-next/dist/assets/preload-helper-oH4irX4C.js +0 -1
  488. package/src/console/ui-next/dist/assets/react-D8E3mtu1.js +0 -1
  489. package/src/console/ui-next/dist/assets/react-dom-Bph1y7z7.js +0 -9
  490. package/src/console/ui-next/dist/assets/replica-lag-DKRrbvdo.js +0 -18
  491. package/src/console/ui-next/dist/assets/request-meta-DV0ywz7t.js +0 -1
  492. package/src/console/ui-next/dist/assets/shortcut-JQIZlWfm.js +0 -1
  493. package/src/console/ui-next/dist/assets/shortcut-keys-DKxNTe_m.js +0 -1
  494. package/src/console/ui-next/dist/assets/skeleton-D-czQJT6.js +0 -1
  495. package/src/console/ui-next/dist/assets/store-page-02xOiqIK.js +0 -41
  496. package/src/console/ui-next/dist/assets/trace-detail-sheet-B09O8rA6.js +0 -2
  497. package/src/console/ui-next/dist/assets/tree-expand-toggle-BtyhmWb4.js +0 -55
  498. package/src/console/ui-next/dist/assets/units-page-4rHOePuE.js +0 -1
  499. package/src/console/ui-next/dist/assets/useMutation-B8EO02Ej.js +0 -1
  500. package/src/console/ui-next/dist/assets/useRender-BE2A9BWC.js +0 -1
  501. package/src/console/ui-next/dist/assets/vault-page-DISPgxLM.js +0 -2
  502. package/src/console/ui-next/dist/assets/xyflow-D7n4g6go.js +0 -7
  503. package/src/console/ui-next/dist/assets/xyflow-DZ0Ws1xk.css +0 -1
  504. package/src/docker/ollama-pull.ts +0 -232
  505. package/src/docker/recipes/llama-cpp.ts +0 -298
  506. package/src/docker/recipes/ollama.ts +0 -44
  507. package/src/docker/recipes/sglang.ts +0 -55
  508. package/src/docker/recipes/vllm.ts +0 -44
  509. package/src/drivers/ai-ollama-tools.integration.test.ts +0 -109
  510. package/src/drivers/ai-ollama.integration.test.ts +0 -184
  511. package/src/drivers/ai-ollama.ts +0 -389
  512. package/src/drivers/ollama.ts +0 -14
@@ -1,623 +1,167 @@
1
1
  /**
2
- * Curated model catalog for `oke ai setup` / create-oke AI wizard.
3
- *
4
- * Tiers map to machine RAM classes (not download size). Manual lists show
5
- * up to 10 entries with modalities.
2
+ * Curated cloud model catalog for `oke ai setup` / create-oke AI wizard.
6
3
  */
7
4
 
8
- /** Role a model can fill in the wizard. */
9
- export type CatalogRole = "chat" | "vision" | "embed";
10
-
11
- /** Speed / quality tier for the Select model step. */
12
- export type ModelTier = "ultra-fast" | "fast" | "balanced" | "smart";
13
-
14
- /** Capability tags shown in manual model lists. */
15
- export type ModelModality = "text" | "vision" | "code" | "reasoning";
5
+ import { getAiProviderEntry } from "../../elements/ai/providers.ts";
16
6
 
17
- /** One curated local model entry (Ollama tag or Docker Hub `ai/` id). */
18
- export type CatalogModel = {
19
- readonly id: string;
7
+ /** Thin cloud / host-side provider menu. */
8
+ export type CloudProviderMenuEntry = {
9
+ readonly value: string;
20
10
  readonly label: string;
21
- readonly hint: string;
22
- readonly role: CatalogRole;
23
- readonly recommended?: boolean;
24
- /** Approximate RAM (GB) needed to run comfortably (machine tier). */
25
- readonly ramGb: number;
26
- readonly tier: ModelTier;
27
- readonly modalities: readonly ModelModality[];
11
+ readonly hint?: string;
12
+ readonly driver: "openai-compatible" | "anthropic";
13
+ /** Registry / declare provider name (defaults to `value`). */
14
+ readonly provider?: string;
15
+ readonly baseUrl?: string;
16
+ readonly apiKeyEnv?: string;
17
+ /** When true, wizard asks for base URL even if a default exists. */
18
+ readonly promptBaseUrl?: boolean;
28
19
  };
29
20
 
30
- /** Tier menu rows (prompt labels). */
31
- export const MODEL_TIERS: readonly {
32
- readonly value: ModelTier;
33
- readonly label: string;
34
- readonly hint: string;
35
- readonly minRamGb: number;
36
- readonly maxRamGb: number;
37
- }[] = [
38
- {
39
- value: "ultra-fast",
40
- label: "Ultra Fast",
41
- hint: "~1GB–~2GB RAM",
42
- minRamGb: 1,
43
- maxRamGb: 2,
44
- },
45
- {
46
- value: "fast",
47
- label: "Fast",
48
- hint: "~4GB–~8GB RAM",
49
- minRamGb: 4,
50
- maxRamGb: 8,
51
- },
52
- {
53
- value: "balanced",
54
- label: "Balanced",
55
- hint: "~8GB–~16GB RAM",
56
- minRamGb: 8,
57
- maxRamGb: 16,
58
- },
59
- {
60
- value: "smart",
61
- label: "Smart",
62
- hint: "~24GB–~32GB RAM",
63
- minRamGb: 24,
64
- maxRamGb: 32,
65
- },
66
- ];
67
-
68
- /** Chat / multimodal models (curated; manual pick shows ≤10 per tier). */
69
- export const CHAT_MODELS: readonly CatalogModel[] = [
70
- // Ultra Fast (~1–2GB)
71
- {
72
- id: "smollm2:135m",
73
- label: "SmolLM2 135M",
74
- hint: "Tiny · on-device",
75
- role: "chat",
76
- ramGb: 1,
77
- tier: "ultra-fast",
78
- modalities: ["text"],
79
- },
80
- {
81
- id: "qwen2.5:0.5b",
82
- label: "Qwen2.5 0.5B",
83
- hint: "Smallest Qwen",
84
- role: "chat",
85
- ramGb: 1,
86
- tier: "ultra-fast",
87
- modalities: ["text", "code"],
88
- },
89
- {
90
- id: "llama3.2:1b",
91
- label: "Llama 3.2 1B",
92
- hint: "Meta tiny",
93
- role: "chat",
94
- ramGb: 2,
95
- tier: "ultra-fast",
96
- modalities: ["text"],
97
- },
98
- {
99
- id: "gemma3:1b",
100
- label: "Gemma 3 1B",
101
- hint: "Google tiny",
102
- role: "chat",
103
- ramGb: 2,
104
- tier: "ultra-fast",
105
- modalities: ["text"],
106
- },
107
- {
108
- id: "qwen2.5:1.5b",
109
- label: "Qwen2.5 1.5B",
110
- hint: "Small coding",
111
- role: "chat",
112
- recommended: true,
113
- ramGb: 2,
114
- tier: "ultra-fast",
115
- modalities: ["text", "code"],
116
- },
117
- {
118
- id: "deepseek-r1:1.5b",
119
- label: "DeepSeek R1 1.5B",
120
- hint: "Tiny reasoning",
121
- role: "chat",
122
- ramGb: 2,
123
- tier: "ultra-fast",
124
- modalities: ["text", "reasoning"],
125
- },
126
- {
127
- id: "moondream",
128
- label: "Moondream",
129
- hint: "Tiny vision",
130
- role: "chat",
131
- ramGb: 2,
132
- tier: "ultra-fast",
133
- modalities: ["text", "vision"],
134
- },
135
- {
136
- id: "tinydolphin",
137
- label: "TinyDolphin",
138
- hint: "Ultra-compact chat",
139
- role: "chat",
140
- ramGb: 1,
141
- tier: "ultra-fast",
142
- modalities: ["text"],
143
- },
144
- {
145
- id: "phi3:mini",
146
- label: "Phi-3 Mini",
147
- hint: "Microsoft compact",
148
- role: "chat",
149
- ramGb: 2,
150
- tier: "ultra-fast",
151
- modalities: ["text", "code"],
152
- },
153
- {
154
- id: "stable-code:3b",
155
- label: "Stable Code 3B",
156
- hint: "Compact coder",
157
- role: "chat",
158
- ramGb: 2,
159
- tier: "ultra-fast",
160
- modalities: ["text", "code"],
161
- },
162
-
163
- // Fast (~4–8GB)
164
- {
165
- id: "llama3.2:3b",
166
- label: "Llama 3.2 3B",
167
- hint: "Small general",
168
- role: "chat",
169
- ramGb: 4,
170
- tier: "fast",
171
- modalities: ["text"],
172
- },
173
- {
174
- id: "phi4-mini",
175
- label: "Phi-4 Mini",
176
- hint: "Strong small",
177
- role: "chat",
178
- ramGb: 4,
179
- tier: "fast",
180
- modalities: ["text", "code"],
181
- },
182
- {
183
- id: "qwen2.5:3b",
184
- label: "Qwen2.5 3B",
185
- hint: "Coding · small",
186
- role: "chat",
187
- ramGb: 4,
188
- tier: "fast",
189
- modalities: ["text", "code"],
190
- },
191
- {
192
- id: "gemma4:e4b",
193
- label: "Gemma 4 4B",
194
- hint: "Fast default",
195
- role: "chat",
196
- recommended: true,
197
- ramGb: 8,
198
- tier: "fast",
199
- modalities: ["text"],
200
- },
201
- {
202
- id: "qwen2.5:7b",
203
- label: "Qwen2.5 7B",
204
- hint: "Coding workhorse",
205
- role: "chat",
206
- ramGb: 8,
207
- tier: "fast",
208
- modalities: ["text", "code"],
209
- },
210
- {
211
- id: "mistral:7b",
212
- label: "Mistral 7B",
213
- hint: "General purpose",
214
- role: "chat",
215
- ramGb: 8,
216
- tier: "fast",
217
- modalities: ["text"],
218
- },
219
- {
220
- id: "deepseek-r1:7b",
221
- label: "DeepSeek R1 7B",
222
- hint: "Reasoning",
223
- role: "chat",
224
- ramGb: 8,
225
- tier: "fast",
226
- modalities: ["text", "reasoning"],
227
- },
228
- {
229
- id: "llava:7b",
230
- label: "LLaVA 7B",
231
- hint: "Vision-language",
232
- role: "chat",
233
- ramGb: 8,
234
- tier: "fast",
235
- modalities: ["text", "vision"],
236
- },
237
- {
238
- id: "qwen3-vl:4b",
239
- label: "Qwen3-VL 4B",
240
- hint: "Vision-language",
241
- role: "chat",
242
- ramGb: 8,
243
- tier: "fast",
244
- modalities: ["text", "vision"],
245
- },
246
- {
247
- id: "granite3.3:8b",
248
- label: "Granite 3.3 8B",
249
- hint: "IBM enterprise",
250
- role: "chat",
251
- ramGb: 8,
252
- tier: "fast",
253
- modalities: ["text", "code"],
254
- },
255
-
256
- // Balanced (~8–16GB)
257
- {
258
- id: "deepseek-r1:8b",
259
- label: "DeepSeek R1 8B",
260
- hint: "Strong reasoning",
261
- role: "chat",
262
- ramGb: 10,
263
- tier: "balanced",
264
- modalities: ["text", "reasoning"],
265
- },
266
- {
267
- id: "llama3.1:8b",
268
- label: "Llama 3.1 8B",
269
- hint: "General purpose",
270
- role: "chat",
271
- ramGb: 10,
272
- tier: "balanced",
273
- modalities: ["text"],
274
- },
275
- {
276
- id: "qwen3.5:9b",
277
- label: "Qwen3.5 9B",
278
- hint: "Better coding",
279
- role: "chat",
280
- recommended: true,
281
- ramGb: 16,
282
- tier: "balanced",
283
- modalities: ["text", "code"],
284
- },
285
- {
286
- id: "llama4:scout",
287
- label: "Llama 4 Scout",
288
- hint: "General purpose",
289
- role: "chat",
290
- ramGb: 16,
291
- tier: "balanced",
292
- modalities: ["text"],
293
- },
294
- {
295
- id: "qwen2.5:14b",
296
- label: "Qwen2.5 14B",
297
- hint: "Larger Qwen",
298
- role: "chat",
299
- ramGb: 16,
300
- tier: "balanced",
301
- modalities: ["text", "code"],
302
- },
303
- {
304
- id: "qwen2.5-coder:14b",
305
- label: "Qwen2.5 Coder 14B",
306
- hint: "Coding specialist",
307
- role: "chat",
308
- ramGb: 16,
309
- tier: "balanced",
310
- modalities: ["text", "code"],
311
- },
312
- {
313
- id: "mistral-nemo",
314
- label: "Mistral Nemo",
315
- hint: "12B-class general",
316
- role: "chat",
317
- ramGb: 12,
318
- tier: "balanced",
319
- modalities: ["text"],
320
- },
321
- {
322
- id: "llava:13b",
323
- label: "LLaVA 13B",
324
- hint: "Vision-language",
325
- role: "chat",
326
- ramGb: 16,
327
- tier: "balanced",
328
- modalities: ["text", "vision"],
329
- },
330
- {
331
- id: "gemma2:9b",
332
- label: "Gemma 2 9B",
333
- hint: "Google mid",
334
- role: "chat",
335
- ramGb: 12,
336
- tier: "balanced",
337
- modalities: ["text"],
338
- },
339
- {
340
- id: "command-r",
341
- label: "Command R",
342
- hint: "Cohere RAG-friendly",
343
- role: "chat",
344
- ramGb: 16,
345
- tier: "balanced",
346
- modalities: ["text"],
347
- },
348
-
349
- // Smart (~24–32GB)
350
- {
351
- id: "gemma2:27b",
352
- label: "Gemma 2 27B",
353
- hint: "Large Gemma",
354
- role: "chat",
355
- ramGb: 24,
356
- tier: "smart",
357
- modalities: ["text"],
358
- },
359
- {
360
- id: "qwen3.5:27b",
361
- label: "Qwen3.5 27B",
362
- hint: "Best local quality",
363
- role: "chat",
364
- recommended: true,
365
- ramGb: 32,
366
- tier: "smart",
367
- modalities: ["text", "code"],
368
- },
21
+ /**
22
+ * Cloud / openai-compatible menu — URLs from the verified provider registry
23
+ * where known; Anthropic stays native.
24
+ */
25
+ export const CLOUD_PROVIDERS: readonly CloudProviderMenuEntry[] = [
369
26
  {
370
- id: "qwen2.5:32b",
371
- label: "Qwen2.5 32B",
372
- hint: "Large Qwen",
373
- role: "chat",
374
- ramGb: 32,
375
- tier: "smart",
376
- modalities: ["text", "code"],
27
+ value: "openrouter",
28
+ label: "OpenRouter",
29
+ hint: "recommended · zero Docker · openrouter/free",
30
+ driver: "openai-compatible",
31
+ baseUrl: getAiProviderEntry("openrouter")!.baseUrl,
32
+ apiKeyEnv: "OPENROUTER_API_KEY",
377
33
  },
378
34
  {
379
- id: "qwen2.5-coder:32b",
380
- label: "Qwen2.5 Coder 32B",
381
- hint: "Large coder",
382
- role: "chat",
383
- ramGb: 32,
384
- tier: "smart",
385
- modalities: ["text", "code"],
35
+ value: "openai",
36
+ label: "OpenAI",
37
+ driver: "openai-compatible",
38
+ baseUrl: getAiProviderEntry("openai")!.baseUrl,
39
+ apiKeyEnv: "OPENAI_API_KEY",
386
40
  },
387
41
  {
388
- id: "deepseek-r1:32b",
389
- label: "DeepSeek R1 32B",
390
- hint: "Large reasoning",
391
- role: "chat",
392
- ramGb: 32,
393
- tier: "smart",
394
- modalities: ["text", "reasoning"],
42
+ value: "anthropic",
43
+ label: "Anthropic",
44
+ hint: "native Messages API",
45
+ driver: "anthropic",
46
+ provider: "anthropic",
47
+ baseUrl: undefined,
48
+ apiKeyEnv: "ANTHROPIC_API_KEY",
395
49
  },
396
50
  {
397
- id: "mixtral:8x7b",
398
- label: "Mixtral 8x7B",
399
- hint: "MoE general",
400
- role: "chat",
401
- ramGb: 26,
402
- tier: "smart",
403
- modalities: ["text"],
51
+ value: "groq",
52
+ label: "Groq",
53
+ driver: "openai-compatible",
54
+ baseUrl: getAiProviderEntry("groq")!.baseUrl,
55
+ apiKeyEnv: "GROQ_API_KEY",
404
56
  },
405
57
  {
406
- id: "command-r-plus",
407
- label: "Command R+",
408
- hint: "Cohere large",
409
- role: "chat",
410
- ramGb: 32,
411
- tier: "smart",
412
- modalities: ["text"],
58
+ value: "together",
59
+ label: "Together AI",
60
+ driver: "openai-compatible",
61
+ baseUrl: getAiProviderEntry("together")!.baseUrl,
62
+ apiKeyEnv: "TOGETHER_API_KEY",
413
63
  },
414
64
  {
415
- id: "mistral-small:24b",
416
- label: "Mistral Small 24B",
417
- hint: "Mistral mid-large",
418
- role: "chat",
419
- ramGb: 24,
420
- tier: "smart",
421
- modalities: ["text"],
65
+ value: "deepseek",
66
+ label: "DeepSeek",
67
+ driver: "openai-compatible",
68
+ baseUrl: getAiProviderEntry("deepseek")!.baseUrl,
69
+ apiKeyEnv: "DEEPSEEK_API_KEY",
422
70
  },
423
71
  {
424
- id: "llama3.1:70b",
425
- label: "Llama 3.1 70B",
426
- hint: "Needs ~40GB+; listed for reference",
427
- role: "chat",
428
- ramGb: 40,
429
- tier: "smart",
430
- modalities: ["text"],
72
+ value: "mistral",
73
+ label: "Mistral",
74
+ driver: "openai-compatible",
75
+ baseUrl: getAiProviderEntry("mistral")!.baseUrl,
76
+ apiKeyEnv: "MISTRAL_API_KEY",
431
77
  },
432
78
  {
433
- id: "qwen2.5:72b",
434
- label: "Qwen2.5 72B",
435
- hint: "Needs ~48GB+; listed for reference",
436
- role: "chat",
437
- ramGb: 48,
438
- tier: "smart",
439
- modalities: ["text", "code"],
79
+ value: "xai",
80
+ label: "xAI (Grok)",
81
+ driver: "openai-compatible",
82
+ baseUrl: getAiProviderEntry("xai")!.baseUrl,
83
+ apiKeyEnv: "XAI_API_KEY",
440
84
  },
441
- ];
442
-
443
- /** Vision-only short list (legacy / optional). */
444
- export const VISION_MODELS: readonly CatalogModel[] = [
445
85
  {
446
- id: "qwen3-vl:4b",
447
- label: "Qwen3-VL 4B",
448
- hint: "Vision-language",
449
- role: "vision",
450
- recommended: true,
451
- ramGb: 8,
452
- tier: "fast",
453
- modalities: ["text", "vision"],
86
+ value: "deepinfra",
87
+ label: "DeepInfra",
88
+ driver: "openai-compatible",
89
+ baseUrl: getAiProviderEntry("deepinfra")!.baseUrl,
90
+ apiKeyEnv: "DEEPINFRA_API_KEY",
454
91
  },
455
92
  {
456
- id: "llava:7b",
457
- label: "LLaVA 7B",
458
- hint: "Vision-language",
459
- role: "vision",
460
- ramGb: 8,
461
- tier: "fast",
462
- modalities: ["text", "vision"],
93
+ value: "vercel",
94
+ label: "Vercel AI Gateway",
95
+ driver: "openai-compatible",
96
+ baseUrl: getAiProviderEntry("vercel")!.baseUrl,
97
+ apiKeyEnv: "AI_GATEWAY_API_KEY",
463
98
  },
464
- ];
465
-
466
- /** Embedding models (applied automatically — no download prompt). */
467
- export const EMBED_MODELS: readonly CatalogModel[] = [
468
99
  {
469
- id: "nomic-embed-text",
470
- label: "nomic-embed-text",
471
- hint: "Default local RAG embedder",
472
- role: "embed",
473
- recommended: true,
474
- ramGb: 1,
475
- tier: "ultra-fast",
476
- modalities: ["text"],
100
+ value: "gemini",
101
+ label: "Google Gemini",
102
+ hint: "Limited OpenAI-compat tool schemas constrained",
103
+ driver: "openai-compatible",
104
+ provider: "gemini",
105
+ baseUrl: getAiProviderEntry("gemini")!.baseUrl,
106
+ apiKeyEnv: "GEMINI_API_KEY",
477
107
  },
478
108
  {
479
- id: "bge-m3",
480
- label: "bge-m3",
481
- hint: "Multilingual + long docs",
482
- role: "embed",
483
- ramGb: 2,
484
- tier: "ultra-fast",
485
- modalities: ["text"],
109
+ value: "lmstudio",
110
+ label: "LM Studio",
111
+ driver: "openai-compatible",
112
+ provider: "openai-compatible",
113
+ baseUrl: "http://127.0.0.1:1234/v1",
114
+ apiKeyEnv: undefined,
486
115
  },
487
116
  {
488
- id: "jina-embeddings-v4",
489
- label: "jina-embeddings-v4",
490
- hint: "High-quality embedder",
491
- role: "embed",
492
- ramGb: 2,
493
- tier: "ultra-fast",
494
- modalities: ["text"],
117
+ value: "custom",
118
+ label: "Custom OpenAI Compatible",
119
+ hint: "requires base URL",
120
+ driver: "openai-compatible",
121
+ provider: "openai-compatible",
122
+ baseUrl: undefined,
123
+ apiKeyEnv: "OPENAI_API_KEY",
124
+ promptBaseUrl: true,
495
125
  },
496
126
  ];
497
127
 
498
- /** All curated ids (for detect / not-installed). */
499
- export const ALL_CURATED: readonly CatalogModel[] = [
500
- ...CHAT_MODELS,
501
- ...VISION_MODELS.filter((m) => !CHAT_MODELS.some((c) => c.id === m.id)),
502
- ...EMBED_MODELS,
503
- ];
504
-
505
- /**
506
- * Sort catalog rows by RAM ascending, then label (stable pick lists).
507
- *
508
- * @param models - Catalog entries
509
- */
510
- function byRamThenLabel(models: readonly CatalogModel[]): CatalogModel[] {
511
- return [...models].sort((a, b) => a.ramGb - b.ramGb || a.label.localeCompare(b.label));
512
- }
513
-
514
- /**
515
- * Chat models in a tier (≤10 for manual pick), ordered by RAM.
516
- *
517
- * @param tier - Speed / quality tier
518
- */
519
- export function modelsForTier(tier: ModelTier): readonly CatalogModel[] {
520
- return byRamThenLabel(CHAT_MODELS.filter((m) => m.tier === tier)).slice(0, 10);
521
- }
522
-
523
- /**
524
- * Recommended chat model for a tier (falls back to first in tier).
525
- *
526
- * @param tier - Selected tier
527
- * @param totalRamGb - Prefer models that fit when RAM is known
528
- */
529
- export function recommendForTier(tier: ModelTier, totalRamGb: number | null = null): CatalogModel {
530
- const list = modelsForTier(tier);
531
- const headroom = 4;
532
- const fits =
533
- totalRamGb !== null && Number.isFinite(totalRamGb)
534
- ? list.filter((m) => m.ramGb + headroom <= totalRamGb || m.ramGb <= totalRamGb)
535
- : list;
536
- const pool = fits.length > 0 ? fits : list;
537
- return pool.find((m) => m.recommended) ?? pool[pool.length - 1] ?? list[0]!;
538
- }
128
+ /** One row in the AI Provider select. */
129
+ export type AiProviderSelectOption = {
130
+ readonly value: string;
131
+ readonly label: string;
132
+ readonly hint?: string;
133
+ };
539
134
 
540
135
  /**
541
- * Recommend a chat model for the host RAM (comfortable headroom).
136
+ * AI Provider menu OpenRouter first (recommended), then other cloud,
137
+ * then optional mock.
542
138
  *
543
- * @param totalRamGb - Detected total system RAM in GB (or null)
139
+ * @param options - Include Mock (create-oke Customize)
544
140
  */
545
- export function recommendChatModel(totalRamGb: number | null): CatalogModel {
546
- const HEADROOM = 4;
547
- const sorted = [...CHAT_MODELS].sort((a, b) => a.ramGb - b.ramGb);
548
- const smallest = sorted[0]!;
549
- if (totalRamGb === null || !Number.isFinite(totalRamGb)) {
550
- return CHAT_MODELS.find((m) => m.recommended && m.tier === "fast") ?? smallest;
551
- }
552
- const comfortable = sorted.filter(
553
- (m) => (m.id === smallest.id && m.ramGb <= totalRamGb) || m.ramGb + HEADROOM <= totalRamGb,
554
- );
555
- if (comfortable.length > 0) return comfortable[comfortable.length - 1]!;
556
- const tierOk = sorted.filter((m) => m.ramGb <= totalRamGb);
557
- return tierOk.length > 0 ? tierOk[tierOk.length - 1]! : smallest;
141
+ export function aiProviderSelectOptions(
142
+ options: { readonly includeMock?: boolean } = {},
143
+ ): readonly AiProviderSelectOption[] {
144
+ const cloud = CLOUD_PROVIDERS.map((p) => ({
145
+ value: p.value,
146
+ label: p.label,
147
+ ...(p.hint !== undefined ? { hint: p.hint } : {}),
148
+ }));
149
+ const mock: readonly AiProviderSelectOption[] = options.includeMock
150
+ ? [{ value: "mock", label: "Mock (dev only)", hint: "no network" }]
151
+ : [];
152
+ return [...cloud, ...mock];
558
153
  }
559
154
 
560
155
  /**
561
- * Recommend vision / embed defaults.
156
+ * Protocol driver for an AI Provider menu id.
562
157
  *
563
- * @param role - vision or embed
158
+ * @param provider - Menu value
564
159
  */
565
- export function recommendForRole(role: "vision" | "embed"): CatalogModel {
566
- const list = role === "vision" ? VISION_MODELS : EMBED_MODELS;
567
- return list.find((m) => m.recommended) ?? list[0]!;
160
+ export function aiDriverForMenuProvider(provider: string): string {
161
+ if (provider === "mock") return "mock";
162
+ return CLOUD_PROVIDERS.find((p) => p.value === provider)?.driver ?? "openai-compatible";
568
163
  }
569
164
 
570
- /** Format modalities for a list row. */
571
- export function formatModalities(modalities: readonly ModelModality[]): string {
572
- return modalities.join(" · ");
573
- }
574
-
575
- /** Thin cloud provider menu (non-Ollama). */
576
- export const CLOUD_PROVIDERS = [
577
- {
578
- value: "openai",
579
- label: "OpenAI",
580
- driver: "openai-compatible" as const,
581
- baseUrl: "https://api.openai.com/v1",
582
- apiKeyEnv: "OPENAI_API_KEY",
583
- },
584
- {
585
- value: "anthropic",
586
- label: "Anthropic",
587
- driver: "anthropic" as const,
588
- baseUrl: undefined,
589
- apiKeyEnv: "ANTHROPIC_API_KEY",
590
- },
591
- {
592
- value: "gemini",
593
- label: "Gemini",
594
- driver: "openai-compatible" as const,
595
- baseUrl: undefined,
596
- apiKeyEnv: "OPENAI_API_KEY",
597
- },
598
- {
599
- value: "lmstudio",
600
- label: "LM Studio",
601
- driver: "openai-compatible" as const,
602
- baseUrl: "http://127.0.0.1:1234/v1",
603
- apiKeyEnv: undefined,
604
- },
605
- {
606
- value: "openrouter",
607
- label: "OpenRouter",
608
- driver: "openai-compatible" as const,
609
- baseUrl: "https://openrouter.ai/api/v1",
610
- apiKeyEnv: "OPENAI_API_KEY",
611
- },
612
- {
613
- value: "custom",
614
- label: "Custom OpenAI Compatible",
615
- driver: "openai-compatible" as const,
616
- baseUrl: undefined,
617
- apiKeyEnv: "OPENAI_API_KEY",
618
- },
619
- ] as const;
620
-
621
165
  /** Cloud chat model entry (no RAM tier). */
622
166
  export type CloudModel = {
623
167
  readonly id: string;
@@ -716,21 +260,91 @@ export const CLOUD_CHAT_MODELS: Readonly<Record<string, readonly CloudModel[]>>
716
260
  ],
717
261
  openrouter: [
718
262
  {
719
- id: "openai/gpt-4o-mini",
720
- label: "GPT-4o mini",
721
- hint: "via OpenRouter",
263
+ id: "openrouter/free",
264
+ label: "openrouter/free",
265
+ hint: "Free router · zero cost",
722
266
  recommended: true,
723
267
  },
268
+ { id: "openrouter/auto", label: "openrouter/auto", hint: "Market pick by task + cost" },
269
+ {
270
+ id: "openrouter/pareto-code",
271
+ label: "openrouter/pareto-code",
272
+ hint: "Strong coding router",
273
+ },
274
+ {
275
+ id: "openrouter/fusion",
276
+ label: "openrouter/fusion",
277
+ hint: "Multi-model panel",
278
+ },
279
+ { id: "openai/gpt-4o-mini", label: "GPT-4o mini", hint: "via OpenRouter" },
724
280
  { id: "openai/gpt-4.1", label: "GPT-4.1", hint: "via OpenRouter" },
725
- { id: "openai/o4-mini", label: "o4-mini", hint: "via OpenRouter" },
726
281
  { id: "anthropic/claude-sonnet-4", label: "Claude Sonnet 4", hint: "via OpenRouter" },
727
- { id: "anthropic/claude-opus-4", label: "Claude Opus 4", hint: "via OpenRouter" },
728
- { id: "anthropic/claude-haiku-4", label: "Claude Haiku 4", hint: "via OpenRouter" },
729
282
  { id: "google/gemini-2.5-flash", label: "Gemini 2.5 Flash", hint: "via OpenRouter" },
730
- { id: "google/gemini-2.5-pro", label: "Gemini 2.5 Pro", hint: "via OpenRouter" },
731
283
  { id: "meta-llama/llama-4-scout", label: "Llama 4 Scout", hint: "via OpenRouter" },
732
284
  { id: "deepseek/deepseek-r1", label: "DeepSeek R1", hint: "via OpenRouter" },
733
285
  ],
286
+ groq: [
287
+ {
288
+ id: "llama-3.1-8b-instant",
289
+ label: "Llama 3.1 8B Instant",
290
+ hint: "Fast default",
291
+ recommended: true,
292
+ },
293
+ { id: "llama-3.3-70b-versatile", label: "Llama 3.3 70B", hint: "Higher quality" },
294
+ { id: "mixtral-8x7b-32768", label: "Mixtral 8x7B", hint: "Long context" },
295
+ ],
296
+ together: [
297
+ {
298
+ id: "meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo",
299
+ label: "Llama 3.1 8B Turbo",
300
+ hint: "Fast",
301
+ recommended: true,
302
+ },
303
+ {
304
+ id: "meta-llama/Meta-Llama-3.1-70B-Instruct-Turbo",
305
+ label: "Llama 3.1 70B Turbo",
306
+ hint: "Higher quality",
307
+ },
308
+ ],
309
+ deepseek: [
310
+ {
311
+ id: "deepseek-v4-flash",
312
+ label: "DeepSeek V4 Flash",
313
+ hint: "Fast default",
314
+ recommended: true,
315
+ },
316
+ { id: "deepseek-v4-pro", label: "DeepSeek V4 Pro", hint: "Higher quality" },
317
+ ],
318
+ mistral: [
319
+ {
320
+ id: "mistral-small-latest",
321
+ label: "Mistral Small",
322
+ hint: "Fast default",
323
+ recommended: true,
324
+ },
325
+ { id: "mistral-large-latest", label: "Mistral Large", hint: "Higher quality" },
326
+ ],
327
+ xai: [
328
+ { id: "grok-4.6", label: "Grok 4.6", hint: "Current default", recommended: true },
329
+ { id: "grok-3-mini", label: "Grok 3 Mini", hint: "Faster / cheaper" },
330
+ ],
331
+ deepinfra: [
332
+ {
333
+ id: "meta-llama/Meta-Llama-3.1-8B-Instruct",
334
+ label: "Llama 3.1 8B",
335
+ hint: "Fast",
336
+ recommended: true,
337
+ },
338
+ ],
339
+ vercel: [
340
+ {
341
+ id: "openai/gpt-4o-mini",
342
+ label: "GPT-4o mini",
343
+ hint: "via AI Gateway",
344
+ recommended: true,
345
+ },
346
+ { id: "anthropic/claude-sonnet-4", label: "Claude Sonnet 4", hint: "via AI Gateway" },
347
+ ],
734
348
  lmstudio: [
735
349
  {
736
350
  id: "local-model",
@@ -778,767 +392,49 @@ export function recommendCloudChat(provider: string): string {
778
392
  }
779
393
 
780
394
  /**
781
- * Curated Docker Hub `ai/` chat models for llama.cpp (`LLAMA_ARG_DOCKER_REPO`).
782
- * Ids omit the `ai/` org prefix (llama.cpp default). ≥10 per tier; manual pick
783
- * shows up to 20. HF-origin weights are only listed when published under
784
- * Docker Hub [`ai/`](https://hub.docker.com/u/ai) (recipe cannot load raw HF ids).
785
- */
786
- export const LLAMA_CPP_CHAT_MODELS: readonly CatalogModel[] = [
787
- // Ultra Fast (~1–2GB)
788
- {
789
- id: "smollm2",
790
- label: "SmolLM2",
791
- hint: "Lightest",
792
- role: "chat",
793
- ramGb: 1,
794
- tier: "ultra-fast",
795
- modalities: ["text"],
796
- },
797
- {
798
- id: "smollm2:135M-Q4_K_M",
799
- label: "SmolLM2 135M",
800
- hint: "Tiny smoke test",
801
- role: "chat",
802
- ramGb: 1,
803
- tier: "ultra-fast",
804
- modalities: ["text"],
805
- },
806
- {
807
- id: "functiongemma",
808
- label: "FunctionGemma 270M",
809
- hint: "Tool calling",
810
- role: "chat",
811
- ramGb: 1,
812
- tier: "ultra-fast",
813
- modalities: ["text", "code"],
814
- },
815
- {
816
- id: "gemma3:270m",
817
- label: "Gemma 3 270M",
818
- hint: "Google tiny",
819
- role: "chat",
820
- ramGb: 1,
821
- tier: "ultra-fast",
822
- modalities: ["text"],
823
- },
824
- {
825
- id: "granite-4.0-h-nano:350M-Q8_0",
826
- label: "Granite 4.0 H Nano 350M",
827
- hint: "IBM tiny",
828
- role: "chat",
829
- ramGb: 1,
830
- tier: "ultra-fast",
831
- modalities: ["text"],
832
- },
833
- {
834
- id: "qwen3:0.6B-Q4_K_M",
835
- label: "Qwen3 0.6B",
836
- hint: "Small coding",
837
- role: "chat",
838
- ramGb: 2,
839
- tier: "ultra-fast",
840
- modalities: ["text", "code"],
841
- },
842
- {
843
- id: "smolvlm:500M-Q8_0",
844
- label: "SmolVLM 500M",
845
- hint: "Tiny vision",
846
- role: "chat",
847
- ramGb: 2,
848
- tier: "ultra-fast",
849
- modalities: ["text", "vision"],
850
- },
851
- {
852
- id: "llama3.2:1B-Q4_0",
853
- label: "Llama 3.2 1B",
854
- hint: "Meta tiny",
855
- role: "chat",
856
- ramGb: 2,
857
- tier: "ultra-fast",
858
- modalities: ["text"],
859
- },
860
- {
861
- id: "granite-4.0-h-nano",
862
- label: "Granite 4.0 H Nano 1B",
863
- hint: "IBM nano",
864
- role: "chat",
865
- ramGb: 2,
866
- tier: "ultra-fast",
867
- modalities: ["text"],
868
- },
869
- {
870
- id: "qwen2.5:0.5B-F16",
871
- label: "Qwen2.5 0.5B",
872
- hint: "Small coding",
873
- role: "chat",
874
- ramGb: 2,
875
- tier: "ultra-fast",
876
- modalities: ["text", "code"],
877
- },
878
- {
879
- id: "smollm2:360M-Q4_K_M",
880
- label: "SmolLM2 360M",
881
- hint: "Small instruct",
882
- role: "chat",
883
- ramGb: 1,
884
- tier: "ultra-fast",
885
- modalities: ["text"],
886
- },
887
- {
888
- id: "smollm2:135M-Q4_0",
889
- label: "SmolLM2 135M Q4_0",
890
- hint: "Tiny Q4_0",
891
- role: "chat",
892
- ramGb: 1,
893
- tier: "ultra-fast",
894
- modalities: ["text"],
895
- },
896
- {
897
- id: "gemma3:270m-q4_K_M",
898
- label: "Gemma 3 270M Q4",
899
- hint: "Google tiny Q4",
900
- role: "chat",
901
- ramGb: 1,
902
- tier: "ultra-fast",
903
- modalities: ["text"],
904
- },
905
- {
906
- id: "functiongemma:q4_K_M",
907
- label: "FunctionGemma Q4",
908
- hint: "Tool calling Q4",
909
- role: "chat",
910
- ramGb: 1,
911
- tier: "ultra-fast",
912
- modalities: ["text", "code"],
913
- },
914
- {
915
- id: "qwen3:0.6B-Q4_0",
916
- label: "Qwen3 0.6B Q4_0",
917
- hint: "Small coding",
918
- role: "chat",
919
- ramGb: 2,
920
- tier: "ultra-fast",
921
- modalities: ["text", "code"],
922
- },
923
- {
924
- id: "llama3.2:1B-Q8_0",
925
- label: "Llama 3.2 1B Q8",
926
- hint: "Meta tiny Q8",
927
- role: "chat",
928
- ramGb: 2,
929
- tier: "ultra-fast",
930
- modalities: ["text"],
931
- },
932
- {
933
- id: "granite-4.0-nano:350M-BF16",
934
- label: "Granite 4.0 Nano 350M",
935
- hint: "IBM nano",
936
- role: "chat",
937
- ramGb: 2,
938
- tier: "ultra-fast",
939
- modalities: ["text"],
940
- },
941
- {
942
- id: "smolvlm",
943
- label: "SmolVLM",
944
- hint: "Tiny vision default",
945
- role: "chat",
946
- ramGb: 2,
947
- tier: "ultra-fast",
948
- modalities: ["text", "vision"],
949
- },
950
- {
951
- id: "granite3.3:2b",
952
- label: "Granite 3.3 2B",
953
- hint: "Default · IBM 2B",
954
- role: "chat",
955
- recommended: true,
956
- ramGb: 2,
957
- tier: "ultra-fast",
958
- modalities: ["text", "code"],
959
- },
960
- {
961
- id: "gemma3:270m-q8_0",
962
- label: "Gemma 3 270M Q8",
963
- hint: "Google tiny Q8",
964
- role: "chat",
965
- ramGb: 1,
966
- tier: "ultra-fast",
967
- modalities: ["text"],
968
- },
969
- // Fast (~4–8GB) — Gemma 4 · Qwen near the top
970
- {
971
- id: "llama3.2",
972
- label: "Llama 3.2 3B",
973
- hint: "Balanced local chat",
974
- role: "chat",
975
- recommended: true,
976
- ramGb: 4,
977
- tier: "fast",
978
- modalities: ["text"],
979
- },
980
- {
981
- id: "gemma4:e2b-q4_K_M",
982
- label: "Gemma 4 E2B",
983
- hint: "Popular · multimodal",
984
- role: "chat",
985
- ramGb: 8,
986
- tier: "fast",
987
- modalities: ["text", "vision"],
988
- },
989
- {
990
- id: "qwen3:4B-UD-Q4_K_XL",
991
- label: "Qwen3 4B",
992
- hint: "Popular · coding · agents",
993
- role: "chat",
994
- ramGb: 6,
995
- tier: "fast",
996
- modalities: ["text", "code"],
997
- },
998
- {
999
- id: "qwen2.5:3B-Q4_K_M",
1000
- label: "Qwen2.5 3B",
1001
- hint: "Coding",
1002
- role: "chat",
1003
- ramGb: 4,
1004
- tier: "fast",
1005
- modalities: ["text", "code"],
1006
- },
1007
- {
1008
- id: "gemma3:4b",
1009
- label: "Gemma 3 4B",
1010
- hint: "Reasoning",
1011
- role: "chat",
1012
- ramGb: 8,
1013
- tier: "fast",
1014
- modalities: ["text", "reasoning"],
1015
- },
1016
- {
1017
- id: "gemma3n:e2b",
1018
- label: "Gemma 3n E2B",
1019
- hint: "On-device multimodal",
1020
- role: "chat",
1021
- ramGb: 8,
1022
- tier: "fast",
1023
- modalities: ["text", "vision"],
1024
- },
1025
- {
1026
- id: "qwen3-vl:2B-UD-Q4_K_XL",
1027
- label: "Qwen3-VL 2B",
1028
- hint: "Vision",
1029
- role: "chat",
1030
- ramGb: 6,
1031
- tier: "fast",
1032
- modalities: ["text", "vision"],
1033
- },
1034
- {
1035
- id: "smollm3",
1036
- label: "SmolLM3",
1037
- hint: "On-device chat",
1038
- role: "chat",
1039
- ramGb: 4,
1040
- tier: "fast",
1041
- modalities: ["text"],
1042
- },
1043
- {
1044
- id: "ministral3:3B-Q4_K_M",
1045
- label: "Ministral 3B",
1046
- hint: "Mistral small",
1047
- role: "chat",
1048
- ramGb: 4,
1049
- tier: "fast",
1050
- modalities: ["text", "code"],
1051
- },
1052
- {
1053
- id: "nemotron-3-nano:4b",
1054
- label: "Nemotron 3 Nano 4B",
1055
- hint: "NVIDIA nano",
1056
- role: "chat",
1057
- ramGb: 6,
1058
- tier: "fast",
1059
- modalities: ["text", "code"],
1060
- },
1061
- {
1062
- id: "granite-4.0-micro",
1063
- label: "Granite 4.0 Micro 3B",
1064
- hint: "IBM micro",
1065
- role: "chat",
1066
- ramGb: 4,
1067
- tier: "fast",
1068
- modalities: ["text", "code"],
1069
- },
1070
- {
1071
- id: "granite4:micro",
1072
- label: "Granite 4 Micro",
1073
- hint: "IBM micro Q4",
1074
- role: "chat",
1075
- ramGb: 4,
1076
- tier: "fast",
1077
- modalities: ["text"],
1078
- },
1079
- {
1080
- id: "moondream2",
1081
- label: "Moondream2 1.5B",
1082
- hint: "Vision",
1083
- role: "chat",
1084
- ramGb: 6,
1085
- tier: "fast",
1086
- modalities: ["text", "vision"],
1087
- },
1088
- {
1089
- id: "medgemma:4b",
1090
- label: "MedGemma 4B",
1091
- hint: "Medical",
1092
- role: "chat",
1093
- ramGb: 8,
1094
- tier: "fast",
1095
- modalities: ["text", "vision"],
1096
- },
1097
- {
1098
- id: "granite4.1:3b",
1099
- label: "Granite 4.1 3B",
1100
- hint: "IBM 3B",
1101
- role: "chat",
1102
- ramGb: 4,
1103
- tier: "fast",
1104
- modalities: ["text", "code"],
1105
- },
1106
- {
1107
- id: "llama3.2:3B-Q4_K_M",
1108
- label: "Llama 3.2 3B Q4",
1109
- hint: "Meta 3B Q4",
1110
- role: "chat",
1111
- ramGb: 4,
1112
- tier: "fast",
1113
- modalities: ["text"],
1114
- },
1115
- {
1116
- id: "gemma4:e2b",
1117
- label: "Gemma 4 E2B default",
1118
- hint: "Popular · multimodal",
1119
- role: "chat",
1120
- ramGb: 8,
1121
- tier: "fast",
1122
- modalities: ["text", "vision"],
1123
- },
1124
- {
1125
- id: "gemma3:4b-q4_K_M",
1126
- label: "Gemma 3 4B Q4",
1127
- hint: "Reasoning Q4",
1128
- role: "chat",
1129
- ramGb: 8,
1130
- tier: "fast",
1131
- modalities: ["text", "reasoning"],
1132
- },
1133
- {
1134
- id: "smollm3:Q4_K_M",
1135
- label: "SmolLM3 Q4",
1136
- hint: "On-device Q4",
1137
- role: "chat",
1138
- ramGb: 4,
1139
- tier: "fast",
1140
- modalities: ["text"],
1141
- },
1142
- {
1143
- id: "granite3.3:2b-q4_K_M",
1144
- label: "Granite 3.3 2B Q4",
1145
- hint: "IBM 2B Q4",
1146
- role: "chat",
1147
- ramGb: 4,
1148
- tier: "fast",
1149
- modalities: ["text", "code"],
1150
- },
1151
- // Balanced (~8–16GB) — Gemma 4 E4B · Qwen near the top
1152
- {
1153
- id: "qwen3:8B-Q4_K_M",
1154
- label: "Qwen3 8B",
1155
- hint: "Popular · coding · agents",
1156
- role: "chat",
1157
- recommended: true,
1158
- ramGb: 12,
1159
- tier: "balanced",
1160
- modalities: ["text", "code"],
1161
- },
1162
- {
1163
- id: "gemma4:e4b",
1164
- label: "Gemma 4 E4B",
1165
- hint: "Popular · multimodal",
1166
- role: "chat",
1167
- ramGb: 16,
1168
- tier: "balanced",
1169
- modalities: ["text", "vision", "reasoning"],
1170
- },
1171
- {
1172
- id: "qwen2.5:7B-Q4_K_M",
1173
- label: "Qwen2.5 7B",
1174
- hint: "Coding",
1175
- role: "chat",
1176
- ramGb: 12,
1177
- tier: "balanced",
1178
- modalities: ["text", "code"],
1179
- },
1180
- {
1181
- id: "qwen3-vl:8B",
1182
- label: "Qwen3-VL 8B",
1183
- hint: "Vision",
1184
- role: "chat",
1185
- ramGb: 16,
1186
- tier: "balanced",
1187
- modalities: ["text", "vision", "code"],
1188
- },
1189
- {
1190
- id: "llama3.1:8B-Q4_K_M",
1191
- label: "Llama 3.1 8B",
1192
- hint: "Meta general",
1193
- role: "chat",
1194
- ramGb: 12,
1195
- tier: "balanced",
1196
- modalities: ["text"],
1197
- },
1198
- {
1199
- id: "gemma3n:e4b",
1200
- label: "Gemma 3n E4B",
1201
- hint: "On-device multimodal",
1202
- role: "chat",
1203
- ramGb: 16,
1204
- tier: "balanced",
1205
- modalities: ["text", "vision"],
1206
- },
1207
- {
1208
- id: "mistral",
1209
- label: "Mistral 7B",
1210
- hint: "General + code",
1211
- role: "chat",
1212
- ramGb: 12,
1213
- tier: "balanced",
1214
- modalities: ["text", "code"],
1215
- },
1216
- {
1217
- id: "deepseek-r1-distill-llama:8B-Q4_K_M",
1218
- label: "DeepSeek R1 8B",
1219
- hint: "Reasoning distill",
1220
- role: "chat",
1221
- ramGb: 12,
1222
- tier: "balanced",
1223
- modalities: ["text", "reasoning"],
1224
- },
1225
- {
1226
- id: "mistral-nemo",
1227
- label: "Mistral Nemo 12B",
1228
- hint: "General",
1229
- role: "chat",
1230
- ramGb: 16,
1231
- tier: "balanced",
1232
- modalities: ["text", "code"],
1233
- },
1234
- {
1235
- id: "ministral3:8B-Q4_K_M",
1236
- label: "Ministral 8B",
1237
- hint: "Mistral instruct",
1238
- role: "chat",
1239
- ramGb: 12,
1240
- tier: "balanced",
1241
- modalities: ["text", "code"],
1242
- },
1243
- {
1244
- id: "granite-4.0-h-tiny",
1245
- label: "Granite 4.0 H Tiny 7B",
1246
- hint: "IBM tiny",
1247
- role: "chat",
1248
- ramGb: 12,
1249
- tier: "balanced",
1250
- modalities: ["text", "code"],
1251
- },
1252
- {
1253
- id: "ministral-3:8b-instruct",
1254
- label: "Ministral 3 8B Instruct",
1255
- hint: "Instruct",
1256
- role: "chat",
1257
- ramGb: 12,
1258
- tier: "balanced",
1259
- modalities: ["text", "code"],
1260
- },
1261
- {
1262
- id: "granite3.3:8b",
1263
- label: "Granite 3.3 8B",
1264
- hint: "IBM 8B",
1265
- role: "chat",
1266
- ramGb: 12,
1267
- tier: "balanced",
1268
- modalities: ["text", "code"],
1269
- },
1270
- {
1271
- id: "granite4.1:8b",
1272
- label: "Granite 4.1 8B",
1273
- hint: "IBM 8B",
1274
- role: "chat",
1275
- ramGb: 12,
1276
- tier: "balanced",
1277
- modalities: ["text", "code"],
1278
- },
1279
- {
1280
- id: "qwen3:8B-Q4_0",
1281
- label: "Qwen3 8B Q4_0",
1282
- hint: "Coding Q4_0",
1283
- role: "chat",
1284
- ramGb: 12,
1285
- tier: "balanced",
1286
- modalities: ["text", "code"],
1287
- },
1288
- {
1289
- id: "gemma4:e4b-q4_K_M",
1290
- label: "Gemma 4 E4B Q4",
1291
- hint: "Popular · multimodal Q4",
1292
- role: "chat",
1293
- ramGb: 16,
1294
- tier: "balanced",
1295
- modalities: ["text", "vision", "reasoning"],
1296
- },
1297
- {
1298
- id: "ministral-3:8b-reasoning",
1299
- label: "Ministral 3 8B Reasoning",
1300
- hint: "Reasoning",
1301
- role: "chat",
1302
- ramGb: 12,
1303
- tier: "balanced",
1304
- modalities: ["text", "reasoning", "code"],
1305
- },
1306
- {
1307
- id: "llama3.1",
1308
- label: "Llama 3.1 8B",
1309
- hint: "Meta default",
1310
- role: "chat",
1311
- ramGb: 12,
1312
- tier: "balanced",
1313
- modalities: ["text"],
1314
- },
1315
- {
1316
- id: "qwen2.5",
1317
- label: "Qwen2.5 7B",
1318
- hint: "Coding default",
1319
- role: "chat",
1320
- ramGb: 12,
1321
- tier: "balanced",
1322
- modalities: ["text", "code"],
1323
- },
1324
- {
1325
- id: "gemma3n",
1326
- label: "Gemma 3n",
1327
- hint: "On-device default",
1328
- role: "chat",
1329
- ramGb: 16,
1330
- tier: "balanced",
1331
- modalities: ["text", "vision"],
1332
- },
1333
- // Smart (~24–32GB) — Gemma 4 31B · Qwen family near the top
1334
- {
1335
- id: "phi4",
1336
- label: "Phi-4 14B",
1337
- hint: "Reasoning",
1338
- role: "chat",
1339
- recommended: true,
1340
- ramGb: 24,
1341
- tier: "smart",
1342
- modalities: ["text", "reasoning", "code"],
1343
- },
1344
- {
1345
- id: "gemma4:31b",
1346
- label: "Gemma 4 31B",
1347
- hint: "Popular · large multimodal",
1348
- role: "chat",
1349
- ramGb: 32,
1350
- tier: "smart",
1351
- modalities: ["text", "vision", "reasoning"],
1352
- },
1353
- {
1354
- id: "qwen3.5:27b",
1355
- label: "Qwen3.5 27B",
1356
- hint: "Popular · general · coding",
1357
- role: "chat",
1358
- ramGb: 32,
1359
- tier: "smart",
1360
- modalities: ["text", "code"],
1361
- },
1362
- {
1363
- id: "qwen3:30B-A3B-Q4_K_M",
1364
- label: "Qwen3 30B-A3B",
1365
- hint: "MoE · coding",
1366
- role: "chat",
1367
- ramGb: 24,
1368
- tier: "smart",
1369
- modalities: ["text", "code"],
1370
- },
1371
- {
1372
- id: "qwen3-coder:30B",
1373
- label: "Qwen3-Coder 30B",
1374
- hint: "Coding agent",
1375
- role: "chat",
1376
- ramGb: 24,
1377
- tier: "smart",
1378
- modalities: ["text", "code"],
1379
- },
1380
- {
1381
- id: "qwen3-vl:32B-UD-Q4_K_XL",
1382
- label: "Qwen3-VL 32B",
1383
- hint: "Vision",
1384
- role: "chat",
1385
- ramGb: 32,
1386
- tier: "smart",
1387
- modalities: ["text", "vision", "code"],
1388
- },
1389
- {
1390
- id: "gemma3:27b",
1391
- label: "Gemma 3 27B",
1392
- hint: "Large reasoning",
1393
- role: "chat",
1394
- ramGb: 32,
1395
- tier: "smart",
1396
- modalities: ["text", "reasoning"],
1397
- },
1398
- {
1399
- id: "qwq:32B-Q4_K_M",
1400
- label: "QwQ 32B",
1401
- hint: "Reasoning",
1402
- role: "chat",
1403
- ramGb: 32,
1404
- tier: "smart",
1405
- modalities: ["text", "reasoning"],
1406
- },
1407
- {
1408
- id: "gpt-oss:20b",
1409
- label: "GPT-OSS 20B",
1410
- hint: "Open weights",
1411
- role: "chat",
1412
- ramGb: 24,
1413
- tier: "smart",
1414
- modalities: ["text", "reasoning"],
1415
- },
1416
- {
1417
- id: "magistral-small-3.2",
1418
- label: "Magistral Small 24B",
1419
- hint: "Reasoning",
1420
- role: "chat",
1421
- ramGb: 24,
1422
- tier: "smart",
1423
- modalities: ["text", "reasoning"],
1424
- },
1425
- {
1426
- id: "ministral3:14B",
1427
- label: "Ministral 14B",
1428
- hint: "Mistral mid",
1429
- role: "chat",
1430
- ramGb: 24,
1431
- tier: "smart",
1432
- modalities: ["text", "code"],
1433
- },
1434
- {
1435
- id: "nemotron-3-nano:30b-a3b",
1436
- label: "Nemotron 3 Nano 30B-A3B",
1437
- hint: "NVIDIA MoE",
1438
- role: "chat",
1439
- ramGb: 24,
1440
- tier: "smart",
1441
- modalities: ["text", "code"],
1442
- },
1443
- {
1444
- id: "devstral-small-2",
1445
- label: "Devstral Small 2",
1446
- hint: "Coding",
1447
- role: "chat",
1448
- ramGb: 24,
1449
- tier: "smart",
1450
- modalities: ["text", "code"],
1451
- },
1452
- {
1453
- id: "medgemma:27b-text",
1454
- label: "MedGemma 27B Text",
1455
- hint: "Medical",
1456
- role: "chat",
1457
- ramGb: 32,
1458
- tier: "smart",
1459
- modalities: ["text"],
1460
- },
1461
- {
1462
- id: "gemma4:26b-a4b-q4_K_M",
1463
- label: "Gemma 4 26B-A4B",
1464
- hint: "Popular · MoE multimodal",
1465
- role: "chat",
1466
- ramGb: 32,
1467
- tier: "smart",
1468
- modalities: ["text", "vision", "reasoning"],
1469
- },
1470
- {
1471
- id: "glm-4.7-flash",
1472
- label: "GLM-4.7 Flash",
1473
- hint: "MoE flash",
1474
- role: "chat",
1475
- ramGb: 24,
1476
- tier: "smart",
1477
- modalities: ["text", "code"],
1478
- },
1479
- {
1480
- id: "granite4.1:30b",
1481
- label: "Granite 4.1 30B",
1482
- hint: "IBM 30B",
1483
- role: "chat",
1484
- ramGb: 32,
1485
- tier: "smart",
1486
- modalities: ["text", "code"],
1487
- },
1488
- {
1489
- id: "deepcoder-preview",
1490
- label: "DeepCoder Preview 14B",
1491
- hint: "Coding",
1492
- role: "chat",
1493
- ramGb: 24,
1494
- tier: "smart",
1495
- modalities: ["text", "code"],
1496
- },
1497
- {
1498
- id: "qwen3:14B-Q6_K",
1499
- label: "Qwen3 14B",
1500
- hint: "Coding mid",
1501
- role: "chat",
1502
- ramGb: 24,
1503
- tier: "smart",
1504
- modalities: ["text", "code"],
1505
- },
1506
- {
1507
- id: "nemotron3",
1508
- label: "Nemotron 3 30B",
1509
- hint: "NVIDIA",
1510
- role: "chat",
1511
- ramGb: 32,
1512
- tier: "smart",
1513
- modalities: ["text", "code"],
1514
- },
1515
- ];
1516
-
1517
- /**
1518
- * llama.cpp chat models in a tier (manual pick shows up to 20), ordered by RAM.
1519
- *
1520
- * @param tier - Speed / quality tier
1521
- */
1522
- export function llamaCppModelsForTier(tier: ModelTier): readonly CatalogModel[] {
1523
- return byRamThenLabel(LLAMA_CPP_CHAT_MODELS.filter((m) => m.tier === tier)).slice(0, 20);
1524
- }
1525
-
1526
- /**
1527
- * Recommended Docker Hub `ai/` model for a tier (RAM-aware).
395
+ * Resolve apply fields for a cloud menu id (interactive + `--yes`).
1528
396
  *
1529
- * @param tier - Selected tier
1530
- * @param totalRamGb - Prefer models that fit when RAM is known
397
+ * @param menuValue - CLOUD_PROVIDERS value
398
+ * @param overrides - Chat model / API key / base URL overrides
1531
399
  */
1532
- export function recommendLlamaCppForTier(
1533
- tier: ModelTier,
1534
- totalRamGb: number | null = null,
1535
- ): CatalogModel {
1536
- const list = llamaCppModelsForTier(tier);
1537
- const headroom = 4;
1538
- const fits =
1539
- totalRamGb !== null && Number.isFinite(totalRamGb)
1540
- ? list.filter((m) => m.ramGb + headroom <= totalRamGb || m.ramGb <= totalRamGb)
1541
- : list;
1542
- const pool = fits.length > 0 ? fits : list;
1543
- return pool.find((m) => m.recommended) ?? pool[pool.length - 1] ?? list[0]!;
400
+ export function cloudApplyDefaults(
401
+ menuValue: string,
402
+ overrides: {
403
+ readonly chatModel?: string;
404
+ readonly apiKey?: string;
405
+ readonly baseUrl?: string;
406
+ } = {},
407
+ ): {
408
+ readonly driver: "openai-compatible" | "anthropic";
409
+ readonly provider: string;
410
+ readonly baseUrl?: string;
411
+ readonly chatModel: string;
412
+ readonly visionModel: null;
413
+ readonly embedModel: null;
414
+ readonly apiKeyEnv?: string;
415
+ readonly apiKey?: string;
416
+ } {
417
+ const meta = CLOUD_PROVIDERS.find((p) => p.value === menuValue);
418
+ if (!meta) {
419
+ throw new Error(`oke ai setup: unknown cloud provider "${menuValue}"`);
420
+ }
421
+ const provider = meta.provider ?? meta.value;
422
+ const registry = getAiProviderEntry(provider);
423
+ // Registry openai-compat: omit baseUrl so ai.model auto-resolves.
424
+ const omitBase = registry !== undefined && meta.driver === "openai-compatible";
425
+ const baseUrl = omitBase ? undefined : (overrides.baseUrl ?? meta.baseUrl);
426
+ return {
427
+ driver: meta.driver,
428
+ provider,
429
+ ...(baseUrl !== undefined ? { baseUrl } : {}),
430
+ chatModel: overrides.chatModel ?? recommendCloudChat(menuValue),
431
+ visionModel: null,
432
+ embedModel: null,
433
+ ...(meta.apiKeyEnv
434
+ ? {
435
+ apiKeyEnv: meta.apiKeyEnv,
436
+ ...(overrides.apiKey ? { apiKey: overrides.apiKey } : {}),
437
+ }
438
+ : {}),
439
+ };
1544
440
  }