Onboarding follows the vision provider

The wizard's fresh config.toml now carries both [vision.*] blocks, and
its credential pass reads the ACTIVE provider before prompting: an
anthropic setup asks for ANTHROPIC_API_KEY as before, a keyed
openai-compatible endpoint asks for its configured key_env instead,
and a keyless local runtime says so and asks for nothing. Doc sweep
for the same: README's stage list and knobs line, CLAUDE.md's config
summary (which still claimed username lived there), the Help flow's
"Claude vision" wording, and .env.example's ANTHROPIC_API_KEY note.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016jXZFSTZQKzAC8fqpWSz9g
This commit is contained in:
Eric Wagoner
2026-08-03 18:48:22 -04:00
co-authored by Claude Fable 5
parent 118503e4e0
commit 15d3120029
6 changed files with 89 additions and 6 deletions
+40 -2
View File
@@ -28,8 +28,22 @@ CONFIG_TEMPLATE = """\
photos_dir = "photos"
data_dir = "data"
model = "claude-sonnet-5"
rate_limit_seconds = 2.0
# Which vision backend reads your shelf photos. Both recipes below stay
# on file; this line picks one.
vision_provider = "anthropic"
[vision.anthropic]
# reads ANTHROPIC_API_KEY from the environment
model = "claude-sonnet-5"
[vision."openai-compatible"]
# OpenAI, OpenRouter, or a local runtime (Ollama, LM Studio, vLLM).
# key_env names the env var holding the key; "" = endpoint needs none.
base_url = "http://localhost:11434/v1"
model = "qwen2.5vl:7b"
key_env = ""
"""
ENV_HEADER = """\
@@ -159,9 +173,33 @@ def run_init(
typer.echo(f" found {config_path}")
# -- credentials ----------------------------------------------------
# the vision key follows the configured provider: an openai-compatible
# setup prompts for ITS key env (or none, for a local endpoint)
from bggpipe.config import load_config
active = load_config(config_path if config_path.exists() else None)
env_keys = list(ENV_KEYS)
if active.vision_provider != "anthropic":
env_keys = [k for k in env_keys if k[0] != "ANTHROPIC_API_KEY"]
if active.vision_key_env:
env_keys.insert(
0,
(
active.vision_key_env,
True,
"vision extraction via "
+ (active.vision_base_url or "the configured endpoint"),
"your vision provider's console",
),
)
else:
typer.echo(
" vision: openai-compatible endpoint with no key configured "
"(local runtime) — nothing to prompt for"
)
env_path = project_dir / ".env"
in_file = _env_file_keys(env_path)
for key, secret, why, where in ENV_KEYS:
for key, secret, why, where in env_keys:
if os.environ.get(key) or key in in_file:
report.keys_ready.append(key)
typer.echo(f" {key}: set")
+1 -1
View File
@@ -12,7 +12,7 @@
<div class="card prose">
<p>Six pipeline stages and two checkpoints that are yours. Stages run from the <a href="/">Pipeline</a> page (or the CLI — both share all state and either can pick up where the other left off):</p>
<ol>
<li><b>extract</b> — every photo goes to Claude vision once; what it reads (titles plus edition cues: publisher, edition wording, year, language) lands on the Titles page. Boxes it can see but can't read become <b>reshoot tickets</b> on the Photos page.</li>
<li><b>extract</b> — every photo goes to the vision model once (Claude by default; a local model works too — see the README); what it reads (titles plus edition cues: publisher, edition wording, year, language) lands on the Titles page. Boxes it can see but can't read become <b>reshoot tickets</b> on the Photos page.</li>
<li><b>proofread</b> <i>(you, on <a href="/titles">Titles</a>)</i> — fix misread titles, add cues you know, split multi-box lines, remove non-games, <a href="#curation">details below</a>. Worth doing <i>before</i> resolve: a fix made now is one BGG search done right; a fix made later sends the title back through resolve again.</li>
<li><b>resolve</b> — titles are matched to BoardGameGeek games and editions. Anything uncertain is flagged, never guessed. Without a BGG API token, titles wait as <i>awaiting BGG</i> and are picked up automatically once the token exists.</li>
<li><b>review</b> <i>(you, on <a href="/review">Review</a>)</i> — decide the flagged ones: which game, which edition, whether two reads are one box. Every decision saves immediately.</li>