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.
- package/AGENTS.md +1 -1
- package/manifest.v1.schema.json +9 -1
- package/package.json +3 -3
- package/site/content/docs/console/runs.mdx +10 -0
- package/site/content/docs/console/traces.mdx +4 -0
- package/site/content/docs/elements/ai.mdx +54 -32
- package/site/content/docs/elements/channel.mdx +105 -14
- package/site/content/docs/elements/clock.mdx +1 -0
- package/site/content/docs/elements/flow.mdx +42 -8
- package/site/content/docs/get-started/basic-usage.mdx +5 -1
- package/site/content/docs/get-started/installation.mdx +9 -5
- package/site/content/docs/meta.json +2 -0
- package/site/content/docs/plugins/otp.mdx +58 -46
- package/site/content/docs/providers/azure-redis.mdx +85 -0
- package/site/content/docs/providers/cockroachdb.mdx +86 -0
- package/site/content/docs/providers/digitalocean-caching.mdx +88 -0
- package/site/content/docs/providers/dragonfly-cloud.mdx +82 -0
- package/site/content/docs/providers/elasticache.mdx +92 -0
- package/site/content/docs/providers/index.mdx +101 -0
- package/site/content/docs/providers/memorystore.mdx +89 -0
- package/site/content/docs/providers/meta.json +20 -0
- package/site/content/docs/providers/neon.mdx +115 -0
- package/site/content/docs/providers/redis-cloud.mdx +93 -0
- package/site/content/docs/providers/supabase.mdx +117 -0
- package/site/content/docs/providers/upstash.mdx +91 -0
- package/site/content/docs/providers/yugabytedb.mdx +95 -0
- package/site/content/docs/recipes/caddy.mdx +128 -0
- package/site/content/docs/recipes/cockroachdb.mdx +127 -0
- package/site/content/docs/recipes/dragonfly.mdx +125 -0
- package/site/content/docs/recipes/index.mdx +146 -0
- package/site/content/docs/recipes/llama-cpp.mdx +153 -0
- package/site/content/docs/recipes/mailpit.mdx +136 -0
- package/site/content/docs/recipes/meilisearch.mdx +139 -0
- package/site/content/docs/recipes/meta.json +31 -0
- package/site/content/docs/recipes/ollama.mdx +142 -0
- package/site/content/docs/recipes/openbao.mdx +141 -0
- package/site/content/docs/recipes/pgdog.mdx +137 -0
- package/site/content/docs/recipes/postgres.mdx +136 -0
- package/site/content/docs/recipes/redis.mdx +130 -0
- package/site/content/docs/recipes/rustfs.mdx +148 -0
- package/site/content/docs/recipes/sglang.mdx +105 -0
- package/site/content/docs/recipes/supabase-docker.mdx +145 -0
- package/site/content/docs/recipes/timescale.mdx +129 -0
- package/site/content/docs/recipes/traefik.mdx +136 -0
- package/site/content/docs/recipes/valkey.mdx +121 -0
- package/site/content/docs/recipes/vllm.mdx +106 -0
- package/site/content/docs/recipes/yugabytedb.mdx +135 -0
- package/site/content/docs/reference/cli.md +42 -6
- package/site/content/docs/reference/configuration.mdx +5 -3
- package/site/content/docs/reference/environment-variables.mdx +12 -12
- package/site/content/docs/reference/fx.mdx +38 -4
- package/src/auth/otp-capability.ts +14 -14
- package/src/cli/ai-setup/ai-setup.test.ts +32 -12
- package/src/cli/ai-setup/apply.ts +65 -23
- package/src/cli/ai-setup/catalog.ts +1316 -35
- package/src/cli/ai-setup/detect-ollama.ts +47 -0
- package/src/cli/ai-setup/index.ts +44 -7
- package/src/cli/ai-setup/prompts.ts +430 -486
- package/src/cli/ai-setup/recommend.test.ts +150 -50
- package/src/cli/ai-setup/recommend.ts +118 -101
- package/src/cli/ask-seed.test.ts +68 -0
- package/src/cli/ask-seed.ts +79 -0
- package/src/cli/db-seed-redact.test.ts +25 -0
- package/src/cli/db-seed.ts +36 -7
- package/src/cli/db.test.ts +1 -1
- package/src/cli/db.ts +2 -2
- package/src/cli/dev-controls.test.ts +107 -0
- package/src/cli/dev-controls.ts +354 -0
- package/src/cli/dev-schema-sync.ts +12 -4
- package/src/cli/dev.test.ts +50 -30
- package/src/cli/dev.ts +607 -66
- package/src/cli/drizzle-env.test.ts +40 -6
- package/src/cli/drizzle-env.ts +22 -1
- package/src/cli/ensure-drizzle-config.ts +6 -4
- package/src/cli/hero-meta.test.ts +13 -1
- package/src/cli/hero-meta.ts +28 -6
- package/src/cli/index.ts +5 -0
- package/src/cli/registry.ts +24 -0
- package/src/cli/replay.test.ts +105 -0
- package/src/cli/replay.ts +206 -0
- package/src/compiler/extract.ts +3 -3
- package/src/config/index.ts +3 -3
- package/src/console/server/claim.ts +3 -1
- package/src/console/ui/dist/assets/{index-ClX0ZCe5.js → index-D-9KFce5.js} +2 -2
- package/src/console/ui/dist/assets/panel-overview-CW0CQEc2.js +1 -0
- package/src/console/ui/dist/assets/panel-runs-BxuyDI3x.js +1 -0
- package/src/console/ui/dist/assets/{panel-signals-Dsxdu_AR.js → panel-signals-BXofbj7v.js} +1 -1
- package/src/console/ui/dist/assets/{panel-store-hy7O8HOs.js → panel-store-B8mH-arU.js} +1 -1
- package/src/console/ui/dist/assets/{panel-traces-CBiAe5go.js → panel-traces-DSA-ZWnf.js} +1 -1
- package/src/console/ui/dist/index.html +1 -1
- package/src/console/ui/overview/slo.ts +31 -3
- package/src/console/ui/overview/types.ts +6 -0
- package/src/console/ui/runs/errors.test.ts +53 -0
- package/src/console/ui/runs/errors.ts +88 -0
- package/src/console/ui/runs/index.ts +8 -0
- package/src/console/ui/runs/search.ts +16 -0
- package/src/console/ui/shell/panels/runs/RunsPanel.tsx +72 -1
- package/src/docker/ai-model-status.test.ts +101 -0
- package/src/docker/ai-model-status.ts +276 -0
- package/src/docker/compose-health.test.ts +115 -0
- package/src/docker/compose-health.ts +234 -0
- package/src/docker/compose.ts +24 -8
- package/src/docker/derive.ts +35 -9
- package/src/docker/docker.test.ts +304 -12
- package/src/docker/helpers.ts +56 -0
- package/src/docker/index.ts +52 -0
- package/src/docker/ollama-pull.ts +232 -0
- package/src/docker/recipes/cockroach.ts +24 -0
- package/src/docker/recipes/index.ts +32 -0
- package/src/docker/recipes/llama-cpp.ts +273 -0
- package/src/docker/recipes/ollama.ts +19 -23
- package/src/docker/recipes/pgdog.ts +4 -1
- package/src/docker/recipes/postgres.ts +5 -18
- package/src/docker/recipes/sglang.ts +55 -0
- package/src/docker/recipes/supabase.ts +21 -0
- package/src/docker/recipes/timescale.ts +18 -0
- package/src/docker/recipes/vllm.ts +44 -0
- package/src/docker/recipes/yugabyte.ts +23 -0
- package/src/docker/stack-id.test.ts +22 -0
- package/src/docker/stack-id.ts +38 -4
- package/src/docker/types.ts +15 -0
- package/src/drivers/ai-ollama.integration.test.ts +7 -4
- package/src/drivers/signal-engine.ts +10 -0
- package/src/drivers/signal-postgres.ts +24 -2
- package/src/drivers/signal-types.ts +10 -0
- package/src/elements/channel/fallback.test.ts +91 -0
- package/src/elements/channel/hard-bounce.test.ts +82 -0
- package/src/elements/channel/injection.test.ts +153 -0
- package/src/elements/channel/locale-ar.test.ts +102 -0
- package/src/elements/channel/otp-delivery.ts +5 -2
- package/src/elements/channel/receipts-ledger.test.ts +100 -0
- package/src/elements/channel/runtime.ts +24 -1
- package/src/elements/channel/test-helpers.ts +60 -0
- package/src/elements/channel/whatsapp-compliance.test.ts +124 -0
- package/src/elements/store/cache.ts +1 -1
- package/src/elements/store/emit-drizzle.ts +43 -9
- package/src/elements/store/runtime.ts +1 -1
- package/src/elements/store/schema-decl.test.ts +2 -0
- package/src/elements/store/schema-decl.ts +15 -0
- package/src/elements/store/seed.ts +1 -1
- package/src/index.ts +1 -0
- package/src/kernel/app.ts +118 -11
- package/src/kernel/boot-bind/signal.ts +6 -2
- package/src/kernel/boot-bind/store.ts +2 -1
- package/src/kernel/boot.test.ts +6 -5
- package/src/kernel/boot.ts +8 -3
- package/src/kernel/compensate.test.ts +131 -0
- package/src/kernel/correlation.test.ts +108 -0
- package/src/kernel/effect-timing.test.ts +82 -0
- package/src/kernel/flow.ts +38 -0
- package/src/kernel/fx-runs.test.ts +49 -0
- package/src/kernel/fx.test.ts +14 -0
- package/src/kernel/fx.ts +111 -1
- package/src/manifest/types.ts +8 -2
- package/src/plugins/auth-delivery.mailpit.integration.test.ts +1 -1
- package/src/plugins/auth-methods.security.test.ts +3 -3
- package/src/plugins/auth-methods.test.ts +1 -1
- package/src/plugins/index.ts +2 -2
- package/src/plugins/otp.test.ts +21 -19
- package/src/plugins/otp.ts +36 -34
- package/src/plugins/taqnyat.live.test.ts +3 -3
- package/src/runs/collect.ts +3 -0
- package/src/runs/export-otlp.ts +64 -0
- package/src/runs/index.ts +16 -0
- package/src/runs/parquet.ts +9 -0
- package/src/runs/types.ts +5 -0
- package/src/runs/window.test.ts +68 -0
- package/src/runs/window.ts +148 -0
- package/src/runtime/boot-warn.test.ts +45 -0
- package/src/runtime/boot-warn.ts +17 -0
- package/src/runtime/dev-request-log.ts +5 -5
- package/src/term.test.ts +95 -10
- package/src/term.ts +369 -14
- package/src/console/ui/dist/assets/panel-overview-DONDzBd2.js +0 -1
- 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>
|