Repository navigation
v2.1.0
What changed
Features
set_model+ ask-once gate (AGY_ASK_MODEL, default on). On first use the server asks the user through MCP elicitation — "Proceed with the default — Gemini 3.8 Flash (High) at high effort — or change?" with model and effort pickers. Accept unchanged records the default; decline delegates nothing. Saved to~/.config/claude-agy-mcp/preferences.json, shared by every client on the machine, asked once. Clients without elicitation get the same question as error text and callset_model(no args = default). Fan-out is gated too.- Gemini Flash High leads every chain.
deep_search/web_lookupfall back to Medium; review and council tools to Pro then Claude.
Fixes
--effortwas rejected by agy 1.2.1 for every tiered model name, so every tool that set its own tier failed with "invalid model selection". Effort now selects the sibling tier (Flash (High)+medium→Flash (Medium));--effortonly reaches untiered models. Tools no longer carry a separate effort.- README claimed
--mode planproved a run changed nothing. Verified false on agy 1.2.1 with the bypass on (agy wrote a file in plan mode, with and without slash-command expansion); without the bypass headless agy denies evenread_fileand returns empty. Docs now say what the grant means.
Hardening (from an agy review of this branch, each with a test)
- stream-json envelopes were never parsed. Every run with a progress token (Claude Code always sends one) got raw NDJSON back as the answer, zero usage, no denied actions, no structured output, and a conversation id from the shared cache file. Text-mode output is no longer scanned for an envelope either, so a JSON line in a plain answer cannot forge one.
- Effort applies to the primary model only. Re-tiering the whole chain turned the
Flash (Medium)fallback back into theFlash (High)that had just 429'd; cooldowns were keyed on the pre-tier name. - Resident sessions are bounded by the run timeout and cancellation (a stalled turn held its admission slot forever), run cold when the call pins a model/effort or writes, carry the delegation-depth env, respect
warmMaxwhen every session is busy, read onclosenotexit, and record per-turn usage — agy reports the conversation's running total on every result (verified on 1.2.1), which compounded the budget. - Runner gives a killed child a bounded chance to exit before taking its output and removing its log. Cooldown file saves merge across processes and keep entries in memory when the cache dir is read-only. Elicitation is offered only to form-capable clients. Progress notifications no longer become unhandled rejections.
AGY_ALLOWED_ROOTSuses the platform delimiter and follows symlinks. Fan-out with every leg failed gets the strict-mode note.CapabilityCacheand the unused per-tooleffortfield are gone.
Chores
- CI's test job hung for hours: the cooldown-store test used
/proc/nope/nopeas an unwritable dir, and on Linux Node's recursive mkdir loops forever under procfs. It now uses a regular file in the directory's place. - Lockfile refreshed past hono, fast-uri, qs advisories (supersedes #28). Deps to zod 4.6.2, lint-staged 17.5.1, @types/node 26.5.1, vitest 5 (supersedes #29).
- README: CI/npm-version/node/license badges removed, remaining badges flat; screenshot of the form added.
Also carries the JSON-envelope hardening this branch started with.