feat: add cloud-based LLM support and robust error recovery - #41
Open
amaynez wants to merge 1 commit into
Open
Conversation
nocode-ananas
added a commit
to nocode-ananas/polylop
that referenced
this pull request
Jun 6, 2026
…kept FAST patch, kept 24h timeout, kept ollama out of compose)
nocode-ananas
added a commit
to nocode-ananas/polylop
that referenced
this pull request
Jul 24, 2026
…j connection guards, 0-entities => FAILED - llm_client.py: retry loop (429/5xx, Retry-After, exp. backoff 2-60s) merged onto Polylop base (24h timeout, JSON repair, for_graph_extraction kept) - neo4j_storage.py: health_check + _verify_connection guards, louder embedding-failure log - api/graph.py: build task with 0 extracted entities now marked FAILED instead of completed - embedding_service.py part of PR nikmcfly#50 NOT taken: Polylop already has the better implementation (Bearer token + index sort) from PR nikmcfly#41 backport - verified: 4 fault-injection tests in container (retry, exhaustion, non-retryable, backoff timing)
nocode-ananas
added a commit
to nocode-ananas/polylop
that referenced
this pull request
Jul 24, 2026
Fixes the simulation lifecycle bugs from the 2026-06-13 audit (section B). No upstream PR covers these — nikmcfly nikmcfly#30/nikmcfly#41/nikmcfly#50/nikmcfly#51 are already backported and address other areas. Every finding was reproduced against the unpatched code before fixing, using backend/tests/test_simulation_lifecycle.py: 11/31 checks pass on the baseline, 31/31 with this patch. Stop had no effect on reconnected simulations stop_simulation only ever looked at cls._processes, which is empty after a backend restart. The status flipped to 'stopped' while the process kept running — and kept calling the LLM API, costing real money. Added a PID-based termination path (SIGTERM, then SIGKILL) for simulations we have no Popen handle for. Manually stopped runs were reported as failed/completed The monitor thread woke up to the SIGTERM exit code and overwrote the stop with 'failed'; the orphan monitor could report 'completed'. An explicit stop is now recorded and wins over the exit-code verdict. stop_simulation also waits for the monitor instead of racing it. Double start was possible Nothing serialized check-and-spawn, so concurrent /start requests (the axios interceptor retries POSTs up to 3x) each spawned a process into the same directory. Added a per-simulation lock, and a liveness check so a start is refused while the real process is alive even if the status file claims otherwise. state.json and run_state.json drifted apart Nothing wrote the terminal status into state.json when a simulation ended on its own, so finished runs kept showing as running (live: sim_cb2ebb78e07a, run_state 'completed' vs state.json 'running'). The runner now mirrors its terminal status into state.json through one shared, atomic writer. /stop records STOPPED instead of PAUSED — the process is terminated, not suspended, no view renders 'paused', and PAUSED overwrote the runner's own status. PID reuse could adopt an unrelated process os.kill(pid, 0) only proves some process holds that PID. The start command line is now recorded and verified before a process is adopted or signalled; an unverifiable PID closes the run instead of hanging it on 'running' forever. psutil is not in the runtime image, so this is stdlib only (/proc, with a ps fallback for macOS). Also in this change - run_state.json is written atomically; concurrent readers used to see truncated JSON (40008 corrupted reads in a 2s test on the old code) - a 'running' state with no PID no longer hangs forever on reconnect - failed runs get a completed_at timestamp like every other terminal state - the orphan reconnect is skipped in the Flask reloader's parent process: with DEBUG on, create_app runs twice, and two monitor threads in two processes were writing the same run_state.json Not touched on purpose: FLASK_HOST/DEBUG/NEO4J_PASSWORD hardening, declined 2026-07-15. The reloader guard above makes the lifecycle robust against debug mode instead of turning it off.
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.
This pull request introduces comprehensive support for cloud-based LLM providers like OpenRouter, significantly expanding the accessibility of MiroFish-Offline.
The primary objective of these changes is to democratize access to the platform. By allowing users to offload the heavy lifting of model inference to cloud providers, we enable participation from a much broader user base. This includes individuals who lack the high performance hardware typically required for sufficiently intelligent local inference.
Key Enhancements:
By incorporating these changes, the project transitions from a hardware-dependent tool to a versatile platform that adapts to the user's environment. This strategy not only increases the potential user base but also improves the overall reliability and professional polish of the codebase.