okengine 0.9.0 → 0.10.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 (175) hide show
  1. package/AGENTS.md +1 -1
  2. package/manifest.v1.schema.json +9 -1
  3. package/package.json +3 -3
  4. package/site/content/docs/console/runs.mdx +10 -0
  5. package/site/content/docs/console/traces.mdx +4 -0
  6. package/site/content/docs/elements/ai.mdx +54 -32
  7. package/site/content/docs/elements/channel.mdx +105 -14
  8. package/site/content/docs/elements/clock.mdx +1 -0
  9. package/site/content/docs/elements/flow.mdx +42 -8
  10. package/site/content/docs/get-started/basic-usage.mdx +5 -1
  11. package/site/content/docs/get-started/installation.mdx +9 -5
  12. package/site/content/docs/meta.json +2 -0
  13. package/site/content/docs/plugins/otp.mdx +58 -46
  14. package/site/content/docs/providers/azure-redis.mdx +85 -0
  15. package/site/content/docs/providers/cockroachdb.mdx +86 -0
  16. package/site/content/docs/providers/digitalocean-caching.mdx +88 -0
  17. package/site/content/docs/providers/dragonfly-cloud.mdx +82 -0
  18. package/site/content/docs/providers/elasticache.mdx +92 -0
  19. package/site/content/docs/providers/index.mdx +101 -0
  20. package/site/content/docs/providers/memorystore.mdx +89 -0
  21. package/site/content/docs/providers/meta.json +20 -0
  22. package/site/content/docs/providers/neon.mdx +115 -0
  23. package/site/content/docs/providers/redis-cloud.mdx +93 -0
  24. package/site/content/docs/providers/supabase.mdx +117 -0
  25. package/site/content/docs/providers/upstash.mdx +91 -0
  26. package/site/content/docs/providers/yugabytedb.mdx +95 -0
  27. package/site/content/docs/recipes/caddy.mdx +128 -0
  28. package/site/content/docs/recipes/cockroachdb.mdx +127 -0
  29. package/site/content/docs/recipes/dragonfly.mdx +125 -0
  30. package/site/content/docs/recipes/index.mdx +146 -0
  31. package/site/content/docs/recipes/llama-cpp.mdx +153 -0
  32. package/site/content/docs/recipes/mailpit.mdx +136 -0
  33. package/site/content/docs/recipes/meilisearch.mdx +139 -0
  34. package/site/content/docs/recipes/meta.json +31 -0
  35. package/site/content/docs/recipes/ollama.mdx +142 -0
  36. package/site/content/docs/recipes/openbao.mdx +141 -0
  37. package/site/content/docs/recipes/pgdog.mdx +137 -0
  38. package/site/content/docs/recipes/postgres.mdx +136 -0
  39. package/site/content/docs/recipes/redis.mdx +130 -0
  40. package/site/content/docs/recipes/rustfs.mdx +148 -0
  41. package/site/content/docs/recipes/sglang.mdx +105 -0
  42. package/site/content/docs/recipes/supabase-docker.mdx +145 -0
  43. package/site/content/docs/recipes/timescale.mdx +129 -0
  44. package/site/content/docs/recipes/traefik.mdx +136 -0
  45. package/site/content/docs/recipes/valkey.mdx +121 -0
  46. package/site/content/docs/recipes/vllm.mdx +106 -0
  47. package/site/content/docs/recipes/yugabytedb.mdx +135 -0
  48. package/site/content/docs/reference/cli.md +42 -6
  49. package/site/content/docs/reference/configuration.mdx +5 -3
  50. package/site/content/docs/reference/environment-variables.mdx +12 -12
  51. package/site/content/docs/reference/fx.mdx +38 -4
  52. package/src/auth/otp-capability.ts +14 -14
  53. package/src/cli/ai-setup/ai-setup.test.ts +32 -12
  54. package/src/cli/ai-setup/apply.ts +65 -23
  55. package/src/cli/ai-setup/catalog.ts +1316 -35
  56. package/src/cli/ai-setup/detect-ollama.ts +47 -0
  57. package/src/cli/ai-setup/index.ts +44 -7
  58. package/src/cli/ai-setup/prompts.ts +430 -486
  59. package/src/cli/ai-setup/recommend.test.ts +150 -50
  60. package/src/cli/ai-setup/recommend.ts +118 -101
  61. package/src/cli/ask-seed.test.ts +68 -0
  62. package/src/cli/ask-seed.ts +79 -0
  63. package/src/cli/db-seed-redact.test.ts +25 -0
  64. package/src/cli/db-seed.ts +36 -7
  65. package/src/cli/db.test.ts +1 -1
  66. package/src/cli/db.ts +2 -2
  67. package/src/cli/dev-controls.test.ts +107 -0
  68. package/src/cli/dev-controls.ts +354 -0
  69. package/src/cli/dev-schema-sync.ts +12 -4
  70. package/src/cli/dev.test.ts +50 -30
  71. package/src/cli/dev.ts +607 -66
  72. package/src/cli/drizzle-env.test.ts +40 -6
  73. package/src/cli/drizzle-env.ts +22 -1
  74. package/src/cli/ensure-drizzle-config.ts +6 -4
  75. package/src/cli/hero-meta.test.ts +13 -1
  76. package/src/cli/hero-meta.ts +28 -6
  77. package/src/cli/index.ts +5 -0
  78. package/src/cli/registry.ts +24 -0
  79. package/src/cli/replay.test.ts +105 -0
  80. package/src/cli/replay.ts +206 -0
  81. package/src/compiler/extract.ts +3 -3
  82. package/src/config/index.ts +3 -3
  83. package/src/console/server/claim.ts +3 -1
  84. package/src/console/ui/dist/assets/{index-ClX0ZCe5.js → index-D-9KFce5.js} +2 -2
  85. package/src/console/ui/dist/assets/panel-overview-CW0CQEc2.js +1 -0
  86. package/src/console/ui/dist/assets/panel-runs-BxuyDI3x.js +1 -0
  87. package/src/console/ui/dist/assets/{panel-signals-Dsxdu_AR.js → panel-signals-BXofbj7v.js} +1 -1
  88. package/src/console/ui/dist/assets/{panel-store-hy7O8HOs.js → panel-store-B8mH-arU.js} +1 -1
  89. package/src/console/ui/dist/assets/{panel-traces-CBiAe5go.js → panel-traces-DSA-ZWnf.js} +1 -1
  90. package/src/console/ui/dist/index.html +1 -1
  91. package/src/console/ui/overview/slo.ts +31 -3
  92. package/src/console/ui/overview/types.ts +6 -0
  93. package/src/console/ui/runs/errors.test.ts +53 -0
  94. package/src/console/ui/runs/errors.ts +88 -0
  95. package/src/console/ui/runs/index.ts +8 -0
  96. package/src/console/ui/runs/search.ts +16 -0
  97. package/src/console/ui/shell/panels/runs/RunsPanel.tsx +72 -1
  98. package/src/docker/ai-model-status.test.ts +101 -0
  99. package/src/docker/ai-model-status.ts +276 -0
  100. package/src/docker/compose-health.test.ts +115 -0
  101. package/src/docker/compose-health.ts +234 -0
  102. package/src/docker/compose.ts +24 -8
  103. package/src/docker/derive.ts +35 -9
  104. package/src/docker/docker.test.ts +304 -12
  105. package/src/docker/helpers.ts +56 -0
  106. package/src/docker/index.ts +52 -0
  107. package/src/docker/ollama-pull.ts +232 -0
  108. package/src/docker/recipes/cockroach.ts +24 -0
  109. package/src/docker/recipes/index.ts +32 -0
  110. package/src/docker/recipes/llama-cpp.ts +273 -0
  111. package/src/docker/recipes/ollama.ts +19 -23
  112. package/src/docker/recipes/pgdog.ts +4 -1
  113. package/src/docker/recipes/postgres.ts +5 -18
  114. package/src/docker/recipes/sglang.ts +55 -0
  115. package/src/docker/recipes/supabase.ts +21 -0
  116. package/src/docker/recipes/timescale.ts +18 -0
  117. package/src/docker/recipes/vllm.ts +44 -0
  118. package/src/docker/recipes/yugabyte.ts +23 -0
  119. package/src/docker/stack-id.test.ts +22 -0
  120. package/src/docker/stack-id.ts +38 -4
  121. package/src/docker/types.ts +15 -0
  122. package/src/drivers/ai-ollama.integration.test.ts +7 -4
  123. package/src/drivers/signal-engine.ts +10 -0
  124. package/src/drivers/signal-postgres.ts +24 -2
  125. package/src/drivers/signal-types.ts +10 -0
  126. package/src/elements/channel/fallback.test.ts +91 -0
  127. package/src/elements/channel/hard-bounce.test.ts +82 -0
  128. package/src/elements/channel/injection.test.ts +153 -0
  129. package/src/elements/channel/locale-ar.test.ts +102 -0
  130. package/src/elements/channel/otp-delivery.ts +5 -2
  131. package/src/elements/channel/receipts-ledger.test.ts +100 -0
  132. package/src/elements/channel/runtime.ts +24 -1
  133. package/src/elements/channel/test-helpers.ts +60 -0
  134. package/src/elements/channel/whatsapp-compliance.test.ts +124 -0
  135. package/src/elements/store/cache.ts +1 -1
  136. package/src/elements/store/emit-drizzle.ts +43 -9
  137. package/src/elements/store/runtime.ts +1 -1
  138. package/src/elements/store/schema-decl.test.ts +2 -0
  139. package/src/elements/store/schema-decl.ts +15 -0
  140. package/src/elements/store/seed.ts +1 -1
  141. package/src/index.ts +1 -0
  142. package/src/kernel/app.ts +118 -11
  143. package/src/kernel/boot-bind/signal.ts +6 -2
  144. package/src/kernel/boot-bind/store.ts +2 -1
  145. package/src/kernel/boot.test.ts +6 -5
  146. package/src/kernel/boot.ts +8 -3
  147. package/src/kernel/compensate.test.ts +131 -0
  148. package/src/kernel/correlation.test.ts +108 -0
  149. package/src/kernel/effect-timing.test.ts +82 -0
  150. package/src/kernel/flow.ts +38 -0
  151. package/src/kernel/fx-runs.test.ts +49 -0
  152. package/src/kernel/fx.test.ts +14 -0
  153. package/src/kernel/fx.ts +111 -1
  154. package/src/manifest/types.ts +8 -2
  155. package/src/plugins/auth-delivery.mailpit.integration.test.ts +1 -1
  156. package/src/plugins/auth-methods.security.test.ts +3 -3
  157. package/src/plugins/auth-methods.test.ts +1 -1
  158. package/src/plugins/index.ts +2 -2
  159. package/src/plugins/otp.test.ts +21 -19
  160. package/src/plugins/otp.ts +36 -34
  161. package/src/plugins/taqnyat.live.test.ts +3 -3
  162. package/src/runs/collect.ts +3 -0
  163. package/src/runs/export-otlp.ts +64 -0
  164. package/src/runs/index.ts +16 -0
  165. package/src/runs/parquet.ts +9 -0
  166. package/src/runs/types.ts +5 -0
  167. package/src/runs/window.test.ts +68 -0
  168. package/src/runs/window.ts +148 -0
  169. package/src/runtime/boot-warn.test.ts +45 -0
  170. package/src/runtime/boot-warn.ts +17 -0
  171. package/src/runtime/dev-request-log.ts +5 -5
  172. package/src/term.test.ts +95 -10
  173. package/src/term.ts +369 -14
  174. package/src/console/ui/dist/assets/panel-overview-DONDzBd2.js +0 -1
  175. package/src/console/ui/dist/assets/panel-runs-D5zf-D9c.js +0 -1
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Boot honesty suppress flag for the `oke dev` Backend child.
3
+ */
4
+
5
+ import { afterEach, describe, expect, test } from "bun:test";
6
+ import { emitBootWarn } from "./boot-warn.ts";
7
+
8
+ describe("emitBootWarn", () => {
9
+ const prev = process.env["OKE_SUPPRESS_BOOT_WARN"];
10
+
11
+ afterEach(() => {
12
+ if (prev === undefined) delete process.env["OKE_SUPPRESS_BOOT_WARN"];
13
+ else process.env["OKE_SUPPRESS_BOOT_WARN"] = prev;
14
+ });
15
+
16
+ test("forwards to console.warn by default", () => {
17
+ delete process.env["OKE_SUPPRESS_BOOT_WARN"];
18
+ const lines: string[] = [];
19
+ const original = console.warn;
20
+ console.warn = (...args: unknown[]) => {
21
+ lines.push(args.map(String).join(" "));
22
+ };
23
+ try {
24
+ emitBootWarn("oke boot: test notice");
25
+ expect(lines).toEqual(["oke boot: test notice"]);
26
+ } finally {
27
+ console.warn = original;
28
+ }
29
+ });
30
+
31
+ test("no-ops when OKE_SUPPRESS_BOOT_WARN=1", () => {
32
+ process.env["OKE_SUPPRESS_BOOT_WARN"] = "1";
33
+ const lines: string[] = [];
34
+ const original = console.warn;
35
+ console.warn = (...args: unknown[]) => {
36
+ lines.push(args.map(String).join(" "));
37
+ };
38
+ try {
39
+ emitBootWarn("oke boot: hidden");
40
+ expect(lines).toEqual([]);
41
+ } finally {
42
+ console.warn = original;
43
+ }
44
+ });
45
+ });
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Boot honesty lines (`oke boot: …`) — once per process, suppressible in
3
+ * the `oke dev` Backend child so the parent Console owns the notice.
4
+ */
5
+
6
+ /**
7
+ * Emit a boot warning unless suppressed for this process.
8
+ *
9
+ * Set `OKE_SUPPRESS_BOOT_WARN=1` on the Backend child during `oke dev` so
10
+ * Signal / Channel / files process-local notices print once (parent only).
11
+ *
12
+ * @param message - Full warning text (usually prefixed `oke boot:`)
13
+ */
14
+ export function emitBootWarn(message: string): void {
15
+ if (process.env["OKE_SUPPRESS_BOOT_WARN"] === "1") return;
16
+ console.warn(message);
17
+ }
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Dev-only request lines for `oke dev` (App / Console / MCP).
2
+ * Dev-only request lines for `oke dev` (Backend / Console / MCP).
3
3
  *
4
4
  * Gated by `OKE_DEV_REQUEST_LOG=1`. Surfaces share one TTY; label + color
5
5
  * keep streams readable without a multiplexer.
@@ -18,22 +18,22 @@ export function shouldLogDevRequests(): boolean {
18
18
  }
19
19
 
20
20
  /**
21
- * Active surface for this async context, or `OKE_DEV_SURFACE`, or `App`.
21
+ * Active surface for this async context, or `OKE_DEV_SURFACE`, or `Backend`.
22
22
  */
23
23
  export function currentDevSurface(): DevLogSurface {
24
24
  const fromAls = surfaceAls.getStore();
25
25
  if (fromAls) return fromAls;
26
26
  const fromEnv = process.env.OKE_DEV_SURFACE;
27
- if (fromEnv === "App" || fromEnv === "Console" || fromEnv === "MCP") {
27
+ if (fromEnv === "Backend" || fromEnv === "Console" || fromEnv === "MCP") {
28
28
  return fromEnv;
29
29
  }
30
- return "App";
30
+ return "Backend";
31
31
  }
32
32
 
33
33
  /**
34
34
  * Run a handler tagged with a surface (Console wrap around `app.fetch`).
35
35
  *
36
- * @param surface - App · Console · MCP
36
+ * @param surface - Backend · Console · MCP
37
37
  * @param fn - Async work
38
38
  */
39
39
  export function runWithDevSurface<T>(
package/src/term.test.ts CHANGED
@@ -5,7 +5,9 @@
5
5
  import { describe, expect, test } from "bun:test";
6
6
  import {
7
7
  formatAppReadyLine,
8
+ formatBootWarn,
8
9
  formatClaimNote,
10
+ formatCliChrome,
9
11
  formatDevBanner,
10
12
  formatDevHero,
11
13
  formatDevLogSeparator,
@@ -13,6 +15,11 @@ import {
13
15
  formatServiceLine,
14
16
  formatRequestLine,
15
17
  formatStackSummary,
18
+ countTermLines,
19
+ createAnchoredBoard,
20
+ createBootProgress,
21
+ createRewritableBlock,
22
+ formatStatusDot,
16
23
  formatStatusLine,
17
24
  termStyle,
18
25
  } from "./term.ts";
@@ -38,9 +45,10 @@ describe("term", () => {
38
45
  runtimeEnv: "local",
39
46
  system: "darwin 25.4.0 · bun 1.3.14",
40
47
  elements: [
41
- { element: "flow", detail: "" },
42
- { element: "store", detail: "sql postgres · kv redis" },
43
- { element: "signal", detail: "memory" },
48
+ { element: "flow", detail: "", status: "ready" },
49
+ { element: "store", detail: "sql postgres · kv redis", status: "ready" },
50
+ { element: "signal", detail: "memory", status: "ready" },
51
+ { element: "ai", detail: "openai-compatible · smollm2", status: "pending" },
44
52
  ],
45
53
  });
46
54
  expect(out).toContain("oke dev v0.2.4");
@@ -53,11 +61,65 @@ describe("term", () => {
53
61
  expect(out).toContain("elements");
54
62
  expect(out).toContain("store");
55
63
  expect(out).toContain("postgres");
64
+ expect(out).toContain("● flow");
65
+ expect(out).toContain("● ai");
56
66
  expect(out).not.toContain("on(Trigger)");
57
67
  expect(out).not.toContain("O·K·E");
58
68
  expect(out).not.toMatch(/\u001b\[/);
59
69
  });
60
70
 
71
+ test("formatStatusDot colors by status", () => {
72
+ const s = termStyle(true);
73
+ expect(formatStatusDot("ready", true)).toBe(`${s.green}●${s.reset}`);
74
+ expect(formatStatusDot("pending", true)).toBe(`${s.yellow}●${s.reset}`);
75
+ expect(formatStatusDot("error", true)).toBe(`${s.red}●${s.reset}`);
76
+ expect(formatStatusDot("idle", true)).toBe(`${s.dim}●${s.reset}`);
77
+ expect(formatStatusDot("ready", false)).toBe("●");
78
+ });
79
+
80
+ test("createRewritableBlock appends when disabled", () => {
81
+ let out = "";
82
+ const block = createRewritableBlock((t) => {
83
+ out += t;
84
+ }, false);
85
+ block.paint("a\nb\n");
86
+ block.paint("c\n");
87
+ expect(out).toBe("a\nb\nc\n");
88
+ expect(countTermLines("a\nb\n")).toBe(2);
89
+ });
90
+
91
+ test("createBootProgress replaces keyed rows then clears", () => {
92
+ let out = "";
93
+ const progress = createBootProgress((t) => {
94
+ out += t;
95
+ }, false);
96
+ progress.set("compose", "compose…\n");
97
+ progress.set("compose", "compose ok\n");
98
+ progress.set("vault", "vault ok\n");
99
+ // Non-TTY appends each set (including replacements).
100
+ expect(out).toContain("compose ok\n");
101
+ expect(out).toContain("vault ok\n");
102
+ progress.clear();
103
+ // clear is a no-op on the stream when rewrite is disabled
104
+ expect(out).toContain("vault ok\n");
105
+ });
106
+
107
+ test("createAnchoredBoard wrapWrite tracks below output", () => {
108
+ let out = "";
109
+ const board = createAnchoredBoard((t) => {
110
+ out += t;
111
+ }, false);
112
+ board.paint("board\n");
113
+ const w = board.wrapWrite((t) => {
114
+ out += t;
115
+ });
116
+ w("below\n");
117
+ board.paint("board2\n"); // non-TTY: no rewrite append
118
+ expect(out).toContain("board\n");
119
+ expect(out).toContain("below\n");
120
+ board.stop();
121
+ });
122
+
61
123
  test("formatServiceLine / formatAppReadyLine include URL", () => {
62
124
  expect(formatServiceLine("Console", "http://127.0.0.1:6533", false)).toContain(
63
125
  "http://127.0.0.1:6533",
@@ -65,7 +127,7 @@ describe("term", () => {
65
127
  expect(formatAppReadyLine("http://127.0.0.1:6530", false)).toContain("http://127.0.0.1:6530");
66
128
  });
67
129
 
68
- test("formatDevHero keeps App Console MCP URLs", () => {
130
+ test("formatDevHero keeps Backend Console MCP URLs", () => {
69
131
  const out = formatDevHero({
70
132
  appUrl: "http://127.0.0.1:6530",
71
133
  consoleUrl: "http://127.0.0.1:6533",
@@ -73,12 +135,12 @@ describe("term", () => {
73
135
  profile: "local",
74
136
  runtimeEnv: "local",
75
137
  system: "darwin 25.4.0 · bun 1.3.14",
76
- elements: [{ element: "flow", detail: "" }],
138
+ elements: [{ element: "flow", detail: "", status: "ready" }],
77
139
  color: false,
78
140
  });
79
141
  expect(out).toContain("oke dev");
80
142
  expect(out).toContain("██");
81
- expect(out).toContain("App");
143
+ expect(out).toContain("Backend");
82
144
  expect(out).toContain("Console");
83
145
  expect(out).toContain("MCP");
84
146
  expect(out).toContain("http://127.0.0.1:6530");
@@ -106,10 +168,27 @@ describe("term", () => {
106
168
  expect(formatStatusLine("stack up (sql)", false)).toContain("stack up");
107
169
  });
108
170
 
171
+ test("formatBootWarn wraps under Notice chrome", () => {
172
+ const out = formatBootWarn(
173
+ "oke boot: Channel suppression defaults to process-local memory for multi-instance",
174
+ false,
175
+ );
176
+ expect(out).toContain("Notice");
177
+ expect(out).toContain("process-local");
178
+ expect(out).not.toContain("oke boot:");
179
+ });
180
+
181
+ test("formatCliChrome routes boot and status lines", () => {
182
+ const out = formatCliChrome("oke db seed: ok\noke boot: hello world\n", false);
183
+ expect(out).toContain("oke db seed: ok");
184
+ expect(out).toContain("Notice");
185
+ expect(out).toContain("hello world");
186
+ });
187
+
109
188
  test("formatRequestLine shows date, time, surface, flow, ms, status", () => {
110
189
  const at = new Date(2026, 6, 26, 3, 11, 42);
111
190
  const out = formatRequestLine({
112
- surface: "App",
191
+ surface: "Backend",
113
192
  method: "GET",
114
193
  path: "/health",
115
194
  flow: "main.health",
@@ -120,7 +199,7 @@ describe("term", () => {
120
199
  });
121
200
  expect(out).toContain("2026-07-26");
122
201
  expect(out).toContain("03:11:42");
123
- expect(out).toContain("App");
202
+ expect(out).toContain("Backend");
124
203
  expect(out).toContain("200");
125
204
  expect(out).not.toMatch(/\u001b\[/);
126
205
  });
@@ -144,14 +223,20 @@ describe("term", () => {
144
223
  const out = formatStackSummary({
145
224
  project: "oke-dev-a3f791",
146
225
  services: [
147
- { label: "postgres", hostPort: 15975 },
148
- { label: "redis", hostPort: 16975 },
226
+ { label: "postgres", hostPort: 15975, status: "ready" },
227
+ { label: "redis", hostPort: 16975, status: "ready" },
228
+ { label: "ai", hostPort: 23975, detail: "gemma4:e4b-q4_K_M", status: "pending" },
149
229
  ],
150
230
  appDrivers: ["postgres", "redis"],
151
231
  color: false,
152
232
  });
153
233
  expect(out).toContain("Docker");
154
234
  expect(out).toContain(":15975");
235
+ expect(out).toContain("gemma4:e4b-q4_K_M");
236
+ expect(out).toContain("● postgres");
237
+ expect(out).toContain("● ai");
238
+ // Blank │ row separates the Docker header from whatever sits above.
239
+ expect(out).toMatch(/│\n◇ {2}Docker/);
155
240
  expect(out).not.toMatch(/\u001b\[/);
156
241
  });
157
242
  });