@bitmagic/cli 0.1.14 → 0.1.16

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 (48) hide show
  1. package/README.md +37 -11
  2. package/dist/cli.d.ts +56 -1
  3. package/dist/cli.js +3 -1
  4. package/dist/cli.js.map +1 -1
  5. package/dist/commands/check.d.ts +6 -1
  6. package/dist/commands/check.js +14 -2
  7. package/dist/commands/check.js.map +1 -1
  8. package/dist/commands/cover.d.ts +100 -0
  9. package/dist/commands/cover.js +321 -0
  10. package/dist/commands/cover.js.map +1 -0
  11. package/dist/commands/forge.d.ts +4 -0
  12. package/dist/commands/forge.js +24 -9
  13. package/dist/commands/forge.js.map +1 -1
  14. package/dist/commands/generate.d.ts +13 -3
  15. package/dist/commands/generate.js +54 -15
  16. package/dist/commands/generate.js.map +1 -1
  17. package/dist/commands/init.d.ts +8 -0
  18. package/dist/commands/init.js +44 -14
  19. package/dist/commands/init.js.map +1 -1
  20. package/dist/commands/login.d.ts +4 -0
  21. package/dist/commands/login.js +15 -6
  22. package/dist/commands/login.js.map +1 -1
  23. package/dist/commands/logout.d.ts +4 -0
  24. package/dist/commands/logout.js +8 -1
  25. package/dist/commands/logout.js.map +1 -1
  26. package/dist/commands/publish.d.ts +23 -0
  27. package/dist/commands/publish.js +72 -23
  28. package/dist/commands/publish.js.map +1 -1
  29. package/dist/commands/upgrade.d.ts +7 -1
  30. package/dist/commands/upgrade.js +30 -14
  31. package/dist/commands/upgrade.js.map +1 -1
  32. package/dist/commands/verify.js +2 -3
  33. package/dist/commands/verify.js.map +1 -1
  34. package/dist/commands/whoami.d.ts +4 -0
  35. package/dist/commands/whoami.js +9 -2
  36. package/dist/commands/whoami.js.map +1 -1
  37. package/dist/publish/fingerprint.js +13 -5
  38. package/dist/publish/fingerprint.js.map +1 -1
  39. package/dist/render/inline-image.d.ts +45 -0
  40. package/dist/render/inline-image.js +70 -0
  41. package/dist/render/inline-image.js.map +1 -0
  42. package/dist/scaffold/project-files.d.ts +15 -0
  43. package/dist/scaffold/project-files.js +80 -6
  44. package/dist/scaffold/project-files.js.map +1 -1
  45. package/dist/scaffold/project.d.ts +2 -0
  46. package/dist/scaffold/project.js +5 -2
  47. package/dist/scaffold/project.js.map +1 -1
  48. package/package.json +2 -2
package/README.md CHANGED
@@ -18,6 +18,7 @@ bitmagic --version
18
18
  bitmagic login # device-code auth in your browser
19
19
  bitmagic init my-game # scaffold a new project into ./my-game
20
20
  cd my-game
21
+ bitmagic cover # generate cover art from GAME-DESIGN.md
21
22
  bitmagic check # typecheck against the vendored engine
22
23
  bitmagic dev # build, then serve with live rebuilds
23
24
  bitmagic verify # boot the game in a real browser and report what broke
@@ -31,7 +32,7 @@ bitmagic publish # verify-gate, build, and ship — private by defa
31
32
  | `bitmagic login [--env <env>]` | Device-code auth against Auth0; stores credentials per environment. |
32
33
  | `bitmagic logout [--env <env>]` | Remove stored credentials for an environment. |
33
34
  | `bitmagic whoami [--env <env>]` | Show the identity the CLI is authenticated as. |
34
- | `bitmagic init [dir] [--template <id>] [--name <name>] [--env <env>] [--force]` | Scaffold a new project: mints a game, downloads the vendored engine, writes `AGENTS.md` and templates. |
35
+ | `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. `--idea` seeds the design doc's pitch. |
35
36
  | `bitmagic check` | Typecheck (`tsc --noEmit`) against the vendored engine. Fast; does not prove the game runs. |
36
37
  | `bitmagic dev [--port <port>]` | Build, then serve with `tsc --watch` + `vite`, default port 3010. |
37
38
  | `bitmagic verify [--timeout <ms>]` | Build, boot the game in a headless browser, click 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. `--timeout` is settle time in ms measured after gameplay starts, so the screenshot captures gameplay. Writes the artifacts the publish gate reads (see below). |
@@ -39,6 +40,7 @@ bitmagic publish # verify-gate, build, and ship — private by defa
39
40
  | `bitmagic publish [--visibility public\|private] [--name <name>] [--description <desc>] [--force]` | Verify-gate, build if needed, and upload straight to GCS. **Private unless `--visibility public` is passed.** |
40
41
  | `bitmagic upgrade [--engine <version>] [--force]` | Refresh vendored platform files to the currently published engine. Refuses a dirty git tree unless `--force`. |
41
42
  | `bitmagic generate <skybox\|sound\|image\|character\|animation> ...` | Generate one asset directly into `src/work/world.json`. Costs sparks. |
43
+ | `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. |
42
44
  | `bitmagic forge --prompt "..." [--city\|--dungeon\|--platformer\|--freeform] [--name <name>] [--resume <jobId>]` | Design and bake a whole playable level into `world.json`. Slow and expensive; supports `--resume`. |
43
45
 
44
46
  Every command exits non-zero on failure with a single-line message (no stack trace) and, where a
@@ -56,16 +58,35 @@ my-game/
56
58
  src/work/ # your game — Game.ts, game.json, world.json
57
59
  engine/ # vendored engine, read-only, replaced wholesale by `bitmagic upgrade`
58
60
  AGENTS.md # guidance for the agent editing this project
61
+ GAME-DESIGN.md # what the game is — yours to write; bitmagic cover reads it
59
62
  .bitmagic/
63
+ cover.webp # bitmagic cover's artwork — the publish thumbnail when present
64
+ cover.json # its URL and the design hash it was generated from
60
65
  build/
61
- index.html # bitmagic build's output bundle
62
- manifest.json # engineVersion, fingerprint, bytes, sha256, builtAt
66
+ index.html # bitmagic build's output bundle
67
+ manifest.json # engineVersion, fingerprint, bytes, sha256, builtAt
63
68
  verify/
64
- result.json # bitmagic verify's verdict — ok, failures, warnings, fingerprint, at
65
- screenshot.png # becomes the publish thumbnail
66
- console.log # captured browser console output
69
+ result.json # bitmagic verify's verdict — ok, failures, warnings, fingerprint, at
70
+ screenshot.png # the publish thumbnail when there is no cover art
71
+ console.log # captured browser console output
67
72
  ```
68
73
 
74
+ ## Cover art
75
+
76
+ `bitmagic cover` generates the game's cover from `GAME-DESIGN.md` — the same artwork the web
77
+ Creator's Planning Mode produces, from the same style direction. It sets `hud.startScreen.imageUrl`
78
+ so the image appears in the game itself, saves `.bitmagic/cover.webp`, and hands that to
79
+ `bitmagic publish` as the portal thumbnail.
80
+
81
+ Run it **early** — right after the design doc says what the game is, before implementing it. The
82
+ first build takes a while, and the cover is what there is to look at meanwhile. In iTerm2, WezTerm
83
+ and Konsole it is drawn straight into the terminal; everywhere else the path and URL are printed
84
+ and `.bitmagic/cover.webp` is there to open (`BITMAGIC_NO_INLINE_IMAGE=1` turns the drawing off).
85
+
86
+ Re-running on an unchanged design generates nothing and costs nothing — it reports the existing
87
+ cover. Edit the design and run again, or pass `--force`, to replace it. Because it writes
88
+ `world.json`, it invalidates a passing verify: run it before `bitmagic verify`, not after.
89
+
69
90
  ## Publishing
70
91
 
71
92
  `bitmagic publish` is two gated steps in one command:
@@ -76,7 +97,8 @@ my-game/
76
97
  record stale immediately, while an unmodified project stays fresh no matter how much time has
77
98
  passed. There is no way to check freshness except running `bitmagic verify` again.
78
99
  `.git/`, `node_modules/`, `dist/`, `.bitmagic/` and `.vite-cache/` are excluded, so committing
79
- between `bitmagic verify` and `bitmagic publish` does **not** invalidate the verify.
100
+ between `bitmagic verify` and `bitmagic publish` does **not** invalidate the verify. Neither
101
+ does editing `GAME-DESIGN.md`, which no build step reads.
80
102
  2. **The build.** If the project has changed since the last `.bitmagic/build/manifest.json`,
81
103
  publish rebuilds automatically; a prior manual `bitmagic build` is never required, only useful
82
104
  if you want to inspect `.bitmagic/build/index.html` before it ships.
@@ -89,9 +111,9 @@ service, so a previously-public game re-published bare is gone from bitmagic.ai
89
111
  publicly again.
90
112
 
91
113
  `--force` overrides a **stale or failed** verify verdict. It does **not** override a missing
92
- verify record — publish's thumbnail comes from the verify screenshot, so `bitmagic verify` must
93
- have produced at least one `.bitmagic/verify/screenshot.png`, ever, before `--force` has anything
94
- to work with.
114
+ verify record — a project with no cover art has only the verify screenshot to publish a thumbnail
115
+ from, so `bitmagic verify` must have produced at least one `.bitmagic/verify/screenshot.png`, ever,
116
+ before `--force` has anything to work with.
95
117
 
96
118
  `--name` and `--description` apply to that one publish call only. They are never written back to
97
119
  `src/work/game.json`, so pass them again on every future `bitmagic publish` if you want them to
@@ -134,7 +156,7 @@ dependencies too.
134
156
 
135
157
  ## Machine-readable output
136
158
 
137
- `build`, `verify` and `publish` accept `--json`:
159
+ Every command accepts `--json` except `dev`, which starts a server and never terminates with a result to report:
138
160
 
139
161
  - **stdout** carries exactly one JSON document — the result, or on failure
140
162
  `{ "ok": false, "exitCode": N, "error": "..." }`
@@ -145,6 +167,10 @@ parses one stream whether the command succeeded or not. The exit code remains au
145
167
 
146
168
  Without `--json` nothing changes: prose goes to stdout as before and no JSON is emitted.
147
169
 
170
+ The result shape is per-command — `publish` reports `url`/`visibility`/`publishVersion`, `init`
171
+ reports `gameId`/`root`/`dependenciesInstalled`, `upgrade` reports `replaced` and any
172
+ `missingDependencies` as structured entries rather than only as a printed install command.
173
+
148
174
  ## Staying current
149
175
 
150
176
  Two nudges, both advisory — nothing is ever blocked because something is out of date.
package/dist/cli.d.ts CHANGED
@@ -13,18 +13,30 @@ declare const rawCommands: {
13
13
  readonly type: "string";
14
14
  readonly description: "Environment to log in to (dev, prod, local).";
15
15
  };
16
+ readonly json: {
17
+ readonly type: "boolean";
18
+ readonly description: "Print the result as JSON on stdout; all progress goes to stderr.";
19
+ };
16
20
  }>;
17
21
  logout: CommandDef<{
18
22
  readonly env: {
19
23
  readonly type: "string";
20
24
  readonly description: "Environment to log out of (dev, prod, local).";
21
25
  };
26
+ readonly json: {
27
+ readonly type: "boolean";
28
+ readonly description: "Print the result as JSON on stdout; all progress goes to stderr.";
29
+ };
22
30
  }>;
23
31
  whoami: CommandDef<{
24
32
  readonly env: {
25
33
  readonly type: "string";
26
34
  readonly description: "Environment to query (dev, prod, local).";
27
35
  };
36
+ readonly json: {
37
+ readonly type: "boolean";
38
+ readonly description: "Print the result as JSON on stdout; all progress goes to stderr.";
39
+ };
28
40
  }>;
29
41
  init: CommandDef<{
30
42
  readonly dir: {
@@ -40,6 +52,10 @@ declare const rawCommands: {
40
52
  readonly type: "string";
41
53
  readonly description: "Game name.";
42
54
  };
55
+ readonly idea: {
56
+ readonly type: "string";
57
+ readonly description: "One-line pitch, seeded into GAME-DESIGN.md. Optional — you can write it yourself.";
58
+ };
43
59
  readonly env: {
44
60
  readonly type: "string";
45
61
  readonly description: "Environment (dev, prod, local).";
@@ -48,6 +64,10 @@ declare const rawCommands: {
48
64
  readonly type: "boolean";
49
65
  readonly description: "Scaffold into a non-empty directory.";
50
66
  };
67
+ readonly json: {
68
+ readonly type: "boolean";
69
+ readonly description: "Print the result as JSON on stdout; all progress goes to stderr.";
70
+ };
51
71
  }>;
52
72
  upgrade: CommandDef<{
53
73
  readonly engine: {
@@ -58,8 +78,17 @@ declare const rawCommands: {
58
78
  readonly type: "boolean";
59
79
  readonly description: "Upgrade even with uncommitted changes in the working tree.";
60
80
  };
81
+ readonly json: {
82
+ readonly type: "boolean";
83
+ readonly description: "Print the result as JSON on stdout; all progress goes to stderr.";
84
+ };
85
+ }>;
86
+ check: CommandDef<{
87
+ readonly json: {
88
+ readonly type: "boolean";
89
+ readonly description: "Print the result as JSON on stdout; all progress goes to stderr.";
90
+ };
61
91
  }>;
62
- check: CommandDef<ArgsDef>;
63
92
  dev: CommandDef<{
64
93
  readonly port: {
65
94
  readonly type: "string";
@@ -83,6 +112,28 @@ declare const rawCommands: {
83
112
  };
84
113
  }>;
85
114
  generate: CommandDef<ArgsDef>;
115
+ cover: CommandDef<{
116
+ readonly prompt: {
117
+ readonly type: "string";
118
+ readonly description: "Describe the game for this call only, instead of reading GAME-DESIGN.md. Never written to the file.";
119
+ };
120
+ readonly force: {
121
+ readonly type: "boolean";
122
+ readonly description: "Generate a new cover even when the design has not changed since the last one.";
123
+ };
124
+ readonly 'start-screen': {
125
+ readonly type: "boolean";
126
+ readonly negativeDescription: "Leave hud.startScreen.imageUrl alone — still saves the cover and uses it as the publish thumbnail.";
127
+ };
128
+ readonly 'reference-image-url': {
129
+ readonly type: "string";
130
+ readonly description: "Style/composition reference image URL forwarded to the image model.";
131
+ };
132
+ readonly json: {
133
+ readonly type: "boolean";
134
+ readonly description: "Print the result as JSON on stdout; all progress goes to stderr.";
135
+ };
136
+ }>;
86
137
  forge: CommandDef<{
87
138
  readonly prompt: {
88
139
  readonly type: "string";
@@ -112,6 +163,10 @@ declare const rawCommands: {
112
163
  readonly type: "boolean";
113
164
  readonly description: "Build a custom place (arena, fortress, camp).";
114
165
  };
166
+ readonly json: {
167
+ readonly type: "boolean";
168
+ readonly description: "Print the result as JSON on stdout; all progress goes to stderr.";
169
+ };
115
170
  }>;
116
171
  publish: CommandDef<{
117
172
  readonly visibility: {
package/dist/cli.js CHANGED
@@ -11,6 +11,7 @@ import { devCommand } from './commands/dev.js';
11
11
  import { verifyCommand } from './commands/verify.js';
12
12
  import { buildCommand } from './commands/build.js';
13
13
  import { generateCommand } from './commands/generate.js';
14
+ import { coverCommand } from './commands/cover.js';
14
15
  import { forgeCommand } from './commands/forge.js';
15
16
  import { publishCommand } from './commands/publish.js';
16
17
  // citty's runMain() catches every error thrown from a command's `run()` internally and calls
@@ -88,7 +89,7 @@ export function isWrappedWithCleanErrors(command) {
88
89
  if (!subs)
89
90
  return false;
90
91
  const entries = Object.values(subs);
91
- return entries.length > 0 && entries.every((sub) => isWrappedWithCleanErrors(sub));
92
+ return entries.length > 0 && entries.every(isWrappedWithCleanErrors);
92
93
  }
93
94
  // Wrapping happens once here, over the whole map, rather than per-entry at each call site —
94
95
  // a future command added to `rawCommands` is wrapped automatically, so there is no per-command
@@ -104,6 +105,7 @@ const rawCommands = {
104
105
  verify: verifyCommand,
105
106
  build: buildCommand,
106
107
  generate: generateCommand,
108
+ cover: coverCommand,
107
109
  forge: forgeCommand,
108
110
  publish: publishCommand,
109
111
  };
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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"}
@@ -1 +1,6 @@
1
- export declare const checkCommand: import("citty").CommandDef<import("citty").ArgsDef>;
1
+ export declare const checkCommand: import("citty").CommandDef<{
2
+ readonly json: {
3
+ readonly type: "boolean";
4
+ readonly description: "Print the result as JSON on stdout; all progress goes to stderr.";
5
+ };
6
+ }>;
@@ -2,9 +2,17 @@ import { defineCommand } from 'citty';
2
2
  import { spawnSync } from 'child_process';
3
3
  import { CliError } from '../errors.js';
4
4
  import { loadProjectContext, projectBin } from '../project/context.js';
5
+ import { createOutput } from '../output.js';
5
6
  export const checkCommand = defineCommand({
6
7
  meta: { name: 'check', description: 'Type-check the game against the vendored engine.' },
7
- run() {
8
+ args: {
9
+ json: {
10
+ type: 'boolean',
11
+ description: 'Print the result as JSON on stdout; all progress goes to stderr.',
12
+ },
13
+ },
14
+ run({ args }) {
15
+ const output = createOutput(args.json === true);
8
16
  const context = loadProjectContext();
9
17
  const tsc = projectBin(context.root, 'tsc');
10
18
  // stdio inherit: tsc's own diagnostics are what the creator (or their agent) needs to read.
@@ -16,7 +24,11 @@ export const checkCommand = defineCommand({
16
24
  // tsc already printed the diagnostics; add nothing but the exit code.
17
25
  throw new CliError('Type check failed.', result.status ?? 1);
18
26
  }
19
- console.log('Type check passed.');
27
+ output.info('Type check passed.');
28
+ // tsc's own diagnostics went straight to the inherited stdio, so a --json run's stdout is
29
+ // clean only on SUCCESS. A failure throws above and the wrapper emits the error document —
30
+ // interleaved with whatever tsc printed, which is documented rather than pretended away.
31
+ output.result({ ok: true, root: context.root });
20
32
  },
21
33
  });
22
34
  //# sourceMappingURL=check.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"check.js","sourceRoot":"","sources":["../../src/commands/check.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAEvE,MAAM,CAAC,MAAM,YAAY,GAAG,aAAa,CAAC;IACxC,IAAI,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,kDAAkD,EAAE;IACxF,GAAG;QACD,MAAM,OAAO,GAAG,kBAAkB,EAAE,CAAC;QACrC,MAAM,GAAG,GAAG,UAAU,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAC5C,4FAA4F;QAC5F,MAAM,MAAM,GAAG,SAAS,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,EAAE,EAAE,GAAG,EAAE,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;QACrF,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;YACjB,MAAM,IAAI,QAAQ,CAAC,0CAA0C,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QACvF,CAAC;QACD,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxB,sEAAsE;YACtE,MAAM,IAAI,QAAQ,CAAC,oBAAoB,EAAE,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC;QAC/D,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;IACpC,CAAC;CACF,CAAC,CAAC"}
1
+ {"version":3,"file":"check.js","sourceRoot":"","sources":["../../src/commands/check.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACvE,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,MAAM,CAAC,MAAM,YAAY,GAAG,aAAa,CAAC;IACxC,IAAI,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,kDAAkD,EAAE;IACxF,IAAI,EAAE;QACJ,IAAI,EAAE;YACJ,IAAI,EAAE,SAAS;YACf,WAAW,EAAE,kEAAkE;SAChF;KACF;IACD,GAAG,CAAC,EAAE,IAAI,EAAE;QACV,MAAM,MAAM,GAAG,YAAY,CAAC,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;QAChD,MAAM,OAAO,GAAG,kBAAkB,EAAE,CAAC;QACrC,MAAM,GAAG,GAAG,UAAU,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAC5C,4FAA4F;QAC5F,MAAM,MAAM,GAAG,SAAS,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,EAAE,EAAE,GAAG,EAAE,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;QACrF,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;YACjB,MAAM,IAAI,QAAQ,CAAC,0CAA0C,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QACvF,CAAC;QACD,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxB,sEAAsE;YACtE,MAAM,IAAI,QAAQ,CAAC,oBAAoB,EAAE,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC;QAC/D,CAAC;QACD,MAAM,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;QAClC,0FAA0F;QAC1F,2FAA2F;QAC3F,yFAAyF;QACzF,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IAClD,CAAC;CACF,CAAC,CAAC"}
@@ -0,0 +1,100 @@
1
+ import { Buffer } from 'buffer';
2
+ import { type WorldPatch } from '@bitmagic/asset-core';
3
+ import type { GenerationOutcome } from '../generate/stream.js';
4
+ import { type GenerateRunDeps } from './generate.js';
5
+ /** The design document `bitmagic init` scaffolds and the coding agent maintains. */
6
+ export declare const GAME_DESIGN_FILE = "GAME-DESIGN.md";
7
+ export declare function coverImagePath(root: string): string;
8
+ export interface CoverRecord {
9
+ /** The public image URL, as written into world.json. */
10
+ url: string;
11
+ /** Hash of the design text this cover was drawn from — see `readCoverRecord`. */
12
+ designHash: string;
13
+ generatedAt: string;
14
+ }
15
+ /**
16
+ * Identifies the design text a cover was generated from, so a repeat `bitmagic cover` on an
17
+ * unchanged design can decline to spend sparks on the same picture twice. This is the local
18
+ * equivalent of `PLAN_COVER_CACHE` in game-play-agent's PromptToGameController, which does the
19
+ * same for Planning Mode, keyed the same way — on the design text rather than the game.
20
+ */
21
+ export declare function hashDesign(designText: string): string;
22
+ export declare function readCoverRecord(root: string): CoverRecord | null;
23
+ /**
24
+ * The prose the cover is drawn from: `--prompt` when given, otherwise GAME-DESIGN.md.
25
+ *
26
+ * `--prompt` is a one-call override and is never written to the file — the design document belongs
27
+ * to the creator, and a flag silently rewriting it would be a surprise the next `bitmagic cover`
28
+ * inherits.
29
+ *
30
+ * The error path matters as much as the happy one: projects scaffolded before GAME-DESIGN.md
31
+ * existed have no such file, and an agent that only sees "not found" cannot tell whether it should
32
+ * create one or has run the command in the wrong place. So the message says both what to write and
33
+ * what to run instead.
34
+ */
35
+ export declare function resolveDesignText(options: {
36
+ promptFlag?: string | undefined;
37
+ root: string;
38
+ readFile?: (file: string) => string;
39
+ }): string;
40
+ /**
41
+ * The generated image's URL, read back out of the patch the image generator returned.
42
+ *
43
+ * The generator's terminal frame carries only `{ success, message, patches }` — the URL is not a
44
+ * separate field on the wire — so the patch it upserts into `assets[]` is where it lives. Matched
45
+ * on the patch's own shape rather than on the message text, which is prose and not a contract.
46
+ */
47
+ export declare function coverUrlFromPatches(patches: WorldPatch[]): string | null;
48
+ /**
49
+ * The patch that puts the cover behind the game's start screen.
50
+ *
51
+ * `set`, NOT `setRoot`: `set` addresses a path inside `worldProfileData`, which is where the
52
+ * engine's GameRuntimeController reads `hud.startScreen.imageUrl` from. A root-level write would
53
+ * land somewhere nothing ever looks and report success — the exact trap apply-patches.ts documents.
54
+ */
55
+ export declare function startScreenPatch(url: string): WorldPatch;
56
+ export interface CoverArgs {
57
+ prompt?: string;
58
+ force?: boolean;
59
+ 'reference-image-url'?: string;
60
+ /** citty's negative form of the boolean flag: `--no-start-screen` arrives here as `false`. */
61
+ 'start-screen'?: boolean;
62
+ json?: boolean;
63
+ }
64
+ export interface CoverRunDeps extends GenerateRunDeps {
65
+ /**
66
+ * Seam over `runAssetGeneration`, so a test can drive this without a network or a token.
67
+ *
68
+ * Deliberately narrower than `runAssetGeneration`'s own signature: it omits that function's
69
+ * `json` parameter, because this command always passes `false` there. Under `--json` stdout must
70
+ * carry exactly one document, and this command emits its own.
71
+ */
72
+ generate: (type: string, label: string, body: Record<string, unknown>, json: boolean, deps: GenerateRunDeps) => Promise<GenerationOutcome>;
73
+ /** Returns whether the terminal actually drew the image. */
74
+ renderImage: (bytes: Buffer) => boolean;
75
+ /** The machine-readable result, emitted only under `--json`. */
76
+ result: (value: unknown) => void;
77
+ }
78
+ export declare function runCover(args: CoverArgs, deps?: CoverRunDeps): Promise<void>;
79
+ export declare const coverCommand: import("citty").CommandDef<{
80
+ readonly prompt: {
81
+ readonly type: "string";
82
+ readonly description: "Describe the game for this call only, instead of reading GAME-DESIGN.md. Never written to the file.";
83
+ };
84
+ readonly force: {
85
+ readonly type: "boolean";
86
+ readonly description: "Generate a new cover even when the design has not changed since the last one.";
87
+ };
88
+ readonly 'start-screen': {
89
+ readonly type: "boolean";
90
+ readonly negativeDescription: "Leave hud.startScreen.imageUrl alone — still saves the cover and uses it as the publish thumbnail.";
91
+ };
92
+ readonly 'reference-image-url': {
93
+ readonly type: "string";
94
+ readonly description: "Style/composition reference image URL forwarded to the image model.";
95
+ };
96
+ readonly json: {
97
+ readonly type: "boolean";
98
+ readonly description: "Print the result as JSON on stdout; all progress goes to stderr.";
99
+ };
100
+ }>;