okengine 0.18.4 → 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (512) hide show
  1. package/AGENTS.md +18 -10
  2. package/README.md +2 -2
  3. package/package.json +51 -50
  4. package/site/content/docs/ai/index.mdx +25 -6
  5. package/site/content/docs/ai/llms-txt.mdx +1 -1
  6. package/site/content/docs/ai/meta.json +1 -1
  7. package/site/content/docs/ai/skills.mdx +4 -1
  8. package/site/content/docs/ai/try-it.mdx +58 -0
  9. package/site/content/docs/client/auth.mdx +208 -0
  10. package/site/content/docs/client/calling.mdx +451 -0
  11. package/site/content/docs/client/index.mdx +209 -0
  12. package/site/content/docs/client/live.mdx +234 -0
  13. package/site/content/docs/client/meta.json +5 -0
  14. package/site/content/docs/client/react.mdx +249 -0
  15. package/site/content/docs/elements/ai/agents.mdx +232 -0
  16. package/site/content/docs/elements/ai/index.mdx +341 -0
  17. package/site/content/docs/elements/ai/mcp.mdx +275 -0
  18. package/site/content/docs/elements/ai/meta.json +5 -0
  19. package/site/content/docs/elements/ai/models.mdx +283 -0
  20. package/site/content/docs/elements/ai/prompts.mdx +256 -0
  21. package/site/content/docs/elements/channel/email.mdx +266 -0
  22. package/site/content/docs/elements/channel/index.mdx +344 -0
  23. package/site/content/docs/elements/channel/meta.json +5 -0
  24. package/site/content/docs/elements/channel/push.mdx +218 -0
  25. package/site/content/docs/elements/channel/receipts.mdx +206 -0
  26. package/site/content/docs/elements/channel/sms.mdx +264 -0
  27. package/site/content/docs/elements/channel/whatsapp.mdx +220 -0
  28. package/site/content/docs/elements/clock/index.mdx +300 -0
  29. package/site/content/docs/elements/clock/meta.json +5 -0
  30. package/site/content/docs/elements/clock/schedules.mdx +508 -0
  31. package/site/content/docs/elements/clock/sleep.mdx +445 -0
  32. package/site/content/docs/elements/flow/consumers.mdx +707 -0
  33. package/site/content/docs/elements/flow/http.mdx +1080 -0
  34. package/site/content/docs/elements/flow/index.mdx +618 -0
  35. package/site/content/docs/elements/flow/meta.json +5 -0
  36. package/site/content/docs/elements/flow/routing.mdx +559 -0
  37. package/site/content/docs/elements/flow/workflows.mdx +640 -0
  38. package/site/content/docs/elements/gate/auth.mdx +371 -0
  39. package/site/content/docs/elements/gate/authorization.mdx +298 -0
  40. package/site/content/docs/elements/gate/index.mdx +418 -0
  41. package/site/content/docs/elements/gate/meta.json +5 -0
  42. package/site/content/docs/elements/gate/rate-limits.mdx +365 -0
  43. package/site/content/docs/elements/gate/rls.mdx +303 -0
  44. package/site/content/docs/elements/gate/tenancy.mdx +372 -0
  45. package/site/content/docs/elements/index.mdx +52 -11
  46. package/site/content/docs/elements/signal/broadcast.mdx +517 -0
  47. package/site/content/docs/elements/signal/index.mdx +352 -0
  48. package/site/content/docs/elements/signal/live.mdx +590 -0
  49. package/site/content/docs/elements/signal/meta.json +5 -0
  50. package/site/content/docs/elements/signal/once.mdx +596 -0
  51. package/site/content/docs/elements/store/files.mdx +659 -0
  52. package/site/content/docs/elements/store/index.mdx +310 -0
  53. package/site/content/docs/elements/store/kv.mdx +629 -0
  54. package/site/content/docs/elements/store/meta.json +5 -0
  55. package/site/content/docs/elements/store/search.mdx +946 -0
  56. package/site/content/docs/elements/store/sql.mdx +937 -0
  57. package/site/content/docs/elements/vault/config.mdx +256 -0
  58. package/site/content/docs/elements/vault/index.mdx +356 -0
  59. package/site/content/docs/elements/vault/meta.json +5 -0
  60. package/site/content/docs/elements/vault/rotation.mdx +273 -0
  61. package/site/content/docs/elements/vault/secrets.mdx +285 -0
  62. package/site/content/docs/index.mdx +78 -30
  63. package/site/content/docs/meta.json +11 -8
  64. package/site/content/docs/plugins/cors.mdx +2 -1
  65. package/site/content/docs/plugins/csrf.mdx +4 -1
  66. package/site/content/docs/plugins/headers.mdx +2 -1
  67. package/site/content/docs/plugins/ip-allowlist.mdx +2 -1
  68. package/site/content/docs/plugins/magic-link.mdx +6 -0
  69. package/site/content/docs/plugins/maintenance-mode.mdx +2 -1
  70. package/site/content/docs/plugins/oauth.mdx +1 -1
  71. package/site/content/docs/plugins/otp.mdx +12 -1
  72. package/site/content/docs/plugins/passkey.mdx +39 -15
  73. package/site/content/docs/plugins/two-factor.mdx +91 -34
  74. package/site/content/docs/plugins/username.mdx +1 -1
  75. package/site/content/docs/recipes/caddy.mdx +3 -3
  76. package/site/content/docs/recipes/index.mdx +18 -28
  77. package/site/content/docs/recipes/mailpit.mdx +1 -1
  78. package/site/content/docs/recipes/meilisearch.mdx +3 -3
  79. package/site/content/docs/recipes/meta.json +1 -4
  80. package/site/content/docs/recipes/nginx.mdx +2 -2
  81. package/site/content/docs/recipes/openrouter.mdx +283 -0
  82. package/site/content/docs/recipes/pgdog.mdx +3 -3
  83. package/site/content/docs/recipes/postgres.mdx +1 -2
  84. package/site/content/docs/recipes/rustfs.mdx +2 -2
  85. package/site/content/docs/recipes/traefik.mdx +3 -3
  86. package/site/content/docs/reference/cli.mdx +231 -0
  87. package/site/content/docs/reference/configuration.mdx +30 -10
  88. package/site/content/docs/reference/environment-variables.mdx +93 -20
  89. package/site/content/docs/reference/errors.mdx +132 -29
  90. package/site/content/docs/reference/fx.mdx +137 -73
  91. package/site/content/docs/reference/index.mdx +13 -21
  92. package/site/content/docs/reference/meta.json +4 -5
  93. package/site/content/docs/reference/okid.mdx +42 -17
  94. package/site/content/docs/reference/plugins.mdx +4 -3
  95. package/site/content/docs/reference/security.mdx +197 -0
  96. package/site/content/docs/understand/meta.json +5 -0
  97. package/site/content/docs/understand/the-anatomy.mdx +132 -0
  98. package/site/content/docs/understand/the-model.mdx +32 -0
  99. package/site/content/docs/understand/the-problem.mdx +74 -0
  100. package/site/content/docs/understand/the-vocabulary.mdx +26 -0
  101. package/src/auth/api-keys.ts +2 -1
  102. package/src/auth/bindings.ts +64 -16
  103. package/src/auth/gate-auth.test.ts +6 -1
  104. package/src/auth/identity.ts +152 -5
  105. package/src/auth/index.ts +29 -0
  106. package/src/auth/invites.ts +2 -1
  107. package/src/auth/method-context.ts +41 -0
  108. package/src/auth/oauth-as/crypto.ts +2 -1
  109. package/src/auth/oauth-as/stores.ts +2 -1
  110. package/src/auth/operator.ts +2 -1
  111. package/src/auth/sessions-jwt.test.ts +77 -0
  112. package/src/auth/sessions.ts +20 -4
  113. package/src/auth/tenants.ts +3 -2
  114. package/src/auth/two-factor-challenge.test.ts +61 -0
  115. package/src/auth/two-factor-challenge.ts +284 -0
  116. package/src/auth/verification.ts +5 -0
  117. package/src/bench/REPORT.md +49 -0
  118. package/src/bench/g03-signal-once.bench.ts +1 -1
  119. package/src/bench/g10-observability-contention.bench.ts +1 -1
  120. package/src/bench/g17-hybrid-search.bench.ts +572 -0
  121. package/src/bench/load-app.ts +2 -10
  122. package/src/cli/ai-setup/ai-setup.test.ts +331 -42
  123. package/src/cli/ai-setup/apply.ts +294 -52
  124. package/src/cli/ai-setup/catalog.ts +238 -1342
  125. package/src/cli/ai-setup/index.ts +14 -99
  126. package/src/cli/ai-setup/prompts.ts +60 -443
  127. package/src/cli/ask-seed.test.ts +96 -0
  128. package/src/cli/ask-seed.ts +82 -0
  129. package/src/cli/ask-vault-gaps.test.ts +84 -0
  130. package/src/cli/ask-vault-gaps.ts +146 -0
  131. package/src/cli/build.ts +2 -2
  132. package/src/cli/client-add.test.ts +26 -1
  133. package/src/cli/client-add.ts +106 -27
  134. package/src/cli/competitor-mention-removal.test.ts +1 -1
  135. package/src/cli/db-seed.ts +2 -0
  136. package/src/cli/db.ts +150 -11
  137. package/src/cli/dev.ts +119 -211
  138. package/src/cli/docker-clean.ts +2 -2
  139. package/src/cli/docker-cli.test.ts +1 -1
  140. package/src/cli/doctor-diff.ts +4 -2
  141. package/src/cli/doctor-pii.test.ts +1 -1
  142. package/src/cli/doctor.ts +14 -1
  143. package/src/cli/hero-meta.test.ts +4 -2
  144. package/src/cli/load-config.images.test.ts +8 -10
  145. package/src/cli/load-config.ts +1 -1
  146. package/src/cli/registry.ts +22 -10
  147. package/src/cli/replay.ts +3 -1
  148. package/src/cli/start.ts +1 -1
  149. package/src/cli/tui/keys.ts +2 -3
  150. package/src/client/auth/cookies.ts +74 -0
  151. package/src/client/auth/create-auth-client.ts +636 -0
  152. package/src/client/auth/denials.ts +99 -0
  153. package/src/client/auth/session.ts +283 -0
  154. package/src/client/auth.test.ts +251 -0
  155. package/src/client/auth.ts +39 -114
  156. package/src/client/create-with-session.ts +245 -0
  157. package/src/client/create.ts +51 -5
  158. package/src/client/index.ts +11 -1
  159. package/src/client/live.ts +11 -79
  160. package/src/client/notes-contract.test.ts +5 -10
  161. package/src/client/sse.ts +137 -0
  162. package/src/client/stream.ts +147 -0
  163. package/src/client/transport.test.ts +32 -0
  164. package/src/client/transport.ts +123 -26
  165. package/src/client/types.ts +118 -14
  166. package/src/client-react/index.ts +185 -24
  167. package/src/client-react/use-live-query.ts +13 -3
  168. package/src/compiler/aot.test.ts +7 -4
  169. package/src/compiler/effects-embed.test.ts +56 -0
  170. package/src/compiler/effects-fetch.test.ts +43 -0
  171. package/src/compiler/effects-infer.ts +58 -2
  172. package/src/compiler/extract.test.ts +258 -44
  173. package/src/compiler/extract.ts +566 -48
  174. package/src/compiler/fixtures/skyport/src/flows/bookings/index.ts +7 -4
  175. package/src/compiler/fixtures/skyport/src/flows/bookings/signals.ts +2 -8
  176. package/src/compiler/fixtures/skyport.expected.json +4 -4
  177. package/src/compiler/fixtures/triggers/five-triggers.ts +14 -10
  178. package/src/compiler/response.ts +2 -2
  179. package/src/compiler/search-writer-isolation.test.ts +40 -0
  180. package/src/config/index.ts +11 -0
  181. package/src/console/server/app.ts +17 -23
  182. package/src/console/server/bind.ts +4 -0
  183. package/src/console/server/console.test.ts +2 -2
  184. package/src/console/server/flows-invoke.test.ts +50 -34
  185. package/src/console/server/flows.ts +436 -255
  186. package/src/console/server/runs-ingest.test.ts +6 -3
  187. package/src/console/server/serve.ts +1 -1
  188. package/src/console/server/signals.test.ts +1 -5
  189. package/src/console/server/signals.ts +8 -6
  190. package/src/console/server/state.ts +6 -1
  191. package/src/console/server/store.ts +1 -1
  192. package/src/console/ui-next/dist/assets/FileExportIcon-Ck-5od4R.js +1 -0
  193. package/src/console/ui-next/dist/assets/MoreHorizontalCircle01Icon-gMNGsE37.js +1 -0
  194. package/src/console/ui-next/dist/assets/PlusSignIcon-CwG3nxfu.js +1 -0
  195. package/src/console/ui-next/dist/assets/UnavailableIcon-D9cvHVPr.js +1 -0
  196. package/src/console/ui-next/dist/assets/UserIcon-DaE2PB5_.js +1 -0
  197. package/src/console/ui-next/dist/assets/access-page-DFeymU07.js +4 -0
  198. package/src/console/ui-next/dist/assets/agent-disclosure-U1rdfblp.js +1 -0
  199. package/src/console/ui-next/dist/assets/cache-glyph-BeFJeqBG.js +1 -0
  200. package/src/console/ui-next/dist/assets/call-pii-button-CVAONPii.js +1 -0
  201. package/src/console/ui-next/dist/assets/collapsible-D2A6NJ-3.js +1 -0
  202. package/src/console/ui-next/dist/assets/copy-inline-button-CAYD18cr.js +1 -0
  203. package/src/console/ui-next/dist/assets/dagre.esm-B1_XeuLP.js +1 -0
  204. package/src/console/ui-next/dist/assets/detail-header-DVWNjWjg.js +1 -0
  205. package/src/console/ui-next/dist/assets/dropdown-menu-4h2LOVXM.js +1 -0
  206. package/src/console/ui-next/dist/assets/duration-tone-Cgk_h5ja.js +9 -0
  207. package/src/console/ui-next/dist/assets/element-icons-BI8cJgdh.js +1 -0
  208. package/src/console/ui-next/dist/assets/explorer-empty-CJs5A-wm.js +1 -0
  209. package/src/console/ui-next/dist/assets/flows-page-Dss7941e.js +1 -0
  210. package/src/console/ui-next/dist/assets/highlighted-json-MYZQtRnw.js +154 -0
  211. package/src/console/ui-next/dist/assets/http-method-Jrh39p7A.js +1 -0
  212. package/src/console/ui-next/dist/assets/index-D0zS5rKO.css +2 -0
  213. package/src/console/ui-next/dist/assets/index-DXP2dBIF.js +63 -0
  214. package/src/console/ui-next/dist/assets/observability-page-HvolXxTI.js +4 -0
  215. package/src/console/ui-next/dist/assets/react-dom-Ddte4I-Q.js +9 -0
  216. package/src/console/ui-next/dist/assets/replica-lag-CSh2dzrb.js +18 -0
  217. package/src/console/ui-next/dist/assets/request-meta-BatF8KrK.js +1 -0
  218. package/src/console/ui-next/dist/assets/shortcut-keys-3ILd8oGn.js +1 -0
  219. package/src/console/ui-next/dist/assets/{sql-BskegiFM.js → sql-BsFa4tDR.js} +1 -1
  220. package/src/console/ui-next/dist/assets/store-page-eiKiHnNe.js +41 -0
  221. package/src/console/ui-next/dist/assets/trace-detail-sheet-CZkMeKS-.js +2 -0
  222. package/src/console/ui-next/dist/assets/tree-expand-toggle-CW8y5A2h.js +55 -0
  223. package/src/console/ui-next/dist/assets/units-page-B_RWJrEO.js +1 -0
  224. package/src/console/ui-next/dist/assets/{use-vault-list-uk4WVboC.js → use-vault-list-CT4-gajj.js} +1 -1
  225. package/src/console/ui-next/dist/assets/vault-page-CWrg-A68.js +2 -0
  226. package/src/console/ui-next/dist/assets/xyflow-CSyC6ryz.css +1 -0
  227. package/src/console/ui-next/dist/assets/xyflow-yApv7D4e.js +7 -0
  228. package/src/console/ui-next/dist/index.html +6 -13
  229. package/src/console/ui-next/seed-invoke-host.ts +21 -18
  230. package/src/console/ui-next/src/client.ts +7 -2
  231. package/src/console/ui-next/src/features/flows/graph/element-map.ts +2 -0
  232. package/src/console/ui-next/src/features/flows/traces/effect-kind.ts +12 -2
  233. package/src/console/ui-next/src/features/flows/traces/effect-summary.ts +4 -0
  234. package/src/console/ui-next/src/features/flows/traces/trace-detail-sheet.tsx +8 -0
  235. package/src/console/ui-next/src/features/flows/traces/waterfall-bars.ts +4 -0
  236. package/src/console/ui-next/src/features/flows/traces/waterfall-tooltip.ts +9 -3
  237. package/src/console/ui-next/src/features/store/detail/reveal-cell.tsx +7 -11
  238. package/src/console/ui-next/src/features/store/detail/store-row-detail-sheet.tsx +2 -2
  239. package/src/console/ui-next/src/features/store/lib/fields-from-table.ts +2 -0
  240. package/src/console/ui-next/src/features/store/lib/grid-model.test.ts +25 -1
  241. package/src/console/ui-next/src/features/store/lib/grid-model.ts +36 -1
  242. package/src/console/ui-next/src/features/store/query/query-results.tsx +3 -3
  243. package/src/console/ui-next/src/features/units/detail/effects-summary.tsx +2 -0
  244. package/src/console/ui-next/src/features/units/lib/call-read-safe.ts +3 -1
  245. package/src/console/ui-next/src/features/units/lib/fields-from-schema.ts +6 -0
  246. package/src/docker/ai-model-status.test.ts +1 -12
  247. package/src/docker/ai-model-status.ts +10 -38
  248. package/src/docker/compose-up.test.ts +100 -0
  249. package/src/docker/compose-up.ts +292 -0
  250. package/src/docker/compose.ts +4 -14
  251. package/src/docker/derive.ts +9 -34
  252. package/src/docker/docker.test.ts +16 -261
  253. package/src/docker/images-config.test.ts +13 -25
  254. package/src/docker/index.ts +1 -24
  255. package/src/docker/recipes/index.ts +0 -23
  256. package/src/docker/recipes/pgdog.ts +6 -4
  257. package/src/docker/stack-id.test.ts +2 -2
  258. package/src/docker/stack-id.ts +0 -1
  259. package/src/docker/types.ts +2 -2
  260. package/src/drivers/ai-anthropic.ts +10 -0
  261. package/src/drivers/ai-openai-compatible.ts +34 -7
  262. package/src/drivers/ai-providers.test.ts +0 -107
  263. package/src/drivers/ai-stream.test.ts +0 -34
  264. package/src/drivers/ai-types.ts +17 -8
  265. package/src/drivers/channel-fcm.ts +6 -1
  266. package/src/drivers/channel-msegat.ts +6 -1
  267. package/src/drivers/channel-resend.ts +5 -1
  268. package/src/drivers/channel-smtp.ts +5 -1
  269. package/src/drivers/channel-sndr.ts +10 -1
  270. package/src/drivers/channel-taqnyat-mail.ts +5 -1
  271. package/src/drivers/channel-taqnyat-whatsapp.ts +6 -1
  272. package/src/drivers/channel-taqnyat.ts +6 -1
  273. package/src/drivers/channel-types.ts +10 -0
  274. package/src/drivers/channel-unifonic.ts +6 -1
  275. package/src/drivers/channel-wa-cloud.ts +6 -1
  276. package/src/drivers/channel-webpush.ts +6 -1
  277. package/src/drivers/external.ts +33 -0
  278. package/src/drivers/index.ts +0 -10
  279. package/src/drivers/meilisearch.ts +6 -0
  280. package/src/drivers/oauth-types.ts +4 -0
  281. package/src/drivers/postgres.test.ts +74 -3
  282. package/src/drivers/postgres.ts +175 -6
  283. package/src/drivers/signal-types.ts +5 -5
  284. package/src/drivers/types.ts +7 -0
  285. package/src/drivers/vault-types.ts +5 -0
  286. package/src/elements/ai/declare.ts +17 -4
  287. package/src/elements/ai/eval.ts +1 -1
  288. package/src/elements/ai/mcp-http.ts +1 -1
  289. package/src/elements/ai/pii.ts +1 -1
  290. package/src/elements/ai/providers.test.ts +289 -0
  291. package/src/elements/ai/providers.ts +169 -0
  292. package/src/elements/ai/runtime.ts +68 -5
  293. package/src/elements/ai/schema.ts +2 -2
  294. package/src/elements/ai.test.ts +7 -7
  295. package/src/elements/ai.ts +17 -1
  296. package/src/elements/channel/runtime.ts +105 -12
  297. package/src/elements/clock/cron-fields.test.ts +144 -0
  298. package/src/elements/clock/cron-fields.ts +185 -0
  299. package/src/elements/clock/declare.ts +247 -3
  300. package/src/elements/clock.ts +21 -1
  301. package/src/elements/index.ts +15 -0
  302. package/src/elements/signal/chaos-child.ts +1 -2
  303. package/src/elements/signal/declare.ts +65 -37
  304. package/src/elements/signal/delivery-modes.test.ts +11 -31
  305. package/src/elements/signal/dry-run-replay.test.ts +1 -7
  306. package/src/elements/signal/dry-run-write-isolation.test.ts +1 -7
  307. package/src/elements/signal/key-ordering.test.ts +6 -26
  308. package/src/elements/signal/lease-reclaim.test.ts +2 -6
  309. package/src/elements/signal/optional-emit.test.ts +6 -9
  310. package/src/elements/signal/order-lifecycle.test.ts +4 -17
  311. package/src/elements/signal/orphan-messages.test.ts +4 -15
  312. package/src/elements/signal/reconcile.test.ts +2 -2
  313. package/src/elements/signal/runtime.ts +1 -1
  314. package/src/elements/signal/schema-emit.test.ts +4 -8
  315. package/src/elements/signal.test.ts +24 -49
  316. package/src/elements/signal.ts +9 -2
  317. package/src/elements/store/domain-ddl.test.ts +1 -1
  318. package/src/elements/store/live-http.test.ts +9 -4
  319. package/src/elements/store/prepare-row.test.ts +123 -0
  320. package/src/elements/store/resource.ts +43 -12
  321. package/src/elements/store/schema-decl.ts +117 -0
  322. package/src/elements/store/search-backfill.ts +205 -0
  323. package/src/elements/store/search-bind.ts +66 -0
  324. package/src/elements/store/search-bm25.ts +78 -0
  325. package/src/elements/store/search-ddl.ts +156 -0
  326. package/src/elements/store/search-embed-flow.ts +141 -0
  327. package/src/elements/store/search-errors.ts +34 -0
  328. package/src/elements/store/search-fusion.ts +112 -0
  329. package/src/elements/store/search-lsh.ts +179 -0
  330. package/src/elements/store/search-runtime.ts +300 -0
  331. package/src/elements/store/search.test.ts +144 -0
  332. package/src/elements/store/sql-session.test.ts +1 -0
  333. package/src/elements/store/sql-session.ts +83 -3
  334. package/src/elements/store/table.ts +23 -2
  335. package/src/elements/store/upsert-app.test.ts +1 -3
  336. package/src/elements/store.ts +50 -0
  337. package/src/full.ts +4 -2
  338. package/src/http.ts +4 -1
  339. package/src/i18n/catalogs/ar.ts +14 -6
  340. package/src/i18n/catalogs/en.ts +14 -6
  341. package/src/index.ts +6 -1
  342. package/src/kernel/adopt-barrel-fresh.test.ts +7 -7
  343. package/src/kernel/adopt-routes.ts +9 -1
  344. package/src/kernel/app-auth.ts +5 -0
  345. package/src/kernel/app.ts +102 -9
  346. package/src/kernel/auto-cache.test.ts +6 -12
  347. package/src/kernel/auto-registry.test.ts +3 -3
  348. package/src/kernel/boot-bind/ai.test.ts +22 -19
  349. package/src/kernel/boot-bind/ai.ts +5 -43
  350. package/src/kernel/boot-bind/clock.ts +23 -5
  351. package/src/kernel/boot-bind/honor-config.test.ts +4 -4
  352. package/src/kernel/boot.test.ts +11 -6
  353. package/src/kernel/boot.ts +66 -16
  354. package/src/kernel/boundary-contract.ts +93 -0
  355. package/src/kernel/budget.test.ts +1 -1
  356. package/src/kernel/call.ts +89 -0
  357. package/src/kernel/capability.ts +6 -0
  358. package/src/kernel/client-descriptor.ts +123 -0
  359. package/src/kernel/clock-timezone.test.ts +80 -0
  360. package/src/kernel/correlation.test.ts +1 -1
  361. package/src/kernel/dry-run.ts +11 -8
  362. package/src/kernel/effects-stamping.test.ts +42 -9
  363. package/src/kernel/effects.test.ts +4 -2
  364. package/src/kernel/effects.ts +51 -9
  365. package/src/kernel/errors-channel.ts +17 -0
  366. package/src/kernel/errors-live-resume.ts +3 -2
  367. package/src/kernel/errors-tenant.ts +7 -4
  368. package/src/kernel/errors.registry-helpers.ts +96 -0
  369. package/src/kernel/errors.registry.test.ts +139 -25
  370. package/src/kernel/errors.ts +102 -23
  371. package/src/kernel/external-effects.test.ts +196 -0
  372. package/src/kernel/flow.test.ts +13 -4
  373. package/src/kernel/flow.ts +69 -71
  374. package/src/kernel/fx-ask-telemetry.test.ts +2 -2
  375. package/src/kernel/fx-dead-letters.test.ts +3 -3
  376. package/src/kernel/fx-fetch.ts +55 -0
  377. package/src/kernel/fx-live-stream.ts +2 -2
  378. package/src/kernel/fx-live.test.ts +8 -8
  379. package/src/kernel/fx.test.ts +17 -11
  380. package/src/kernel/fx.ts +180 -57
  381. package/src/kernel/horizontal-child.ts +1 -1
  382. package/src/kernel/http-query.test.ts +3 -6
  383. package/src/kernel/index.ts +13 -3
  384. package/src/kernel/instance-id.ts +1 -1
  385. package/src/kernel/instances.test.ts +40 -0
  386. package/src/kernel/instances.ts +47 -9
  387. package/src/kernel/live-http.test.ts +6 -7
  388. package/src/kernel/live-http.ts +6 -2
  389. package/src/kernel/live-resume.test.ts +1 -1
  390. package/src/kernel/mcp-tool.test.ts +3 -3
  391. package/src/kernel/on.ts +98 -4
  392. package/src/kernel/pipeline.test.ts +12 -15
  393. package/src/kernel/plugin-elements.test.ts +1 -1
  394. package/src/kernel/stamp-http.test.ts +3 -3
  395. package/src/kernel/triggers.ts +210 -95
  396. package/src/kernel-entry.ts +0 -1
  397. package/src/manifest/diff.ts +11 -1
  398. package/src/manifest/fixtures/skyport.excerpt.json +1 -1
  399. package/src/manifest/types.ts +46 -2
  400. package/src/mcp/docs-index.ts +3 -3
  401. package/src/mcp/docs-mcp.test.ts +2 -2
  402. package/src/mcp/docs-tools.ts +1 -1
  403. package/src/okid.test.ts +56 -0
  404. package/src/okid.ts +55 -11
  405. package/src/plugins/anonymous.ts +8 -4
  406. package/src/plugins/auth/shared.ts +27 -3
  407. package/src/plugins/auth-delivery.mailpit.integration.test.ts +1 -1
  408. package/src/plugins/auth-methods.security.test.ts +561 -23
  409. package/src/plugins/config-source.ts +1 -1
  410. package/src/plugins/csrf.test.ts +65 -0
  411. package/src/plugins/index.ts +2 -0
  412. package/src/plugins/magic-link.ts +36 -16
  413. package/src/plugins/oauth/shared.ts +3 -1
  414. package/src/plugins/oauth.ts +22 -14
  415. package/src/plugins/otp.ts +37 -21
  416. package/src/plugins/passkey-webauthn.ts +9 -6
  417. package/src/plugins/passkey.ts +98 -26
  418. package/src/plugins/pre-account-hijack.test.ts +223 -0
  419. package/src/plugins/two-factor.ts +466 -37
  420. package/src/plugins/username.ts +19 -7
  421. package/src/release/build-lib.ts +1 -0
  422. package/src/release/limits.ts +2 -2
  423. package/src/release/measure.ts +1 -1
  424. package/src/runs/collect.test.ts +0 -2
  425. package/src/runtime/json-code-block.test.ts +250 -20
  426. package/src/runtime/json-code-block.ts +1261 -41
  427. package/src/term.test.ts +1 -1
  428. package/src/test/create-test-app.test.ts +12 -12
  429. package/src/test/live-signals.test.ts +6 -6
  430. package/src/test/provisions.integration.test.ts +10 -14
  431. package/src/test/reset-element-registries.ts +1 -1
  432. package/src/test/tenant-isolation.test.ts +12 -6
  433. package/site/content/docs/deployment/docker-swarm.mdx +0 -164
  434. package/site/content/docs/deployment/docker.mdx +0 -227
  435. package/site/content/docs/deployment/index.mdx +0 -83
  436. package/site/content/docs/deployment/kubernetes.mdx +0 -176
  437. package/site/content/docs/deployment/meta.json +0 -5
  438. package/site/content/docs/deployment/reverse-proxy.mdx +0 -234
  439. package/site/content/docs/elements/ai.mdx +0 -385
  440. package/site/content/docs/elements/channel.mdx +0 -346
  441. package/site/content/docs/elements/clock.mdx +0 -244
  442. package/site/content/docs/elements/flow.mdx +0 -420
  443. package/site/content/docs/elements/gate.mdx +0 -436
  444. package/site/content/docs/elements/signal.mdx +0 -380
  445. package/site/content/docs/elements/store.mdx +0 -1099
  446. package/site/content/docs/elements/vault.mdx +0 -405
  447. package/site/content/docs/get-started/basic-usage.mdx +0 -173
  448. package/site/content/docs/get-started/index.mdx +0 -43
  449. package/site/content/docs/get-started/installation.mdx +0 -220
  450. package/site/content/docs/get-started/introduction.mdx +0 -132
  451. package/site/content/docs/get-started/meta.json +0 -13
  452. package/site/content/docs/get-started/project-structure.mdx +0 -925
  453. package/site/content/docs/get-started/testing.mdx +0 -328
  454. package/site/content/docs/get-started/why.mdx +0 -162
  455. package/site/content/docs/recipes/llama-cpp.mdx +0 -151
  456. package/site/content/docs/recipes/ollama.mdx +0 -142
  457. package/site/content/docs/recipes/sglang.mdx +0 -105
  458. package/site/content/docs/recipes/vllm.mdx +0 -106
  459. package/site/content/docs/reference/cli.md +0 -232
  460. package/site/content/docs/reference/client.mdx +0 -469
  461. package/site/content/docs/reference/security.md +0 -74
  462. package/src/cli/ai-setup/detect-ollama.ts +0 -213
  463. package/src/cli/ai-setup/recommend.test.ts +0 -225
  464. package/src/cli/ai-setup/recommend.ts +0 -225
  465. package/src/cli/dev-controls.test.ts +0 -122
  466. package/src/cli/dev-controls.ts +0 -164
  467. package/src/cli/tui/DevLive.tsx +0 -126
  468. package/src/console/ui-next/dist/assets/access-page-De7Lc2JC.js +0 -4
  469. package/src/console/ui-next/dist/assets/agent-disclosure-BP0Y0Sux.js +0 -1
  470. package/src/console/ui-next/dist/assets/cache-glyph-B5X-NM0-.js +0 -1
  471. package/src/console/ui-next/dist/assets/call-pii-button-ChAUiLo9.js +0 -1
  472. package/src/console/ui-next/dist/assets/collapsible-DGnOM2ph.js +0 -1
  473. package/src/console/ui-next/dist/assets/copy-inline-button-DBHhgHKP.js +0 -1
  474. package/src/console/ui-next/dist/assets/dagre.esm-ZwcdTuZZ.js +0 -1
  475. package/src/console/ui-next/dist/assets/detail-header-DhHM1iaZ.js +0 -1
  476. package/src/console/ui-next/dist/assets/dropdown-menu-_NjTEo5_.js +0 -1
  477. package/src/console/ui-next/dist/assets/duration-tone-sC3lGABz.js +0 -9
  478. package/src/console/ui-next/dist/assets/element-icons-BVXtRyd3.js +0 -1
  479. package/src/console/ui-next/dist/assets/explorer-empty-2uIhBu0_.js +0 -1
  480. package/src/console/ui-next/dist/assets/flows-page-RGy7VEA_.js +0 -1
  481. package/src/console/ui-next/dist/assets/highlighted-json-Awq7gYdu.js +0 -154
  482. package/src/console/ui-next/dist/assets/http-method-_UHM2ODJ.js +0 -1
  483. package/src/console/ui-next/dist/assets/index-Ck88Jmv8.css +0 -2
  484. package/src/console/ui-next/dist/assets/index-_rgpdVzo.js +0 -66
  485. package/src/console/ui-next/dist/assets/link-BX6Vqztd.js +0 -1
  486. package/src/console/ui-next/dist/assets/observability-page-Ds6pcnh-.js +0 -4
  487. package/src/console/ui-next/dist/assets/preload-helper-oH4irX4C.js +0 -1
  488. package/src/console/ui-next/dist/assets/react-D8E3mtu1.js +0 -1
  489. package/src/console/ui-next/dist/assets/react-dom-Bph1y7z7.js +0 -9
  490. package/src/console/ui-next/dist/assets/replica-lag-DKRrbvdo.js +0 -18
  491. package/src/console/ui-next/dist/assets/request-meta-DV0ywz7t.js +0 -1
  492. package/src/console/ui-next/dist/assets/shortcut-JQIZlWfm.js +0 -1
  493. package/src/console/ui-next/dist/assets/shortcut-keys-DKxNTe_m.js +0 -1
  494. package/src/console/ui-next/dist/assets/skeleton-D-czQJT6.js +0 -1
  495. package/src/console/ui-next/dist/assets/store-page-02xOiqIK.js +0 -41
  496. package/src/console/ui-next/dist/assets/trace-detail-sheet-B09O8rA6.js +0 -2
  497. package/src/console/ui-next/dist/assets/tree-expand-toggle-BtyhmWb4.js +0 -55
  498. package/src/console/ui-next/dist/assets/units-page-4rHOePuE.js +0 -1
  499. package/src/console/ui-next/dist/assets/useMutation-B8EO02Ej.js +0 -1
  500. package/src/console/ui-next/dist/assets/useRender-BE2A9BWC.js +0 -1
  501. package/src/console/ui-next/dist/assets/vault-page-DISPgxLM.js +0 -2
  502. package/src/console/ui-next/dist/assets/xyflow-D7n4g6go.js +0 -7
  503. package/src/console/ui-next/dist/assets/xyflow-DZ0Ws1xk.css +0 -1
  504. package/src/docker/ollama-pull.ts +0 -232
  505. package/src/docker/recipes/llama-cpp.ts +0 -298
  506. package/src/docker/recipes/ollama.ts +0 -44
  507. package/src/docker/recipes/sglang.ts +0 -55
  508. package/src/docker/recipes/vllm.ts +0 -44
  509. package/src/drivers/ai-ollama-tools.integration.test.ts +0 -109
  510. package/src/drivers/ai-ollama.integration.test.ts +0 -184
  511. package/src/drivers/ai-ollama.ts +0 -389
  512. package/src/drivers/ollama.ts +0 -14
@@ -1,9 +1,24 @@
1
1
  /**
2
- * Postgres placeholder conversion.
2
+ * Postgres placeholder conversion + shared pool lifecycle.
3
3
  */
4
4
 
5
- import { describe, expect, test } from "bun:test";
6
- import { toPostgresParams } from "./postgres.ts";
5
+ import { afterEach, describe, expect, test } from "bun:test";
6
+ import {
7
+ closeSharedPostgresClients,
8
+ connectPostgres,
9
+ isPostgresConnectionNoise,
10
+ isSharedPostgresPaused,
11
+ pauseSharedPostgresClients,
12
+ resumeSharedPostgresClients,
13
+ SharedPostgresPausedError,
14
+ sharedPostgresClient,
15
+ toPostgresParams,
16
+ } from "./postgres.ts";
17
+
18
+ afterEach(async () => {
19
+ resumeSharedPostgresClients();
20
+ await closeSharedPostgresClients();
21
+ });
7
22
 
8
23
  describe("toPostgresParams", () => {
9
24
  test("rewrites ? only when values are bound", () => {
@@ -21,3 +36,59 @@ describe("toPostgresParams", () => {
21
36
  expect(toPostgresParams(sql, [])).toBe(sql);
22
37
  });
23
38
  });
39
+
40
+ describe("closeSharedPostgresClients", () => {
41
+ test("drops cached pools so the next checkout is a new client", async () => {
42
+ const url = "postgres://127.0.0.1:9/oke-close-shared-test";
43
+ const first = sharedPostgresClient(url);
44
+ expect(sharedPostgresClient(url)).toBe(first);
45
+ await closeSharedPostgresClients();
46
+ const second = sharedPostgresClient(url);
47
+ expect(second).not.toBe(first);
48
+ });
49
+
50
+ test("holder close is a no-op so seed stop cannot leave a dead cached pool", async () => {
51
+ const url = "postgres://127.0.0.1:9/oke-holder-close-shared-test";
52
+ const first = sharedPostgresClient(url);
53
+ await first.close?.({ timeout: 1 });
54
+ // Same live pool — journal/instances close during in-process seed must not
55
+ // tear Bun.SQL while the map still hands out this client.
56
+ expect(sharedPostgresClient(url)).toBe(first);
57
+ await expect(first.close?.({ timeout: 1 })).resolves.toBeUndefined();
58
+ });
59
+ });
60
+
61
+ describe("pauseSharedPostgresClients", () => {
62
+ test("blocks new pools and fails soft on existing wrappers", async () => {
63
+ const url = "postgres://127.0.0.1:9/oke-pause-shared-test";
64
+ const sql = await connectPostgres({ url });
65
+ const held = sharedPostgresClient(url);
66
+ await pauseSharedPostgresClients();
67
+ expect(isSharedPostgresPaused()).toBe(true);
68
+ expect(() => sharedPostgresClient(url)).toThrow(SharedPostgresPausedError);
69
+ await expect(sql.query("SELECT 1")).rejects.toBeInstanceOf(SharedPostgresPausedError);
70
+ // Fleet wrappers (journal / clock / instances) call .unsafe on the held client.
71
+ expect(() => held.unsafe("SELECT 1")).toThrow(SharedPostgresPausedError);
72
+ resumeSharedPostgresClients();
73
+ expect(isSharedPostgresPaused()).toBe(false);
74
+ const next = sharedPostgresClient(url);
75
+ expect(next).toBeDefined();
76
+ });
77
+
78
+ test("isPostgresConnectionNoise matches Bun close / refuse codes", () => {
79
+ expect(
80
+ isPostgresConnectionNoise({
81
+ code: "ERR_POSTGRES_CONNECTION_CLOSED",
82
+ message: "Connection closed",
83
+ }),
84
+ ).toBe(true);
85
+ expect(
86
+ isPostgresConnectionNoise({
87
+ code: "ERR_POSTGRES_CONNECTION_REFUSED",
88
+ message: "Failed to connect",
89
+ }),
90
+ ).toBe(true);
91
+ expect(isPostgresConnectionNoise(new SharedPostgresPausedError())).toBe(true);
92
+ expect(isPostgresConnectionNoise(new Error("relation missing"))).toBe(false);
93
+ });
94
+ });
@@ -5,6 +5,7 @@
5
5
  */
6
6
 
7
7
  import type { SqlConnectOptions, SqlConnection, SqlDriver, SqlRole, SqlRow } from "./types.ts";
8
+ import { hostFromUrl } from "./external.ts";
8
9
 
9
10
  /** Bun.SQL client checked out via {@link PostgresClientLike.reserve}. */
10
11
  export interface PostgresReservedClient extends PostgresClientLike {
@@ -36,7 +37,35 @@ export interface PostgresClientLike {
36
37
  /** Cap shared Bun.SQL pools so one process cannot outrun PgDog (default 10). */
37
38
  export const POSTGRES_POOL_MAX = 8;
38
39
 
39
- const sharedClients = new Map<string, PostgresClientLike>();
40
+ /** One shared pool entry — raw Bun.SQL plus a pause-aware facade. */
41
+ type SharedPostgresEntry = {
42
+ readonly raw: PostgresClientLike;
43
+ readonly guarded: PostgresClientLike;
44
+ };
45
+
46
+ const sharedClients = new Map<string, SharedPostgresEntry>();
47
+
48
+ /**
49
+ * When true, shared pools stay closed and every query fails fast — no Bun.SQL
50
+ * reconnect into a torn-down Postgres (see {@link pauseSharedPostgresClients}).
51
+ */
52
+ let sharedPostgresPaused = false;
53
+
54
+ /**
55
+ * Thrown when Console / host code touches SQL after `oke dev` paused Postgres
56
+ * for compose stop. Fail soft — never open a new TCP connection.
57
+ */
58
+ export class SharedPostgresPausedError extends Error {
59
+ readonly code = "ERR_OKE_POSTGRES_PAUSED";
60
+
61
+ /**
62
+ * @param message - Operator-facing reason
63
+ */
64
+ constructor(message = "shared Postgres pools are paused (compose stopped)") {
65
+ super(message);
66
+ this.name = "SharedPostgresPausedError";
67
+ }
68
+ }
40
69
 
41
70
  /**
42
71
  * Resolve the Postgres URL (injected, `DATABASE_URL`, then localhost).
@@ -47,18 +76,145 @@ export function resolvePostgresUrl(url?: string): string {
47
76
  return url ?? process.env.DATABASE_URL ?? "postgres://localhost:5432/oke";
48
77
  }
49
78
 
79
+ /**
80
+ * True while {@link pauseSharedPostgresClients} has not been resumed.
81
+ */
82
+ export function isSharedPostgresPaused(): boolean {
83
+ return sharedPostgresPaused;
84
+ }
85
+
86
+ /**
87
+ * Bun / driver connection failures that flood the TTY when Postgres dies
88
+ * under an open pool (compose stop).
89
+ *
90
+ * @param reason - Rejection reason
91
+ */
92
+ export function isPostgresConnectionNoise(reason: unknown): boolean {
93
+ if (reason instanceof SharedPostgresPausedError) return true;
94
+ if (!reason || typeof reason !== "object") return false;
95
+ const code = (reason as { code?: unknown }).code;
96
+ if (typeof code === "string") {
97
+ if (
98
+ code === "ERR_POSTGRES_CONNECTION_CLOSED" ||
99
+ code === "ERR_POSTGRES_CONNECTION_REFUSED" ||
100
+ code === "ERR_POSTGRES_CONNECTION_TIMEOUT" ||
101
+ code === "ERR_OKE_POSTGRES_PAUSED"
102
+ ) {
103
+ return true;
104
+ }
105
+ }
106
+ const message = (reason as { message?: unknown }).message;
107
+ if (typeof message !== "string") return false;
108
+ return (
109
+ message === "Connection closed" ||
110
+ /Failed to connect/i.test(message) ||
111
+ /ECONNREFUSED/i.test(message)
112
+ );
113
+ }
114
+
115
+ function assertSharedPostgresReady(): void {
116
+ if (sharedPostgresPaused) throw new SharedPostgresPausedError();
117
+ }
118
+
119
+ /**
120
+ * Pause-aware facade over a Bun.SQL client so journal / clock / instances /
121
+ * Console wrappers that call `.unsafe` directly cannot reconnect after pause.
122
+ *
123
+ * @param raw - Underlying Bun.SQL (or test fake)
124
+ */
125
+ function guardSharedPostgresClient(raw: PostgresClientLike): PostgresClientLike {
126
+ const guarded: PostgresClientLike = {
127
+ unsafe(sql, values) {
128
+ assertSharedPostgresReady();
129
+ return raw.unsafe(sql, values);
130
+ },
131
+ async reserve() {
132
+ assertSharedPostgresReady();
133
+ if (typeof raw.reserve !== "function") {
134
+ throw new Error("postgres client needs reserve()");
135
+ }
136
+ const reserved = await raw.reserve();
137
+ const guardedReserved = guardSharedPostgresClient(reserved) as PostgresReservedClient;
138
+ return Object.assign(guardedReserved, {
139
+ release(): void {
140
+ reserved.release();
141
+ },
142
+ });
143
+ },
144
+ begin(fn) {
145
+ assertSharedPostgresReady();
146
+ if (typeof raw.begin !== "function") {
147
+ throw new Error("postgres client needs begin()");
148
+ }
149
+ return raw.begin((tx) => fn(guardSharedPostgresClient(tx)));
150
+ },
151
+ async close(): Promise<void> {
152
+ // Shared pools are process-owned ({@link closeSharedPostgresClients}).
153
+ // Journal / clock / instances / store holders must not tear down Bun.SQL
154
+ // or the map keeps a dead client — next checkout returns
155
+ // ERR_POSTGRES_CONNECTION_CLOSED (e.g. after in-process `oke db seed`
156
+ // stops the temporary app boot inside `oke dev`).
157
+ },
158
+ };
159
+ return guarded;
160
+ }
161
+
50
162
  /**
51
163
  * One Bun.SQL pool per URL for store / journal / clock / vault / console.
52
164
  *
165
+ * Returns a pause-aware client — holders (including fleet store wrappers)
166
+ * fail soft after {@link pauseSharedPostgresClients} instead of reconnecting.
167
+ *
53
168
  * @param url - Connection URL
54
169
  */
55
170
  export function sharedPostgresClient(url?: string): PostgresClientLike {
171
+ assertSharedPostgresReady();
56
172
  const key = resolvePostgresUrl(url);
57
173
  const existing = sharedClients.get(key);
58
- if (existing) return existing;
59
- const created = new Bun.SQL(key, { max: POSTGRES_POOL_MAX }) as unknown as PostgresClientLike;
60
- sharedClients.set(key, created);
61
- return created;
174
+ if (existing) return existing.guarded;
175
+ const raw = new Bun.SQL(key, { max: POSTGRES_POOL_MAX }) as unknown as PostgresClientLike;
176
+ const guarded = guardSharedPostgresClient(raw);
177
+ sharedClients.set(key, { raw, guarded });
178
+ return guarded;
179
+ }
180
+
181
+ /**
182
+ * Close and drop every shared Bun.SQL pool.
183
+ *
184
+ * Prefer {@link pauseSharedPostgresClients} from `oke dev` — close alone does
185
+ * not stop Console from opening a fresh pool on the next poll.
186
+ */
187
+ export async function closeSharedPostgresClients(): Promise<void> {
188
+ const clients = [...sharedClients.values()];
189
+ sharedClients.clear();
190
+ await Promise.all(
191
+ clients.map(async (entry) => {
192
+ try {
193
+ await entry.raw.close?.({ timeout: 1 });
194
+ } catch {
195
+ // Pool already closed / server already gone.
196
+ }
197
+ }),
198
+ );
199
+ }
200
+
201
+ /**
202
+ * Pause shared Postgres: block new pools, fail soft on existing wrappers, and
203
+ * close open clients.
204
+ *
205
+ * Used by `oke dev` **`x`** before `docker compose stop` so parent Console
206
+ * polls do not keep reconnecting into a torn-down Postgres/PgDog.
207
+ */
208
+ export async function pauseSharedPostgresClients(): Promise<void> {
209
+ sharedPostgresPaused = true;
210
+ await closeSharedPostgresClients();
211
+ }
212
+
213
+ /**
214
+ * Allow shared pools again after compose is back ( `oke dev` **`u`** ).
215
+ */
216
+ export function resumeSharedPostgresClients(): void {
217
+ sharedPostgresPaused = false;
62
218
  }
63
219
 
64
220
  /**
@@ -135,6 +291,7 @@ export async function connectPostgres(options: SqlConnectOptions = {}): Promise<
135
291
  : sharedPostgresClient(options.url));
136
292
  return wrapPostgresClient(client, role, {
137
293
  shared: injected === undefined && !dedicated,
294
+ ...(options.url !== undefined ? { url: options.url } : {}),
138
295
  });
139
296
  }
140
297
 
@@ -153,18 +310,29 @@ function dedicatedPostgresClient(url: string): PostgresClientLike {
153
310
  function wrapPostgresClient(
154
311
  client: PostgresClientLike,
155
312
  role: SqlRole,
156
- opts: { readonly shared?: boolean; readonly pinned?: boolean } = {},
313
+ opts: {
314
+ readonly shared?: boolean;
315
+ readonly pinned?: boolean;
316
+ readonly url?: string;
317
+ } = {},
157
318
  ): SqlConnection {
319
+ const host = opts.url ? hostFromUrl(opts.url) : undefined;
158
320
  const connection: SqlConnection = {
159
321
  driverId: "postgres",
160
322
  role,
323
+ ...(host !== undefined
324
+ ? { external: { host, provider: "postgres", kind: "infrastructure" as const } }
325
+ : {}),
161
326
  async query(sql, params = []) {
327
+ // Shared wrappers outlive pause — fail soft before Bun.SQL reconnects.
328
+ if (opts.shared) assertSharedPostgresReady();
162
329
  const pg = toPostgresParams(sql, params);
163
330
  const result = await client.unsafe(pg, [...params]);
164
331
  if (Array.isArray(result)) return result as SqlRow[];
165
332
  return Array.from(result as ArrayLike<SqlRow>);
166
333
  },
167
334
  async exec(sql, params = []) {
335
+ if (opts.shared) assertSharedPostgresReady();
168
336
  const pg = toPostgresParams(sql, params);
169
337
  const result = await client.unsafe(pg, [...params]);
170
338
  if (
@@ -181,6 +349,7 @@ function wrapPostgresClient(
181
349
  return { changes: 0 };
182
350
  },
183
351
  async transaction(fn) {
352
+ if (opts.shared) assertSharedPostgresReady();
184
353
  if (opts.pinned) return fn(connection);
185
354
  return withPinnedPostgres(client, (tx) => fn(wrapPostgresClient(tx, role, { pinned: true })));
186
355
  },
@@ -150,7 +150,7 @@ export interface SignalReplayMessageResult {
150
150
 
151
151
  /** Irreversible effect intercepted during a dry-run replay. */
152
152
  export interface SignalDryRunStub {
153
- readonly kind: "send" | "ask";
153
+ readonly kind: "send" | "ask" | "embed" | "fetch";
154
154
  readonly resource: string;
155
155
  readonly messageId?: string;
156
156
  }
@@ -201,7 +201,7 @@ export interface LiveEvent {
201
201
  export interface LiveSubscribeOptions {
202
202
  /**
203
203
  * Exclusive SSE cursor — replay events after this id, then continue.
204
- * Omit for the full retained tape. Unknown / pruned ids throw OKE1014.
204
+ * Omit for the full retained tape. Unknown / pruned ids throw OKE1210.
205
205
  */
206
206
  readonly afterId?: string;
207
207
  }
@@ -332,7 +332,7 @@ export interface SignalBus {
332
332
  *
333
333
  * Replays retained history, then yields new events until the iterator
334
334
  * returns. `delivery` must be `"live"`. `afterId` skips through that
335
- * id (exclusive); unknown or pruned ids throw OKE1014.
335
+ * id (exclusive); unknown or pruned ids throw OKE1210.
336
336
  *
337
337
  * @param signal - Signal name
338
338
  * @param opts - Optional resume cursor
@@ -341,7 +341,7 @@ export interface SignalBus {
341
341
  /**
342
342
  * Validate a live resume cursor without waiting for new events.
343
343
  *
344
- * Prunes the tape first. Throws OKE1014 when `afterId` is absent.
344
+ * Prunes the tape first. Throws OKE1210 when `afterId` is absent.
345
345
  *
346
346
  * @param signal - Signal name
347
347
  * @param afterId - SSE cursor
@@ -399,7 +399,7 @@ export interface SignalDriver {
399
399
  /**
400
400
  * Validate an emit payload against the signal declaration's Standard Schema.
401
401
  *
402
- * @param name - Signal name (for OKE1043)
402
+ * @param name - Signal name (for OKE1250)
403
403
  * @param decl - Declared signal
404
404
  * @param payload - Raw emit payload
405
405
  */
@@ -48,6 +48,11 @@ export interface SqlConnection {
48
48
  readonly driverId: "postgres" | "pglite" | "memory";
49
49
  /** Primary vs replica. */
50
50
  readonly role: SqlRole;
51
+ /**
52
+ * Egress identity when queries leave the process (remote Postgres).
53
+ * Omitted for in-process drivers (`pglite`, `memory`).
54
+ */
55
+ readonly external?: import("./external.ts").DriverExternal;
51
56
  /**
52
57
  * Run a parameterised query and return rows.
53
58
  *
@@ -338,6 +343,8 @@ export interface TextIndexSearchResult {
338
343
  /** Full-text index handle. */
339
344
  export interface TextIndexStore {
340
345
  readonly driverId: "meilisearch";
346
+ /** Egress identity for Meilisearch HTTP calls. */
347
+ readonly external?: import("./external.ts").DriverExternal;
341
348
  /**
342
349
  * Upsert a document.
343
350
  *
@@ -54,6 +54,11 @@ export interface VaultOpenOptions {
54
54
  export interface VaultBag {
55
55
  /** Protocol driver id. */
56
56
  readonly driverId: VaultDriverId;
57
+ /**
58
+ * Egress identity when the bag was opened / mutated over the network.
59
+ * Omitted for `env` / `memory` / injected managed bags.
60
+ */
61
+ readonly external?: import("./external.ts").DriverExternal;
57
62
  /**
58
63
  * Read a secret by name.
59
64
  *
@@ -13,6 +13,7 @@ import {
13
13
  } from "../../kernel/element-registries.ts";
14
14
  import { mcpToolRef, type McpToolRef } from "../../manifest/mcp-ref.ts";
15
15
  import type { VaultSecretDecl } from "../vault/declare.ts";
16
+ import { formatAiProviderTier2Warn, resolveAiModelBaseUrl } from "./providers.ts";
16
17
 
17
18
  /** Budget for a prompt or agent. */
18
19
  export interface AiBudgetDecl {
@@ -27,14 +28,15 @@ export interface AiModelOptions {
27
28
  readonly model?: string;
28
29
  /**
29
30
  * Optional endpoint override for this logical binding (openai-compatible /
30
- * ollama). Lets `fx.ask(…, { via: ["smart", "local"] })` reach cloud then
31
- * local without sharing one process-wide base URL.
31
+ * local). When omitted and `provider` is a known OpenAI-compatible name,
32
+ * the verified registry base URL is filled in automatically. Explicit
33
+ * `baseUrl` always wins (self-hosted proxy / mirror).
32
34
  */
33
35
  readonly baseUrl?: string;
34
36
  /** Optional API key override for this binding (cloud providers). */
35
37
  readonly apiKey?: string;
36
38
  /**
37
- * Protocol driver for this binding (`anthropic`, `ollama`, …).
39
+ * Protocol driver for this binding (`anthropic`, `openai-compatible`, …).
38
40
  * When omitted, the app-level default driver is used.
39
41
  */
40
42
  readonly driverId?: string;
@@ -260,13 +262,24 @@ export const ai: AiNamespace = {
260
262
  */
261
263
  model(name: string, options: AiModelOptions = {}): AiModelDecl {
262
264
  if (!name) throw new TypeError("ai.model: name is required");
265
+ const resolved = resolveAiModelBaseUrl({
266
+ ...(options.provider !== undefined ? { provider: options.provider } : {}),
267
+ ...(options.baseUrl !== undefined ? { baseUrl: options.baseUrl } : {}),
268
+ ...(options.driverId !== undefined ? { driverId: options.driverId } : {}),
269
+ });
270
+ if (resolved.tier2Caveat !== undefined && resolved.tier2Provider !== undefined) {
271
+ console.warn(
272
+ formatAiProviderTier2Warn(resolved.tier2Provider, resolved.tier2Caveat, "ai.model"),
273
+ );
274
+ }
275
+ const baseUrl = resolved.baseUrl;
263
276
  const decl: AiModelDecl = {
264
277
  kind: "model",
265
278
  name,
266
279
  ...(options.provider !== undefined ? { provider: options.provider } : {}),
267
280
  ...(options.tier !== undefined ? { tier: options.tier } : {}),
268
281
  ...(options.model !== undefined ? { model: options.model } : {}),
269
- ...(options.baseUrl !== undefined ? { baseUrl: options.baseUrl } : {}),
282
+ ...(baseUrl !== undefined ? { baseUrl } : {}),
270
283
  ...(options.apiKey !== undefined ? { apiKey: options.apiKey } : {}),
271
284
  ...(options.driverId !== undefined ? { driverId: options.driverId } : {}),
272
285
  prompt(promptName, promptOpts = {}) {
@@ -126,7 +126,7 @@ export async function runPromptEvals(options: RunPromptEvalsOptions): Promise<Ev
126
126
  export function parseEvalJsonl(text: string): EvalCase[] {
127
127
  const jsonl = (Bun as typeof Bun & { JSONL?: { parse: (t: string) => unknown[] } }).JSONL;
128
128
  if (!jsonl) {
129
- throw new Error("ai.eval: Bun.JSONL is required (Bun >= 1.4.0)");
129
+ throw new Error("ai.eval: Bun.JSONL is required (Bun >= 1.4.2)");
130
130
  }
131
131
  return jsonl.parse(text) as EvalCase[];
132
132
  }
@@ -153,7 +153,7 @@ async function readSseJsonRpc(
153
153
  function responseTextStream(res: Response): AsyncIterable<string> {
154
154
  const stream = (res as Response & { textStream?: () => AsyncIterable<string> }).textStream;
155
155
  if (typeof stream !== "function") {
156
- throw new Error("ai.mcp: Response.textStream is required (Bun >= 1.4.0)");
156
+ throw new Error("ai.mcp: Response.textStream is required (Bun >= 1.4.2)");
157
157
  }
158
158
  return stream.call(res);
159
159
  }
@@ -70,7 +70,7 @@ function isPiiTags(tags: ColumnClassification | string | readonly string[] | und
70
70
  function isThirdParty(provider: string | undefined): boolean {
71
71
  if (!provider) return true;
72
72
  const p = provider.toLowerCase();
73
- return p !== "mock" && p !== "ollama" && p !== "local";
73
+ return p !== "mock" && p !== "local" && p !== "openai-compatible";
74
74
  }
75
75
 
76
76
  /**