okengine 0.10.2 → 0.11.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 (343) hide show
  1. package/package.json +76 -10
  2. package/site/content/docs/ai/mcp.mdx +0 -1
  3. package/site/content/docs/deployment/docker-swarm.mdx +48 -111
  4. package/site/content/docs/deployment/docker.mdx +43 -36
  5. package/site/content/docs/deployment/index.mdx +9 -9
  6. package/site/content/docs/deployment/kubernetes.mdx +4 -4
  7. package/site/content/docs/elements/ai.mdx +7 -13
  8. package/site/content/docs/elements/channel.mdx +9 -13
  9. package/site/content/docs/elements/clock.mdx +8 -14
  10. package/site/content/docs/elements/flow.mdx +46 -54
  11. package/site/content/docs/elements/gate.mdx +6 -11
  12. package/site/content/docs/elements/signal.mdx +2 -8
  13. package/site/content/docs/elements/store.mdx +79 -93
  14. package/site/content/docs/elements/vault.mdx +89 -76
  15. package/site/content/docs/get-started/basic-usage.mdx +8 -14
  16. package/site/content/docs/get-started/installation.mdx +36 -36
  17. package/site/content/docs/get-started/introduction.mdx +11 -0
  18. package/site/content/docs/get-started/why.mdx +3 -4
  19. package/site/content/docs/index.mdx +0 -1
  20. package/site/content/docs/meta.json +0 -1
  21. package/site/content/docs/plugins/anonymous.mdx +1 -1
  22. package/site/content/docs/plugins/magic-link.mdx +11 -11
  23. package/site/content/docs/plugins/otp.mdx +2 -2
  24. package/site/content/docs/plugins/passkey.mdx +1 -1
  25. package/site/content/docs/plugins/two-factor.mdx +1 -1
  26. package/site/content/docs/plugins/username.mdx +1 -1
  27. package/site/content/docs/recipes/caddy.mdx +1 -1
  28. package/site/content/docs/recipes/cockroachdb.mdx +2 -2
  29. package/site/content/docs/recipes/dragonfly.mdx +1 -1
  30. package/site/content/docs/recipes/index.mdx +1 -2
  31. package/site/content/docs/recipes/llama-cpp.mdx +21 -23
  32. package/site/content/docs/recipes/mailpit.mdx +11 -11
  33. package/site/content/docs/recipes/meilisearch.mdx +10 -10
  34. package/site/content/docs/recipes/meta.json +0 -1
  35. package/site/content/docs/recipes/ollama.mdx +1 -1
  36. package/site/content/docs/recipes/pgdog.mdx +12 -9
  37. package/site/content/docs/recipes/postgres.mdx +3 -3
  38. package/site/content/docs/recipes/redis.mdx +2 -2
  39. package/site/content/docs/recipes/rustfs.mdx +10 -7
  40. package/site/content/docs/recipes/sglang.mdx +1 -1
  41. package/site/content/docs/recipes/supabase-docker.mdx +1 -1
  42. package/site/content/docs/recipes/timescale.mdx +2 -2
  43. package/site/content/docs/recipes/valkey.mdx +1 -1
  44. package/site/content/docs/recipes/vllm.mdx +1 -1
  45. package/site/content/docs/recipes/yugabytedb.mdx +2 -2
  46. package/site/content/docs/reference/cli.md +61 -38
  47. package/site/content/docs/reference/configuration.mdx +145 -70
  48. package/site/content/docs/reference/environment-variables.mdx +36 -28
  49. package/site/content/docs/reference/errors.mdx +28 -29
  50. package/site/content/docs/reference/fx.mdx +14 -7
  51. package/site/content/docs/reference/i18n.mdx +17 -6
  52. package/site/content/docs/reference/index.mdx +5 -0
  53. package/site/content/docs/reference/meta.json +1 -0
  54. package/site/content/docs/reference/migrating-environments.mdx +158 -0
  55. package/site/content/docs/reference/plugins.mdx +2 -2
  56. package/src/auth/gate-auth.test.ts +12 -10
  57. package/src/cli/ai-setup/ai-setup.test.ts +30 -16
  58. package/src/cli/ai-setup/apply.ts +111 -15
  59. package/src/cli/ai-setup/catalog.ts +3 -3
  60. package/src/cli/ai-setup/index.ts +1 -1
  61. package/src/cli/ai-setup/prompts.ts +1 -1
  62. package/src/cli/ai-setup/recommend.test.ts +1 -1
  63. package/src/cli/ask-seed.test.ts +3 -3
  64. package/src/cli/build.ts +8 -9
  65. package/src/cli/db-auto-push.test.ts +6 -3
  66. package/src/cli/db-auto-push.ts +7 -5
  67. package/src/cli/db-seed.ts +7 -8
  68. package/src/cli/db.test.ts +70 -71
  69. package/src/cli/db.ts +86 -12
  70. package/src/cli/dev-controller.test.ts +35 -0
  71. package/src/cli/dev-controller.ts +298 -0
  72. package/src/cli/dev-controls.ts +11 -65
  73. package/src/cli/dev-db-push.test.ts +47 -15
  74. package/src/cli/dev-schema-sync.test.ts +11 -11
  75. package/src/cli/dev-schema-sync.ts +10 -10
  76. package/src/cli/dev-session-lock.test.ts +106 -0
  77. package/src/cli/dev-session-lock.ts +209 -0
  78. package/src/cli/dev.test.ts +246 -114
  79. package/src/cli/dev.ts +153 -205
  80. package/src/cli/doc-staleness.test.ts +3 -6
  81. package/src/cli/docker-clean.test.ts +33 -1
  82. package/src/cli/docker-clean.ts +28 -33
  83. package/src/cli/docker-cli.test.ts +12 -11
  84. package/src/cli/docker.ts +95 -20
  85. package/src/cli/doctor.test.ts +40 -0
  86. package/src/cli/doctor.ts +142 -9
  87. package/src/cli/drizzle-env.test.ts +11 -13
  88. package/src/cli/drizzle-env.ts +18 -11
  89. package/src/cli/ensure-drizzle-config.ts +11 -14
  90. package/src/cli/hero-meta.test.ts +15 -15
  91. package/src/cli/hero-meta.ts +10 -9
  92. package/src/cli/index.ts +36 -6
  93. package/src/cli/load-config.images.test.ts +44 -10
  94. package/src/cli/load-config.source.test.ts +50 -0
  95. package/src/cli/load-config.ts +35 -29
  96. package/src/cli/meilisearch-local.ts +1 -2
  97. package/src/cli/mode.ts +7 -58
  98. package/src/cli/registry.ts +175 -19
  99. package/src/cli/resolve-dev-sql-env.test.ts +8 -16
  100. package/src/cli/resolve-dev-sql-env.ts +13 -15
  101. package/src/cli/safe-defaults.test.ts +29 -11
  102. package/src/cli/schema.ts +65 -16
  103. package/src/cli/test.ts +58 -0
  104. package/src/cli/tui/App.tsx +252 -0
  105. package/src/cli/tui/DevLive.tsx +116 -0
  106. package/src/cli/tui/components/ConfirmDialog.tsx +48 -0
  107. package/src/cli/tui/components/HeaderBar.tsx +67 -0
  108. package/src/cli/tui/components/LogStream.tsx +47 -0
  109. package/src/cli/tui/components/PanelCard.tsx +39 -0
  110. package/src/cli/tui/components/SelectRow.tsx +37 -0
  111. package/src/cli/tui/components/SlashPalette.tsx +172 -0
  112. package/src/cli/tui/components/Spinner.tsx +32 -0
  113. package/src/cli/tui/components/StatusBar.tsx +51 -0
  114. package/src/cli/tui/components/StatusDot.tsx +37 -0
  115. package/src/cli/tui/components/TabBar.tsx +49 -0
  116. package/src/cli/tui/components/Wordmark.tsx +43 -0
  117. package/src/cli/tui/format.ts +38 -0
  118. package/src/cli/tui/keys.test.ts +18 -0
  119. package/src/cli/tui/keys.ts +26 -0
  120. package/src/cli/tui/launch.test.ts +18 -0
  121. package/src/cli/tui/launch.ts +57 -0
  122. package/src/cli/tui/panels/Dashboard.tsx +201 -0
  123. package/src/cli/tui/panels/Database.tsx +198 -0
  124. package/src/cli/tui/panels/Dev.tsx +257 -0
  125. package/src/cli/tui/panels/Docker.tsx +357 -0
  126. package/src/cli/tui/panels/Navigator.test.ts +22 -0
  127. package/src/cli/tui/panels/Navigator.tsx +213 -0
  128. package/src/cli/tui/slash-catalog.test.ts +31 -0
  129. package/src/cli/tui/slash-catalog.ts +184 -0
  130. package/src/cli/tui/slash-run.ts +54 -0
  131. package/src/cli/tui/state/ports.ts +95 -0
  132. package/src/cli/tui/theme.ts +24 -0
  133. package/src/cli/vault-cmd.test.ts +402 -0
  134. package/src/cli/vault-cmd.ts +727 -69
  135. package/src/cli/vault-secure-input.test.ts +56 -0
  136. package/src/cli/vault-secure-input.ts +124 -0
  137. package/src/compiler/effects-infer.ts +7 -0
  138. package/src/compiler/extract.ts +12 -0
  139. package/src/compiler/fixtures/skyport/oke.config.ts +7 -5
  140. package/src/compiler/fixtures/skyport/src/flows/payments/index.ts +1 -1
  141. package/src/compiler/fixtures/skyport.expected.json +1 -1
  142. package/src/compiler/generate-adopt.ts +27 -1
  143. package/src/compiler-entry.ts +7 -0
  144. package/src/config/define-config.test.ts +111 -47
  145. package/src/config/driver-defaults.test.ts +115 -0
  146. package/src/config/driver-defaults.ts +156 -0
  147. package/src/config/index.ts +246 -131
  148. package/src/config/resolve-driver.test.ts +14 -19
  149. package/src/console/server/app.ts +4 -2
  150. package/src/console/server/console.test.ts +58 -1
  151. package/src/console/server/flows.ts +22 -2
  152. package/src/console/server/index.ts +3 -0
  153. package/src/console/server/operator-db.test.ts +55 -13
  154. package/src/console/server/operator-db.ts +305 -263
  155. package/src/console/server/serve.ts +16 -7
  156. package/src/console/server/state.ts +31 -9
  157. package/src/console/server/vault.test.ts +120 -5
  158. package/src/console/server/vault.ts +208 -12
  159. package/src/console/ui/dist/assets/{index-D-9KFce5.js → index--Y0Uaz-m.js} +2 -2
  160. package/src/console/ui/dist/assets/panel-vault-BkZdJPX8.js +1 -0
  161. package/src/console/ui/dist/assets/style-C3L349iZ.css +3 -0
  162. package/src/console/ui/dist/index.html +2 -2
  163. package/src/console/ui/shell/client.ts +16 -0
  164. package/src/console/ui/shell/panels/vault/VaultPanel.tsx +54 -1
  165. package/src/console/ui/vault/VaultA11yView.tsx +33 -1
  166. package/src/console/ui/vault/backend.test.ts +75 -0
  167. package/src/console/ui/vault/backend.ts +117 -0
  168. package/src/console/ui/vault/fixture.ts +21 -2
  169. package/src/console/ui/vault/index.ts +11 -1
  170. package/src/console/ui/vault/types.ts +26 -0
  171. package/src/docker/compose.ts +164 -61
  172. package/src/docker/derive.ts +106 -12
  173. package/src/docker/docker.test.ts +156 -110
  174. package/src/docker/helpers.ts +98 -0
  175. package/src/docker/images-config.test.ts +163 -0
  176. package/src/docker/index.ts +30 -5
  177. package/src/docker/recipes/index.ts +0 -3
  178. package/src/docker/recipes/llama-cpp.ts +4 -4
  179. package/src/docker/recipes/pgdog.ts +9 -2
  180. package/src/docker/resources.test.ts +71 -0
  181. package/src/docker/resources.ts +176 -0
  182. package/src/docker/stack-id.test.ts +11 -4
  183. package/src/docker/stack-id.ts +42 -32
  184. package/src/docker/stack.integration.test.ts +4 -15
  185. package/src/docker/types.ts +35 -3
  186. package/src/drivers/ai-ollama.integration.test.ts +2 -2
  187. package/src/drivers/conformance.test.ts +11 -12
  188. package/src/drivers/drizzle-dialect.test.ts +0 -4
  189. package/src/drivers/drizzle-dialect.ts +7 -13
  190. package/src/drivers/index.ts +24 -7
  191. package/src/drivers/journal-postgres.test.ts +3 -1
  192. package/src/drivers/journal-postgres.ts +4 -2
  193. package/src/drivers/meilisearch.ts +1 -1
  194. package/src/drivers/pglite.ts +28 -5
  195. package/src/drivers/types.ts +9 -11
  196. package/src/drivers/vault-aws-secrets-manager.test.ts +159 -0
  197. package/src/drivers/vault-aws-secrets-manager.ts +333 -0
  198. package/src/drivers/vault-builtin.test.ts +110 -0
  199. package/src/drivers/vault-builtin.ts +184 -0
  200. package/src/drivers/vault-driver-removal.test.ts +13 -0
  201. package/src/drivers/vault-managed.test.ts +95 -0
  202. package/src/drivers/vault-managed.ts +101 -25
  203. package/src/drivers/vault-types.ts +25 -5
  204. package/src/elements/ai/runtime.ts +1 -1
  205. package/src/elements/clock/chaos.test.ts +4 -1
  206. package/src/elements/clock/durable.ts +57 -4
  207. package/src/elements/clock.test.ts +13 -14
  208. package/src/elements/gate/constants.ts +18 -0
  209. package/src/elements/gate.test.ts +1 -1
  210. package/src/elements/gate.ts +2 -2
  211. package/src/elements/store/domain-ddl.test.ts +5 -12
  212. package/src/elements/store/emit-drizzle.ts +44 -19
  213. package/src/elements/store/index-boot.test.ts +15 -116
  214. package/src/elements/store/load-plugin-tables.ts +1 -1
  215. package/src/elements/store/resource-list-docs.fixture.ts +12 -6
  216. package/src/elements/store/resource-list-docs.test.ts +64 -44
  217. package/src/elements/store/resource.test.ts +17 -10
  218. package/src/elements/store/runtime.ts +9 -12
  219. package/src/elements/store/schema-decl.test.ts +16 -32
  220. package/src/elements/store/seed.test.ts +1 -2
  221. package/src/elements/store/seed.ts +7 -8
  222. package/src/elements/store/sql-condition.test.ts +2 -2
  223. package/src/elements/store/sql-session.test.ts +8 -10
  224. package/src/elements/store/sql-session.ts +10 -2
  225. package/src/elements/store.test.ts +13 -13
  226. package/src/elements/vault/audit.ts +233 -0
  227. package/src/elements/vault/boot-chain.test.ts +78 -0
  228. package/src/elements/vault/boot-chain.ts +43 -39
  229. package/src/elements/vault/builtin-adapter.test.ts +479 -0
  230. package/src/elements/vault/builtin-adapter.ts +1184 -0
  231. package/src/elements/vault/crypto.test.ts +237 -0
  232. package/src/elements/vault/crypto.ts +431 -0
  233. package/src/elements/vault/declare.ts +164 -3
  234. package/src/elements/vault/errors.ts +56 -0
  235. package/src/elements/vault/kms-unseal.test.ts +76 -0
  236. package/src/elements/vault/kms-unseal.ts +181 -0
  237. package/src/elements/vault/path.ts +90 -0
  238. package/src/elements/vault/resilience.test.ts +102 -0
  239. package/src/elements/vault/resilience.ts +107 -0
  240. package/src/elements/vault/runtime.ts +36 -4
  241. package/src/elements/vault/security-checklist.test.ts +130 -0
  242. package/src/elements/vault/storage.ts +448 -0
  243. package/src/elements/vault/types.ts +288 -0
  244. package/src/elements/vault/unseal.ts +150 -0
  245. package/src/elements/vault.test.ts +72 -4
  246. package/src/elements/vault.ts +91 -2
  247. package/src/full.ts +248 -0
  248. package/src/http.ts +41 -0
  249. package/src/i18n/interpolate-simple.ts +37 -0
  250. package/src/i18n/messages.ts +51 -4
  251. package/src/i18n-entry.ts +7 -0
  252. package/src/index.ts +35 -145
  253. package/src/journal-entry.ts +20 -0
  254. package/src/kernel/adopt-barrel-fresh.test.ts +25 -10
  255. package/src/kernel/app.ts +40 -42
  256. package/src/kernel/auto-registry.test.ts +2 -2
  257. package/src/kernel/boot-bind/ai.test.ts +5 -5
  258. package/src/kernel/boot-bind/ai.ts +2 -1
  259. package/src/kernel/boot-bind/channel.test.ts +6 -6
  260. package/src/kernel/boot-bind/channel.ts +5 -4
  261. package/src/kernel/boot-bind/clock.ts +5 -5
  262. package/src/kernel/boot-bind/gate.ts +6 -7
  263. package/src/kernel/boot-bind/honor-config.test.ts +42 -42
  264. package/src/kernel/boot-bind/journal.ts +5 -5
  265. package/src/kernel/boot-bind/signal.ts +3 -1
  266. package/src/kernel/boot-bind/store.test.ts +55 -37
  267. package/src/kernel/boot-bind/store.ts +24 -34
  268. package/src/kernel/boot-bind/vault.ts +19 -4
  269. package/src/kernel/boot.test.ts +12 -4
  270. package/src/kernel/boot.ts +31 -19
  271. package/src/kernel/budget-entry.ts +1 -1
  272. package/src/kernel/compensate.test.ts +288 -1
  273. package/src/kernel/compensate.ts +126 -0
  274. package/src/kernel/concurrency.test.ts +10 -9
  275. package/src/kernel/effects-stamping.test.ts +27 -2
  276. package/src/kernel/element-registries.ts +5 -3
  277. package/src/kernel/flow.ts +4 -2
  278. package/src/kernel/fx.test.ts +119 -3
  279. package/src/kernel/fx.ts +215 -40
  280. package/src/kernel/index.ts +14 -0
  281. package/src/kernel/journal.ts +130 -7
  282. package/src/kernel/pipeline.test.ts +20 -6
  283. package/src/kernel/redacted.test.ts +35 -0
  284. package/src/kernel/redacted.ts +24 -2
  285. package/src/kernel/router/create-default.ts +16 -0
  286. package/src/kernel/router/create-edge.ts +18 -0
  287. package/src/kernel/router/create.ts +23 -0
  288. package/src/kernel/router/index.ts +23 -0
  289. package/src/kernel/router/linear.ts +88 -0
  290. package/src/kernel/router/regexp.ts +188 -0
  291. package/src/kernel/router/smart.ts +120 -0
  292. package/src/kernel/router/trie.ts +108 -0
  293. package/src/kernel/router/types.ts +56 -0
  294. package/src/kernel/router.ts +18 -532
  295. package/src/kernel-entry.ts +43 -0
  296. package/src/manifest/fixtures/skyport.excerpt.json +1 -1
  297. package/src/manifest/fixtures/skyport.manifest.json +1 -1
  298. package/src/plugins/config-source.test.ts +7 -7
  299. package/src/release/build-lib.ts +58 -0
  300. package/src/release/exports.test.ts +4 -2
  301. package/src/release/exports.ts +30 -4
  302. package/src/release/measure.ts +101 -22
  303. package/src/runs/duckdb.ts +7 -2
  304. package/src/shared/optional-peer.ts +41 -0
  305. package/src/term.test.ts +3 -44
  306. package/src/test/create-test-app.ts +12 -0
  307. package/src/test/provisions.integration.test.ts +1 -1
  308. package/src/test/reset-element-registries.ts +2 -0
  309. package/src/upgrade/codemods.test.ts +7 -20
  310. package/src/upgrade/codemods.ts +93 -60
  311. package/site/content/docs/console/access.mdx +0 -29
  312. package/site/content/docs/console/ai.mdx +0 -35
  313. package/site/content/docs/console/architecture.mdx +0 -35
  314. package/site/content/docs/console/channels.mdx +0 -37
  315. package/site/content/docs/console/clock.mdx +0 -51
  316. package/site/content/docs/console/flows.mdx +0 -31
  317. package/site/content/docs/console/gates.mdx +0 -73
  318. package/site/content/docs/console/index.mdx +0 -54
  319. package/site/content/docs/console/manifest-diff.mdx +0 -34
  320. package/site/content/docs/console/meta.json +0 -24
  321. package/site/content/docs/console/overview.mdx +0 -40
  322. package/site/content/docs/console/plugins.mdx +0 -41
  323. package/site/content/docs/console/privacy.mdx +0 -32
  324. package/site/content/docs/console/runs.mdx +0 -50
  325. package/site/content/docs/console/signals.mdx +0 -40
  326. package/site/content/docs/console/store.mdx +0 -32
  327. package/site/content/docs/console/tenancy.mdx +0 -32
  328. package/site/content/docs/console/traces.mdx +0 -38
  329. package/site/content/docs/console/vault.mdx +0 -41
  330. package/site/content/docs/recipes/openbao.mdx +0 -141
  331. package/src/cli/ask-dev-mode.ts +0 -40
  332. package/src/cli/dev-mode.test.ts +0 -45
  333. package/src/cli/dev-mode.ts +0 -78
  334. package/src/cli/openbao-bootstrap.test.ts +0 -150
  335. package/src/cli/openbao-bootstrap.ts +0 -321
  336. package/src/cli/openbao-restart.integration.test.ts +0 -145
  337. package/src/console/ui/dist/assets/panel-vault-Za1GyJfM.js +0 -1
  338. package/src/console/ui/dist/assets/style-C8MxEWPd.css +0 -3
  339. package/src/docker/recipes/openbao.ts +0 -47
  340. package/src/drivers/libsql.ts +0 -179
  341. package/src/drivers/sqlite.ts +0 -44
  342. package/src/drivers/vault-openbao.test.ts +0 -97
  343. package/src/drivers/vault-openbao.ts +0 -143
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Write AI driver config, env, and `src/core/ai.ts` for `oke ai setup`.
2
+ * Write AI driver config, env, and AI models into `src/core.ts` for `oke ai setup`.
3
3
  */
4
4
 
5
5
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
@@ -70,13 +70,15 @@ export function applyAiSetup(
70
70
  : existsSync(envExample)
71
71
  ? readFileSync(envExample, "utf8")
72
72
  : "";
73
- // Driver / URL stay commented so docker mode can hydrate `OKE_AI_URL` from
74
- // `docker/.env.docker` without being shadowed. The selected chat model is
75
- // written active `oke dev` seeds it into stack controls / `LLAMA_ARG_DOCKER_REPO`
76
- // (commented-only left the compose default `smollm2` forever).
73
+ // Driver / URL / model stay commented so docker mode can hydrate from
74
+ // `docker/.env.docker` without being shadowed. The chosen model is still
75
+ // written into `.env.local` as a hint (and into `.env.docker` when present);
76
+ // `loadExistingStackControls` seeds commented `OKE_AI_MODEL` on first boot.
77
77
  env = upsertEnv(env, "OKE_AI_DRIVER", input.driver, { comment: true });
78
78
  if (input.baseUrl) env = upsertEnv(env, "OKE_AI_URL", input.baseUrl, { comment: true });
79
- if (input.chatModel) env = upsertEnv(env, "OKE_AI_MODEL", input.chatModel);
79
+ if (input.chatModel) {
80
+ env = upsertEnv(env, "OKE_AI_MODEL", input.chatModel, { comment: true });
81
+ }
80
82
  if (input.visionModel) {
81
83
  env = upsertEnv(env, "OKE_AI_VISION_MODEL", input.visionModel, { comment: true });
82
84
  }
@@ -104,10 +106,7 @@ export function applyAiSetup(
104
106
  }
105
107
  }
106
108
 
107
- const aiTsPath = join(cwd, "src", "core", "ai.ts");
108
- mkdirSync(dirname(aiTsPath), { recursive: true });
109
- writeFileSync(aiTsPath, renderAiTs(input), "utf8");
110
- ensureAiImported(cwd);
109
+ const aiTsPath = writeAiModels(cwd, input);
111
110
 
112
111
  return { configPath, envPath, aiTsPath };
113
112
  }
@@ -118,8 +117,7 @@ export function applyAiSetup(
118
117
  */
119
118
  export function upsertAiDrivers(source: string, driver: string): string {
120
119
  const block = `{
121
- local: "${driver}",
122
- docker: "${driver === "mock" ? "mock" : driver}",
120
+ dev: "${driver === "mock" ? "mock" : driver}",
123
121
  test: "mock",
124
122
  prod: "${driver === "mock" ? "mock" : driver}",
125
123
  }`;
@@ -243,15 +241,113 @@ export function renderAiTs(input: AiSetupApplyInput): string {
243
241
  }
244
242
 
245
243
  /**
246
- * Ensure `src/app.ts` or `src/core/index.ts` imports AI wiring.
244
+ * Write AI model declarations into `src/core.ts` (preferred) or legacy `src/core/ai.ts`.
245
+ *
246
+ * @param cwd - Project root
247
+ * @param input - Setup choices
248
+ * @returns Path written
249
+ */
250
+ function writeAiModels(cwd: string, input: AiSetupApplyInput): string {
251
+ const rendered = renderAiTs(input);
252
+ const coreTsPath = join(cwd, "src", "core.ts");
253
+ const legacyIndex = join(cwd, "src", "core", "index.ts");
254
+
255
+ // Folder layout still in the wild — keep writing a sidecar.
256
+ if (!existsSync(coreTsPath) && existsSync(legacyIndex)) {
257
+ const aiTsPath = join(cwd, "src", "core", "ai.ts");
258
+ mkdirSync(dirname(aiTsPath), { recursive: true });
259
+ writeFileSync(aiTsPath, rendered, "utf8");
260
+ ensureLegacyAiImported(cwd);
261
+ return aiTsPath;
262
+ }
263
+
264
+ mkdirSync(dirname(coreTsPath), { recursive: true });
265
+ if (existsSync(coreTsPath)) {
266
+ const existing = readFileSync(coreTsPath, "utf8");
267
+ if (hasAiModels(existing)) {
268
+ return coreTsPath;
269
+ }
270
+ writeFileSync(coreTsPath, mergeAiIntoCore(existing, rendered), "utf8");
271
+ } else {
272
+ writeFileSync(coreTsPath, rendered, "utf8");
273
+ }
274
+ ensureCoreImported(cwd);
275
+ return coreTsPath;
276
+ }
277
+
278
+ /**
279
+ * @param source - Existing TypeScript
280
+ */
281
+ function hasAiModels(source: string): boolean {
282
+ return (
283
+ /\bai\.model\s*\(/.test(source) ||
284
+ /from\s+["']\.\/(?:core\/)?ai["']/.test(source) ||
285
+ /import\s+["']\.\/(?:core\/)?ai["']/.test(source)
286
+ );
287
+ }
288
+
289
+ /**
290
+ * Merge rendered AI module into an existing `src/core.ts`.
291
+ *
292
+ * @param existing - Current core.ts
293
+ * @param rendered - Output of {@link renderAiTs}
294
+ */
295
+ export function mergeAiIntoCore(existing: string, rendered: string): string {
296
+ const body = rendered.replace(/^import\s*\{\s*ai\s*\}\s*from\s*["']okengine["'];\s*\n*/m, "");
297
+ const next = ensureNamedOkengineImport(existing, "ai");
298
+ return `${next.trimEnd()}\n\n${body.trimStart()}`;
299
+ }
300
+
301
+ /**
302
+ * Ensure a named binding is imported from `"okengine"`.
303
+ *
304
+ * @param source - Module source
305
+ * @param name - Binding to add
306
+ */
307
+ export function ensureNamedOkengineImport(source: string, name: string): string {
308
+ const re = /import\s*\{([^}]*)\}\s*from\s*["']okengine["']\s*;/;
309
+ const m = re.exec(source);
310
+ if (!m) {
311
+ return `import { ${name} } from "okengine";\n${source}`;
312
+ }
313
+ const names = m[1]!
314
+ .split(",")
315
+ .map((s) => s.trim())
316
+ .filter(Boolean);
317
+ if (names.includes(name)) return source;
318
+ const sorted = [...names, name].sort((a, b) => a.localeCompare(b));
319
+ return source.replace(re, `import { ${sorted.join(", ")} } from "okengine";`);
320
+ }
321
+
322
+ /**
323
+ * Ensure `src/app.ts` loads `@/core` / `./core` so merged AI registers.
324
+ *
325
+ * @param cwd - Project root
326
+ */
327
+ function ensureCoreImported(cwd: string): void {
328
+ const appPath = join(cwd, "src", "app.ts");
329
+ if (!existsSync(appPath)) return;
330
+ const src = readFileSync(appPath, "utf8");
331
+ if (
332
+ /from\s+["']@\/core["']/.test(src) ||
333
+ /import\s+["']@\/core["']/.test(src) ||
334
+ /from\s+["']\.\/core(?:\.ts)?["']/.test(src) ||
335
+ /import\s+["']\.\/core(?:\.ts)?["']/.test(src)
336
+ ) {
337
+ return;
338
+ }
339
+ writeFileSync(appPath, `import "@/core";\n${src}`, "utf8");
340
+ }
341
+
342
+ /**
343
+ * Legacy `src/core/*` layout — side-effect import the AI sidecar.
247
344
  *
248
345
  * @param cwd - Project root
249
346
  */
250
- function ensureAiImported(cwd: string): void {
347
+ function ensureLegacyAiImported(cwd: string): void {
251
348
  const candidates: ReadonlyArray<{ readonly rel: string; readonly importLine: string }> = [
252
349
  { rel: "src/app.ts", importLine: `import "./core/ai";\n` },
253
350
  { rel: "src/core/index.ts", importLine: `import "./ai";\n` },
254
- { rel: "src/core.ts", importLine: `import "./ai";\n` },
255
351
  ];
256
352
  for (const { rel, importLine } of candidates) {
257
353
  const path = join(cwd, rel);
@@ -788,9 +788,8 @@ export const LLAMA_CPP_CHAT_MODELS: readonly CatalogModel[] = [
788
788
  {
789
789
  id: "smollm2",
790
790
  label: "SmolLM2",
791
- hint: "Default · lightest",
791
+ hint: "Lightest",
792
792
  role: "chat",
793
- recommended: true,
794
793
  ramGb: 1,
795
794
  tier: "ultra-fast",
796
795
  modalities: ["text"],
@@ -951,8 +950,9 @@ export const LLAMA_CPP_CHAT_MODELS: readonly CatalogModel[] = [
951
950
  {
952
951
  id: "granite3.3:2b",
953
952
  label: "Granite 3.3 2B",
954
- hint: "IBM 2B",
953
+ hint: "Default · IBM 2B",
955
954
  role: "chat",
955
+ recommended: true,
956
956
  ramGb: 2,
957
957
  tier: "ultra-fast",
958
958
  modalities: ["text", "code"],
@@ -202,7 +202,7 @@ function nonInteractiveInput(args: AiSetupCliArgs): AiSetupApplyInput {
202
202
  return {
203
203
  driver: "openai-compatible",
204
204
  baseUrl: process.env.OKE_AI_URL ?? "http://127.0.0.1:8080/v1",
205
- chatModel: args.chat ?? "smollm2",
205
+ chatModel: args.chat ?? "granite3.3:2b",
206
206
  visionModel: null,
207
207
  embedModel: null,
208
208
  image: "ghcr.io/ggml-org/llama.cpp:server-b10290",
@@ -154,7 +154,7 @@ async function askLlamaCppPath(options: {
154
154
  if (mode === null) return null;
155
155
 
156
156
  if (mode === "manual") {
157
- const id = await askOtherModelId("smollm2");
157
+ const id = await askOtherModelId("granite3.3:2b");
158
158
  if (id === null) return null;
159
159
  return finishLlamaCpp(id);
160
160
  }
@@ -150,7 +150,7 @@ describe("llama.cpp catalog", () => {
150
150
  });
151
151
 
152
152
  test("recommendLlamaCppForTier returns a model in that tier", () => {
153
- expect(recommendLlamaCppForTier("ultra-fast", 8).id).toBe("smollm2");
153
+ expect(recommendLlamaCppForTier("ultra-fast", 8).id).toBe("granite3.3:2b");
154
154
  expect(recommendLlamaCppForTier("fast", 16).tier).toBe("fast");
155
155
  });
156
156
 
@@ -17,7 +17,7 @@ describe("maybeAskSeed", () => {
17
17
  let seeded = false;
18
18
  await maybeAskSeed({
19
19
  cwd: dir,
20
- env: "local",
20
+ env: "test",
21
21
  stdinIsTTY: false,
22
22
  confirmFn: async () => true,
23
23
  seedFn: async () => {
@@ -39,7 +39,7 @@ describe("maybeAskSeed", () => {
39
39
  let calls = 0;
40
40
  await maybeAskSeed({
41
41
  cwd: dir,
42
- env: "local",
42
+ env: "test",
43
43
  stdinIsTTY: true,
44
44
  confirmFn: async () => true,
45
45
  seedFn: async () => {
@@ -52,7 +52,7 @@ describe("maybeAskSeed", () => {
52
52
 
53
53
  await maybeAskSeed({
54
54
  cwd: dir,
55
- env: "local",
55
+ env: "test",
56
56
  stdinIsTTY: true,
57
57
  confirmFn: async () => true,
58
58
  seedFn: async () => {
package/src/cli/build.ts CHANGED
@@ -2,9 +2,6 @@
2
2
  * `oke build --target edge` — tree-shaken kernel profile.
3
3
  */
4
4
 
5
- import { writeFile } from "node:fs/promises";
6
- import { join } from "node:path";
7
-
8
5
  /** Options for {@link runBuild}. */
9
6
  export interface BuildOptions {
10
7
  readonly target?: "bun" | "node" | "edge";
@@ -21,26 +18,28 @@ export interface BuildOptions {
21
18
  }) => Promise<{ success: boolean; logs: string }>;
22
19
  /**
23
20
  * Inject `.adopt()` barrel regeneration (tests). Default: real
24
- * `generateAdoptBarrel` + write to `<rootDir>/src/flows/generated.ts`.
25
- * Returns the unit names written, for the status line.
21
+ * `generateAdoptBarrel` + atomic write to `<rootDir>/src/flows/generated.ts`
22
+ * (`generated.ts.tmp` → rename). Returns the unit names written, for the
23
+ * status line.
26
24
  */
27
25
  readonly syncAdoptBarrel?: (rootDir: string) => Promise<readonly string[]>;
28
26
  }
29
27
 
30
28
  /**
31
29
  * Regenerate `src/flows/generated.ts` from every `src/flows/<unit>/index.ts`
32
- * unit folder — pre-step for `oke build` (mirrors `oke db`'s `schema.generated.ts`
30
+ * unit folder — pre-step for `oke build` (mirrors `oke db`'s `schema.drizzle.ts`
33
31
  * pre-step). A real file on disk, not a virtual module: identical resolution
34
32
  * under `oke dev`'s runtime `import()` and `oke build`'s `Bun.build()`
35
33
  * (investigated — a virtual-module Bun plugin does not resolve consistently
36
- * across those two paths).
34
+ * across those two paths). Written atomically so a concurrent reader never
35
+ * sees a torn file.
37
36
  *
38
37
  * @param rootDir - Project root
39
38
  */
40
39
  async function defaultSyncAdoptBarrel(rootDir: string): Promise<readonly string[]> {
41
- const { generateAdoptBarrel } = await import("../compiler/generate-adopt.ts");
40
+ const { generateAdoptBarrel, writeAdoptBarrel } = await import("../compiler/generate-adopt.ts");
42
41
  const { source, units } = await generateAdoptBarrel({ rootDir });
43
- await writeFile(join(rootDir, "src/flows/generated.ts"), source);
42
+ await writeAdoptBarrel(rootDir, source);
44
43
  return units;
45
44
  }
46
45
 
@@ -18,6 +18,9 @@ describe("isDomainSchemaWatchPath", () => {
18
18
  });
19
19
 
20
20
  test("ignores emit output (avoids push ↔ generated feedback loop)", () => {
21
+ expect(isDomainSchemaWatchPath("src/db/schema.drizzle.ts")).toBe(false);
22
+ expect(isDomainSchemaWatchPath("schema.drizzle.ts")).toBe(false);
23
+ expect(isDomainSchemaWatchPath("flows/notes/schema.drizzle.tsx")).toBe(false);
21
24
  expect(isDomainSchemaWatchPath("src/schema.generated.ts")).toBe(false);
22
25
  expect(isDomainSchemaWatchPath("schema.generated.ts")).toBe(false);
23
26
  expect(isDomainSchemaWatchPath("flows/notes/schema.generated.tsx")).toBe(false);
@@ -35,12 +38,12 @@ describe("isDomainSchemaWatchPath", () => {
35
38
  });
36
39
 
37
40
  describe("resolveDevAutoPush", () => {
38
- test("default on for local", () => {
41
+ test("default on", () => {
39
42
  expect(resolveDevAutoPush({})).toBe(true);
40
43
  });
41
44
 
42
- test("off for docker", () => {
43
- expect(resolveDevAutoPush({ docker: true })).toBe(false);
45
+ test("docker flag ignored (always-compose)", () => {
46
+ expect(resolveDevAutoPush({ docker: true })).toBe(true);
44
47
  });
45
48
 
46
49
  test("off for --no-db-push", () => {
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Debounced domain-schema auto-push for `oke dev` (local mode).
2
+ * Debounced domain-schema auto-push for `oke dev`.
3
3
  */
4
4
 
5
5
  import { basename } from "node:path";
@@ -11,7 +11,7 @@ export const DB_AUTO_PUSH_DEBOUNCE_MS = 300;
11
11
  * Whether a watched path should trigger `oke db push`.
12
12
  *
13
13
  * Inputs only: declaration / drizzle config / app entry. Never the emit
14
- * output (`schema.generated.ts`) — push rewrites that file every run, so
14
+ * output (`schema.drizzle.ts`) — push rewrites that file every run, so
15
15
  * watching it loops `oke db push` forever under `oke dev`.
16
16
  *
17
17
  * @param filename - Relative path from the watcher (may be undefined)
@@ -21,13 +21,14 @@ export function isDomainSchemaWatchPath(filename: string | null | undefined): bo
21
21
  const normalized = filename.replace(/\\/g, "/");
22
22
  const base = basename(normalized);
23
23
  // Emit output — never a watch trigger (feedback loop with `oke db push`).
24
+ if (base === "schema.drizzle.ts" || base === "schema.drizzle.tsx") return false;
24
25
  if (base === "schema.generated.ts" || base === "schema.generated.tsx") return false;
25
26
  if (base === "schema.ts" || base === "schema.tsx") return true;
26
27
  if (base === "schema.decl.ts" || base === "schema.decl.tsx") return true;
27
28
  if (base === "drizzle.config.ts" || base === "drizzle.config.js") return true;
28
29
  // App entry / plugins — `.plug()` table contributions feed emit.
29
30
  if (base === "app.ts" || base === "app.tsx") return true;
30
- // Nested domain schemas commonly live under src/**/schema.ts (not .generated).
31
+ // Nested domain schemas commonly live under src/**/schema.ts (not emit output).
31
32
  if (/(^|\/)schema(\.decl)?\.tsx?$/.test(normalized)) return true;
32
33
  return false;
33
34
  }
@@ -35,14 +36,15 @@ export function isDomainSchemaWatchPath(filename: string | null | undefined): bo
35
36
  /**
36
37
  * Resolve whether auto-push is enabled for this `oke dev` session.
37
38
  *
38
- * @param options - Explicit CLI opt-out, config, docker mode
39
+ * @param options - Explicit CLI opt-out / config (`docker` ignored — kept for call-site compat)
39
40
  */
40
41
  export function resolveDevAutoPush(options: {
41
42
  readonly noDbPush?: boolean;
43
+ /** @deprecated Ignored — `oke dev` is always Docker Compose. */
42
44
  readonly docker?: boolean;
43
45
  readonly configAutoPush?: boolean;
44
46
  }): boolean {
45
- if (options.docker) return false;
47
+ void options.docker;
46
48
  if (options.noDbPush) return false;
47
49
  return options.configAutoPush !== false;
48
50
  }
@@ -97,18 +97,17 @@ export function redactConnectionTarget(raw: string): string {
97
97
  * Human-readable DB target from drizzle overlay.
98
98
  *
99
99
  * @param overlay - Resolved drizzle-kit env overlay
100
- * @param dialect - sqlite | postgresql
100
+ * @param dialect - postgresql (only supported kit dialect)
101
101
  */
102
102
  export function formatSeedTarget(
103
103
  overlay: Readonly<Record<string, string>>,
104
104
  dialect: string,
105
105
  ): string {
106
- if (dialect === "postgresql" || overlay.DATABASE_URL) {
107
- const url = overlay.DATABASE_URL ?? "(DATABASE_URL unset)";
108
- return `postgresql ${redactConnectionTarget(url)}`;
106
+ if (overlay.OKE_PGLITE_URL && !overlay.DATABASE_URL) {
107
+ return `pglite ${redactConnectionTarget(overlay.OKE_PGLITE_URL)}`;
109
108
  }
110
- const url = overlay.OKE_SQLITE_URL ?? "file:.oke/app.sqlite";
111
- return `sqlite ${redactConnectionTarget(url)}`;
109
+ const url = overlay.DATABASE_URL ?? "(DATABASE_URL unset)";
110
+ return `${dialect === "postgresql" ? "postgresql" : dialect} ${redactConnectionTarget(url)}`;
112
111
  }
113
112
 
114
113
  /**
@@ -218,7 +217,7 @@ export async function bootSeedFx(
218
217
  entry?: string,
219
218
  config?: OkeConfig | null,
220
219
  ): Promise<{ readonly fx: Fx; readonly stop: () => Promise<void> }> {
221
- if (env === "docker") {
220
+ if (env === "dev") {
222
221
  await applyComposeEnvToProcess(cwd);
223
222
  if (process.env.OKE_DOCKER === undefined) process.env.OKE_DOCKER = "1";
224
223
  }
@@ -272,7 +271,7 @@ export async function runSeed(options: SeedOptions = {}): Promise<number> {
272
271
  }
273
272
  write(`oke db seed: env ${env} → ${targetLabel}\n`);
274
273
 
275
- if (env === "docker" || env === "prod") {
274
+ if (env === "dev" || env === "prod") {
276
275
  if (options.force !== true) {
277
276
  const tty = options.stdinIsTTY ?? Boolean(process.stdin.isTTY);
278
277
  const confirm =