fix: Windows compatibility (claude-cli provider, rapidfuzz wheel) and interview batch timeout - #26
Open
jcartagenamartinez-legaltech wants to merge 5 commits into
Conversation
Two issues prevented the claude-cli LLM provider from running on
Windows:
- cwd="/tmp" is a POSIX-only path; on Windows this raises
WinError 267 (invalid directory name). Replaced with
tempfile.gettempdir() for both the claude and codex subprocess
calls, which resolves correctly on all platforms.
- The prompt was passed as a trailing argv element
(["claude", "-p", "--output-format", "json", prompt]). Large
prompts (tens of KB, common once a few input files are attached)
exceed Windows' command-line length limit and raise
WinError 206 ("filename or extension is too long"). Passing the
prompt via stdin instead removes this ceiling. Bumped the
subprocess timeout from 300s to 600s to give slower/CLI-based
providers headroom, and set encoding="utf-8", errors="replace"
explicitly since Windows' default locale encoding (cp1252) was
raising UnicodeDecodeError on non-ASCII input/output.
Tested on Windows 11 running full simulations (100+ agents,
15 rounds) end to end with LLM_PROVIDER=claude-cli.
rapidfuzz's latest release at time of writing (3.14.4) has no win_amd64 wheel published, which makes `uv sync` fail outright on Windows (no sdist build toolchain assumed). Overriding to 3.13.0, the latest version with a Windows wheel, unblocks installation. This can be relaxed/removed once upstream publishes Windows wheels for a newer version again.
interview_agents() (used by the report generator to interview the top N most-active agents post-simulation) sends a batch IPC command with a hardcoded 180s timeout covering up to N agents x 2 platforms of individual LLM interview calls. With CLI-based LLM providers this was consistently timing out with 0/N successful interviews on runs with 100+ agent profiles, even though the simulation itself completed normally — the report would silently fall back to "(no interview data)" since the failure is caught as non-fatal by the caller. 180s doesn't leave enough headroom when each individual call can legitimately take up to the LLM client's own per-call ceiling (600s in llm_client.py, e.g. for claude-cli subprocess spawns). Raised to match that ceiling.
Addresses self-review findings on the original three commits: - Single CLI_CALL_TIMEOUT_SECONDS constant governs both providers and every timeout error message (the claude handler still said "300s" after the ceiling moved to 600; codex was left at 180 with no encoding handling — same cp1252 hazards the claude path already fixed). - Interview batch budget now scales with the batch instead of a flat 600s: one full per-call ceiling per interviewed agent. A fixed budget equals the worst case of a single call and still starves multi-agent batches. - rapidfuzz override scoped with sys_platform == 'win32' marker so macOS/Linux keep the resolver's pick; pyproject now documents why the pin exists and when to drop it (the missing wheels are specifically Windows cp312, not all of win_amd64). - Provider binaries resolved via shutil.which for a clear early error when the CLI is missing (and to tolerate npm-style .cmd shims on Windows). - Warn when undecodable bytes were replaced with U+FFFD instead of corrupting output silently. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
jcartagenamartinez-legaltech
added a commit
to jcartagenamartinez-legaltech/mirofish-cli
that referenced
this pull request
Jul 19, 2026
- Document the ExecutionPolicy Bypass invocation (stock Windows blocks .ps1 execution outright — it is the first command the target user will run) in both the script header and the README. - Fail fast with a clear message when stdin is not interactive and --yes/-Yes was not passed, instead of dying on EOF at the uv prompt. - On Windows, explain the known uv sync failure mode (rapidfuzz >=3.14 without cp312 wheels, fix proposed in amadad#26) and its workaround (uv python pin 3.11) instead of a bare "failed". - Read .env back with the same BOM-less UTF-8 used to write it (Get-Content -Raw on PS 5.1 decodes BOM-less files as ANSI and would corrupt non-ASCII values on the read-modify-write cycle). - Gate ANSI colors on a real TTY and honor NO_COLOR; replace the fragile grep-the-header --help with an explicit usage() heredoc. - Show the claude CLI version on Windows too (parity with setup.sh). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Author
|
Pushed a hardening commit after running an adversarial review pass over my own diff (multi-agent panel + manual verification):
Happy to split or adjust anything. |
This was referenced Jul 19, 2026
- LLMTimeoutError (RuntimeError subclass) raised on TimeoutExpired and excluded from the x3 retry loop: a prompt that exhausts the 600s ceiling will almost certainly exhaust it again, so retrying turned one slow call into ~30 minutes of blocked wall clock. - _resolve_cli cached with lru_cache: the binary does not move during the process lifetime, so the per-request PATH scan was waste. (Failures are not cached: lru_cache does not memoize exceptions.) 🤖 Generated with [Claude Code](https://claude.com/claude-code)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Three independent fixes discovered while running MiroFish end-to-end on
Windows 11 for a real investor-facing market simulation suite (multiple
runs, 100-185 agents each,
LLM_PROVIDER=claude-cli):claude-cliprovider (app/utils/llm_client.py):cwd="/tmp"is POSIX-only and raisesWinError 267on Windows. Fixed withtempfile.gettempdir().Windows' command-line length limit once a few input files are attached
(
WinError 206, "filename or extension is too long"). Fixed by passingthe prompt via stdin instead. Also bumped the subprocess timeout
300s → 600s and pinned
encoding="utf-8", errors="replace"(Windows'default locale encoding, cp1252, was raising
UnicodeDecodeErroronnon-ASCII content).
rapidfuzzWindows wheel (pyproject.toml/uv.lock): the resolvedversion (3.14.4) has no
win_amd64wheel, souv syncfails outright onWindows. Pinned via
[tool.uv] override-dependenciesto 3.13.0, the lastversion with a Windows wheel.
app/services/graph_tools.py): thepost-simulation interview step (
interview_agents, used by the reportgenerator) hardcoded a 180s timeout for a batch of up to 5 agents × 2
platforms of individual LLM calls. With CLI-based providers this
consistently produced 0/N successful interviews — even on otherwise
healthy runs — because the failure is swallowed as non-fatal and the
report silently falls back to no interview data. Raised to 600s to match
the LLM client's own per-call ceiling.
Why this matters
Without these three fixes, MiroFish does not run at all on Windows with the
claude-cliprovider (setup fails atuv sync, then every LLM call failswith
WinError 267/206), and even once running, the interview step ofevery report silently produces no data.
Testing
Ran the full pipeline (
mirofish run --files ... --requirement ... --platform parallel --max-rounds 15) end to end on Windows 11 across severalsimulations (100–185 agent profiles each), producing complete
verdict.json/report.md/visuals, and confirmed the interview step nowreturns non-empty results after the timeout fix (previously 0/N on every
affected run).
Scope / non-goals
Kept intentionally minimal and surgical — no refactors, no new
abstractions, no behavior change on non-Windows platforms beyond the
(strictly larger) timeouts.
🤖 Generated with Claude Code