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
@@ -0,0 +1,275 @@
1
+ ---
2
+ title: "MCP"
3
+ description: "Two directions — expose Flows as gated mcp.tool endpoints on :6535, and consume external servers with ai.mcpServer allowlists."
4
+ icon: "Plug"
5
+ source: "docs/spec/unified-theory.md"
6
+ ---
7
+
8
+ Model Context Protocol (MCP) connects OKE to Cursor, Claude Desktop, and other agents in
9
+ **two directions**: your app exposes selected Flows as tools, and your Flows call tools on
10
+ external MCP servers.
11
+
12
+ For developers wiring Cursor to a backend or letting an agent open a GitHub issue — opt-in
13
+ gates inbound; allowlists outbound.
14
+
15
+ <Callout title="The one rule">
16
+ Inbound: `on(mcp.tool("name").gate(...), flow)` — ungated tools are not exposed. Outbound:
17
+ `ai.mcpServer` with a required `tools` allowlist — the runtime never trusts raw `tools/list`.
18
+ </Callout>
19
+
20
+ ## Smallest Example — expose a Flow
21
+
22
+ <Steps>
23
+
24
+ <Step>
25
+ ### Bind a gated MCP tool
26
+
27
+ ```typescript title="src/flows/bookings/create.ts"
28
+ import { on, flow, mcp } from "okengine";
29
+ import { z } from "zod";
30
+ import { member } from "@/core/gate";
31
+
32
+ export const create = on(
33
+ mcp
34
+ .tool("bookings.create", {
35
+ in: z.object({
36
+ guest: z.string().min(1),
37
+ night: z.string(),
38
+ }),
39
+ out: z.object({ id: z.string(), guest: z.string(), night: z.string() }),
40
+ })
41
+ .gate(member),
42
+ flow({
43
+ do: async (input, fx) => {
44
+ return { id: fx.id(), ...input };
45
+ },
46
+ }),
47
+ );
48
+ ```
49
+
50
+ Deny-by-default: `on(mcp.tool("…"), flow)` without `.gate(...)` fails gate posture at boot.
51
+
52
+ </Step>
53
+
54
+ <Step>
55
+ ### Connect a client
56
+
57
+ App MCP listens on port **6535**, path **`/mcp`** (not the backend `:6530` HTTP port). Bearer
58
+ auth is required.
59
+
60
+ ```json
61
+ {
62
+ "mcpServers": {
63
+ "notes": {
64
+ "url": "http://127.0.0.1:6535/mcp",
65
+ "headers": {
66
+ "Authorization": "Bearer <token>"
67
+ }
68
+ }
69
+ }
70
+ }
71
+ ```
72
+
73
+ `GET /health` on the same port probes liveness. Override with `ports.mcp` in config when needed.
74
+
75
+ </Step>
76
+
77
+ <Step>
78
+ ### Call the tool
79
+
80
+ The client lists `bookings.create` (and other gated tools). Invocations run the Flow under the
81
+ same gate chain as HTTP.
82
+
83
+ </Step>
84
+
85
+ </Steps>
86
+
87
+ ## Smallest Example — consume a server
88
+
89
+ <Steps>
90
+
91
+ <Step>
92
+ ### Declare an outbound server
93
+
94
+ ```typescript title="src/core/mcp.ts"
95
+ import { ai, vault } from "okengine";
96
+
97
+ const githubToken = vault.secret("GITHUB_MCP_TOKEN");
98
+
99
+ export const github = ai.mcpServer("github", {
100
+ url: "https://mcp.example/github",
101
+ auth: { bearer: githubToken },
102
+ tools: ["create_issue", "list_repos"],
103
+ });
104
+
105
+ export const createIssue = github.tool("create_issue"); // mcp:github/create_issue
106
+ ```
107
+
108
+ Exactly one of `url` (Streamable HTTP) or `command` (+ optional `args` for stdio). Bearer must
109
+ be a `vault.secret` handle or contract name — never a token literal in source.
110
+
111
+ </Step>
112
+
113
+ <Step>
114
+ ### Use in ask / agent tools
115
+
116
+ ```typescript
117
+ await fx.ask(triage, input, {
118
+ tools: [github.tool("create_issue")],
119
+ maxSteps: 2,
120
+ });
121
+ ```
122
+
123
+ Capability ref is `mcp:github/create_issue`. Model-facing names use `server__tool`
124
+ (`github__create_issue`).
125
+
126
+ </Step>
127
+
128
+ </Steps>
129
+
130
+ ## Progressive Patterns
131
+
132
+ <Tabs items={["Inbound gate", "stdio server", "Agent bag", "Docs MCP"]}>
133
+
134
+ <Tab value="Inbound gate">
135
+
136
+ Chain policies like HTTP — first denial wins:
137
+
138
+ ```typescript
139
+ on(
140
+ mcp.tool("admin.wipe").gate(member, gate.scope("admin")),
141
+ flow({ do: async (_input, fx) => fx.json.empty() }),
142
+ );
143
+ ```
144
+
145
+ </Tab>
146
+
147
+ <Tab value="stdio server">
148
+
149
+ Local executable transport:
150
+
151
+ ```typescript
152
+ export const localTools = ai.mcpServer("local", {
153
+ command: "npx",
154
+ args: ["-y", "some-mcp-server"],
155
+ tools: ["lookup"],
156
+ });
157
+ ```
158
+
159
+ </Tab>
160
+
161
+ <Tab value="Agent bag">
162
+
163
+ Mix Flows and MCP refs on one agent:
164
+
165
+ ```typescript
166
+ ai.agent("planner", {
167
+ model: "smart",
168
+ tools: ["tasks.create", github.tool("create_issue")],
169
+ maxSteps: 8,
170
+ budget: { maxCostPerRun: 0.25 },
171
+ });
172
+ ```
173
+
174
+ </Tab>
175
+
176
+ <Tab value="Docs MCP">
177
+
178
+ Read-only docs MCP is a **separate** process on port **6536** — not your app’s `:6535` tool
179
+ server. Use it for documentation search, not business Flows.
180
+
181
+ </Tab>
182
+
183
+ </Tabs>
184
+
185
+ ## Inbound reference
186
+
187
+ | Piece | Detail |
188
+ | ------- | ------------------------------------------------------ |
189
+ | Trigger | `mcp.tool(name, { in, out, errors? })` from `okengine` |
190
+ | Gates | `.gate(...)` required for exposure |
191
+ | Port | **6535** (`ports.mcp`) |
192
+ | Path | `POST /mcp` · `GET /health` |
193
+ | Auth | Bearer required (`Bearer token required`) |
194
+
195
+ Empty name throws `TypeError: mcp.tool(name): name is required`.
196
+
197
+ ## Outbound reference — `ai.mcpServer`
198
+
199
+ | Option | Type | Required | Meaning |
200
+ | ------------- | ------------- | ------------- | ---------------------------------- |
201
+ | `url` | `string` | XOR `command` | Streamable HTTP endpoint |
202
+ | `command` | `string` | XOR `url` | stdio executable (no shell string) |
203
+ | `args` | `string[]` | no | Arguments for `command` |
204
+ | `auth.bearer` | secret / name | no | Vault contract for Bearer |
205
+ | `tools` | `string[]` | **yes** | Allowlist — never raw `tools/list` |
206
+
207
+ | Method | Returns | Meaning |
208
+ | ------------------- | ----------------------------- | ------------------------------------------ |
209
+ | `server.tool(name)` | `{ name: "mcp:server/tool" }` | Capability ref for ask / agent / `fx.call` |
210
+
211
+ ### Declare errors
212
+
213
+ | Message | Fix |
214
+ | --------------------------------------- | ------------------------------------------- |
215
+ | `ai.mcpServer: name is required` | Pass a non-empty server id |
216
+ | `name "…" must not contain "/" or "__"` | Use a simple id (`github`, not `org/repo`) |
217
+ | `tools allowlist is required` | Pass `tools: ["…"]` |
218
+ | `declare exactly one of url or command` | Pick HTTP **or** stdio |
219
+ | `tool "…" is not in the allowlist` | Add the name to `tools` before `.tool(...)` |
220
+
221
+ ## Ports
222
+
223
+ | Port | Surface |
224
+ | -------- | ------------------------ |
225
+ | **6530** | Backend HTTP |
226
+ | **6535** | App MCP (Flows as tools) |
227
+ | **6536** | Docs MCP (read-only) |
228
+
229
+ Mnemonic: O·K·E = 6·5·3.
230
+
231
+ ## Troubleshooting
232
+
233
+ <Accordions>
234
+
235
+ <Accordion title="Bearer token required">
236
+ Clients must send `Authorization: Bearer …`. Missing or invalid Bearer is rejected before tool
237
+ dispatch.
238
+ </Accordion>
239
+
240
+ <Accordion title="Tool missing from Cursor / client list">
241
+ The Flow is not bound with `mcp.tool(…).gate(…)`, gates deny the identity, or the client points at
242
+ `:6530` instead of `:6535/mcp`.
243
+ </Accordion>
244
+
245
+ <Accordion title="Ungated mcp.tool fails at boot">
246
+ Deny-by-default posture: attach at least one gate. Public-style exposure still needs an explicit
247
+ gate policy you intend (there is no `.public()` on MCP triggers).
248
+ </Accordion>
249
+
250
+ <Accordion title="ai.mcpServer allowlist / transport errors">
251
+ See the declare-error table above. Runtime `ai.mcp: …` covers unknown server, non-allowlisted
252
+ tool, and unsupported HITL prompts from the remote.
253
+ </Accordion>
254
+
255
+ </Accordions>
256
+
257
+ ## Learn more
258
+
259
+ - [Agents](/docs/elements/ai/agents) — MCP refs in tool bags
260
+ - [Gate](/docs/elements/gate) — policies on `mcp.tool`
261
+ - [Vault](/docs/elements/vault) — bearer secret contracts
262
+ - [AI](/docs/elements/ai) — element overview
263
+ - [Security](/docs/reference/security) — ports 6530 · 6533 · 6535 · 6536
264
+
265
+ ## Next
266
+
267
+ <Cards>
268
+ <Card
269
+ title="Agents"
270
+ description="Run bounded agents that call MCP tools."
271
+ href="/docs/elements/ai/agents"
272
+ />
273
+ <Card title="AI" description="Models, prompts, and fx.ask." href="/docs/elements/ai" />
274
+ <Card title="Flow" description="Flows are the tools MCP exposes." href="/docs/elements/flow" />
275
+ </Cards>
@@ -0,0 +1,5 @@
1
+ {
2
+ "title": "AI",
3
+ "icon": "Sparkles",
4
+ "pages": ["index", "models", "prompts", "agents", "mcp"]
5
+ }
@@ -0,0 +1,283 @@
1
+ ---
2
+ title: "Models"
3
+ description: "Declare ai.model bindings — known providers auto-resolve baseUrl; Anthropic and Google OpenAI-compat have documented limits."
4
+ icon: "Cpu"
5
+ source: "docs/spec/unified-theory.md"
6
+ ---
7
+
8
+ An `ai.model` binding names a logical model (`smart`, `local`, …), the wire `model` id, and how
9
+ to reach it (`provider`, optional `baseUrl` / `apiKey` / `driverId`).
10
+
11
+ For developers swapping OpenRouter for a self-hosted OpenAI-compatible `/v1` — one logical
12
+ name, different bindings per environment.
13
+
14
+ <Callout title="The one rule">
15
+ Known OpenAI-compatible `provider` names resolve `baseUrl` automatically. Explicit `baseUrl`
16
+ always wins. Unknown providers require `baseUrl` — they fail loud. Per-binding `apiKey` isolates
17
+ tokens when several providers run together.
18
+ </Callout>
19
+
20
+ ## Smallest Example
21
+
22
+ <Steps>
23
+
24
+ <Step>
25
+ ### Declare cloud + BYO bindings
26
+
27
+ ```typescript title="src/core/ai.ts"
28
+ import { ai } from "okengine";
29
+
30
+ export const smart = ai.model("smart", {
31
+ provider: "openrouter",
32
+ model: "openrouter/free",
33
+ apiKey: process.env.OPENROUTER_API_KEY,
34
+ });
35
+
36
+ export const local = ai.model("local", {
37
+ provider: "openai-compatible",
38
+ model: process.env.OKE_AI_MODEL ?? "your-model-id",
39
+ ...(process.env.OKE_AI_URL?.trim() ? { baseUrl: process.env.OKE_AI_URL.trim() } : {}),
40
+ });
41
+ ```
42
+
43
+ OpenRouter fills `https://openrouter.ai/api/v1` without typing it. Any
44
+ OpenAI-compatible `/v1` uses the same driver — set `OKE_AI_URL` yourself;
45
+ Compose does not manage inference.
46
+
47
+ </Step>
48
+
49
+ <Step>
50
+ ### Attach a versioned prompt
51
+
52
+ ```typescript
53
+ export const triage = smart.prompt("ticket-triage", {
54
+ version: 1,
55
+ via: ["smart", "local"],
56
+ });
57
+ ```
58
+
59
+ </Step>
60
+
61
+ <Step>
62
+ ### Ask from a Flow
63
+
64
+ ```typescript title="src/flows/support/triage.ts"
65
+ import { on, flow, http } from "okengine";
66
+ import { triage } from "@/core/ai";
67
+
68
+ export const classify = on(
69
+ http.post(),
70
+ flow({
71
+ do: async (input, fx) => await fx.ask(triage, input),
72
+ }),
73
+ );
74
+ ```
75
+
76
+ `fx.ask` uses the prompt’s model chain. Recovery via `via` opens a **separate** client per
77
+ binding — keys and base URLs do not mix.
78
+
79
+ </Step>
80
+
81
+ </Steps>
82
+
83
+ ## Progressive Patterns
84
+
85
+ <Tabs items={["OpenRouter", "BYO /v1", "Native Anthropic", "Multi-key"]}>
86
+
87
+ <Tab value="OpenRouter">
88
+
89
+ Zero Docker — registry fills the URL:
90
+
91
+ ```typescript
92
+ export const smart = ai.model("smart", {
93
+ provider: "openrouter",
94
+ model: "openrouter/free",
95
+ apiKey: process.env.OPENROUTER_API_KEY,
96
+ });
97
+ ```
98
+
99
+ See [OpenRouter](/docs/recipes/openrouter) for router aliases (`openrouter/auto`, fusion, …).
100
+
101
+ </Tab>
102
+
103
+ <Tab value="BYO /v1">
104
+
105
+ Same `openai-compatible` driver — you supply the base URL (no Compose AI recipe):
106
+
107
+ ```typescript
108
+ export const local = ai.model("local", {
109
+ provider: "openai-compatible",
110
+ model: process.env.OKE_AI_MODEL ?? "your-model-id",
111
+ baseUrl: process.env.OKE_AI_URL, // must end in /v1
112
+ });
113
+ ```
114
+
115
+ Pin `drivers.ai.dev: "openai-compatible"`. Set `OKE_AI_URL` / `OKE_AI_MODEL`
116
+ in env, or pass `baseUrl` on the binding.
117
+
118
+ </Tab>
119
+
120
+ <Tab value="Native Anthropic">
121
+
122
+ Production Claude — native Messages API, not the OpenAI-compat shim:
123
+
124
+ ```typescript
125
+ export const claude = ai.model("claude", {
126
+ provider: "anthropic",
127
+ model: "claude-sonnet-4-20250514",
128
+ driverId: "anthropic",
129
+ apiKey: process.env.ANTHROPIC_API_KEY,
130
+ });
131
+ ```
132
+
133
+ </Tab>
134
+
135
+ <Tab value="Multi-key">
136
+
137
+ One binding per provider so tokens never collide:
138
+
139
+ ```typescript
140
+ export const smart = ai.model("smart", {
141
+ provider: "openrouter",
142
+ model: "openrouter/auto",
143
+ apiKey: process.env.OPENROUTER_API_KEY,
144
+ });
145
+
146
+ export const gpt = ai.model("gpt", {
147
+ provider: "openai",
148
+ model: "gpt-4.1-mini",
149
+ apiKey: process.env.OPENAI_API_KEY,
150
+ });
151
+ ```
152
+
153
+ </Tab>
154
+
155
+ </Tabs>
156
+
157
+ ## Options
158
+
159
+ | Option | Type | Default | Meaning |
160
+ | ---------- | -------- | ----------- | ------------------------------------------------------------- |
161
+ | `provider` | `string` | — | Registry name or exempt/local label |
162
+ | `model` | `string` | — | Wire model id sent to the provider |
163
+ | `baseUrl` | `string` | auto / omit | Override (always wins over registry) |
164
+ | `apiKey` | `string` | — | Per-binding key (isolates multi-provider apps) |
165
+ | `driverId` | `string` | app default | Protocol driver (`openai-compatible`, `anthropic`, `mock`, …) |
166
+ | `tier` | `string` | — | Optional app label (not the registry status below) |
167
+
168
+ Empty name throws `TypeError: ai.model: name is required`.
169
+
170
+ ## Verified providers
171
+
172
+ These names auto-resolve a verified OpenAI-compatible `baseUrl`:
173
+
174
+ | Provider | Base URL (auto) |
175
+ | ------------ | ------------------------------------- |
176
+ | `openai` | `https://api.openai.com/v1` |
177
+ | `openrouter` | `https://openrouter.ai/api/v1` |
178
+ | `groq` | `https://api.groq.com/openai/v1` |
179
+ | `together` | `https://api.together.ai/v1` |
180
+ | `deepinfra` | `https://api.deepinfra.com/v1/openai` |
181
+ | `xai` | `https://api.x.ai/v1` |
182
+ | `mistral` | `https://api.mistral.ai/v1` |
183
+ | `deepseek` | `https://api.deepseek.com` |
184
+ | `vercel` | `https://ai-gateway.vercel.sh/v1` |
185
+
186
+ **Not** registered (pass `baseUrl` if you still need them): Cloudflare Workers AI
187
+ (account-scoped URL); Meta (retired Llama OpenAI-compat API / unverified Muse Spark
188
+ host — do not guess a URL).
189
+
190
+ Exempt labels (no registry URL): `mock`, `local`, `openai-compatible`.
191
+
192
+ ## Limited compatibility
193
+
194
+ `anthropic`, `google`, and alias `gemini` also auto-resolve a URL, with documented limits.
195
+ Prefer native Anthropic for production Claude.
196
+
197
+ | Provider | Base URL (auto) |
198
+ | ------------------- | --------------------------------------------------------- |
199
+ | `anthropic` | `https://api.anthropic.com/v1` |
200
+ | `google` / `gemini` | `https://generativelanguage.googleapis.com/v1beta/openai` |
201
+
202
+ <Callout type="warn" title="Anthropic OpenAI-compat is evaluation-only">
203
+ Anthropic’s OpenAI-compatible endpoint is for testing/comparison only. `tools[].function.strict`
204
+ is ignored; `n` must be 1; no embeddings here. **Production:** `driverId: "anthropic"` (native
205
+ Messages API).
206
+ </Callout>
207
+
208
+ <Callout type="warn" title="Google OpenAI-compat tool schemas">
209
+ Tool/parameter schemas are not full OpenAI JSON Schema fidelity. Complex Flow-as-tool schemas can
210
+ fail — do not rely on this path for agent tool calling in production.
211
+ </Callout>
212
+
213
+ Declare-time and `oke extract` both warn when these providers auto-resolve.
214
+
215
+ ## Native vs OpenAI-compat Anthropic
216
+
217
+ | Path | When |
218
+ | --------------------------------------------- | ----------------------------------------------- |
219
+ | `driverId: "anthropic"` | Production Claude — native Messages API |
220
+ | `provider: "anthropic"` without native driver | Quick eval via openai-compatible + registry URL |
221
+
222
+ They are not interchangeable for agents that depend on reliable tool calling.
223
+
224
+ ## Streaming
225
+
226
+ `fx.stream(model, { prompt, data?, via? })` records `asks` and yields token chunks. Drivers
227
+ that do not support stream throw
228
+ `ai: model "…" (driver …) does not support stream`.
229
+
230
+ ```typescript
231
+ for await (const chunk of fx.stream(smart, { prompt: "Say hello" })) {
232
+ // chunk is a string token
233
+ }
234
+ ```
235
+
236
+ ## Per-environment drivers
237
+
238
+ See [AI Overview](/docs/elements/ai#per-environment-drivers). create-oke does **not** pin
239
+ `drivers.ai` by default — unset dev/test → `mock`; prod must declare.
240
+
241
+ ## Troubleshooting
242
+
243
+ <Accordions>
244
+
245
+ <Accordion title='ai.model: unknown provider "…" requires an explicit baseUrl'>
246
+ The name is not in the registry (and not an exempt local label). Pass `baseUrl`, or use a known
247
+ provider id from the tables above. Exact message lists known providers and notes that Cloudflare
248
+ and Meta always need `baseUrl`.
249
+ </Accordion>
250
+
251
+ <Accordion title="Limited-compatibility warn on extract / declare">
252
+ Expected for `anthropic` / `google` / `gemini` when auto-resolving the OpenAI-compat URL. Switch
253
+ to native `driverId: "anthropic"` for production Claude.
254
+ </Accordion>
255
+
256
+ <Accordion title='ai: no client for model "…" and no defaultDriver'>
257
+ The binding has no resolvable client and boot has no default AI driver. Pin `drivers.ai` or set
258
+ `OKE_AI_DRIVER` / `OKE_AI_URL` for the active environment.
259
+ </Accordion>
260
+
261
+ <Accordion title="TypeError: ai.model: name is required">
262
+ Pass a non-empty logical name (`"smart"`, `"local"`, …).
263
+ </Accordion>
264
+
265
+ </Accordions>
266
+
267
+ ## Learn more
268
+
269
+ - [OpenRouter](/docs/recipes/openrouter) — free / auto / fusion routers
270
+ - [Prompts](/docs/elements/ai/prompts) — `model.prompt` and `via`
271
+ - [AI](/docs/elements/ai) — element overview and `fx` surface
272
+
273
+ ## Next
274
+
275
+ <Cards>
276
+ <Card
277
+ title="Prompts"
278
+ description="Versioned prompts and via chains."
279
+ href="/docs/elements/ai/prompts"
280
+ />
281
+ <Card title="OpenRouter" description="Zero-cost cloud default." href="/docs/recipes/openrouter" />
282
+ <Card title="AI" description="Element overview." href="/docs/elements/ai" />
283
+ </Cards>