Spaces:
Sleeping
Sleeping
|
Download AGENTS.md from lucashudsn/wavereader: direct link, hf CLI and curl.
- Browser
- Download file 6.92 kB
-
https://huggingface.co/spaces/lucashudsn/wavereader/resolve/main/AGENTS.md
- Command line
-
hf download hf://spaces/lucashudsn/wavereader/AGENTS.md
-
curl -L -o AGENTS.md https://huggingface.co/spaces/lucashudsn/wavereader/resolve/main/AGENTS.md
6.92 kB
A newer version of the Gradio SDK is available: 6.31.0
AGENTS.md
Guidance for AI coding agents working in this repo. The active surface is
app.py + ui/ + wavereader/ + data/ (the v2 rebuild). legacy/
holds the frozen v1 front end (main.py + app/) β don't extend it; it
survives only as the fallback layer in ui/_compat.py.
What is live now
app.pyβ v2 entrypoint:build()+gr.apitools +demo.launch(css=APP_CSS, mcp_server=True). Runuv run python app.py.ui/β the single-page front end (no tabs):app.py(layout + wiring, β€3gr.State; Bells Beach auto-selected on load so there are no empty states),panels/{lens,story,intel,agent}.py(map-lens column | forecast story | intel rail | full-width agent bar),charts/{strip,score,seafloor,climate,map,_style}.py,contracts.py(SELECT_KEYS/FETCH_KEYS/AGENT_KEYS+fill()β handlers return viafill(KEYS, β¦)so output ordering can't drift),_compat.py(backend access: v2 core βlegacy.app.*β stubs; also wetsuit hints, engine chips, surf cams),theme.py(APP_CSS, IBM Plex Mono lo-fi identity β don't restyle without asking).wavereader/β pure core, typed + tested, no Gradio imports:breaks.py(catalogue, memoizedload_breaks),openmeteo.py(versioned/atomic disk cache, seaward grid-snap),scoring.py(deterministic 0β10 engine β the LLM never owns numbers),seafloor.py(GEBCO world model),climate.py(ERA5 5-yr profiles + audit;break_climatereads the profile embedded on each break record, per-slug file fallback),tools.py(the typed tool functions shared by agent + MCP),agent.py(smolagentsToolCallingAgent, native tool calls, budget: 6 steps / 2 score_week / 700 tokens),narrate.py+llm.py(one InferenceClient factory: Nemotron 3 Ultra via deepinfra,WR_*env overrides).scripts/warm_caches.pyβ pre-fill forecast + seafloor caches (demo hot start).scripts/build_climate.pyβ climatology builder (re-embeds built profiles into the catalogue after each run, backup first).scripts/check_coords.py+scripts/check_coast.pyβ break-coordinate maintenance:check_coordsvalidates/fixes state/region/duplicate placement against OSM;check_coastaudits GEBCO elevation at every break point and (--fix) snaps non-coastal ones to the nearest 0 m shoreline crossing (both write a timestamped backup first).data/βaustralia-surf-breaks-enriched.json(238 breaks; each record embeds its ERA5 profile underclimateβ 236 of 238, the two duplicate Gnaraloo rows have no profile),surf-break-schema.json(contract),climate/*.json(per-slug ERA5 profiles βbuild_climate.pyoutput andbreak_climate's fallback; alsoindex.jsonmanifest),surf-cams.json(camera links keyed"name | state | region"),surf-break-example-bells.json(prompt worked example).
Deploying to HF Spaces
- The Space
lucashudsn/wavereader(public) is this repo β remotespace. Every push tomainauto-deploys via.github/workflows/deploy-space.yml(needs the GitHub repo secretHF_TOKEN) β merging to main ships it; no manual step. For any other branch, ship manually withscripts/deploy_space.sh [ref](builds a throwaway commit that prependsspace-config.yamltoREADME.mdand force-pushes it tospace:mainβ Spaces need YAML frontmatter, GitHub doesn't have to see it; the ref defaults to your current branch), thengit push origin <branch>to keep GitHub in sync. The Space builds from the pushed commit; watch Logs β Build on the Space page or pollHfApi().get_space_runtime("lucashudsn/wavereader")untilRUNNING. space-config.yamlis the Space config. Keepsdk_versionin lockstep with the gradio pin inrequirements.txt(regenerate that file only viauv export --no-hashes --format requirements-txt --no-dev -o requirements.txtβ other invocations can leave stray progress lines that break pip), andpython_versionin lockstep withpyproject.toml'srequires-python. If you change Space settings via the web UI, HF rewrites the Space'sREADME.mdβ mirror anything you care about back into the yaml.HF_TOKENis a Space secret (set once via Settings β Variables and secrets orHfApi().add_space_secret);WR_*overrides can be added the same way..cache/is ephemeral on the Space and rebuilds lazily β no persistent storage, no warm step.
Conventions that matter
- One spot drives everything:
selected(gr.State) is the single source of truth β picking a spot re-aims the map, badges, forecast strip, world model and climatology together. Keep it that way. - Staged spin-ups:
ui/panels/story.py::fetch_forecastis a generator that yields stage 1 (charts, ~ms) then stage 2 (seafloor world model from a parallel thread). Status lines name the engine + latency. Keep that pattern for anything slow. - Charts: theme through
ui/charts/_style.py::style_fig; weekend shading viaadd_weekend_shading. The week strip lives incharts/strip.py(score/swell/wind rows); window slicing (weekend/mornings/arvos) re-charts from state viafilter_hoursβ no refetch. Seafloor display is bicubically smoothed (scipy) and its wave animation is period-driven β smoothing and animation are display-only; stats stay on the raw grid. - MCP surface = exactly
score_week/rank_region_week/explain_score(gr.apiinapp.py). All event listeners are registered withapi_name=Falseβ keep it that way. - The LLM never owns numbers. Scores/forecasts/analysis stay deterministic; the model narrates and cites tools.
Data contracts
- Required break fields:
name,state,region,location,skillLevel,breakType,peakType,idealSwell,idealWind,idealTide. Optional:description,id,bestSeason,hazards,crowdFactor. Never invent enum values β checkdata/surf-break-schema.jsonfirst. - Canonical
state/regionalways come from the input list, never the model.location.countryis"Australia". - New prompts must load schema + example from
data/(don't paste copies).
Rules for edits
- Everything is tracked in this repo (no nested git β don't re-init one).
- Never commit
.env,.venv/,__pycache__/,.DS_Store,.cache/(all ignored). - Never read
.envor print secrets/tokens. Use.env.examplefor var names; check presence withprintenv HF_TOKEN | wc -cor[ -n "$HF_TOKEN" ]style checks that never echo the value. - Keep prompt files in
data/; keepapp.pyfree of embedded schema text. - Test cheaply:
uv run pytest -q(offline fixtures) +uv run python -c "import app"for import health. Live LLM calls cost inference β dry-run the agent via the injected fake model (tests/test_agent_dryrun.py) before any live turn.