GPU service
A thin Modal worker wraps the LingBot runner.
The scaffold in `gpu/lingbot-map-modal/app.py` exposes `/scans`
for browser uploads, publishes `/health` with the source/model
contract, validates scan input, spawns a GPU reconstruction job,
records a receipt timeline, caches the public LingBot checkpoint,
can require a bearer token for expensive routes, serves finished
artifacts from a persistent volume, lets active jobs be cancelled,
lets completed scan data be deleted, can prewarm the checkpoint
before a first scan, stores room coverage metadata with each
receipt, returns rough GPU minute and cost estimates, enforces a
selected budget cap before GPU work starts, stores a selected
24-hour, 7-day, or 30-day retention window, and gives the browser
a shareable viewer URL with a per-scan read-only token in the
fragment plus a local QR, so a completed scan can be opened
without the expensive API token. Each run also publishes a worker
log link, and failed runs return the latest log tail in the
receipt. Expired receipts remain readable, but staged input and
generated artifacts are removed by the worker. The browser can
also run a protected runtime check against the worker image before
spending GPU time on a real house scan. Dry-run Preflight can run
first, but Generate 3D model waits for `Check runtime` to pass. A phone capture link carries
endpoint setup through the URL fragment, with a local QR code so
desktop configuration can move to the phone without sending the
token to the website server or a QR image service. The Preflight
button sends the same recorded walkthrough with
`dry_run=true`, so endpoint auth, upload staging, and rough cost
can be tested before a real GPU run; when the setup still
matches, Generate 3D model reuses that staged upload instead of
sending the video a second time. A real receipt is only marked
complete after the worker exports a browser-viewable GLB from
saved depth predictions and confirms `batch_results.json` did not
report failed scenes. The browser also sends an ordered capture route so the
receipt can preserve room steps, doorway count, and minimum
capture time; the route chips can be reordered before recording
so the path matches the real floor plan. In-page recordings are
saved as a browser-local 24-hour draft, capped at 256 MB, so a
phone refresh can recover the video before upload without storing
endpoint bearer tokens in the draft. Completed GLB scans open with
room context, camera presets, and a locally saved viewpoint for
returning to the same inspection angle. The browser keeps a local
recent-scan list with read-only viewer tokens so active,
completed, failed, cancelled, and held scan receipts can be
reopened later without saving the API token. The page and
terminal preflight/verify commands require the endpoint
`/health.source.ref` to match the pinned LingBot-Map ref before
uploads start.
npm run lingbot:gpu:auth
npm run lingbot:gpu:deploy
LINGBOT_ENDPOINT=https://YOUR-ENDPOINT.modal.run \
LINGBOT_API_TOKEN=YOUR_TOKEN \
npm run lingbot:gpu:accept -- \
--file ./walkthrough.mp4 \
--rooms entry,living,kitchen \
--route entry,living,kitchen \
--allow-low-quality
npm run lingbot:smoke -- --url https://www.matthoffner.com/lingbot-house-scan.html