@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.
- package/README.md +37 -11
- package/dist/cli.d.ts +56 -1
- package/dist/cli.js +3 -1
- package/dist/cli.js.map +1 -1
- package/dist/commands/check.d.ts +6 -1
- package/dist/commands/check.js +14 -2
- package/dist/commands/check.js.map +1 -1
- package/dist/commands/cover.d.ts +100 -0
- package/dist/commands/cover.js +321 -0
- package/dist/commands/cover.js.map +1 -0
- package/dist/commands/forge.d.ts +4 -0
- package/dist/commands/forge.js +24 -9
- package/dist/commands/forge.js.map +1 -1
- package/dist/commands/generate.d.ts +13 -3
- package/dist/commands/generate.js +54 -15
- package/dist/commands/generate.js.map +1 -1
- package/dist/commands/init.d.ts +8 -0
- package/dist/commands/init.js +44 -14
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/login.d.ts +4 -0
- package/dist/commands/login.js +15 -6
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/logout.d.ts +4 -0
- package/dist/commands/logout.js +8 -1
- package/dist/commands/logout.js.map +1 -1
- package/dist/commands/publish.d.ts +23 -0
- package/dist/commands/publish.js +72 -23
- package/dist/commands/publish.js.map +1 -1
- package/dist/commands/upgrade.d.ts +7 -1
- package/dist/commands/upgrade.js +30 -14
- package/dist/commands/upgrade.js.map +1 -1
- package/dist/commands/verify.js +2 -3
- package/dist/commands/verify.js.map +1 -1
- package/dist/commands/whoami.d.ts +4 -0
- package/dist/commands/whoami.js +9 -2
- package/dist/commands/whoami.js.map +1 -1
- package/dist/publish/fingerprint.js +13 -5
- package/dist/publish/fingerprint.js.map +1 -1
- package/dist/render/inline-image.d.ts +45 -0
- package/dist/render/inline-image.js +70 -0
- package/dist/render/inline-image.js.map +1 -0
- package/dist/scaffold/project-files.d.ts +15 -0
- package/dist/scaffold/project-files.js +80 -6
- package/dist/scaffold/project-files.js.map +1 -1
- package/dist/scaffold/project.d.ts +2 -0
- package/dist/scaffold/project.js +5 -2
- package/dist/scaffold/project.js.map +1 -1
- 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
|
|
62
|
-
manifest.json
|
|
66
|
+
index.html # bitmagic build's output bundle
|
|
67
|
+
manifest.json # engineVersion, fingerprint, bytes, sha256, builtAt
|
|
63
68
|
verify/
|
|
64
|
-
result.json
|
|
65
|
-
screenshot.png
|
|
66
|
-
console.log
|
|
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 —
|
|
93
|
-
have produced at least one `.bitmagic/verify/screenshot.png`, ever,
|
|
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
|
-
`
|
|
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(
|
|
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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"}
|
package/dist/commands/check.d.ts
CHANGED
|
@@ -1 +1,6 @@
|
|
|
1
|
-
export declare const checkCommand: import("citty").CommandDef<
|
|
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
|
+
}>;
|
package/dist/commands/check.js
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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;
|
|
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
|
+
}>;
|