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,153 @@
1
+ ---
2
+ title: "llama.cpp"
3
+ description: "Default local AI image — OpenAI-compatible llama-server, loopback-only publish, pinned build ≥ b8146."
4
+ icon: "Bot"
5
+ source: "docs/spec/unified-theory.md"
6
+ ---
7
+
8
+ llama.cpp is the default `images.ai` pin for local inference. It runs
9
+ `llama-server` with an OpenAI-compatible `/v1` API — lightest resource footprint
10
+ for single-user / dev. Driver id stays `openai-compatible`.
11
+
12
+ <Callout title="The one rule">
13
+ Pin a verified build ≥ `b8146`, publish only on loopback, and load models only from curated
14
+ registries (Docker Hub `ai/`) — never arbitrary untrusted GGUF.
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: { local: "openai-compatible", docker: "openai-compatible", test: "mock" },
27
+ },
28
+ images: {
29
+ ai: "ghcr.io/ggml-org/llama.cpp:server-b10290", // never :latest
30
+ },
31
+ ```
32
+
33
+ Or `oke ai setup --provider llama-cpp` (TTY: banner → Ultra Fast / Fast /
34
+ Balanced / Smart → up to 20 curated Docker Hub `ai/` picks per tier) / `--yes`
35
+ for `smollm2`.
36
+
37
+ </Step>
38
+
39
+ <Step>
40
+ ### Env written by the stack
41
+
42
+ ```bash title="docker/.env.docker"
43
+ OKE_AI_URL=http://127.0.0.1:8080/v1
44
+ OKE_AI_MODEL=smollm2
45
+ ```
46
+
47
+ `OKE_AI_MODEL` is a Docker Hub `ai/<id>` model. The recipe writes
48
+ `docker/llama-entrypoint.py`, which Hub-pulls into the cache volume (native
49
+ `llama download -dr`, then a CNCF `model.weight` fallback for newer tags like
50
+ gemma4), then starts `llama-server -m <gguf> --alias <id>` (single-model — not
51
+ router `--models-preset` / bare `--docker-repo`, which hang on b10290+). Never
52
+ set `LLAMA_ARG_MODELS_PRESET` / `LLAMA_ARG_DOCKER_REPO` in the container env.
53
+
54
+ `oke dev -d` shows the model id in the hero / Docker summary and polls
55
+ `/v1/models` in the background until status is `ready` (first boot may take
56
+ minutes while the Hub image downloads).
57
+
58
+ </Step>
59
+
60
+ <Step>
61
+ ### Ask through the OpenAI-compatible driver
62
+
63
+ ```typescript
64
+ import { ai } from "okengine";
65
+
66
+ export const smart = ai.model("smart", {
67
+ provider: "openai-compatible",
68
+ model: process.env.OKE_AI_MODEL ?? "smollm2",
69
+ });
70
+ ```
71
+
72
+ </Step>
73
+
74
+ </Steps>
75
+
76
+ ## Security (hard requirements)
77
+
78
+ | Control | Requirement |
79
+ | -------------------- | ---------------------------------------------------------------------------- |
80
+ | Host publish | `127.0.0.1:8080:8080` only — never `0.0.0.0` |
81
+ | Image pin | Explicit build ≥ **b8146** (CVE-2026-27940 / CVE-2026-33298); never `latest` |
82
+ | Model source | Docker Hub [`ai/`](https://hub.docker.com/u/ai) namespace (or known HF GGUF) |
83
+ | Untrusted GGUF | **Forbidden** — crafted files can RCE the parser on unpatched builds |
84
+ | RPC / extra backends | Not published — OpenAI HTTP only |
85
+
86
+ Inside the container the server listens on `0.0.0.0` so the Compose network and
87
+ loopback map work. The **host** bind is loopback — same isolation idea as
88
+ Postgres/Redis, stricter on the published interface because of GGUF CVE risk.
89
+
90
+ ## Required env
91
+
92
+ | Variable | Required? | Meaning |
93
+ | -------------- | ----------------- | --------------------------------------- |
94
+ | `OKE_AI_URL` | **Yes** in docker | Base URL including `/v1` |
95
+ | `OKE_AI_MODEL` | Recommended | Docker Hub `ai/` id (default `smollm2`) |
96
+
97
+ ## What the recipe configures
98
+
99
+ | Field | Value |
100
+ | -------------- | --------------------------------------------------------------- |
101
+ | Container port | `8080` |
102
+ | Host publish | `127.0.0.1:8080:8080` |
103
+ | Healthcheck | `GET /health`, every 5s, 24 retries, 900s start |
104
+ | Connection URL | `http://host:8080/v1` |
105
+ | Model load | `llama-entrypoint.py` → Hub pull (incl. CNCF weights) then `-m` |
106
+
107
+ ## When to choose something else
108
+
109
+ | Workload | Prefer |
110
+ | ------------------------------------------ | --------------------------------------- |
111
+ | Single-user / dev, lightest footprint | **llama.cpp** (this recipe) |
112
+ | Local DX with library pull UX | [Ollama](/docs/recipes/ollama) |
113
+ | Multi-user / production concurrency on GPU | [vLLM](/docs/recipes/vllm) |
114
+ | Structured / agent workloads on GPU | [SGLang](/docs/recipes/sglang) |
115
+ | Managed cloud | Anthropic / OpenAI / … (no `images.ai`) |
116
+
117
+ ## Troubleshooting
118
+
119
+ <Accordions>
120
+ <Accordion title="Connection refused on :8080">
121
+
122
+ Confirm compose published `127.0.0.1:8080:8080` (not bare `8080:8080` on all
123
+ interfaces). `OKE_AI_URL` must include `/v1`.
124
+
125
+ </Accordion>
126
+ <Accordion title="Model fails to load / slow first boot">
127
+
128
+ First start Hub-pulls the curated `ai/` model into the named cache volume
129
+ (see logs: `oke ai: ensuring…` / download %). Prefer `oke ai setup` tiers
130
+ (Ultra Fast → `smollm2`) for smoke tests. Confirm `OKE_AI_MODEL` is active in
131
+ `.env.local` / `docker/.env.docker`. Watch `oke dev` (`AI … — waiting…` →
132
+ `ready`). If status stays `loading` forever on an old stack that still uses
133
+ `--models-preset`, regenerate `docker/` and recreate AI. Newer Hub tags use
134
+ CNCF weight layers — the entrypoint falls back when native `llama download`
135
+ cannot find `vnd.docker.ai.gguf.v3`. Do not mount random GGUF files. Never put
136
+ `LLAMA_ARG_MODELS_PRESET` / `LLAMA_ARG_DOCKER_REPO` in the container env.
137
+
138
+ </Accordion>
139
+ </Accordions>
140
+
141
+ ## Learn more
142
+
143
+ - [AI](/docs/elements/ai) — `fx.ask`, prompts, drivers
144
+ - [Ollama](/docs/recipes/ollama) — fully supported alternative
145
+ - [Environment variables](/docs/reference/environment-variables) — `OKE_AI_*`
146
+
147
+ ## Next
148
+
149
+ <Cards>
150
+ <Card title="Ollama" description="Library UX alternative." href="/docs/recipes/ollama" />
151
+ <Card title="vLLM" description="Production GPU serving." href="/docs/recipes/vllm" />
152
+ <Card title="AI" description="Prompts, models, guardrails." href="/docs/elements/ai" />
153
+ </Cards>
@@ -0,0 +1,136 @@
1
+ ---
2
+ title: "Mailpit"
3
+ description: "Local SMTP catcher for channel.email — SMTP_URL on :1025, UI on :8025, MAILPIT_UI_URL."
4
+ icon: "Mail"
5
+ source: "docs/spec/unified-theory.md"
6
+ ---
7
+
8
+ Mailpit is the docker-mode email catcher — every message the `smtp` channel driver sends
9
+ lands in a web UI instead of a real inbox. Pin it as `images["channel.email"]` when
10
+ `drivers.channel.email.docker` is `smtp`.
11
+
12
+ <Callout title="The one rule">
13
+ Docker ≈ prod for the **SMTP protocol** — same `SMTP_URL` shape. Mailpit is not a production MTA;
14
+ swap the image / URL for a real relay when you leave local docker.
15
+ </Callout>
16
+
17
+ ## Quick start
18
+
19
+ <Steps>
20
+
21
+ <Step>
22
+ ### Pin the image (templates already do)
23
+
24
+ ```typescript title="oke.config.ts"
25
+ drivers: {
26
+ channel: {
27
+ email: { local: "console", docker: "smtp", test: "console", prod: "smtp" },
28
+ },
29
+ },
30
+ images: {
31
+ "channel.email": "axllent/mailpit:v1.22.3",
32
+ },
33
+ ```
34
+
35
+ </Step>
36
+
37
+ <Step>
38
+ ### Connect the smtp driver
39
+
40
+ ```bash title="docker/.env.docker (written by oke docker)"
41
+ SMTP_URL=smtp://127.0.0.1:1025
42
+ MAILPIT_UI_URL=http://127.0.0.1:8025
43
+ ```
44
+
45
+ No `SMTP_USER` / `SMTP_PASSWORD` required for Mailpit's open local listener.
46
+
47
+ </Step>
48
+
49
+ <Step>
50
+ ### Send and inspect
51
+
52
+ Trigger any flow that uses `fx.email` / channel email. Open `MAILPIT_UI_URL` (port
53
+ **8025**) to read the caught message — subject, body, headers.
54
+
55
+ </Step>
56
+
57
+ </Steps>
58
+
59
+ ## Required env
60
+
61
+ | Variable | Required? | Meaning |
62
+ | ----------------------------- | -------------------------- | ------------------------------------------------------- |
63
+ | `SMTP_URL` | **Yes** (app, smtp driver) | `smtp://host:1025` — boot fails without it |
64
+ | `OKE_CHANNEL_EMAIL_URL` | Alternative | Same role as `SMTP_URL` |
65
+ | `MAILPIT_UI_URL` | Written by stack | Browser UI — not read by the smtp driver |
66
+ | `SMTP_USER` / `SMTP_PASSWORD` | No for Mailpit | Used when pointing `SMTP_URL` at an authenticated relay |
67
+
68
+ ## Data and backup
69
+
70
+ Mailpit declares **no volume**. Caught messages live in container memory/disk for that
71
+ instance only.
72
+
73
+ **Backup means:** nothing durable to back up — this is a catcher. For forensic copies,
74
+ export from the UI before recreate. Production mail never uses this image as the store of
75
+ record.
76
+
77
+ ## Production note
78
+
79
+ Templates set `prod: "smtp"` but still pin Mailpit in `images` for docker. In real prod,
80
+ point `SMTP_URL` at your provider and set `SMTP_USER` / `SMTP_PASSWORD` as needed.
81
+
82
+ Leaving Mailpit reachable on a public host exposes an open relay UI — bind to the compose
83
+ network only.
84
+
85
+ Healthcheck probes `http://127.0.0.1:8025/api/v1/info` — UI down ⇒ service unhealthy even
86
+ if SMTP still accepts mail.
87
+
88
+ ## What the recipe configures
89
+
90
+ | Field | Value |
91
+ | -------------- | --------------------------------------------------- |
92
+ | SMTP port | `1025` (published) |
93
+ | Extra port | `8025` → UI |
94
+ | Healthcheck | `wget` against `/api/v1/info`, every 5s, 10 retries |
95
+ | Connection URL | `smtp://host:1025` |
96
+
97
+ ## Troubleshooting
98
+
99
+ <Accordions>
100
+ <Accordion title="oke boot: smtp driver needs SMTP_URL">
101
+
102
+ The smtp binder refuses to start without `SMTP_URL` (or `OKE_CHANNEL_EMAIL_URL`). In
103
+ docker mode the error asks whether `oke dev -d` wrote `docker/.env.docker`. Also rejects
104
+ non-`smtp://` schemes: `oke boot: SMTP_URL must use smtp://`.
105
+
106
+ </Accordion>
107
+ <Accordion title="Messages send but UI is empty">
108
+
109
+ Wrong UI port, or you opened a different instance's Mailpit. Confirm `MAILPIT_UI_URL`
110
+ matches the published `8025` mapping for **this** compose project (instance-id offsets
111
+ shift the host port).
112
+
113
+ </Accordion>
114
+ </Accordions>
115
+
116
+ ## Learn more
117
+
118
+ - [Channel](/docs/elements/channel) — email delivery physics
119
+ - [Environment variables](/docs/reference/environment-variables) — `SMTP_*` map
120
+ - [Configuration](/docs/reference/configuration) — default `channel.email` image pin
121
+
122
+ ## Next
123
+
124
+ <Cards>
125
+ <Card
126
+ title="RustFS"
127
+ description="S3-compatible files for the same stack."
128
+ href="/docs/recipes/rustfs"
129
+ />
130
+ <Card
131
+ title="OpenBao"
132
+ description="Vault recipe for docker/prod secrets."
133
+ href="/docs/recipes/openbao"
134
+ />
135
+ <Card title="Channel" description="How fx.email reaches humans." href="/docs/elements/channel" />
136
+ </Cards>
@@ -0,0 +1,139 @@
1
+ ---
2
+ title: "Meilisearch"
3
+ description: "Full-text store.index image — OKE_STORE_INDEX_URL, OKE_STORE_INDEX_KEY / MEILI_MASTER_KEY, /meili_data volume."
4
+ icon: "Search"
5
+ source: "docs/spec/unified-theory.md"
6
+ ---
7
+
8
+ Meilisearch backs the `meilisearch` index driver — typo-tolerant full-text search over
9
+ HTTP. Pin `images["store.index"]` and set `drivers.store.index` to `meilisearch` where
10
+ you need it (index does **not** auto-promote in docker).
11
+
12
+ <Callout title="The one rule">
13
+ Index stays `memory` in every environment until you set the driver map explicitly — there is no
14
+ silent docker fallback to Meilisearch or pgvector.
15
+ </Callout>
16
+
17
+ ## Quick start
18
+
19
+ <Steps>
20
+
21
+ <Step>
22
+ ### Declare driver + image
23
+
24
+ ```typescript title="oke.config.ts"
25
+ drivers: {
26
+ store: {
27
+ index: { local: "memory", docker: "meilisearch", prod: "meilisearch" },
28
+ },
29
+ },
30
+ images: {
31
+ "store.index": "getmeili/meilisearch:v1.14",
32
+ },
33
+ ```
34
+
35
+ </Step>
36
+
37
+ <Step>
38
+ ### Keys written by oke docker
39
+
40
+ ```bash title="docker/.env.docker"
41
+ OKE_STORE_INDEX_URL=http://127.0.0.1:7700
42
+ OKE_STORE_INDEX_KEY=… # also accepted as MEILI_MASTER_KEY
43
+ ```
44
+
45
+ Recipe injects into the container:
46
+
47
+ - `MEILI_MASTER_KEY=${OKE_STORE_INDEX_KEY}`
48
+ - `MEILI_ENV=${OKE_MEILI_ENV:-production}`
49
+ - `MEILI_NO_ANALYTICS=true`
50
+
51
+ </Step>
52
+
53
+ <Step>
54
+ ### Search from a flow
55
+
56
+ Use `store.index(…)` without `{ dims }` for full-text (vector dims select pgvector /
57
+ libsql). Writes wait on Meilisearch tasks before returning.
58
+
59
+ </Step>
60
+
61
+ </Steps>
62
+
63
+ ## Required env
64
+
65
+ | Variable | Required? | Meaning |
66
+ | --------------------- | -------------------- | ------------------------------------------------ |
67
+ | `OKE_STORE_INDEX_URL` | **Yes** | Base URL — boot fails without it |
68
+ | `OKE_STORE_INDEX_KEY` | **Yes** (production) | Master/API key; falls back to `MEILI_MASTER_KEY` |
69
+ | `MEILI_MASTER_KEY` | Alternate | Same secret, container-side name |
70
+ | `OKE_MEILI_ENV` | Optional | Passed as `MEILI_ENV` (default `production`) |
71
+
72
+ ## Data and backup
73
+
74
+ | Volume | Path | What it stores |
75
+ | ------------------ | ------------- | ---------------------------- |
76
+ | `store-index-data` | `/meili_data` | Indexes, documents, settings |
77
+
78
+ **Backup means:** snapshot/restore that named volume (or Meilisearch dumps). Recreating
79
+ the container **keeps** data if the volume remains; deleting the volume wipes every index.
80
+
81
+ The master key is **not** inside the volume — it lives in `.env.docker` / secrets.
82
+ Losing the key without a backup blocks admin API access even if data remains.
83
+
84
+ ## Production note
85
+
86
+ Always set a non-empty `OKE_STORE_INDEX_KEY` when `MEILI_ENV=production` — Meilisearch
87
+ refuses insecure production mode without a master key. Prefer network isolation (compose
88
+ network only) plus the key; do not publish `:7700` on the public internet without auth.
89
+
90
+ Vector `ai.embed` into a meilisearch index fails loud — embeddings need `pgvector` /
91
+ `libsql`, not FTS. See [Store · Index](/docs/elements/store#index).
92
+
93
+ ## What the recipe configures
94
+
95
+ | Field | Value |
96
+ | -------------- | ---------------------------------------------- |
97
+ | Container port | `7700` |
98
+ | Healthcheck | `wget` against `/health`, every 5s, 12 retries |
99
+ | Connection URL | `http://host:7700` |
100
+
101
+ ## Troubleshooting
102
+
103
+ <Accordions>
104
+ <Accordion title="oke boot: meilisearch index needs OKE_STORE_INDEX_URL">
105
+
106
+ No silent memory fallback. Re-run `oke dev --docker` or export `OKE_STORE_INDEX_URL`.
107
+ Docker-mode wording asks whether `docker/.env.docker` was written.
108
+
109
+ </Accordion>
110
+ <Accordion title="meilisearch index: GET/POST … failed (403) — or master key errors">
111
+
112
+ `OKE_STORE_INDEX_KEY` does not match `MEILI_MASTER_KEY` inside the container, or the key
113
+ was rotated without updating the app env. Align both sides and restart. Unreachable host
114
+ surfaces as `meilisearch index: unreachable at <url> — …`.
115
+
116
+ </Accordion>
117
+ </Accordions>
118
+
119
+ ## Learn more
120
+
121
+ - [Store · Index](/docs/elements/store#index) — FTS vs vector drivers
122
+ - [Environment variables](/docs/reference/environment-variables) — index URL / key
123
+ - [Configuration](/docs/reference/configuration) — `drivers.store.index` union
124
+
125
+ ## Next
126
+
127
+ <Cards>
128
+ <Card
129
+ title="llama.cpp"
130
+ description="Default local AI for the same stack."
131
+ href="/docs/recipes/llama-cpp"
132
+ />
133
+ <Card
134
+ title="Postgres"
135
+ description="pgvector alternative for embeddings."
136
+ href="/docs/recipes/postgres"
137
+ />
138
+ <Card title="Store" description="Index facet API." href="/docs/elements/store" />
139
+ </Cards>
@@ -0,0 +1,31 @@
1
+ {
2
+ "title": "Recipes",
3
+ "icon": "Container",
4
+ "pages": [
5
+ "index",
6
+ "---SQL---",
7
+ "postgres",
8
+ "supabase-docker",
9
+ "cockroachdb",
10
+ "yugabytedb",
11
+ "timescale",
12
+ "---KV---",
13
+ "redis",
14
+ "valkey",
15
+ "dragonfly",
16
+ "---Proxy---",
17
+ "caddy",
18
+ "traefik",
19
+ "---Services---",
20
+ "pgdog",
21
+ "rustfs",
22
+ "mailpit",
23
+ "openbao",
24
+ "meilisearch",
25
+ "---AI---",
26
+ "llama-cpp",
27
+ "ollama",
28
+ "vllm",
29
+ "sglang"
30
+ ]
31
+ }
@@ -0,0 +1,142 @@
1
+ ---
2
+ title: "Ollama"
3
+ description: "Fully supported local AI alternative — OKE_AI_URL, pinned ≥ 0.17.1, loopback-only publish, library models only."
4
+ icon: "Bot"
5
+ source: "docs/spec/unified-theory.md"
6
+ ---
7
+
8
+ Ollama remains a **fully supported** local model server (not deprecated). The
9
+ default local pin is [llama.cpp](/docs/recipes/llama-cpp); choose Ollama when you
10
+ want its library pull UX. Pin `images.ai` and set `drivers.ai` to `ollama`.
11
+
12
+ <Callout title="The one rule">
13
+ Pin ≥ `0.17.1` (never `latest`), publish only on loopback, and load models only from Ollama’s
14
+ library — never arbitrary untrusted GGUF via `/api/create`.
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: { local: "ollama", docker: "ollama", test: "mock" }, // prod: set deliberately
27
+ },
28
+ images: {
29
+ ai: "ollama/ollama:0.32.6", // never :latest — floor 0.17.1 (CVE-2026-7482)
30
+ },
31
+ ```
32
+
33
+ Or run `oke ai setup --provider ollama --yes`.
34
+
35
+ </Step>
36
+
37
+ <Step>
38
+ ### Env written by the stack
39
+
40
+ ```bash title="docker/.env.docker"
41
+ OKE_AI_URL=http://127.0.0.1:11434
42
+ OKE_AI_MODEL=qwen3.5:9b
43
+ ```
44
+
45
+ Host publish is `127.0.0.1:11434:11434`. Inside the container
46
+ `OLLAMA_HOST=0.0.0.0:11434` so Docker networking works.
47
+
48
+ </Step>
49
+
50
+ <Step>
51
+ ### Boot pulls against the container API
52
+
53
+ After compose is healthy, `oke dev -d` shows `OKE_AI_MODEL` in the hero / Docker
54
+ summary, POSTs `/api/pull` to **this container’s**
55
+ loopback URL when the recipe is Ollama — never a host `ollama` CLI.
56
+
57
+ </Step>
58
+
59
+ </Steps>
60
+
61
+ ## Security (hard requirements)
62
+
63
+ | Control | Requirement |
64
+ | -------------- | -------------------------------------------------------------------------- |
65
+ | Host publish | `127.0.0.1:11434:11434` only — never `0.0.0.0` |
66
+ | Image pin | Explicit tag ≥ **0.17.1** (CVE-2026-7482); never `latest` |
67
+ | Model source | [Ollama library](https://ollama.com/library) only |
68
+ | Untrusted GGUF | **Forbidden** — `/api/create` with crafted files is the CVE-2026-7482 path |
69
+
70
+ Ollama and llama.cpp share GGUF-parser risk; Ollama also has its own Go loader
71
+ CVE. Network exposure of `:11434` turns that into a remote attack.
72
+
73
+ <Callout type="warn" title="Host `ollama` CLI is unrelated">
74
+ A host `ollama pull` often talks to a separately installed daemon. Trust boot ensure against
75
+ `OKE_AI_URL`.
76
+ </Callout>
77
+
78
+ ## Required env
79
+
80
+ | Variable | Required? | Meaning |
81
+ | -------------------------------------------- | ----------------- | ------------------------------------------------------------------ |
82
+ | `OKE_AI_URL` | **Yes** in docker | Base URL — `oke boot: ollama driver needs OKE_AI_URL` when missing |
83
+ | `OKE_AI_MODEL` | Recommended | Model tag to pull/serve (default `qwen3.5:9b`) |
84
+ | `OLLAMA_HOST` | Set by recipe | `0.0.0.0:11434` inside the container |
85
+ | `OKE_AI_VISION_MODEL` / `OKE_AI_EMBED_MODEL` | Optional | Written by `oke ai setup` for logical models |
86
+
87
+ ## Data and backup
88
+
89
+ | Volume | Path | What it stores |
90
+ | --------- | --------------- | -------------------------------------- |
91
+ | `ai-data` | `/root/.ollama` | Pulled model weights + Ollama metadata |
92
+
93
+ ## Production note
94
+
95
+ Local Ollama is for docker/dev (and air-gapped prod you deliberately choose).
96
+ For multi-user GPU self-hosting see [vLLM](/docs/recipes/vllm) /
97
+ [SGLang](/docs/recipes/sglang). Cloud drivers stay separate.
98
+
99
+ PII egress rules treat `ollama` as local — see [AI · PII](/docs/elements/ai).
100
+
101
+ ## What the recipe configures
102
+
103
+ | Field | Value |
104
+ | -------------- | ---------------------------------------------- |
105
+ | Container port | `11434` |
106
+ | Host publish | `127.0.0.1:11434:11434` |
107
+ | Entrypoint | Image default (`ollama serve`) |
108
+ | Healthcheck | `ollama list`, every 5s, 24 retries, 10s start |
109
+ | Connection URL | `http://host:11434` |
110
+ | Model pull | Host-side `POST /api/pull` after healthy |
111
+
112
+ ## Troubleshooting
113
+
114
+ <Accordions>
115
+ <Accordion title="oke boot: ollama driver needs OKE_AI_URL">
116
+
117
+ Docker mode expects `OKE_AI_URL` from `docker/.env.docker` when `images.ai` is pinned.
118
+ Locally the default is `http://127.0.0.1:11434`. Prefer `oke ai setup` to wire everything
119
+ in one pass.
120
+
121
+ </Accordion>
122
+ <Accordion title="Model missing / I already ran ollama pull on the host">
123
+
124
+ The host CLI likely filled a **different** Ollama. Check `GET $OKE_AI_URL/api/tags`,
125
+ then recreate with `oke dev -d`.
126
+
127
+ </Accordion>
128
+ </Accordions>
129
+
130
+ ## Learn more
131
+
132
+ - [llama.cpp](/docs/recipes/llama-cpp) — default local AI
133
+ - [AI](/docs/elements/ai) — `fx.ask`, prompts, evals
134
+ - [CLI · oke ai setup](/docs/reference/cli) — non-interactive provider wiring
135
+
136
+ ## Next
137
+
138
+ <Cards>
139
+ <Card title="llama.cpp" description="Default local AI." href="/docs/recipes/llama-cpp" />
140
+ <Card title="Meilisearch" description="Full-text index peer." href="/docs/recipes/meilisearch" />
141
+ <Card title="AI" description="Prompts, models, guardrails." href="/docs/elements/ai" />
142
+ </Cards>