Skip to content

feat: pin a template's model and reasoning for every box - #51

Merged
OndrejDrapalik merged 3 commits into
mainfrom
feat/template-model-reasoning
Sep 8, 2026
Merged

OndrejDrapalik merged 3 commits into
mainfrom
feat/template-model-reasoning

Conversation

@OndrejDrapalik

Copy link
Copy Markdown
Collaborator

Summary

One knob per template, applied to every box booted from it (open, fleet, run):

[templates.opencode]
model = "openrouter/qwen/qwen3.8-max-0902"
[templates.codex]
model = "gpt-5.4"
reasoning = "high"

Why: every harness has a default model and a TUI to change it, and a box has nobody at the TUI. Left alone an agent runs whatever its provider ranks first; an opencode member on an OpenRouter key came up on Nano Banana Pro, an image model with no tool use (live, 2026-09-08). Pinning it in the launch command has to be repeated in [fleet.agents] and [run.agents], and a plain e2b-box open followed by typing opencode gets neither. So the pin goes where each harness reads its defaults, and the launch commands stay untouched.

src/model-pin.js owns the per-harness knowledge, verified against each vendor's docs or a file the CLI wrote itself:

template route model reasoning
claude env ANTHROPIC_MODEL CLAUDE_CODE_EFFORT_LEVEL
opencode env OPENCODE_CONFIG_CONTENT (inline JSON {"model": …}) not pinned (per-model variants)
codex file ~/.codex/config.toml model model_reasoning_effort
grok file ~/.grok/config.toml [models] default default_reasoning_effort
droid file ~/.factory/settings.json model reasoningEffort
prime file ~/.prime/agent/settings.json defaultProvider + defaultModel (split at the first /) defaultThinkingLevel
muse file not pinned (no verified key; reported) ~/.config/muse/settings.json reasoning_effort
amp none amp has no model setting, --mode is its knob
  • modelEnv: the env-route variables plus HERDR_E2B_MODEL / HERDR_E2B_REASONING on every pinned box, merged into resolveEnv below the user's own [templates.<name>.env] (a hand-written ANTHROPIC_MODEL still wins). The two shared variables are also the hook for a user's own launch command: mine --model "$HERDR_E2B_MODEL".
  • pinCommand: one-line commands with the seeds' rules (one line, variable names never values, never overwrite a key that is already set), run by provision.js right after the first-run seed. Codex keys are prepended so they sit above any [table]; grok only creates a [models] section when none exists.
  • Config: resolveEnvConfig reads model / reasoning per template into templateModels.
  • Docs: config.example.toml (per-harness table), README, docs/headless-run.md, ARCHITECTURE, CHANGELOG.

Test plan

  • node --test test/model-pin.test.js: 16 tests. The five file-route commands are executed with bash against fake homes: codex prepends and is idempotent, keys land above an existing table and a set key is untouched; grok creates [models] and leaves an existing one alone; droid merges without clobbering; prime splits prime-inference/z-ai/glm-5.2 at the first slash and keeps a bare id whole; muse pins reasoning and reports the model; no variables → nothing written
  • node --test test/config.test.js: templateModels parsing, the env rung, the user's env table winning
  • bash test/cli.test.sh: 322 passed
  • Live, EU: [templates.opencode] model = "openrouter/qwen/qwen3.8-max-0902" and no -m in any launch command → e2b-box run -t opencode banner build · qwen/qwen3.8-max-0902, file home, 15 s
  • Live, EU: [templates.codex] model = "gpt-5.4", reasoning = "low" → e2b-box up -t codex, box ~/.codex/config.toml reads model = "gpt-5.4" / model_reasoning_effort = "low" above the seeded trust table, HERDR_E2B_MODEL/REASONING present in the box env, re-running the pin says "already set - leaving it alone"
  • grok, droid, prime, muse file routes: executed in tests against fake homes, not yet on a live box

Notes

@cla-bot cla-bot Bot added the cla-signed label Sep 8, 2026
…easoning

# Conflicts:
#	ARCHITECTURE.md
#	CHANGELOG.md
#	test/config.test.js
@OndrejDrapalik
OndrejDrapalik merged commit a42ee39 into main Sep 8, 2026
12 checks passed
@OndrejDrapalik
OndrejDrapalik deleted the feat/template-model-reasoning branch September 8, 2026 20:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant