@bitmagic/cli 0.1.53-dev.0 → 0.1.53-dev.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +130 -29
- package/dist/assets/revoxelize.d.ts +116 -0
- package/dist/assets/revoxelize.js +343 -0
- package/dist/assets/revoxelize.js.map +1 -0
- package/dist/cli.d.ts +27 -1
- package/dist/cli.js +18 -1
- package/dist/cli.js.map +1 -1
- package/dist/commands/assets.d.ts +18 -0
- package/dist/commands/assets.js +110 -1
- package/dist/commands/assets.js.map +1 -1
- package/dist/commands/cover.d.ts +5 -0
- package/dist/commands/cover.js +3 -0
- package/dist/commands/cover.js.map +1 -1
- package/dist/commands/dev.js +1 -2
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/forge.d.ts +4 -0
- package/dist/commands/forge.js +9 -0
- package/dist/commands/forge.js.map +1 -1
- package/dist/commands/generate.d.ts +25 -0
- package/dist/commands/generate.js +80 -8
- package/dist/commands/generate.js.map +1 -1
- package/dist/commands/init.d.ts +4 -0
- package/dist/commands/init.js +12 -1
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/publish.d.ts +31 -4
- package/dist/commands/publish.js +86 -15
- package/dist/commands/publish.js.map +1 -1
- package/dist/commands/reload.js +1 -3
- package/dist/commands/reload.js.map +1 -1
- package/dist/commands/reset-account.js +25 -8
- package/dist/commands/reset-account.js.map +1 -1
- package/dist/commands/self-update.d.ts +67 -0
- package/dist/commands/self-update.js +196 -0
- package/dist/commands/self-update.js.map +1 -0
- package/dist/commands/upgrade.js +5 -2
- package/dist/commands/upgrade.js.map +1 -1
- package/dist/editor/asset-detail-panel.d.ts +2 -2
- package/dist/editor/asset-detail-panel.js +5 -2
- package/dist/editor/asset-detail-panel.js.map +1 -1
- package/dist/editor/cli-update.d.ts +32 -0
- package/dist/editor/cli-update.js +67 -0
- package/dist/editor/cli-update.js.map +1 -0
- package/dist/editor/publish-panel.d.ts +31 -0
- package/dist/editor/publish-panel.js +69 -0
- package/dist/editor/publish-panel.js.map +1 -0
- package/dist/editor/server.js +43 -1
- package/dist/editor/server.js.map +1 -1
- package/dist/editor/shell-page.js +249 -8
- package/dist/editor/shell-page.js.map +1 -1
- package/dist/forge/upload-proxy.d.ts +14 -0
- package/dist/forge/upload-proxy.js +28 -1
- package/dist/forge/upload-proxy.js.map +1 -1
- package/dist/generate/model.d.ts +7 -0
- package/dist/generate/model.js +13 -3
- package/dist/generate/model.js.map +1 -1
- package/dist/generate/prop.d.ts +20 -0
- package/dist/generate/prop.js +22 -2
- package/dist/generate/prop.js.map +1 -1
- package/dist/generate/vehicle.d.ts +2 -0
- package/dist/generate/vehicle.js +1 -0
- package/dist/generate/vehicle.js.map +1 -1
- package/dist/project/dev-handle.d.ts +28 -0
- package/dist/project/dev-handle.js +43 -0
- package/dist/project/dev-handle.js.map +1 -1
- package/dist/project/jobs.js +11 -9
- package/dist/project/jobs.js.map +1 -1
- package/dist/publish/client.d.ts +13 -2
- package/dist/publish/client.js.map +1 -1
- package/dist/publish/record.d.ts +22 -0
- package/dist/publish/record.js +62 -0
- package/dist/publish/record.js.map +1 -0
- package/dist/render/qr-output.d.ts +44 -0
- package/dist/render/qr-output.js +71 -0
- package/dist/render/qr-output.js.map +1 -0
- package/dist/render/qr-png.d.ts +37 -0
- package/dist/render/qr-png.js +111 -0
- package/dist/render/qr-png.js.map +1 -0
- package/dist/render/qr-terminal.d.ts +63 -0
- package/dist/render/qr-terminal.js +142 -0
- package/dist/render/qr-terminal.js.map +1 -0
- package/dist/render/qr.d.ts +51 -0
- package/dist/render/qr.js +516 -0
- package/dist/render/qr.js.map +1 -0
- package/dist/scaffold/project-files.js +44 -27
- package/dist/scaffold/project-files.js.map +1 -1
- package/dist/scaffold/suggest-template.d.ts +2 -0
- package/dist/scaffold/suggest-template.js +2 -1
- package/dist/scaffold/suggest-template.js.map +1 -1
- package/dist/telemetry/command-context.d.ts +12 -0
- package/dist/telemetry/command-context.js +7 -0
- package/dist/telemetry/command-context.js.map +1 -1
- package/dist/telemetry/creator-prompt.d.ts +35 -0
- package/dist/telemetry/creator-prompt.js +45 -0
- package/dist/telemetry/creator-prompt.js.map +1 -0
- package/dist/update/check.js +2 -1
- package/dist/update/check.js.map +1 -1
- package/dist/update/notice.d.ts +31 -1
- package/dist/update/notice.js +39 -5
- package/dist/update/notice.js.map +1 -1
- package/dist/update/self-install.d.ts +175 -0
- package/dist/update/self-install.js +335 -0
- package/dist/update/self-install.js.map +1 -0
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -49,6 +49,9 @@ npm install -g @bitmagic/cli
|
|
|
49
49
|
bitmagic --version
|
|
50
50
|
```
|
|
51
51
|
|
|
52
|
+
That is the only time you need npm. From then on, `bitmagic self-update` updates the CLI — see
|
|
53
|
+
[Staying current](#staying-current) for why the npm line is the wrong tool for the second install.
|
|
54
|
+
|
|
52
55
|
### The dev line
|
|
53
56
|
|
|
54
57
|
```bash
|
|
@@ -61,9 +64,10 @@ installs the unreleased build the Bitmagic team and external testers run — a p
|
|
|
61
64
|
production, so a CLI that uses them has to be installable before it is released. Pair it with
|
|
62
65
|
`bitmagic login --env dev`.
|
|
63
66
|
|
|
64
|
-
`
|
|
65
|
-
single `bitmagic` on your PATH, so `bitmagic --version`
|
|
66
|
-
`-dev.N` suffix means the dev line. To have both at once,
|
|
67
|
+
`bitmagic self-update --tag latest` puts you back on the release at any time, and `--tag dev` takes
|
|
68
|
+
you the other way. One global install is a single `bitmagic` on your PATH, so `bitmagic --version`
|
|
69
|
+
is how you tell which line you are on: a `-dev.N` suffix means the dev line. To have both at once,
|
|
70
|
+
see below.
|
|
67
71
|
|
|
68
72
|
### Running both lines side by side
|
|
69
73
|
|
|
@@ -113,6 +117,11 @@ env=local
|
|
|
113
117
|
apiUrl=http://localhost:3102
|
|
114
118
|
```
|
|
115
119
|
|
|
120
|
+
`bitmagic self-update` works inside this setup unchanged: it reinstalls into the root the
|
|
121
|
+
`bitmagic` you just ran came from, with the same `--global-dir` and `--global-bin-dir`, so updating
|
|
122
|
+
from `dev-games/` cannot disturb the prod root. (Running `pnpm add -g` by hand would, unless you
|
|
123
|
+
repeat both flags.)
|
|
124
|
+
|
|
116
125
|
`direnv allow` each, and both halves are right in each tree:
|
|
117
126
|
|
|
118
127
|
```
|
|
@@ -184,11 +193,12 @@ browser reloads itself on every change and the assets panel shows each generatio
|
|
|
184
193
|
| `bitmagic whoami [--env <env>]` | Show the identity the CLI is authenticated as — the account's email address alongside its user id — and which environment answered, including where that environment was chosen from. |
|
|
185
194
|
| `bitmagic init [dir] [--template <id>] [--name <name>] [--idea "<pitch>"] [--env <env>] [--force]` | Scaffold a new project: mints a game, downloads the vendored engine, writes `AGENTS.md`, `GAME-DESIGN.md` and templates. Starts from `empty-3d` unless told otherwise. `--idea` seeds the design doc's pitch **and** picks the template whose camera and controls fit it — "a doom-like corridor shooter" scaffolds `first-person`, "jump between floating islands" scaffolds `sidescroller`. `--template` overrides both; a suggestion that fails for any reason falls back to `empty-3d` rather than failing the scaffold. Dependencies are installed with **pnpm** when your machine has it and npm otherwise — the lockfile that produces is what every later command reads, so it never tells you to run the wrong one. |
|
|
186
195
|
| `bitmagic check` | Typecheck (`tsc --noEmit`) against the vendored engine. Fast; does not prove the game runs. |
|
|
187
|
-
| `bitmagic dev [--port <port>] [--editor-port <port>] [--no-open]` | Build, then serve everything and keep it running: `tsc --watch`, `vite` on 3010, and a **Game / Editor** view on 3011 that reloads itself when the project changes. Opens the view in your browser; `--no-open` (or `BITMAGIC_NO_OPEN=1`) skips that. The one command to leave open. See **The dev view** below. |
|
|
196
|
+
| `bitmagic dev [--port <port>] [--editor-port <port>] [--no-open]` | Build, then serve everything and keep it running: `tsc --watch`, `vite` on 3010, and a **Game / Editor** view on 3011 that reloads itself when the project changes, and shows where the game is published (with a QR code) once it has been. Opens the view in your browser; `--no-open` (or `BITMAGIC_NO_OPEN=1`) skips that. The one command to leave open. See **The dev view** below. |
|
|
188
197
|
| `bitmagic reload [--port <port>]` | Tell a running `bitmagic dev` to reload the browser now. For agents: run it when you finish a round of edits. Exits 0 and does nothing when no dev server is running. |
|
|
189
198
|
| `bitmagic verify [--timeout <ms>] [--renderer webgpu\|webgl] [--platform desktop\|mobile\|both] [--fast] [--watch]` | Build, boot the game in a headless browser, press the engine's Play button like a player would, and report what broke. A game without the button passes as long as gameplay starts by itself (auto-starting genres, custom start UIs); a run where gameplay never starts fails. The settle is adaptive: the run ends as soon as the live engine proves stable gameplay (state, rendered frames, no fresh errors, player standing), with `--timeout` as the cap. The verdict includes live engine state — actual GPU backend, fps, player position, physics body count, gameplay events (see **Gameplay events** below) — recorded in `result.json`. `--renderer` pins the pipeline (default `webgpu`, what players run; a silent WebGPU→WebGL2 fallback **fails** the run, and `--renderer webgl` is the deliberate escape hatch). A run failing on a lost WebGL context retries once on software rendering automatically. `--fast` skips the screenshot pipeline (then there is no thumbnail candidate from this run). `--watch` keeps everything warm — incremental `tsc --watch`, one vite, one browser — and re-verifies on file change in seconds; `--fast` is the watch default (`--no-fast` restores the screenshot). `--platform` picks what the run emulates — see **Verifying the mobile path** below. Every run also reports the engine's mobile-parity check: a desktop action with no touch button is a warning, and a **failure** when `game.json` declares `primaryPlatform: "mobile"`. Writes the artifacts the publish gate reads (see below). |
|
|
190
199
|
| `bitmagic build` | Bundle the game into one self-contained `.bitmagic/build/index.html`. Rarely needs to be run by hand — `publish` builds automatically when the project changed. |
|
|
191
|
-
| `bitmagic publish [--visibility public\|private] [--name <name>] [--description <desc>] [--force]` | Verify-gate, build if needed, and upload straight to GCS. **
|
|
200
|
+
| `bitmagic publish [--visibility public\|private] [--name <name>] [--description <desc>] [--force] [--no-qr]` | Verify-gate, build if needed, and upload straight to GCS. **Keeps the game's current visibility**; a new game is private until published with `--visibility public`. Shows the published URL as a QR code so you can scan it onto a phone — drawn in the terminal, or written to `.bitmagic/publish-qr.png` when it cannot be. `--no-qr` skips both. |
|
|
201
|
+
| `bitmagic self-update [--tag latest\|dev]` | Update the **CLI itself** to the newest build of its line, installing into the place this CLI actually lives rather than wherever the `npm` on your `PATH` would put it — which under nvm is routinely somewhere else. Reads the project's line from `bitmagic.json` when there is one, so it also fixes a wrong-line install; `--tag` overrides. Verifies the version on disk moved, and refuses (naming the path) for an `npx` run, a source checkout, or an install shape it cannot recognise. Not to be confused with `upgrade`, which is about the project's engine. |
|
|
192
202
|
| `bitmagic upgrade [--engine <version>] [--force]` | Refresh vendored platform files and the CLI's own skills to the currently published engine. Refuses a dirty git tree unless `--force`. Also records the project's `environment` in `bitmagic.json` if it has none yet — the engine it just vendored came from that api-server — and says so when it does. |
|
|
193
203
|
| `bitmagic generate <skybox\|background\|block-type\|sound\|image\|character\|animation\|model\|prop\|vehicle> ...` | Generate one asset directly into `src/work/world.json`. Costs sparks. `model` mints a **new** 3D object from a prompt, `prop` upgrades an existing placeholder **in place**, `vehicle` adds a new drivable one, `animation` takes a parameter spec rather than a prompt, `block-type` registers a custom voxel block — see below. `skybox` and `background` write the **same** field: pick one. |
|
|
194
204
|
| `bitmagic assets add <file> [--name <n>] [--asset-id <id>] [--keep-glb] [--voxel-size <m>] [--max-voxel-size <m>] [--height <m>] [--hollow\|--solid] [--force]` | Upload **your own** file — `.glb`, `.vxl`, `.png/.jpg/.webp`, `.opus/.ogg/.m4a/.mp3`, `.json` — into the game's assets and write its entry into `src/work/world.json`. A `.glb` is voxelized in a headless browser (Chrome + a free port in 3000–3199, like `prop`) unless `--keep-glb`. Free — no sparks. See **Adding your own assets** below. |
|
|
@@ -411,6 +421,21 @@ While the game boots, the mark hops over the stage — the first time only. Late
|
|
|
411
421
|
still, and only if the reload is slow enough to be worth explaining. If a boot fails it stays put,
|
|
412
422
|
says what went wrong and offers to try again, instead of leaving you a black rectangle.
|
|
413
423
|
|
|
424
|
+
### Where your game is published
|
|
425
|
+
|
|
426
|
+
Once the project has been published, a **Published** pill appears in the top bar. It opens the
|
|
427
|
+
game's address, the visibility it went out with, which publish this is and how long ago — and the
|
|
428
|
+
same QR code the terminal draws, so the phone in your hand can reach the build without you typing
|
|
429
|
+
anything.
|
|
430
|
+
|
|
431
|
+
The pill lights up on its own within a second or two of a publish finishing, with no reload: the
|
|
432
|
+
page polls, and the publish it should show almost always happens in another terminal — often your
|
|
433
|
+
agent's, which you never look at. Until the first publish the pill is there but dead, because a
|
|
434
|
+
control that opens an empty dialog is worse than one that is plainly not ready.
|
|
435
|
+
|
|
436
|
+
It works even when the game will not boot, which is deliberate: that is the moment the link matters
|
|
437
|
+
most, since the last good build is still live at that address.
|
|
438
|
+
|
|
414
439
|
Put the page beside your agent's window. It is one page with
|
|
415
440
|
two tabs over the same running game, so switching costs nothing and does not restart anything:
|
|
416
441
|
|
|
@@ -727,12 +752,18 @@ manage the registry, not gameplay.
|
|
|
727
752
|
publish rebuilds automatically; a prior manual `bitmagic build` is never required, only useful
|
|
728
753
|
if you want to inspect `.bitmagic/build/index.html` before it ships.
|
|
729
754
|
|
|
730
|
-
**Publishing does not make a game public.**
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
755
|
+
**Publishing does not make a game public.** A new game starts `private` — reachable by URL, not
|
|
756
|
+
listed anywhere on bitmagic.ai. Pass `--visibility public` when you want it listed.
|
|
757
|
+
|
|
758
|
+
**Visibility is sticky.** `bitmagic publish` with no `--visibility` keeps the game exactly as it
|
|
759
|
+
is, so shipping an update to a public game leaves it public. You only need `--visibility` when you
|
|
760
|
+
want to *change* something: `public` to list it, `private` to take it out of service.
|
|
761
|
+
|
|
762
|
+
**Managing a published game** — changing its visibility, or taking it down for good — happens on
|
|
763
|
+
the web, at the **My games** page `publish` prints a link to (`bitmagic.ai/my-games/`). It is
|
|
764
|
+
the same page web-lane creators use, so there is one place to manage a game regardless of how it
|
|
765
|
+
was built. Withdrawing a game there unlists it and frees any custom `/play/` address; it does not
|
|
766
|
+
touch your project, and you can publish it again afterwards.
|
|
736
767
|
|
|
737
768
|
`--force` overrides a **stale or failed** verify verdict. It does **not** override a missing
|
|
738
769
|
verify record — a project with no cover art has only the verify screenshot to publish a thumbnail
|
|
@@ -744,6 +775,33 @@ from, so `bitmagic verify` must have produced at least one screenshot — `scree
|
|
|
744
775
|
stick — and note that writing them into `game.json` yourself would change the fingerprint and
|
|
745
776
|
invalidate the verify you just checked.
|
|
746
777
|
|
|
778
|
+
### Testing it on a phone
|
|
779
|
+
|
|
780
|
+
Publish draws the URL it just printed as a QR code, so you can point a phone at the terminal
|
|
781
|
+
instead of retyping a twelve-character game id into a mobile browser. Scan it and the game opens.
|
|
782
|
+
|
|
783
|
+
This is the pro lane's "try it on my phone" loop, and `--visibility private` is the whole of it: a
|
|
784
|
+
private game is *unlisted*, not access-controlled, so its URL works from any device while the game
|
|
785
|
+
stays off bitmagic.ai. Publish as often as you like and scan the code each time.
|
|
786
|
+
|
|
787
|
+
**When the code cannot be drawn, publish writes it as a file instead** — `.bitmagic/publish-qr.png`
|
|
788
|
+
— and names the path (`qrPath` in the `--json` result). That is the normal case for an agent-driven
|
|
789
|
+
publish: your agent's stdout is a pipe, not a terminal, so there is nothing to paint a code onto,
|
|
790
|
+
and the person who would scan it is on the other side of that pipe. The image is how it reaches
|
|
791
|
+
them. The same happens under `--json`, for `TERM=dumb`, and when the terminal is narrower than the
|
|
792
|
+
code (37 columns for a typical publish URL), since a wrapped code cannot be scanned anyway. A
|
|
793
|
+
terminal that draws the code successfully writes no file.
|
|
794
|
+
|
|
795
|
+
`.bitmagic/` is excluded from the publish fingerprint, so the image cannot invalidate a verify.
|
|
796
|
+
|
|
797
|
+
The code is extra, never a substitute — the URL is always printed as a plain line above it, and
|
|
798
|
+
everything still works if neither a drawing nor a file appears. `--no-qr` and `BITMAGIC_NO_QR`
|
|
799
|
+
suppress both.
|
|
800
|
+
|
|
801
|
+
`bitmagic dev` deliberately has no equivalent. Its servers bind `127.0.0.1`, and the asset CDN
|
|
802
|
+
only serves assets to `localhost` origins — a phone pointed at your machine's LAN address would
|
|
803
|
+
load the game with no terrain and drop the player through the floor. Publish privately instead.
|
|
804
|
+
|
|
747
805
|
### Which platform the game is catalogued as
|
|
748
806
|
|
|
749
807
|
Publish syncs two indicators from your project files, so bitmagic.ai lists the game as what it
|
|
@@ -867,7 +925,12 @@ parses one stream whether the command succeeded or not. The exit code remains au
|
|
|
867
925
|
|
|
868
926
|
Without `--json` nothing changes: prose goes to stdout as before and no JSON is emitted.
|
|
869
927
|
|
|
870
|
-
|
|
928
|
+
`--json` suppresses `publish`'s *drawn* QR code, which uses terminal escape sequences: under
|
|
929
|
+
`--json` stdout carries the result document and nothing else. The image is still written, and
|
|
930
|
+
`qrPath` in the result names it — that is the only way an agent learns the file exists.
|
|
931
|
+
|
|
932
|
+
The result shape is per-command — `publish` reports
|
|
933
|
+
`url`/`visibility`/`publishVersion`/`manageUrl`, plus `qrPath` when it wrote a QR image, `init`
|
|
871
934
|
reports `gameId`/`root`/`dependenciesInstalled`/`packageManager`, `upgrade` reports `replaced` and any
|
|
872
935
|
`missingDependencies` as structured entries rather than only as a printed install command, plus
|
|
873
936
|
`cliUpdate` (`{ current, latest, updateAvailable }`, or `null` when the engine did not move and so
|
|
@@ -877,7 +940,39 @@ no check was made — which is not the same as "no update"), and `legacyAssetsRe
|
|
|
877
940
|
|
|
878
941
|
## Staying current
|
|
879
942
|
|
|
880
|
-
|
|
943
|
+
```bash
|
|
944
|
+
bitmagic self-update
|
|
945
|
+
```
|
|
946
|
+
|
|
947
|
+
updates the CLI itself. Use it rather than `npm install -g @bitmagic/cli`, which is only for the
|
|
948
|
+
first install — see [Why self-update and not npm](#why-self-update-and-not-npm) below.
|
|
949
|
+
|
|
950
|
+
It installs into the exact place this CLI is already installed, on the line it is already on. Inside
|
|
951
|
+
a project it uses that project's line instead (`environment` in `bitmagic.json`), so running it in a
|
|
952
|
+
`dev` project from a release build crosses you over; `--tag dev` / `--tag latest` overrides both. It
|
|
953
|
+
reads back the version on disk afterwards and fails if it did not move, so a successful-looking
|
|
954
|
+
update that changed nothing is reported rather than believed.
|
|
955
|
+
|
|
956
|
+
It refuses, with the path it looked at, when there is nothing for it to do: a run through `npx`
|
|
957
|
+
(nothing is installed), a source checkout (`git pull` and rebuild), or an install shape it does not
|
|
958
|
+
recognise — it will not guess at where to write.
|
|
959
|
+
|
|
960
|
+
### Why self-update and not npm
|
|
961
|
+
|
|
962
|
+
`npm install -g @bitmagic/cli` installs into whichever Node the `npm` on your `PATH` belongs to,
|
|
963
|
+
which is not necessarily the one this CLI is installed in. Under a version manager — nvm, fnm,
|
|
964
|
+
Volta — those two are routinely different, and a coding agent's non-interactive shell makes it
|
|
965
|
+
worse: it sources no profile, so nvm never loads and `npm` is whatever else is on the system path.
|
|
966
|
+
The install then succeeds, into a prefix nothing on your `PATH` points at, and `bitmagic --version`
|
|
967
|
+
never moves. The same applies to the two-root pnpm setup below, where a bare `npm i -g` writes to a
|
|
968
|
+
third place entirely.
|
|
969
|
+
|
|
970
|
+
`self-update` resolves its own install from the Node binary running it, so it cannot be aimed
|
|
971
|
+
anywhere else.
|
|
972
|
+
|
|
973
|
+
### The nudges
|
|
974
|
+
|
|
975
|
+
Three, all advisory — nothing is ever blocked because something is out of date.
|
|
881
976
|
|
|
882
977
|
- **The CLI itself.** Commands print a line when a newer `@bitmagic/cli` is on npm. The check reads
|
|
883
978
|
a cache written by an earlier run, so it costs no time; the cache refreshes in the background at
|
|
@@ -885,15 +980,17 @@ Three nudges, all advisory — nothing is ever blocked because something is out
|
|
|
885
980
|
every merge to `main` and can move several times an hour, so an older answer there is usually
|
|
886
981
|
about a build several versions back. It asks about the line you are actually on — a build
|
|
887
982
|
installed from `@dev` asks the `dev` dist-tag and hears about the next dev build, rather than
|
|
888
|
-
being told the production release is "newer"
|
|
889
|
-
|
|
890
|
-
|
|
983
|
+
being told the production release is "newer". An unreachable registry, a first-ever run, and a
|
|
984
|
+
version with no recognisable numeric core all stay quiet. `bitmagic dev` also shows it as a
|
|
985
|
+
banner in the browser, because that command runs for hours and the terminal line scrolls away.
|
|
891
986
|
- **The CLI, after an engine bump.** When `bitmagic upgrade` actually moves the engine version, it
|
|
892
987
|
asks npm there and then instead of trusting that cache — which can be a whole interval stale, and
|
|
893
988
|
so silent about the CLI published alongside the engine you just vendored. The CLI and the engine
|
|
894
989
|
ship together, so a newer engine can need build config or a command only the newer CLI has, and
|
|
895
|
-
finding that out as a failed `bitmagic build` is worse than being told here.
|
|
896
|
-
|
|
990
|
+
finding that out as a failed `bitmagic build` is worse than being told here. It names the line the
|
|
991
|
+
*project* is on rather than the one you happen to be running, so it says `bitmagic self-update
|
|
992
|
+
--tag dev` where that is the crossing you need. No request is made when the engine version did not
|
|
993
|
+
change, and an unreachable registry costs the hint and nothing else.
|
|
897
994
|
- **The vendored engine.** `bitmagic dev` and `bitmagic publish` say when a newer engine exists and
|
|
898
995
|
suggest `bitmagic upgrade`. Publishing is never refused for an old engine — the prompt belongs
|
|
899
996
|
where rebuilding is cheap, not at the moment you ship.
|
|
@@ -916,19 +1013,23 @@ and where the generators fall short. It is the same thing the web editor already
|
|
|
916
1013
|
typed there, and it goes to the same place. None of it reaches Google Analytics, which only ever
|
|
917
1014
|
receives counts, outcomes and timings.
|
|
918
1015
|
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
1016
|
+
**What you asked your agent for is kept too, when it passes it on.** The scaffolded project docs
|
|
1017
|
+
tell your agent to add `--original-prompt "<your request, verbatim>"`, so on those commands the
|
|
1018
|
+
wording *you* used — typically what you typed into Claude Code or Codex — is stored beside the
|
|
1019
|
+
command's own text and as a record of its own. The CLI has no other view of your agent's
|
|
1020
|
+
conversation: it sees only the arguments your agent chooses to pass it, and this is the one
|
|
1021
|
+
argument that is your words rather than its paraphrase. It is optional, never required, and never
|
|
1022
|
+
influences what gets generated.
|
|
924
1023
|
|
|
925
1024
|
Set `DO_NOT_TRACK=1` in your environment to switch the end-of-command report off. Nothing is
|
|
926
|
-
collected for it in that case — not even the file reads it would have needed.
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
1025
|
+
collected for it in that case — not even the file reads it would have needed. It also stops
|
|
1026
|
+
`--original-prompt` being forwarded: the CLI drops it at the point every command reads its flags,
|
|
1027
|
+
so no request carries it, whether or not your agent passed it.
|
|
1028
|
+
|
|
1029
|
+
It does **not** switch off the paragraph before that one. The text you pass to `forge`, `generate`,
|
|
1030
|
+
`cover` and `init --idea` is not telemetry: it is the request, and the server cannot generate
|
|
1031
|
+
anything without it. If you would rather it were not kept, the honest answer is that today there is
|
|
1032
|
+
no flag for that — tell us and we will add one.
|
|
932
1033
|
|
|
933
1034
|
The report is deliberately unobtrusive but it is not free: it is capped at 1.5 seconds per request
|
|
934
1035
|
(two at worst, when your access token is due for a refresh first), it never prints, and it can never
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import type { Environment } from '../config/environments.js';
|
|
2
|
+
import { withVoxelizeSession } from '../forge/voxelize-session.js';
|
|
3
|
+
import type { ProjectContext } from '../project/context.js';
|
|
4
|
+
import { type VoxelizeFlags, type VoxelizeGlb } from './voxelize-glb.js';
|
|
5
|
+
/** Which stored source a re-bake will read. */
|
|
6
|
+
export type RevoxelizeSource = {
|
|
7
|
+
kind: 'master';
|
|
8
|
+
masterUrl: string;
|
|
9
|
+
} | {
|
|
10
|
+
kind: 'glb';
|
|
11
|
+
glbUrl: string;
|
|
12
|
+
};
|
|
13
|
+
export interface RevoxelizeOptions {
|
|
14
|
+
context: ProjectContext;
|
|
15
|
+
environment: Environment;
|
|
16
|
+
token: string;
|
|
17
|
+
assetId: string;
|
|
18
|
+
voxel: VoxelizeFlags;
|
|
19
|
+
log: (message: string) => void;
|
|
20
|
+
fetchImpl?: typeof globalThis.fetch;
|
|
21
|
+
/** Injected in tests so the lane runs without Chrome. */
|
|
22
|
+
session?: typeof withVoxelizeSession;
|
|
23
|
+
/** Injected in tests; used for the GLB source, which reuses the shared bake. */
|
|
24
|
+
voxelize?: VoxelizeGlb;
|
|
25
|
+
}
|
|
26
|
+
export interface RevoxelizeResult {
|
|
27
|
+
assetId: string;
|
|
28
|
+
assetName: string;
|
|
29
|
+
source: RevoxelizeSource['kind'];
|
|
30
|
+
assetUrl?: string;
|
|
31
|
+
voxelCount?: number;
|
|
32
|
+
/** Placed instances that changed with it — the blast radius, reported rather than assumed. */
|
|
33
|
+
instanceCount: number;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* The stored source to re-bake, preferring the master.
|
|
37
|
+
*
|
|
38
|
+
* The master is preferred when both are present because it is a hundredth of the bytes for the
|
|
39
|
+
* same answer at or below its own resolution. `assertCanGoFiner` is what catches the case where
|
|
40
|
+
* that preference would cost detail.
|
|
41
|
+
*/
|
|
42
|
+
export declare function chooseSource(asset: Record<string, unknown>): RevoxelizeSource | null;
|
|
43
|
+
/** The asset to re-bake, refused before the browser starts if it cannot be. */
|
|
44
|
+
export declare function findRevoxelizableAsset(world: Record<string, unknown>, assetId: string): {
|
|
45
|
+
asset: Record<string, unknown>;
|
|
46
|
+
source: RevoxelizeSource;
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* A voxel size fit to show a person and to store.
|
|
50
|
+
*
|
|
51
|
+
* The `.vxl` header holds float32, so the size read back out of it is `0.019999999552965164` where
|
|
52
|
+
* the creator asked for `0.01` and got a doubling. Six significant figures is far beyond any
|
|
53
|
+
* resolution this means anything at, and it puts the number back in the vocabulary the flag uses —
|
|
54
|
+
* both in the note and in world.json, which would otherwise carry the artifact into every diff.
|
|
55
|
+
*/
|
|
56
|
+
export declare function tidyVoxelSize(value: number): number;
|
|
57
|
+
/**
|
|
58
|
+
* What the bake actually produced, when that is not what was asked for.
|
|
59
|
+
*
|
|
60
|
+
* The engine's compiler halves resolution until the model fits a leaf budget
|
|
61
|
+
* (`compileVoxelModelToVxlAsset`: `while (cells.size > maxLeaves) { downsample; vs *= 2 }`, budget
|
|
62
|
+
* 600k for a working asset). It says so — but only as a `console.warn` inside the headless Chrome
|
|
63
|
+
* the CLI drives, which reaches nobody, and `REVOXELIZE_FROM_VXL_MASTER_RESULT` did not carry it.
|
|
64
|
+
* So a request just under the knee came back at exactly twice the size, silently, with a zero exit
|
|
65
|
+
* code.
|
|
66
|
+
*
|
|
67
|
+
* The effect is worse than "not quite what you asked for", which is why this is said out loud
|
|
68
|
+
* rather than left to whoever compares two numbers in world.json: the result is NON-MONOTONIC.
|
|
69
|
+
* One step below the knee the asset is coarser than a COARSER request would have produced —
|
|
70
|
+
* measured on a 2.78 m stall with a 512³ master, 0.011 m gave 556k voxels and 0.0105 m gave 141k.
|
|
71
|
+
* Nothing about "I asked for finer voxels and got a blockier model" suggests looking at a budget.
|
|
72
|
+
*
|
|
73
|
+
* Detected from the .vxl header rather than from anything the engine says, deliberately: the
|
|
74
|
+
* header is what was actually written, and the CLI drives whatever engine the project vendored —
|
|
75
|
+
* including ones that predate any reply field carrying this.
|
|
76
|
+
*/
|
|
77
|
+
export declare function describeBudgetCoarsening(requested: number, achieved: number): {
|
|
78
|
+
coarsened: boolean;
|
|
79
|
+
factor: number;
|
|
80
|
+
note: string;
|
|
81
|
+
};
|
|
82
|
+
/**
|
|
83
|
+
* The height a master re-bake will be resampled to.
|
|
84
|
+
*
|
|
85
|
+
* `--height` wins. Otherwise the height the asset was BAKED at, which the master path records in
|
|
86
|
+
* `voxelizeSettings` for exactly this. Falling through to neither is the case worth naming: a
|
|
87
|
+
* master is a grid, not a size, so the engine has nothing to derive a height from and lands on its
|
|
88
|
+
* own `DEFAULT_TARGET_HEIGHT` of 2 m — silently returning a 10 m building as a 2 m one. The mesh
|
|
89
|
+
* branch has no such gap, which is why `--height`'s "omit to keep the source's own size" only ever
|
|
90
|
+
* described half of this command.
|
|
91
|
+
*/
|
|
92
|
+
export declare function resolveMasterTargetHeight(asset: Record<string, unknown>, requested: number | undefined): number | undefined;
|
|
93
|
+
/**
|
|
94
|
+
* Refuse a master re-bake that asks for more detail than the master holds.
|
|
95
|
+
*
|
|
96
|
+
* The engine would refuse it too — `resampleMaster` throws "re-forge at a higher resolution rather
|
|
97
|
+
* than upsampling" — but only after the browser, vite and the page have started. Saying it here
|
|
98
|
+
* costs nothing and names the thing to do instead, which the engine's message cannot know.
|
|
99
|
+
*
|
|
100
|
+
* The floor is derived from the MASTER, not from the previous bake. Those are very different
|
|
101
|
+
* numbers: a 512³ master baked once at 0.1 m holds detail down to about `targetHeight / 512`, and
|
|
102
|
+
* refusing everything below 0.1 m would make that headroom unreachable from the CLI — which is the
|
|
103
|
+
* whole reason the master is stored rather than the working asset.
|
|
104
|
+
*
|
|
105
|
+
* Deliberately PERMISSIVE. The engine's real limit is the master's occupied span along the up
|
|
106
|
+
* axis, which is at most its resolution and usually less, so a request between
|
|
107
|
+
* `targetHeight / resolution` and `targetHeight / spanUp` still throws in the browser. That is the
|
|
108
|
+
* right way round: this pre-flight exists to avoid paying for a browser on a request that cannot
|
|
109
|
+
* work, never to refuse a size the master can serve. The engine stays the authority.
|
|
110
|
+
*
|
|
111
|
+
* Falls back to the old "no finer than the last bake" rule when either field is missing, so assets
|
|
112
|
+
* written before `sourceVxlMasterResolution` existed — or hand-edited ones — keep a guard rather
|
|
113
|
+
* than losing it.
|
|
114
|
+
*/
|
|
115
|
+
export declare function assertMasterCanGoFiner(asset: Record<string, unknown>, requestedVoxelSize: number, targetHeight: number | undefined, name: string): void;
|
|
116
|
+
export declare function revoxelizeAsset(options: RevoxelizeOptions): Promise<RevoxelizeResult>;
|