okengine 0.2.6 → 0.2.8

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 (584) hide show
  1. package/AGENTS.md +24 -23
  2. package/README.md +52 -346
  3. package/docs/spec/console.md +165 -142
  4. package/docs/spec/example.md +490 -312
  5. package/docs/spec/four-applications.md +495 -314
  6. package/docs/spec/unified-theory.md +184 -175
  7. package/package.json +45 -37
  8. package/spec/manifest.v1.schema.json +40 -9
  9. package/src/auth/api-keys.ts +2 -5
  10. package/src/auth/attenuation.ts +2 -6
  11. package/src/auth/auth.test.ts +53 -31
  12. package/src/auth/invoke-as.ts +1 -3
  13. package/src/auth/operator.ts +8 -26
  14. package/src/auth/planes.ts +2 -7
  15. package/src/auth/plugin.ts +4 -7
  16. package/src/auth/roles.ts +1 -5
  17. package/src/auth/sessions.ts +10 -39
  18. package/src/cli/args.ts +1 -5
  19. package/src/cli/ask-dev-mode.ts +40 -0
  20. package/src/cli/build.ts +1 -2
  21. package/src/cli/client-add.test.ts +8 -15
  22. package/src/cli/client-add.ts +5 -14
  23. package/src/cli/completion.test.ts +1 -5
  24. package/src/cli/completion.ts +4 -17
  25. package/src/cli/db-auto-push.test.ts +64 -0
  26. package/src/cli/db-auto-push.ts +72 -0
  27. package/src/cli/db.test.ts +189 -0
  28. package/src/cli/db.ts +386 -0
  29. package/src/cli/dev-app-runner.ts +2 -8
  30. package/src/cli/dev-db-push.test.ts +163 -0
  31. package/src/cli/dev-mode.test.ts +45 -0
  32. package/src/cli/dev-mode.ts +78 -0
  33. package/src/cli/dev.test.ts +148 -21
  34. package/src/cli/dev.ts +208 -134
  35. package/src/cli/doc-drift.test.ts +3 -2
  36. package/src/cli/doc-drift.ts +21 -50
  37. package/src/cli/doc-staleness.test.ts +69 -0
  38. package/src/cli/docker-cli.test.ts +7 -8
  39. package/src/cli/docker.ts +1 -3
  40. package/src/cli/doctor-diff-examples.ts +1 -3
  41. package/src/cli/doctor-diff.test.ts +1 -5
  42. package/src/cli/doctor-diff.ts +17 -46
  43. package/src/cli/doctor-pii.ts +2 -7
  44. package/src/cli/doctor.test.ts +26 -4
  45. package/src/cli/doctor.ts +35 -11
  46. package/src/cli/eval.ts +4 -14
  47. package/src/cli/gates-list.ts +1 -4
  48. package/src/cli/hero-meta.test.ts +17 -19
  49. package/src/cli/hero-meta.ts +20 -30
  50. package/src/cli/images.ts +3 -8
  51. package/src/cli/index.ts +11 -2
  52. package/src/cli/load-config.images.test.ts +14 -14
  53. package/src/cli/load-config.ts +41 -47
  54. package/src/cli/mcp-from-console.ts +1 -4
  55. package/src/cli/mode.ts +45 -0
  56. package/src/cli/ports.test.ts +4 -13
  57. package/src/cli/ports.ts +1 -3
  58. package/src/cli/privacy-erase.ts +1 -3
  59. package/src/cli/registry.ts +75 -25
  60. package/src/cli/schema.ts +3 -10
  61. package/src/cli/stack.ts +2 -7
  62. package/src/cli/start.ts +4 -15
  63. package/src/cli/upgrade.ts +1 -4
  64. package/src/client/budget-entry.ts +1 -6
  65. package/src/client/create.test.ts +6 -12
  66. package/src/client/create.ts +2 -8
  67. package/src/client/errors.ts +1 -4
  68. package/src/client/index.ts +1 -6
  69. package/src/client/notes-contract.test.ts +4 -13
  70. package/src/client/transport.ts +9 -30
  71. package/src/client/types.ts +8 -29
  72. package/src/compiler/aot.test.ts +2 -9
  73. package/src/compiler/aot.ts +1 -4
  74. package/src/compiler/differential.test.ts +3 -11
  75. package/src/compiler/dynamic.ts +1 -4
  76. package/src/compiler/effects-infer.ts +8 -34
  77. package/src/compiler/emit.ts +1 -3
  78. package/src/compiler/extract.test.ts +96 -30
  79. package/src/compiler/extract.ts +362 -156
  80. package/src/compiler/fixtures/skyport/oke.config.ts +1 -1
  81. package/src/compiler/fixtures/skyport/src/flows/bookings/index.ts +7 -3
  82. package/src/compiler/fixtures/skyport/src/flows/payments/index.ts +1 -3
  83. package/src/compiler/fixtures/skyport/src/flows/support/index.ts +4 -1
  84. package/src/compiler/fixtures/skyport.expected.json +24 -83
  85. package/src/compiler/fixtures/triggers/five-triggers.ts +1 -2
  86. package/src/compiler/http-parse.ts +2 -9
  87. package/src/compiler/index.ts +1 -5
  88. package/src/compiler/response.ts +4 -7
  89. package/src/compiler/sucrose.ts +11 -31
  90. package/src/config/define-config.test.ts +57 -34
  91. package/src/config/index.ts +181 -37
  92. package/src/config/resolve-driver.test.ts +28 -17
  93. package/src/console/budget.test.ts +1 -4
  94. package/src/console/index.ts +1 -4
  95. package/src/console/server/access.test.ts +15 -43
  96. package/src/console/server/access.ts +19 -49
  97. package/src/console/server/ai.test.ts +3 -11
  98. package/src/console/server/ai.ts +23 -46
  99. package/src/console/server/app.ts +14 -45
  100. package/src/console/server/auth-rate.test.ts +4 -12
  101. package/src/console/server/bind.ts +1 -5
  102. package/src/console/server/channels.test.ts +2 -6
  103. package/src/console/server/channels.ts +10 -35
  104. package/src/console/server/claim.ts +2 -8
  105. package/src/console/server/clock.test.ts +2 -6
  106. package/src/console/server/clock.ts +8 -26
  107. package/src/console/server/console.test.ts +1 -3
  108. package/src/console/server/diff.test.ts +5 -17
  109. package/src/console/server/diff.ts +10 -31
  110. package/src/console/server/dry-run.audit.test.ts +2 -8
  111. package/src/console/server/flows.ts +64 -233
  112. package/src/console/server/gates.test.ts +14 -50
  113. package/src/console/server/gates.ts +13 -48
  114. package/src/console/server/index.ts +2 -9
  115. package/src/console/server/live.ts +3 -12
  116. package/src/console/server/operator-db.test.ts +4 -15
  117. package/src/console/server/operator-db.ts +13 -32
  118. package/src/console/server/plugin.ts +50 -53
  119. package/src/console/server/plugins.test.ts +2 -6
  120. package/src/console/server/plugins.ts +17 -56
  121. package/src/console/server/runs-pii.ts +2 -7
  122. package/src/console/server/security.gate.test.ts +18 -40
  123. package/src/console/server/serve.ts +10 -25
  124. package/src/console/server/signals.test.ts +1 -3
  125. package/src/console/server/signals.ts +17 -40
  126. package/src/console/server/state.ts +21 -59
  127. package/src/console/server/store.test.ts +20 -22
  128. package/src/console/server/store.ts +31 -76
  129. package/src/console/server/vault.test.ts +12 -29
  130. package/src/console/server/vault.ts +23 -60
  131. package/src/console/ui/access/AccessA11yView.tsx +6 -21
  132. package/src/console/ui/access/a11y.test.tsx +3 -12
  133. package/src/console/ui/access/acknowledgement.test.ts +1 -4
  134. package/src/console/ui/access/acknowledgement.ts +1 -3
  135. package/src/console/ui/access/blast-radius.ts +1 -3
  136. package/src/console/ui/access/confirmation.test.ts +1 -5
  137. package/src/console/ui/access/confirmation.ts +1 -4
  138. package/src/console/ui/access/fixture.ts +1 -5
  139. package/src/console/ui/access/grantable.test.ts +1 -3
  140. package/src/console/ui/access/grantable.ts +2 -7
  141. package/src/console/ui/access/index.ts +2 -9
  142. package/src/console/ui/access/provenance.test.ts +1 -3
  143. package/src/console/ui/access/provenance.ts +2 -6
  144. package/src/console/ui/access/search.test.ts +1 -5
  145. package/src/console/ui/access/search.ts +2 -6
  146. package/src/console/ui/ai/AiA11yView.tsx +6 -17
  147. package/src/console/ui/ai/a11y.test.tsx +2 -5
  148. package/src/console/ui/ai/fixture.ts +2 -7
  149. package/src/console/ui/ai/format.ts +1 -3
  150. package/src/console/ui/ai/group.test.ts +1 -3
  151. package/src/console/ui/ai/group.ts +4 -12
  152. package/src/console/ui/ai/index.ts +2 -9
  153. package/src/console/ui/ai/promotion.test.ts +2 -7
  154. package/src/console/ui/ai/promotion.ts +4 -13
  155. package/src/console/ui/ai/search.test.ts +2 -11
  156. package/src/console/ui/ai/search.ts +3 -13
  157. package/src/console/ui/ai/types.ts +1 -8
  158. package/src/console/ui/architecture/ArchitectureA11yView.tsx +8 -29
  159. package/src/console/ui/architecture/a11y.test.tsx +1 -2
  160. package/src/console/ui/architecture/declared.ts +1 -5
  161. package/src/console/ui/architecture/index.ts +7 -35
  162. package/src/console/ui/architecture/layout.ts +1 -3
  163. package/src/console/ui/architecture/pathologies.ts +10 -19
  164. package/src/console/ui/architecture/search.ts +6 -15
  165. package/src/console/ui/architecture/traffic.ts +4 -14
  166. package/src/console/ui/architecture/types.ts +2 -10
  167. package/src/console/ui/architecture/view.test.ts +7 -19
  168. package/src/console/ui/architecture/view.ts +9 -36
  169. package/src/console/ui/channels/ChannelsA11yView.tsx +4 -13
  170. package/src/console/ui/channels/a11y.test.tsx +1 -2
  171. package/src/console/ui/channels/confirmation.test.ts +1 -4
  172. package/src/console/ui/channels/confirmation.ts +1 -4
  173. package/src/console/ui/channels/findings.ts +1 -5
  174. package/src/console/ui/channels/index.ts +2 -8
  175. package/src/console/ui/channels/locale.test.ts +1 -3
  176. package/src/console/ui/channels/locale.ts +2 -8
  177. package/src/console/ui/channels/search.ts +4 -13
  178. package/src/console/ui/channels/taxonomy.ts +1 -3
  179. package/src/console/ui/clock/ClockA11yView.tsx +9 -26
  180. package/src/console/ui/clock/a11y.test.tsx +2 -5
  181. package/src/console/ui/clock/confirmation.test.ts +1 -3
  182. package/src/console/ui/clock/confirmation.ts +1 -4
  183. package/src/console/ui/clock/findings.ts +1 -4
  184. package/src/console/ui/clock/health.ts +2 -7
  185. package/src/console/ui/clock/index.ts +2 -10
  186. package/src/console/ui/clock/search.test.ts +1 -3
  187. package/src/console/ui/clock/search.ts +2 -6
  188. package/src/console/ui/clock/timeline.test.ts +1 -3
  189. package/src/console/ui/clock/waiting-on.test.ts +1 -5
  190. package/src/console/ui/clock/waiting-on.ts +2 -7
  191. package/src/console/ui/diff/DiffA11yView.tsx +8 -17
  192. package/src/console/ui/diff/a11y.test.tsx +2 -5
  193. package/src/console/ui/diff/group.test.ts +3 -13
  194. package/src/console/ui/diff/group.ts +2 -8
  195. package/src/console/ui/diff/index.ts +2 -8
  196. package/src/console/ui/diff/search.test.ts +1 -5
  197. package/src/console/ui/diff/search.ts +4 -16
  198. package/src/console/ui/diff/summary.ts +1 -2
  199. package/src/console/ui/dist/assets/{index-Dy4jht9P.js → index-BWo8R7NR.js} +2 -2
  200. package/src/console/ui/dist/assets/{panel-access-Dd37LU2c.js → panel-access-C0J2D-a2.js} +1 -1
  201. package/src/console/ui/dist/assets/{panel-ai-CC7LR6-J.js → panel-ai-D_m6WQI8.js} +1 -1
  202. package/src/console/ui/dist/assets/{panel-architecture-B5b3iKCz.js → panel-architecture-CKnXFyUx.js} +1 -1
  203. package/src/console/ui/dist/assets/{panel-channels-CeNjTKXp.js → panel-channels-BOmQ-onL.js} +1 -1
  204. package/src/console/ui/dist/assets/{panel-clock-DgFTLoHV.js → panel-clock-giAq0Ccv.js} +1 -1
  205. package/src/console/ui/dist/assets/{panel-diff-DxehccqB.js → panel-diff-cdonmH8c.js} +1 -1
  206. package/src/console/ui/dist/assets/{panel-flows-BtrVn-Eg.js → panel-flows-DlCU5zjA.js} +2 -2
  207. package/src/console/ui/dist/assets/{panel-gates-Z9MKRGdH.js → panel-gates-XclZxWD5.js} +1 -1
  208. package/src/console/ui/dist/assets/{panel-overview-Dt_AeXgd.js → panel-overview-BznEOTnb.js} +1 -1
  209. package/src/console/ui/dist/assets/{panel-plugins-DWd0TowH.js → panel-plugins-CcGM1g64.js} +1 -1
  210. package/src/console/ui/dist/assets/{panel-runs-DGstFHeq.js → panel-runs-CGWNHLR4.js} +1 -1
  211. package/src/console/ui/dist/assets/{panel-signals-DzEa2Fnt.js → panel-signals-CNywkdak.js} +1 -1
  212. package/src/console/ui/dist/assets/{panel-store-BJkbNgxx.js → panel-store-KmTbFHMH.js} +1 -1
  213. package/src/console/ui/dist/assets/{panel-traces-BaRVO3gM.js → panel-traces-DBLx2ilD.js} +1 -1
  214. package/src/console/ui/dist/assets/panel-vault-CEnFc0dk.js +1 -0
  215. package/src/console/ui/dist/index.html +1 -1
  216. package/src/console/ui/flows/FlowsA11yView.tsx +7 -22
  217. package/src/console/ui/flows/a11y.test.tsx +2 -8
  218. package/src/console/ui/flows/buffer.test.ts +3 -11
  219. package/src/console/ui/flows/buffer.ts +4 -11
  220. package/src/console/ui/flows/confirmation.ts +1 -3
  221. package/src/console/ui/flows/contract.test.ts +3 -7
  222. package/src/console/ui/flows/contract.ts +12 -36
  223. package/src/console/ui/flows/graph.test.ts +3 -11
  224. package/src/console/ui/flows/graph.ts +5 -15
  225. package/src/console/ui/flows/index.ts +1 -6
  226. package/src/console/ui/flows/save-as-test.ts +1 -3
  227. package/src/console/ui/flows/search.ts +8 -25
  228. package/src/console/ui/flows/tiers.ts +2 -9
  229. package/src/console/ui/gates/GatesA11yView.tsx +4 -13
  230. package/src/console/ui/gates/a11y.test.tsx +2 -5
  231. package/src/console/ui/gates/audit.ts +1 -3
  232. package/src/console/ui/gates/denial.test.ts +1 -3
  233. package/src/console/ui/gates/denial.ts +4 -12
  234. package/src/console/ui/gates/findings.ts +1 -3
  235. package/src/console/ui/gates/group.test.ts +3 -3
  236. package/src/console/ui/gates/group.ts +3 -11
  237. package/src/console/ui/gates/index.ts +2 -10
  238. package/src/console/ui/gates/search.ts +3 -10
  239. package/src/console/ui/overview/OverviewA11yView.tsx +9 -27
  240. package/src/console/ui/overview/a11y.test.tsx +1 -2
  241. package/src/console/ui/overview/busiest.ts +1 -3
  242. package/src/console/ui/overview/compose.ts +1 -13
  243. package/src/console/ui/overview/cost.ts +34 -38
  244. package/src/console/ui/overview/fixture.ts +21 -26
  245. package/src/console/ui/overview/golden.ts +4 -14
  246. package/src/console/ui/overview/index.ts +2 -9
  247. package/src/console/ui/overview/rank.test.ts +3 -10
  248. package/src/console/ui/overview/rank.ts +2 -7
  249. package/src/console/ui/overview/slo.test.ts +5 -9
  250. package/src/console/ui/overview/slo.ts +6 -23
  251. package/src/console/ui/overview/verdict.ts +3 -10
  252. package/src/console/ui/plugins/PluginsA11yView.tsx +8 -18
  253. package/src/console/ui/plugins/a11y.test.tsx +1 -2
  254. package/src/console/ui/plugins/fixture.ts +2 -4
  255. package/src/console/ui/plugins/group.test.ts +1 -3
  256. package/src/console/ui/plugins/group.ts +1 -6
  257. package/src/console/ui/plugins/index.ts +3 -13
  258. package/src/console/ui/plugins/search.ts +7 -19
  259. package/src/console/ui/runs/RunsA11yView.tsx +5 -20
  260. package/src/console/ui/runs/a11y.test.tsx +2 -5
  261. package/src/console/ui/runs/explain.ts +2 -6
  262. package/src/console/ui/runs/group.ts +3 -12
  263. package/src/console/ui/runs/histogram.test.ts +2 -11
  264. package/src/console/ui/runs/histogram.ts +1 -4
  265. package/src/console/ui/runs/index.ts +4 -18
  266. package/src/console/ui/runs/project.ts +2 -6
  267. package/src/console/ui/runs/query.test.ts +1 -3
  268. package/src/console/ui/runs/query.ts +12 -35
  269. package/src/console/ui/runs/search.ts +5 -19
  270. package/src/console/ui/runs/trace-link.test.ts +2 -6
  271. package/src/console/ui/runs/trace-link.ts +4 -16
  272. package/src/console/ui/runs/types.ts +1 -3
  273. package/src/console/ui/shell/App.tsx +2 -10
  274. package/src/console/ui/shell/client.ts +22 -115
  275. package/src/console/ui/shell/components/ui.tsx +1 -4
  276. package/src/console/ui/shell/layout/Shell.tsx +2 -4
  277. package/src/console/ui/shell/main.tsx +31 -96
  278. package/src/console/ui/shell/panels/access/AccessPanel.tsx +34 -98
  279. package/src/console/ui/shell/panels/ai/AiPanel.tsx +35 -106
  280. package/src/console/ui/shell/panels/architecture/ArchitecturePanel.tsx +18 -66
  281. package/src/console/ui/shell/panels/channels/ChannelsPanel.tsx +20 -57
  282. package/src/console/ui/shell/panels/clock/ClockPanel.tsx +22 -54
  283. package/src/console/ui/shell/panels/diff/DiffPanel.tsx +20 -61
  284. package/src/console/ui/shell/panels/flows/ContractEditor.tsx +6 -23
  285. package/src/console/ui/shell/panels/flows/FlowDrawer.tsx +13 -28
  286. package/src/console/ui/shell/panels/flows/FlowsPanel.tsx +9 -29
  287. package/src/console/ui/shell/panels/gates/GatesPanel.tsx +24 -80
  288. package/src/console/ui/shell/panels/overview/OverviewPanel.tsx +20 -58
  289. package/src/console/ui/shell/panels/plugins/PluginsPanel.tsx +16 -41
  290. package/src/console/ui/shell/panels/runs/RunsPanel.tsx +31 -99
  291. package/src/console/ui/shell/panels/signals/SignalsPanel.tsx +38 -101
  292. package/src/console/ui/shell/panels/store/StorePanel.tsx +27 -66
  293. package/src/console/ui/shell/panels/traces/TracesPanel.tsx +28 -89
  294. package/src/console/ui/shell/panels/vault/VaultPanel.tsx +22 -53
  295. package/src/console/ui/shell/setup/Wizard.tsx +3 -5
  296. package/src/console/ui/shell/styles.css +1 -2
  297. package/src/console/ui/signals/SignalsA11yView.tsx +9 -33
  298. package/src/console/ui/signals/a11y.test.tsx +2 -5
  299. package/src/console/ui/signals/confirmation.test.ts +1 -5
  300. package/src/console/ui/signals/confirmation.ts +2 -6
  301. package/src/console/ui/signals/dry-run.ts +1 -3
  302. package/src/console/ui/signals/durable.ts +1 -3
  303. package/src/console/ui/signals/findings.ts +1 -3
  304. package/src/console/ui/signals/group.test.ts +2 -8
  305. package/src/console/ui/signals/group.ts +2 -10
  306. package/src/console/ui/signals/index.ts +1 -4
  307. package/src/console/ui/signals/monitor.ts +2 -7
  308. package/src/console/ui/signals/schema-form.test.ts +3 -14
  309. package/src/console/ui/signals/schema-form.ts +1 -4
  310. package/src/console/ui/signals/search.ts +4 -13
  311. package/src/console/ui/store/StoreA11yView.tsx +3 -9
  312. package/src/console/ui/store/a11y.test.tsx +2 -5
  313. package/src/console/ui/store/confirmation.test.ts +1 -3
  314. package/src/console/ui/store/confirmation.ts +1 -4
  315. package/src/console/ui/store/dry-run.ts +2 -5
  316. package/src/console/ui/store/fixture.ts +1 -2
  317. package/src/console/ui/store/group.test.ts +1 -6
  318. package/src/console/ui/store/group.ts +1 -4
  319. package/src/console/ui/store/index.ts +1 -5
  320. package/src/console/ui/store/search.ts +2 -6
  321. package/src/console/ui/store/will-not-fire.ts +1 -2
  322. package/src/console/ui/traces/TracesA11yView.tsx +10 -29
  323. package/src/console/ui/traces/a11y.test.tsx +1 -2
  324. package/src/console/ui/traces/chain.test.ts +5 -19
  325. package/src/console/ui/traces/chain.ts +1 -3
  326. package/src/console/ui/traces/critical-path.test.ts +1 -3
  327. package/src/console/ui/traces/critical-path.ts +2 -6
  328. package/src/console/ui/traces/filter.test.ts +2 -6
  329. package/src/console/ui/traces/filter.ts +5 -13
  330. package/src/console/ui/traces/fold.test.ts +4 -12
  331. package/src/console/ui/traces/fold.ts +1 -3
  332. package/src/console/ui/traces/mini.ts +1 -3
  333. package/src/console/ui/traces/replay.test.ts +1 -3
  334. package/src/console/ui/traces/replay.ts +1 -3
  335. package/src/console/ui/traces/sampling.ts +1 -4
  336. package/src/console/ui/traces/search.ts +4 -17
  337. package/src/console/ui/traces/tier.ts +1 -3
  338. package/src/console/ui/vault/VaultA11yView.tsx +5 -17
  339. package/src/console/ui/vault/a11y.test.tsx +1 -2
  340. package/src/console/ui/vault/blast-radius.ts +1 -3
  341. package/src/console/ui/vault/confirmation.test.ts +1 -5
  342. package/src/console/ui/vault/confirmation.ts +1 -4
  343. package/src/console/ui/vault/dormant.test.ts +1 -4
  344. package/src/console/ui/vault/export-safe.test.ts +1 -5
  345. package/src/console/ui/vault/export-safe.ts +1 -4
  346. package/src/console/ui/vault/fixture.ts +3 -3
  347. package/src/console/ui/vault/group.ts +1 -2
  348. package/src/console/ui/vault/index.ts +2 -10
  349. package/src/console/ui/vault/search.ts +2 -6
  350. package/src/console/ui/vault/types.ts +1 -1
  351. package/src/console/xss.gate.test.ts +1 -3
  352. package/src/docker/compose.ts +112 -20
  353. package/src/docker/derive.ts +5 -19
  354. package/src/docker/docker.test.ts +15 -15
  355. package/src/docker/dockerfile.integration.test.ts +12 -21
  356. package/src/docker/helpers.ts +5 -4
  357. package/src/docker/index.ts +4 -11
  358. package/src/docker/pin.ts +1 -9
  359. package/src/docker/recipes/index.ts +5 -6
  360. package/src/docker/recipes/mailpit.ts +22 -0
  361. package/src/docker/recipes/postgres.ts +17 -6
  362. package/src/docker/recipes/redis.ts +6 -1
  363. package/src/docker/recipes/rustfs.ts +33 -0
  364. package/src/docker/stack-id.test.ts +33 -0
  365. package/src/docker/stack-id.ts +25 -13
  366. package/src/docker/stack.integration.test.ts +6 -21
  367. package/src/docker/types.ts +13 -4
  368. package/src/drivers/ai-anthropic.ts +5 -14
  369. package/src/drivers/ai-mock.ts +2 -5
  370. package/src/drivers/ai-openai-compatible.ts +4 -10
  371. package/src/drivers/ai-providers.test.ts +6 -13
  372. package/src/drivers/bun-native-completeness.test.ts +6 -15
  373. package/src/drivers/channel-console.ts +6 -7
  374. package/src/drivers/channel-fcm.ts +20 -30
  375. package/src/drivers/channel-resend.ts +1 -3
  376. package/src/drivers/channel-smtp.ts +2 -6
  377. package/src/drivers/channel-types.ts +2 -12
  378. package/src/drivers/channel-unifonic.ts +2 -6
  379. package/src/drivers/channel-wa-cloud.ts +2 -6
  380. package/src/drivers/channel-webpush.ts +21 -60
  381. package/src/drivers/conformance.test.ts +2 -10
  382. package/src/drivers/conformance.ts +8 -21
  383. package/src/drivers/fs.ts +2 -8
  384. package/src/drivers/index.ts +12 -56
  385. package/src/drivers/memory.ts +14 -41
  386. package/src/drivers/pgvector.ts +7 -11
  387. package/src/drivers/postgres.ts +7 -13
  388. package/src/drivers/redis.ts +13 -37
  389. package/src/drivers/s3.ts +5 -17
  390. package/src/drivers/signal-engine.ts +12 -49
  391. package/src/drivers/signal-memory.ts +2 -8
  392. package/src/drivers/signal-nats.ts +4 -9
  393. package/src/drivers/signal-postgres.ts +62 -129
  394. package/src/drivers/signal-redis.ts +7 -21
  395. package/src/drivers/signal-types.ts +1 -4
  396. package/src/drivers/sqlite.ts +3 -12
  397. package/src/drivers/types.ts +4 -23
  398. package/src/drivers/vault-env.ts +2 -6
  399. package/src/drivers/vault-infisical.ts +1 -5
  400. package/src/drivers/vault-managed.ts +1 -5
  401. package/src/drivers/vault-memory.ts +1 -5
  402. package/src/drivers/vault-openbao.ts +1 -5
  403. package/src/drivers/vault-sops.ts +10 -35
  404. package/src/drivers/vault-types.ts +1 -7
  405. package/src/elements/ai/declare.ts +4 -14
  406. package/src/elements/ai/eval.ts +2 -6
  407. package/src/elements/ai/pii.ts +1 -3
  408. package/src/elements/ai/runtime.ts +12 -50
  409. package/src/elements/ai/schema.ts +4 -15
  410. package/src/elements/ai.test.ts +13 -24
  411. package/src/elements/ai.ts +1 -5
  412. package/src/elements/channel/consent.ts +3 -12
  413. package/src/elements/channel/costs.ts +4 -15
  414. package/src/elements/channel/declare.ts +1 -4
  415. package/src/elements/channel/email-auth.ts +1 -4
  416. package/src/elements/channel/locale.ts +2 -10
  417. package/src/elements/channel/mask.ts +1 -3
  418. package/src/elements/channel/mime.ts +2 -12
  419. package/src/elements/channel/outcomes.test.ts +1 -5
  420. package/src/elements/channel/outcomes.ts +5 -15
  421. package/src/elements/channel/receipts.ts +2 -7
  422. package/src/elements/channel/runtime.ts +28 -74
  423. package/src/elements/channel/suppression.ts +8 -14
  424. package/src/elements/channel.test.ts +8 -31
  425. package/src/elements/channel.ts +3 -14
  426. package/src/elements/clock/actions.ts +6 -18
  427. package/src/elements/clock/declare.ts +1 -3
  428. package/src/elements/clock/dst.ts +1 -5
  429. package/src/elements/clock/durable.ts +4 -16
  430. package/src/elements/clock/health.ts +2 -7
  431. package/src/elements/clock/leader.ts +2 -9
  432. package/src/elements/clock/reconcile.ts +4 -15
  433. package/src/elements/clock/runtime.ts +2 -5
  434. package/src/elements/clock/schedule.ts +4 -20
  435. package/src/elements/clock.test.ts +2 -7
  436. package/src/elements/clock.ts +5 -23
  437. package/src/elements/gate/permissions.ts +1 -4
  438. package/src/elements/gate/runtime.ts +7 -28
  439. package/src/elements/gate.ts +1 -5
  440. package/src/elements/index.ts +9 -7
  441. package/src/elements/signal/declare.ts +2 -7
  442. package/src/elements/signal/reconcile.test.ts +1 -4
  443. package/src/elements/signal/runtime.ts +1 -3
  444. package/src/elements/signal.test.ts +3 -15
  445. package/src/elements/signal.ts +2 -8
  446. package/src/elements/store/cache.test.ts +46 -0
  447. package/src/elements/store/cache.ts +3 -11
  448. package/src/elements/store/classify.ts +5 -22
  449. package/src/elements/store/declare.ts +8 -17
  450. package/src/elements/store/domain-ddl.test.ts +86 -0
  451. package/src/elements/store/emit-drizzle.ts +363 -0
  452. package/src/elements/store/files-policy.test.ts +1 -5
  453. package/src/elements/store/files-policy.ts +4 -12
  454. package/src/elements/store/load-plugin-tables.ts +103 -0
  455. package/src/elements/store/missing-relation.test.ts +83 -0
  456. package/src/elements/store/missing-relation.ts +38 -0
  457. package/src/elements/store/replica.ts +1 -4
  458. package/src/elements/store/runtime.ts +25 -28
  459. package/src/elements/store/schema-decl.test.ts +227 -0
  460. package/src/elements/store/schema-decl.ts +516 -0
  461. package/src/elements/store/sql-condition.ts +11 -21
  462. package/src/elements/store/sql-session.test.ts +50 -0
  463. package/src/elements/store/sql-session.ts +60 -63
  464. package/src/elements/store/table.ts +35 -19
  465. package/src/elements/store.test.ts +17 -39
  466. package/src/elements/store.ts +37 -31
  467. package/src/elements/vault/chain.ts +34 -0
  468. package/src/elements/vault/declare.ts +22 -32
  469. package/src/elements/vault/fingerprint.ts +2 -7
  470. package/src/elements/vault/redact.ts +2 -6
  471. package/src/elements/vault/runtime.ts +18 -32
  472. package/src/elements/vault.test.ts +12 -28
  473. package/src/elements/vault.ts +8 -12
  474. package/src/index.ts +5 -2
  475. package/src/kernel/adopt-routes.ts +15 -29
  476. package/src/kernel/app.ts +34 -94
  477. package/src/kernel/auth-resolve.ts +2 -9
  478. package/src/kernel/boot-bind/ai.ts +1 -4
  479. package/src/kernel/boot-bind/channel.ts +2 -8
  480. package/src/kernel/boot-bind/clock.ts +2 -6
  481. package/src/kernel/boot-bind/gate.ts +2 -8
  482. package/src/kernel/boot-bind/runs.ts +1 -3
  483. package/src/kernel/boot-bind/signal.ts +3 -10
  484. package/src/kernel/boot-bind/store.test.ts +17 -17
  485. package/src/kernel/boot-bind/store.ts +44 -50
  486. package/src/kernel/boot-bind/vault.ts +2 -8
  487. package/src/kernel/boot.test.ts +4 -9
  488. package/src/kernel/boot.ts +29 -76
  489. package/src/kernel/budget.test.ts +1 -3
  490. package/src/kernel/capability.ts +3 -10
  491. package/src/kernel/dry-run.test.ts +1 -4
  492. package/src/kernel/dry-run.ts +3 -11
  493. package/src/kernel/effects.test.ts +1 -5
  494. package/src/kernel/effects.ts +4 -11
  495. package/src/kernel/errors.registry.test.ts +2 -8
  496. package/src/kernel/errors.ts +23 -32
  497. package/src/kernel/flow.test.ts +12 -25
  498. package/src/kernel/flow.ts +5 -25
  499. package/src/kernel/fx.test.ts +15 -44
  500. package/src/kernel/fx.ts +27 -79
  501. package/src/kernel/hook-timing.test.ts +3 -6
  502. package/src/kernel/hook-timing.ts +5 -14
  503. package/src/kernel/hooks.test.ts +10 -10
  504. package/src/kernel/hooks.ts +3 -12
  505. package/src/kernel/index.ts +4 -17
  506. package/src/kernel/journal.ts +7 -31
  507. package/src/kernel/on.ts +1 -6
  508. package/src/kernel/pipeline.test.ts +10 -19
  509. package/src/kernel/pipeline.ts +5 -17
  510. package/src/kernel/plug.ts +4 -11
  511. package/src/kernel/plugin/conflicts.test.ts +13 -25
  512. package/src/kernel/plugin/decorate.test.ts +8 -13
  513. package/src/kernel/plugin/scoping.test.ts +4 -11
  514. package/src/kernel/plugin.ts +48 -24
  515. package/src/kernel/registry.ts +80 -29
  516. package/src/kernel/router.test.ts +15 -13
  517. package/src/kernel/router.ts +9 -29
  518. package/src/kernel/routing-budget.test.ts +1 -3
  519. package/src/kernel/run-telemetry.ts +1 -3
  520. package/src/kernel/triggers.ts +4 -21
  521. package/src/manifest/diff.test.ts +26 -91
  522. package/src/manifest/diff.ts +95 -225
  523. package/src/manifest/index.ts +2 -9
  524. package/src/manifest/types.ts +29 -5
  525. package/src/manifest/undeclared.test.ts +4 -12
  526. package/src/manifest/undeclared.ts +1 -2
  527. package/src/manifest/validate.test.ts +2 -6
  528. package/src/manifest/validate.ts +4 -14
  529. package/src/mcp/authorization.ts +8 -27
  530. package/src/mcp/confirmation.ts +3 -10
  531. package/src/mcp/data.ts +2 -6
  532. package/src/mcp/docs-index.ts +4 -7
  533. package/src/mcp/docs-mcp.test.ts +3 -12
  534. package/src/mcp/docs-server.ts +7 -27
  535. package/src/mcp/docs-tools.ts +2 -6
  536. package/src/mcp/index.ts +1 -6
  537. package/src/mcp/injection.gate.test.ts +4 -18
  538. package/src/mcp/mcp.test.ts +18 -49
  539. package/src/mcp/protocol.ts +3 -10
  540. package/src/mcp/server.ts +11 -52
  541. package/src/mcp/session.ts +4 -14
  542. package/src/mcp/tools.ts +14 -50
  543. package/src/plugins/catalogue.test.ts +3 -7
  544. package/src/plugins/catalogue.ts +1 -3
  545. package/src/plugins/node-import-scan.ts +2 -5
  546. package/src/plugins/supply-chain.ts +5 -17
  547. package/src/release/exports.ts +3 -8
  548. package/src/release/measure.exports.test.ts +1 -3
  549. package/src/release/measure.ts +15 -43
  550. package/src/runs/bench.test.ts +1 -3
  551. package/src/runs/collect.ts +8 -25
  552. package/src/runs/drivers/clickhouse.ts +2 -9
  553. package/src/runs/drivers/files.ts +9 -31
  554. package/src/runs/drivers/memory.ts +5 -22
  555. package/src/runs/drivers/postgres.ts +8 -20
  556. package/src/runs/duckdb.ts +2 -8
  557. package/src/runs/index.ts +3 -14
  558. package/src/runs/outlier.ts +3 -10
  559. package/src/runs/parquet.ts +8 -26
  560. package/src/runs/privacy.ts +2 -8
  561. package/src/runs/runs.test.ts +3 -9
  562. package/src/runs/runtime.ts +7 -32
  563. package/src/runs/shred.ts +10 -29
  564. package/src/runs/types.ts +1 -4
  565. package/src/runtime/bun.ts +4 -15
  566. package/src/runtime/cold-start.bench.ts +1 -3
  567. package/src/runtime/dev-request-log.test.ts +1 -4
  568. package/src/runtime/dev-request-log.ts +1 -4
  569. package/src/runtime/index.ts +1 -6
  570. package/src/runtime/primitives.ts +5 -4
  571. package/src/runtime/security.ts +3 -13
  572. package/src/runtime/serve.test.ts +4 -7
  573. package/src/runtime/types.ts +1 -4
  574. package/src/runtime/web-standard.ts +3 -15
  575. package/src/term.test.ts +4 -6
  576. package/src/term.ts +49 -98
  577. package/src/test/create-test-app.test.ts +4 -14
  578. package/src/test/create-test-app.ts +13 -31
  579. package/src/test/provisions.integration.test.ts +3 -11
  580. package/src/upgrade/codemods.test.ts +25 -6
  581. package/src/upgrade/codemods.ts +116 -3
  582. package/src/validation/standard-schema.test.ts +2 -5
  583. package/src/validation/standard-schema.ts +13 -33
  584. package/src/console/ui/dist/assets/panel-vault-BbfWdox0.js +0 -1
@@ -1,13 +1,14 @@
1
1
  /**
2
2
  * Per-project local stack identity — unique compose project + host ports.
3
3
  *
4
- * `oke dev --stack` must not share one `oke-dev` Postgres across every app on
4
+ * `oke dev --docker` must not share one `oke-dev` Postgres across every app on
5
5
  * the machine. Identity is a stable short hash of the project cwd.
6
6
  */
7
7
 
8
8
  import { createHash } from "node:crypto";
9
9
  import { resolve } from "node:path";
10
10
  import type { ServiceCredentials } from "./types.ts";
11
+ import { DEFAULT_DOCKER_DIR } from "./types.ts";
11
12
  import { defaultHostPort, envPrefix } from "./helpers.ts";
12
13
 
13
14
  /**
@@ -16,10 +17,7 @@ import { defaultHostPort, envPrefix } from "./helpers.ts";
16
17
  * @param cwd - Project root
17
18
  */
18
19
  export function stackInstanceId(cwd: string): string {
19
- return createHash("sha256")
20
- .update(resolve(cwd))
21
- .digest("hex")
22
- .slice(0, 6);
20
+ return createHash("sha256").update(resolve(cwd)).digest("hex").slice(0, 6);
23
21
  }
24
22
 
25
23
  /**
@@ -31,6 +29,15 @@ export function stackAppSlug(cwd: string): string {
31
29
  return `dev-${stackInstanceId(cwd)}`;
32
30
  }
33
31
 
32
+ /**
33
+ * Stable 0–999 offset derived from a stack instance id.
34
+ *
35
+ * @param instanceId - 6-hex stack id
36
+ */
37
+ export function instancePortOffset(instanceId: string): number {
38
+ return Number.parseInt(instanceId.slice(0, 4), 16) % 1000;
39
+ }
40
+
34
41
  /**
35
42
  * Host port for a role, offset by instance id so two stacks can run at once.
36
43
  *
@@ -43,7 +50,7 @@ export function hostPortForInstance(
43
50
  containerPort: number,
44
51
  instanceId: string,
45
52
  ): number {
46
- const n = Number.parseInt(instanceId.slice(0, 4), 16) % 1000;
53
+ const n = instancePortOffset(instanceId);
47
54
  if (role === "store.sql") return 15_000 + n;
48
55
  if (role === "store.kv") return 16_000 + n;
49
56
  if (role === "signal") return 17_000 + n;
@@ -51,7 +58,7 @@ export function hostPortForInstance(
51
58
  }
52
59
 
53
60
  /**
54
- * Parse role credentials from an existing `.env.stack` body (reuse on restart).
61
+ * Parse role credentials from an existing `.env.docker` body (reuse on restart).
55
62
  *
56
63
  * @param text - Dotenv contents
57
64
  * @param roles - Roles to look up
@@ -91,7 +98,9 @@ export function parseStackCredentials(
91
98
  }
92
99
 
93
100
  /**
94
- * Load credentials from project `.env.stack` when present.
101
+ * Load credentials from `docker/.env.docker` when present.
102
+ *
103
+ * Soft-compat: also reads legacy project-root `.env.docker`.
95
104
  *
96
105
  * @param cwd - Project root
97
106
  * @param roles - Image roles
@@ -100,9 +109,12 @@ export async function loadExistingStackCredentials(
100
109
  cwd: string,
101
110
  roles: readonly string[],
102
111
  ): Promise<Readonly<Record<string, ServiceCredentials>> | undefined> {
103
- const path = resolve(cwd, ".env.stack");
104
- const file = Bun.file(path);
105
- if (!(await file.exists())) return undefined;
106
- const parsed = parseStackCredentials(await file.text(), roles);
107
- return Object.keys(parsed).length > 0 ? parsed : undefined;
112
+ const candidates = [resolve(cwd, DEFAULT_DOCKER_DIR, ".env.docker"), resolve(cwd, ".env.docker")];
113
+ for (const path of candidates) {
114
+ const file = Bun.file(path);
115
+ if (!(await file.exists())) continue;
116
+ const parsed = parseStackCredentials(await file.text(), roles);
117
+ if (Object.keys(parsed).length > 0) return parsed;
118
+ }
119
+ return undefined;
108
120
  }
@@ -6,11 +6,7 @@ import { describe, expect, test } from "bun:test";
6
6
  import { mkdtemp, rm } from "node:fs/promises";
7
7
  import { tmpdir } from "node:os";
8
8
  import { join } from "node:path";
9
- import {
10
- deriveInfrastructure,
11
- formatStackEnv,
12
- writeDerivedFiles,
13
- } from "./index.ts";
9
+ import { deriveInfrastructure, formatStackEnv, writeDerivedFiles } from "./index.ts";
14
10
 
15
11
  async function dockerAvailable(): Promise<boolean> {
16
12
  try {
@@ -24,7 +20,7 @@ async function dockerAvailable(): Promise<boolean> {
24
20
  }
25
21
  }
26
22
 
27
- describe("oke dev --stack postgres integration", () => {
23
+ describe("oke dev --docker postgres integration", () => {
28
24
  test("compose brings up postgres and the app talks to it", async () => {
29
25
  if (!(await dockerAvailable())) {
30
26
  console.warn("skipping: docker daemon not available");
@@ -51,21 +47,12 @@ describe("oke dev --stack postgres integration", () => {
51
47
  });
52
48
  await writeDerivedFiles(derived, dockerDir, {
53
49
  writeStackEnv: true,
54
- stackEnvDir: dir,
55
50
  });
56
51
 
57
52
  // Infra-only: network + role compose (no app build).
58
53
  const composeFiles = ["compose.yml", "compose.store.sql.yml"];
59
54
  const up = Bun.spawn(
60
- [
61
- "docker",
62
- "compose",
63
- "-p",
64
- project,
65
- ...composeFiles.flatMap((f) => ["-f", f]),
66
- "up",
67
- "-d",
68
- ],
55
+ ["docker", "compose", "-p", project, ...composeFiles.flatMap((f) => ["-f", f]), "up", "-d"],
69
56
  {
70
57
  cwd: dockerDir,
71
58
  stdout: "pipe",
@@ -120,13 +107,11 @@ describe("oke dev --stack postgres integration", () => {
120
107
  await sql.close();
121
108
  }
122
109
 
123
- // Prove credentials live in .env.stack, not YAML.
110
+ // Prove credentials live in docker/.env.docker, not YAML.
124
111
  const yml = await Bun.file(join(dockerDir, "compose.store.sql.yml")).text();
125
112
  expect(yml).not.toContain("stack-integration-pass");
126
- expect(formatStackEnv(derived.stackEnv)).toContain(
127
- "stack-integration-pass",
128
- );
129
- expect(await Bun.file(join(dir, ".env.stack")).exists()).toBe(true);
113
+ expect(formatStackEnv(derived.stackEnv)).toContain("stack-integration-pass");
114
+ expect(await Bun.file(join(dockerDir, ".env.docker")).exists()).toBe(true);
130
115
  } finally {
131
116
  await Bun.spawn(
132
117
  [
@@ -37,7 +37,7 @@ export interface ServiceSpec {
37
37
  readonly port: number;
38
38
  /** Host port published in compose (dev defaults). */
39
39
  readonly hostPort: number;
40
- /** Credential placeholders (values live in `.env.stack`, not YAML). */
40
+ /** Credential placeholders (values live in `.env.docker`, not YAML). */
41
41
  readonly credentials: ServiceCredentials;
42
42
  }
43
43
 
@@ -50,6 +50,12 @@ export interface ComposeHealthcheck {
50
50
  readonly start_period?: string;
51
51
  }
52
52
 
53
+ /** Extra published host↔container port pair from a recipe. */
54
+ export interface RecipeExtraPort {
55
+ readonly host: number;
56
+ readonly container: number;
57
+ }
58
+
53
59
  /** Image-specific compose fragment from {@link ImageRecipe.apply}. */
54
60
  export interface RecipeApplyResult {
55
61
  readonly environment?: Readonly<Record<string, string>>;
@@ -57,6 +63,8 @@ export interface RecipeApplyResult {
57
63
  readonly healthcheck?: ComposeHealthcheck;
58
64
  readonly volumes?: readonly string[];
59
65
  readonly user?: string;
66
+ /** Additional published ports (e.g. Mailpit UI, RustFS console). */
67
+ readonly extraPorts?: readonly RecipeExtraPort[];
60
68
  }
61
69
 
62
70
  /**
@@ -102,12 +110,13 @@ export interface DeriveOptions {
102
110
  readonly prod?: boolean;
103
111
  /**
104
112
  * Include the `app` service in `compose.yml` (default true).
105
- * `oke dev --stack` sets false — host Bun runs the app; Docker is infra only.
113
+ * `oke dev --docker` sets false — host Bun runs the app; Docker is infra only.
106
114
  */
107
115
  readonly includeApp?: boolean;
108
116
  /**
109
117
  * Compose artefact directory relative to the project root (default `docker`).
110
- * Controls generated `env_file` / `build.context` paths (e.g. `../.env.stack`).
118
+ * Controls generated `env_file` / `build.context` paths (`.env.docker` lives
119
+ * beside compose under this directory).
111
120
  * Pass `"."` for legacy root-level layout.
112
121
  */
113
122
  readonly composeDir?: string;
@@ -144,7 +153,7 @@ export interface DeriveResult {
144
153
  /** Generated files (Dockerfile + compose layers). */
145
154
  readonly files: readonly GeneratedFile[];
146
155
  /**
147
- * Stack env contents for `.env.stack` — written by `oke dev --stack`,
156
+ * Stack env contents for `.env.docker` — written by `oke dev --docker`,
148
157
  * never embedded in YAML.
149
158
  */
150
159
  readonly stackEnv: Readonly<Record<string, string>>;
@@ -21,9 +21,7 @@ const ANTHROPIC_VERSION = "2023-06-01";
21
21
  *
22
22
  * @param options - API key / model / base URL / injectable fetch
23
23
  */
24
- export async function openAnthropic(
25
- options: AiOpenOptions = {},
26
- ): Promise<AiModelClient> {
24
+ export async function openAnthropic(options: AiOpenOptions = {}): Promise<AiModelClient> {
27
25
  const apiKey = options.apiKey ?? process.env.ANTHROPIC_API_KEY;
28
26
  if (!apiKey) {
29
27
  throw new Error("anthropic: apiKey is required (or ANTHROPIC_API_KEY)");
@@ -48,17 +46,14 @@ export async function openAnthropic(
48
46
  body: JSON.stringify({
49
47
  model: resolvedModel,
50
48
  max_tokens: opts.maxTokens ?? 1024,
51
- ...(opts.temperature !== undefined
52
- ? { temperature: opts.temperature }
53
- : {}),
49
+ ...(opts.temperature !== undefined ? { temperature: opts.temperature } : {}),
54
50
  ...(system !== undefined ? { system } : {}),
55
51
  messages,
56
52
  }),
57
53
  });
58
54
  const raw = (await res.json().catch(() => ({}))) as AnthropicMessagesResponse;
59
55
  if (!res.ok) {
60
- const msg =
61
- raw.error?.message ?? `anthropic HTTP ${res.status}`;
56
+ const msg = raw.error?.message ?? `anthropic HTTP ${res.status}`;
62
57
  throw new Error(`anthropic: ${msg}`);
63
58
  }
64
59
  const text = textFromContent(raw.content);
@@ -92,9 +87,7 @@ interface AnthropicMessagesResponse {
92
87
  readonly error?: { readonly message?: string };
93
88
  }
94
89
 
95
- function splitSystem(
96
- messages: AiCompleteOptions["messages"],
97
- ): {
90
+ function splitSystem(messages: AiCompleteOptions["messages"]): {
98
91
  system?: string;
99
92
  messages: Array<{ role: "user" | "assistant"; content: string }>;
100
93
  } {
@@ -117,9 +110,7 @@ function splitSystem(
117
110
  };
118
111
  }
119
112
 
120
- function textFromContent(
121
- content: AnthropicMessagesResponse["content"],
122
- ): string {
113
+ function textFromContent(content: AnthropicMessagesResponse["content"]): string {
123
114
  if (!content?.length) return "";
124
115
  return content
125
116
  .filter((b) => b.type === "text" && typeof b.text === "string")
@@ -39,8 +39,7 @@ export const mockAiDriver: AiDriver = {
39
39
  if (payload === undefined) {
40
40
  payload = canned["*"] ?? { ok: true, echo: last };
41
41
  }
42
- const text =
43
- typeof payload === "string" ? payload : JSON.stringify(payload);
42
+ const text = typeof payload === "string" ? payload : JSON.stringify(payload);
44
43
  return {
45
44
  text,
46
45
  raw: payload,
@@ -70,9 +69,7 @@ export const mockAiDriver: AiDriver = {
70
69
  *
71
70
  * @param responses - Key → JSON payload
72
71
  */
73
- export function createMockAiDriver(
74
- responses: Readonly<Record<string, unknown>>,
75
- ): AiDriver {
72
+ export function createMockAiDriver(responses: Readonly<Record<string, unknown>>): AiDriver {
76
73
  return {
77
74
  id: "mock",
78
75
  open(options = {}) {
@@ -23,14 +23,10 @@ const DEFAULT_BASE = "https://api.openai.com/v1";
23
23
  *
24
24
  * @param options - API key / model / base URL / injectable fetch
25
25
  */
26
- export async function openOpenaiCompatible(
27
- options: AiOpenOptions = {},
28
- ): Promise<AiModelClient> {
26
+ export async function openOpenaiCompatible(options: AiOpenOptions = {}): Promise<AiModelClient> {
29
27
  const apiKey = options.apiKey ?? process.env.OPENAI_API_KEY;
30
28
  if (!apiKey) {
31
- throw new Error(
32
- "openai-compatible: apiKey is required (or OPENAI_API_KEY)",
33
- );
29
+ throw new Error("openai-compatible: apiKey is required (or OPENAI_API_KEY)");
34
30
  }
35
31
  const model = options.model ?? "gpt-4o-mini";
36
32
  const baseUrl = (options.baseUrl ?? DEFAULT_BASE).replace(/\/$/, "");
@@ -65,8 +61,7 @@ export async function openOpenaiCompatible(
65
61
  });
66
62
  const raw = (await res.json().catch(() => ({}))) as OpenAiChatResponse;
67
63
  if (!res.ok) {
68
- const msg =
69
- raw.error?.message ?? `openai-compatible HTTP ${res.status}`;
64
+ const msg = raw.error?.message ?? `openai-compatible HTTP ${res.status}`;
70
65
  throw new Error(`openai-compatible: ${msg}`);
71
66
  }
72
67
  const text = raw.choices?.[0]?.message?.content ?? "";
@@ -94,8 +89,7 @@ export async function openOpenaiCompatible(
94
89
  });
95
90
  const raw = (await res.json().catch(() => ({}))) as OpenAiEmbedResponse;
96
91
  if (!res.ok) {
97
- const msg =
98
- raw.error?.message ?? `openai-compatible embed HTTP ${res.status}`;
92
+ const msg = raw.error?.message ?? `openai-compatible embed HTTP ${res.status}`;
99
93
  throw new Error(`openai-compatible: ${msg}`);
100
94
  }
101
95
  const vectors = (raw.data ?? [])
@@ -4,10 +4,7 @@
4
4
 
5
5
  import { describe, expect, test } from "bun:test";
6
6
  import { anthropicAiDriver, openAnthropic } from "./ai-anthropic.ts";
7
- import {
8
- openaiCompatibleAiDriver,
9
- openOpenaiCompatible,
10
- } from "./ai-openai-compatible.ts";
7
+ import { openaiCompatibleAiDriver, openOpenaiCompatible } from "./ai-openai-compatible.ts";
11
8
  import { mockAiDriver } from "./ai-mock.ts";
12
9
 
13
10
  describe("anthropic driver", () => {
@@ -56,9 +53,7 @@ describe("anthropic driver", () => {
56
53
  messages: Array<{ role: string }>;
57
54
  };
58
55
  expect(body.system).toBe("be brief");
59
- expect(body.messages).toEqual([
60
- { role: "user", content: "hi" } as { role: string },
61
- ]);
56
+ expect(body.messages).toEqual([{ role: "user", content: "hi" } as { role: string }]);
62
57
  });
63
58
 
64
59
  test("HTTP error surfaces provider message", async () => {
@@ -73,18 +68,16 @@ describe("anthropic driver", () => {
73
68
  apiKey: "sk-test",
74
69
  fetch: fetchFn,
75
70
  });
76
- await expect(
77
- client.complete({ messages: [{ role: "user", content: "x" }] }),
78
- ).rejects.toThrow("rate limited");
71
+ await expect(client.complete({ messages: [{ role: "user", content: "x" }] })).rejects.toThrow(
72
+ "rate limited",
73
+ );
79
74
  });
80
75
 
81
76
  test("live Anthropic ask when ANTHROPIC_API_KEY is set", async () => {
82
77
  const key = process.env.ANTHROPIC_API_KEY;
83
78
  if (!key) {
84
79
  // Clearly-marked skip — never fail CI for lack of credentials.
85
- console.log(
86
- "skip: live anthropic ask (ANTHROPIC_API_KEY not set)",
87
- );
80
+ console.log("skip: live anthropic ask (ANTHROPIC_API_KEY not set)");
88
81
  return;
89
82
  }
90
83
  const client = await anthropicAiDriver.open({
@@ -7,10 +7,7 @@
7
7
 
8
8
  import { describe, expect, test } from "bun:test";
9
9
  import { createBunRedisClient } from "./redis.ts";
10
- import {
11
- createBunSignalRedisClient,
12
- parseXreadgroupReply,
13
- } from "./signal-redis.ts";
10
+ import { createBunSignalRedisClient, parseXreadgroupReply } from "./signal-redis.ts";
14
11
 
15
12
  /** One row in the completeness report. */
16
13
  export interface BunNativeGapRow {
@@ -26,10 +23,7 @@ export interface BunNativeGapRow {
26
23
  * Kept as a pure function so the gate test and human report share one source.
27
24
  */
28
25
  export function bunNativeCompletenessReport(): readonly BunNativeGapRow[] {
29
- const redisProto = Bun.RedisClient.prototype as unknown as Record<
30
- string,
31
- unknown
32
- >;
26
+ const redisProto = Bun.RedisClient.prototype as unknown as Record<string, unknown>;
33
27
  const hasTypedScan = typeof redisProto.scan === "function";
34
28
  const hasTypedPublish = typeof redisProto.publish === "function";
35
29
  const hasTypedSubscribe = typeof redisProto.subscribe === "function";
@@ -57,8 +51,7 @@ export function bunNativeCompletenessReport(): readonly BunNativeGapRow[] {
57
51
  {
58
52
  surface: "redis signal",
59
53
  capability: "native Bun bind (publish/subscribe)",
60
- status:
61
- hasTypedPublish && hasTypedSubscribe ? "closed" : "bun_limitation",
54
+ status: hasTypedPublish && hasTypedSubscribe ? "closed" : "bun_limitation",
62
55
  note:
63
56
  hasTypedPublish && hasTypedSubscribe
64
57
  ? "createBunSignalRedisClient uses typed publish/subscribe"
@@ -107,9 +100,7 @@ describe("Bun native client completeness", () => {
107
100
  expect(rows.length).toBe(8);
108
101
 
109
102
  const closed = rows.filter((r) => r.status === "closed").map((r) => r.capability);
110
- const limited = rows
111
- .filter((r) => r.status === "bun_limitation")
112
- .map((r) => r.capability);
103
+ const limited = rows.filter((r) => r.status === "bun_limitation").map((r) => r.capability);
113
104
 
114
105
  // Closed on Bun 1.3.14
115
106
  expect(closed).toContain("SCAN (typed)");
@@ -141,13 +132,13 @@ describe("Bun native client completeness", () => {
141
132
  [
142
133
  "oke:signal:order",
143
134
  [
144
- ["1-0", ["payload", "{\"a\":1}", "signal", "order"]],
135
+ ["1-0", ["payload", '{"a":1}', "signal", "order"]],
145
136
  ["1-1", ["payload", "{}", "signal", "order"]],
146
137
  ],
147
138
  ],
148
139
  ]);
149
140
  expect(parsed).toEqual([
150
- { id: "1-0", fields: { payload: "{\"a\":1}", signal: "order" } },
141
+ { id: "1-0", fields: { payload: '{"a":1}', signal: "order" } },
151
142
  { id: "1-1", fields: { payload: "{}", signal: "order" } },
152
143
  ]);
153
144
  expect(parseXreadgroupReply(null)).toEqual([]);
@@ -21,9 +21,7 @@ import { createChannelInbox } from "./channel-types.ts";
21
21
  function formatAddressInput(input: AddressInput): string {
22
22
  if (typeof input === "string") return input;
23
23
  if (Array.isArray(input)) {
24
- return input
25
- .map((t) => (typeof t === "string" ? t : t.address))
26
- .join(",");
24
+ return input.map((t) => (typeof t === "string" ? t : t.address)).join(",");
27
25
  }
28
26
  return input.address;
29
27
  }
@@ -33,9 +31,7 @@ function formatAddressInput(input: AddressInput): string {
33
31
  *
34
32
  * @param options - Optional shared inbox
35
33
  */
36
- export function openConsoleChannel(
37
- options: ChannelOpenOptions = {},
38
- ): ChannelDriver {
34
+ export function openConsoleChannel(options: ChannelOpenOptions = {}): ChannelDriver {
39
35
  const inbox = options.inbox ?? createChannelInbox();
40
36
 
41
37
  const channel: ChannelTransport = {
@@ -88,7 +84,10 @@ export function openConsoleChannel(
88
84
  template: mail.template,
89
85
  at: Date.now(),
90
86
  });
91
- const recipients = to.split(",").map((s) => s.trim()).filter(Boolean);
87
+ const recipients = to
88
+ .split(",")
89
+ .map((s) => s.trim())
90
+ .filter(Boolean);
92
91
  return {
93
92
  messageId: id,
94
93
  accepted: recipients,
@@ -15,9 +15,7 @@ import type {
15
15
  *
16
16
  * @param options - `token` (OAuth access token) + `from` (project id)
17
17
  */
18
- export function openFcmChannel(
19
- options: ChannelOpenOptions = {},
20
- ): ChannelDriver {
18
+ export function openFcmChannel(options: ChannelOpenOptions = {}): ChannelDriver {
21
19
  const accessToken = options.token ?? options.apiKey;
22
20
  const projectId = options.from;
23
21
  const fetchFn = options.fetch ?? globalThis.fetch;
@@ -30,31 +28,25 @@ export function openFcmChannel(
30
28
  if (!accessToken || !projectId) {
31
29
  throw new Error("fcm: token and from (project id) are required");
32
30
  }
33
- const res = await fetchFn(
34
- `${base}/v1/projects/${projectId}/messages:send`,
35
- {
36
- method: "POST",
37
- headers: {
38
- Authorization: `Bearer ${accessToken}`,
39
- "Content-Type": "application/json",
40
- },
41
- body: JSON.stringify({
42
- message: {
43
- token: message.to,
44
- notification: {
45
- title: message.subject ?? message.template ?? "notification",
46
- body: message.text ?? "",
47
- },
48
- data: Object.fromEntries(
49
- Object.entries(message.data ?? {}).map(([k, v]) => [
50
- k,
51
- String(v),
52
- ]),
53
- ),
54
- },
55
- }),
31
+ const res = await fetchFn(`${base}/v1/projects/${projectId}/messages:send`, {
32
+ method: "POST",
33
+ headers: {
34
+ Authorization: `Bearer ${accessToken}`,
35
+ "Content-Type": "application/json",
56
36
  },
57
- );
37
+ body: JSON.stringify({
38
+ message: {
39
+ token: message.to,
40
+ notification: {
41
+ title: message.subject ?? message.template ?? "notification",
42
+ body: message.text ?? "",
43
+ },
44
+ data: Object.fromEntries(
45
+ Object.entries(message.data ?? {}).map(([k, v]) => [k, String(v)]),
46
+ ),
47
+ },
48
+ }),
49
+ });
58
50
  const body = (await res.json().catch(() => ({}))) as {
59
51
  name?: string;
60
52
  error?: { message?: string };
@@ -79,9 +71,7 @@ export function openFcmChannel(
79
71
  ok: true,
80
72
  messageId: id,
81
73
  driverId: "fcm",
82
- attempts: [
83
- { driverId: "fcm", ok: true, at: Date.now(), messageId: id },
84
- ],
74
+ attempts: [{ driverId: "fcm", ok: true, at: Date.now(), messageId: id }],
85
75
  };
86
76
  },
87
77
  };
@@ -10,9 +10,7 @@ import type { ChannelDriver, ChannelOpenOptions } from "./channel-types.ts";
10
10
  *
11
11
  * @param options - API key
12
12
  */
13
- export function openResendChannel(
14
- options: ChannelOpenOptions = {},
15
- ): ChannelDriver {
13
+ export function openResendChannel(options: ChannelOpenOptions = {}): ChannelDriver {
16
14
  if (!options.apiKey) {
17
15
  throw new Error("resend channel: apiKey is required");
18
16
  }
@@ -10,18 +10,14 @@ import type { ChannelDriver, ChannelOpenOptions } from "./channel-types.ts";
10
10
  *
11
11
  * @param options - Host / port / auth
12
12
  */
13
- export function openSmtpChannel(
14
- options: ChannelOpenOptions = {},
15
- ): ChannelDriver {
13
+ export function openSmtpChannel(options: ChannelOpenOptions = {}): ChannelDriver {
16
14
  if (!options.host) {
17
15
  throw new Error("smtp channel: host is required");
18
16
  }
19
17
  const transport = new SMTPTransport({
20
18
  host: options.host,
21
19
  port: options.port ?? 587,
22
- ...(options.user && options.pass
23
- ? { auth: { user: options.user, pass: options.pass } }
24
- : {}),
20
+ ...(options.user && options.pass ? { auth: { user: options.user, pass: options.pass } } : {}),
25
21
  });
26
22
  return { id: "smtp", transport };
27
23
  }
@@ -5,12 +5,7 @@
5
5
  * run unchanged. Non-email media (sms / whatsapp / push) use {@link ChannelTransport}.
6
6
  */
7
7
 
8
- import type {
9
- MailOptions,
10
- SendResult,
11
- Transport,
12
- VerifyResult,
13
- } from "sently";
8
+ import type { MailOptions, SendResult, Transport, VerifyResult } from "sently";
14
9
 
15
10
  export type {
16
11
  Address,
@@ -35,12 +30,7 @@ export type ChannelDriverId =
35
30
  | "webpush";
36
31
 
37
32
  /** Channel medium. */
38
- export type ChannelMediumId =
39
- | "email"
40
- | "sms"
41
- | "whatsapp"
42
- | "push"
43
- | "any";
33
+ export type ChannelMediumId = "email" | "sms" | "whatsapp" | "push" | "any";
44
34
 
45
35
  /** Unified outbound message (medium-agnostic). */
46
36
  export interface ChannelMessage {
@@ -15,9 +15,7 @@ import type {
15
15
  *
16
16
  * @param options - `apiKey` + optional `from` (sender id)
17
17
  */
18
- export function openUnifonicChannel(
19
- options: ChannelOpenOptions = {},
20
- ): ChannelDriver {
18
+ export function openUnifonicChannel(options: ChannelOpenOptions = {}): ChannelDriver {
21
19
  const apiKey = options.apiKey;
22
20
  const from = options.from ?? "OKE";
23
21
  const fetchFn = options.fetch ?? globalThis.fetch;
@@ -62,9 +60,7 @@ export function openUnifonicChannel(
62
60
  ok: true,
63
61
  messageId: id,
64
62
  driverId: "unifonic",
65
- attempts: [
66
- { driverId: "unifonic", ok: true, at: Date.now(), messageId: id },
67
- ],
63
+ attempts: [{ driverId: "unifonic", ok: true, at: Date.now(), messageId: id }],
68
64
  };
69
65
  },
70
66
  };
@@ -15,9 +15,7 @@ import type {
15
15
  *
16
16
  * @param options - `token` (access token) + `from` (phone number id)
17
17
  */
18
- export function openWaCloudChannel(
19
- options: ChannelOpenOptions = {},
20
- ): ChannelDriver {
18
+ export function openWaCloudChannel(options: ChannelOpenOptions = {}): ChannelDriver {
21
19
  const token = options.token ?? options.apiKey;
22
20
  const phoneNumberId = options.from;
23
21
  const fetchFn = options.fetch ?? globalThis.fetch;
@@ -67,9 +65,7 @@ export function openWaCloudChannel(
67
65
  ok: true,
68
66
  messageId: id,
69
67
  driverId: "wa-cloud",
70
- attempts: [
71
- { driverId: "wa-cloud", ok: true, at: Date.now(), messageId: id },
72
- ],
68
+ attempts: [{ driverId: "wa-cloud", ok: true, at: Date.now(), messageId: id }],
73
69
  };
74
70
  },
75
71
  };