okengine 0.9.1 → 0.10.1
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 +97 -9
- 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/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/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-app-runner.ts +6 -0
- 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 +633 -66
- package/src/cli/docker-cli.test.ts +15 -0
- 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/cli/start.ts +12 -1
- package/src/compiler/effects-infer.ts +37 -8
- package/src/compiler/extract.test.ts +125 -0
- package/src/compiler/extract.ts +31 -6
- 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.test.ts +28 -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 +131 -10
- 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 +113 -10
- 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/effects-stamping.test.ts +207 -0
- package/src/kernel/errors.ts +11 -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 +153 -14
- package/src/manifest/sql-resource.ts +41 -0
- package/src/manifest/types.ts +8 -2
- 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,125 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Dragonfly"
|
|
3
|
+
description: "Multi-threaded Redis-wire runtime — OKE_STORE_KV_PASSWORD, memlock ulimit, no maxmemory-policy flag."
|
|
4
|
+
icon: "Zap"
|
|
5
|
+
source: "docs/spec/unified-theory.md"
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
Dragonfly is a multi-threaded, memory-efficient reimplementation of the Redis protocol —
|
|
9
|
+
same `redis://` wire format, different engine. Slots behind the same `redis` driver with
|
|
10
|
+
zero Flow changes.
|
|
11
|
+
|
|
12
|
+
<Callout title="The one rule">
|
|
13
|
+
Driver id stays `redis`. Dragonfly is an image choice — every KV call through `fx.store` behaves
|
|
14
|
+
identically to Redis or Valkey at the protocol layer.
|
|
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.kv": "docker.dragonflydb.io/dragonflydb/dragonfly",
|
|
27
|
+
},
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
</Step>
|
|
31
|
+
|
|
32
|
+
<Step>
|
|
33
|
+
### Password + memory
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
OKE_STORE_KV_PASSWORD=…
|
|
37
|
+
OKE_STORE_KV_MAXMEMORY=256mb # optional; recipe passes --maxmemory
|
|
38
|
+
REDIS_URL=redis://:…@127.0.0.1:6379
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Command: `dragonfly --requirepass "$OKE_STORE_KV_PASSWORD" --maxmemory "…"`.
|
|
42
|
+
|
|
43
|
+
Unlike Redis/Valkey, this recipe does **not** pass `--maxmemory-policy` — Dragonfly's
|
|
44
|
+
own defaults apply.
|
|
45
|
+
|
|
46
|
+
</Step>
|
|
47
|
+
|
|
48
|
+
<Step>
|
|
49
|
+
### memlock ulimit
|
|
50
|
+
|
|
51
|
+
The recipe sets `ulimits.memlock: -1` — required for Dragonfly's shared-nothing design.
|
|
52
|
+
If the host forbids unlimited memlock, the container may fail to start.
|
|
53
|
+
|
|
54
|
+
</Step>
|
|
55
|
+
|
|
56
|
+
</Steps>
|
|
57
|
+
|
|
58
|
+
## Required env
|
|
59
|
+
|
|
60
|
+
| Variable | Required? | Meaning |
|
|
61
|
+
| ------------------------ | ------------- | --------------------------------------------------- |
|
|
62
|
+
| `OKE_STORE_KV_PASSWORD` | **Yes** | `--requirepass` |
|
|
63
|
+
| `REDIS_URL` | **Yes** (app) | `redis://` URL for the driver |
|
|
64
|
+
| `OKE_STORE_KV_MAXMEMORY` | Optional | `--maxmemory` (default `0` in the command template) |
|
|
65
|
+
| `HEALTHCHECK_PORT` | Set by recipe | `6379` — used by the image's healthcheck script |
|
|
66
|
+
|
|
67
|
+
## Data and backup
|
|
68
|
+
|
|
69
|
+
No named volume — ephemeral by default, same as Redis/Valkey. **Backup means:** do not
|
|
70
|
+
treat this container as durable storage until you add a volume and Dragonfly persistence
|
|
71
|
+
settings; rebuild from SQL/files, or use [Dragonfly Cloud](/docs/providers/dragonfly-cloud).
|
|
72
|
+
|
|
73
|
+
## Production note
|
|
74
|
+
|
|
75
|
+
BSL 1.1 — converts to Apache 2.0 on a published change date per release. Free for
|
|
76
|
+
self-hosting; the BSL terms restrict offering Dragonfly itself as a commercial managed
|
|
77
|
+
service to third parties — running it for your own app is unaffected.
|
|
78
|
+
|
|
79
|
+
Multi-threaded architecture makes better use of multi-core hosts than single-threaded
|
|
80
|
+
Redis under heavy concurrent load. For a managed endpoint with TLS + passkey, see
|
|
81
|
+
[Dragonfly Cloud](/docs/providers/dragonfly-cloud).
|
|
82
|
+
|
|
83
|
+
## What the recipe configures
|
|
84
|
+
|
|
85
|
+
| Field | Value |
|
|
86
|
+
| -------------- | ----------------------------------------------------- |
|
|
87
|
+
| Container port | `6379` |
|
|
88
|
+
| `ulimits` | `memlock: -1` |
|
|
89
|
+
| Healthcheck | `/usr/local/bin/healthcheck.sh`, every 5s, 10 retries |
|
|
90
|
+
| Connection URL | `redis://:pass@host:6379` |
|
|
91
|
+
|
|
92
|
+
## Troubleshooting
|
|
93
|
+
|
|
94
|
+
<Accordions>
|
|
95
|
+
<Accordion title="Container exits — cannot lock memory / memlock">
|
|
96
|
+
|
|
97
|
+
Host `ulimit -l` is too low. The recipe requests unlimited memlock. Raise the Docker
|
|
98
|
+
daemon / systemd limit, or run on a host that allows `memlock: -1`.
|
|
99
|
+
|
|
100
|
+
</Accordion>
|
|
101
|
+
<Accordion title="oke boot: redis driver needs REDIS_URL">
|
|
102
|
+
|
|
103
|
+
Same driver failure as Redis — export `REDIS_URL` or let docker mode write it. Wrong
|
|
104
|
+
password yields Redis-protocol `NOAUTH` / `WRONGPASS` from the server.
|
|
105
|
+
|
|
106
|
+
</Accordion>
|
|
107
|
+
</Accordions>
|
|
108
|
+
|
|
109
|
+
## Learn more
|
|
110
|
+
|
|
111
|
+
- [Store · KV](/docs/elements/store#kv) — full Redis-protocol image license table
|
|
112
|
+
- [Dragonfly Cloud](/docs/providers/dragonfly-cloud) — the managed equivalent
|
|
113
|
+
- [Redis](/docs/recipes/redis) · [Valkey](/docs/recipes/valkey) — the other two peers
|
|
114
|
+
|
|
115
|
+
## Next
|
|
116
|
+
|
|
117
|
+
<Cards>
|
|
118
|
+
<Card
|
|
119
|
+
title="Dragonfly Cloud"
|
|
120
|
+
description="Managed Dragonfly."
|
|
121
|
+
href="/docs/providers/dragonfly-cloud"
|
|
122
|
+
/>
|
|
123
|
+
<Card title="Valkey" description="Permissive-licensed peer." href="/docs/recipes/valkey" />
|
|
124
|
+
<Card title="PgDog" description="Pooling for the SQL side." href="/docs/recipes/pgdog" />
|
|
125
|
+
</Cards>
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Recipes"
|
|
3
|
+
description: "Docker recipes already shipped in oke docker — SQL (including Cockroach, Yugabyte, Timescale), KV, proxy, and services."
|
|
4
|
+
icon: "Container"
|
|
5
|
+
source: "docs/spec/unified-theory.md"
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
Every recipe below is already wired into `oke docker` — pin an image in `oke.config.ts`
|
|
9
|
+
and get env, healthcheck, and a connection URL for free.
|
|
10
|
+
|
|
11
|
+
<Callout title="The one rule">
|
|
12
|
+
Vendor choice lives in `images[…]` — never in `drivers.*`, which only ever say protocol ids
|
|
13
|
+
(`postgres`, `redis`, `s3`, `smtp`, `openbao`, `meilisearch`, `openai-compatible`, `ollama`, …).
|
|
14
|
+
</Callout>
|
|
15
|
+
|
|
16
|
+
## SQL
|
|
17
|
+
|
|
18
|
+
<Cards>
|
|
19
|
+
<Card
|
|
20
|
+
title="Postgres"
|
|
21
|
+
description="Default store.sql — POSTGRES_*, PGDATA, DATABASE_URL."
|
|
22
|
+
href="/docs/recipes/postgres"
|
|
23
|
+
/>
|
|
24
|
+
<Card
|
|
25
|
+
title="Supabase"
|
|
26
|
+
description="supabase/postgres extension bundle only."
|
|
27
|
+
href="/docs/recipes/supabase-docker"
|
|
28
|
+
/>
|
|
29
|
+
<Card
|
|
30
|
+
title="CockroachDB"
|
|
31
|
+
description="Self-hosted single-node — port 26257, COCKROACH_*."
|
|
32
|
+
href="/docs/recipes/cockroachdb"
|
|
33
|
+
/>
|
|
34
|
+
<Card
|
|
35
|
+
title="YugabyteDB"
|
|
36
|
+
description="Self-hosted YSQL — port 5433, YSQL_*."
|
|
37
|
+
href="/docs/recipes/yugabytedb"
|
|
38
|
+
/>
|
|
39
|
+
<Card
|
|
40
|
+
title="Timescale"
|
|
41
|
+
description="Postgres + hypertables — same POSTGRES_* contract."
|
|
42
|
+
href="/docs/recipes/timescale"
|
|
43
|
+
/>
|
|
44
|
+
</Cards>
|
|
45
|
+
|
|
46
|
+
## KV
|
|
47
|
+
|
|
48
|
+
Driver id stays `redis` for every image below.
|
|
49
|
+
|
|
50
|
+
<Cards>
|
|
51
|
+
<Card
|
|
52
|
+
title="Redis"
|
|
53
|
+
description="Default store.kv — requirepass + maxmemory."
|
|
54
|
+
href="/docs/recipes/redis"
|
|
55
|
+
/>
|
|
56
|
+
<Card title="Valkey" description="BSD-licensed Redis-wire fork." href="/docs/recipes/valkey" />
|
|
57
|
+
<Card
|
|
58
|
+
title="Dragonfly"
|
|
59
|
+
description="Multi-threaded Redis-wire runtime."
|
|
60
|
+
href="/docs/recipes/dragonfly"
|
|
61
|
+
/>
|
|
62
|
+
</Cards>
|
|
63
|
+
|
|
64
|
+
## Proxy
|
|
65
|
+
|
|
66
|
+
Opt-in via `images.proxy` — leave unset until you need HTTPS or `--scale app=N`.
|
|
67
|
+
|
|
68
|
+
<Cards>
|
|
69
|
+
<Card title="Caddy" description="Automatic-HTTPS, single instance." href="/docs/recipes/caddy" />
|
|
70
|
+
<Card
|
|
71
|
+
title="Traefik"
|
|
72
|
+
description="Docker-label discovery + socket-proxy."
|
|
73
|
+
href="/docs/recipes/traefik"
|
|
74
|
+
/>
|
|
75
|
+
</Cards>
|
|
76
|
+
|
|
77
|
+
## Services
|
|
78
|
+
|
|
79
|
+
<Cards>
|
|
80
|
+
<Card title="PgDog" description="Transaction pooler on :6432." href="/docs/recipes/pgdog" />
|
|
81
|
+
<Card
|
|
82
|
+
title="RustFS"
|
|
83
|
+
description="S3-compatible store.files — /data volume."
|
|
84
|
+
href="/docs/recipes/rustfs"
|
|
85
|
+
/>
|
|
86
|
+
<Card title="Mailpit" description="SMTP catcher — UI on :8025." href="/docs/recipes/mailpit" />
|
|
87
|
+
<Card title="OpenBao" description="Raft vault — unseal key SPOF." href="/docs/recipes/openbao" />
|
|
88
|
+
<Card
|
|
89
|
+
title="Meilisearch"
|
|
90
|
+
description="Full-text store.index on :7700."
|
|
91
|
+
href="/docs/recipes/meilisearch"
|
|
92
|
+
/>
|
|
93
|
+
</Cards>
|
|
94
|
+
|
|
95
|
+
## AI (local / self-hosted)
|
|
96
|
+
|
|
97
|
+
Default local pin is **llama.cpp**. Ollama stays fully supported. vLLM / SGLang
|
|
98
|
+
are production-tier self-host options — most apps still use a managed provider.
|
|
99
|
+
|
|
100
|
+
| Workload | Recipe |
|
|
101
|
+
| -------------------------------- | ---------------------------------------------- |
|
|
102
|
+
| Single-user / dev (lightest) | [llama.cpp](/docs/recipes/llama-cpp) (default) |
|
|
103
|
+
| Local library UX | [Ollama](/docs/recipes/ollama) |
|
|
104
|
+
| Multi-user GPU concurrency | [vLLM](/docs/recipes/vllm) |
|
|
105
|
+
| Structured / agent GPU workloads | [SGLang](/docs/recipes/sglang) |
|
|
106
|
+
| Managed cloud | Anthropic / OpenAI / … (no `images.ai`) |
|
|
107
|
+
|
|
108
|
+
All four recipes **loopback-publish only** and pin explicit tags (never
|
|
109
|
+
`latest`). Load models from curated registries — never arbitrary untrusted GGUF.
|
|
110
|
+
|
|
111
|
+
<Cards>
|
|
112
|
+
<Card
|
|
113
|
+
title="llama.cpp"
|
|
114
|
+
description="Default local AI — OpenAI /v1, lightest footprint."
|
|
115
|
+
href="/docs/recipes/llama-cpp"
|
|
116
|
+
/>
|
|
117
|
+
<Card
|
|
118
|
+
title="Ollama"
|
|
119
|
+
description="Fully supported alternative — library pull UX."
|
|
120
|
+
href="/docs/recipes/ollama"
|
|
121
|
+
/>
|
|
122
|
+
<Card title="vLLM" description="Self-hosted multi-user GPU serving." href="/docs/recipes/vllm" />
|
|
123
|
+
<Card
|
|
124
|
+
title="SGLang"
|
|
125
|
+
description="Self-hosted structured / agent GPU serving."
|
|
126
|
+
href="/docs/recipes/sglang"
|
|
127
|
+
/>
|
|
128
|
+
</Cards>
|
|
129
|
+
|
|
130
|
+
## Learn more
|
|
131
|
+
|
|
132
|
+
- [Providers](/docs/providers) — managed cloud alternatives
|
|
133
|
+
- [Docker](/docs/deployment/docker) — compose derivation, PgDog, reverse proxy
|
|
134
|
+
- [Store](/docs/elements/store) — `sql` / `kv` / `files` / `index` facets
|
|
135
|
+
|
|
136
|
+
## Next
|
|
137
|
+
|
|
138
|
+
<Cards>
|
|
139
|
+
<Card
|
|
140
|
+
title="Postgres"
|
|
141
|
+
description="Start with the default SQL recipe."
|
|
142
|
+
href="/docs/recipes/postgres"
|
|
143
|
+
/>
|
|
144
|
+
<Card title="Providers" description="Managed cloud alternatives." href="/docs/providers" />
|
|
145
|
+
<Card title="Deployment" description="Compose, Swarm, or Kubernetes." href="/docs/deployment" />
|
|
146
|
+
</Cards>
|
|
@@ -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>
|