Download docs/hosting-plan.md from Farshadm/beampilot: direct link, hf CLI and curl.
- Browser
- Download file 19.6 kB
-
https://huggingface.co/spaces/Farshadm/beampilot/resolve/main/docs/hosting-plan.md
- Command line
-
hf download hf://spaces/Farshadm/beampilot/docs/hosting-plan.md
-
curl -L -o hosting-plan.md https://huggingface.co/spaces/Farshadm/beampilot/resolve/main/docs/hosting-plan.md
A newer version of the Gradio SDK is available: 6.31.0
Hosting plan: BeamPilot demo on Hugging Face Spaces
Status: approved 31 Oct 2026, built on branch add-hosting. Decisions taken
by the maintainer:
- Plan: HF PRO, subscribed by the maintainer and kept until after the community-vote result on 16 Nov 2026.
- Lens replays: ship both: the v3 L5 run and the seed-920 smoke run, so five replay files in total.
- Delivery: upload with the
hfCLI (section 6).
Goal: a public URL where anyone can replay saved agent runs (no key needed) and, while the budget lasts, start live runs of the Muse Spark agent.
1. Platform: what the Hugging Face docs say (checked 31 Oct 2026)
| Topic | What the docs say | Source |
|---|---|---|
| Free CPU tier | CPU Basic (2 vCPU, 16 GB) has no hourly cost, but Gradio and Docker Spaces "require a paid plan to create" (PRO for personal accounts). Only static Spaces are free for everyone. | Spaces overview, GPU Spaces, CPU table note |
| Free-account exception | Free accounts in good standing (verified email, account older than 30 days) can host up to 2 Gradio Spaces on ZeroGPU. | ZeroGPU |
| PRO price | $9 per month; the list includes "Host ZeroGPU, Gradio & Docker Spaces". | Pricing |
| Sleep | A cpu-basic Space sleeps when inactive "currently, 48 hours"; the next visitor restarts it automatically. You can't change the sleep time on free hardware. |
GPU Spaces, sleep time |
| Secrets | Secrets are private. Their value can't be read back from the settings page, and they are not copied when someone duplicates the Space. The app sees them as environment variables (os.getenv). |
Spaces overview, secrets |
| Variables | Variables are public and are copied to duplicates. Use them for non-secret settings only. | same |
| Front matter | Keys in a YAML block at the top of README.md: title, emoji, colorFrom, colorTo, sdk, sdk_version, python_version, app_file, short_description, license, pinned, suggested_hardware. |
Config reference |
| Dependencies | requirements.txt is installed by the runtime; sdk_version sets the Gradio version. |
Gradio Spaces |
| Rebuild | Every new commit rebuilds and restarts the Space. | Spaces overview |
| Network | Outbound requests may use ports 80, 443 and 8080 only. The Meta Model API is HTTPS on port 443. | same |
| Git auth and large files | Push access needs a login (hf auth login, or a token in the git credential prompt). Binary files go through Git Xet. |
Repositories: getting started, Xet |
Verdict: the free CPU tier does not fit as asked. A free account can no longer create a Gradio Space on CPU Basic.
Alternative (recommended): HF PRO for one month ($9). Everything else in this
plan stays the same: Gradio SDK, cpu-basic, and the same secrets. Cancel after
the judging period.
Not recommended: ZeroGPU on a free account. ZeroGPU is built for functions that
use the @spaces.GPU decorator, and BeamPilot runs no GPU code. It would be an
untested misuse of GPU hardware, and the 30-day account-age rule may not be met.
Decision 1 (taken): PRO.
2. Replay without a key
Replay reads JSON files from docs/runs/ and calls no API. It works with no
secret set. Five files ship; three were already tracked:
| File | What it shows | Status |
|---|---|---|
docs/runs/mystery_s7.json |
Mystery beam (632.8 nm, MΒ² β 1.43) with a built-in laser power Γ3 fault: the agent met 6 saturated frames, lowered the exposure, and reached iso_compliant in 18 positions ($0.09). |
tracked |
docs/runs/clean_room_light_live.json |
Clean beam with a room-light fault added by the operator before measurement 6: +3 counts of background ($0.07). | tracked |
docs/runs/clean_operator_note.json |
Operator note ("stage blocked 60β80 mm") respected ($0.05). | tracked |
docs/runs/lens_v3_L5.json (byte-identical copy of runs/evaluation-v3/L5_agent.json) |
Lens run from the pre-registered v3 evaluation: the waist lies outside the stage; the agent inserts +750 mm at β20 mm and reaches iso_compliant with the back-calculated original beam ($0.12). |
added |
docs/runs/lens_smoke_s920.json (byte-identical copy of runs/20261031-183949_waist_outside_range_s920_muse-spark-1.2.json) |
Lens run, the change_lens smoke run before v3: +25 mm at β20 mm, iso_compliant ($0.13). |
added |
Decision 2 (taken): ship both lens runs.
Labels. Every replay is labelled on the page as "Recorded run, ,
muse-spark-1.2", both in the run list and above the replay, so that a visitor
never takes a replay for a live run. The model name comes from the file
(config.model).
The run files themselves hold no date. So the date comes from a small manifest,
docs/runs/recorded.csv (file, date, source of the date):
- the two lens runs: 31 Oct 2026, from the original file timestamps;
- the three older runs: 27 Oct 2026, the date of commit becabe2, which added them. Their original timestamped files are no longer kept.
A test checks that every replay file has a manifest entry. An uploaded file is labelled "Recorded run, date unknown, ".
Read-only checks done on all five candidates on 31 Oct:
- Searched for
C:\,Users,farsh, the maintainer's e-mail domain,MODEL_API_KEY,BASETEN,sk-,api_key,Bearer,.env: 0 matches in every file. - Searched for path-like strings (
X:\β¦,/home/β¦,/Users/β¦): none. - Top-level keys are only scenario/case, seed, positions, truth, scenario parameters, fault events, lens changes, tool log, config (model name and limits), operator note, stop reason, usage, cost, report and steps.
load_runandreplay_eventsload L5 (68 events), seed 920 (88) and mystery_s7 (59) without errors.
A new test (section 5) repeats this scan for every docs/runs/*.json file, so a
file added later can't leak a path or key.
3. Live runs: only with a secret, and capped
A live run is possible only when the Space secret MODEL_API_KEY is set and
the live switch is on. The protections:
| Protection | Today in app.py |
Planned |
|---|---|---|
| Queue concurrency | queue(default_concurrency_limit=2), MAX_CONCURRENT_RUNS = 2 |
1 live run at a time. Set concurrency_limit=1, concurrency_id="live" on the Start event only, and MAX_CONCURRENT_RUNS = 1. Replay events keep the default concurrency, so replay never waits behind a 15-minute live run. |
| Per-run caps | AgentConfig: $0.50, 1.5 M tokens and 60 model calls (lens: 80 calls, 28 positions); 15-minute timeout |
Normal runs unchanged. Live lens runs use the v3 limits: 80 model calls, 3 M tokens, $0.50 and 28 positions. |
| Per-tab caps | 3 runs and 2 M tokens per tab (convenience only) | 3 runs; 3 M tokens per tab, so that one lens run can use its full v3 token limit. |
| Process caps | 50 runs; BEAMPILOT_TOKEN_CAP (default 60 M tokens, about $20) |
unchanged, plus the spend cap below |
| Spend cap per restart | none | New env var BEAMPILOT_SPEND_CAP_USD, default 5. A thread-safe running total adds run.cost_usd after each run. A run starts only if spent + $0.55 (the per-run cap plus one call of overshoot) β€ cap. So the cap cannot be exceeded, even by the last run. |
| Live switch | none | New env var BEAMPILOT_LIVE_RUNS (on/off, default on so local use is unchanged). On the Space it is a public Variable. Setting it to off turns live runs off without a code push. |
| Clear messages | a "needs MODEL_API_KEY" text, shown only after Start is clicked | A banner when the page loads, and the Start button disabled, in three cases (checked in this order): switched off ("Live runs are switched off on this demo right now. Replay works."), no key ("Live runs are not set up on this demo (no MODEL_API_KEY). Replay works without one."), budget used ("This demo has used its live-run budget for now; use Replay."). The server-side check stays the real guard; the banner is only information. |
Caveat: the $5 budget counter lives in process memory. It resets on every restart: a push, a settings change, or waking from sleep after 48 h. Visitors can't force a restart, but the cap is per restart, not lifetime. A typical live run costs $0.05β0.13, so $5 is roughly 40β100 runs. If the Meta Model API console offers a spending limit on the key, set it as a lifetime backstop (I have not checked whether it does).
Scope: all changes are in src/beampilot/app.py (the UI) and new files. The
agent, prompt and tools stay frozen. With change_lens off, nothing changes, so
the hash test still holds.
4. The key is never logged, printed or saved
- Where the key lives: only in the Space secret
MODEL_API_KEY.make_client()reads it from the environment; there is no.envon the Space. The UI never asks for a key. - What can leak today: nothing found. API errors are already shown by type and HTTP status only, never by message text.
app.pyandagent.pycontain noprintorloggingcalls. Run files store the model name and limits, not the client. - New test: set
MODEL_API_KEYto a sentinel string and run a live run against a fake client. Then assert the sentinel appears in none of: the saved run JSON, the UI outputs (log, report, messages), and the captured stdout and stderr. - Hard rules:
- no Gradio
debug=True; - no
show_error=True; - no
OPENAI_LOGvariable on the Space; - live run files stay on the Space's temporary disk (
runs/) and are not offered for download.
- no Gradio
- Baseten: the Baseten key is not set on the Space. The app uses only the Meta Model API.
5. Files needed
Space README
space/README.md. The GitHubREADME.mdgets no front matter. The deploy step copiesspace/README.mdoverREADME.mdin the exported folder only. The Space README has the front matter below, plus a few plain lines:- what the demo does;
- that all data is simulated;
- that replays need no key;
- a link to the GitHub repository.
--- title: BeamPilot emoji: π― colorFrom: indigo colorTo: blue sdk: gradio sdk_version: 6.30.0 python_version: "3.12" app_file: scripts/space_app.py short_description: Muse Spark agent measures laser MΒ² to ISO 11146 license: mit pinned: false suggested_hardware: cpu-basic ---A test reads
space/README.mdand checks the front matter against the project:sdk_versionequals the Gradio pin inpyproject.toml;app_fileexists;short_descriptionis at most 60 characters.
requirements.txt, pinned to the versions tested locally. Gradio is not listed, becausesdk_versionpins it (6.30.0, the same pin as thedemoextra).numpy==2.5.4 scipy==1.18.1 scikit-image==0.26.0 matplotlib==3.11.2 openai==3.38.0 python-dotenv==1.2.4A test checks that these names match
[project] dependenciesinpyproject.toml.Entry point
scripts/space_app.py(about 10 lines). It putssrc/onsys.pathand callsbeampilot.app.main(). This keeps the src layout and theREPO_ROOTlookup that findsdocs/runs/; a rootapp.pywould also work. The package is not pip-installed on the Space, because an installed copy would not finddocs/runs/.docs/runs/lens_v3_L5.json,docs/runs/lens_smoke_s920.json, anddocs/runs/recorded.csv: the two lens replays and the manifest of recording dates (section 2).Code and tests:
- the
app.pychanges from section 3 and the replay labels; - tests for the spend cap (fake costs), the live switch, the no-key banner, the key sentinel, the run-file scan and the requirement pins;
- the run-file scan looks for drive and home paths, e-mail addresses and key-like strings. It also looks for the local user name, home folder and git e-mail of whoever runs the tests, read at test time, so no personal data is written into the test;
- the new env vars added to
.env.exampleas comments (no values; Baseten entries untouched).
- the
README: a "Hosted demo" line with the Space URL, added after the first successful deploy.
6. Code delivery: a git remote is a problem, so upload instead
You asked for a separate git remote for the Space and a push of main. Two
problems block a plain push:
- History contains a binary file.
docs/figures/hero.png(330 kB) is stored as a plain git blob in commits 18397f1 and 6c1b414. Forum reports show the Hub rejects pushes that contain binary files not stored through Xet, and that removing the file from the latest commit is not enough. Examples: HF forum: push rejected due to binary files, an example error log. The fix would be rewriting history, which our rules forbid. - A new Space already has a first commit (
.gitattributes,README.md), created by the Hub. Pushingmainon top of it is not a fast-forward, so it would need a force push (forbidden) or a merge of the Space's commit intomain.
Recommended instead: upload a clean export of main with the hf CLI.
git archive mainexports exactly the committed files: no.env, noruns/, no.venv.hf uploadsends them as one new commit on top of the Space's first commit. That is no force push and no history rewrite. The CLI handles the PNG through Xet by itself.- GitHub stays the only git history. The Space is a deploy target.
Decision 3 (taken): upload with the hf CLI.
.gitattributes: the repository has none (checked 31 Oct 2026). So the
upload cannot overwrite the Space's own .gitattributes, which the Hub created
for Xet/LFS handling. The deploy command still passes
--exclude ".gitattributes", so that a file added later can't replace it.
7. Steps for the maintainer (browser and PowerShell)
I will not handle any token or password. Steps 1β4 are in the browser; steps 5β7 are in PowerShell, run by you.
Plan: subscribe to PRO (Decision 1), and keep it until after the vote result on 16 Nov: https://huggingface.co/subscribe/pro
Create the Space: https://huggingface.co/new-space. Settings:
- Owner: your user; name
beampilot; licence MIT; - SDK Gradio; hardware CPU Basic (free); visibility Public.
- Owner: your user; name
Add the secret and variables under the Space's Settings β Variables and secrets:
New secret
MODEL_API_KEY: paste the key there yourself.If the Meta Model API console allows a second key, create a dedicated key for the Space, and revoke it after judging; then the Space can never spend from your main key. (Unverified whether the console allows a second key.)
New variable
BEAMPILOT_LIVE_RUNS=offfor the first deploy. Turn it on after the replay check.New variable
BEAMPILOT_SPEND_CAP_USD=5.
Create a write token at https://huggingface.co/settings/tokens. Choose Fine-grained, with write access to this one Space only.
Install the
hfCLI in its own tools venv (not in the project venv):py -3.12 -m venv C:\dev\hf-tools C:\dev\hf-tools\Scripts\python.exe -m pip install -U huggingface_hub C:\dev\hf-tools\Scripts\hf.exe auth loginhf auth loginasks for the token in a hidden prompt; paste it there. Answer n to "Add token as git credential?" (we don't push with git).Deploy main (replace
<HF_USER>; run fromC:\dev\beampiloton a clean, up-to-datemain):git switch main git status git pull Remove-Item -Recurse -Force "$env:TEMP\beampilot-space" -ErrorAction SilentlyContinue git archive --format=zip -o "$env:TEMP\beampilot-space.zip" main Expand-Archive "$env:TEMP\beampilot-space.zip" -DestinationPath "$env:TEMP\beampilot-space" -Force Copy-Item "$env:TEMP\beampilot-space\space\README.md" "$env:TEMP\beampilot-space\README.md" -Force C:\dev\hf-tools\Scripts\hf.exe upload <HF_USER>/beampilot "$env:TEMP\beampilot-space" . --repo-type space --exclude ".gitattributes" --commit-message "Deploy main $(git rev-parse --short main)"What each line does:
git switch main: switch tomain.git status: check there are no local changes.git pull: fetch the latestmainfrom GitHub.Remove-Item: delete the previous export.git archive: export the committed files ofmain(no.env, noruns/) as a zip.Expand-Archive: unzip it.Copy-Item: put the Space README, with its front matter, in place of the GitHub README.hf upload: upload the folder as one commit to the Space, keeping the Space's own.gitattributes.
The Space builds and restarts. Watch the Logs tab on the Space page.
Later deploys: repeat step 6. Files deleted from
mainare not deleted on the Space by an upload; remove them in the Space's Files tab, if any.Optional:
C:\dev\hf-tools\Scripts\hf.exe auth logoutwhen done; revoke the token after the hackathon.
8. Dry run on the Space (after the first deploy)
- With
BEAMPILOT_LIVE_RUNS=off, check:- the banner says live runs are off;
- the Start button is disabled;
- all five replays play, each labelled "Recorded run, , muse-spark-1.2", including both lens runs with their segment plots.
- Search the build and run logs for the first characters of the key; there should be no match. Check by eye, and never paste the key anywhere.
- Set
BEAMPILOT_LIVE_RUNS=onand do one live run (about $0.05β0.13).- Check that a second tab queues instead of running in parallel.
- Check the cost line in the report.
- Temporarily set
BEAMPILOT_SPEND_CAP_USD=0.3and confirm that the budget message appears; then set it back to 5. - Record the Space URL in the README (one commit), then upload again.
9. Time estimate
| Work | Who | Time |
|---|---|---|
| Code: switch, spend cap, concurrency, banner, entry point, requirements, front matter, lens replay file | Claude | 1.5 h |
| Tests (section 4β5) and the ruff/pytest gate, small commits on a branch | Claude | 1 h |
| Browser steps 1β4 and CLI steps 5β6 | maintainer | 20β30 min |
| First build, dry run (section 8), fixes | both | 1 h |
| Buffer for Space-specific surprises | β | 1 h |
| Total | about 4.5β5 h; API cost β€ $1 for the dry run |
This fits comfortably before the deadline (Wed 4 Nov, 21:00 ET), leaving the video script as the next step.