okengine 0.18.5 → 0.19.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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/llms-txt.mdx +1 -1
  5. package/site/content/docs/ai/skills.mdx +4 -1
  6. package/site/content/docs/client/auth.mdx +208 -0
  7. package/site/content/docs/client/calling.mdx +451 -0
  8. package/site/content/docs/client/index.mdx +208 -0
  9. package/site/content/docs/client/live.mdx +234 -0
  10. package/site/content/docs/client/meta.json +5 -0
  11. package/site/content/docs/client/react.mdx +249 -0
  12. package/site/content/docs/elements/ai/agents.mdx +235 -0
  13. package/site/content/docs/elements/ai/index.mdx +342 -0
  14. package/site/content/docs/elements/ai/mcp.mdx +275 -0
  15. package/site/content/docs/elements/ai/meta.json +5 -0
  16. package/site/content/docs/elements/ai/models.mdx +283 -0
  17. package/site/content/docs/elements/ai/prompts.mdx +257 -0
  18. package/site/content/docs/elements/channel/email.mdx +269 -0
  19. package/site/content/docs/elements/channel/index.mdx +344 -0
  20. package/site/content/docs/elements/channel/meta.json +5 -0
  21. package/site/content/docs/elements/channel/push.mdx +218 -0
  22. package/site/content/docs/elements/channel/receipts.mdx +206 -0
  23. package/site/content/docs/elements/channel/sms.mdx +264 -0
  24. package/site/content/docs/elements/channel/whatsapp.mdx +220 -0
  25. package/site/content/docs/elements/clock/index.mdx +301 -0
  26. package/site/content/docs/elements/clock/meta.json +5 -0
  27. package/site/content/docs/elements/clock/schedules.mdx +508 -0
  28. package/site/content/docs/elements/clock/sleep.mdx +448 -0
  29. package/site/content/docs/elements/flow/consumers.mdx +707 -0
  30. package/site/content/docs/elements/flow/http.mdx +1080 -0
  31. package/site/content/docs/elements/flow/index.mdx +618 -0
  32. package/site/content/docs/elements/flow/meta.json +5 -0
  33. package/site/content/docs/elements/flow/routing.mdx +559 -0
  34. package/site/content/docs/elements/flow/workflows.mdx +640 -0
  35. package/site/content/docs/elements/gate/auth.mdx +371 -0
  36. package/site/content/docs/elements/gate/authorization.mdx +298 -0
  37. package/site/content/docs/elements/gate/index.mdx +418 -0
  38. package/site/content/docs/elements/gate/meta.json +5 -0
  39. package/site/content/docs/elements/gate/rate-limits.mdx +365 -0
  40. package/site/content/docs/elements/gate/rls.mdx +303 -0
  41. package/site/content/docs/elements/gate/tenancy.mdx +375 -0
  42. package/site/content/docs/elements/index.mdx +20 -10
  43. package/site/content/docs/elements/signal/broadcast.mdx +519 -0
  44. package/site/content/docs/elements/signal/index.mdx +352 -0
  45. package/site/content/docs/elements/signal/live.mdx +591 -0
  46. package/site/content/docs/elements/signal/meta.json +5 -0
  47. package/site/content/docs/elements/signal/once.mdx +597 -0
  48. package/site/content/docs/elements/store/files.mdx +667 -0
  49. package/site/content/docs/elements/store/index.mdx +313 -0
  50. package/site/content/docs/elements/store/kv.mdx +637 -0
  51. package/site/content/docs/elements/store/meta.json +5 -0
  52. package/site/content/docs/elements/store/search.mdx +950 -0
  53. package/site/content/docs/elements/store/sql.mdx +941 -0
  54. package/site/content/docs/elements/vault/config.mdx +259 -0
  55. package/site/content/docs/elements/vault/index.mdx +356 -0
  56. package/site/content/docs/elements/vault/meta.json +5 -0
  57. package/site/content/docs/elements/vault/rotation.mdx +276 -0
  58. package/site/content/docs/elements/vault/secrets.mdx +288 -0
  59. package/site/content/docs/index.mdx +52 -40
  60. package/site/content/docs/meta.json +8 -7
  61. package/site/content/docs/plugins/cors.mdx +2 -1
  62. package/site/content/docs/plugins/csrf.mdx +4 -1
  63. package/site/content/docs/plugins/headers.mdx +2 -1
  64. package/site/content/docs/plugins/ip-allowlist.mdx +2 -1
  65. package/site/content/docs/plugins/magic-link.mdx +6 -0
  66. package/site/content/docs/plugins/maintenance-mode.mdx +2 -1
  67. package/site/content/docs/plugins/oauth.mdx +1 -1
  68. package/site/content/docs/plugins/otp.mdx +12 -1
  69. package/site/content/docs/plugins/passkey.mdx +39 -15
  70. package/site/content/docs/plugins/two-factor.mdx +91 -34
  71. package/site/content/docs/plugins/username.mdx +1 -1
  72. package/site/content/docs/recipes/caddy.mdx +3 -3
  73. package/site/content/docs/recipes/index.mdx +18 -28
  74. package/site/content/docs/recipes/mailpit.mdx +1 -1
  75. package/site/content/docs/recipes/meilisearch.mdx +3 -3
  76. package/site/content/docs/recipes/meta.json +1 -4
  77. package/site/content/docs/recipes/nginx.mdx +2 -2
  78. package/site/content/docs/recipes/openrouter.mdx +283 -0
  79. package/site/content/docs/recipes/pgdog.mdx +3 -3
  80. package/site/content/docs/recipes/postgres.mdx +1 -2
  81. package/site/content/docs/recipes/rustfs.mdx +2 -2
  82. package/site/content/docs/recipes/traefik.mdx +3 -3
  83. package/site/content/docs/reference/cli.mdx +231 -0
  84. package/site/content/docs/reference/configuration.mdx +30 -10
  85. package/site/content/docs/reference/environment-variables.mdx +93 -20
  86. package/site/content/docs/reference/errors.mdx +132 -29
  87. package/site/content/docs/reference/fx.mdx +138 -73
  88. package/site/content/docs/reference/index.mdx +13 -21
  89. package/site/content/docs/reference/meta.json +4 -5
  90. package/site/content/docs/reference/okid.mdx +42 -17
  91. package/site/content/docs/reference/plugins.mdx +4 -3
  92. package/site/content/docs/reference/security.mdx +197 -0
  93. package/site/content/docs/understand/meta.json +5 -0
  94. package/site/content/docs/understand/the-architecture.mdx +264 -0
  95. package/site/content/docs/understand/try-it.mdx +58 -0
  96. package/src/auth/api-keys.ts +2 -1
  97. package/src/auth/bindings.ts +64 -16
  98. package/src/auth/gate-auth.test.ts +6 -1
  99. package/src/auth/identity.ts +152 -5
  100. package/src/auth/index.ts +29 -0
  101. package/src/auth/invites.ts +2 -1
  102. package/src/auth/method-context.ts +41 -0
  103. package/src/auth/oauth-as/crypto.ts +2 -1
  104. package/src/auth/oauth-as/stores.ts +2 -1
  105. package/src/auth/operator.ts +2 -1
  106. package/src/auth/sessions-jwt.test.ts +77 -0
  107. package/src/auth/sessions.ts +20 -4
  108. package/src/auth/tenants.ts +3 -2
  109. package/src/auth/two-factor-challenge.test.ts +61 -0
  110. package/src/auth/two-factor-challenge.ts +284 -0
  111. package/src/auth/verification.ts +5 -0
  112. package/src/bench/REPORT.md +80 -0
  113. package/src/bench/g03-signal-once.bench.ts +1 -1
  114. package/src/bench/g10-observability-contention.bench.ts +1 -1
  115. package/src/bench/g17-hybrid-search.bench.ts +572 -0
  116. package/src/bench/load-app.ts +2 -10
  117. package/src/cli/ai-setup/ai-setup.test.ts +331 -42
  118. package/src/cli/ai-setup/apply.ts +294 -52
  119. package/src/cli/ai-setup/catalog.ts +238 -1342
  120. package/src/cli/ai-setup/index.ts +14 -99
  121. package/src/cli/ai-setup/prompts.ts +60 -443
  122. package/src/cli/ask-seed.test.ts +96 -0
  123. package/src/cli/ask-seed.ts +82 -0
  124. package/src/cli/ask-vault-gaps.test.ts +84 -0
  125. package/src/cli/ask-vault-gaps.ts +146 -0
  126. package/src/cli/build.ts +2 -2
  127. package/src/cli/client-add.test.ts +26 -1
  128. package/src/cli/client-add.ts +106 -27
  129. package/src/cli/db-seed.ts +2 -0
  130. package/src/cli/db.ts +150 -11
  131. package/src/cli/dev.ts +119 -211
  132. package/src/cli/docker-clean.ts +2 -2
  133. package/src/cli/docker-cli.test.ts +1 -1
  134. package/src/cli/doctor-diff.ts +4 -2
  135. package/src/cli/doctor-pii.test.ts +1 -1
  136. package/src/cli/doctor.ts +14 -1
  137. package/src/cli/hero-meta.test.ts +4 -2
  138. package/src/cli/load-config.images.test.ts +8 -10
  139. package/src/cli/load-config.ts +1 -1
  140. package/src/cli/registry.ts +22 -10
  141. package/src/cli/replay.ts +3 -1
  142. package/src/cli/start.ts +1 -1
  143. package/src/cli/tui/keys.ts +2 -3
  144. package/src/client/auth/cookies.ts +74 -0
  145. package/src/client/auth/create-auth-client.ts +636 -0
  146. package/src/client/auth/denials.ts +99 -0
  147. package/src/client/auth/session.ts +283 -0
  148. package/src/client/auth.test.ts +251 -0
  149. package/src/client/auth.ts +39 -114
  150. package/src/client/create-with-session.ts +245 -0
  151. package/src/client/create.ts +51 -5
  152. package/src/client/index.ts +11 -1
  153. package/src/client/live.ts +11 -79
  154. package/src/client/notes-contract.test.ts +5 -10
  155. package/src/client/sse.ts +137 -0
  156. package/src/client/stream.ts +147 -0
  157. package/src/client/transport.test.ts +32 -0
  158. package/src/client/transport.ts +123 -26
  159. package/src/client/types.ts +118 -14
  160. package/src/client-react/index.ts +185 -24
  161. package/src/client-react/use-live-query.ts +13 -3
  162. package/src/compiler/aot.test.ts +7 -4
  163. package/src/compiler/effects-embed.test.ts +56 -0
  164. package/src/compiler/effects-fetch.test.ts +43 -0
  165. package/src/compiler/effects-infer.ts +58 -2
  166. package/src/compiler/extract.test.ts +257 -43
  167. package/src/compiler/extract.ts +566 -48
  168. package/src/compiler/fixtures/skyport/src/flows/bookings/index.ts +7 -4
  169. package/src/compiler/fixtures/skyport/src/flows/bookings/signals.ts +2 -8
  170. package/src/compiler/fixtures/skyport.expected.json +4 -4
  171. package/src/compiler/fixtures/triggers/five-triggers.ts +14 -10
  172. package/src/compiler/response.ts +2 -2
  173. package/src/compiler/search-writer-isolation.test.ts +40 -0
  174. package/src/config/index.ts +11 -0
  175. package/src/console/server/app.ts +17 -23
  176. package/src/console/server/bind.ts +4 -0
  177. package/src/console/server/console.test.ts +2 -2
  178. package/src/console/server/flows-invoke.test.ts +50 -34
  179. package/src/console/server/flows.ts +436 -255
  180. package/src/console/server/runs-ingest.test.ts +6 -3
  181. package/src/console/server/serve.ts +1 -1
  182. package/src/console/server/signals.test.ts +1 -5
  183. package/src/console/server/signals.ts +8 -6
  184. package/src/console/server/state.ts +6 -1
  185. package/src/console/server/store.ts +1 -1
  186. package/src/console/ui-next/dist/assets/FileExportIcon-Ck-5od4R.js +1 -0
  187. package/src/console/ui-next/dist/assets/MoreHorizontalCircle01Icon-gMNGsE37.js +1 -0
  188. package/src/console/ui-next/dist/assets/PlusSignIcon-CwG3nxfu.js +1 -0
  189. package/src/console/ui-next/dist/assets/UnavailableIcon-D9cvHVPr.js +1 -0
  190. package/src/console/ui-next/dist/assets/UserIcon-DaE2PB5_.js +1 -0
  191. package/src/console/ui-next/dist/assets/access-page-C_qLDhTq.js +4 -0
  192. package/src/console/ui-next/dist/assets/agent-disclosure-BHVqr3TN.js +1 -0
  193. package/src/console/ui-next/dist/assets/cache-glyph-CKe92lRQ.js +1 -0
  194. package/src/console/ui-next/dist/assets/call-pii-button-DEwTl8ZX.js +1 -0
  195. package/src/console/ui-next/dist/assets/collapsible-BCBtDrCt.js +1 -0
  196. package/src/console/ui-next/dist/assets/copy-inline-button-CAYD18cr.js +1 -0
  197. package/src/console/ui-next/dist/assets/dagre.esm-B1_XeuLP.js +1 -0
  198. package/src/console/ui-next/dist/assets/detail-header-DVWNjWjg.js +1 -0
  199. package/src/console/ui-next/dist/assets/dropdown-menu-4h2LOVXM.js +1 -0
  200. package/src/console/ui-next/dist/assets/duration-tone-JroqeuCp.js +9 -0
  201. package/src/console/ui-next/dist/assets/element-icons-BI8cJgdh.js +1 -0
  202. package/src/console/ui-next/dist/assets/explorer-empty-CJs5A-wm.js +1 -0
  203. package/src/console/ui-next/dist/assets/flows-page-CVHa0RTt.js +1 -0
  204. package/src/console/ui-next/dist/assets/highlighted-json-DjJW6hqe.js +154 -0
  205. package/src/console/ui-next/dist/assets/http-method-DC5HBdLU.js +1 -0
  206. package/src/console/ui-next/dist/assets/index-CYjiZ3WO.js +63 -0
  207. package/src/console/ui-next/dist/assets/index-D0zS5rKO.css +2 -0
  208. package/src/console/ui-next/dist/assets/observability-page-CAYMyKb3.js +4 -0
  209. package/src/console/ui-next/dist/assets/react-dom-Ddte4I-Q.js +9 -0
  210. package/src/console/ui-next/dist/assets/replica-lag-yAQYLv75.js +18 -0
  211. package/src/console/ui-next/dist/assets/request-meta-D0yusGxJ.js +1 -0
  212. package/src/console/ui-next/dist/assets/shortcut-keys-3ILd8oGn.js +1 -0
  213. package/src/console/ui-next/dist/assets/{sql-BskegiFM.js → sql-BsFa4tDR.js} +1 -1
  214. package/src/console/ui-next/dist/assets/store-page-BTKJeJ02.js +41 -0
  215. package/src/console/ui-next/dist/assets/trace-detail-sheet-Bp-Yygs5.js +2 -0
  216. package/src/console/ui-next/dist/assets/tree-expand-toggle-DoaVDfAM.js +55 -0
  217. package/src/console/ui-next/dist/assets/units-page-BRz7xyYL.js +1 -0
  218. package/src/console/ui-next/dist/assets/{use-vault-list-uk4WVboC.js → use-vault-list-CT4-gajj.js} +1 -1
  219. package/src/console/ui-next/dist/assets/vault-page-3jQt-bOJ.js +2 -0
  220. package/src/console/ui-next/dist/assets/xyflow-CSyC6ryz.css +1 -0
  221. package/src/console/ui-next/dist/assets/xyflow-yApv7D4e.js +7 -0
  222. package/src/console/ui-next/dist/index.html +6 -13
  223. package/src/console/ui-next/seed-invoke-host.ts +21 -18
  224. package/src/console/ui-next/src/client.ts +7 -2
  225. package/src/console/ui-next/src/features/flows/graph/element-map.test.ts +1 -1
  226. package/src/console/ui-next/src/features/flows/graph/element-map.ts +5 -3
  227. package/src/console/ui-next/src/features/flows/traces/effect-kind.ts +12 -2
  228. package/src/console/ui-next/src/features/flows/traces/effect-summary.ts +4 -0
  229. package/src/console/ui-next/src/features/flows/traces/trace-detail-sheet.tsx +8 -0
  230. package/src/console/ui-next/src/features/flows/traces/trace-detail.test.ts +4 -5
  231. package/src/console/ui-next/src/features/flows/traces/trace-gates.ts +3 -6
  232. package/src/console/ui-next/src/features/flows/traces/waterfall-bars.ts +4 -0
  233. package/src/console/ui-next/src/features/flows/traces/waterfall-tooltip.ts +9 -3
  234. package/src/console/ui-next/src/features/store/detail/reveal-cell.tsx +7 -11
  235. package/src/console/ui-next/src/features/store/detail/store-row-detail-sheet.tsx +2 -2
  236. package/src/console/ui-next/src/features/store/lib/fields-from-table.ts +2 -0
  237. package/src/console/ui-next/src/features/store/lib/grid-model.test.ts +25 -1
  238. package/src/console/ui-next/src/features/store/lib/grid-model.ts +36 -1
  239. package/src/console/ui-next/src/features/store/query/query-results.tsx +3 -3
  240. package/src/console/ui-next/src/features/units/detail/effects-summary.tsx +2 -0
  241. package/src/console/ui-next/src/features/units/lib/call-read-safe.ts +3 -1
  242. package/src/console/ui-next/src/features/units/lib/fields-from-schema.ts +6 -0
  243. package/src/docker/ai-model-status.test.ts +1 -12
  244. package/src/docker/ai-model-status.ts +10 -38
  245. package/src/docker/compose-up.test.ts +100 -0
  246. package/src/docker/compose-up.ts +292 -0
  247. package/src/docker/compose.ts +4 -14
  248. package/src/docker/derive.ts +9 -34
  249. package/src/docker/docker.test.ts +16 -261
  250. package/src/docker/images-config.test.ts +13 -25
  251. package/src/docker/index.ts +1 -24
  252. package/src/docker/recipes/index.ts +0 -23
  253. package/src/docker/recipes/pgdog.ts +6 -4
  254. package/src/docker/stack-id.test.ts +2 -2
  255. package/src/docker/stack-id.ts +0 -1
  256. package/src/docker/types.ts +2 -2
  257. package/src/drivers/ai-anthropic.ts +10 -0
  258. package/src/drivers/ai-openai-compatible.ts +34 -7
  259. package/src/drivers/ai-providers.test.ts +0 -107
  260. package/src/drivers/ai-stream.test.ts +0 -34
  261. package/src/drivers/ai-types.ts +17 -8
  262. package/src/drivers/channel-fcm.ts +6 -1
  263. package/src/drivers/channel-msegat.ts +6 -1
  264. package/src/drivers/channel-resend.ts +5 -1
  265. package/src/drivers/channel-smtp.ts +5 -1
  266. package/src/drivers/channel-sndr.ts +10 -1
  267. package/src/drivers/channel-taqnyat-mail.ts +5 -1
  268. package/src/drivers/channel-taqnyat-whatsapp.ts +6 -1
  269. package/src/drivers/channel-taqnyat.ts +6 -1
  270. package/src/drivers/channel-types.ts +10 -0
  271. package/src/drivers/channel-unifonic.ts +6 -1
  272. package/src/drivers/channel-wa-cloud.ts +6 -1
  273. package/src/drivers/channel-webpush.ts +6 -1
  274. package/src/drivers/external.ts +33 -0
  275. package/src/drivers/index.ts +0 -10
  276. package/src/drivers/meilisearch.ts +6 -0
  277. package/src/drivers/oauth-types.ts +4 -0
  278. package/src/drivers/postgres.test.ts +74 -3
  279. package/src/drivers/postgres.ts +175 -6
  280. package/src/drivers/signal-types.ts +5 -5
  281. package/src/drivers/types.ts +7 -0
  282. package/src/drivers/vault-types.ts +5 -0
  283. package/src/elements/ai/declare.ts +17 -4
  284. package/src/elements/ai/eval.ts +1 -1
  285. package/src/elements/ai/mcp-http.ts +1 -1
  286. package/src/elements/ai/pii.ts +1 -1
  287. package/src/elements/ai/providers.test.ts +289 -0
  288. package/src/elements/ai/providers.ts +169 -0
  289. package/src/elements/ai/runtime.ts +68 -5
  290. package/src/elements/ai/schema.ts +2 -2
  291. package/src/elements/ai.test.ts +7 -7
  292. package/src/elements/ai.ts +17 -1
  293. package/src/elements/channel/runtime.ts +105 -12
  294. package/src/elements/clock/cron-fields.test.ts +144 -0
  295. package/src/elements/clock/cron-fields.ts +185 -0
  296. package/src/elements/clock/declare.ts +247 -3
  297. package/src/elements/clock.ts +21 -1
  298. package/src/elements/gate/declare.ts +1 -1
  299. package/src/elements/gate.ts +1 -1
  300. package/src/elements/index.ts +15 -0
  301. package/src/elements/signal/chaos-child.ts +1 -2
  302. package/src/elements/signal/declare.ts +65 -37
  303. package/src/elements/signal/delivery-modes.test.ts +11 -31
  304. package/src/elements/signal/dry-run-replay.test.ts +1 -7
  305. package/src/elements/signal/dry-run-write-isolation.test.ts +1 -7
  306. package/src/elements/signal/key-ordering.test.ts +6 -26
  307. package/src/elements/signal/lease-reclaim.test.ts +2 -6
  308. package/src/elements/signal/optional-emit.test.ts +6 -9
  309. package/src/elements/signal/order-lifecycle.test.ts +4 -17
  310. package/src/elements/signal/orphan-messages.test.ts +4 -15
  311. package/src/elements/signal/reconcile.test.ts +2 -2
  312. package/src/elements/signal/runtime.ts +1 -1
  313. package/src/elements/signal/schema-emit.test.ts +4 -8
  314. package/src/elements/signal.test.ts +24 -49
  315. package/src/elements/signal.ts +9 -2
  316. package/src/elements/store/domain-ddl.test.ts +1 -1
  317. package/src/elements/store/live-http.test.ts +9 -4
  318. package/src/elements/store/prepare-row.test.ts +123 -0
  319. package/src/elements/store/resource.ts +43 -12
  320. package/src/elements/store/schema-decl.ts +117 -0
  321. package/src/elements/store/search-backfill.ts +205 -0
  322. package/src/elements/store/search-bind.ts +66 -0
  323. package/src/elements/store/search-bm25.ts +78 -0
  324. package/src/elements/store/search-ddl.ts +156 -0
  325. package/src/elements/store/search-embed-flow.ts +141 -0
  326. package/src/elements/store/search-errors.ts +34 -0
  327. package/src/elements/store/search-fusion.ts +112 -0
  328. package/src/elements/store/search-lsh.ts +214 -0
  329. package/src/elements/store/search-runtime.pglite.test.ts +186 -0
  330. package/src/elements/store/search-runtime.ts +314 -0
  331. package/src/elements/store/search.test.ts +226 -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 +52 -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 +2 -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 -144
  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 -114
  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-3-EFj-2G.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-cVFnA4HH.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-CMIgUbD0.js +0 -66
  484. package/src/console/ui-next/dist/assets/index-Ck88Jmv8.css +0 -2
  485. package/src/console/ui-next/dist/assets/link-BX6Vqztd.js +0 -1
  486. package/src/console/ui-next/dist/assets/observability-page-CQ3p34ip.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-l8FeKfnP.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-CL-d_mLE.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,235 @@
1
+ ---
2
+ title: "Agents"
3
+ description: "Bounded agents — tools are Flows, maxSteps and budget.maxCostPerRun cap the loop, invoke with fx.run."
4
+ icon: "Bot"
5
+ source: "docs/spec/unified-theory.md"
6
+ ---
7
+
8
+ An agent (`ai.agent`) is a **bounded tool-calling loop**. Tools are your app’s Flows (and
9
+ allowlisted MCP refs) — each step goes through `fx.call`. The loop stops at `maxSteps` or
10
+ `budget.maxCostPerRun`.
11
+
12
+ For developers who need a planner or support assistant without writing a custom tool runtime —
13
+ declare the bag, run with `fx.run`.
14
+
15
+ <Callout title="The one rule">
16
+ Pass Flow names (or handles) in `tools`, set `maxSteps` and `budget.maxCostPerRun`, then
17
+ `fx.run(agent, {message})`. There is no `instructions` / `in` / `out` on `ai.agent` — shape the
18
+ user message yourself.
19
+ </Callout>
20
+
21
+ ## Smallest Example
22
+
23
+ <Steps>
24
+
25
+ <Step>
26
+ ### Declare model + agent
27
+
28
+ ```typescript title="src/core/ai.ts"
29
+ import { ai } from "okengine";
30
+
31
+ export const smart = ai.model("smart", {
32
+ provider: "openrouter",
33
+ model: "openrouter/free",
34
+ apiKey: process.env.OPENROUTER_API_KEY,
35
+ });
36
+
37
+ export const supportAgent = ai.agent("support.assistant", {
38
+ model: "smart",
39
+ tools: ["docs.search", "tickets.create"],
40
+ maxSteps: 5,
41
+ budget: { maxCostPerRun: 0.1 },
42
+ });
43
+ ```
44
+
45
+ </Step>
46
+
47
+ <Step>
48
+ ### Run from a Flow
49
+
50
+ ```typescript title="src/flows/support/assist.ts"
51
+ import { on, flow, http } from "okengine";
52
+ import { z } from "zod";
53
+ import { supportAgent } from "@/core/ai";
54
+ import { member } from "@/core/gate";
55
+
56
+ export const assist = on(
57
+ http
58
+ .post({
59
+ in: z.object({ query: z.string().min(1) }),
60
+ })
61
+ .gate(member),
62
+ flow({
63
+ do: async ({ query }, fx) => {
64
+ return await fx.run(supportAgent, {
65
+ message: `Help the member: ${query}`,
66
+ });
67
+ },
68
+ }),
69
+ );
70
+ ```
71
+
72
+ Runtime records the agent name under `asks`. Prefer declaring `effects: { asks: ["support.assistant"] }`
73
+ when inference does not see `fx.run`.
74
+
75
+ </Step>
76
+
77
+ <Step>
78
+ ### Bound termination
79
+
80
+ Default `maxSteps` is **6** when omitted. Hitting the step cap ends the loop; exceeding
81
+ `budget.maxCostPerRun` throws `AiBudgetExceededError`:
82
+ `ai: agent "…" exceeded maxCostPerRun N`.
83
+
84
+ </Step>
85
+
86
+ </Steps>
87
+
88
+ ## Progressive Patterns
89
+
90
+ <Tabs items={["Flow tools", "MCP tools", "Ask tools", "Budget"]}>
91
+
92
+ <Tab value="Flow tools">
93
+
94
+ String names or Flow handles — same capability path as `fx.call`:
95
+
96
+ ```typescript
97
+ import { searchDocs } from "@/flows/docs/search";
98
+ import { createTicket } from "@/flows/tickets/create";
99
+
100
+ export const supportAgent = ai.agent("support.assistant", {
101
+ model: smart,
102
+ tools: [searchDocs, createTicket],
103
+ maxSteps: 8,
104
+ });
105
+ ```
106
+
107
+ </Tab>
108
+
109
+ <Tab value="MCP tools">
110
+
111
+ Outbound MCP refs join the same bag (`mcp:<server>/<tool>`):
112
+
113
+ ```typescript
114
+ const github = ai.mcpServer("github", {
115
+ url: "https://mcp.example/github",
116
+ auth: { bearer: vault.secret("GITHUB_MCP_TOKEN") },
117
+ tools: ["create_issue"],
118
+ });
119
+
120
+ export const planner = ai.agent("planner", {
121
+ model: "smart",
122
+ tools: ["tasks.list", github.tool("create_issue")],
123
+ maxSteps: 8,
124
+ budget: { maxCostPerRun: 0.25 },
125
+ });
126
+ ```
127
+
128
+ See [MCP](/docs/elements/ai/mcp).
129
+
130
+ </Tab>
131
+
132
+ <Tab value="Ask tools">
133
+
134
+ One-shot tool loop on `fx.ask` without a named agent:
135
+
136
+ ```typescript
137
+ await fx.ask(triage, input, {
138
+ tools: ["docs.search"],
139
+ maxSteps: 3,
140
+ });
141
+ ```
142
+
143
+ </Tab>
144
+
145
+ <Tab value="Budget">
146
+
147
+ Run cost is on `budget`, not a top-level `maxCostPerRun` field:
148
+
149
+ ```typescript
150
+ ai.agent("planner", {
151
+ tools: ["tasks.list", "tasks.create"],
152
+ budget: { maxCostPerRun: 0.25, maxCostPerCall: 0.05 },
153
+ });
154
+ ```
155
+
156
+ </Tab>
157
+
158
+ </Tabs>
159
+
160
+ ## Options
161
+
162
+ | Option | Type | Default | Meaning |
163
+ | ---------- | ------------------------------------- | ----------- | ---------------------------- |
164
+ | `model` | `AiModelDecl` \| `string` | first model | Logical binding for the loop |
165
+ | `tools` | Flow / MCP refs | `[]` | Callable via `fx.call` |
166
+ | `maxSteps` | `number` | `6` | Hard cap on tool rounds |
167
+ | `budget` | `{ maxCostPerCall?, maxCostPerRun? }` | — | Cost contracts for the run |
168
+
169
+ ## `fx.run` input
170
+
171
+ Pass a string or `{ message: string }` (and any extra fields your tools need in context). The
172
+ agent declaration does **not** take Zod `in` / `out` — validate on the surrounding Flow.
173
+
174
+ ```typescript
175
+ await fx.run(supportAgent, "Summarize open tickets");
176
+ await fx.run(supportAgent, { message: "Summarize open tickets" });
177
+ ```
178
+
179
+ ## Agents vs ask-with-tools
180
+
181
+ | Surface | When |
182
+ | ------------------------------ | -------------------------------------------- |
183
+ | `ai.agent` + `fx.run` | Reusable tool bag, shared step/budget policy |
184
+ | `fx.ask(prompt, …, { tools })` | One prompt, occasional tools |
185
+
186
+ Both default `maxSteps` to `6`. Denied or unknown tools surface as
187
+ `ai: all tool calls denied for prompt "…"` / `ai: model requested unknown tool "…"`.
188
+
189
+ ## Troubleshooting
190
+
191
+ <Accordions>
192
+
193
+ <Accordion title='ai: unknown agent "…"'>
194
+ `fx.run` named an agent that was never declared, or the declaring module was not imported before
195
+ `oke()`.
196
+ </Accordion>
197
+
198
+ <Accordion title='ai: agent "…" exceeded maxCostPerRun'>
199
+ `AiBudgetExceededError` — raise `budget.maxCostPerRun`, lower `maxSteps`, or shrink tools.
200
+ </Accordion>
201
+
202
+ <Accordion title='ai: model requested unknown tool "…"'>
203
+ The model emitted a tool name outside the declared `tools` bag. Align names with Flow / MCP refs,
204
+ or tighten instructions in the user `message`.
205
+ </Accordion>
206
+
207
+ <Accordion title="OKE1005 on agent runs">
208
+ Runtime gates `fx.run` as an ask of the agent name. List `effects: { asks: ["support.assistant"] }`
209
+ when the compiler does not infer `fx.run`.
210
+ </Accordion>
211
+
212
+ </Accordions>
213
+
214
+ ## Learn more
215
+
216
+ - [Prompts](/docs/elements/ai/prompts) — `fx.ask` and ask-time tools
217
+ - [MCP](/docs/elements/ai/mcp) — inbound tools and outbound servers
218
+ - [Flow](/docs/elements/flow) — tools are ordinary Flows
219
+ - [AI](/docs/elements/ai) — guardrails figure and drivers
220
+
221
+ ## Next
222
+
223
+ <Cards>
224
+ <Card
225
+ title="MCP"
226
+ description="Expose and consume Model Context Protocol tools."
227
+ href="/docs/elements/ai/mcp"
228
+ />
229
+ <Card
230
+ title="Prompts"
231
+ description="Versioned fx.ask artifacts."
232
+ href="/docs/elements/ai/prompts"
233
+ />
234
+ <Card title="AI" description="Element overview." href="/docs/elements/ai" />
235
+ </Cards>
@@ -0,0 +1,342 @@
1
+ ---
2
+ title: "Overview"
3
+ description: "Machine intelligence — bind models, ask versioned prompts, run bounded agents, embed into store.index, and connect MCP."
4
+ icon: "Sparkles"
5
+ source: "docs/spec/unified-theory.md"
6
+ ---
7
+
8
+ AI is how your backend **calls a model as a declared effect**. Ticket triage, a weekly
9
+ summary, a planner that tools your own Flows — each ask is a named prompt or agent with
10
+ budgets, not an SDK call buried in `do`.
11
+
12
+ For developers wiring OpenRouter or any OpenAI-compatible `/v1` endpoint — bind a model,
13
+ mint a prompt, ask through `fx`.
14
+
15
+ <Callout title="The one rule">
16
+ Declare `ai.model` → `model.prompt` (or `ai.agent` / `ai.embed`), then call through `fx.ask` /
17
+ `fx.run` / `fx.embed`. There is no top-level `ai.prompt`. Budgets and `maxSteps` are contracts;
18
+ PII to a third-party model needs explicit `allowPii`.
19
+ </Callout>
20
+
21
+ <AiBlocks />
22
+
23
+ ## Smallest Example
24
+
25
+ <Steps>
26
+
27
+ <Step>
28
+ ### Bind a model and mint a prompt
29
+
30
+ ```typescript title="src/core/ai.ts"
31
+ import { ai } from "okengine";
32
+ import { z } from "zod";
33
+
34
+ export const smart = ai.model("smart", {
35
+ provider: "openrouter",
36
+ model: "openrouter/free",
37
+ apiKey: process.env.OPENROUTER_API_KEY,
38
+ });
39
+
40
+ export const triage = smart.prompt("ticket-triage", {
41
+ version: 1,
42
+ budget: { maxCostPerCall: 0.02 },
43
+ out: z.object({
44
+ category: z.enum(["billing", "technical", "other"]),
45
+ urgency: z.enum(["low", "medium", "high"]),
46
+ }),
47
+ });
48
+ ```
49
+
50
+ Import this module before `oke()` so registries adopt the decls.
51
+
52
+ </Step>
53
+
54
+ <Step>
55
+ ### Ask from a Flow
56
+
57
+ ```typescript title="src/flows/support/triage.ts"
58
+ import { on, flow, http } from "okengine";
59
+ import { z } from "zod";
60
+ import { triage } from "@/core/ai";
61
+
62
+ export const classify = on(
63
+ http.post({
64
+ in: z.object({ message: z.string().min(1) }),
65
+ }),
66
+ flow({
67
+ do: async ({ message }, fx) => {
68
+ return await fx.ask(triage, { message });
69
+ },
70
+ }),
71
+ );
72
+ ```
73
+
74
+ The compiler stamps `asks: ["ticket-triage"]` on the Flow’s effects.
75
+
76
+ </Step>
77
+
78
+ <Step>
79
+ ### Call the endpoint
80
+
81
+ ```bash
82
+ curl -X POST http://localhost:6530/support/triage \
83
+ -H "accept: application/json" \
84
+ -H "content-type: application/json" \
85
+ -d '{"message":"Invoice double-charged last week"}'
86
+ ```
87
+
88
+ With `out` set, the model must return JSON matching the schema or the ask throws
89
+ `AiSchemaValidationError`.
90
+
91
+ </Step>
92
+
93
+ </Steps>
94
+
95
+ ## Progressive Patterns
96
+
97
+ From a bare ask to fallback models, tools on ask, and a bounded agent:
98
+
99
+ <Tabs items={["Minimal", "via", "Tools", "Agent"]}>
100
+
101
+ <Tab value="Minimal">
102
+
103
+ Prompt handle + input — model comes from the parent `ai.model`:
104
+
105
+ ```typescript
106
+ const result = await fx.ask(triage, { message: "Cannot reset password" });
107
+ ```
108
+
109
+ </Tab>
110
+
111
+ <Tab value="via">
112
+
113
+ Ordered recovery across logical bindings. Each name opens its **own** client — keys and
114
+ `baseUrl` never mix:
115
+
116
+ ```typescript
117
+ export const triage = smart.prompt("ticket-triage", {
118
+ version: 1,
119
+ via: ["smart", "local"],
120
+ out: z.object({ category: z.string() }),
121
+ });
122
+ ```
123
+
124
+ Override per call with `fx.ask(triage, input, { via: ["local"] })`.
125
+
126
+ </Tab>
127
+
128
+ <Tab value="Tools">
129
+
130
+ Offer Flows as tools on a single ask. Each invocation goes through `fx.call`
131
+ (default `maxSteps: 6`):
132
+
133
+ ```typescript
134
+ await fx.ask(
135
+ triage,
136
+ { message },
137
+ {
138
+ tools: [searchDocs, createTicket],
139
+ maxSteps: 4,
140
+ },
141
+ );
142
+ ```
143
+
144
+ **Consequence:** undeclared tools fail capability checks the same way as `fx.call`.
145
+
146
+ </Tab>
147
+
148
+ <Tab value="Agent">
149
+
150
+ Multi-step loop with a declared tool bag and run budget:
151
+
152
+ ```typescript
153
+ export const supportAgent = ai.agent("support.assistant", {
154
+ model: "smart",
155
+ tools: ["docs.search", "tickets.create"],
156
+ maxSteps: 5,
157
+ budget: { maxCostPerRun: 0.1 },
158
+ });
159
+
160
+ // In a Flow:
161
+ return await fx.run(supportAgent, { message: "Help with billing" });
162
+ ```
163
+
164
+ </Tab>
165
+
166
+ </Tabs>
167
+
168
+ ## Declaration Reference
169
+
170
+ | Declaration | Signature | Purpose |
171
+ | -------------- | ------------------------------ | --------------------------------------------- |
172
+ | `ai.model` | `ai.model(name, options?)` | Logical binding (provider / wire model / key) |
173
+ | `model.prompt` | `model.prompt(name, options?)` | Versioned prompt on that binding |
174
+ | `ai.agent` | `ai.agent(name, options?)` | Bounded tool-calling agent |
175
+ | `ai.embed` | `ai.embed(name, options?)` | Embedding pipeline into `store.index` |
176
+ | `ai.mcpServer` | `ai.mcpServer(name, options)` | Outbound MCP client (allowlisted tools) |
177
+
178
+ There is **no** `ai.prompt(...)` — mint prompts only via `model.prompt`.
179
+
180
+ ## `fx` surface
181
+
182
+ | Method | Capability | Meaning |
183
+ | -------------------------------- | ------------------- | ------------------------------------------------ |
184
+ | `fx.ask(prompt, input?, opts?)` | `asks` | Complete a versioned prompt (optional tool loop) |
185
+ | `fx.run(agent, input?)` | `asks` (agent name) | Run a declared agent |
186
+ | `fx.stream(model, opts?)` | `asks` | Token stream from a model binding |
187
+ | `fx.embed(model, text)` | `embeds` | Return a vector (does not write an index) |
188
+ | `fx.search(embed, query, opts?)` | `reads` | Similarity search over an embed / index |
189
+
190
+ ### `fx.ask` options
191
+
192
+ | Option | Type | Default | Meaning |
193
+ | ---------- | ------------- | ------------------------ | ------------------------------ |
194
+ | `via` | refs | prompt `via` / `[model]` | Recovery chain for this call |
195
+ | `timeout` | `"30s"` \| ms | prompt `timeout` | Per-call deadline |
196
+ | `tools` | Flow refs | — | Offered as tools via `fx.call` |
197
+ | `maxSteps` | `number` | `6` | Cap on tool rounds |
198
+
199
+ Undeclared ask → **OKE1005** `UNDECLARED_ASK`. Undeclared embed → **OKE1009**.
200
+
201
+ ## Guardrails
202
+
203
+ Budgets, version pins, step limits, and PII egress are contracts — not guidelines:
204
+
205
+ <AiGuardrails />
206
+
207
+ ### PII egress
208
+
209
+ Sending a `.pii()` field to a **third-party** provider fails the build unless the Flow
210
+ declares `allowPii: true` (or `pii: "allow"`). `mock`, `local`, and `openai-compatible` are
211
+ not third-party egress.
212
+
213
+ <AiPiiEgress />
214
+
215
+ ```typescript
216
+ flow({
217
+ allowPii: true,
218
+ do: async (input, fx) => fx.ask(triage, { email: input.email }),
219
+ });
220
+ ```
221
+
222
+ ## Per-environment drivers
223
+
224
+ `AiDriverId`: `mock` · `anthropic` · `openai-compatible` · `bedrock` · `vertex`.
225
+
226
+ Boot implements `mock`, `anthropic`, and `openai-compatible`. `bedrock` / `vertex` are
227
+ reserved and throw until implemented. Dev/test fall back to **`mock`** when unset — **prod
228
+ must declare** `drivers.ai`.
229
+
230
+ ```typescript title="oke.config.ts"
231
+ import { defineConfig } from "okengine/config";
232
+
233
+ export default defineConfig({
234
+ drivers: {
235
+ ai: {
236
+ dev: "openai-compatible",
237
+ test: "mock",
238
+ prod: "openai-compatible",
239
+ },
240
+ },
241
+ });
242
+ ```
243
+
244
+ | Driver | Runs as | Best for |
245
+ | ------------------- | ------------------- | ---------------------------------------------- |
246
+ | `mock` | In-process stub | Tests, CI, no network |
247
+ | `openai-compatible` | OpenAI HTTP API | OpenRouter, cloud registries, any `/v1` server |
248
+ | `anthropic` | Native Messages API | Production Claude + reliable tools |
249
+
250
+ Env knobs: `OKE_AI_DRIVER`, `OKE_AI_URL` / `OPENAI_BASE_URL`, provider API keys.
251
+ Compose does not pin inference — BYO URL + keys, or [OpenRouter](/docs/recipes/openrouter).
252
+
253
+ ## The Capabilities of AI
254
+
255
+ <Cards>
256
+ <Card
257
+ title="Models"
258
+ description="Verified providers, limited-compatibility caveats, cloud and BYO bindings."
259
+ href="/docs/elements/ai/models"
260
+ />
261
+ <Card
262
+ title="Prompts"
263
+ description="Versioned artifacts, via chains, budgets, out-schema validation."
264
+ href="/docs/elements/ai/prompts"
265
+ />
266
+ <Card
267
+ title="Agents"
268
+ description="Tool bags are Flows — maxSteps and maxCostPerRun bound the loop."
269
+ href="/docs/elements/ai/agents"
270
+ />
271
+ <Card
272
+ title="Model Context Protocol"
273
+ description="Expose Flows as MCP tools; consume external servers via ai.mcpServer."
274
+ href="/docs/elements/ai/mcp"
275
+ />
276
+ </Cards>
277
+
278
+ ## Troubleshooting
279
+
280
+ <Accordions>
281
+
282
+ <Accordion title='ai: unknown prompt "…"'>
283
+ `fx.ask` named a prompt that was never minted with `model.prompt`, or the declaring module was not
284
+ imported before `oke()`.
285
+ </Accordion>
286
+
287
+ <Accordion title="OKE1005 — UNDECLARED_ASK">
288
+ Cause: `Flow "{flow}" asks "{resource}" without declaring it.` Touch the prompt handle
289
+ inside `do` (inference) or list `effects: { asks: ["ticket-triage"] }`.
290
+ </Accordion>
291
+
292
+ <Accordion title="AiSchemaValidationError / AiSchemaInvalid">
293
+ Cause: `ai: schema validation failed for prompt "…"@N: …` The model reply did not match `out`. Fix
294
+ the schema, the input, or the model — there is no automatic “schema correction” retry.
295
+ </Accordion>
296
+
297
+ <Accordion title="AiBudgetExceededError">
298
+ Cause: `ai: prompt "…" exceeded maxCostPerCall N` or `ai: agent "…" exceeded maxCostPerRun N`.
299
+ Raise the budget or shrink the work.
300
+ </Accordion>
301
+
302
+ <Accordion title="build failed: … without allowPii">
303
+ Cause: `build failed: flow "…" sends pii field(s) […] to a third-party model without allowPii`.
304
+ Set `allowPii: true` on the Flow, or keep the ask on `mock` / `local` / `openai-compatible`.
305
+ </Accordion>
306
+
307
+ <Accordion title="oke boot: unknown AI driver / reserved">
308
+ Prod must pin a real `drivers.ai` id. `bedrock` and `vertex` throw `oke boot: AI driver "…" is
309
+ reserved but not implemented yet`.
310
+ </Accordion>
311
+
312
+ </Accordions>
313
+
314
+ ## Learn more
315
+
316
+ - [Models](/docs/elements/ai/models) — provider registry and `baseUrl` rules
317
+ - [Prompts](/docs/elements/ai/prompts) — `via`, budgets, versions, evals
318
+ - [Agents](/docs/elements/ai/agents) — `fx.run`, tools, `maxSteps`
319
+ - [MCP](/docs/elements/ai/mcp) — inbound `mcp.tool` and outbound `ai.mcpServer`
320
+ - [OpenRouter](/docs/recipes/openrouter) — zero-Docker cloud path
321
+ - [fx](/docs/reference/fx) — `fx.ask` / `fx.run` / `fx.embed`
322
+ - [Errors](/docs/reference/errors) — OKE1005 · OKE1009
323
+
324
+ ## Next
325
+
326
+ <Cards>
327
+ <Card
328
+ title="Models"
329
+ description="Bind providers and wire model ids."
330
+ href="/docs/elements/ai/models"
331
+ />
332
+ <Card
333
+ title="Channel Element"
334
+ description="Reach humans with email, SMS, WhatsApp, and push."
335
+ href="/docs/elements/channel"
336
+ />
337
+ <Card
338
+ title="The Model"
339
+ description="Eight elements overview."
340
+ href="/docs/understand/the-architecture"
341
+ />
342
+ </Cards>