okengine 0.21.1 → 0.23.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 (342) hide show
  1. package/AGENTS.md +11 -4
  2. package/LICENSE +202 -0
  3. package/NOTICE +2 -0
  4. package/README.md +15 -9
  5. package/manifest.v1.schema.json +54 -0
  6. package/package.json +53 -38
  7. package/site/content/docs/ai/mcp.mdx +13 -9
  8. package/site/content/docs/ai/skills.mdx +2 -2
  9. package/site/content/docs/client/calling.mdx +27 -19
  10. package/site/content/docs/client/index.mdx +1 -1
  11. package/site/content/docs/elements/ai/agents.mdx +61 -13
  12. package/site/content/docs/elements/ai/decide.mdx +536 -0
  13. package/site/content/docs/elements/ai/events.mdx +373 -0
  14. package/site/content/docs/elements/ai/index.mdx +9 -3
  15. package/site/content/docs/elements/ai/meta.json +1 -1
  16. package/site/content/docs/elements/ai/prompts.mdx +4 -2
  17. package/site/content/docs/elements/channel/email.mdx +1 -1
  18. package/site/content/docs/elements/channel/index.mdx +1 -1
  19. package/site/content/docs/elements/flow/http.mdx +4 -4
  20. package/site/content/docs/elements/flow/index.mdx +3 -3
  21. package/site/content/docs/elements/flow/meta.json +1 -1
  22. package/site/content/docs/elements/gate/auth.mdx +4 -1
  23. package/site/content/docs/elements/gate/tenancy.mdx +1 -1
  24. package/site/content/docs/elements/store/index.mdx +1 -1
  25. package/site/content/docs/elements/store/kv.mdx +5 -5
  26. package/site/content/docs/elements/vault/rotation.mdx +15 -0
  27. package/site/content/docs/plugins/otp.mdx +31 -31
  28. package/site/content/docs/recipes/dragonfly.mdx +5 -5
  29. package/site/content/docs/recipes/index.mdx +6 -6
  30. package/site/content/docs/recipes/mailpit.mdx +1 -1
  31. package/site/content/docs/recipes/meilisearch.mdx +1 -1
  32. package/site/content/docs/recipes/pgdog.mdx +1 -1
  33. package/site/content/docs/recipes/postgres.mdx +12 -8
  34. package/site/content/docs/recipes/redis.mdx +4 -4
  35. package/site/content/docs/reference/cli.mdx +2 -1
  36. package/site/content/docs/reference/configuration.mdx +11 -9
  37. package/site/content/docs/reference/errors.mdx +12 -2
  38. package/site/content/docs/reference/fx.mdx +35 -21
  39. package/site/content/docs/reference/idempotency.mdx +192 -0
  40. package/site/content/docs/reference/index.mdx +6 -1
  41. package/site/content/docs/reference/meta.json +2 -1
  42. package/site/content/docs/understand/meta.json +1 -1
  43. package/site/content/docs/{elements/flow → understand}/routing.mdx +11 -10
  44. package/site/content/docs/understand/the-architecture.mdx +14 -12
  45. package/site/content/docs/understand/try-it.mdx +3 -3
  46. package/src/auth/api-key-sql.test.ts +44 -0
  47. package/src/auth/api-key-sql.ts +1 -0
  48. package/src/auth/api-keys.ts +30 -12
  49. package/src/auth/config.ts +6 -2
  50. package/src/auth/gate-auth.test.ts +20 -0
  51. package/src/cli/agents-md.test.ts +25 -0
  52. package/src/cli/ask-vault-gaps.test.ts +38 -1
  53. package/src/cli/ask-vault-gaps.ts +35 -2
  54. package/src/cli/competitor-mention-removal.test.ts +3 -3
  55. package/src/cli/decide.ts +174 -0
  56. package/src/cli/decision-lock-watch.test.ts +45 -0
  57. package/src/cli/decision-lock-watch.ts +51 -0
  58. package/src/cli/dev-app-runner.ts +34 -8
  59. package/src/cli/dev-auth-secret.test.ts +49 -0
  60. package/src/cli/dev-auth-secret.ts +49 -0
  61. package/src/cli/dev-hot.test.ts +41 -0
  62. package/src/cli/dev-hot.ts +48 -0
  63. package/src/cli/dev.test.ts +1 -1
  64. package/src/cli/dev.ts +24 -6
  65. package/src/cli/docker-cli.test.ts +1 -1
  66. package/src/cli/eval.ts +142 -1
  67. package/src/cli/index.ts +14 -1
  68. package/src/cli/load-config.images.test.ts +12 -12
  69. package/src/cli/load-config.ts +2 -2
  70. package/src/cli/mcp-from-console.ts +48 -0
  71. package/src/cli/registry.ts +35 -1
  72. package/src/cli/vault-cmd.test.ts +23 -0
  73. package/src/cli/vault-cmd.ts +7 -0
  74. package/src/client/agent.ts +307 -0
  75. package/src/client/create.ts +18 -1
  76. package/src/client/transport.test.ts +245 -0
  77. package/src/client/transport.ts +133 -19
  78. package/src/client/types.ts +29 -3
  79. package/src/client-react/index.ts +7 -1
  80. package/src/client-react/use-agent-run.test.ts +271 -0
  81. package/src/client-react/use-agent-run.ts +193 -0
  82. package/src/compiler/ai-approval.test.ts +36 -0
  83. package/src/compiler/ai-repair.test.ts +22 -0
  84. package/src/compiler/decisions.extract.test.ts +164 -0
  85. package/src/compiler/effects-infer.ts +753 -17
  86. package/src/compiler/extract.test.ts +37 -0
  87. package/src/compiler/extract.ts +381 -24
  88. package/src/compiler/fixtures/skyport.expected.json +24 -0
  89. package/src/compiler/fx-follow.test.ts +164 -0
  90. package/src/compiler/fx-index.ts +399 -0
  91. package/src/compiler/response.ts +35 -2
  92. package/src/config/index.ts +21 -3
  93. package/src/console/server/ai-runs-flows.ts +269 -0
  94. package/src/console/server/ai-runs.test.ts +323 -0
  95. package/src/console/server/ai-runs.ts +562 -0
  96. package/src/console/server/ai.ts +12 -1
  97. package/src/console/server/app.ts +10 -1
  98. package/src/console/server/decisions-flows.ts +157 -0
  99. package/src/console/server/decisions.test.ts +66 -0
  100. package/src/console/server/decisions.ts +229 -0
  101. package/src/console/server/flows-invoke.test.ts +2 -2
  102. package/src/console/server/flows.ts +50 -2
  103. package/src/console/server/invoke-user-flow.ts +9 -0
  104. package/src/console/server/runs-ingest.ts +16 -0
  105. package/src/console/server/serve.ts +5 -0
  106. package/src/console/server/state.ts +25 -1
  107. package/src/console/server/store-stats.test.ts +47 -0
  108. package/src/console/server/store-stats.ts +92 -18
  109. package/src/console/ui-next/dist/assets/access-page-DDKkhT9v.js +4 -0
  110. package/src/console/ui-next/dist/assets/agent-disclosure-62Xts8Xi.js +1 -0
  111. package/src/console/ui-next/dist/assets/{cache-glyph-92uM5MO7.js → cache-glyph-DyeoKHKA.js} +1 -1
  112. package/src/console/ui-next/dist/assets/{call-pii-button-DtGVPtcs.js → call-pii-button-DvfpLXsU.js} +1 -1
  113. package/src/console/ui-next/dist/assets/{collapsible-DN7l6zmC.js → collapsible-BY03SeCg.js} +1 -1
  114. package/src/console/ui-next/dist/assets/confirm-sheet-DZfuJXP4.js +1 -0
  115. package/src/console/ui-next/dist/assets/copy-inline-button-BTjPVjRT.js +1 -0
  116. package/src/console/ui-next/dist/assets/decisions-page-CgkKlA56.js +1 -0
  117. package/src/console/ui-next/dist/assets/detail-header-Dk5LipF6.js +1 -0
  118. package/src/console/ui-next/dist/assets/dropdown-menu-CRGrj5JU.js +1 -0
  119. package/src/console/ui-next/dist/assets/duration-tone-Y6HLjyJ5.js +9 -0
  120. package/src/console/ui-next/dist/assets/element-icons-C6t8Vlml.js +1 -0
  121. package/src/console/ui-next/dist/assets/explorer-chrome-Dslh2yE8.js +1 -0
  122. package/src/console/ui-next/dist/assets/explorer-empty-CIVg7Jgb.js +1 -0
  123. package/src/console/ui-next/dist/assets/flows-page-DLPfNy-_.js +1 -0
  124. package/src/console/ui-next/dist/assets/{highlighted-json-BlAEVgNW.js → highlighted-json-D7nNzpgB.js} +1 -1
  125. package/src/console/ui-next/dist/assets/{http-method-BDf7OAHv.js → http-method-DdL19zzh.js} +1 -1
  126. package/src/console/ui-next/dist/assets/index-BlrN49Hs.css +2 -0
  127. package/src/console/ui-next/dist/assets/index-C0lc_s9d.js +58 -0
  128. package/src/console/ui-next/dist/assets/observability-page-CRlcyLCC.js +8 -0
  129. package/src/console/ui-next/dist/assets/{replica-lag-B3GLNVfF.js → replica-lag-Bb3FWUu9.js} +7 -7
  130. package/src/console/ui-next/dist/assets/request-meta-DYBMWhX8.js +1 -0
  131. package/src/console/ui-next/dist/assets/shortcut-keys-DTE1sjTC.js +1 -0
  132. package/src/console/ui-next/dist/assets/store-page-CcE-SXC8.js +41 -0
  133. package/src/console/ui-next/dist/assets/trace-detail-sheet-CKMSEQ4s.js +2 -0
  134. package/src/console/ui-next/dist/assets/tree-expand-toggle-QOfk0M0H.js +55 -0
  135. package/src/console/ui-next/dist/assets/units-page-DKC1CDDd.js +1 -0
  136. package/src/console/ui-next/dist/assets/use-vault-list-BAyQG8Re.js +1 -0
  137. package/src/console/ui-next/dist/assets/vault-page-B54v4Yit.js +2 -0
  138. package/src/console/ui-next/dist/index.html +4 -3
  139. package/src/console/ui-next/seed-parked-approval.ts +126 -0
  140. package/src/console/ui-next/src/client.ts +224 -1
  141. package/src/console/ui-next/src/components/explorer/detail-header.tsx +9 -0
  142. package/src/console/ui-next/src/components/explorer/explorer-start-toggle.tsx +5 -1
  143. package/src/console/ui-next/src/components/ui/sheet-form.tsx +21 -12
  144. package/src/console/ui-next/src/features/flows/decisions/decisions-page.tsx +216 -0
  145. package/src/console/ui-next/src/features/flows/decisions/resolve.test.ts +48 -0
  146. package/src/console/ui-next/src/features/flows/decisions/resolve.ts +111 -0
  147. package/src/console/ui-next/src/features/flows/flows-page.tsx +10 -0
  148. package/src/console/ui-next/src/features/flows/graph/element-map.ts +1 -0
  149. package/src/console/ui-next/src/features/flows/traces/effect-kind.ts +6 -0
  150. package/src/console/ui-next/src/features/flows/traces/effect-summary.test.ts +24 -0
  151. package/src/console/ui-next/src/features/flows/traces/effect-summary.ts +24 -0
  152. package/src/console/ui-next/src/features/flows/traces/http-status.ts +58 -0
  153. package/src/console/ui-next/src/features/flows/traces/request-client-card.tsx +355 -0
  154. package/src/console/ui-next/src/features/flows/traces/request-client.test.ts +114 -0
  155. package/src/console/ui-next/src/features/flows/traces/request-client.ts +423 -0
  156. package/src/console/ui-next/src/features/flows/traces/request-input-view.test.ts +52 -6
  157. package/src/console/ui-next/src/features/flows/traces/request-input-view.ts +85 -19
  158. package/src/console/ui-next/src/features/flows/traces/trace-detail-sheet.tsx +505 -80
  159. package/src/console/ui-next/src/features/flows/traces/trace-lanes.test.ts +61 -0
  160. package/src/console/ui-next/src/features/flows/traces/trace-lanes.ts +78 -0
  161. package/src/console/ui-next/src/features/flows/traces/trace-nav.test.ts +48 -0
  162. package/src/console/ui-next/src/features/flows/traces/trace-nav.ts +57 -0
  163. package/src/console/ui-next/src/features/flows/traces/trace-request-section.tsx +275 -96
  164. package/src/console/ui-next/src/features/flows/traces/traces-pane.tsx +16 -2
  165. package/src/console/ui-next/src/features/observability/detail/ai-runs.tsx +369 -0
  166. package/src/console/ui-next/src/features/observability/observability-page.tsx +31 -1
  167. package/src/console/ui-next/src/features/observability/state/observability-selection.ts +18 -3
  168. package/src/console/ui-next/src/features/store/performance/kv-performance-panel.tsx +12 -1
  169. package/src/console/ui-next/src/features/store/performance/performance-panel.tsx +14 -1
  170. package/src/console/ui-next/src/features/units/call/call-api-panel.tsx +1 -1
  171. package/src/console/ui-next/src/features/units/detail/flow-contract-panel.tsx +15 -2
  172. package/src/console/ui-next/src/features/units/explorer/units-tree.tsx +73 -18
  173. package/src/console/ui-next/src/features/units/lib/unit-tree.test.ts +21 -0
  174. package/src/console/ui-next/src/features/units/lib/unit-tree.ts +82 -0
  175. package/src/console/ui-next/src/features/units/units-page.tsx +25 -7
  176. package/src/console/ui-next/src/router.tsx +17 -0
  177. package/src/console/ui-next/ui-next-seed-runs.ts +23 -0
  178. package/src/console/ui-next/vite-console-kernel-plugin.ts +43 -3
  179. package/src/console/ui-next/vite.config.ts +9 -0
  180. package/src/docker/docker.test.ts +13 -13
  181. package/src/docker/images-config.test.ts +12 -12
  182. package/src/docker/recipes/dragonfly.ts +3 -2
  183. package/src/docker/recipes/redis.ts +1 -1
  184. package/src/docker/stack-id.test.ts +1 -1
  185. package/src/drivers/ai-anthropic.ts +212 -21
  186. package/src/drivers/ai-mock.ts +34 -1
  187. package/src/drivers/ai-openai-compatible.ts +67 -26
  188. package/src/drivers/ai-preconnect.ts +18 -0
  189. package/src/drivers/ai-stream.test.ts +62 -0
  190. package/src/drivers/ai-types.ts +20 -0
  191. package/src/drivers/journal-postgres.ts +455 -3
  192. package/src/drivers/meilisearch.ts +2 -0
  193. package/src/drivers/memory-ddl.test.ts +18 -0
  194. package/src/drivers/memory.ts +21 -1
  195. package/src/drivers/pg-rls.test.ts +31 -0
  196. package/src/drivers/pg-rls.ts +15 -0
  197. package/src/drivers/postgres.test.ts +9 -0
  198. package/src/drivers/postgres.ts +49 -11
  199. package/src/drivers/vault-builtin.test.ts +10 -0
  200. package/src/drivers/vault-builtin.ts +13 -1
  201. package/src/drivers/vault-remote-bag.ts +5 -1
  202. package/src/drivers/vault-types.ts +6 -1
  203. package/src/elements/ai/agent-event-slot.ts +27 -0
  204. package/src/elements/ai/approval-http.ts +207 -0
  205. package/src/elements/ai/approval.test.ts +741 -0
  206. package/src/elements/ai/approval.ts +228 -0
  207. package/src/elements/ai/decisions/bind.ts +163 -0
  208. package/src/elements/ai/decisions/certificate.test.ts +291 -0
  209. package/src/elements/ai/decisions/certificate.ts +377 -0
  210. package/src/elements/ai/decisions/certify.ts +314 -0
  211. package/src/elements/ai/decisions/decide.test.ts +953 -0
  212. package/src/elements/ai/decisions/e2e.test.ts +399 -0
  213. package/src/elements/ai/decisions/export.test.ts +120 -0
  214. package/src/elements/ai/decisions/export.ts +146 -0
  215. package/src/elements/ai/decisions/fixtures/openrouter-request.json +24 -0
  216. package/src/elements/ai/decisions/fixtures/openrouter-response.json +22 -0
  217. package/src/elements/ai/decisions/fixtures/typesafe-request.json +19 -0
  218. package/src/elements/ai/decisions/fixtures/typesafe-response.json +13 -0
  219. package/src/elements/ai/decisions/http.test.ts +154 -0
  220. package/src/elements/ai/decisions/http.ts +240 -0
  221. package/src/elements/ai/decisions/labels.test.ts +282 -0
  222. package/src/elements/ai/decisions/labels.ts +257 -0
  223. package/src/elements/ai/decisions/openrouter.live.test.ts +136 -0
  224. package/src/elements/ai/decisions/openrouter.ts +36 -0
  225. package/src/elements/ai/decisions/provider.ts +102 -0
  226. package/src/elements/ai/decisions/typesafe.ts +36 -0
  227. package/src/elements/ai/declare.ts +252 -1
  228. package/src/elements/ai/events.test.ts +379 -0
  229. package/src/elements/ai/events.ts +138 -0
  230. package/src/elements/ai/run-events.test.ts +461 -0
  231. package/src/elements/ai/run-events.ts +522 -0
  232. package/src/elements/ai/runtime.ts +1186 -105
  233. package/src/elements/ai/stream-turn.ts +214 -0
  234. package/src/elements/ai/stream.live.test.ts +76 -0
  235. package/src/elements/ai/subagent.test.ts +136 -0
  236. package/src/elements/ai.test.ts +497 -3
  237. package/src/elements/ai.ts +16 -1
  238. package/src/elements/clock/durable.ts +27 -1
  239. package/src/elements/store/emit-drizzle.ts +2 -2
  240. package/src/elements/store/live-default.test.ts +2 -0
  241. package/src/elements/store/live-http.test.ts +1 -0
  242. package/src/elements/store/resource-list-docs.test.ts +2 -2
  243. package/src/elements/store/resource.test.ts +3 -3
  244. package/src/elements/store/schema-decl.test.ts +1 -0
  245. package/src/elements/store/sql-condition.ts +24 -7
  246. package/src/elements/store/sql-session.test.ts +51 -0
  247. package/src/elements/store/sql-session.ts +111 -1
  248. package/src/elements/store/upsert-app.test.ts +1 -1
  249. package/src/elements/vault/audit.test.ts +137 -0
  250. package/src/elements/vault/audit.ts +106 -13
  251. package/src/elements/vault/boot-chain.ts +9 -1
  252. package/src/elements/vault/builtin-adapter.ts +33 -3
  253. package/src/i18n/catalogs/ar.ts +9 -0
  254. package/src/i18n/catalogs/en.ts +9 -0
  255. package/src/index.ts +2 -0
  256. package/src/kernel/abort-scope.ts +33 -2
  257. package/src/kernel/agent-event-store.ts +448 -0
  258. package/src/kernel/app.ts +294 -19
  259. package/src/kernel/auto-cache.test.ts +6 -6
  260. package/src/kernel/boot-bind/ai.ts +3 -0
  261. package/src/kernel/boot-bind/store.test.ts +26 -0
  262. package/src/kernel/boot-bind/store.ts +82 -6
  263. package/src/kernel/boot-bind/vault.ts +1 -0
  264. package/src/kernel/boot.ts +34 -5
  265. package/src/kernel/builtin-errors.ts +10 -0
  266. package/src/kernel/capability.ts +3 -0
  267. package/src/kernel/client-descriptor.ts +1 -0
  268. package/src/kernel/concurrency.test.ts +33 -0
  269. package/src/kernel/decision-label-store.ts +441 -0
  270. package/src/kernel/effects-stamping.test.ts +2 -2
  271. package/src/kernel/effects.test.ts +2 -1
  272. package/src/kernel/effects.ts +13 -1
  273. package/src/kernel/element-registries.ts +3 -0
  274. package/src/kernel/errors-compiler.ts +20 -0
  275. package/src/kernel/errors-text.ts +4 -0
  276. package/src/kernel/errors.ts +2 -0
  277. package/src/kernel/external-effects.test.ts +36 -0
  278. package/src/kernel/flow.test.ts +2 -3
  279. package/src/kernel/flow.ts +24 -0
  280. package/src/kernel/fx-decide.ts +761 -0
  281. package/src/kernel/fx-fetch.ts +5 -1
  282. package/src/kernel/fx.test.ts +12 -5
  283. package/src/kernel/fx.ts +316 -29
  284. package/src/kernel/http-frame.test.ts +94 -0
  285. package/src/kernel/http-frame.ts +203 -0
  286. package/src/kernel/idempotency-store.ts +578 -0
  287. package/src/kernel/idempotency.test.ts +556 -0
  288. package/src/kernel/idempotency.ts +304 -0
  289. package/src/kernel/index.ts +1 -0
  290. package/src/kernel/journal.ts +160 -0
  291. package/src/kernel/json-result.ts +10 -0
  292. package/src/kernel/pipeline.test.ts +45 -0
  293. package/src/kernel/sse-id.ts +32 -0
  294. package/src/manifest/diff.ts +1 -0
  295. package/src/manifest/types.ts +37 -2
  296. package/src/mcp/ai-tools.test.ts +202 -0
  297. package/src/mcp/authorization.ts +66 -0
  298. package/src/mcp/session.ts +3 -0
  299. package/src/mcp/tools.ts +168 -0
  300. package/src/plugins/auth-delivery.mailpit.integration.test.ts +1 -1
  301. package/src/plugins/otp.test.ts +65 -1
  302. package/src/plugins/otp.ts +59 -7
  303. package/src/release/absolute-regression.test.ts +63 -0
  304. package/src/release/http-graph.test.ts +27 -0
  305. package/src/release/http-graph.ts +95 -0
  306. package/src/release/index.ts +3 -0
  307. package/src/release/limits.ts +17 -2
  308. package/src/release/measure.ts +144 -28
  309. package/src/runs/collect.ts +4 -1
  310. package/src/runs/parquet.test.ts +27 -1
  311. package/src/runs/parquet.ts +19 -0
  312. package/src/runs/types.ts +31 -0
  313. package/src/runtime/json-code-block.test.ts +106 -47
  314. package/src/runtime/json-code-block.ts +1209 -46
  315. package/src/term.test.ts +13 -0
  316. package/src/term.ts +81 -49
  317. package/src/test/create-test-app.test.ts +3 -1
  318. package/src/test/create-test-app.ts +40 -0
  319. package/src/test/live-signals.test.ts +1 -0
  320. package/src/test/provisions.integration.test.ts +1 -0
  321. package/src/test/tenant-isolation.test.ts +1 -0
  322. package/src/console/ui-next/dist/assets/PlusSignIcon-CwG3nxfu.js +0 -1
  323. package/src/console/ui-next/dist/assets/access-page-Bgt9bq2r.js +0 -4
  324. package/src/console/ui-next/dist/assets/agent-disclosure-B43CXZZR.js +0 -1
  325. package/src/console/ui-next/dist/assets/copy-inline-button-CAYD18cr.js +0 -1
  326. package/src/console/ui-next/dist/assets/detail-header-DVWNjWjg.js +0 -1
  327. package/src/console/ui-next/dist/assets/dropdown-menu-4h2LOVXM.js +0 -1
  328. package/src/console/ui-next/dist/assets/duration-tone-BmIR9FV8.js +0 -9
  329. package/src/console/ui-next/dist/assets/element-icons-BI8cJgdh.js +0 -1
  330. package/src/console/ui-next/dist/assets/explorer-empty-CJs5A-wm.js +0 -1
  331. package/src/console/ui-next/dist/assets/flows-page-BMHs-IzK.js +0 -1
  332. package/src/console/ui-next/dist/assets/index-BKpaes3n.js +0 -63
  333. package/src/console/ui-next/dist/assets/index-VxoEz295.css +0 -2
  334. package/src/console/ui-next/dist/assets/observability-page-WnVLI-0j.js +0 -4
  335. package/src/console/ui-next/dist/assets/request-meta-DMbnAe3f.js +0 -1
  336. package/src/console/ui-next/dist/assets/shortcut-keys-3ILd8oGn.js +0 -1
  337. package/src/console/ui-next/dist/assets/store-page-KvFDingJ.js +0 -41
  338. package/src/console/ui-next/dist/assets/trace-detail-sheet-Htk8Cm9t.js +0 -2
  339. package/src/console/ui-next/dist/assets/tree-expand-toggle-CFMPWX4f.js +0 -55
  340. package/src/console/ui-next/dist/assets/units-page-C4NdNuxP.js +0 -1
  341. package/src/console/ui-next/dist/assets/use-vault-list-CT4-gajj.js +0 -1
  342. package/src/console/ui-next/dist/assets/vault-page-CBYl0LW_.js +0 -2
@@ -12,7 +12,13 @@ import { join } from "node:path";
12
12
 
13
13
  import { duckPath, openDuckDB } from "./duckdb.ts";
14
14
  import { createRunsRuntime } from "./runtime.ts";
15
- import { readParquet, wideEventToRow, writeParquet, type ParquetRow } from "./parquet.ts";
15
+ import {
16
+ readParquet,
17
+ rowToWideEvent,
18
+ wideEventToRow,
19
+ writeParquet,
20
+ type ParquetRow,
21
+ } from "./parquet.ts";
16
22
  import type { WideEvent } from "./types.ts";
17
23
 
18
24
  const temps: string[] = [];
@@ -62,6 +68,26 @@ async function writeLegacyParquet(path: string, rows: readonly ParquetRow[]): Pr
62
68
  }
63
69
  }
64
70
 
71
+ describe("parquet http frame", () => {
72
+ test("round-trips a frame and omits a null column", () => {
73
+ const event = sample("framed", null);
74
+ const framed = {
75
+ ...event,
76
+ http: {
77
+ request: {
78
+ method: "GET",
79
+ path: "/tasks",
80
+ query: { limit: "20" },
81
+ headers: { accept: "application/json" },
82
+ },
83
+ response: { status: 200, headers: { "content-type": "application/json" } },
84
+ },
85
+ };
86
+ expect(rowToWideEvent(wideEventToRow(framed)).http).toEqual(framed.http);
87
+ expect(rowToWideEvent(wideEventToRow(event)).http).toBeUndefined();
88
+ });
89
+ });
90
+
65
91
  describe("parquet error_code types", () => {
66
92
  test("readParquet unions all-null JSON error_code with VARCHAR Unauthorized", async () => {
67
93
  const dir = await tmpDir();
@@ -35,6 +35,7 @@ const PARQUET_VARCHAR_COLUMNS = [
35
35
  "error_message",
36
36
  "input",
37
37
  "output",
38
+ "http",
38
39
  "effects",
39
40
  "logs",
40
41
  "archived",
@@ -88,6 +89,7 @@ export function wideEventToRow(event: WideEvent): ParquetRow {
88
89
  error_message: event.error?.message ?? null,
89
90
  input: event.input === undefined ? null : JSON.stringify(event.input),
90
91
  output: event.output === undefined ? null : JSON.stringify(event.output),
92
+ http: event.http === undefined ? null : JSON.stringify(event.http),
91
93
  effects: JSON.stringify(event.effects),
92
94
  logs: JSON.stringify(event.logs),
93
95
  duration_ms: event.durationMs,
@@ -167,6 +169,7 @@ export function rowToWideEvent(row: Record<string, unknown>): WideEvent {
167
169
  : (row.output as unknown),
168
170
  }
169
171
  : {}),
172
+ ...httpFromRow(row.http),
170
173
  effects: parseJsonArray(row.effects) as WideEvent["effects"],
171
174
  logs: parseJsonArray(row.logs) as WideEvent["logs"],
172
175
  durationMs: Number(row.duration_ms ?? 0),
@@ -308,6 +311,22 @@ function columnTypeOf(row: Record<string, unknown>): string | undefined {
308
311
  return typeof type === "string" && type.length > 0 ? type : undefined;
309
312
  }
310
313
 
314
+ function httpFromRow(value: unknown): { http: WideEvent["http"] } | undefined {
315
+ const raw = typeof value === "string" && value.length > 0 ? safeJson(value) : value;
316
+ if (raw === null || raw === undefined || typeof raw !== "object") return undefined;
317
+ const frame = raw as NonNullable<WideEvent["http"]>;
318
+ if (typeof frame.request !== "object" || frame.request === null) return undefined;
319
+ return { http: frame };
320
+ }
321
+
322
+ function safeJson(value: string): unknown {
323
+ try {
324
+ return JSON.parse(value) as unknown;
325
+ } catch {
326
+ return undefined;
327
+ }
328
+ }
329
+
311
330
  function parseJsonArray(value: unknown): unknown[] {
312
331
  if (Array.isArray(value)) return value;
313
332
  if (typeof value === "string" && value.length > 0) {
package/src/runs/types.ts CHANGED
@@ -28,6 +28,32 @@ export interface RunError {
28
28
  */
29
29
  export type RunDimensions = Record<string, string | number | boolean | null | undefined>;
30
30
 
31
+ /**
32
+ * HTTP message around a run — everything except the flow body.
33
+ *
34
+ * Credential header and query values are `[redacted]` before this is stored.
35
+ */
36
+ export interface RunHttpFrame {
37
+ /** Request line plus query and headers. */
38
+ readonly request: {
39
+ /** Verb as received (`GET`, `POST`, …). */
40
+ readonly method: string;
41
+ /** Pathname only — query lives in {@link query}. */
42
+ readonly path: string;
43
+ /** Query string, last value wins for a repeated key. */
44
+ readonly query: Readonly<Record<string, string>>;
45
+ /** Lower-case header names. */
46
+ readonly headers: Readonly<Record<string, string>>;
47
+ };
48
+ /** Final response after `onResponse`, when the trigger produced one. */
49
+ readonly response?: {
50
+ /** Status code. */
51
+ readonly status: number;
52
+ /** Lower-case header names. */
53
+ readonly headers: Readonly<Record<string, string>>;
54
+ };
55
+ }
56
+
31
57
  /**
32
58
  * One wide event — the atomic observability record.
33
59
  *
@@ -83,6 +109,11 @@ export interface WideEvent {
83
109
  * Absent on failures / in-flight sleeps — never invent a response.
84
110
  */
85
111
  readonly output?: unknown;
112
+ /**
113
+ * HTTP wire frame when the trigger was `http`.
114
+ * Absent on signal, clock, call-only, and runs recorded before the frame existed.
115
+ */
116
+ readonly http?: RunHttpFrame;
86
117
  /** Effect ledger snapshot. */
87
118
  readonly effects: readonly EffectEntry[];
88
119
  /**
@@ -118,8 +118,11 @@ describe("renderJsonCodeBlockHtml", () => {
118
118
  expect(html).toContain("Ready");
119
119
  expect(html).not.toContain('data-slot="json-code-auth-switch"');
120
120
  expect(html).toContain('data-slot="json-code-view-toggle"');
121
- expect(html).toContain('href="/?raw=1"');
122
- expect(html).toContain(">Pretty</a>");
121
+ expect(html).toContain('data-view="fields"');
122
+ expect(html).toContain('data-slot="json-code-fields"');
123
+ expect(html).toContain(">Fields</button>");
124
+ expect(html).toContain(">JSON</button>");
125
+ expect(html).not.toContain(">Pretty</button>");
123
126
  expect(html).not.toContain(">Raw</a>");
124
127
  expect(html).not.toContain(">Console</a>");
125
128
  expect(html).not.toContain("</script><script>alert(1)</script>");
@@ -130,6 +133,28 @@ describe("renderJsonCodeBlockHtml", () => {
130
133
  expect(escapeHtml(`<&"`)).toBe("&lt;&amp;&quot;");
131
134
  });
132
135
 
136
+ test("response fields preview nested values and redact credential headers", () => {
137
+ const html = renderJsonCodeBlockHtml({
138
+ json: JSON.stringify({ data: [{ id: "ENG-12", n: 2 }], error: null }),
139
+ status: 200,
140
+ method: "GET",
141
+ path: "/views",
142
+ app: "keel",
143
+ rawHref: "/views?raw=1",
144
+ prettyHref: "/views",
145
+ headers: { "content-type": "application/json", authorization: "Bearer secret" },
146
+ });
147
+ expect(html).toContain('data-slot="json-code-response"');
148
+ expect(html).toContain('data-slot="json-code-response-status"');
149
+ expect(html).toContain('data-slot="json-code-response-headers"');
150
+ expect(html).toContain("id: ENG-12 · n: 2");
151
+ expect(html).toContain(">1 item<");
152
+ expect(html).toContain("application/json");
153
+ expect(html).toContain("[redacted]");
154
+ expect(html).not.toContain("Bearer secret");
155
+ expect(html).toContain(">OK<");
156
+ });
157
+
133
158
  test("renders latency next to the status", () => {
134
159
  const html = renderJsonCodeBlockHtml({
135
160
  json: '{"ok":true}',
@@ -193,12 +218,10 @@ describe("renderJsonCodeBlockHtml", () => {
193
218
  expect(publicHtml).not.toContain('data-slot="json-code-auth-switch"');
194
219
  expect(publicHtml).not.toContain("data-auth-default");
195
220
  expect(publicHtml).not.toContain("data-route-public");
196
- expect(publicHtml).not.toContain('data-slot="json-code-auth-global"');
197
- expect(publicHtml).not.toContain('data-rail-section="auth"');
198
- expect(publicHtml).not.toContain(">Inherit</button>");
199
- expect(publicHtml).not.toContain(">Custom</button>");
200
- expect(publicHtml).not.toContain("oke:json-code:bearer");
201
- expect(publicHtml).not.toContain("Authentication");
221
+ expect(publicHtml).toContain('data-rail-section="auth"');
222
+ expect(publicHtml).toContain(">Auth</span>");
223
+ expect(publicHtml).toContain(">Inherit</button>");
224
+ expect(publicHtml).toContain(">Custom</button>");
202
225
 
203
226
  const userHtml = renderJsonCodeBlockHtml({
204
227
  json: '{"ok":true}',
@@ -216,13 +239,12 @@ describe("renderJsonCodeBlockHtml", () => {
216
239
  expect(userHtml).not.toContain('data-slot="json-code-auth-switch"');
217
240
  expect(userHtml).not.toContain('data-slot="json-code-api-key-global"');
218
241
  expect(userHtml).not.toContain('data-slot="json-code-api-key-route"');
219
- expect(userHtml).not.toContain('data-slot="json-code-auth-global"');
220
- expect(userHtml).not.toContain('data-rail-section="auth"');
221
- expect(userHtml).not.toContain("Authentication");
242
+ expect(userHtml).toContain('data-rail-section="auth"');
243
+ expect(userHtml).toContain('data-slot="json-code-global-auth"');
222
244
  expect(userHtml).not.toContain(">Console</a>");
223
245
  });
224
246
 
225
- test("Authentication interactive UI is gone", () => {
247
+ test("Authorization follows headers and global auth lives on the strip", () => {
226
248
  const html = renderJsonCodeBlockHtml({
227
249
  json: '{"ok":true}',
228
250
  status: 200,
@@ -234,29 +256,56 @@ describe("renderJsonCodeBlockHtml", () => {
234
256
  auth: { kind: "public" },
235
257
  });
236
258
  expect(html).not.toContain('data-slot="json-code-auth-switch"');
237
- expect(html).not.toContain(">Authentication</button>");
238
- expect(html).not.toContain("Global API Key");
239
- expect(html).not.toContain("Route API Key");
240
- expect(html).not.toContain('data-slot="json-code-api-key-apply-global"');
241
- expect(html).not.toContain('data-slot="json-code-api-key-apply-route"');
242
- expect(html).not.toContain('data-slot="json-code-auth-route-mode"');
243
- expect(html).not.toContain('data-slot="json-code-auth-inherit"');
244
- expect(html).not.toContain('data-rail-section="auth"');
245
- expect(html).not.toContain(">Inherit</button>");
246
- expect(html).not.toContain(">Custom</button>");
247
- expect(html).not.toContain("oke:json-code:bearer");
248
- expect(html).not.toContain("oke:json-code:bearer-route");
249
- expect(html).not.toContain("oke:json-code:auth-route-mode");
250
- expect(html).not.toContain("oke:json-code:auth-tone");
259
+ expect(html).toContain(">Inherit</button>");
260
+ expect(html).toContain(">Custom</button>");
261
+ expect(html).toContain('aria-label="Request headers"');
262
+ expect(html).toContain('data-headers-mode="inherit"');
263
+ expect(html).toContain('data-headers-mode="custom"');
264
+ expect(html).toContain("data-headers-custom");
265
+ expect(html).toContain("oke:json-code:headers-mode");
266
+ expect(html).toContain("function headersMode");
267
+ const headersAt = html.indexOf('<details class="rail-acc" data-rail-section="headers"');
268
+ const authAt = html.indexOf('<details class="rail-acc" data-rail-section="auth"');
269
+ expect(html.slice(headersAt, authAt)).toContain('data-headers-mode="inherit"');
270
+ expect(html.slice(authAt)).toContain('data-auth-mode="inherit"');
251
271
  expect(html).not.toContain("function resolveBearer");
252
- expect(html).not.toContain("function routeIsPublic");
253
- expect(html).not.toContain("function applyGlobalKey");
254
- expect(html).not.toContain("refreshAuthTone");
272
+ expect(html.indexOf('<details class="rail-acc" data-rail-section="headers"')).toBeLessThan(
273
+ html.indexOf('<details class="rail-acc" data-rail-section="auth"'),
274
+ );
275
+ expect(html.indexOf('<details class="rail-acc" data-rail-section="auth"')).toBeLessThan(
276
+ html.indexOf('<details class="rail-acc" data-rail-section="cookies"'),
277
+ );
278
+ expect(html.indexOf('<details class="rail-acc" data-rail-section="query"')).toBeLessThan(
279
+ html.indexOf('<details class="rail-acc" data-rail-section="path"'),
280
+ );
281
+ expect(html.indexOf('<details class="rail-acc" data-rail-section="path"')).toBeLessThan(
282
+ html.indexOf('<details class="rail-acc" data-rail-section="body"'),
283
+ );
284
+ expect(html).toContain(">Auth</span>");
285
+ expect(html).toContain('data-auth-type="none"');
286
+ expect(html).toContain(">No</button>");
287
+ expect(html).toContain(">Bearer</button>");
288
+ expect(html).toContain(">Basic</button>");
289
+ expect(html).toContain(">API</button>");
290
+ expect(html).not.toContain("auth-opt");
291
+ expect(html).toContain('data-auth-scope="request"');
292
+ expect(html).toContain('data-auth-scope="global"');
293
+ expect(html).toContain('data-slot="json-code-global-auth"');
294
+ expect(html).toContain('data-slot="json-code-global-headers"');
295
+ expect(html).toContain('data-slot="json-code-global-panel"');
296
+ expect(html).toContain('data-kv="headers-global"');
297
+ expect(html).toContain("oke:json-code:auth");
298
+ expect(html).toContain("oke:json-code:auth-global");
299
+ expect(html).toContain("oke:json-code:headers-global");
300
+ expect(html).toContain("function effectiveAuth");
301
+ expect(html).toContain("function storedAuth");
302
+ expect(html).toContain("function forgetSecretsOnReload");
303
+ expect(html).toContain("function replayStoredAuth");
304
+ expect(html).toContain("oke:json-code:auth-replay");
305
+ expect(html).toContain("parsed.token");
306
+ expect(html).toContain('type="password"');
307
+ expect(html).toContain("data-auth-reveal");
255
308
  expect(html).toContain('data-slot="json-code-send"');
256
- expect(html).toContain('data-kv="headers"');
257
- expect(html).toContain('aria-label="Request"');
258
- expect(html).not.toContain(":6533");
259
- expect(html).not.toContain(">Console</a>");
260
309
  });
261
310
 
262
311
  test("renders the Request rail with tabs and current GET on", () => {
@@ -319,7 +368,7 @@ describe("renderJsonCodeBlockHtml", () => {
319
368
  expect(html).toContain('data-slot="json-code-request-dock"');
320
369
  expect(html).toContain('data-slot="json-code-send"');
321
370
  expect(html).toContain('data-slot="json-code-reset"');
322
- expect(html).not.toContain('data-slot="json-code-dock-auth"');
371
+ expect(html).toContain('data-slot="json-code-global-auth"');
323
372
  expect(html).toContain('data-rail-section="query"');
324
373
  expect(html).toContain(">Params</span>");
325
374
  expect(html).toContain('data-rail-section="body"');
@@ -330,25 +379,35 @@ describe("renderJsonCodeBlockHtml", () => {
330
379
  expect(html).toContain('data-slot="json-code-body-raw"');
331
380
  expect(html).toContain('data-slot="json-code-body-hi"');
332
381
  expect(html).toContain('data-kv="body"');
333
- expect(html).not.toContain('data-rail-section="auth"');
334
- expect(html).not.toContain('data-slot="json-code-auth-route-mode"');
335
- expect(html).not.toContain(">Inherit</button>");
336
- expect(html).not.toContain(">Custom</button>");
337
- expect(html).not.toContain('data-slot="json-code-auth-global"');
382
+ expect(html).toContain('data-rail-section="auth"');
383
+ expect(html).toContain(">Inherit</button>");
384
+ expect(html).toContain(">Custom</button>");
385
+ expect(html).toContain('data-slot="json-code-global-headers"');
338
386
  expect(html).toContain('data-rail-section="cookies"');
339
387
  expect(html).toContain('data-rail-section="headers"');
340
388
  expect(html).toContain('data-rail-section="path"');
341
- expect(html.indexOf('data-rail-section="query"')).toBeLessThan(
342
- html.indexOf('data-rail-section="body"'),
389
+ expect(html.indexOf('<details class="rail-acc" data-rail-section="query"')).toBeLessThan(
390
+ html.indexOf('<details class="rail-acc" data-rail-section="path"'),
391
+ );
392
+ expect(html.indexOf('<details class="rail-acc" data-rail-section="path"')).toBeLessThan(
393
+ html.indexOf('<details class="rail-acc" data-rail-section="body"'),
343
394
  );
344
- expect(html.indexOf('data-rail-section="body"')).toBeLessThan(
345
- html.indexOf('data-rail-section="cookies"'),
395
+ expect(html.indexOf('<details class="rail-acc" data-rail-section="body"')).toBeLessThan(
396
+ html.indexOf('<details class="rail-acc" data-rail-section="headers"'),
397
+ );
398
+ expect(html.indexOf('<details class="rail-acc" data-rail-section="auth"')).toBeLessThan(
399
+ html.indexOf('<details class="rail-acc" data-rail-section="cookies"'),
346
400
  );
347
401
  expect(html).toContain('data-method="GET"');
348
402
  expect(html).toContain('data-method="POST"');
349
403
  expect(html).toContain('class="rail-acc"');
350
404
  expect(html).toContain('class="rail-dock"');
351
- expect(html).toContain(">Routes</p>");
405
+ expect(html.indexOf('data-slot="json-code-request-dock"')).toBeLessThan(
406
+ html.indexOf('data-rail-section="routes"'),
407
+ );
408
+ expect(html).toContain(">Routes</span>");
409
+ expect(html).toContain('aria-label="Collapse routes"');
410
+ expect(html).toContain('aria-label="Expand routes"');
352
411
  expect(html).toContain('data-kv="cookies"');
353
412
  expect(html).toContain('data-kv="headers"');
354
413
  expect(html).toContain('data-kv="query"');
@@ -521,10 +580,10 @@ describe("asBrowserJsonCodeBlock — HTTP", () => {
521
580
  expect(raw.headers.get("content-type")).toContain("text/html");
522
581
  const html = await raw.text();
523
582
  expect(html).toContain('data-view="raw"');
583
+ expect(html).toContain('data-code-view="raw"');
524
584
  expect(html).toContain('data-slot="json-code-view-toggle"');
525
- expect(html).toContain('href="/health"');
526
- expect(html).toContain(">Raw</a>");
527
- expect(html).toContain('aria-pressed="true"');
585
+ expect(html).toContain(">JSON</button>");
586
+ expect(html).toContain('data-response-view="json" aria-pressed="true"');
528
587
  expect(html).toContain("&quot;ok&quot;:true");
529
588
 
530
589
  const forced = await app.fetch(