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,451 @@
1
+ ---
2
+ title: "Calling"
3
+ description: "createClient forms, REST vs RPC, options, result envelopes, store resources, and remote types."
4
+ icon: "Braces"
5
+ source: "docs/spec/unified-theory.md"
6
+ ---
7
+
8
+ `createClient` builds a typed proxy over your adopted Flows. HTTP triggers go out as REST from
9
+ `$routes`; untriggered Flows fall back to RPC. Every call returns `{ data, error }` — never a
10
+ thrown domain failure.
11
+
12
+ For developers wiring a storefront, mobile app, or partner service to an okengine backend (port
13
+ **6530**).
14
+
15
+ <Callout title="The one rule">
16
+ Treat every call as a result envelope: `{ data, error }`. Switch on `error.code`. Only transport
17
+ / protocol problems use `code: "TransportError"`.
18
+ </Callout>
19
+
20
+ ## Smallest Example
21
+
22
+ <Steps>
23
+
24
+ <Step>
25
+ ### Create the client from the app
26
+
27
+ ```typescript title="web/src/api.ts"
28
+ import { createClient } from "okengine/client";
29
+ import { vault } from "okengine/vault";
30
+ import { app } from "../../src/app";
31
+
32
+ export const api = createClient(app, vault.env("PUBLIC_API_URL") ?? "");
33
+ ```
34
+
35
+ </Step>
36
+
37
+ <Step>
38
+ ### Confirm a booking and narrow the result
39
+
40
+ ```typescript
41
+ const { data, error } = await api.bookings.get({ id: "bkg_7f3a" });
42
+
43
+ if (error) {
44
+ // show “booking not found” or a network banner
45
+ return;
46
+ }
47
+
48
+ renderConfirmation(data.confirmationCode, data.seats);
49
+ ```
50
+
51
+ Envelope:
52
+
53
+ ```json
54
+ {
55
+ "data": {
56
+ "id": "bkg_7f3a",
57
+ "confirmationCode": "SK-4812",
58
+ "seats": 2,
59
+ "status": "confirmed"
60
+ },
61
+ "error": null
62
+ }
63
+ ```
64
+
65
+ </Step>
66
+
67
+ </Steps>
68
+
69
+ ## Base URL (Vault + env)
70
+
71
+ Do not paste origins into source. Declare the public API origin as Vault config, then read it from
72
+ env in each runtime:
73
+
74
+ ```typescript title="src/core/vault.ts"
75
+ import { vault } from "okengine/vault";
76
+ import { z } from "zod";
77
+
78
+ export const publicApiUrl = vault.config("PUBLIC_API_URL", {
79
+ description: "Browser-facing API origin",
80
+ schema: z.string().url(),
81
+ });
82
+ ```
83
+
84
+ | Runtime | Base URL for `createClient` |
85
+ | ------------------------------------------ | --------------------------------------------------------------- |
86
+ | Browser / Bun (create-oke web) | `vault.env("PUBLIC_API_URL") ?? ""` — empty = same-origin proxy |
87
+ | Node / worker / CLI | `vault.env.required("PUBLIC_API_URL")` |
88
+ | Separate storefront after `oke client add` | Same `vault.env("PUBLIC_API_URL") ?? ""` |
89
+
90
+ Set `PUBLIC_API_URL` via environment or `oke vault set`. Prefer `vault.env` over raw
91
+ `process.env` — same helpers as the rest of the measure. See
92
+ [Vault · Config](/docs/elements/vault/config).
93
+
94
+ ## Progressive Patterns
95
+
96
+ From a simple read to typed domain failures and transport errors:
97
+
98
+ <Tabs items={["Minimal", "Narrow", "Failures", "Transport", "Binary"]}>
99
+
100
+ <Tab value="Minimal">
101
+
102
+ ```typescript
103
+ const { data, error } = await api.bookings.get({ id: "bkg_7f3a" });
104
+ if (error) return;
105
+ showSeatMap(data.seats);
106
+ ```
107
+
108
+ </Tab>
109
+
110
+ <Tab value="Narrow">
111
+
112
+ ```typescript
113
+ import { isOk } from "okengine/client";
114
+
115
+ const result = await api.orders.get({ id: "ord_9c2e" });
116
+
117
+ if (isOk(result)) {
118
+ result.data.trackingNumber;
119
+ result.data.eta;
120
+ }
121
+ ```
122
+
123
+ </Tab>
124
+
125
+ <Tab value="Failures">
126
+
127
+ ```typescript
128
+ import { isOk, isErrorCode } from "okengine/client";
129
+
130
+ const result = await api.bookings.create({
131
+ flightId: "SK481",
132
+ seats: 2,
133
+ cabin: "economy",
134
+ });
135
+
136
+ if (isOk(result)) {
137
+ result.data.confirmationCode;
138
+ } else if (result.error.code === "FlightFull") {
139
+ offerWaitlist(result.error.data.seatsLeft);
140
+ } else if (isErrorCode(result.error, "NotFound")) {
141
+ // shared helper narrowing
142
+ }
143
+ ```
144
+
145
+ Prefer `error?.code === "FlightFull"` for inference; use `isErrorCode` in shared helpers.
146
+
147
+ </Tab>
148
+
149
+ <Tab value="Transport">
150
+
151
+ ```typescript
152
+ import { isTransportError } from "okengine/client";
153
+
154
+ const result = await api.orders.list({ limit: 20, status: "shipped" });
155
+
156
+ if (result.error && isTransportError(result.error)) {
157
+ showOfflineBanner(result.error.data.message);
158
+ // optional: result.error.data.status
159
+ }
160
+ ```
161
+
162
+ Network failure, abort (`timeout`), non-JSON body, or HTTP status without a `{ data, error }`
163
+ envelope — never a declared Flow code.
164
+
165
+ </Tab>
166
+
167
+ <Tab value="Binary">
168
+
169
+ ```typescript
170
+ const { data, error } = await api.files.download({ id: "file_1" }, { response: "blob" });
171
+ if (error || !data) return;
172
+ a.href = URL.createObjectURL(data);
173
+ a.download = "report.pdf";
174
+ ```
175
+
176
+ Same `{ data, error }` envelope; `{ response: "arrayBuffer" }` for raw bytes. Default remains
177
+ JSON envelopes.
178
+
179
+ </Tab>
180
+
181
+ </Tabs>
182
+
183
+ ## `createClient` forms
184
+
185
+ | Form | Types from | Wire |
186
+ | ------------------------------- | -------------------------------------- | ------------------------------------------------ |
187
+ | `createClient(app, url, opts?)` | `typeof app` | REST from `app.$routes`; untriggered flows → RPC |
188
+ | `createClient<App>(url, opts?)` | Explicit `App` type | RPC unless `opts.$routes` or `opts.routes` |
189
+ | `createClient(url, opts?)` | Ambient `Register` (`oke-client.d.ts`) | Same — pass routes for REST |
190
+
191
+ `url` is the app origin from `vault.env("PUBLIC_API_URL")` — empty string means same-origin.
192
+ See [Base URL](#base-url-vault--env).
193
+
194
+ **Consequence:** `createClient<App>(url)` alone types the proxy but still posts
195
+ `POST /_oke/{unit}/{flow}` until you pass the app value, `$routes`, or `routes`.
196
+
197
+ ## REST vs RPC
198
+
199
+ | Situation | Request |
200
+ | ----------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
201
+ | HTTP trigger with method + path on `$routes` | That method and path (`:id` filled from input; leftover fields → query on GET/HEAD, JSON body otherwise). QUERY always sends JSON (`{}` when only path params) |
202
+ | Adopted flow with no HTTP trigger | `POST {base}/_oke/{unit}/{flow}` with JSON body |
203
+ | Incomplete proxy path (`api.bookings()` with no flow) | Result error: `Incomplete path: api.bookings(…)` |
204
+
205
+ ```typescript
206
+ // REST — method/path from the bound HTTP trigger (file tree or explicit)
207
+ await api.bookings.get({ id: "bkg_7f3a" }); // GET /bookings/bkg_7f3a
208
+
209
+ // RPC — untriggered flow named bookings.manifest (internal tally)
210
+ await api.bookings.manifest({ flightId: "SK481" }); // POST /_oke/bookings/manifest
211
+ ```
212
+
213
+ Full file-tree rules: [Routing](/docs/elements/flow/routing).
214
+
215
+ ## How input becomes a request
216
+
217
+ Before the wire call, the client maps `input` onto the REST template or the RPC body:
218
+
219
+ 1. **Path params** — `:id` (and friends) filled from matching input keys.
220
+ 2. **Leftover fields** — query string on GET/HEAD; JSON body otherwise.
221
+ 3. **QUERY** — always JSON (`{}` when only path params remain).
222
+ 4. **RPC** — whole input as JSON on `POST /_oke/{unit}/{flow}`.
223
+
224
+ ```typescript
225
+ await api.orders.get({ id: "ord_9c2e" });
226
+ // GET /orders/ord_9c2e
227
+
228
+ await api.orders.list({ limit: 20, q: "stockholm" });
229
+ // GET /orders?limit=20&q=stockholm (when list is GET on $routes)
230
+
231
+ await api.bookings.create({ flightId: "SK481", seats: 2 });
232
+ // POST /bookings with JSON body
233
+ ```
234
+
235
+ ## Call shapes
236
+
237
+ <Tabs items={["unit.flow", "List pager", "for await", "Empty 204"]}>
238
+
239
+ <Tab value="unit.flow">
240
+
241
+ ```typescript
242
+ const { data, error } = await api.orders.get({ id: "ord_9c2e" });
243
+ if (error) return;
244
+ data.trackingNumber;
245
+ ```
246
+
247
+ </Tab>
248
+
249
+ <Tab value="List pager">
250
+
251
+ ```typescript
252
+ const page = await api.orders.list({ limit: 20, status: "open" });
253
+ const more = await page.next();
254
+
255
+ // meta.next / meta.prev are { cursor } bags — spread them, or use page.next()
256
+ ```
257
+
258
+ TanStack `useInfiniteQuery` takes the bag, not the methods:
259
+
260
+ ```typescript
261
+ useInfiniteQuery({
262
+ queryKey: ["orders", status],
263
+ queryFn: ({ pageParam }) => api.orders.list({ limit: 20, status, ...pageParam }),
264
+ initialPageParam: {} as { cursor?: string },
265
+ getNextPageParam: (last) => last.meta.next ?? undefined,
266
+ getPreviousPageParam: (last) => last.meta.prev ?? undefined,
267
+ });
268
+ ```
269
+
270
+ </Tab>
271
+
272
+ <Tab value="for await">
273
+
274
+ ```typescript
275
+ for await (const page of api.orders.list({ limit: 20, status: "shipped" })) {
276
+ for (const order of page.data) renderRow(order);
277
+ }
278
+ ```
279
+
280
+ </Tab>
281
+
282
+ <Tab value="Empty 204">
283
+
284
+ ```typescript
285
+ await api.orders.remove({ id: "ord_9c2e" }); // DELETE → 204, data undefined
286
+ ```
287
+
288
+ </Tab>
289
+
290
+ </Tabs>
291
+
292
+ ## Resources
293
+
294
+ Mount a resource, adopt the returned ops, then call the five Flows like any other:
295
+
296
+ ```typescript
297
+ const ordersR = store.resource(db, orders, {/* in, out, list */});
298
+ const mounted = on(http.resource("/orders", ordersR.all()).gate(member));
299
+ // .adopt({ orders: mounted }) →
300
+ const page = await api.orders.list({ limit: 20, status: "open" });
301
+ await api.orders.get({ id: "ord_9c2e" }); // GET /orders/:id — NotFound when missing
302
+ await api.orders.remove({ id: "ord_9c2e" }); // DELETE → 204
303
+ ```
304
+
305
+ See [Store](/docs/elements/store) for the list query language. Handwritten lists use
306
+ `fx.json.withQuery(rows, input)` for the same envelope. Auth posture:
307
+ [Gate](/docs/elements/gate). Live mounts: [Live](/docs/client/live).
308
+
309
+ ## Options
310
+
311
+ | Option | Type | Default | Meaning |
312
+ | --------------- | ---------------------------------------------- | ------------------ | -------------------------------------------------------------- |
313
+ | `fetch` | `(input, init?) => Promise<Response>` | `globalThis.fetch` | Inject a fetch implementation |
314
+ | `headers` | `Record<string, string>` \| pairs \| `() => …` | — | Static headers, or a getter per request |
315
+ | `timeout` | `number` (ms) | — | Abort after this many milliseconds |
316
+ | `retry.retries` | `number` | `0` | Extra attempts after the first (network / 5xx) |
317
+ | `retry.delay` | `number` (ms) | `50` | Initial backoff delay |
318
+ | `retry.backoff` | `number` | `2` | Multiplier after each retry |
319
+ | `auth.getToken` | `() => string \| null \| …` | — | Bearer access token (or null) — see [Auth](/docs/client/auth) |
320
+ | `auth.refresh` | `() => Promise<string \| null \| …>` | — | Runs once on HTTP 401, then the request retries |
321
+ | `$routes` | `ClientRouteMap` | — | Runtime map from `app.$routes` (REST when method+path present) |
322
+ | `routes` | `Record<"unit.flow", { method, path }>` | — | Flat REST table; wins over flattening `$routes` |
323
+
324
+ ## Result envelopes
325
+
326
+ Success may include optional top-level `meta` (for example pagination). Declared flow errors and
327
+ transport failures share the failure arm:
328
+
329
+ ```typescript
330
+ import { isOk, isFail, isErrorCode, isTransportError } from "okengine/client";
331
+
332
+ const result = await api.bookings.create({ flightId: "SK481", seats: 2 });
333
+
334
+ if (isOk(result)) {
335
+ result.data.confirmationCode;
336
+ } else if (result.error.code === "FlightFull") {
337
+ result.error.data.seatsLeft;
338
+ } else if (isTransportError(result.error)) {
339
+ result.error.data.message;
340
+ }
341
+
342
+ isFail(result); // true when error !== null
343
+ ```
344
+
345
+ ## Remote types
346
+
347
+ `oke dev` regenerates `oke-client.d.ts` from `GET /_oke/client.json`. A separate storefront repo —
348
+ pass the origin from Vault / env (never a hardcoded host in source):
349
+
350
+ ```bash
351
+ oke client add "$PUBLIC_API_URL"
352
+ oke client add "$PUBLIC_API_URL" --out ./types/oke-client.d.ts
353
+ # also writes oke-client.routes.ts (or types/oke-client.routes.ts)
354
+ ```
355
+
356
+ ```typescript
357
+ import { createClient } from "okengine/client";
358
+ import { routes } from "./oke-client.routes.ts";
359
+
360
+ const api = createClient(import.meta.env.PUBLIC_API_URL ?? "", { $routes: routes });
361
+ ```
362
+
363
+ Ambient `.d.ts` types `in` / `out` / live / stream stamps. The routes module supplies wire REST.
364
+
365
+ create-oke starters ship `web/`: Vite proxies Flow paths plus `/auth` and `/_oke` to the app.
366
+ Leave `PUBLIC_API_URL` unset in local web so `createClient("")` stays same-origin.
367
+
368
+ CLI details: [CLI Reference](/docs/reference/cli).
369
+
370
+ ## Exports
371
+
372
+ | Export | Kind | Role |
373
+ | ----------------------------------------- | --------- | --------------------------------------------------- |
374
+ | `createClient` | function | Typed proxy `api.unit.flow(input?)` plus `api.live` |
375
+ | `flattenRoutes` | function | `$routes` → flat `unit.flow` REST table |
376
+ | `createTransport` | function | Low-level HTTP transport (timeout / retry / auth) |
377
+ | `isOk` / `isFail` | function | Envelope predicates |
378
+ | `isErrorCode` / `isTransportError` | function | Error narrowing |
379
+ | `Client`, `ClientCall`, `ClientResult`, … | types | Contracts, `page.next()` / `for await` of `list()` |
380
+ | `Register` | interface | Module-augmentation slot for ambient App types |
381
+ | `AppOf` | type | Brand a bare route map as an App |
382
+
383
+ Budget: the `./client` export stays under the measured client-runtime cap (hard gate in CI).
384
+
385
+ ## Troubleshooting
386
+
387
+ <Accordions>
388
+
389
+ <Accordion title="api.bookings.get is not a function / type error">
390
+ Confirm the Flow is `export`ed from a generated unit (`import "@/flows/generated"` then
391
+ `oke({ name })`), or from a module you still `.adopt({ bookings })`.
392
+
393
+ Type `createClient` with that `App` (or ambient `Register` after `oke-client.d.ts` regenerates).
394
+ Restart `oke dev` after renaming exports.
395
+
396
+ </Accordion>
397
+
398
+ <Accordion title="Calls hit /_oke/… instead of my HTTP path">
399
+ Types alone do not choose REST. Pass `createClient(app, url)`, or
400
+ `createClient(url, { $routes: app.$routes })`, or an explicit `routes` map.
401
+ </Accordion>
402
+
403
+ <Accordion title='error.code is "TransportError"'>
404
+ Network failure, abort (`timeout`), non-JSON body, empty error response, or HTTP status without a
405
+ `{ data, error }` envelope. Declared flow codes (`NotFound`, `FlightFull`, …) never use this code.
406
+ Message text lives in `error.data.message`; HTTP status may appear as `error.data.status`.
407
+ </Accordion>
408
+
409
+ <Accordion title="Failed to fetch …/_oke/client.json">
410
+ `oke client add` needs a running app that serves the descriptor. Start the app (`oke dev` /
411
+ `oke start`), check the URL, then retry. Usage when the URL is missing:
412
+ `Usage: oke client add <url> [--out oke-client.d.ts]`.
413
+ </Accordion>
414
+
415
+ <Accordion title="Incomplete path: api.bookings(…)">
416
+ The proxy path stopped at a unit. Call a Flow: `api.bookings.get({id})`, not `api.bookings()`.
417
+ </Accordion>
418
+
419
+ </Accordions>
420
+
421
+ ## Learn more
422
+
423
+ - [Overview](/docs/client) — ClientLoop, Flows only
424
+ - [Auth](/docs/client/auth) — Bearer, refresh, denials
425
+ - [Live](/docs/client/live) — `api.live` and live queries
426
+ - [React](/docs/client/react) — hooks package
427
+ - [Vault · Config](/docs/elements/vault/config) — `PUBLIC_API_URL`, `vault.env`
428
+ - [Routing](/docs/elements/flow/routing) — `$routes` stamps
429
+ - [HTTP](/docs/elements/flow/http) — verbs and envelopes on the server
430
+ - [Errors](/docs/reference/errors) — framework codes vs failure values
431
+ - [CLI](/docs/reference/cli) — `oke client add`, `oke dev`
432
+
433
+ ## Next
434
+
435
+ <Cards>
436
+ <Card
437
+ title="Auth"
438
+ description="Sessions and gate denials on the client."
439
+ href="/docs/client/auth"
440
+ />
441
+ <Card
442
+ title="Live"
443
+ description="SSE subscribe and live resource queries."
444
+ href="/docs/client/live"
445
+ />
446
+ <Card
447
+ title="Routing"
448
+ description="Folders stamp HTTP paths and client units."
449
+ href="/docs/elements/flow/routing"
450
+ />
451
+ </Cards>
@@ -0,0 +1,209 @@
1
+ ---
2
+ title: "Overview"
3
+ description: "Typed caller for your Flows — createClient from okengine/client, zero codegen, errors as values."
4
+ icon: "Cable"
5
+ source: "docs/spec/unified-theory.md"
6
+ ---
7
+
8
+ `okengine/client` is how a browser, CLI, or another service calls your app's Flows. Import the
9
+ generated barrel, take `typeof app`, and `api.bookings.get({ id })` is fully typed — same contracts
10
+ the server already has, no separate schema project.
11
+
12
+ For developers consuming an okengine app from the outside — create the client, call a Flow, narrow
13
+ the envelope.
14
+
15
+ <Callout title="The one rule">
16
+ Treat every call as a result envelope: `{ data, error }`. Flow failures are values you switch on
17
+ (`error.code`); they are never thrown. Only transport / protocol problems use
18
+ `code: "TransportError"`.
19
+ </Callout>
20
+
21
+ ## Smallest Example
22
+
23
+ <Steps>
24
+
25
+ <Step>
26
+ ### Export `App` from the server
27
+
28
+ ```typescript title="src/app.ts"
29
+ import "@/core";
30
+ import "@/flows/generated";
31
+ import { oke } from "okengine/http";
32
+
33
+ export const app = oke({ name: "commerce" });
34
+ export type App = typeof app;
35
+ ```
36
+
37
+ `.adopt({ bookings })` is optional and additive when a unit is not already in the generated barrel.
38
+
39
+ </Step>
40
+
41
+ <Step>
42
+ ### Load a booking from the client
43
+
44
+ ```typescript title="web/src/api.ts"
45
+ import { createClient } from "okengine/client";
46
+ import { vault } from "okengine/vault";
47
+ import { app } from "../../src/app";
48
+
49
+ // Base URL via vault.env (empty = same-origin proxy in create-oke web)
50
+ const api = createClient(app, vault.env("PUBLIC_API_URL") ?? "");
51
+ const { data, error } = await api.bookings.get({ id: "bkg_7f3a" });
52
+
53
+ if (error) {
54
+ // TransportError or a declared flow code (NotFound, …)
55
+ return;
56
+ }
57
+
58
+ console.log(data.confirmationCode, data.seats);
59
+ ```
60
+
61
+ With `$routes` wired that is `GET /bookings/bkg_7f3a` on the backend (port **6530**):
62
+
63
+ ```json
64
+ {
65
+ "data": {
66
+ "id": "bkg_7f3a",
67
+ "confirmationCode": "SK-4812",
68
+ "seats": 2,
69
+ "status": "confirmed"
70
+ },
71
+ "error": null
72
+ }
73
+ ```
74
+
75
+ </Step>
76
+
77
+ </Steps>
78
+
79
+ ## Progressive Patterns
80
+
81
+ Same typed proxy from same-repo REST to a separate frontend repo:
82
+
83
+ <Tabs items={["Same-repo", "Type-only", "Ambient Register"]}>
84
+
85
+ <Tab value="Same-repo">
86
+
87
+ Pass the app value so HTTP triggers hit REST (method + path from `$routes`):
88
+
89
+ ```typescript
90
+ import { createClient } from "okengine/client";
91
+ import { vault } from "okengine/vault";
92
+ import { app } from "./app";
93
+
94
+ const api = createClient(app, vault.env("PUBLIC_API_URL") ?? "");
95
+ await api.bookings.get({ id: "bkg_7f3a" }); // GET /bookings/bkg_7f3a
96
+ ```
97
+
98
+ </Tab>
99
+
100
+ <Tab value="Type-only">
101
+
102
+ Types from an explicit `App` — still RPC until you pass routes:
103
+
104
+ ```typescript
105
+ import { createClient } from "okengine/client";
106
+ import { vault } from "okengine/vault";
107
+ import type { App } from "./app";
108
+ import { app } from "./app";
109
+
110
+ const api = createClient<App>(vault.env("PUBLIC_API_URL") ?? "", {
111
+ $routes: app.$routes,
112
+ });
113
+ ```
114
+
115
+ </Tab>
116
+
117
+ <Tab value="Ambient Register">
118
+
119
+ `oke dev` regenerates `oke-client.d.ts` from `GET /_oke/client.json`. A separate storefront repo
120
+ runs `oke client add` against your public API origin (from Vault / env):
121
+
122
+ ```typescript
123
+ import { createClient } from "okengine/client";
124
+ import { vault } from "okengine/vault";
125
+
126
+ const api = createClient(vault.env("PUBLIC_API_URL") ?? "");
127
+ // types from ambient Register in oke-client.d.ts
128
+ ```
129
+
130
+ Declare the origin on the server with [Vault · Config](/docs/elements/vault/config)
131
+ (`PUBLIC_API_URL`), then set it via env or `oke vault set`. Leave it unset in local web
132
+ dev so `createClient("")` stays same-origin behind the Vite proxy.
133
+
134
+ </Tab>
135
+
136
+ </Tabs>
137
+
138
+ <ClientLoop />
139
+
140
+ ## Flows only
141
+
142
+ <Callout title="Flows only">
143
+ The client calls **Flows**. Every other element runs on the server through `fx`. You reach its
144
+ outcome by calling a Flow that uses it — or by handling a gate denial on that call.
145
+ </Callout>
146
+
147
+ | Element | On the client | How |
148
+ | --------------------------------- | ------------- | ------------------------------------------------------------------------------------------ |
149
+ | [Flow](/docs/elements/flow) | Direct | `api.unit.flow(input)` — the only public surface |
150
+ | [Gate](/docs/elements/gate) | Indirect | Bearer via `auth`; denials as `Unauthorized` / `Forbidden` / `RateLimited` |
151
+ | [Store](/docs/elements/store) | Via Flows | `fx.store` inside Flows; `store.resource` + `on(http.resource…)` → five Flows on `$routes` |
152
+ | [Signal](/docs/elements/signal) | Live SSE | `api.live(signal, input?, { onEvent })` — HTTP GET, callback + unsubscribe |
153
+ | [Clock](/docs/elements/clock) | Via Flows | Schedules fire on the server — the client never ticks a clock |
154
+ | [Vault](/docs/elements/vault) | Via Flows | Secrets stay server-side; never ship them to the browser package |
155
+ | [Channel](/docs/elements/channel) | Via Flows | `fx.send` in a Flow — the client does not send email/SMS/push |
156
+ | [AI](/docs/elements/ai) | Via Flows | `fx.ask` / `fx.run` inside a Flow; the client gets that Flow’s `out` |
157
+
158
+ ## Pages
159
+
160
+ <Cards>
161
+ <Card
162
+ title="Calling"
163
+ description="createClient forms, REST vs RPC, options, envelopes, resources, remote types."
164
+ href="/docs/client/calling"
165
+ />
166
+ <Card
167
+ title="Auth"
168
+ description="memorySession, Bearer refresh, and gate denials as values."
169
+ href="/docs/client/auth"
170
+ />
171
+ <Card
172
+ title="Live"
173
+ description="api.live SSE, resume gaps, and live resource queries."
174
+ href="/docs/client/live"
175
+ />
176
+ <Card
177
+ title="React"
178
+ description="useSession, useLive, useLiveQuery from okengine/client-react."
179
+ href="/docs/client/react"
180
+ />
181
+ </Cards>
182
+
183
+ ## Learn more
184
+
185
+ - [Routing](/docs/elements/flow/routing) — folders are the URL; `$routes` without `.adopt()`
186
+ - [HTTP](/docs/elements/flow/http) — verbs, `http.resource`, live SSE
187
+ - [The Anatomy](/docs/understand/the-anatomy) — generated barrel → client → test loop
188
+ - [The Model](/docs/understand/the-model) — same contract for Client, Console, MCP
189
+ - [Errors](/docs/reference/errors) — framework codes vs failure values
190
+
191
+ ## Next
192
+
193
+ <Cards>
194
+ <Card
195
+ title="Calling"
196
+ description="REST vs RPC, options, helpers, and remote types."
197
+ href="/docs/client/calling"
198
+ />
199
+ <Card
200
+ title="Auth"
201
+ description="Sessions and gate denials on the client."
202
+ href="/docs/client/auth"
203
+ />
204
+ <Card
205
+ title="Live"
206
+ description="SSE subscribe and live resource queries."
207
+ href="/docs/client/live"
208
+ />
209
+ </Cards>