@bitmagic/cli 0.1.53-dev.9 → 0.1.54-dev.0

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 CHANGED
@@ -196,11 +196,11 @@ browser reloads itself on every change and the assets panel shows each generatio
196
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. |
197
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. |
198
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). |
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. |
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. |
199
+ | `bitmagic build [--single-file]` | Bundle the game into a single `.bitmagic/build/index.html`. The engine, your game and its data are inlined; three.js, Rapier and the other third-party packages load from a CDN at the versions your import map pins — the same shape a game published from bitmagic.ai has. `--single-file` inlines those too, for a game that has to run with no network (offline, `file://`, a packaged shell); the file is several megabytes bigger. Rarely needs to be run by hand — `publish` builds automatically when the project changed. |
200
+ | `bitmagic publish [--visibility public\|private] [--name <name>] [--description <desc>] [--force] [--single-file] [--no-qr]` | Verify-gate, build if needed, and upload straight to GCS. `--single-file` publishes the offline bundle described under `bitmagic build`; switching the flag between runs always rebuilds, since it changes nothing on disk for the reuse check to notice. **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
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. |
202
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. |
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. |
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** (both produce voxels directly; `--mesh` takes the older mesh path), `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. |
204
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. |
205
205
  | `bitmagic assets list` | The assets in `world.json`: id, name, type, size, placed instances, and total references. Local, no network. |
206
206
  | `bitmagic assets remove <assetId> [--force]` | Remove an asset from `world.json` (the uploaded file stays in storage). Refuses while anything in `world.json` still references it; `--force` removes the asset and its placed instances together. |
@@ -556,8 +556,9 @@ bitmagic generate prop --asset <assetId> --prompt "<what it should be>"
556
556
  ```
557
557
 
558
558
  Either way it lands in the journal — `hq.started` then `hq.completed` — so your agent finds out an
559
- asset changed and why, instead of tripping over it. If it fails after the mesh exists, the error
560
- carries the URL: retry with `--glb-url <url>` and you are not charged again.
559
+ asset changed and why, instead of tripping over it. If it fails after the source exists, the error
560
+ carries the URL: retry with `--master-url <url>` (or `--glb-url <url>` on the mesh path) and you
561
+ are not charged again.
561
562
 
562
563
  Both ports must fall between 3000 and 3199. That is the window the asset CDN allows as an origin;
563
564
  outside it the game loads with no terrain and no error.
@@ -665,8 +666,21 @@ because a solid-filled building is millions of wasted voxels.
665
666
  It costs the same sparks as generating the same object in the web editor — both bill the Asset
666
667
  Forger call under one price, so the lane you choose never changes what a creator pays.
667
668
 
668
- If the bake fails after the mesh exists, the error prints the exact
669
- `--glb-url --asset-id …` command to retry the browser step **without paying again**.
669
+ **What gets generated: voxels, not a mesh.** The generator produces voxels directly, and the
670
+ `.vxl` master it returns is stored as the asset's source around a megabyte, against the
671
+ 50–100 MB textured mesh the old path bought only to voxelize and throw away. `--voxel-grid` sets
672
+ the grid that master is forged at (default 512, one of 0/32/64/128/256/512). It is worth
673
+ understanding once: a master can only ever be re-baked **coarser**, so the grid is the ceiling on
674
+ every later `bitmagic assets revoxelize`.
675
+
676
+ `--mesh` asks for the old path instead. The one thing it buys is that a mesh is
677
+ resolution-independent, so its stored source can be re-voxelized to any resolution at all — if you
678
+ know you will want more detail later than a 512³ master can hold, ask for the mesh. A project
679
+ whose vendored engine predates voxel masters takes the mesh path regardless, and says so; run
680
+ `bitmagic upgrade` to get the newer engine.
681
+
682
+ If the bake fails after the source exists, the error prints the exact command to retry the browser
683
+ step **without paying again** — `--master-url …` for voxels, `--glb-url …` for a mesh.
670
684
 
671
685
  ## Drivable vehicles
672
686
 
@@ -850,7 +864,7 @@ refused is a bundle that is not a Bitmagic engine build at all (exit 1).
850
864
 
851
865
  | Code | Meaning |
852
866
  |---|---|
853
- | 1 | Build failed, or the uploaded bundle was not a Bitmagic engine build (check `vite.publish.config.js`). Not retryable — republishing the same bytes gets the same refusal. |
867
+ | 1 | Build failed, or the uploaded bundle was not a Bitmagic engine build (check `vite.publish.config.js`, or `vite.publish-standalone.config.js` for a `--single-file` build). Not retryable — republishing the same bytes gets the same refusal. |
854
868
  | 2 | Not logged in |
855
869
  | 3 | Verify missing, stale, or failed |
856
870
  | 4 | `bitmagic judge --min-score`: the judge ran, but the overall score is below the bar. The scorecard is in `.bitmagic/judge.json`. |
@@ -907,10 +921,12 @@ exact install command to run, using your project's own package manager (detected
907
921
  added needs that command run once before `bitmagic build` (and therefore `bitmagic publish`) will
908
922
  work.
909
923
 
910
- A project scaffolded before `vite.publish.config.js` existed cannot be bundled at all: `bitmagic
924
+ A project scaffolded before the bundle config it needs existed cannot be bundled at all: `bitmagic
911
925
  build` stops with a message naming `bitmagic upgrade`, which vendors the file without touching
912
- your game code. Run the printed install command afterwards if `upgrade` reports missing
913
- dependencies too.
926
+ your game code. This applies to `vite.publish-standalone.config.js` too, which arrived later than
927
+ `vite.publish.config.js` — so a project can have one and not the other, and the message names
928
+ whichever one your build actually needs. Run the printed install command afterwards if `upgrade`
929
+ reports missing dependencies too.
914
930
 
915
931
  ## Machine-readable output
916
932
 
@@ -1054,9 +1070,10 @@ it, modified or not, free or paid, as a game engine, framework, SDK, library, st
1054
1070
  game-creation tool.
1055
1071
 
1056
1072
  One practical consequence: a published game contains compiled engine code, so the licence requires
1057
- the notice to travel with it. `vite.publish.config.js` carries a `banner` that does this
1058
- automatically, along with the attribution three.js, Rapier and the other bundled libraries require.
1059
- Leave it in place. `engine/THIRD-PARTY-NOTICES.md` has the full texts.
1073
+ the notice to travel with it. Both bundle configs carry a `banner` that does this automatically,
1074
+ along with the attribution three.js, Rapier and the other libraries require — which a
1075
+ `--single-file` build inlines outright, and a default build still ships loaders for. Leave it in
1076
+ place. `engine/THIRD-PARTY-NOTICES.md` has the full texts.
1060
1077
 
1061
1078
  ## Development
1062
1079
 
@@ -45,6 +45,40 @@ export declare function findRevoxelizableAsset(world: Record<string, unknown>, a
45
45
  asset: Record<string, unknown>;
46
46
  source: RevoxelizeSource;
47
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
+ };
48
82
  /**
49
83
  * The height a master re-bake will be resampled to.
50
84
  *
@@ -74,6 +74,57 @@ function positiveNumber(value) {
74
74
  }
75
75
  /** The finest grid the generator will forge a master at. */
76
76
  const MAX_MASTER_GRID = Math.max(...propVoxelGrids);
77
+ /**
78
+ * Floating-point slack for "the engine baked what I asked for".
79
+ *
80
+ * The requested size round-trips through a float32 header, so an exact `===` would report a
81
+ * coarsening on every bake. A real one is a DOUBLING, so anything under a few percent is noise.
82
+ */
83
+ const VOXEL_SIZE_EPSILON = 0.02;
84
+ /**
85
+ * A voxel size fit to show a person and to store.
86
+ *
87
+ * The `.vxl` header holds float32, so the size read back out of it is `0.019999999552965164` where
88
+ * the creator asked for `0.01` and got a doubling. Six significant figures is far beyond any
89
+ * resolution this means anything at, and it puts the number back in the vocabulary the flag uses —
90
+ * both in the note and in world.json, which would otherwise carry the artifact into every diff.
91
+ */
92
+ export function tidyVoxelSize(value) {
93
+ return Number(value.toPrecision(6));
94
+ }
95
+ /**
96
+ * What the bake actually produced, when that is not what was asked for.
97
+ *
98
+ * The engine's compiler halves resolution until the model fits a leaf budget
99
+ * (`compileVoxelModelToVxlAsset`: `while (cells.size > maxLeaves) { downsample; vs *= 2 }`, budget
100
+ * 600k for a working asset). It says so — but only as a `console.warn` inside the headless Chrome
101
+ * the CLI drives, which reaches nobody, and `REVOXELIZE_FROM_VXL_MASTER_RESULT` did not carry it.
102
+ * So a request just under the knee came back at exactly twice the size, silently, with a zero exit
103
+ * code.
104
+ *
105
+ * The effect is worse than "not quite what you asked for", which is why this is said out loud
106
+ * rather than left to whoever compares two numbers in world.json: the result is NON-MONOTONIC.
107
+ * One step below the knee the asset is coarser than a COARSER request would have produced —
108
+ * measured on a 2.78 m stall with a 512³ master, 0.011 m gave 556k voxels and 0.0105 m gave 141k.
109
+ * Nothing about "I asked for finer voxels and got a blockier model" suggests looking at a budget.
110
+ *
111
+ * Detected from the .vxl header rather than from anything the engine says, deliberately: the
112
+ * header is what was actually written, and the CLI drives whatever engine the project vendored —
113
+ * including ones that predate any reply field carrying this.
114
+ */
115
+ export function describeBudgetCoarsening(requested, achieved) {
116
+ const factor = achieved / requested;
117
+ if (!(factor > 1 + VOXEL_SIZE_EPSILON))
118
+ return { coarsened: false, factor: 1, note: '' };
119
+ return {
120
+ coarsened: true,
121
+ factor,
122
+ note: `note: baked at ${tidyVoxelSize(achieved)} m, not the ${requested} m requested — the model did not fit `
123
+ + 'the renderer\'s 600,000-leaf budget, so the engine halved the resolution to make it fit. '
124
+ + 'A slightly LARGER --voxel-size will come back finer than this one did; there is a knee '
125
+ + 'just above the size you asked for.',
126
+ };
127
+ }
77
128
  /**
78
129
  * What to actually do about a master that cannot go finer — which is NOT the same advice at every
79
130
  * resolution.
@@ -232,6 +283,9 @@ async function rebakeFromMaster(options) {
232
283
  if (summary === null) {
233
284
  throw new CliError(`The engine returned bytes that are not a readable .vxl for "${assetName}". ${retryHint}`);
234
285
  }
286
+ const achieved = describeBudgetCoarsening(voxel.minVoxelSize, summary.minVoxelSize);
287
+ if (achieved.coarsened)
288
+ log(achieved.note);
235
289
  const timestamp = Date.now();
236
290
  const upload = await uploadProjectFile(environment, token, {
237
291
  gameId: context.metadata.gameId,
@@ -245,17 +299,19 @@ async function rebakeFromMaster(options) {
245
299
  size: bytes.byteLength,
246
300
  boundingBox: summary.boundingBox,
247
301
  boundingBoxInMeters: true,
248
- voxelSize: summary.minVoxelSize,
302
+ voxelSize: tidyVoxelSize(summary.minVoxelSize),
249
303
  fragmentCount: summary.fragmentCount,
250
304
  ...(summary.voxelCount !== undefined ? { voxelCount: summary.voxelCount } : {}),
251
- // Re-recorded, mirroring what the engine writes on the create path and what the GLB branch
252
- // gets back for free. A `--height` re-bake that left the old height here would leave the next
253
- // run computing its master floor — and its own default height — against a size that no longer
254
- // matches the asset. `fillInterior` is meaningless on this path: a master already carries its
255
- // own occupancy.
305
+ // Re-recorded from what the bake ACHIEVED, never from what was asked for. A `--height` re-bake
306
+ // that left the old height here would leave the next run computing its master floor against a
307
+ // size that no longer matches the asset — and recording the requested voxel size next to a
308
+ // `voxelSize` the compiler coarsened leaves world.json asserting two resolutions for one file.
309
+ // `fillInterior` is meaningless on this path: a master already carries its own occupancy.
256
310
  voxelizeSettings: {
257
- minVoxelSize: voxel.minVoxelSize,
258
- maxVoxelSize: voxel.maxVoxelSize,
311
+ minVoxelSize: tidyVoxelSize(summary.minVoxelSize),
312
+ // Scaled by the same factor, so the ladder the creator asked for (a 5x spread, say) survives
313
+ // a coarsening rather than silently narrowing to 2.5x.
314
+ maxVoxelSize: tidyVoxelSize(voxel.maxVoxelSize * achieved.factor),
259
315
  ...(targetHeight !== undefined ? { targetHeight } : {}),
260
316
  fillInterior: false,
261
317
  },
@@ -1 +1 @@
1
- {"version":3,"file":"revoxelize.js","sourceRoot":"","sources":["../../src/assets/revoxelize.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"revoxelize.js","sourceRoot":"","sources":["../../src/assets/revoxelize.ts"],"names":[],"mappings":"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"}
package/dist/cli.d.ts CHANGED
@@ -247,6 +247,10 @@ declare const rawCommands: {
247
247
  readonly type: "boolean";
248
248
  readonly description: "Print the result as JSON on stdout; all progress goes to stderr.";
249
249
  };
250
+ readonly 'single-file': {
251
+ readonly type: "boolean";
252
+ readonly description: string;
253
+ };
250
254
  }>;
251
255
  generate: CommandDef<ArgsDef>;
252
256
  assets: CommandDef<ArgsDef>;
@@ -362,6 +366,10 @@ declare const rawCommands: {
362
366
  readonly type: "boolean";
363
367
  readonly description: "Do not draw the published URL as a QR code. `BITMAGIC_NO_QR` does the same for every run.";
364
368
  };
369
+ readonly 'single-file': {
370
+ readonly type: "boolean";
371
+ readonly description: string;
372
+ };
365
373
  readonly json: {
366
374
  readonly type: "boolean";
367
375
  readonly description: "Print the result as JSON on stdout; all progress goes to stderr.";
@@ -3,4 +3,8 @@ export declare const buildCommand: import("citty").CommandDef<{
3
3
  readonly type: "boolean";
4
4
  readonly description: "Print the result as JSON on stdout; all progress goes to stderr.";
5
5
  };
6
+ readonly 'single-file': {
7
+ readonly type: "boolean";
8
+ readonly description: string;
9
+ };
6
10
  }>;
@@ -12,12 +12,18 @@ export const buildCommand = defineCommand({
12
12
  type: 'boolean',
13
13
  description: 'Print the result as JSON on stdout; all progress goes to stderr.',
14
14
  },
15
+ 'single-file': {
16
+ type: 'boolean',
17
+ description: 'Inline three.js, Rapier and the other CDN packages into the bundle, so it runs with no '
18
+ + 'network. Bigger; for offline or packaged distribution, not everyday publishing.',
19
+ },
15
20
  },
16
21
  async run({ args }) {
17
22
  const output = createOutput(args.json === true);
18
23
  const context = loadProjectContext();
19
24
  output.info('Building…');
20
- const manifest = runBuild(context.root, context.metadata.engineVersion);
25
+ const singleFile = args['single-file'] === true;
26
+ const manifest = runBuild(context.root, context.metadata.engineVersion, { singleFile });
21
27
  const { htmlPath, manifestPath } = buildBundlePaths(context.root);
22
28
  output.info(`Bundle ready: .bitmagic/build/index.html (${manifest.bytes} bytes)`);
23
29
  output.result({ ok: true, bundlePath: htmlPath, manifestPath, ...manifest });
@@ -1 +1 @@
1
- {"version":3,"file":"build.js","sourceRoot":"","sources":["../../src/commands/build.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AACtC,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,MAAM,CAAC,MAAM,YAAY,GAAG,aAAa,CAAC;IACxC,IAAI,EAAE;QACJ,IAAI,EAAE,OAAO;QACb,WAAW,EAAE,iEAAiE;KAC/E;IACD,IAAI,EAAE;QACJ,IAAI,EAAE;YACJ,IAAI,EAAE,SAAS;YACf,WAAW,EAAE,kEAAkE;SAChF;KACF;IACD,KAAK,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE;QAChB,MAAM,MAAM,GAAG,YAAY,CAAC,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;QAChD,MAAM,OAAO,GAAG,kBAAkB,EAAE,CAAC;QACrC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACzB,MAAM,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;QACxE,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAE,GAAG,gBAAgB,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAClE,MAAM,CAAC,IAAI,CAAC,6CAA6C,QAAQ,CAAC,KAAK,SAAS,CAAC,CAAC;QAClF,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,YAAY,EAAE,GAAG,QAAQ,EAAE,CAAC,CAAC;IAC/E,CAAC;CACF,CAAC,CAAC"}
1
+ {"version":3,"file":"build.js","sourceRoot":"","sources":["../../src/commands/build.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AACtC,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,MAAM,CAAC,MAAM,YAAY,GAAG,aAAa,CAAC;IACxC,IAAI,EAAE;QACJ,IAAI,EAAE,OAAO;QACb,WAAW,EAAE,iEAAiE;KAC/E;IACD,IAAI,EAAE;QACJ,IAAI,EAAE;YACJ,IAAI,EAAE,SAAS;YACf,WAAW,EAAE,kEAAkE;SAChF;QACD,aAAa,EAAE;YACb,IAAI,EAAE,SAAS;YACf,WAAW,EACT,yFAAyF;kBACvF,iFAAiF;SACtF;KACF;IACD,KAAK,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE;QAChB,MAAM,MAAM,GAAG,YAAY,CAAC,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;QAChD,MAAM,OAAO,GAAG,kBAAkB,EAAE,CAAC;QACrC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACzB,MAAM,UAAU,GAAG,IAAI,CAAC,aAAa,CAAC,KAAK,IAAI,CAAC;QAChD,MAAM,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,aAAa,EAAE,EAAE,UAAU,EAAE,CAAC,CAAC;QACxF,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAE,GAAG,gBAAgB,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAClE,MAAM,CAAC,IAAI,CAAC,6CAA6C,QAAQ,CAAC,KAAK,SAAS,CAAC,CAAC;QAClF,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,YAAY,EAAE,GAAG,QAAQ,EAAE,CAAC,CAAC;IAC/E,CAAC;CACF,CAAC,CAAC"}
@@ -1,5 +1,4 @@
1
1
  import { type CommandRunDeps } from './run-deps.js';
2
- import type { Environment } from '../config/environments.js';
3
2
  import { type GenerationOutcome } from '../generate/stream.js';
4
3
  import { type PropVoxelizeResult } from '../generate/prop.js';
5
4
  import { type VehicleInstallResult } from '../generate/vehicle.js';
@@ -105,23 +104,22 @@ export declare function runAssetGeneration(type: string, label: string, body: Re
105
104
  * or an asset with no `fitBox` costs nothing.
106
105
  */
107
106
  /**
108
- * Refuses `--direct-voxels` outside `dev`, rather than ignoring it.
109
- *
110
- * The flag asks for a materially different asset — voxels tapped straight from the generator
111
- * instead of a voxelized mesh — so quietly producing the other thing would be the wrong answer to
112
- * a question the creator asked explicitly. Everywhere but dev, api-server does not expose the
113
- * generator at all.
114
- */
115
- export declare function assertDirectVoxelsAllowed(environment: Environment, directVoxels: boolean): void;
116
- /**
117
- * Refuses `--voxel-grid` without `--direct-voxels`, rather than ignoring it.
107
+ * Refuses `--voxel-grid` alongside `--mesh`, rather than ignoring it.
118
108
  *
119
109
  * The grid only reaches the `prop-voxel` generator, so on the mesh path the flag does nothing at
120
110
  * all — and it is the one flag whose whole point is a decision that cannot be revisited later
121
111
  * (see DEFAULT_MASTER_GRID). Silently dropping it is how a creator ends up believing they asked
122
112
  * for a finer master and finding out months later, when a re-voxelize refuses.
123
113
  */
124
- export declare function assertVoxelGridAllowed(voxelGrid: number | undefined, directVoxels: boolean): void;
114
+ export declare function assertVoxelGridAllowed(voxelGrid: number | undefined, mesh: boolean): void;
115
+ /**
116
+ * Refuses a run that names two sources to bake from.
117
+ *
118
+ * Each flag skips the paid generation and points the bake at something the caller already has, and
119
+ * they point at different things. Picking a winner silently would bake one and leave the creator
120
+ * believing they had baked the other.
121
+ */
122
+ export declare function assertOneRetrySource(glbUrl: string | undefined, masterUrl: string | undefined): void;
125
123
  /**
126
124
  * The grid flag's value, validated against the generator's own allowlist.
127
125
  *
@@ -137,9 +135,11 @@ export declare function runPropGeneration(options: {
137
135
  /** The creator's own request, verbatim — recorded for analytics, never generated from. */
138
136
  /** Skip the paid generation and voxelize this mesh instead — how a failed run is retried. */
139
137
  glbUrl?: string;
140
- /** `--direct-voxels`: ask for voxels rather than a mesh. Dev only. */
141
- directVoxels?: boolean;
142
- /** `--voxel-grid`: the grid the master is forged at. Only with `--direct-voxels`. */
138
+ /** `--master-url`: bake this voxel master instead of generating one. The voxel `--glb-url`. */
139
+ masterUrl?: string;
140
+ /** `--mesh`: ask for a mesh rather than voxels, which are the default. */
141
+ mesh?: boolean;
142
+ /** `--voxel-grid`: the grid the master is forged at. Not valid with `--mesh`. */
143
143
  voxelGrid?: number;
144
144
  json: boolean;
145
145
  deps?: GenerateRunDeps;
@@ -184,9 +184,11 @@ export declare function runModelGeneration(options: {
184
184
  fillInterior: boolean;
185
185
  /** Skip the paid generation and voxelize this mesh instead — how a failed run is retried. */
186
186
  glbUrl?: string;
187
- /** `--direct-voxels`: ask for voxels rather than a mesh. Dev only. */
188
- directVoxels?: boolean;
189
- /** `--voxel-grid`: the grid the master is forged at. Only with `--direct-voxels`. */
187
+ /** `--master-url`: bake this voxel master instead of generating one. The voxel `--glb-url`. */
188
+ masterUrl?: string;
189
+ /** `--mesh`: ask for a mesh rather than voxels, which are the default. */
190
+ mesh?: boolean;
191
+ /** `--voxel-grid`: the grid the master is forged at. Not valid with `--mesh`. */
190
192
  voxelGrid?: number;
191
193
  json: boolean;
192
194
  deps?: GenerateRunDeps;
@@ -352,33 +352,32 @@ export async function runAssetGeneration(type, label, body, json = false, deps)
352
352
  * or an asset with no `fitBox` costs nothing.
353
353
  */
354
354
  /**
355
- * Refuses `--direct-voxels` outside `dev`, rather than ignoring it.
356
- *
357
- * The flag asks for a materially different asset — voxels tapped straight from the generator
358
- * instead of a voxelized mesh — so quietly producing the other thing would be the wrong answer to
359
- * a question the creator asked explicitly. Everywhere but dev, api-server does not expose the
360
- * generator at all.
361
- */
362
- export function assertDirectVoxelsAllowed(environment, directVoxels) {
363
- if (!directVoxels || environment.name === 'dev')
364
- return;
365
- throw new CliError(`--direct-voxels is only available in the dev environment (this project is on "${environment.name}"). `
366
- + 'Omit it to generate through the mesh path.');
367
- }
368
- /**
369
- * Refuses `--voxel-grid` without `--direct-voxels`, rather than ignoring it.
355
+ * Refuses `--voxel-grid` alongside `--mesh`, rather than ignoring it.
370
356
  *
371
357
  * The grid only reaches the `prop-voxel` generator, so on the mesh path the flag does nothing at
372
358
  * all — and it is the one flag whose whole point is a decision that cannot be revisited later
373
359
  * (see DEFAULT_MASTER_GRID). Silently dropping it is how a creator ends up believing they asked
374
360
  * for a finer master and finding out months later, when a re-voxelize refuses.
375
361
  */
376
- export function assertVoxelGridAllowed(voxelGrid, directVoxels) {
377
- if (voxelGrid === undefined || directVoxels)
362
+ export function assertVoxelGridAllowed(voxelGrid, mesh) {
363
+ if (voxelGrid === undefined || !mesh)
378
364
  return;
379
- throw new CliError('--voxel-grid only applies to --direct-voxels, which this run did not ask for. The mesh path '
365
+ throw new CliError('--voxel-grid has no meaning with --mesh: there is no voxel master to forge, and the mesh path '
380
366
  + 'voxelizes at --voxel-size instead. world.json is unchanged.');
381
367
  }
368
+ /**
369
+ * Refuses a run that names two sources to bake from.
370
+ *
371
+ * Each flag skips the paid generation and points the bake at something the caller already has, and
372
+ * they point at different things. Picking a winner silently would bake one and leave the creator
373
+ * believing they had baked the other.
374
+ */
375
+ export function assertOneRetrySource(glbUrl, masterUrl) {
376
+ if (glbUrl === undefined || masterUrl === undefined)
377
+ return;
378
+ throw new CliError('Pass either --glb-url or --master-url, not both — they name different sources to bake from. '
379
+ + 'world.json is unchanged.');
380
+ }
382
381
  /**
383
382
  * The grid flag's value, validated against the generator's own allowlist.
384
383
  *
@@ -403,24 +402,56 @@ export function parseVoxelGridFlag(raw) {
403
402
  */
404
403
  const VOXEL_GRID_FLAG = {
405
404
  type: 'string',
406
- description: 'With --direct-voxels: the grid the stored voxel master is forged at (default '
405
+ description: 'The grid the stored voxel master is forged at (default '
407
406
  + `${DEFAULT_MASTER_GRID}, one of ${propVoxelGrids.join('/')}, 0 keeps the generator's own). `
408
407
  + 'A master can only ever be re-baked COARSER, so this is the ceiling on every later '
409
408
  + '`bitmagic assets revoxelize` — lower it only to save storage on something you will never '
410
- + 'want in more detail.',
409
+ + 'want in more detail. Not valid with --mesh.',
411
410
  };
412
411
  /** The parsed flag as a spreadable field, so `undefined` never reaches an exactOptionalProperty. */
413
412
  function voxelGridField(raw) {
414
413
  const voxelGrid = parseVoxelGridFlag(raw);
415
414
  return voxelGrid === undefined ? {} : { voxelGrid };
416
415
  }
416
+ /**
417
+ * The way back to a mesh source, now that voxels are the default.
418
+ *
419
+ * Worth having rather than "voxels always": the two sources are not interchangeable in one
420
+ * respect. A mesh is resolution-independent, so it is the only source a later
421
+ * `bitmagic assets revoxelize` can take arbitrarily finer; a master is capped at the grid it was
422
+ * forged at. Someone who knows they will want more detail later than 512³ can hold at that height
423
+ * has a reason to ask for the mesh, and it should not require knowing an env var.
424
+ */
425
+ const MESH_FLAG = {
426
+ type: 'boolean',
427
+ description: 'Generate a mesh and voxelize it, instead of voxels direct from the generator. '
428
+ + 'Slower and far larger, but the stored source can later be re-voxelized to any resolution.',
429
+ };
430
+ /**
431
+ * The flag that used to turn the voxel path on, kept working as a no-op.
432
+ *
433
+ * It is in shell history, in `.bitmagic/edit/events.jsonl` journal entries and in whatever a
434
+ * creator's agent wrote down last week, and every one of those now asks for exactly what it gets
435
+ * anyway. Erroring would teach nothing that silence does not.
436
+ */
437
+ const DIRECT_VOXELS_FLAG = {
438
+ type: 'boolean',
439
+ description: 'Deprecated and ignored — direct voxels are the default. Pass --mesh for the old '
440
+ + 'behaviour.',
441
+ };
442
+ /** The voxel path's `--glb-url`: a paid-for master to bake, instead of buying another. */
443
+ const MASTER_URL_FLAG = {
444
+ type: 'string',
445
+ description: 'Bake this existing voxel master instead of generating one — how to retry for free '
446
+ + 'when a bake failed after the generation was billed.',
447
+ };
417
448
  export async function runPropGeneration(options) {
418
449
  const output = createOutput(options.json);
419
450
  const runDeps = options.deps ?? defaultDeps(options.json);
451
+ assertVoxelGridAllowed(options.voxelGrid, options.mesh === true);
452
+ assertOneRetrySource(options.glbUrl, options.masterUrl);
420
453
  const context = loadProjectContext(runDeps.startDir);
421
454
  const environment = resolveEnvironmentForCommand({ cwd: context.root, baseDir: runDeps.baseDir });
422
- assertDirectVoxelsAllowed(environment, options.directVoxels === true);
423
- assertVoxelGridAllowed(options.voxelGrid, options.directVoxels === true);
424
455
  const token = await getAccessToken(environment, resolveAuth0ClientId(environment), { fetch: runDeps.fetch, sleep: runDeps.sleep, now: runDeps.now }, runDeps.baseDir);
425
456
  const result = await withJobRecord({
426
457
  root: context.root,
@@ -440,7 +471,8 @@ export async function runPropGeneration(options) {
440
471
  assetId: options.assetId,
441
472
  prompt: options.prompt,
442
473
  ...(options.glbUrl ? { glbUrl: options.glbUrl } : {}),
443
- ...(options.directVoxels === true ? { directVoxels: true } : {}),
474
+ ...(options.masterUrl ? { masterUrl: options.masterUrl } : {}),
475
+ ...(options.mesh === true ? { mesh: true } : {}),
444
476
  ...(options.voxelGrid !== undefined ? { voxelGrid: options.voxelGrid } : {}),
445
477
  fetchImpl: runDeps.fetch,
446
478
  log,
@@ -534,10 +566,10 @@ export async function runVehicleGeneration(options) {
534
566
  export async function runModelGeneration(options) {
535
567
  const output = createOutput(options.json);
536
568
  const runDeps = options.deps ?? defaultDeps(options.json);
569
+ assertVoxelGridAllowed(options.voxelGrid, options.mesh === true);
570
+ assertOneRetrySource(options.glbUrl, options.masterUrl);
537
571
  const context = loadProjectContext(runDeps.startDir);
538
572
  const environment = resolveEnvironmentForCommand({ cwd: context.root, baseDir: runDeps.baseDir });
539
- assertDirectVoxelsAllowed(environment, options.directVoxels === true);
540
- assertVoxelGridAllowed(options.voxelGrid, options.directVoxels === true);
541
573
  const token = await getAccessToken(environment, resolveAuth0ClientId(environment), { fetch: runDeps.fetch, sleep: runDeps.sleep, now: runDeps.now }, runDeps.baseDir);
542
574
  const result = await withJobRecord({
543
575
  root: context.root,
@@ -556,7 +588,8 @@ export async function runModelGeneration(options) {
556
588
  ...(options.name !== undefined ? { name: options.name } : {}),
557
589
  ...(options.assetId !== undefined ? { assetId: options.assetId } : {}),
558
590
  ...(options.glbUrl !== undefined ? { glbUrl: options.glbUrl } : {}),
559
- ...(options.directVoxels === true ? { directVoxels: true } : {}),
591
+ ...(options.masterUrl !== undefined ? { masterUrl: options.masterUrl } : {}),
592
+ ...(options.mesh === true ? { mesh: true } : {}),
560
593
  ...(options.voxelGrid !== undefined ? { voxelGrid: options.voxelGrid } : {}),
561
594
  voxel: {
562
595
  minVoxelSize: options.minVoxelSize,
@@ -878,11 +911,9 @@ const propCommand = defineCommand({
878
911
  type: 'string',
879
912
  description: 'Voxelize this existing mesh instead of generating one — how to retry for free.',
880
913
  },
881
- 'direct-voxels': {
882
- type: 'boolean',
883
- description: 'Dev only. Generate voxels directly instead of a mesh the bake then discards — '
884
- + 'smaller and faster, but newer. Falls back to the mesh path if it is unavailable.',
885
- },
914
+ 'master-url': MASTER_URL_FLAG,
915
+ mesh: MESH_FLAG,
916
+ 'direct-voxels': DIRECT_VOXELS_FLAG,
886
917
  'voxel-grid': VOXEL_GRID_FLAG,
887
918
  'original-prompt': ORIGINAL_PROMPT_FLAG,
888
919
  json: JSON_FLAG,
@@ -892,7 +923,8 @@ const propCommand = defineCommand({
892
923
  assetId: args.asset,
893
924
  prompt: args.prompt,
894
925
  ...(args['glb-url'] ? { glbUrl: args['glb-url'] } : {}),
895
- ...(args['direct-voxels'] === true ? { directVoxels: true } : {}),
926
+ ...(args['master-url'] ? { masterUrl: args['master-url'] } : {}),
927
+ ...(args.mesh === true ? { mesh: true } : {}),
896
928
  ...(voxelGridField(args['voxel-grid'])),
897
929
  json: args.json === true,
898
930
  });
@@ -982,11 +1014,9 @@ const modelCommand = defineCommand({
982
1014
  type: 'string',
983
1015
  description: 'Voxelize this existing mesh instead of generating one — how to retry for free.',
984
1016
  },
985
- 'direct-voxels': {
986
- type: 'boolean',
987
- description: 'Dev only. Generate voxels directly instead of a mesh the bake then discards — '
988
- + 'smaller and faster, but newer. Falls back to the mesh path if it is unavailable.',
989
- },
1017
+ 'master-url': MASTER_URL_FLAG,
1018
+ mesh: MESH_FLAG,
1019
+ 'direct-voxels': DIRECT_VOXELS_FLAG,
990
1020
  'voxel-grid': VOXEL_GRID_FLAG,
991
1021
  'original-prompt': ORIGINAL_PROMPT_FLAG,
992
1022
  json: JSON_FLAG,
@@ -1015,7 +1045,8 @@ const modelCommand = defineCommand({
1015
1045
  fillInterior: args.solid === true
1016
1046
  || (args.hollow !== true && (targetHeight === undefined || targetHeight <= SOLID_FILL_MAX_HEIGHT_M)),
1017
1047
  ...(args['glb-url'] !== undefined ? { glbUrl: args['glb-url'] } : {}),
1018
- ...(args['direct-voxels'] === true ? { directVoxels: true } : {}),
1048
+ ...(args['master-url'] !== undefined ? { masterUrl: args['master-url'] } : {}),
1049
+ ...(args.mesh === true ? { mesh: true } : {}),
1019
1050
  ...(voxelGridField(args['voxel-grid'])),
1020
1051
  json: args.json === true,
1021
1052
  });