okengine 0.22.0 → 0.23.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (312) hide show
  1. package/AGENTS.md +7 -0
  2. package/manifest.v1.schema.json +44 -0
  3. package/package.json +32 -19
  4. package/site/content/docs/ai/mcp.mdx +14 -10
  5. package/site/content/docs/ai/skills.mdx +1 -1
  6. package/site/content/docs/elements/ai/agents.mdx +61 -13
  7. package/site/content/docs/elements/ai/decide.mdx +536 -0
  8. package/site/content/docs/elements/ai/events.mdx +373 -0
  9. package/site/content/docs/elements/ai/index.mdx +9 -3
  10. package/site/content/docs/elements/ai/meta.json +1 -1
  11. package/site/content/docs/elements/ai/prompts.mdx +4 -2
  12. package/site/content/docs/elements/channel/index.mdx +4 -4
  13. package/site/content/docs/elements/channel/receipts.mdx +7 -5
  14. package/site/content/docs/elements/channel/sms.mdx +2 -1
  15. package/site/content/docs/elements/flow/index.mdx +22 -18
  16. package/site/content/docs/elements/gate/auth.mdx +4 -1
  17. package/site/content/docs/elements/signal/index.mdx +15 -14
  18. package/site/content/docs/elements/store/index.mdx +1 -1
  19. package/site/content/docs/elements/store/kv.mdx +5 -5
  20. package/site/content/docs/plugins/otp.mdx +3 -3
  21. package/site/content/docs/recipes/dragonfly.mdx +5 -5
  22. package/site/content/docs/recipes/index.mdx +6 -6
  23. package/site/content/docs/recipes/postgres.mdx +12 -8
  24. package/site/content/docs/recipes/redis.mdx +4 -4
  25. package/site/content/docs/reference/cli.mdx +2 -1
  26. package/site/content/docs/reference/configuration.mdx +9 -7
  27. package/site/content/docs/reference/fx.mdx +19 -10
  28. package/src/auth/api-key-sql.test.ts +44 -0
  29. package/src/auth/api-key-sql.ts +1 -0
  30. package/src/auth/api-keys.ts +30 -12
  31. package/src/auth/config.ts +6 -2
  32. package/src/auth/gate-auth.test.ts +20 -0
  33. package/src/auth/tenants.ts +17 -0
  34. package/src/cli/agents-md.test.ts +25 -0
  35. package/src/cli/ask-vault-gaps.test.ts +38 -1
  36. package/src/cli/ask-vault-gaps.ts +35 -2
  37. package/src/cli/decide.ts +174 -0
  38. package/src/cli/decision-lock-watch.test.ts +45 -0
  39. package/src/cli/decision-lock-watch.ts +51 -0
  40. package/src/cli/dev-app-runner.ts +34 -8
  41. package/src/cli/dev-auth-secret.test.ts +49 -0
  42. package/src/cli/dev-auth-secret.ts +49 -0
  43. package/src/cli/dev-hot.test.ts +41 -0
  44. package/src/cli/dev-hot.ts +48 -0
  45. package/src/cli/dev.test.ts +1 -1
  46. package/src/cli/dev.ts +24 -6
  47. package/src/cli/doctor-diff.test.ts +29 -1
  48. package/src/cli/doctor-diff.ts +35 -0
  49. package/src/cli/eval.ts +142 -1
  50. package/src/cli/index.ts +5 -0
  51. package/src/cli/load-config.images.test.ts +2 -2
  52. package/src/cli/load-config.ts +1 -1
  53. package/src/cli/manifest-pr-diff.ts +16 -0
  54. package/src/cli/mcp-from-console.ts +48 -0
  55. package/src/cli/registry.ts +35 -1
  56. package/src/client/agent.ts +307 -0
  57. package/src/client/transport.test.ts +20 -0
  58. package/src/client/transport.ts +2 -1
  59. package/src/client/types.ts +1 -1
  60. package/src/client-react/index.ts +7 -1
  61. package/src/client-react/use-agent-run.test.ts +271 -0
  62. package/src/client-react/use-agent-run.ts +193 -0
  63. package/src/compiler/ai-approval.test.ts +36 -0
  64. package/src/compiler/ai-repair.test.ts +22 -0
  65. package/src/compiler/decisions.extract.test.ts +164 -0
  66. package/src/compiler/effects-fetch.test.ts +77 -0
  67. package/src/compiler/effects-infer.ts +114 -17
  68. package/src/compiler/effects-join.test.ts +48 -0
  69. package/src/compiler/extract.test.ts +28 -0
  70. package/src/compiler/extract.ts +279 -13
  71. package/src/compiler/fx-index.ts +58 -4
  72. package/src/compiler/response.ts +35 -2
  73. package/src/config/index.ts +21 -3
  74. package/src/console/index.ts +1 -1
  75. package/src/console/server/ai-runs-flows.ts +269 -0
  76. package/src/console/server/ai-runs.test.ts +323 -0
  77. package/src/console/server/ai-runs.ts +562 -0
  78. package/src/console/server/ai.ts +12 -1
  79. package/src/console/server/app.ts +10 -1
  80. package/src/console/server/decisions-flows.ts +157 -0
  81. package/src/console/server/decisions.test.ts +66 -0
  82. package/src/console/server/decisions.ts +229 -0
  83. package/src/console/server/flows.ts +50 -2
  84. package/src/console/server/invoke-user-flow.ts +9 -0
  85. package/src/console/server/runs-ingest.ts +16 -0
  86. package/src/console/server/serve.ts +5 -0
  87. package/src/console/server/state.ts +25 -1
  88. package/src/console/server/store-stats.test.ts +47 -0
  89. package/src/console/server/store-stats.ts +92 -18
  90. package/src/console/ui-next/dist/assets/access-page-C_N4qvai.js +4 -0
  91. package/src/console/ui-next/dist/assets/{agent-disclosure-Bkohc_8X.js → agent-disclosure-Cq1TxniW.js} +1 -1
  92. package/src/console/ui-next/dist/assets/{cache-glyph-rL0lHxat.js → cache-glyph-BaI4uxZz.js} +1 -1
  93. package/src/console/ui-next/dist/assets/{call-pii-button-Deo4PP18.js → call-pii-button-DNyK7IIY.js} +1 -1
  94. package/src/console/ui-next/dist/assets/{collapsible-CoJ6amHf.js → collapsible-CRhBJMZR.js} +1 -1
  95. package/src/console/ui-next/dist/assets/confirm-sheet-DZfuJXP4.js +1 -0
  96. package/src/console/ui-next/dist/assets/copy-inline-button-BTjPVjRT.js +1 -0
  97. package/src/console/ui-next/dist/assets/decisions-page-D9twj8Xy.js +1 -0
  98. package/src/console/ui-next/dist/assets/detail-header-Dk5LipF6.js +1 -0
  99. package/src/console/ui-next/dist/assets/dropdown-menu-CRGrj5JU.js +1 -0
  100. package/src/console/ui-next/dist/assets/duration-tone-CsHWlVPU.js +9 -0
  101. package/src/console/ui-next/dist/assets/element-icons-C6t8Vlml.js +1 -0
  102. package/src/console/ui-next/dist/assets/explorer-chrome-Dslh2yE8.js +1 -0
  103. package/src/console/ui-next/dist/assets/explorer-empty-CIVg7Jgb.js +1 -0
  104. package/src/console/ui-next/dist/assets/flows-page-ZaTJAhR9.js +1 -0
  105. package/src/console/ui-next/dist/assets/{highlighted-json-CPYBzDh0.js → highlighted-json-DQ-EMAfz.js} +1 -1
  106. package/src/console/ui-next/dist/assets/{http-method-DTPevKmM.js → http-method-Cn_Fl79s.js} +1 -1
  107. package/src/console/ui-next/dist/assets/index-BlrN49Hs.css +2 -0
  108. package/src/console/ui-next/dist/assets/index-CmRFeWdT.js +58 -0
  109. package/src/console/ui-next/dist/assets/observability-page-Cn6R_dXz.js +8 -0
  110. package/src/console/ui-next/dist/assets/{replica-lag-BM27lXld.js → replica-lag-Bx6EZhSe.js} +7 -7
  111. package/src/console/ui-next/dist/assets/request-meta-DmdiUrfh.js +1 -0
  112. package/src/console/ui-next/dist/assets/shortcut-keys-DTE1sjTC.js +1 -0
  113. package/src/console/ui-next/dist/assets/store-page-8P6vGXnn.js +41 -0
  114. package/src/console/ui-next/dist/assets/trace-detail-sheet-BfGvpFSv.js +2 -0
  115. package/src/console/ui-next/dist/assets/tree-expand-toggle-CWdUHbc0.js +55 -0
  116. package/src/console/ui-next/dist/assets/units-page-CZOFZzay.js +1 -0
  117. package/src/console/ui-next/dist/assets/use-vault-list-BAyQG8Re.js +1 -0
  118. package/src/console/ui-next/dist/assets/vault-page-ki_ishmX.js +2 -0
  119. package/src/console/ui-next/dist/index.html +4 -3
  120. package/src/console/ui-next/seed-parked-approval.ts +126 -0
  121. package/src/console/ui-next/src/client.ts +224 -1
  122. package/src/console/ui-next/src/components/explorer/detail-header.tsx +9 -0
  123. package/src/console/ui-next/src/components/explorer/explorer-start-toggle.tsx +5 -1
  124. package/src/console/ui-next/src/components/ui/sheet-form.tsx +21 -12
  125. package/src/console/ui-next/src/features/flows/decisions/decisions-page.tsx +216 -0
  126. package/src/console/ui-next/src/features/flows/decisions/resolve.test.ts +48 -0
  127. package/src/console/ui-next/src/features/flows/decisions/resolve.ts +111 -0
  128. package/src/console/ui-next/src/features/flows/flows-page.tsx +10 -0
  129. package/src/console/ui-next/src/features/flows/graph/element-map.ts +1 -0
  130. package/src/console/ui-next/src/features/flows/traces/effect-kind.ts +6 -0
  131. package/src/console/ui-next/src/features/flows/traces/effect-summary.test.ts +24 -0
  132. package/src/console/ui-next/src/features/flows/traces/effect-summary.ts +24 -0
  133. package/src/console/ui-next/src/features/flows/traces/http-status.ts +58 -0
  134. package/src/console/ui-next/src/features/flows/traces/request-client-card.tsx +355 -0
  135. package/src/console/ui-next/src/features/flows/traces/request-client.test.ts +114 -0
  136. package/src/console/ui-next/src/features/flows/traces/request-client.ts +423 -0
  137. package/src/console/ui-next/src/features/flows/traces/request-input-view.test.ts +52 -6
  138. package/src/console/ui-next/src/features/flows/traces/request-input-view.ts +85 -19
  139. package/src/console/ui-next/src/features/flows/traces/trace-detail-sheet.tsx +505 -80
  140. package/src/console/ui-next/src/features/flows/traces/trace-lanes.test.ts +61 -0
  141. package/src/console/ui-next/src/features/flows/traces/trace-lanes.ts +78 -0
  142. package/src/console/ui-next/src/features/flows/traces/trace-nav.test.ts +48 -0
  143. package/src/console/ui-next/src/features/flows/traces/trace-nav.ts +57 -0
  144. package/src/console/ui-next/src/features/flows/traces/trace-request-section.tsx +275 -96
  145. package/src/console/ui-next/src/features/flows/traces/traces-pane.tsx +16 -2
  146. package/src/console/ui-next/src/features/observability/detail/ai-runs.tsx +369 -0
  147. package/src/console/ui-next/src/features/observability/observability-page.tsx +31 -1
  148. package/src/console/ui-next/src/features/observability/state/observability-selection.ts +18 -3
  149. package/src/console/ui-next/src/features/store/performance/kv-performance-panel.tsx +12 -1
  150. package/src/console/ui-next/src/features/store/performance/performance-panel.tsx +14 -1
  151. package/src/console/ui-next/src/features/units/call/call-api-panel.tsx +1 -1
  152. package/src/console/ui-next/src/features/units/detail/flow-contract-panel.tsx +6 -2
  153. package/src/console/ui-next/src/features/units/explorer/units-tree.tsx +73 -18
  154. package/src/console/ui-next/src/features/units/lib/unit-tree.test.ts +21 -0
  155. package/src/console/ui-next/src/features/units/lib/unit-tree.ts +82 -0
  156. package/src/console/ui-next/src/features/units/units-page.tsx +25 -7
  157. package/src/console/ui-next/src/router.tsx +17 -0
  158. package/src/console/ui-next/ui-next-seed-runs.ts +23 -0
  159. package/src/console/ui-next/vite-console-kernel-plugin.ts +43 -3
  160. package/src/console/ui-next/vite.config.ts +9 -0
  161. package/src/docker/recipes/dragonfly.ts +3 -2
  162. package/src/docker/recipes/redis.ts +1 -1
  163. package/src/drivers/ai-anthropic.ts +212 -21
  164. package/src/drivers/ai-mock.ts +34 -1
  165. package/src/drivers/ai-openai-compatible.ts +67 -26
  166. package/src/drivers/ai-preconnect.ts +18 -0
  167. package/src/drivers/ai-stream.test.ts +62 -0
  168. package/src/drivers/ai-types.ts +20 -0
  169. package/src/drivers/journal-postgres.test.ts +22 -1
  170. package/src/drivers/journal-postgres.ts +511 -13
  171. package/src/drivers/memory-ddl.test.ts +18 -0
  172. package/src/drivers/memory.ts +21 -1
  173. package/src/drivers/pg-rls.test.ts +31 -0
  174. package/src/drivers/pg-rls.ts +15 -0
  175. package/src/drivers/postgres.test.ts +9 -0
  176. package/src/drivers/postgres.ts +49 -11
  177. package/src/drivers/signal-compete.test.ts +234 -0
  178. package/src/drivers/signal-postgres.ts +39 -19
  179. package/src/drivers/signal-redis.ts +167 -11
  180. package/src/drivers/signal-types.ts +12 -0
  181. package/src/elements/ai/agent-event-slot.ts +27 -0
  182. package/src/elements/ai/approval-http.ts +207 -0
  183. package/src/elements/ai/approval.test.ts +741 -0
  184. package/src/elements/ai/approval.ts +228 -0
  185. package/src/elements/ai/decisions/bind.ts +163 -0
  186. package/src/elements/ai/decisions/certificate.test.ts +291 -0
  187. package/src/elements/ai/decisions/certificate.ts +377 -0
  188. package/src/elements/ai/decisions/certify.ts +314 -0
  189. package/src/elements/ai/decisions/decide.test.ts +953 -0
  190. package/src/elements/ai/decisions/e2e.test.ts +399 -0
  191. package/src/elements/ai/decisions/export.test.ts +120 -0
  192. package/src/elements/ai/decisions/export.ts +146 -0
  193. package/src/elements/ai/decisions/fixtures/openrouter-request.json +24 -0
  194. package/src/elements/ai/decisions/fixtures/openrouter-response.json +22 -0
  195. package/src/elements/ai/decisions/fixtures/typesafe-request.json +19 -0
  196. package/src/elements/ai/decisions/fixtures/typesafe-response.json +13 -0
  197. package/src/elements/ai/decisions/http.test.ts +154 -0
  198. package/src/elements/ai/decisions/http.ts +240 -0
  199. package/src/elements/ai/decisions/labels.test.ts +282 -0
  200. package/src/elements/ai/decisions/labels.ts +257 -0
  201. package/src/elements/ai/decisions/openrouter.live.test.ts +136 -0
  202. package/src/elements/ai/decisions/openrouter.ts +36 -0
  203. package/src/elements/ai/decisions/provider.ts +102 -0
  204. package/src/elements/ai/decisions/typesafe.ts +36 -0
  205. package/src/elements/ai/declare.ts +252 -1
  206. package/src/elements/ai/events.test.ts +379 -0
  207. package/src/elements/ai/events.ts +138 -0
  208. package/src/elements/ai/mcp-protocol.ts +5 -6
  209. package/src/elements/ai/run-events.test.ts +461 -0
  210. package/src/elements/ai/run-events.ts +522 -0
  211. package/src/elements/ai/runtime.ts +1187 -105
  212. package/src/elements/ai/stream-turn.ts +214 -0
  213. package/src/elements/ai/stream.live.test.ts +76 -0
  214. package/src/elements/ai/subagent.test.ts +136 -0
  215. package/src/elements/ai.test.ts +497 -3
  216. package/src/elements/ai.ts +16 -1
  217. package/src/elements/channel/runtime.ts +11 -0
  218. package/src/elements/channel/sql-ledger.ts +251 -0
  219. package/src/elements/clock/durable.ts +27 -1
  220. package/src/elements/signal/runtime.ts +9 -0
  221. package/src/elements/signal.test.ts +1 -0
  222. package/src/elements/store/cache.test.ts +120 -15
  223. package/src/elements/store/cache.ts +200 -39
  224. package/src/elements/store/prepare-row.test.ts +6 -2
  225. package/src/elements/store/sql-session.test.ts +53 -0
  226. package/src/elements/store/sql-session.ts +206 -10
  227. package/src/elements/store.ts +1 -0
  228. package/src/i18n/catalogs/ar.ts +5 -0
  229. package/src/i18n/catalogs/en.ts +5 -0
  230. package/src/index.ts +2 -0
  231. package/src/kernel/agent-event-store.ts +448 -0
  232. package/src/kernel/app.ts +135 -17
  233. package/src/kernel/auto-cache.test.ts +228 -0
  234. package/src/kernel/boot-bind/ai.ts +3 -0
  235. package/src/kernel/boot-bind/channel.ts +63 -2
  236. package/src/kernel/boot-bind/honor-config.test.ts +40 -10
  237. package/src/kernel/boot-bind/signal.ts +61 -25
  238. package/src/kernel/boot-bind/store.test.ts +26 -0
  239. package/src/kernel/boot-bind/store.ts +82 -6
  240. package/src/kernel/boot.ts +31 -6
  241. package/src/kernel/builtin-errors.ts +2 -0
  242. package/src/kernel/capability.ts +3 -0
  243. package/src/kernel/decision-label-store.ts +441 -0
  244. package/src/kernel/effects.test.ts +2 -1
  245. package/src/kernel/effects.ts +13 -1
  246. package/src/kernel/element-registries.ts +3 -0
  247. package/src/kernel/errors-compiler.ts +11 -0
  248. package/src/kernel/errors-text.ts +20 -0
  249. package/src/kernel/errors.ts +10 -0
  250. package/src/kernel/flow.test.ts +2 -3
  251. package/src/kernel/flow.ts +33 -3
  252. package/src/kernel/fx-call-types.test.ts +32 -0
  253. package/src/kernel/fx-decide.ts +765 -0
  254. package/src/kernel/fx-sql-handle.ts +46 -7
  255. package/src/kernel/fx.test.ts +13 -8
  256. package/src/kernel/fx.ts +339 -45
  257. package/src/kernel/http-frame.test.ts +94 -0
  258. package/src/kernel/http-frame.ts +203 -0
  259. package/src/kernel/idempotency.test.ts +2 -1
  260. package/src/kernel/journal.test.ts +114 -0
  261. package/src/kernel/journal.ts +471 -51
  262. package/src/kernel/json-result.ts +10 -0
  263. package/src/kernel/pipeline-tenant.ts +5 -1
  264. package/src/kernel/pipeline.test.ts +45 -0
  265. package/src/kernel/pipeline.ts +5 -0
  266. package/src/kernel/signal-tx.ts +28 -0
  267. package/src/kernel/sse-id.ts +32 -0
  268. package/src/kernel/store-transaction.test.ts +95 -0
  269. package/src/manifest/diff.ts +1 -0
  270. package/src/manifest/types.ts +29 -2
  271. package/src/mcp/ai-tools.test.ts +202 -0
  272. package/src/mcp/authorization.ts +66 -0
  273. package/src/mcp/docs-server.ts +19 -2
  274. package/src/mcp/mcp.test.ts +83 -0
  275. package/src/mcp/protocol.ts +8 -2
  276. package/src/mcp/server.ts +23 -2
  277. package/src/mcp/session.ts +3 -0
  278. package/src/mcp/tools.ts +168 -0
  279. package/src/mcp/versions.ts +60 -0
  280. package/src/plugins/index.ts +1 -0
  281. package/src/plugins/mena.ts +56 -0
  282. package/src/release/http-graph.test.ts +2 -0
  283. package/src/release/http-graph.ts +5 -0
  284. package/src/release/measure.ts +39 -14
  285. package/src/runs/collect.ts +4 -1
  286. package/src/runs/parquet.test.ts +27 -1
  287. package/src/runs/parquet.ts +19 -0
  288. package/src/runs/types.ts +31 -0
  289. package/src/runtime/json-code-block.test.ts +106 -47
  290. package/src/runtime/json-code-block.ts +1209 -46
  291. package/src/term.test.ts +13 -0
  292. package/src/term.ts +81 -49
  293. package/src/console/ui-next/dist/assets/PlusSignIcon-CwG3nxfu.js +0 -1
  294. package/src/console/ui-next/dist/assets/access-page-Ze6ckjdd.js +0 -4
  295. package/src/console/ui-next/dist/assets/copy-inline-button-CWG5_ZOh.js +0 -1
  296. package/src/console/ui-next/dist/assets/detail-header-b_ZzIsmU.js +0 -1
  297. package/src/console/ui-next/dist/assets/dropdown-menu-nwXEO1Ac.js +0 -1
  298. package/src/console/ui-next/dist/assets/duration-tone-BbQ_8z50.js +0 -9
  299. package/src/console/ui-next/dist/assets/element-icons-CwyLpVXz.js +0 -1
  300. package/src/console/ui-next/dist/assets/explorer-empty-C8sSCqYT.js +0 -1
  301. package/src/console/ui-next/dist/assets/flows-page-D2E7BtKK.js +0 -1
  302. package/src/console/ui-next/dist/assets/index-VxoEz295.css +0 -2
  303. package/src/console/ui-next/dist/assets/index-vTuwmeQz.js +0 -58
  304. package/src/console/ui-next/dist/assets/observability-page-SJTSzHFJ.js +0 -4
  305. package/src/console/ui-next/dist/assets/request-meta-BjFT7DNl.js +0 -1
  306. package/src/console/ui-next/dist/assets/shortcut-keys-CUNegEV4.js +0 -1
  307. package/src/console/ui-next/dist/assets/store-page-Qj9ThRE-.js +0 -41
  308. package/src/console/ui-next/dist/assets/trace-detail-sheet-Cmitq3da.js +0 -2
  309. package/src/console/ui-next/dist/assets/tree-expand-toggle-CbDIB-7x.js +0 -55
  310. package/src/console/ui-next/dist/assets/units-page-_PuYqFty.js +0 -1
  311. package/src/console/ui-next/dist/assets/use-vault-list-Cs45Czkt.js +0 -1
  312. package/src/console/ui-next/dist/assets/vault-page-BOMr0go9.js +0 -2
package/AGENTS.md CHANGED
@@ -55,6 +55,13 @@ We build only what genuinely does not exist: the effect system, the Manifest and
55
55
 
56
56
  A direct `node:` import (or any other side-channel I/O) in element or flow code is a **defect**. `fx` is the single door to the outside world; effects are inferred from what a Flow touches through it. Deterministic tests, least privilege, cache invalidation, live queries, and durability all depend on this invariant.
57
57
 
58
+ ## AI
59
+
60
+ - `fx.ask` runs a prompt (repair, budgets). `fx.run` runs an agent (`maxSteps`, `maxCostPerRun`, `stopReason`). `fx.decide` runs a decision.
61
+ - A tool with `approval` requires `durable: true`. Resolve it in the Console or on the approval routes. Do not resolve it from MCP.
62
+ - Stream with `return fx.json.stream(fx.run(agent, input, { stream: true }))`. Follow with `GET /agent/runs/:runId/events` (`Last-Event-ID`). Client: `okengine/client/agent`. React: `useAgentRun`.
63
+ - `fx.decide` takes exactly one of `review` or `onUncertain: "abstain"`. Review only inside a durable non-HTTP Flow (emit to a consumer). Autonomy needs `{ maxError, audit }` and comes only from `oke-decisions.lock.json` (`oke eval --certify` / `oke decide promote`).
64
+
58
65
  ## Ports
59
66
 
60
67
  | Port | Surface |
@@ -185,6 +185,11 @@
185
185
  "type": "array",
186
186
  "items": { "$ref": "#/$defs/FlowRef" },
187
187
  "uniqueItems": true
188
+ },
189
+ "decides": {
190
+ "type": "array",
191
+ "items": { "type": "string", "minLength": 1 },
192
+ "uniqueItems": true
188
193
  }
189
194
  }
190
195
  },
@@ -666,6 +671,7 @@
666
671
  "version": { "type": "integer", "minimum": 1 },
667
672
  "evals": { "type": "string", "minLength": 1 },
668
673
  "budget": { "$ref": "#/$defs/AiPromptBudget" },
674
+ "repair": { "type": "integer", "enum": [0, 1] },
669
675
  "model": { "type": "string", "minLength": 1 },
670
676
  "in": { "$ref": "#/$defs/JsonSchema" },
671
677
  "out": { "$ref": "#/$defs/JsonSchema" }
@@ -680,11 +686,44 @@
680
686
  "items": { "$ref": "#/$defs/FlowRef" },
681
687
  "uniqueItems": true
682
688
  },
689
+ "approvals": {
690
+ "type": "object",
691
+ "propertyNames": { "type": "string", "minLength": 1 },
692
+ "additionalProperties": { "const": true }
693
+ },
683
694
  "maxSteps": { "type": "integer", "minimum": 1 },
695
+ "maxDepth": { "type": "integer", "minimum": 1 },
684
696
  "model": { "type": "string", "minLength": 1 },
685
697
  "budget": { "$ref": "#/$defs/AiPromptBudget" }
686
698
  }
687
699
  },
700
+ "AiDecision": {
701
+ "type": "object",
702
+ "additionalProperties": false,
703
+ "required": ["mode", "questions"],
704
+ "properties": {
705
+ "mode": { "enum": ["review", "abstain"] },
706
+ "review": { "type": "string", "minLength": 1 },
707
+ "model": { "type": "string", "minLength": 1 },
708
+ "driverId": { "enum": ["openrouter", "typesafe"] },
709
+ "questions": {
710
+ "type": "array",
711
+ "items": { "type": "string", "minLength": 1 },
712
+ "uniqueItems": true
713
+ },
714
+ "evals": { "type": "string", "minLength": 1 },
715
+ "autonomy": {
716
+ "type": "object",
717
+ "additionalProperties": false,
718
+ "required": ["maxError", "audit"],
719
+ "properties": {
720
+ "maxError": { "type": "number", "exclusiveMinimum": 0, "maximum": 1 },
721
+ "audit": { "type": "number", "minimum": 0, "maximum": 1 },
722
+ "risk": { "type": "number", "exclusiveMinimum": 0, "maximum": 1 }
723
+ }
724
+ }
725
+ }
726
+ },
688
727
  "Ai": {
689
728
  "type": "object",
690
729
  "additionalProperties": false,
@@ -703,6 +742,11 @@
703
742
  "type": "object",
704
743
  "propertyNames": { "type": "string", "minLength": 1 },
705
744
  "additionalProperties": { "$ref": "#/$defs/AiAgent" }
745
+ },
746
+ "decisions": {
747
+ "type": "object",
748
+ "propertyNames": { "type": "string", "minLength": 1 },
749
+ "additionalProperties": { "$ref": "#/$defs/AiDecision" }
706
750
  }
707
751
  }
708
752
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "okengine",
3
- "version": "0.22.0",
3
+ "version": "0.23.1",
4
4
  "description": "One law. Eight elements. One contract. The backend model stays small; operational surfaces are derived from it instead of maintained separately.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -73,6 +73,7 @@
73
73
  "./client": "./src/client/index.ts",
74
74
  "./client/auth": "./src/client/auth.ts",
75
75
  "./client/explain": "./src/client/explain.ts",
76
+ "./client/agent": "./src/client/agent.ts",
76
77
  "./client-react": "./src/client-react/index.ts",
77
78
  "./test": "./src/test/index.ts",
78
79
  "./testing": {
@@ -104,36 +105,46 @@
104
105
  }
105
106
  },
106
107
  "scripts": {
107
- "typecheck": "tsc --noEmit && tsc --noEmit -p tests/console/tsconfig.ui-next.json && tsc --noEmit -p src/console/ui-next && bun run --cwd packages/create-oke typecheck && bun run --cwd examples/keel typecheck",
108
- "lint": "oxlint --quiet",
108
+ "typecheck": "turbo run typecheck typecheck:framework typecheck:console typecheck:console-tests",
109
+ "typecheck:framework": "tsc --noEmit",
110
+ "typecheck:console": "tsc --noEmit -p src/console/ui-next",
111
+ "typecheck:console-tests": "tsc --noEmit -p tests/console/tsconfig.ui-next.json",
112
+ "lint": "turbo run lint:repo",
113
+ "lint:repo": "oxlint --quiet",
109
114
  "lint:fix": "oxlint --fix",
110
115
  "fmt": "oxfmt",
111
116
  "format": "oxfmt",
112
- "fmt:check": "oxfmt --check",
113
- "test": "bun test --pass-with-no-tests",
117
+ "fmt:check": "turbo run fmt:check:repo",
118
+ "fmt:check:repo": "oxfmt --check",
119
+ "test": "turbo run test:framework",
120
+ "test:framework": "bun test --pass-with-no-tests",
114
121
  "test:coverage": "bun test --coverage --pass-with-no-tests",
115
122
  "test:console:smoke": "bunx playwright test tests/console/smoke.spec.ts",
116
123
  "test:console:setup": "bunx playwright test --config playwright.ui-next.config.ts",
117
124
  "test:console:setup:report": "bunx playwright show-report playwright-report/ui-next",
118
- "build": "bunx --bun vite build --config src/console/ui-next/vite.config.ts",
119
- "dev:console": "bunx --bun vite --config src/console/ui-next/vite.config.ts",
120
- "dev:console:seed": "OKE_CONSOLE_SEEDED=1 bunx --bun vite --config src/console/ui-next/vite.config.ts",
121
- "dev:console:fresh": "OKE_CONSOLE_FRESH=1 bunx --bun vite --config src/console/ui-next/vite.config.ts",
122
- "dev:console:fresh:seed": "OKE_CONSOLE_FRESH=1 OKE_CONSOLE_SEEDED=1 bunx --bun vite --config src/console/ui-next/vite.config.ts",
123
- "dev:keel": "bun run --cwd examples/keel dev",
124
- "dev:keel:seed": "bun run --cwd examples/keel seed",
125
- "dev:keel:reset": "bun run --cwd examples/keel reset",
126
- "test:keel": "bun run --cwd examples/keel test",
127
- "test:keel:docker": "OKE_TEST_DOCKER=1 bun run --cwd examples/keel test",
128
- "build:lib": "bun src/release/build-lib.ts",
125
+ "build": "turbo run build:console",
126
+ "build:console": "bunx --bun vite build --config src/console/ui-next/vite.config.ts",
127
+ "dev:console": "turbo run dev:console:repo",
128
+ "dev:console:repo": "bunx --bun vite --config src/console/ui-next/vite.config.ts",
129
+ "dev:console:seed": "OKE_CONSOLE_SEEDED=1 turbo run dev:console:repo",
130
+ "dev:console:fresh": "OKE_CONSOLE_FRESH=1 turbo run dev:console:repo",
131
+ "dev:console:fresh:seed": "OKE_CONSOLE_FRESH=1 OKE_CONSOLE_SEEDED=1 turbo run dev:console:repo",
132
+ "dev:keel": "turbo run dev --filter=@oke/example-keel",
133
+ "dev:keel:seed": "turbo run seed --filter=@oke/example-keel",
134
+ "dev:keel:reset": "turbo run reset --filter=@oke/example-keel",
135
+ "test:keel": "turbo run test --filter=@oke/example-keel",
136
+ "test:keel:docker": "OKE_TEST_DOCKER=1 turbo run test --filter=@oke/example-keel",
137
+ "build:lib": "turbo run build:lib:repo",
138
+ "build:lib:repo": "bun src/release/build-lib.ts",
129
139
  "prepack": "bun run build && bun run build:lib",
130
140
  "bench": "bun test ./src/runtime/cold-start.bench.ts src/client/budget.test.ts src/console/budget.test.ts src/kernel/budget.test.ts src/kernel/routing-budget.test.ts src/runs/bench.test.ts src/okid.bench.test.ts",
131
141
  "bench:load": "OKE_BENCH=1 bun test ./src/bench/*.bench.ts --timeout 600000 --pass-with-no-tests",
132
142
  "budgets": "bun src/release/publish.ts",
133
143
  "budgets:core": "bun test src/kernel/budget.test.ts src/client/budget.test.ts",
134
144
  "gate": "PUBLISH_GATE=1 bun test src/cli/doc-staleness.test.ts src/cli/competitor-mention-removal.test.ts src/drivers/vault-driver-removal.test.ts src/kernel/errors.registry.test.ts src/upgrade/codemods.test.ts scripts/publish.gate.test.ts",
135
- "dev": "bun run --cwd site dev",
136
- "site:build": "bun run --cwd site build",
145
+ "dev": "turbo run dev --filter=site",
146
+ "site:build": "turbo run build --filter=site",
147
+ "boundaries": "turbo boundaries",
137
148
  "verify": "bun run lint && bun run fmt:check && bun run typecheck && bun run test && bun run gate && bun run site:build",
138
149
  "ci": "bun scripts/ci.ts",
139
150
  "bump": "bun run scripts/bump-version.ts",
@@ -213,6 +224,7 @@
213
224
  "shiki": "^4.4.3",
214
225
  "tailwind-merge": "^3.7.0",
215
226
  "tailwindcss": "^4.3.3",
227
+ "turbo": "^2.11.4",
216
228
  "tw-animate-css": "^1.4.0",
217
229
  "typescript": "^7.0.2",
218
230
  "valibot": "^1.5.0",
@@ -285,5 +297,6 @@
285
297
  },
286
298
  "engines": {
287
299
  "bun": ">=1.4.2"
288
- }
300
+ },
301
+ "packageManager": "bun@1.4.2"
289
302
  }
@@ -16,7 +16,7 @@ Two genuinely distinct things share the protocol in OKE:
16
16
 
17
17
  OKE does not create separate security models for users, operators, and agents. They enter the same execution model through different triggers and planes.
18
18
 
19
- The server on **6535** speaks JSON-RPC over HTTP (MCP protocol `2024-11-05`), requires a Bearer token **even on localhost**, and never forwards that token upstream — adapters receive structured operator ids instead.
19
+ The server on **6535** speaks JSON-RPC over HTTP. It implements `initialize`, `ping`, `tools/list`, and `tools/call`, and advertises protocol `2024-11-05`. A client that sends another `protocolVersion` is rejected. An omitted version gets `2024-11-05`. It requires a Bearer token **even on localhost**, and never forwards that token upstream — adapters receive structured operator ids instead. The outbound client that calls external MCP servers probes `2026-07-28` (`_meta` on each request) and falls back to a `2024-11-05` `initialize`. That probe is not what this server advertises.
20
20
 
21
21
  <Callout title="The one rule">
22
22
  MCP inherits the operator's capability and can never exceed it. Server-level controls alone are
@@ -26,15 +26,19 @@ The server on **6535** speaks JSON-RPC over HTTP (MCP protocol `2024-11-05`), re
26
26
 
27
27
  ## Read tools
28
28
 
29
- Default-safe — they return inert data envelopes, never live handles:
30
-
31
- | Tool | Returns | Scope (any of) |
32
- | ------------------ | ---------------------------------------------- | --------------------------------------------- |
33
- | `oke.manifest.get` | The current Manifest catalogue | `mcp:manifest:read` · `console:manifest:read` |
34
- | `oke.schema.get` | In/out/error schemas for one flow (`flowId`) | `mcp:schema:read` · `console:manifest:read` |
35
- | `oke.effects.get` | Declared effects for one flow (`flowId`) | `mcp:effects:read` · `console:manifest:read` |
36
- | `oke.traces.list` | Recent runs (`limit` ≤ 200, optional `flowId`) | `mcp:traces:read` · `console:runs:read` |
37
- | `oke.traces.get` | One run/trace record (`runId`) | `mcp:traces:read` · `console:runs:read` |
29
+ Default-safe — they return inert data envelopes, never live handles. Approving a tool, resolving a review, and promoting a decision are not tools. Those stay with a person in the Console or the CLI.
30
+
31
+ | Tool | Returns | Scope (any of) |
32
+ | ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------- |
33
+ | `oke.manifest.get` | The current Manifest catalogue | `mcp:manifest:read` · `console:manifest:read` |
34
+ | `oke.schema.get` | In/out/error schemas for one flow (`flowId`) | `mcp:schema:read` · `console:manifest:read` |
35
+ | `oke.effects.get` | Declared effects for one flow (`flowId`) | `mcp:effects:read` · `console:manifest:read` |
36
+ | `oke.traces.list` | Recent runs (`limit` ≤ 200, optional `flowId`) | `mcp:traces:read` · `console:runs:read` |
37
+ | `oke.traces.get` | One run/trace record (`runId`) | `mcp:traces:read` · `console:runs:read` |
38
+ | `oke.ai.runs.list` | Agent runs for the token's tenant (`limit` ≤ 200). `console:*` or `mcp:*` may omit `tenant` or name another one. PII and secrets are masked. | `mcp:ai:read` · `console:runs:read` |
39
+ | `oke.ai.runs.get` | One agent run plus its follow events (`runId`). Same tenant rule. Args, trail, and events are masked. | `mcp:ai:read` · `console:runs:read` |
40
+ | `oke.ai.approvals.list` | Pending tool approvals for the token's tenant. Same operator rule. Approval args are masked. | `mcp:ai:read` · `console:runs:read` |
41
+ | `oke.decisions.list` | Decision state, pending count, metrics, and drift for the token's tenant. Same operator rule. Inputs are masked. | `mcp:decisions:read` · `console:runs:read` |
38
42
 
39
43
  ## Write tools — confirmed, every single call
40
44
 
@@ -23,7 +23,7 @@ Contributor-only skills in the same tree (not required for app authors):
23
23
 
24
24
  ## AGENTS.md — the root contract
25
25
 
26
- Every OKE app's repo carries an `AGENTS.md` that agents (Cursor, Claude Code, and peers) read at session start. It is deliberately short and absolute: every backend behavior is a Flow (`on(Trigger) → Effects`), there are eight elements bound to one contract, all world access goes through `fx`, drivers are named after protocols, and the ports/budgets are fixed. Its closing rule is the one that keeps agents honest: **if the documentation is silent, stop and ask** — never invent the API.
26
+ Every OKE app's repo carries an `AGENTS.md` that agents (Cursor, Claude Code, and peers) read at session start. It is deliberately short and absolute: every backend behavior is a Flow (`on(Trigger) → Effects`), there are eight elements bound to one contract, all world access goes through `fx`, drivers are named after protocols, and the ports/budgets are fixed. The AI section separates `fx.ask`, `fx.run`, and `fx.decide`: tool approvals need `durable: true` and a human resolve, streams follow `GET /agent/runs/:runId/events`, and autonomy comes only from `oke-decisions.lock.json` (`oke eval --certify` writes the certificate; `oke decide promote` installs it). Its closing rule is the one that keeps agents honest: **if the documentation is silent, stop and ask** — never invent the API.
27
27
 
28
28
  ## Skills — installable know-how
29
29
 
@@ -77,9 +77,9 @@ when inference does not see `fx.run`.
77
77
  <Step>
78
78
  ### Bound termination
79
79
 
80
- Default `maxSteps` is **6** when omitted. Hitting the step cap ends the loop; exceeding
81
- `budget.maxCostPerRun` throws `AiBudgetExceededError`:
82
- `ai: agent "…" exceeded maxCostPerRun N`.
80
+ Default `maxSteps` is **6**. `stopReason` is `completed`, `max_steps` (`ok: false`),
81
+ `budget` (partial trail, no throw), or `error` (a thrown tool, rethrown). A denial fed
82
+ back to the model stays `completed`.
83
83
 
84
84
  </Step>
85
85
 
@@ -159,23 +159,66 @@ ai.agent("planner", {
159
159
 
160
160
  ## Options
161
161
 
162
- | Option | Type | Default | Meaning |
163
- | ---------- | ------------------------------------- | ----------- | ---------------------------- |
164
- | `model` | `AiModelDecl` \| `string` | first model | Logical binding for the loop |
165
- | `tools` | Flow / MCP refs | `[]` | Callable via `fx.call` |
166
- | `maxSteps` | `number` | `6` | Hard cap on tool rounds |
167
- | `budget` | `{ maxCostPerCall?, maxCostPerRun? }` | — | Cost contracts for the run |
162
+ | Option | Type | Default | Meaning |
163
+ | ---------- | ------------------------------------------------------------ | ----------- | ---------------------------- |
164
+ | `model` | `AiModelDecl` \| `string` | first model | Logical binding for the loop |
165
+ | `tools` | Flow ref, MCP ref, or `{ name, approval?, gate?, timeout? }` | `[]` | Callable via `fx.call` |
166
+ | `maxSteps` | `number` | `6` | Hard cap on tool rounds |
167
+ | `maxDepth` | `number` | `3` | Nested agent limit |
168
+ | `budget` | `{ maxCostPerCall?, maxCostPerRun? }` | — | Cost contracts for the run |
168
169
 
169
170
  ## `fx.run` input
170
171
 
171
- Pass a string or `{ message: string }` (and any extra fields your tools need in context). The
172
- agent declaration does **not** take Zod `in` / `out` — validate on the surrounding Flow.
172
+ Pass a string, `{ message }`, or `{ messages }` (user, assistant, and tool turns). Passing both
173
+ `message` and `messages` throws. History stays in your Store — `fx.run` does not persist it.
173
174
 
174
175
  ```typescript
175
176
  await fx.run(supportAgent, "Summarize open tickets");
176
177
  await fx.run(supportAgent, { message: "Summarize open tickets" });
178
+ await fx.run(supportAgent, {
179
+ messages: [
180
+ { role: "user", content: "Summarize open tickets" },
181
+ { role: "assistant", content: "There are 3." },
182
+ { role: "user", content: "Open the oldest." },
183
+ ],
184
+ });
185
+ ```
186
+
187
+ ## Agents as tools
188
+
189
+ Another agent can sit in `tools`. The child uses its own `maxSteps`. Its cost cap is the
190
+ smaller of its budget and what the parent has left. Past `maxDepth` (default 3) the tool
191
+ result is an error and no further child starts.
192
+
193
+ ```typescript
194
+ const lookup = ai.agent("lookup", { tools: ["orders.get"], maxSteps: 3 });
195
+ const support = ai.agent("support", { tools: [lookup, "billing.refund"] });
177
196
  ```
178
197
 
198
+ ## Tool approval
199
+
200
+ <Callout>
201
+ A tool with `approval` parks the run until someone calls `fx.agent.approve` or `fx.agent.deny`. The calling Flow must set `durable: true`. The wait defaults to `24h`, then the model sees `{ denied: true, reason: "timeout" }`.
202
+ </Callout>
203
+
204
+ ```typescript
205
+ const support = ai.agent("support", {
206
+ tools: [{ name: "billing.refund", approval: true, gate: ops, timeout: "1h" }],
207
+ });
208
+
209
+ on(
210
+ http.post("/assist"),
211
+ flow("assist", {
212
+ durable: true,
213
+ do: async (_input, fx) => fx.run(support, { message: "Refund order 14" }),
214
+ }),
215
+ );
216
+ ```
217
+
218
+ `gate` is who may resolve. A function for `approval` waits only when it returns true.
219
+ Approve may replace `args`. A second resolution is HTTP 409. Deny is not `stopReason: "denied"` —
220
+ the model continues with `{ denied: true, reason }`.
221
+
179
222
  ## Agents vs ask-with-tools
180
223
 
181
224
  | Surface | When |
@@ -195,8 +238,9 @@ Both default `maxSteps` to `6`. Denied or unknown tools surface as
195
238
  `oke()`.
196
239
  </Accordion>
197
240
 
198
- <Accordion title='ai: agent "…" exceeded maxCostPerRun'>
199
- `AiBudgetExceededError` — raise `budget.maxCostPerRun`, lower `maxSteps`, or shrink tools.
241
+ <Accordion title="The agent stopped before it finished">
242
+ `fx.run` returns the partial trail when `budget.maxCostPerRun` is spent. It does not throw. Raise
243
+ the budget, lower `maxSteps`, or shrink the tool bag.
200
244
  </Accordion>
201
245
 
202
246
  <Accordion title='ai: model requested unknown tool "…"'>
@@ -204,6 +248,10 @@ Both default `maxSteps` to `6`. Denied or unknown tools surface as
204
248
  or tighten instructions in the user `message`.
205
249
  </Accordion>
206
250
 
251
+ <Accordion title="must set durable: true">
252
+ An approval tool cannot wait in memory. Set `durable: true` on the Flow that calls `fx.run`.
253
+ </Accordion>
254
+
207
255
  <Accordion title="OKE1005 on agent runs">
208
256
  Runtime gates `fx.run` as an ask of the agent name. List `effects: { asks: ["support.assistant"] }`
209
257
  when the compiler does not infer `fx.run`.