feat: browser WASM execution (phases 1+2 of 3)#57
Open
samuelduchesne wants to merge 5 commits into
Open
Conversation
…ecution) Accept pre-computed EnergyPlus artifacts (eplusout.sql and friends) via a new MCP tool and materialize them into state.simulation_result via the existing SimulationResult.from_directory factory. Every idfkit://simulation/* resource and every analysis tool (query_timeseries, query_simulation_table, analyze_peak_loads, view_simulation_report) now reads the uploaded run transparently — no contract changes downstream. This is the foundation for running EnergyPlus in the browser via WASM: phase 2 will wrap the idfkit-app WASM runtime behind an embeddable JS API, phase 3 will register ui://idfkit/simulator.html and wire the iframe's tools/call back to upload_simulation_result. Covered by a pytest subprocess harness that spins up the server in streamable-HTTP mode on a free port and exercises the full round-trip (upload → read resource) to validate mcp-session-id affinity. Adds `make serve-http` for manual smoke testing. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…xecution) Ship the iframe that executes EnergyPlus in the browser and posts outputs back through upload_simulation_result, closing the loop that phase 1 set up server-side. - New tool run_simulation_in_browser serializes the pre-flighted IDF + EPW and hands them to the companion UI resource ui://idfkit/simulator.html. - New tool fetch_energyplus_asset pages the WASM glue / binary / IDD / datasets back to the iframe via the MCP Apps SDK tool channel, sidestepping cross-origin fetch restrictions in sandboxed MCP App iframes. Supports offset/chunk_size for byte-level progress. - New tool get_results_summary surfaces idfkit://simulation/results as a callable tool for agents whose clients do not autonomously read resources. - EnergyPlus WASM bundle ships inside the wheel via hatchling force-include (build artifact populated by make sync-wasm-assets or the Dockerfile assets stage). - upload_simulation_result no longer requires eplusout.sql so failed runs can still upload diagnostic artifacts. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Contributor
|
Docs preview for this PR is available at: |
Drops the hardcoded `energyplus.js-26.1.wasm` entry in the asset allowlist. The next envelop rebuild against a newer EnergyPlus release would have emitted a differently-named .wasm and produced an opaque "not in the allowlist" error with no path forward. - `fetch_energyplus_asset` now builds its allowlist by scanning the installed assets directory through a narrow set of globs (`energyplus.js`, `energyplus*.wasm`, `Energy+.idd`, `datasets/*.idf`). Attack surface unchanged; future version bumps work without edits. - `run_simulation_in_browser` passes `wasm_candidates` through the handoff so the iframe can't drift from what's actually on disk. The iframe keeps a static fallback list for older handoff shapes. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
run_simulation and upload_simulation_result include a sample of severe and warning messages capped at 10 to keep tool responses small. UIs had to compare array length against the total count to know whether the sample was complete, leading to displays like "10 Warning" next to "258 warnings" with no explanation. Add severe_messages_truncated / warning_messages_truncated to SimulationErrorDetail and severe_messages_truncated to GetResultsSummaryResult so consumers can render "10 of 258 shown" without inferring the cap. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This reverts commit 4fa6715.
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
Completes phases 1 + 2 of the browser-side EnergyPlus execution work. Clients that can render MCP App iframes (e.g. Claude Desktop) can now run a design-day or small-annual EnergyPlus simulation entirely in the browser via the bundled WASM build, with the server only ingesting the output artifacts.
upload_simulation_resultaccepts pre-computed EnergyPlus artifacts and makes them visible through everyidfkit://simulation/*resource.run_simulation_in_browserhandoff tool: serializes the pre-flighted IDF + EPW into_meta.browser_runfor the companion UI resource.ui://idfkit/simulator.html(newsimulator_viewer.py): self-contained iframe that loads the EnergyPlus WASM build, runs the simulation, and posts outputs back throughupload_simulation_result.fetch_energyplus_asset(paginated viaoffset/chunk_size): proxies WASM glue / binary / IDD / datasets through the MCP Apps SDK tool channel, sidestepping the cross-origin/CSP/mixed-content restrictions that block direct HTTP fetch from sandboxed MCP App iframes. Drives byte-level progress in the iframe.get_results_summarytool: wraps the existingidfkit://simulation/resultsresource so agents whose clients don't autonomously read resources can still pull QA diagnostics.upload_simulation_resultno longer requireseplusout.sql— failed browser runs uploadeplusout.errso the server can still surface the fatal.make sync-wasm-assetscopiesenvelop/public/energyplus/intosrc/idfkit_mcp/assets/energyplus/, hatchlingforce-includeships it inside the wheel, the Dockerfile pulls it from the monorepo build context. Env varIDFKIT_MCP_ENERGYPLUS_DIRlets deployments mirror assets elsewhere.Architecture notes
fetch(). Every asset and every round-trip goes through the MCP Apps SDK'scallServerTool, which means there is no CORS, CSP, or mixed-content path to negotiate with — tunnels, localhost, and remote connectors all behave the same.feat/energyplus-wasm-executionvianpx mcp-remote http://127.0.0.1:8000/mcp/.Test plan
make checkgreen (ruff, pyright strict onsrc/, deptry).make testgreen — 243 tests passing, including:tests/test_run_simulation_in_browser.py: handoff shape, pre-flight on a copy, EPW encoding, version resolution, simulation-lock rejection, unreadable-weather handling,fetch_energyplus_assetallowlist + chunking + offset-past-EOF, asset route 503/404 + CORS.tests/test_upload_simulation_result.py: updated — missing SQL is now accepted with a fatal-onlyerrpayload; emptyfilesis rejected.make sync-wasm-assets && make serve-http; curl/assets/energyplus/*returns the expected WASM / IDD / datasets withAccess-Control-Allow-Origin: *; traversal returns 404; missing-sync returns 503.run_simulation_in_browser→ iframe fetches ~30 MB WASM with visible progress →callMainruns →upload_simulation_resultpopulatesidfkit://simulation/resultson the same session.🤖 Generated with Claude Code