okengine 0.9.1 → 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 (166) 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 +97 -9
  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/providers/azure-redis.mdx +85 -0
  14. package/site/content/docs/providers/cockroachdb.mdx +86 -0
  15. package/site/content/docs/providers/digitalocean-caching.mdx +88 -0
  16. package/site/content/docs/providers/dragonfly-cloud.mdx +82 -0
  17. package/site/content/docs/providers/elasticache.mdx +92 -0
  18. package/site/content/docs/providers/index.mdx +101 -0
  19. package/site/content/docs/providers/memorystore.mdx +89 -0
  20. package/site/content/docs/providers/meta.json +20 -0
  21. package/site/content/docs/providers/neon.mdx +115 -0
  22. package/site/content/docs/providers/redis-cloud.mdx +93 -0
  23. package/site/content/docs/providers/supabase.mdx +117 -0
  24. package/site/content/docs/providers/upstash.mdx +91 -0
  25. package/site/content/docs/providers/yugabytedb.mdx +95 -0
  26. package/site/content/docs/recipes/caddy.mdx +128 -0
  27. package/site/content/docs/recipes/cockroachdb.mdx +127 -0
  28. package/site/content/docs/recipes/dragonfly.mdx +125 -0
  29. package/site/content/docs/recipes/index.mdx +146 -0
  30. package/site/content/docs/recipes/llama-cpp.mdx +153 -0
  31. package/site/content/docs/recipes/mailpit.mdx +136 -0
  32. package/site/content/docs/recipes/meilisearch.mdx +139 -0
  33. package/site/content/docs/recipes/meta.json +31 -0
  34. package/site/content/docs/recipes/ollama.mdx +142 -0
  35. package/site/content/docs/recipes/openbao.mdx +141 -0
  36. package/site/content/docs/recipes/pgdog.mdx +137 -0
  37. package/site/content/docs/recipes/postgres.mdx +136 -0
  38. package/site/content/docs/recipes/redis.mdx +130 -0
  39. package/site/content/docs/recipes/rustfs.mdx +148 -0
  40. package/site/content/docs/recipes/sglang.mdx +105 -0
  41. package/site/content/docs/recipes/supabase-docker.mdx +145 -0
  42. package/site/content/docs/recipes/timescale.mdx +129 -0
  43. package/site/content/docs/recipes/traefik.mdx +136 -0
  44. package/site/content/docs/recipes/valkey.mdx +121 -0
  45. package/site/content/docs/recipes/vllm.mdx +106 -0
  46. package/site/content/docs/recipes/yugabytedb.mdx +135 -0
  47. package/site/content/docs/reference/cli.md +42 -6
  48. package/site/content/docs/reference/configuration.mdx +5 -3
  49. package/site/content/docs/reference/environment-variables.mdx +12 -12
  50. package/site/content/docs/reference/fx.mdx +38 -4
  51. package/src/cli/ai-setup/ai-setup.test.ts +32 -12
  52. package/src/cli/ai-setup/apply.ts +65 -23
  53. package/src/cli/ai-setup/catalog.ts +1316 -35
  54. package/src/cli/ai-setup/detect-ollama.ts +47 -0
  55. package/src/cli/ai-setup/index.ts +44 -7
  56. package/src/cli/ai-setup/prompts.ts +430 -486
  57. package/src/cli/ai-setup/recommend.test.ts +150 -50
  58. package/src/cli/ai-setup/recommend.ts +118 -101
  59. package/src/cli/ask-seed.test.ts +68 -0
  60. package/src/cli/ask-seed.ts +79 -0
  61. package/src/cli/db-seed-redact.test.ts +25 -0
  62. package/src/cli/db-seed.ts +36 -7
  63. package/src/cli/db.test.ts +1 -1
  64. package/src/cli/db.ts +2 -2
  65. package/src/cli/dev-controls.test.ts +107 -0
  66. package/src/cli/dev-controls.ts +354 -0
  67. package/src/cli/dev-schema-sync.ts +12 -4
  68. package/src/cli/dev.test.ts +50 -30
  69. package/src/cli/dev.ts +607 -66
  70. package/src/cli/drizzle-env.test.ts +40 -6
  71. package/src/cli/drizzle-env.ts +22 -1
  72. package/src/cli/ensure-drizzle-config.ts +6 -4
  73. package/src/cli/hero-meta.test.ts +13 -1
  74. package/src/cli/hero-meta.ts +28 -6
  75. package/src/cli/index.ts +5 -0
  76. package/src/cli/registry.ts +24 -0
  77. package/src/cli/replay.test.ts +105 -0
  78. package/src/cli/replay.ts +206 -0
  79. package/src/compiler/extract.ts +3 -3
  80. package/src/config/index.ts +3 -3
  81. package/src/console/server/claim.ts +3 -1
  82. package/src/console/ui/dist/assets/{index-ClX0ZCe5.js → index-D-9KFce5.js} +2 -2
  83. package/src/console/ui/dist/assets/panel-overview-CW0CQEc2.js +1 -0
  84. package/src/console/ui/dist/assets/panel-runs-BxuyDI3x.js +1 -0
  85. package/src/console/ui/dist/assets/{panel-signals-Dsxdu_AR.js → panel-signals-BXofbj7v.js} +1 -1
  86. package/src/console/ui/dist/assets/{panel-store-hy7O8HOs.js → panel-store-B8mH-arU.js} +1 -1
  87. package/src/console/ui/dist/assets/{panel-traces-CBiAe5go.js → panel-traces-DSA-ZWnf.js} +1 -1
  88. package/src/console/ui/dist/index.html +1 -1
  89. package/src/console/ui/overview/slo.ts +31 -3
  90. package/src/console/ui/overview/types.ts +6 -0
  91. package/src/console/ui/runs/errors.test.ts +53 -0
  92. package/src/console/ui/runs/errors.ts +88 -0
  93. package/src/console/ui/runs/index.ts +8 -0
  94. package/src/console/ui/runs/search.ts +16 -0
  95. package/src/console/ui/shell/panels/runs/RunsPanel.tsx +72 -1
  96. package/src/docker/ai-model-status.test.ts +101 -0
  97. package/src/docker/ai-model-status.ts +276 -0
  98. package/src/docker/compose-health.test.ts +115 -0
  99. package/src/docker/compose-health.ts +234 -0
  100. package/src/docker/compose.ts +24 -8
  101. package/src/docker/derive.ts +35 -9
  102. package/src/docker/docker.test.ts +304 -12
  103. package/src/docker/helpers.ts +56 -0
  104. package/src/docker/index.ts +52 -0
  105. package/src/docker/ollama-pull.ts +232 -0
  106. package/src/docker/recipes/cockroach.ts +24 -0
  107. package/src/docker/recipes/index.ts +32 -0
  108. package/src/docker/recipes/llama-cpp.ts +273 -0
  109. package/src/docker/recipes/ollama.ts +19 -23
  110. package/src/docker/recipes/pgdog.ts +4 -1
  111. package/src/docker/recipes/postgres.ts +5 -18
  112. package/src/docker/recipes/sglang.ts +55 -0
  113. package/src/docker/recipes/supabase.ts +21 -0
  114. package/src/docker/recipes/timescale.ts +18 -0
  115. package/src/docker/recipes/vllm.ts +44 -0
  116. package/src/docker/recipes/yugabyte.ts +23 -0
  117. package/src/docker/stack-id.test.ts +22 -0
  118. package/src/docker/stack-id.ts +38 -4
  119. package/src/docker/types.ts +15 -0
  120. package/src/drivers/ai-ollama.integration.test.ts +7 -4
  121. package/src/drivers/signal-engine.ts +10 -0
  122. package/src/drivers/signal-postgres.ts +24 -2
  123. package/src/drivers/signal-types.ts +10 -0
  124. package/src/elements/channel/fallback.test.ts +91 -0
  125. package/src/elements/channel/hard-bounce.test.ts +82 -0
  126. package/src/elements/channel/injection.test.ts +153 -0
  127. package/src/elements/channel/locale-ar.test.ts +102 -0
  128. package/src/elements/channel/otp-delivery.ts +5 -2
  129. package/src/elements/channel/receipts-ledger.test.ts +100 -0
  130. package/src/elements/channel/runtime.ts +24 -1
  131. package/src/elements/channel/test-helpers.ts +60 -0
  132. package/src/elements/channel/whatsapp-compliance.test.ts +124 -0
  133. package/src/elements/store/cache.ts +1 -1
  134. package/src/elements/store/emit-drizzle.ts +43 -9
  135. package/src/elements/store/runtime.ts +1 -1
  136. package/src/elements/store/schema-decl.test.ts +2 -0
  137. package/src/elements/store/schema-decl.ts +15 -0
  138. package/src/elements/store/seed.ts +1 -1
  139. package/src/index.ts +1 -0
  140. package/src/kernel/app.ts +117 -10
  141. package/src/kernel/boot-bind/signal.ts +6 -2
  142. package/src/kernel/boot-bind/store.ts +2 -1
  143. package/src/kernel/boot.test.ts +6 -5
  144. package/src/kernel/boot.ts +8 -3
  145. package/src/kernel/compensate.test.ts +131 -0
  146. package/src/kernel/correlation.test.ts +108 -0
  147. package/src/kernel/effect-timing.test.ts +82 -0
  148. package/src/kernel/flow.ts +38 -0
  149. package/src/kernel/fx-runs.test.ts +49 -0
  150. package/src/kernel/fx.test.ts +14 -0
  151. package/src/kernel/fx.ts +111 -1
  152. package/src/manifest/types.ts +8 -2
  153. package/src/runs/collect.ts +3 -0
  154. package/src/runs/export-otlp.ts +64 -0
  155. package/src/runs/index.ts +16 -0
  156. package/src/runs/parquet.ts +9 -0
  157. package/src/runs/types.ts +5 -0
  158. package/src/runs/window.test.ts +68 -0
  159. package/src/runs/window.ts +148 -0
  160. package/src/runtime/boot-warn.test.ts +45 -0
  161. package/src/runtime/boot-warn.ts +17 -0
  162. package/src/runtime/dev-request-log.ts +5 -5
  163. package/src/term.test.ts +95 -10
  164. package/src/term.ts +369 -14
  165. package/src/console/ui/dist/assets/panel-overview-DONDzBd2.js +0 -1
  166. package/src/console/ui/dist/assets/panel-runs-D5zf-D9c.js +0 -1
@@ -0,0 +1,129 @@
1
+ ---
2
+ title: "Timescale"
3
+ description: "Self-hosted TimescaleDB — same POSTGRES_* contract as Postgres, hypertables included, driver stays postgres."
4
+ icon: "Database"
5
+ source: "docs/spec/unified-theory.md"
6
+ ---
7
+
8
+ TimescaleDB is Postgres plus hypertables and time-series tooling. Pin a
9
+ `timescale/timescaledb` image as `store.sql` and `oke docker` uses the Timescale
10
+ recipe — same `POSTGRES_*` contract as plain Postgres. Driver id stays `postgres`.
11
+
12
+ <Callout title="The one rule">
13
+ The driver id stays `postgres` — vendor choice lives in `images["store.sql"]`. Create the
14
+ `timescaledb` extension in SQL when you need hypertables; the image ships it.
15
+ </Callout>
16
+
17
+ ## Quick start
18
+
19
+ <Steps>
20
+
21
+ <Step>
22
+ ### Pin the image
23
+
24
+ ```typescript title="oke.config.ts"
25
+ images: {
26
+ "store.sql": "timescale/timescaledb:latest-pg17", // pin a real tag
27
+ },
28
+ ```
29
+
30
+ </Step>
31
+
32
+ <Step>
33
+ ### Bring the stack up
34
+
35
+ ```bash
36
+ oke dev --docker
37
+ ```
38
+
39
+ Same credential contract as [Postgres](/docs/recipes/postgres):
40
+ `POSTGRES_USER` / `POSTGRES_PASSWORD` / `POSTGRES_DB` from `OKE_STORE_SQL_*`.
41
+
42
+ </Step>
43
+
44
+ <Step>
45
+ ### Enable the extension when you need it
46
+
47
+ ```sql
48
+ CREATE EXTENSION IF NOT EXISTS timescaledb;
49
+ ```
50
+
51
+ Then create hypertables with Timescale's usual DDL — Flows still talk through
52
+ `fx.store` / Drizzle like any other Postgres.
53
+
54
+ </Step>
55
+
56
+ </Steps>
57
+
58
+ ## Required env
59
+
60
+ | Variable | Who sets it | Meaning |
61
+ | ------------------------ | ---------------------- | --------------------------------- |
62
+ | `OKE_STORE_SQL_USER` | `oke docker` → compose | → `POSTGRES_USER` |
63
+ | `OKE_STORE_SQL_PASSWORD` | `oke docker` → compose | → `POSTGRES_PASSWORD` |
64
+ | `OKE_STORE_SQL_DB` | `oke docker` → compose | → `POSTGRES_DB` |
65
+ | `DATABASE_URL` | stack env for the app | `postgres://…:5432/…` |
66
+ | `PGDATA` | stack default | `/var/lib/postgresql/data/pgdata` |
67
+
68
+ ## Data and backup
69
+
70
+ | Path | What lives there |
71
+ | ----------------------------------------- | ------------------------------------------ |
72
+ | `$PGDATA` | Cluster data, including Timescale catalogs |
73
+ | Image `VOLUME` `/var/lib/postgresql/data` | Persistence mount |
74
+
75
+ Same backup story as plain Postgres: `pg_dump` / volume backup of
76
+ `/var/lib/postgresql/data`. Losing that volume loses tables and extension state.
77
+
78
+ ## Production note
79
+
80
+ Pin a concrete tag (image + Postgres major). For multi-replica apps, keep one
81
+ shared SQL backend — see
82
+ [Postgres · Production note](/docs/recipes/postgres#production-note).
83
+
84
+ Managed time-series hosts still use `DATABASE_URL` and
85
+ `drivers.store.sql: "postgres"`.
86
+
87
+ ## What the recipe configures
88
+
89
+ | Field | Value |
90
+ | -------------- | --------------------------------------- |
91
+ | Match | `timescale` ahead of generic `postgres` |
92
+ | Container port | `5432` |
93
+ | Healthcheck | `pg_isready -U $POSTGRES_USER` |
94
+ | Connection URL | `postgres://user:pass@host:5432/db` |
95
+
96
+ ## Troubleshooting
97
+
98
+ <Accordions>
99
+ <Accordion title='extension "timescaledb" is not available'>
100
+
101
+ You pinned a plain `postgres:` image. Confirm the reference contains `timescale`,
102
+ re-derive, then `CREATE EXTENSION timescaledb`.
103
+
104
+ </Accordion>
105
+ <Accordion title="oke boot: postgres driver needs DATABASE_URL">
106
+
107
+ Same as Postgres — re-run `oke dev --docker` or export `DATABASE_URL` for a remote
108
+ host.
109
+
110
+ </Accordion>
111
+ </Accordions>
112
+
113
+ ## Learn more
114
+
115
+ - [Postgres](/docs/recipes/postgres) — generic recipe this specialises
116
+ - [Store · SQL](/docs/elements/store#sql) — schema workflows
117
+ - [Environment variables](/docs/reference/environment-variables) — `DATABASE_URL`
118
+
119
+ ## Next
120
+
121
+ <Cards>
122
+ <Card title="Postgres" description="Plain Postgres recipe." href="/docs/recipes/postgres" />
123
+ <Card
124
+ title="Supabase"
125
+ description="Postgres + extension bundle."
126
+ href="/docs/recipes/supabase-docker"
127
+ />
128
+ <Card title="PgDog" description="Transaction pooling in front." href="/docs/recipes/pgdog" />
129
+ </Cards>
@@ -0,0 +1,136 @@
1
+ ---
2
+ title: "Traefik"
3
+ description: "Docker-label auto-discovery proxy — OKE_PROXY_HOST, OKE_PROXY_ACME_EMAIL, socket-proxy, ACME volume."
4
+ icon: "Lock"
5
+ source: "docs/spec/unified-theory.md"
6
+ ---
7
+
8
+ Traefik discovers `app` replicas from Docker labels instead of a static upstream, so
9
+ `docker compose up --scale app=N` load-balances without reconfiguring the proxy.
10
+
11
+ <Callout title="The one rule">
12
+ Traefik never mounts the raw Docker socket. A filtered `tecnativa/docker-socket-proxy` companion
13
+ exposes only containers / events / ping / version / networks on the internal compose network.
14
+ </Callout>
15
+
16
+ ## Quick start
17
+
18
+ <Steps>
19
+
20
+ <Step>
21
+ ### Pin the proxy
22
+
23
+ ```typescript title="oke.config.ts"
24
+ images: {
25
+ proxy: "traefik:v3.3",
26
+ },
27
+ ```
28
+
29
+ </Step>
30
+
31
+ <Step>
32
+ ### Hostname + ACME email
33
+
34
+ ```bash title="docker/.env.docker"
35
+ OKE_PROXY_HOST=app.example.com
36
+ OKE_PROXY_ACME_EMAIL=admin@example.com
37
+ ```
38
+
39
+ `OKE_PROXY_ACME_EMAIL` defaults to `admin@example.com` if unset — set a real mailbox
40
+ before production ACME.
41
+
42
+ </Step>
43
+
44
+ <Step>
45
+ ### Scale the app
46
+
47
+ ```bash
48
+ docker compose … up -d --scale app=3
49
+ ```
50
+
51
+ App labels: `traefik.http.routers.app.rule=Host(...)`, TLS cert resolver `letsencrypt`,
52
+ load-balancer port `6530`.
53
+
54
+ </Step>
55
+
56
+ </Steps>
57
+
58
+ ## Required env
59
+
60
+ | Variable | Required? | Meaning |
61
+ | ----------------------- | -------------------- | ---------------------------------------------- |
62
+ | `OKE_PROXY_HOST` | **Yes** (production) | Host rule + ACME identity; default `localhost` |
63
+ | `OKE_PROXY_ACME_EMAIL` | **Yes** (production) | Let's Encrypt account email |
64
+ | `allowedHosts` (config) | Production | Must include the public hostname |
65
+
66
+ ## Data and backup
67
+
68
+ | Volume | Path | What it stores |
69
+ | ------------------- | ------------------------- | ------------------------------------------------- |
70
+ | `proxy-letsencrypt` | `/letsencrypt` | `acme.json` — certificates + ACME account |
71
+ | Socket proxy only | `/var/run/docker.sock:ro` | **Only** the `socket-proxy` companion mounts this |
72
+
73
+ **Backup means:** preserve the `proxy-letsencrypt` volume (especially `acme.json`). Losing
74
+ it forces re-issuance and can hit Let's Encrypt rate limits. The socket-proxy has no
75
+ durable state.
76
+
77
+ ## Production note
78
+
79
+ Security posture is intentional: Traefik talks to `tcp://socket-proxy:2375` with a
80
+ filtered API (`CONTAINERS`, `EVENTS`, `PING`, `VERSION`, `NETWORKS` only). Never mount
81
+ raw `docker.sock` on Traefik — see [Reverse proxy](/docs/deployment/reverse-proxy).
82
+
83
+ HTTP entrypoint redirects to `websecure`. For a single instance with no scale plans,
84
+ [Caddy](/docs/recipes/caddy) is simpler (no labels, no companion).
85
+
86
+ ## What the recipe configures
87
+
88
+ | Field | Value |
89
+ | ----------- | -------------------------------------------------- |
90
+ | Ports | `80` + `443` |
91
+ | Providers | Docker via socket-proxy, `exposedbydefault=false` |
92
+ | Companion | `tecnativa/docker-socket-proxy:v0.5.0` |
93
+ | Healthcheck | `traefik healthcheck --ping`, every 10s, 5 retries |
94
+
95
+ ## Troubleshooting
96
+
97
+ <Accordions>
98
+ <Accordion title="404 / no backend — Traefik cannot see app">
99
+
100
+ Usually `socket-proxy` is down, or `app` lacks Traefik labels. Confirm
101
+ `depends_on: socket-proxy` and that `compose.proxy.yml` merged the app labels.
102
+
103
+ Logs showing Docker provider connection errors point at the socket-proxy, not Traefik
104
+ config syntax.
105
+
106
+ </Accordion>
107
+ <Accordion title="ACME email rejected / rate limited">
108
+
109
+ Replace the default `admin@example.com` with a real `OKE_PROXY_ACME_EMAIL`. If you wiped
110
+ `proxy-letsencrypt`, you may be rate-limited — restore `acme.json` from backup instead of
111
+ re-issuing repeatedly.
112
+
113
+ </Accordion>
114
+ </Accordions>
115
+
116
+ ## Learn more
117
+
118
+ - [Reverse proxy](/docs/deployment/reverse-proxy) — Docker-socket-proxy security rationale
119
+ - [Docker · Reverse proxy](/docs/deployment/docker#reverse-proxy) — compose layer order
120
+ - [Security](/docs/reference/security) — `allowedHosts`
121
+
122
+ ## Next
123
+
124
+ <Cards>
125
+ <Card title="Caddy" description="Single-instance alternative." href="/docs/recipes/caddy" />
126
+ <Card
127
+ title="PgDog"
128
+ description="Pool Postgres behind the same stack."
129
+ href="/docs/recipes/pgdog"
130
+ />
131
+ <Card
132
+ title="Redis Cloud"
133
+ description="A managed backing store."
134
+ href="/docs/providers/redis-cloud"
135
+ />
136
+ </Cards>
@@ -0,0 +1,121 @@
1
+ ---
2
+ title: "Valkey"
3
+ description: "BSD-licensed Redis-wire fork — same redis driver, OKE_STORE_KV_PASSWORD, valkey-server command."
4
+ icon: "Zap"
5
+ source: "docs/spec/unified-theory.md"
6
+ ---
7
+
8
+ Valkey is the Linux Foundation's BSD-3-Clause fork of Redis, forked after Redis's 2024
9
+ license change. Same wire protocol — pin the image and nothing in Flow code moves.
10
+
11
+ <Callout title="The one rule">
12
+ Driver id stays `redis`. Valkey is an image choice, not a driver. `REDIS_URL` and every KV call
13
+ through `fx.store` work exactly as they do against Redis.
14
+ </Callout>
15
+
16
+ ## Quick start
17
+
18
+ <Steps>
19
+
20
+ <Step>
21
+ ### Pin the image
22
+
23
+ ```typescript title="oke.config.ts"
24
+ images: {
25
+ "store.kv": "valkey/valkey:8-alpine",
26
+ },
27
+ ```
28
+
29
+ </Step>
30
+
31
+ <Step>
32
+ ### Same password contract as Redis
33
+
34
+ ```bash
35
+ OKE_STORE_KV_PASSWORD=…
36
+ REDIS_URL=redis://:…@127.0.0.1:6379
37
+ ```
38
+
39
+ Command becomes `valkey-server --requirepass "$OKE_STORE_KV_PASSWORD" …` — healthcheck
40
+ uses `valkey-cli`.
41
+
42
+ </Step>
43
+
44
+ <Step>
45
+ ### Optional memory caps
46
+
47
+ Same knobs as Redis: `OKE_STORE_KV_MAXMEMORY`, `OKE_STORE_KV_MAXMEMORY_POLICY`.
48
+
49
+ </Step>
50
+
51
+ </Steps>
52
+
53
+ ## Required env
54
+
55
+ | Variable | Required? | Meaning |
56
+ | ------------------------------- | ------------- | --------------------------------------------------- |
57
+ | `OKE_STORE_KV_PASSWORD` | **Yes** | `--requirepass` for `valkey-server` |
58
+ | `REDIS_URL` | **Yes** (app) | Still `redis://` scheme — protocol name, not vendor |
59
+ | `OKE_STORE_KV_MAXMEMORY` | Optional | Memory cap |
60
+ | `OKE_STORE_KV_MAXMEMORY_POLICY` | Optional | Eviction policy |
61
+
62
+ ## Data and backup
63
+
64
+ No named volume in the recipe — same ephemeral default as [Redis](/docs/recipes/redis).
65
+ **Backup means:** do not assume durability until you add a volume + persistence config;
66
+ treat the default as a shared cache rebuilt from durable stores.
67
+
68
+ ## Production note
69
+
70
+ Choose Valkey when RSAL/SSPL managed-service terms on Redis ≥8 matter to your legal
71
+ posture — BSD-3-Clause carries no such restriction. Feature parity with Redis 7/8 stays
72
+ close since the fork tracks upstream.
73
+
74
+ DigitalOcean's managed product moved onto Valkey after Aiven stepped back from Redis —
75
+ see [DigitalOcean Managed Caching](/docs/providers/digitalocean-caching).
76
+
77
+ ## What the recipe configures
78
+
79
+ | Field | Value |
80
+ | -------------- | ------------------------------------------------------------------ |
81
+ | Container port | `6379` |
82
+ | Command | `valkey-server --requirepass … --maxmemory … --maxmemory-policy …` |
83
+ | Healthcheck | `valkey-cli -a <password> ping`, every 5s, 10 retries |
84
+ | Connection URL | `redis://:pass@host:6379` |
85
+ | License | BSD-3-Clause |
86
+
87
+ ## Troubleshooting
88
+
89
+ <Accordions>
90
+ <Accordion title="oke boot: redis driver needs REDIS_URL">
91
+
92
+ Same loud failure as Redis — the driver id is still `redis`. Export `REDIS_URL` or let
93
+ `oke dev --docker` write it.
94
+
95
+ </Accordion>
96
+ <Accordion title="Healthcheck uses redis-cli and fails">
97
+
98
+ You still have the Redis recipe matched (image ref contains `redis`). Valkey images must
99
+ match `/valkey/i` so the healthcheck binary is `valkey-cli`. Pin `valkey/valkey:…`
100
+ explicitly.
101
+
102
+ </Accordion>
103
+ </Accordions>
104
+
105
+ ## Learn more
106
+
107
+ - [Store · KV](/docs/elements/store#kv) — full Redis-protocol image license table
108
+ - [Redis](/docs/recipes/redis) · [Dragonfly](/docs/recipes/dragonfly) — the other two peers
109
+ - [DigitalOcean Managed Caching](/docs/providers/digitalocean-caching) — managed Valkey
110
+
111
+ ## Next
112
+
113
+ <Cards>
114
+ <Card
115
+ title="Dragonfly"
116
+ description="Multi-threaded Redis-wire peer."
117
+ href="/docs/recipes/dragonfly"
118
+ />
119
+ <Card title="Redis" description="The mature default." href="/docs/recipes/redis" />
120
+ <Card title="Upstash" description="Managed alternative." href="/docs/providers/upstash" />
121
+ </Cards>
@@ -0,0 +1,106 @@
1
+ ---
2
+ title: "vLLM"
3
+ description: "Production-tier self-hosted inference — OpenAI-compatible GPU serving when you run inference yourself."
4
+ icon: "Cpu"
5
+ source: "docs/spec/unified-theory.md"
6
+ ---
7
+
8
+ vLLM is for **multi-user / production concurrency on real GPU hardware** when
9
+ you choose to self-host inference instead of a managed provider. Driver id stays
10
+ `openai-compatible`. Most apps should prefer Anthropic / OpenAI / … in prod.
11
+
12
+ <Callout title="The one rule">
13
+ Pin an explicit image tag (never `latest`), publish only on loopback, and treat this as “I run
14
+ production inference myself” — not the default create path.
15
+ </Callout>
16
+
17
+ ## Quick start
18
+
19
+ <Steps>
20
+
21
+ <Step>
22
+ ### Pin driver + image
23
+
24
+ ```typescript title="oke.config.ts"
25
+ drivers: {
26
+ ai: { docker: "openai-compatible", prod: "openai-compatible", test: "mock" },
27
+ },
28
+ images: {
29
+ ai: "vllm/vllm-openai:v0.26.0", // never :latest
30
+ },
31
+ ```
32
+
33
+ Or `oke ai setup --provider vllm --yes`.
34
+
35
+ </Step>
36
+
37
+ <Step>
38
+ ### Env + GPU
39
+
40
+ ```bash title="docker/.env.docker"
41
+ OKE_AI_URL=http://127.0.0.1:8000/v1
42
+ OKE_AI_MODEL=Qwen/Qwen3-0.6B
43
+ ```
44
+
45
+ The recipe sets `ipc: host` and an NVIDIA device reservation. Host needs the
46
+ NVIDIA Container Toolkit.
47
+
48
+ </Step>
49
+
50
+ <Step>
51
+ ### Decide deliberately
52
+
53
+ | Path | When |
54
+ | ------------------------------------ | -------------------------------------------- |
55
+ | Managed provider | Default for most production apps |
56
+ | **vLLM** (this recipe) | Self-hosted multi-user GPU serving |
57
+ | [SGLang](/docs/recipes/sglang) | Self-hosted structured / agent GPU workloads |
58
+ | [llama.cpp](/docs/recipes/llama-cpp) | Single-user / dev (default local) |
59
+
60
+ </Step>
61
+
62
+ </Steps>
63
+
64
+ ## Security
65
+
66
+ | Control | Requirement |
67
+ | ------------ | --------------------------------------------- |
68
+ | Host publish | `127.0.0.1:8000:8000` only — never `0.0.0.0` |
69
+ | Image pin | Explicit version tag — never `latest` |
70
+ | Model source | Trusted Hugging Face repos / your own weights |
71
+
72
+ ## What the recipe configures
73
+
74
+ | Field | Value |
75
+ | -------------- | ----------------------------------------------------- |
76
+ | Container port | `8000` |
77
+ | Host publish | `127.0.0.1:8000:8000` |
78
+ | `ipc` | `host` |
79
+ | GPU | `deploy.resources.reservations.devices` (nvidia, all) |
80
+ | Healthcheck | `GET /health`, long start period for model load |
81
+ | Connection URL | `http://host:8000/v1` |
82
+
83
+ ## Troubleshooting
84
+
85
+ <Accordions>
86
+ <Accordion title="GPU not visible / container exits">
87
+
88
+ Install the NVIDIA Container Toolkit on the host. CPU-only hosts should use
89
+ [llama.cpp](/docs/recipes/llama-cpp) or [Ollama](/docs/recipes/ollama) instead.
90
+
91
+ </Accordion>
92
+ </Accordions>
93
+
94
+ ## Learn more
95
+
96
+ - [llama.cpp](/docs/recipes/llama-cpp) — default local AI
97
+ - [SGLang](/docs/recipes/sglang) — structured / agent GPU path
98
+ - [AI](/docs/elements/ai) — drivers and `fx.ask`
99
+
100
+ ## Next
101
+
102
+ <Cards>
103
+ <Card title="SGLang" description="Agent / structured GPU serving." href="/docs/recipes/sglang" />
104
+ <Card title="llama.cpp" description="Default local AI." href="/docs/recipes/llama-cpp" />
105
+ <Card title="AI" description="Prompts and guardrails." href="/docs/elements/ai" />
106
+ </Cards>
@@ -0,0 +1,135 @@
1
+ ---
2
+ title: "YugabyteDB"
3
+ description: "Self-hosted single-node YSQL — YSQL_* env, port 5433, driver stays postgres."
4
+ icon: "Database"
5
+ source: "docs/spec/unified-theory.md"
6
+ ---
7
+
8
+ YugabyteDB's **YSQL** API speaks Postgres wire. Pin `yugabytedb/yugabyte` as
9
+ `store.sql` and `oke docker` derives a single-node `yugabyted` service —
10
+ credentials, healthcheck, and `DATABASE_URL`. Driver id stays `postgres`.
11
+
12
+ <Callout title="The one rule">
13
+ Use the YSQL API only — never treat YCQL as `store.sql`. Vendor choice lives in
14
+ `images["store.sql"]`; host maps `:5432` → container `:5433`.
15
+ </Callout>
16
+
17
+ ## Quick start
18
+
19
+ <Steps>
20
+
21
+ <Step>
22
+ ### Pin the image
23
+
24
+ ```typescript title="oke.config.ts"
25
+ images: {
26
+ "store.sql": "yugabytedb/yugabyte:2025.1.0.0-b100", // pin a real tag
27
+ },
28
+ ```
29
+
30
+ </Step>
31
+
32
+ <Step>
33
+ ### Bring the stack up
34
+
35
+ ```bash
36
+ oke dev --docker
37
+ ```
38
+
39
+ `oke docker` injects `YSQL_USER` / `YSQL_PASSWORD` / `YSQL_DB` from `OKE_STORE_SQL_*`
40
+ (password presence turns authentication on), runs
41
+ `bin/yugabyted start --background=false`, and publishes YSQL on host `:5432`.
42
+
43
+ </Step>
44
+
45
+ <Step>
46
+ ### Connect
47
+
48
+ ```bash
49
+ echo "$DATABASE_URL"
50
+ # postgres://oke:…@127.0.0.1:5432/oke
51
+ ```
52
+
53
+ First healthy state is slower than plain Postgres — the healthcheck allows a long
54
+ start period.
55
+
56
+ </Step>
57
+
58
+ </Steps>
59
+
60
+ ## Required env
61
+
62
+ | Variable | Who sets it | Meaning |
63
+ | ------------------------ | ---------------------- | -------------------------------- |
64
+ | `OKE_STORE_SQL_USER` | `oke docker` → compose | → `YSQL_USER` |
65
+ | `OKE_STORE_SQL_PASSWORD` | `oke docker` → compose | → `YSQL_PASSWORD` (enables auth) |
66
+ | `OKE_STORE_SQL_DB` | `oke docker` → compose | → `YSQL_DB` |
67
+ | `DATABASE_URL` | stack env for the app | Host `:5432` → container `:5433` |
68
+
69
+ ## Data and backup
70
+
71
+ | Path | What lives there |
72
+ | ------------------------ | ---------------------------------------------------- |
73
+ | `/home/yugabyte/yb_data` | Named volume `store-sql-data` — `yugabyted` base dir |
74
+
75
+ **Backup means:** volume backup of `store-sql-data`, or Yugabyte's backup tooling.
76
+ Losing that volume loses the universe data.
77
+
78
+ ## Production note
79
+
80
+ Single-node `yugabyted` is for local and small self-hosted use. For managed Aeon
81
+ clusters, use the [YugabyteDB provider](/docs/providers/yugabytedb). Pin a concrete
82
+ tag; the image is large and cold-start is slower than Postgres.
83
+
84
+ ## What the recipe configures
85
+
86
+ | Field | Value |
87
+ | -------------- | ----------------------------------------------------- |
88
+ | Container port | `5433` (host publishes `5432`) |
89
+ | Command | `bin/yugabyted start --base_dir=… --background=false` |
90
+ | Healthcheck | `ysqlsh … SELECT 1` (90s `start_period`) |
91
+ | Connection URL | `postgres://user:pass@host:5432/db` |
92
+
93
+ ## Troubleshooting
94
+
95
+ <Accordions>
96
+ <Accordion title="store-sql unhealthy for a long time">
97
+
98
+ Yugabyte cold-start is slow. Wait through the healthcheck `start_period`, then read
99
+ `docker compose … logs store-sql`.
100
+
101
+ macOS AirPlay on `:7000` can conflict with Yugabyte's master UI — stop AirPlay
102
+ Receiver or remap that port in `compose.override.yml` if you need the UI.
103
+
104
+ </Accordion>
105
+ <Accordion title="password authentication failed">
106
+
107
+ `YSQL_PASSWORD` must match `DATABASE_URL`. Regenerate `docker/.env.docker` with
108
+ `oke dev --docker`. Auth is off only when `YSQL_PASSWORD` is unset — this recipe
109
+ always sets it.
110
+
111
+ </Accordion>
112
+ </Accordions>
113
+
114
+ ## Learn more
115
+
116
+ - [YugabyteDB (provider)](/docs/providers/yugabytedb) — managed Aeon Connect flow
117
+ - [CockroachDB](/docs/recipes/cockroachdb) — self-hosted distributed peer
118
+ - [Postgres](/docs/recipes/postgres) — default SQL recipe
119
+ - [Store · SQL](/docs/elements/store#sql) — schema workflows
120
+
121
+ ## Next
122
+
123
+ <Cards>
124
+ <Card
125
+ title="YugabyteDB Aeon"
126
+ description="Managed cloud alternative."
127
+ href="/docs/providers/yugabytedb"
128
+ />
129
+ <Card
130
+ title="CockroachDB"
131
+ description="Self-hosted Cockroach recipe."
132
+ href="/docs/recipes/cockroachdb"
133
+ />
134
+ <Card title="Postgres" description="The default store.sql image." href="/docs/recipes/postgres" />
135
+ </Cards>