@bitmagic/cli 0.1.61-dev.0 → 0.1.61-dev.1

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.
Files changed (119) hide show
  1. package/README.md +47 -8
  2. package/assets/fonts/NotoSans-Bold.ttf +0 -0
  3. package/assets/fonts/OFL.txt +94 -0
  4. package/dist/chrome-launch.d.ts +18 -0
  5. package/dist/chrome-launch.js +24 -0
  6. package/dist/chrome-launch.js.map +1 -0
  7. package/dist/cli.d.ts +1 -0
  8. package/dist/cli.js +2 -0
  9. package/dist/cli.js.map +1 -1
  10. package/dist/commands/generate.d.ts +44 -0
  11. package/dist/commands/generate.js +143 -0
  12. package/dist/commands/generate.js.map +1 -1
  13. package/dist/commands/trailer-publish.d.ts +15 -0
  14. package/dist/commands/trailer-publish.js +45 -0
  15. package/dist/commands/trailer-publish.js.map +1 -0
  16. package/dist/commands/trailer.d.ts +3 -0
  17. package/dist/commands/trailer.js +396 -0
  18. package/dist/commands/trailer.js.map +1 -0
  19. package/dist/editor/hud-replay-page.d.ts +7 -0
  20. package/dist/editor/hud-replay-page.js +219 -0
  21. package/dist/editor/hud-replay-page.js.map +1 -0
  22. package/dist/editor/recording-panel.d.ts +3 -1
  23. package/dist/editor/recording-panel.js +6 -2
  24. package/dist/editor/recording-panel.js.map +1 -1
  25. package/dist/editor/recording-sink.d.ts +3 -20
  26. package/dist/editor/recording-sink.js +14 -35
  27. package/dist/editor/recording-sink.js.map +1 -1
  28. package/dist/editor/server.js +15 -18
  29. package/dist/editor/server.js.map +1 -1
  30. package/dist/editor/shell-page.d.ts +0 -8
  31. package/dist/editor/shell-page.js +23 -19
  32. package/dist/editor/shell-page.js.map +1 -1
  33. package/dist/generate/music.d.ts +51 -0
  34. package/dist/generate/music.js +93 -0
  35. package/dist/generate/music.js.map +1 -0
  36. package/dist/generate/stream.d.ts +13 -0
  37. package/dist/generate/stream.js +17 -1
  38. package/dist/generate/stream.js.map +1 -1
  39. package/dist/project/jobs.d.ts +1 -1
  40. package/dist/scaffold/project-files.d.ts +0 -1
  41. package/dist/scaffold/project-files.js +6 -33
  42. package/dist/scaffold/project-files.js.map +1 -1
  43. package/dist/scaffold/project.js +3 -1
  44. package/dist/scaffold/project.js.map +1 -1
  45. package/dist/scaffold/skill-files.d.ts +22 -0
  46. package/dist/scaffold/skill-files.js +198 -0
  47. package/dist/scaffold/skill-files.js.map +1 -0
  48. package/dist/trailer/analyze.d.ts +23 -0
  49. package/dist/trailer/analyze.js +186 -0
  50. package/dist/trailer/analyze.js.map +1 -0
  51. package/dist/trailer/auto-edl.d.ts +46 -0
  52. package/dist/trailer/auto-edl.js +143 -0
  53. package/dist/trailer/auto-edl.js.map +1 -0
  54. package/dist/trailer/beat-cut.d.ts +57 -0
  55. package/dist/trailer/beat-cut.js +232 -0
  56. package/dist/trailer/beat-cut.js.map +1 -0
  57. package/dist/trailer/client.d.ts +52 -0
  58. package/dist/trailer/client.js +133 -0
  59. package/dist/trailer/client.js.map +1 -0
  60. package/dist/trailer/edl-time.d.ts +61 -0
  61. package/dist/trailer/edl-time.js +105 -0
  62. package/dist/trailer/edl-time.js.map +1 -0
  63. package/dist/trailer/ffmpeg.d.ts +8 -0
  64. package/dist/trailer/ffmpeg.js +55 -0
  65. package/dist/trailer/ffmpeg.js.map +1 -0
  66. package/dist/trailer/hud-raster.d.ts +28 -0
  67. package/dist/trailer/hud-raster.js +114 -0
  68. package/dist/trailer/hud-raster.js.map +1 -0
  69. package/dist/trailer/hud-state.d.ts +110 -0
  70. package/dist/trailer/hud-state.js +410 -0
  71. package/dist/trailer/hud-state.js.map +1 -0
  72. package/dist/trailer/io.d.ts +20 -0
  73. package/dist/trailer/io.js +15 -0
  74. package/dist/trailer/io.js.map +1 -0
  75. package/dist/trailer/make.d.ts +54 -0
  76. package/dist/trailer/make.js +205 -0
  77. package/dist/trailer/make.js.map +1 -0
  78. package/dist/trailer/merge.d.ts +7 -0
  79. package/dist/trailer/merge.js +144 -0
  80. package/dist/trailer/merge.js.map +1 -0
  81. package/dist/trailer/music-beats.d.ts +123 -0
  82. package/dist/trailer/music-beats.js +707 -0
  83. package/dist/trailer/music-beats.js.map +1 -0
  84. package/dist/trailer/paths.d.ts +28 -0
  85. package/dist/trailer/paths.js +101 -0
  86. package/dist/trailer/paths.js.map +1 -0
  87. package/dist/trailer/publish-record.d.ts +17 -0
  88. package/dist/trailer/publish-record.js +59 -0
  89. package/dist/trailer/publish-record.js.map +1 -0
  90. package/dist/trailer/publish.d.ts +45 -0
  91. package/dist/trailer/publish.js +149 -0
  92. package/dist/trailer/publish.js.map +1 -0
  93. package/dist/trailer/record-session.d.ts +72 -0
  94. package/dist/trailer/record-session.js +328 -0
  95. package/dist/trailer/record-session.js.map +1 -0
  96. package/dist/trailer/render.d.ts +57 -0
  97. package/dist/trailer/render.js +475 -0
  98. package/dist/trailer/render.js.map +1 -0
  99. package/dist/trailer/revision.d.ts +8 -0
  100. package/dist/trailer/revision.js +31 -0
  101. package/dist/trailer/revision.js.map +1 -0
  102. package/dist/trailer/synth.d.ts +9 -0
  103. package/dist/trailer/synth.js +120 -0
  104. package/dist/trailer/synth.js.map +1 -0
  105. package/dist/trailer/timeline-types.d.ts +176 -0
  106. package/dist/trailer/timeline-types.js +379 -0
  107. package/dist/trailer/timeline-types.js.map +1 -0
  108. package/dist/trailer/title-raster.d.ts +6 -0
  109. package/dist/trailer/title-raster.js +47 -0
  110. package/dist/trailer/title-raster.js.map +1 -0
  111. package/dist/trailer/titles.d.ts +44 -0
  112. package/dist/trailer/titles.js +119 -0
  113. package/dist/trailer/titles.js.map +1 -0
  114. package/dist/trailer/video-chain.d.ts +41 -0
  115. package/dist/trailer/video-chain.js +78 -0
  116. package/dist/trailer/video-chain.js.map +1 -0
  117. package/dist/verify/browser.js +12 -19
  118. package/dist/verify/browser.js.map +1 -1
  119. package/package.json +5 -4
package/README.md CHANGED
@@ -202,7 +202,7 @@ browser reloads itself on every change and the assets panel shows each generatio
202
202
  | `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. |
203
203
  | `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. |
204
204
  | `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. |
205
- | `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. |
205
+ | `bitmagic generate <skybox\|background\|block-type\|sound\|music\|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. |
206
206
  | `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. |
207
207
  | `bitmagic assets list` | The assets in `world.json`: id, name, type, size, placed instances, and total references. Local, no network. |
208
208
  | `bitmagic assets materials <assetId> [--set <file.json>] [--auto] [--clear]` | Show what an asset's voxels look like, or say what they are **made of** — so a sword's steel blade shines and its leather grip does not. With no flag it prints the asset's colour groups; `--set` applies your verdicts; `--auto` lets a model decide (what `generate prop` and `generate model` already do on their own); `--clear` removes them. Free — no sparks, nothing generated. See **Voxel materials** below. |
@@ -210,6 +210,10 @@ browser reloads itself on every change and the assets panel shows each generatio
210
210
  | `bitmagic cover [--prompt "..."] [--force] [--no-start-screen]` | Generate the game's cover art from `GAME-DESIGN.md`: sets the start screen, saves `.bitmagic/cover.webp`, becomes the publish thumbnail. Costs sparks. |
211
211
  | `bitmagic reference <make\|accept\|show\|clear> ...` | Make a concept image of the game's world, iterate until it is right, and `accept` one — the accepted image becomes the default style reference for `generate skybox\|background\|block-type\|image`, `cover` and `forge`. Only `make` costs sparks (priced like an image). See **Reference image** below. |
212
212
  | `bitmagic judge [--genre <name>] [--platform desktop\|mobile] [--min-score <1-10>]` | Grade the screenshot `bitmagic verify` captured against a quality rubric built from `GAME-DESIGN.md` (plus an optional genre hint) with a vision model, and print a scorecard: four dimension scores and at most three actionable findings, also written to `.bitmagic/judge.json`. Informs rather than gates — exits 0 whatever the score, unless `--min-score` sets a bar (exit 4 below it). `--platform` picks which frame to grade; with no flag it grades the mobile one when the game is mobile-primary and `screenshot.mobile.png` exists, and the mobile rubric folds touch-HUD legibility, thumb reach and phone framing into the existing `readability` and `polish` dimensions rather than adding a fifth score. Warns when the project changed since the screenshot. Costs sparks (a few per run — one call to a model that reasons about the frame before it scores). |
213
+ | `bitmagic trailer record [--seconds N] [--resolution WxH] [--flythrough <path.json>]` | Record gameplay for a trailer: opens Chrome on the running `bitmagic dev`, waits for Play, starts the engine's F9 recorder for you, stops after N seconds or your F9, and prints the recording dir (`.bitmagic/trailer/recordings/<name>/`). `--flythrough` records an authored camera path with nobody playing. |
214
+ | `bitmagic trailer make [--music-prompt "..." \| --music <file> \| --no-music] [--title <t>] [--seconds 30] [--ui] [--publish] [--reset-shots]` | The one-shot: analyze the newest recording, lay a music bed (generated from a prompt — sparks — or your file), write a first cut to `trailer/shots.json` or cut the one you edited, render `<game>-trailer.mp4` (new `-rN` each run), and with `--publish` put it on the CDN and the game page. |
215
+ | `bitmagic trailer analyze \| beats \| cut \| render \| merge` | The steps of `make` as separate commands: score a recording into highlight windows with contact sheets; detect a track's beat grid; turn `trailer/shots.json` into a frame-exact `edl.json`; render an EDL (`--ui` redraws the HUD, `--logo`, `--music …`); join recordings from separate sittings. |
216
+ | `bitmagic trailer publish <file.mp4> [--no-attach]` | Upload a trailer (`.mp4`/`.webm`, ≤ 200 MiB, header-checked so a renamed image is refused before upload) to the CDN under `game-media/<gameId>/` and put it at the front of the game page gallery. Re-running replaces the previous trailer (remembered in `.bitmagic/trailer/published.json`); the page is capped at 12 media items. Works before the first publish — the page goes live on the first `bitmagic publish --visibility public`. `--no-attach` uploads only. |
213
217
  | `bitmagic forge --prompt "..." [--city\|--dungeon\|--platformer\|--freeform] [--name <name>] [--resume <jobId>]` | Design and bake a whole playable level into `world.json`. Costs sparks, and takes many minutes — the bake alone can take twenty. `--resume <jobId>` picks a failed run back up from the last step that finished, rather than redoing the whole thing. |
214
218
  | `bitmagic levels <list\|add\|rename\|set-start\|remove> ...` | Manage the levels `forge` creates: which one boots, their names, registering a bake you already have, deleting one. Local, no network, no sparks. See **Managing levels** below. |
215
219
 
@@ -406,7 +410,9 @@ my-game/
406
410
  GAME-DESIGN.md # what the game is — yours to write; bitmagic cover reads it
407
411
  .claude/
408
412
  settings.json # yours; seeded with a Stop hook that runs `bitmagic reload`
409
- skills/ # generating-assets is shipped by the CLI; your own are untouched
413
+ skills/ # generating-assets, making-a-trailer, … are shipped by the CLI; your own are untouched
414
+ trailer/
415
+ shots.json # the trailer's cut — which moments, how long, the end card; bitmagic trailer make re-cuts from it
410
416
  .bitmagic/
411
417
  cover.webp # bitmagic cover's artwork — the publish thumbnail when present
412
418
  cover.json # its URL and the design hash it was generated from
@@ -416,6 +422,10 @@ my-game/
416
422
  dev.json # the running `bitmagic dev`'s ports, so `bitmagic reload` finds it
417
423
  mobile-qr.png # the phone URL as a QR code, written when --mobile cannot draw one
418
424
  jobs/ # one file per generation in flight — what the assets panel reads
425
+ trailer/
426
+ recordings/<name>/ # F9 recordings: <name>_%06d.png at 60 fps + timeline.json
427
+ <name>/ # that recording's analysis.json, sheets/, beats.json, music.mp3, edl.json and renders
428
+ published.json # the trailer's CDN URL after bitmagic trailer publish
419
429
  previews/ # rendered asset thumbnails, cached so they are drawn once
420
430
  build/
421
431
  index.html # bitmagic build's output bundle
@@ -528,6 +538,36 @@ Candidates cost sparks like any image generation; `accept`, `show` and `clear` a
528
538
  `.bitmagic/` is not committed, so paste the accepted URL into `GAME-DESIGN.md` — on a fresh clone,
529
539
  `bitmagic reference accept <url>` re-accepts the same image from that line.
530
540
 
541
+ ## Making a trailer
542
+
543
+ `bitmagic trailer` takes gameplay to a published trailer, and your agent is the editor. With
544
+ `bitmagic dev` running:
545
+
546
+ ```bash
547
+ bitmagic trailer record --seconds 60 # Chrome opens on the dev view; press Play and play well
548
+ bitmagic trailer make --music-prompt "driving synthwave, no vocals" --title "Joyride" --publish
549
+ ```
550
+
551
+ `record` starts the engine's F9 recorder for you and stops it after the time is up (or when you
552
+ press F9); frames and a `timeline.json` of events, sounds and HUD state land in
553
+ `.bitmagic/trailer/recordings/<name>/`. `make` scores the timeline into highlight windows (with a
554
+ contact sheet per window under `.bitmagic/trailer/<name>/sheets/`), generates a music bed from the
555
+ prompt (`bitmagic generate music`, billed per second — `--music <file>` uses your own track,
556
+ `--no-music` skips it), writes a first cut to **`trailer/shots.json`**, snaps every cut to the beat,
557
+ renders `<game>-trailer.mp4` with the game's own sounds reconstructed under the music, and with
558
+ `--publish` uploads it and puts it first in your game page's gallery, printing the URL.
559
+
560
+ Tuning is editing `trailer/shots.json` — which moments (`in` is a source frame at 60 fps), how
561
+ long (`beats` with music, `seconds` without), in what order, with what end card — and running
562
+ `bitmagic trailer make` again: every render is a new `-rN` file, so nothing is lost. The shipped
563
+ `making-a-trailer` skill teaches your agent the craft (ordering, pacing, variety, what not to do)
564
+ and how to turn "faster", "more crashes" or "title at the end" into that edit. `--ui` redraws the
565
+ recorded HUD over the footage through the running dev view. No one to play? Author a camera path
566
+ in `trailer/flythrough.json` and `bitmagic trailer record --flythrough trailer/flythrough.json`
567
+ records a fly-through with nobody at the keyboard.
568
+
569
+ Needs `ffmpeg` and Google Chrome on this machine; each command says so if one is missing.
570
+
531
571
  ## The dev view
532
572
 
533
573
  `bitmagic dev` is meant to be started once and left running, beside your agent:
@@ -596,12 +636,11 @@ open, and they only reach the page when the chrome has focus: click into the gam
596
636
  your keys, which is what you want — press F9 there and the recorder starts.
597
637
 
598
638
  **Record gameplay…** in the **⋯** menu holds the recording settings; the recording itself is a key.
599
- It appears only on the dev line — a build installed with `npm i -g @bitmagic/cli@dev` — while the
600
- feature is still settling; a release build has no such row and no sink. Press **F9**
601
- in the game to start, play, press F9 again to stop. In the default frame-by-frame mode the engine
602
- renders every frame at the chosen resolution — 60 fps output regardless of how fast your machine
603
- renders — and streams them to `~/Downloads/gameplay_recording_*/` along with a `timeline.json` of
604
- game events, sounds and HUD state, ready to be cut into a trailer. Video mode instead captures in
639
+ Press **F9** in the game to start, play, press F9 again to stop — or let `bitmagic trailer record`
640
+ do the pressing. In the default frame-by-frame mode the engine renders every frame at the chosen
641
+ resolution — 60 fps output regardless of how fast your machine renders — and streams them to this
642
+ project's `.bitmagic/trailer/recordings/gameplay_recording_*/` along with a `timeline.json` of game
643
+ events, sounds and HUD state, ready for `bitmagic trailer make`. Video mode instead captures in
605
644
  real time and downloads a `.webm`. If the panel says your project's engine is too old for the disk
606
645
  streaming, run `bitmagic upgrade` and reload.
607
646
 
Binary file
@@ -0,0 +1,94 @@
1
+ Copyright 2022 The Noto Project Authors (https://github.com/notofonts/)
2
+
3
+ This Font Software is licensed under the SIL Open Font License,
4
+ Version 1.1.
5
+
6
+ This license is copied below, and is also available with a FAQ at:
7
+ http://scripts.sil.org/OFL
8
+
9
+ -----------------------------------------------------------
10
+ SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
11
+ -----------------------------------------------------------
12
+
13
+ PREAMBLE
14
+ The goals of the Open Font License (OFL) are to stimulate worldwide
15
+ development of collaborative font projects, to support the font
16
+ creation efforts of academic and linguistic communities, and to
17
+ provide a free and open framework in which fonts may be shared and
18
+ improved in partnership with others.
19
+
20
+ The OFL allows the licensed fonts to be used, studied, modified and
21
+ redistributed freely as long as they are not sold by themselves. The
22
+ fonts, including any derivative works, can be bundled, embedded,
23
+ redistributed and/or sold with any software provided that any reserved
24
+ names are not used by derivative works. The fonts and derivatives,
25
+ however, cannot be released under any other type of license. The
26
+ requirement for fonts to remain under this license does not apply to
27
+ any document created using the fonts or their derivatives.
28
+
29
+ DEFINITIONS
30
+ "Font Software" refers to the set of files released by the Copyright
31
+ Holder(s) under this license and clearly marked as such. This may
32
+ include source files, build scripts and documentation.
33
+
34
+ "Reserved Font Name" refers to any names specified as such after the
35
+ copyright statement(s).
36
+
37
+ "Original Version" refers to the collection of Font Software
38
+ components as distributed by the Copyright Holder(s).
39
+
40
+ "Modified Version" refers to any derivative made by adding to,
41
+ deleting, or substituting -- in part or in whole -- any of the
42
+ components of the Original Version, by changing formats or by porting
43
+ the Font Software to a new environment.
44
+
45
+ "Author" refers to any designer, engineer, programmer, technical
46
+ writer or other person who contributed to the Font Software.
47
+
48
+ PERMISSION & CONDITIONS
49
+ Permission is hereby granted, free of charge, to any person obtaining
50
+ a copy of the Font Software, to use, study, copy, merge, embed,
51
+ modify, redistribute, and sell modified and unmodified copies of the
52
+ Font Software, subject to the following conditions:
53
+
54
+ 1) Neither the Font Software nor any of its individual components, in
55
+ Original or Modified Versions, may be sold by itself.
56
+
57
+ 2) Original or Modified Versions of the Font Software may be bundled,
58
+ redistributed and/or sold with any software, provided that each copy
59
+ contains the above copyright notice and this license. These can be
60
+ included either as stand-alone text files, human-readable headers or
61
+ in the appropriate machine-readable metadata fields within text or
62
+ binary files as long as those fields can be easily viewed by the user.
63
+
64
+ 3) No Modified Version of the Font Software may use the Reserved Font
65
+ Name(s) unless explicit written permission is granted by the
66
+ corresponding Copyright Holder. This restriction only applies to the
67
+ primary font name as presented to the users.
68
+
69
+ 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
70
+ Software shall not be used to promote, endorse or advertise any
71
+ Modified Version, except to acknowledge the contribution(s) of the
72
+ Copyright Holder(s) and the Author(s) or with their explicit written
73
+ permission.
74
+
75
+ 5) The Font Software, modified or unmodified, in part or in whole,
76
+ must be distributed entirely under this license, and must not be
77
+ distributed under any other license. The requirement for fonts to
78
+ remain under this license does not apply to any document created using
79
+ the Font Software.
80
+
81
+ TERMINATION
82
+ This license becomes null and void if any of the above conditions are
83
+ not met.
84
+
85
+ DISCLAIMER
86
+ THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
87
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
88
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
89
+ OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
90
+ COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
91
+ INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
92
+ DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
93
+ FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
94
+ OTHER DEALINGS IN THE FONT SOFTWARE.
@@ -0,0 +1,18 @@
1
+ /**
2
+ * The one way this CLI starts Google Chrome.
3
+ *
4
+ * `channel: 'chrome'` drives the browser the creator already has installed rather than a
5
+ * Playwright-downloaded one, so installing the CLI stays a small, fast npm install. The cost is
6
+ * that Chrome can be missing — and a missing browser must never read as a failure of the thing
7
+ * the command was checking or recording, so the refusal names the browser and the command, not
8
+ * the game.
9
+ */
10
+ import { type Browser } from 'playwright-core';
11
+ export interface ChromeLaunchOptions {
12
+ headless: boolean;
13
+ args: string[];
14
+ /** The command to name in the refusal, e.g. `bitmagic verify`. */
15
+ command: string;
16
+ }
17
+ export declare function chromeMissingMessage(command: string): string;
18
+ export declare function launchSystemChrome(options: ChromeLaunchOptions): Promise<Browser>;
@@ -0,0 +1,24 @@
1
+ /**
2
+ * The one way this CLI starts Google Chrome.
3
+ *
4
+ * `channel: 'chrome'` drives the browser the creator already has installed rather than a
5
+ * Playwright-downloaded one, so installing the CLI stays a small, fast npm install. The cost is
6
+ * that Chrome can be missing — and a missing browser must never read as a failure of the thing
7
+ * the command was checking or recording, so the refusal names the browser and the command, not
8
+ * the game.
9
+ */
10
+ import { chromium } from 'playwright-core';
11
+ import { CliError } from './errors.js';
12
+ export function chromeMissingMessage(command) {
13
+ return (`Could not launch Google Chrome. \`${command}\` drives the Chrome installed on this machine — ` +
14
+ `install it from https://www.google.com/chrome/ and run the command again.`);
15
+ }
16
+ export async function launchSystemChrome(options) {
17
+ try {
18
+ return await chromium.launch({ headless: options.headless, channel: 'chrome', args: options.args });
19
+ }
20
+ catch {
21
+ throw new CliError(chromeMissingMessage(options.command), 1, 'chrome_missing');
22
+ }
23
+ }
24
+ //# sourceMappingURL=chrome-launch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chrome-launch.js","sourceRoot":"","sources":["../src/chrome-launch.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,QAAQ,EAAgB,MAAM,iBAAiB,CAAC;AACzD,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AASvC,MAAM,UAAU,oBAAoB,CAAC,OAAe;IAClD,OAAO,CACL,qCAAqC,OAAO,mDAAmD;QAC/F,2EAA2E,CAC5E,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,OAA4B;IACnE,IAAI,CAAC;QACH,OAAO,MAAM,QAAQ,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IACtG,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,QAAQ,CAAC,oBAAoB,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,gBAAgB,CAAC,CAAC;IACjF,CAAC;AACH,CAAC"}
package/dist/cli.d.ts CHANGED
@@ -334,6 +334,7 @@ declare const rawCommands: {
334
334
  readonly description: "Print the result as JSON on stdout; all progress goes to stderr.";
335
335
  };
336
336
  }>;
337
+ trailer: CommandDef<ArgsDef>;
337
338
  reference: CommandDef<ArgsDef>;
338
339
  judge: CommandDef<{
339
340
  readonly genre: {
package/dist/cli.js CHANGED
@@ -25,6 +25,7 @@ import { assetsCommand } from './commands/assets.js';
25
25
  import { levelsCommand } from './commands/levels.js';
26
26
  import { themeCommand } from './commands/theme.js';
27
27
  import { coverCommand } from './commands/cover.js';
28
+ import { trailerCommand } from './commands/trailer.js';
28
29
  import { referenceCommand } from './commands/reference.js';
29
30
  import { judgeCommand } from './commands/judge.js';
30
31
  import { forgeCommand } from './commands/forge.js';
@@ -211,6 +212,7 @@ const rawCommands = {
211
212
  levels: levelsCommand,
212
213
  theme: themeCommand,
213
214
  cover: coverCommand,
215
+ trailer: trailerCommand,
214
216
  reference: referenceCommand,
215
217
  judge: judgeCommand,
216
218
  forge: forgeCommand,
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -30,6 +30,21 @@ export interface SoundArgs {
30
30
  loop?: boolean;
31
31
  }
32
32
  export declare function buildSoundBody(args: SoundArgs): Record<string, unknown>;
33
+ export interface MusicArgs {
34
+ prompt: string;
35
+ duration?: string;
36
+ instrumental?: boolean;
37
+ /** citty's boolean pair: `--loop` arrives as true, `--no-loop` as false, neither as undefined. */
38
+ loop?: boolean;
39
+ assetId?: string;
40
+ }
41
+ /**
42
+ * The same omission contract as {@link buildSoundBody}: `loop` is only sent when the creator said
43
+ * so either way, because the generator's default (a music bed loops) is the generator's to own.
44
+ * The range is the generator schema's, restated so `--duration 5` is refused here, before a
45
+ * request is made — the plan's verification line 7.
46
+ */
47
+ export declare function buildMusicBody(args: MusicArgs): Record<string, unknown>;
33
48
  export interface ImageArgs {
34
49
  name: string;
35
50
  prompt: string;
@@ -132,6 +147,35 @@ export declare function runAssetGeneration(type: string, label: string, body: Re
132
147
  * dev view shows as running — exactly where it always happened.
133
148
  */
134
149
  export declare function requestAssetWithJobRecord<T>(type: string, label: string, body: Record<string, unknown>, runDeps: GenerateRunDeps, onSuccess: (outcome: GenerationOutcome, worldPath: string, log: (message: string) => void) => T): Promise<T>;
150
+ export interface MusicRunResult {
151
+ musicUrl: string;
152
+ originalUrl: string;
153
+ musicId: string;
154
+ durationSeconds: number;
155
+ patchesApplied: number;
156
+ /** Where the MP3 was saved, when `--out` asked for it. */
157
+ file?: string;
158
+ bytes?: number;
159
+ }
160
+ /**
161
+ * `generate music` is the one `generate` lane with two outputs a creator may want separately: the
162
+ * world.json asset (the default — what a game plays as its bed) and the MP3 file (`--out`, what a
163
+ * video editor or `bitmagic trailer make` wants). `--no-world` keeps the asset out of the game
164
+ * for the file-only case, so a trailer bed is not registered as a track the game never plays.
165
+ *
166
+ * Cannot go through {@link runAssetGeneration} because that always applies the patches and never
167
+ * downloads; it shares {@link requestAssetWithJobRecord} so the request, the job record and the
168
+ * "world.json is unchanged" failure contract are the same as every other lane's.
169
+ */
170
+ export declare function runMusicGeneration(options: {
171
+ body: Record<string, unknown>;
172
+ /** Save the MP3 here (relative to the current directory). */
173
+ out?: string;
174
+ /** Apply the asset to world.json. The default; `--no-world` turns it off. */
175
+ world: boolean;
176
+ json: boolean;
177
+ deps?: GenerateRunDeps;
178
+ }): Promise<MusicRunResult>;
135
179
  /**
136
180
  * Refuses `--voxel-grid` alongside `--mesh`, rather than ignoring it.
137
181
  *
@@ -22,6 +22,8 @@ import { describeAutoTrim, propVoxelGrids } from '@bitmagic/asset-core';
22
22
  import { DEFAULT_MASTER_GRID, generateAndInstallProp } from '../generate/prop.js';
23
23
  import { generateAndInstallVehicle } from '../generate/vehicle.js';
24
24
  import { generateAndInstallModel } from '../generate/model.js';
25
+ import { downloadMusicFile } from '../generate/music.js';
26
+ import { MUSIC_MAX_SECONDS, MUSIC_MIN_SECONDS } from '@bitmagic/asset-core';
25
27
  import { generateAndInstallAnimationFromVideo, isLocomotionState, isVideoToMotionModel, } from '../generate/animation-from-video.js';
26
28
  import { VIDEO_EXTENSIONS } from '../assets/file-kind.js';
27
29
  import { LOCOMOTION_STATES, VIDEO_TO_MOTION_MODELS } from '@bitmagic/asset-core';
@@ -75,6 +77,21 @@ export function buildSoundBody(args) {
75
77
  loop: args.loop,
76
78
  });
77
79
  }
80
+ /**
81
+ * The same omission contract as {@link buildSoundBody}: `loop` is only sent when the creator said
82
+ * so either way, because the generator's default (a music bed loops) is the generator's to own.
83
+ * The range is the generator schema's, restated so `--duration 5` is refused here, before a
84
+ * request is made — the plan's verification line 7.
85
+ */
86
+ export function buildMusicBody(args) {
87
+ return withoutAbsentFlags({
88
+ prompt: args.prompt,
89
+ durationSeconds: parseNumberFlag('duration', args.duration, { min: MUSIC_MIN_SECONDS, max: MUSIC_MAX_SECONDS }),
90
+ instrumental: args.instrumental,
91
+ loop: args.loop,
92
+ assetId: args.assetId,
93
+ });
94
+ }
78
95
  export function buildImageBody(args) {
79
96
  return withoutAbsentFlags({
80
97
  name: args.name,
@@ -437,6 +454,76 @@ export async function requestAssetWithJobRecord(type, label, body, runDeps, onSu
437
454
  return onSuccess(outcome, worldPath, log);
438
455
  });
439
456
  }
457
+ /**
458
+ * `generate music` is the one `generate` lane with two outputs a creator may want separately: the
459
+ * world.json asset (the default — what a game plays as its bed) and the MP3 file (`--out`, what a
460
+ * video editor or `bitmagic trailer make` wants). `--no-world` keeps the asset out of the game
461
+ * for the file-only case, so a trailer bed is not registered as a track the game never plays.
462
+ *
463
+ * Cannot go through {@link runAssetGeneration} because that always applies the patches and never
464
+ * downloads; it shares {@link requestAssetWithJobRecord} so the request, the job record and the
465
+ * "world.json is unchanged" failure contract are the same as every other lane's.
466
+ */
467
+ export async function runMusicGeneration(options) {
468
+ const output = createOutput(options.json);
469
+ const runDeps = options.deps ?? defaultDeps(options.json);
470
+ const outPath = options.out === undefined ? undefined : path.resolve(options.out);
471
+ const result = await requestAssetWithJobRecord('music', 'music', options.body, runDeps, async (outcome, worldPath, log) => {
472
+ if (!outcome.music) {
473
+ throw new CliError('The server reported the music as generated but sent no track URLs. world.json is unchanged.');
474
+ }
475
+ const { music } = outcome;
476
+ let patchesApplied = 0;
477
+ if (options.world) {
478
+ let applyResult;
479
+ try {
480
+ applyResult = applyPatchesToWorld(worldPath, outcome.patches);
481
+ }
482
+ catch (error) {
483
+ throw decoratedError(error, (message) => `Generated music successfully, but could not write it into world.json: ${message} `
484
+ + 'world.json is unchanged — the track was generated (and may have been billed) but is not '
485
+ + `yet in your project. It is at ${music.originalUrl}.`);
486
+ }
487
+ patchesApplied = applyResult.applied;
488
+ log(`Generated music (${music.durationSeconds.toFixed(1)}s): ${outcome.message}`);
489
+ for (const line of applyResult.summary)
490
+ runDeps.log(` - ${line}`);
491
+ runDeps.log(`world.json updated (${patchesApplied} patch${patchesApplied === 1 ? '' : 'es'}).`);
492
+ }
493
+ else {
494
+ log(`Generated music (${music.durationSeconds.toFixed(1)}s): ${outcome.message}`);
495
+ runDeps.log('world.json is unchanged (--no-world).');
496
+ }
497
+ let bytes;
498
+ if (outPath !== undefined) {
499
+ try {
500
+ bytes = await downloadMusicFile(music.originalUrl, outPath, runDeps.fetch);
501
+ }
502
+ catch (error) {
503
+ // The asset is generated, billed, and (unless --no-world) already in world.json; only the
504
+ // local copy is missing, and the message has to say so or the creator regenerates.
505
+ throw decoratedError(error, (message) => `${message} The track was generated${options.world ? ' and is in world.json' : ''}; only saving `
506
+ + 'the local copy failed.');
507
+ }
508
+ runDeps.log(`Saved ${outPath} (${Math.round(bytes / 1024)} KB).`);
509
+ }
510
+ return {
511
+ musicUrl: music.musicUrl,
512
+ originalUrl: music.originalUrl,
513
+ musicId: music.musicId,
514
+ durationSeconds: music.durationSeconds,
515
+ patchesApplied,
516
+ ...(outPath !== undefined ? { file: outPath } : {}),
517
+ ...(bytes !== undefined ? { bytes } : {}),
518
+ };
519
+ });
520
+ output.result({ ok: true, kind: 'music', ...result });
521
+ if (options.world) {
522
+ runDeps.log(`Play it from game code with engine.playMusic('${result.musicId}').`);
523
+ runDeps.log(DEV_VIEW_RELOADS);
524
+ }
525
+ return result;
526
+ }
440
527
  /**
441
528
  * Refuses `--voxel-grid` alongside `--mesh`, rather than ignoring it.
442
529
  *
@@ -894,6 +981,61 @@ const soundCommand = defineCommand({
894
981
  await runAssetGeneration('sound-effect', 'sound effect', withParent(body), args.json === true);
895
982
  },
896
983
  });
984
+ const musicCommand = defineCommand({
985
+ meta: {
986
+ name: 'music',
987
+ description: 'Compose a music track from a prompt and add it to world.json assets (or save it as a file).',
988
+ },
989
+ args: {
990
+ prompt: {
991
+ type: 'string',
992
+ required: true,
993
+ description: 'What the music should sound like: genre, mood, tempo, instruments ("driving synthwave, 120 bpm").',
994
+ },
995
+ duration: {
996
+ type: 'string',
997
+ description: `Track length in seconds, ${MUSIC_MIN_SECONDS}-${MUSIC_MAX_SECONDS} (default 30). Billed per second.`,
998
+ },
999
+ instrumental: {
1000
+ type: 'boolean',
1001
+ description: 'No vocals.',
1002
+ },
1003
+ loop: {
1004
+ type: 'boolean',
1005
+ description: 'Mark the asset as looping (the default for music). Pass --no-loop for a one-shot track.',
1006
+ },
1007
+ 'asset-id': {
1008
+ type: 'string',
1009
+ description: 'Pre-minted asset_… id to store the track under, so code already referencing it resolves.',
1010
+ },
1011
+ out: {
1012
+ type: 'string',
1013
+ description: 'Also save the MP3 to this path — for a trailer, or to listen before wiring it up.',
1014
+ },
1015
+ world: {
1016
+ type: 'boolean',
1017
+ default: true,
1018
+ description: 'Add the track to world.json assets (the default). Pass --no-world with --out for a file only.',
1019
+ },
1020
+ 'original-prompt': ORIGINAL_PROMPT_FLAG,
1021
+ json: JSON_FLAG,
1022
+ },
1023
+ async run({ args }) {
1024
+ const body = buildMusicBody({
1025
+ prompt: args.prompt,
1026
+ duration: args.duration,
1027
+ instrumental: args.instrumental === true ? true : undefined,
1028
+ loop: args.loop,
1029
+ assetId: args['asset-id'],
1030
+ });
1031
+ await runMusicGeneration({
1032
+ body: withParent(body),
1033
+ ...(args.out !== undefined ? { out: args.out } : {}),
1034
+ world: args.world !== false,
1035
+ json: args.json === true,
1036
+ });
1037
+ },
1038
+ });
897
1039
  const imageCommand = defineCommand({
898
1040
  meta: { name: 'image', description: 'Generate an image asset and add it to world.json assets.' },
899
1041
  args: {
@@ -1304,6 +1446,7 @@ export const generateCommand = defineCommand({
1304
1446
  background: backgroundCommand,
1305
1447
  'block-type': blockTypeCommand,
1306
1448
  sound: soundCommand,
1449
+ music: musicCommand,
1307
1450
  image: imageCommand,
1308
1451
  character: characterCommand,
1309
1452
  animation: animationCommand,