Commit Graph
50 Commits
Author SHA1 Message Date
haylanandClaude Bot 68348aad72 feat(bench): add speed-bench tool service for drafter benchmarks
Runs llama.cpp's SPEED-Bench client (pinned commit) against
llama-server over the compose network, in the tools profile.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 16:43:06 +01:00
haylan 1989ec9383 reduced context of small modell 2026-09-25 08:17:42 +02:00
haylan a3437e9cc7 chore(ai): enalbeld mtp mode 2026-09-25 08:13:23 +02:00
haylanandClaude Bot e27f5c03b6 docs(agents): add writing-docs guide and new-term procedure
docs/agents/writing-docs.md holds the doc/comment rules and done-check,
reached via a pointer in CLAUDE.md (AGENTS.md and QWEN.md import it).
docs/agents/domain.md gains the procedure for new or conflicting terms.

Refs #55 (agent guide #62)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-24 21:52:19 +02:00
haylanandClaude Bot 05effe5c88 chore: move code comments into docs, leave one-line pointers
Explanations from docker-compose.yml, .env.example and
scripts/update.sh now live in docs/architecture.md, gateway.md,
network-access.md and operations.md. Code keeps `# see docs/...`
pointers, one-line warnings (storage key, SSRF guard, WAL grace period,
git pull ordering) and "auto-filled — leave blank" markers.

Refs #55 (comment destination map #61)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-24 21:52:00 +02:00
haylanandClaude Bot a0e5e9704b docs: restructure around source-of-truth pages
- CONTEXT.md glossary
- README reduced to intro, quickstart and doc index
- new architecture.md, gateway.md (from proxy-key-onboarding.md),
  operations.md; network-access.md rewritten
- coding-cli-setup: stale OMNIROUTE_PORT:-4000 endpoint, terms and
  duplicated per-slot/classifier explanations fixed
- research/README.md index; proxy-request-priority.md moved there as
  superseded

Every doc names keys instead of restating values and links its source.

Refs #55 (#56, #57, #59, #60)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-24 21:51:01 +02:00
haylanandClaude Bot 072eeb78c2 fix(qdrant): bind port to loopback only
qdrant has no auth; it was reachable from the whole LAN.

Refs #55 (intent vs. source #63)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-24 21:47:16 +02:00
haylanandClaude Bot fd55ce6669 chore: remove image generation, Open WebUI, Lazytainer and neo4j
Drops the comfyui, downloader-comfyui, open-webui, lazytainer and neo4j
services with their volumes, env keys and update.sh steps, plus
scripts/switch-model.sh and the two image-generation research docs.

Refs #55 (removal inventory #58, intent vs. source #63)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-24 21:47:12 +02:00
haylanandClaude Bot 8ae32102f9 feat(open-webui): add chat+image frontend, bypass omniroute for comfyui
OmniRoute's built-in comfyui provider hardcodes a CheckpointLoaderSimple
(single-file-checkpoint) workflow with no override (confirmed by
reading open-sse/handlers/imageGeneration/providers/comfyUI.ts
upstream), so it can't drive Qwen-Image 2.1's split unet/text-encoder/
vae GGUF loader chain. Open WebUI's own ComfyUI image backend is fully
generic instead — any exported workflow_api.json with arbitrary node
IDs mapped to parameters — so it can point straight at comfyui:8188.

Chat still goes through omniroute like every other client, via a
per-workload key (OPENWEBUI_OMNIROUTE_KEY, minted by hand same as
always). Published on host port 8008 per user request.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-22 23:28:44 +02:00
haylanandClaude Bot d09a99accd fix(comfyui): seed custom_nodes/input/output/user dirs under --base-directory
main.py crashed on boot (FileNotFoundError on /storage/custom_nodes) -
--base-directory fully relocates custom_nodes/input/output/user/temp
under it, it doesn't create them or fall back to the image's own
ComfyUI/custom_nodes (which has ComfyUI-Manager baked in). Seed
/storage/custom_nodes from the image's copy on first boot only (skips
once populated), so Manager survives the base-directory switch and
persists across recreates.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-22 23:09:27 +02:00
haylanandClaude Bot 9903b66094 fix(comfyui): correct HF subfolder paths for text encoder/VAE download
abenzerps/Qwen-Image-2.1-Uncensored-GGUF keeps the diffusion GGUFs at
repo root but the companion text encoder and VAE under text_encoders/
and vae/ subfolders — confirmed via the HF API's file listing, not
present in the file list used when these URLs were first written.
404'd on first real run. Local storage paths are unaffected.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-22 23:04:07 +02:00
haylanandClaude Bot 78adbf4cdf fix(update.sh): remove stale downloader-fast call
That service was merged into llama-server a while back (see the
comment on llama-server-fast's old alias), but update.sh's set -euo
pipefail meant every run since has hard-exited there — silently
skipping downloader-comfyui and the final `docker compose up -d`
recreate step on every invocation.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-22 23:02:38 +02:00
haylanandClaude Bot 69d0d76d49 fix(comfyui): add missing launch command, drop dead PUID/PGID vars
yurisasc/comfyui-rocm7.1 has no entrypoint/CMD of its own (drops into
bash) and never reads PUID/PGID/VIDEO_GID/RENDER_GID/BASE_STORAGE_PATH
- confirmed by inspecting the image directly. Without an explicit
command the container just exits 0 immediately and restart-loops
forever with zero log output, which is what was actually blocking
comfyui.home/8138, unrelated to the earlier GGUF model swap.

Add `command: python main.py --listen 0.0.0.0 --port 8188
--base-directory /storage` (the real way to point it at the storage
volume) and remove COMFYUI_PUID/COMFYUI_PGID, since nothing consumes
them.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-22 23:01:24 +02:00
haylanandClaude Bot 38ec636fb5 chore(scripts): mark switch-model.sh executable
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-22 22:43:36 +02:00
haylan db1ef90688 Merge remote-tracking branch 'origin/tool-cassefier-model' 2026-09-22 22:39:21 +02:00
haylanandClaude Bot 4e310741c7 feat(comfyui): switch to Qwen-Image 2.1 uncensored GGUF model
Replace the Comfy-Org FP8 safetensors split with abenzerps'
Qwen-Image-2.1-Uncensored-GGUF (Q4_K_M diffusion weights + int8 text
encoder + bf16 VAE). GGUF weights land in models/unet per
ComfyUI-GGUF's convention instead of models/diffusion_models.

Flagged as unconfirmed: whether yurisasc/comfyui-rocm7.1 already
bundles the ComfyUI-GGUF custom node needed for the "Unet Loader
(GGUF)" node — check on deploy and install manually if absent.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-22 22:38:27 +02:00
haylan edad6b2249 Merge branch 'research/opencode-auto-compact' 2026-09-14 07:44:32 +02:00
haylan 2250e804db Implement code changes to enhance functionality and improve performance 2026-09-11 13:15:30 +02:00
haylanandClaude Bot e31647812a fix(omniroute): raise REQUEST_TIMEOUT_MS and enable --cache-reuse to stop non-ping SSE stream aborts
STREAM_IDLE_TIMEOUT_MS was raised to 180s on 2026-09-09 to give contended
llama-server prefill room to produce a first token, but qwen-code sessions
kept hitting "Stream produced no non-ping SSE event within 95000ms" the very
next morning. Per OmniRoute's own docs, that's the wrong timer: the first
non-ping SSE event's deadline inherits REQUEST_TIMEOUT_MS (default 10 min,
computed as remaining budget after retries/cooldowns), not
STREAM_IDLE_TIMEOUT_MS (which only bounds gaps between chunks once streaming
has already started).

Two changes:
- Add REQUEST_TIMEOUT_MS=1800000 (30 min) on the omniroute service, exposed
  as OMNIROUTE_REQUEST_TIMEOUT_MS like the existing stream-idle var. Safety
  margin, not the root-cause fix.
- Add --cache-reuse 256 to llama-server: it had no KV-cache reuse configured,
  so every request reprefilled its full prompt from scratch even when most
  of a conversation's prefix was unchanged. This is the actual fix for why
  compact-prompt prefill was slow enough to hit the timeout in the first
  place.

Documents the distinction and root cause in docs/research/.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WqWBahogLCkrXNfzCSvcVc
2026-09-10 10:12:02 +02:00
haylan 16df051318 docs(research): add ponytail audit report highlighting over-engineering and complexity issues 2026-09-09 08:22:31 +02:00
haylan 128503b68a docs: add AGENTS.md and QWEN.md with agent instructions and project overview 2026-09-09 07:32:09 +02:00
haylanandClaude Bot c5864beec9 feat(llama.cpp): raise default context to 128K, document RAM/SSD offload knobs
LLAMA_CTX_SIZE default 65536 -> 131072: real usage was burning through 64K
fast. ~25.6GB VRAM (17.6GB weights + ~8GB KV cache) on the 32GB R9700,
~6GB headroom — see docs/research/qwen3.8-27b-quant.md for the full table.

Also documents LLAMA_GPU_LAYERS as the RAM-offload knob for this dense
model (no separate RAM-offload flag exists in llama.cpp, and --n-cpu-moe/
--cpu-moe/--override-tensor "exps" are MoE-only, no-ops here), and that
there's no explicit SSD offload tier to enable — llama.cpp's default mmap
already falls back to disk implicitly if GPU+RAM run out.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FCAUsjGNSoJTtK8hyLKg5m
2026-09-03 06:35:48 +02:00
haylanandClaude Bot 1eaa2a0d2e docs(research): document opencode auto-compact trigger and config surface
Resolves #27 (part of #26). Findings from opencode.ai/docs (fetched
2026-09-03) plus a fresh clone of anomalyco/opencode @ b578b72
(v1.18.27):

- No percentage-threshold config key exists; compaction.{auto,prune,
  reserved,tail_turns,preserve_recent_tokens} is the full global
  config surface (opencode.json top-level, not per-provider/model).
- Trigger is usedTokens >= context - reservedBuffer, not a hardcoded
  75%/95% cutoff — contradicts an unverified claim in a closed
  GitHub feature request (#11314).
- Reasoning tokens (Qwen3's reasoning_content) are counted via the
  provider's usage.total_tokens in the normal path, but excluded
  from the fallback sum if a provider ever omits total_tokens.
- No per-model/per-agent threshold override exists (confirmed by
  several closed-not-planned feature requests); the only per-model
  lever is each model's own limit.context/limit.output.
- Mechanism is provider-agnostic: applies identically to a hand-
  declared @ai-sdk/openai-compatible provider (this repo's llamacpp
  setup) as to hosted providers, provided limit.context is set.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FCAUsjGNSoJTtK8hyLKg5m
2026-09-03 06:25:57 +02:00
haylanandClaude Bot 100fed4274 fix(litellm): default max_tokens=4096 for the reasoning model
Qwen3 spends output tokens on reasoning_content before writing content.
Open WebUI's default chat request doesn't set max_tokens, so it fell
through to llama.cpp's low default and the model ran out mid-thought,
returning finish_reason=length with empty content — no reply shown in
Open WebUI. Confirmed via a manual /v1/chat/completions call: works with
max_tokens=2000, fails without it.

litellm_params.max_tokens is a default, not a cap — any caller (or Open
WebUI's per-model Advanced Params) that sets its own max_tokens still
overrides it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q2CR8yawSf7pwAVYnjwFea
2026-09-02 20:55:39 +02:00
haylanandClaude Bot ee7ebfd8e1 feat(litellm): add UI_USERNAME/UI_PASSWORD for the admin UI login
Without these, LiteLLM's /ui falls back to username 'admin' and the
master key as the password, forcing the master key to be typed into
a browser. generate-secrets.sh now fills UI_PASSWORD like the other
secrets.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q2CR8yawSf7pwAVYnjwFea
2026-09-02 20:29:00 +02:00
haylan 7480a3e566 Merge remote-tracking branch 'origin/research/voidllm-evaluation' 2026-09-02 20:04:44 +02:00
haylan 9604a42e8b Merge remote-tracking branch 'origin/research/proxy-tool-choice' 2026-09-02 20:04:44 +02:00
haylan 705019bc1c Merge remote-tracking branch 'origin/research/proxy-shadow-pricing' 2026-09-02 20:04:44 +02:00
haylan f40a2cff65 Merge remote-tracking branch 'origin/research/connecting-cloud-providers' 2026-09-02 20:04:44 +02:00
haylanandClaude Bot 7863b04787 fix(downloader): run as root to fix permission denied on models volume
The curlimages/curl image drops to non-root curl_user (uid 100) by
default, but the models named volume is created root-owned by Docker,
so writes into it failed with 'Permission denied'.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q2CR8yawSf7pwAVYnjwFea
2026-09-02 20:03:38 +02:00
haylan 2ac4e91862 feat(chore): impelmented seecret generation 2026-09-02 19:51:54 +02:00
haylanandClaude Bot 993f11d6de research: Claude Pro subscription vs Anthropic API for gateway backends
Answers whether the $20/mo Claude Pro subscription can be used as a
LiteLLM backend instead of a pay-per-token Anthropic API key. Finding:
no — Pro/Max OAuth credentials are contractually restricted to Claude
Code / native Anthropic apps (Consumer ToS + Usage Policy, actively
enforced server-side since March 2026). Documents the supported path:
a separate Anthropic Console API key as a model_list entry, same shape
as the existing llama.cpp entry. Same pattern applies to other
providers (ChatGPT Plus, Gemini subscriptions).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-26 08:51:38 +02:00
haylanandClaude Bot f300c5b034 research: evaluate voidllm as a LiteLLM proxy replacement
Verified against the live GitHub repo/docs (not secondhand): real,
active, functioning AI gateway, ~5 months old, effectively
single-maintainer, BSL 1.1. Fails two of the requirements from
docs/research/proxy-tool-choice.md / issue #9 — no Anthropic Messages
inbound endpoint (VoidLLM's own docs say Claude Code's LLM traffic
can't be routed through it) and no request-priority/queuing feature.
Recommendation: stay on LiteLLM.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-26 08:42:23 +02:00
haylan 487573c533 Add build plan documentation for 4x Radeon AI PRO R9700 rackmount LLM server 2026-08-25 07:20:58 +02:00
haylanandClaude Bot 5cb34b19f3 Migrate Open WebUI and coding CLIs to the AI proxy (resolves #15)
Open WebUI now points at litellm instead of llama-server directly, using a
provisioned virtual key. llama-server's host port is dropped (internal-only
on the ai-stack network) since the proxy is the only intended entry point
now. docs/coding-cli-setup.md repointed at the proxy's endpoints/ports with
per-CLI virtual keys instead of the old shared dummy key.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-25 07:18:03 +02:00
haylanandClaude Bot 0aefb36a48 Author LiteLLM AI proxy service (resolves #14)
Adds litellm + litellm-db to docker-compose.yml, litellm-config.yaml with
custom shadow-cost pricing (Claude Sonnet 5 reference, per #11) and a
priority-scheduling stub (per #16, needs real-hardware smoke test), and
required LITELLM_MASTER_KEY/SALT_KEY/DB_PASSWORD env vars. Untested on real
hardware — that's #17. Open WebUI/coding CLIs still talk to llama.cpp
directly, migration is #15.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-25 07:11:15 +02:00
haylanandClaude Bot 0342090e1c Document AI proxy request priority/queueing plan (resolves #16)
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-25 07:07:20 +02:00
haylanandClaude Bot 7e50e1867f Document AI proxy network exposure plan (resolves #13)
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-25 07:05:01 +02:00
haylanandClaude Bot 1c29e07762 Document AI proxy key onboarding process (resolves #12)
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-25 06:56:51 +02:00
haylanandClaude Bot a751e656e3 research: reference cloud pricing for LiteLLM shadow-cost estimate
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-25 06:49:38 +02:00
haylanandClaude Bot a1c37de6b4 research: self-hosted AI gateway/proxy tool choice — recommend LiteLLM
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-25 06:45:10 +02:00
haylanandClaude Bot c01ef8965d Fix docs: no localhost, wire up ai.home / ai.haylan.ch via existing NPM
Resolves wayfinder ticket #8. The stack is reached over LAN/WAN hostnames,
not localhost:
- Open WebUI: ai.home (LAN) and ai.haylan.ch (external, via DMZ) routed
  through the existing Nginx Proxy Manager instance to the published
  WEBUI_PORT — no new reverse-proxy service needed in this repo.
- llama.cpp's raw API stays LAN-only and unregistered in NPM (no auth of
  its own); coding CLIs reach it via the box's LAN IP or ai.home directly.

New docs/network-access.md documents the NPM proxy-host setup and the
LAN-only decision. coding-cli-setup.md and README updated to stop
referencing localhost.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-24 18:28:14 +02:00
haylanandClaude Bot 7d8c9324b2 Write local-usage docs for Claude Code CLI, Kimi CLI, and OpenCode CLI
Resolves wayfinder ticket #6. Covers the two server endpoints (Anthropic
shim vs OpenAI-compatible), exact config for all three CLIs, and surfaces
the shared Qwen3.8-27B tool-calling risk plus OpenCode's own documented
local-backend brittleness up front rather than burying it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-24 18:19:56 +02:00
haylanandClaude Bot b773d9cb8f research: OpenCode CLI install + local llama.cpp provider config
Answers issue #7. Confirms sst/opencode moved to anomalyco/opencode,
documents install methods, opencode.json provider config for a local
OpenAI-compatible server, and known tool-calling compatibility issues
against self-hosted backends (llama.cpp --jinja requirement, empty
tool_calls handling) plus Qwen3.8-27B-specific caveats.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-24 18:17:14 +02:00
haylanandClaude Bot 408a1f16ae Ignore .claude/ worktree scratch dir
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-24 13:01:09 +02:00
haylanandClaude Bot f0e473048d Author docker-compose stack: llama.cpp (ROCm) + Open WebUI + Qdrant + Lazytainer
Resolves wayfinder ticket #4. Wires up the locked decisions from the map:
- llama.cpp (ghcr.io/ggml-org/llama.cpp:server-rocm, gfx1201) serving
  Qwen3.8-27B-UD-Q4_K_XL.gguf, port published for direct Claude Code CLI /
  Kimi CLI access alongside Open WebUI.
- Open WebUI with WEBUI_AUTH on, RAG+Memory wired to a standalone Qdrant
  service.
- Lazytainer labels on llama-server for a 15 min idle-stop.
- Named Docker volumes only (models, qdrant-data, openwebui-data) — no host
  bind-mounts.
- One-off 'downloader' compose profile instead of a host-side script with
  its own dependencies, wrapped by scripts/download-model.sh.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-24 13:01:00 +02:00
haylan 19d62aefd3 Merge branch 'research/qwen3.8-27b-tool-calling' 2026-08-24 13:00:52 +02:00
haylanandClaude Bot ce1ab05c3e docs: research Qwen3.8-27B Unsloth dynamic GGUF quant + VRAM budget
Resolves the wayfinder research question: unsloth/Qwen3.8-27B-GGUF ships
UD-Q4_K_XL.gguf (17.6GB) directly. Documents VRAM footprint on 32GB
RDNA4 (R9700/gfx1201) at 32K and 128K context via llama.cpp ROCm/HIP.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-24 12:16:42 +02:00
haylan a55fbcaa18 research: Qwen3.8-27B tool-calling compat with llama.cpp Anthropic shim 2026-08-24 12:16:09 +02:00
haylanandClaude Bot 3d768181e3 Set up agent skills config and chart wayfinder map for local AI stack
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-24 12:13:21 +02:00