feat(cmd): wire auth/run dispatcher + demo docs

main.go dispatches `tapir auth` (interactive OAuth → persist refresh token via
SecretStore) and `tapir run` (wire YouTube source + local summarizer + store
sink, build engine, run the dedup-aware loop). Config-driven so live creds plug
in at demo time; SIGINT stops the loop cleanly. Block kept minimal so Worker E's
list/show cases union cleanly at merge.

Add .env.example documenting every TAPIR_* var and a README demo runbook. Pin
the summarizer alias-as-config decision and record the max_tokens fix in
docs/homelab-integration.md (clears two `confirm` items).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-02 21:03:21 +02:00
co-authored by Claude Opus 4.8
parent 5645c2c012
commit 61796db16b
4 changed files with 171 additions and 15 deletions
+13 -8
View File
@@ -18,16 +18,21 @@ it** — endpoints and aliases drift, and this file is a snapshot (2026-06-02),
Resolve the live key from the vault when wiring; `sk-local-123` is no longer valid. `confirm` partially resolved.
- **Model alias format:** `host/name`, e.g. `koala/qwen3-coder-30b`, `koala/phi4-mini`,
`iguana/devstral`, `iguana/deepseek-r1-14b`. **Not** the `ollama/` prefix form.
- **Which alias for summarization:** NOT yet decided. `confirm`. Tapir summarizes transcript
text, so a capable general/instruct model on koala or iguana is the candidate — pick during the
build and record the choice (an ADR if it's load-bearing). Do not assume a coder alias is right
for prose summarization. The summarizer adapter does **not** hardcode an alias: it is config,
env `TAPIR_SUMMARIZER_MODEL` (format `host/name`, e.g. `iguana/deepseek-r1-14b`).
- **Which alias for summarization:** alias-as-config, **`confirm` resolved** (2026-06-02, Worker F).
The alias is never hardcoded: it is `TAPIR_SUMMARIZER_MODEL` (format `host/name`), wired through
the summarizer's `Endpoint.Model`. **Default: `koala/phi4-mini`** — a non-thinking instruct model
chosen for safety: it cannot fall into the empty-content trap below, so the demo summarizes even
if no one tunes it. It is provisional and overridable; **final live alias selection happens at
demo time when the gateway is reachable**, where a more capable model (e.g.
`iguana/deepseek-r1-14b`) is preferred for summary quality if its latency/output is acceptable.
The `max_tokens` fix below means thinking models no longer return empty content, so they are now
viable choices, not blocked ones. Do not assume a coder alias is right for prose.
- **Thinking models need an explicit `max_tokens`.** qwen3 / deepseek-r1 spend the budget on
reasoning and return **empty content** if `max_tokens` is too low (or unset). The summarizer's
parser treats an empty summary as an error for exactly this reason. When the alias resolves to a
thinking model, add a generous `max_tokens` to the copied `llm.Client` request (it currently
sends none — change Tapir's copy per ADR-004), or pick a non-thinking instruct model.
parser treats an empty summary as an error for exactly this reason. **Done (2026-06-02, Worker F):**
the copied `llm.Client` now sends a generous `max_tokens` (8192) on every request per ADR-004, so
thinking models no longer return empty content. A non-thinking instruct model remains the safe
default (`koala/phi4-mini`), but thinking aliases are now viable.
This maps directly onto the copied `llm` package: `Client` is the OpenAI-compatible caller,
`Router.Primary` points at this gateway with a chosen alias, `Router.Fallback` is the user's BYO.