@thijshakkenberg/valkyrie-mom-mcp 2.1.0 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/README.md +47 -7
  3. package/agents/scenario-designer.md +9 -3
  4. package/dist/artwork/comfyui.d.ts +146 -0
  5. package/dist/artwork/comfyui.d.ts.map +1 -0
  6. package/dist/artwork/comfyui.js +214 -0
  7. package/dist/artwork/comfyui.js.map +1 -0
  8. package/dist/catalogs/extract-catalogs.js +4 -1
  9. package/dist/catalogs/extract-catalogs.js.map +1 -1
  10. package/dist/io/package-manifest.d.ts +18 -0
  11. package/dist/io/package-manifest.d.ts.map +1 -0
  12. package/dist/io/package-manifest.js +57 -0
  13. package/dist/io/package-manifest.js.map +1 -0
  14. package/dist/resources/format-docs.d.ts +1 -1
  15. package/dist/resources/format-docs.d.ts.map +1 -1
  16. package/dist/resources/format-docs.js +17 -9
  17. package/dist/resources/format-docs.js.map +1 -1
  18. package/dist/server.d.ts.map +1 -1
  19. package/dist/server.js +96 -7
  20. package/dist/server.js.map +1 -1
  21. package/dist/story/story-graph.d.ts +55 -0
  22. package/dist/story/story-graph.d.ts.map +1 -0
  23. package/dist/story/story-graph.js +391 -0
  24. package/dist/story/story-graph.js.map +1 -0
  25. package/dist/validation/rules/custom-images.d.ts.map +1 -1
  26. package/dist/validation/rules/custom-images.js +24 -2
  27. package/dist/validation/rules/custom-images.js.map +1 -1
  28. package/dist/validation/rules/package-name.d.ts +9 -0
  29. package/dist/validation/rules/package-name.d.ts.map +1 -0
  30. package/dist/validation/rules/package-name.js +32 -0
  31. package/dist/validation/rules/package-name.js.map +1 -0
  32. package/dist/validation/rules/puzzles.d.ts +15 -0
  33. package/dist/validation/rules/puzzles.d.ts.map +1 -0
  34. package/dist/validation/rules/puzzles.js +76 -0
  35. package/dist/validation/rules/puzzles.js.map +1 -0
  36. package/dist/validation/validator.d.ts.map +1 -1
  37. package/dist/validation/validator.js +4 -0
  38. package/dist/validation/validator.js.map +1 -1
  39. package/package.json +3 -2
  40. package/skills/artwork/SKILL.md +120 -0
  41. package/skills/scenario/SKILL.md +5 -1
  42. package/skills/ui-and-puzzles/SKILL.md +50 -133
  43. package/src/artwork/comfyui.ts +289 -0
  44. package/src/catalogs/extract-catalogs.ts +4 -4
  45. package/src/io/package-manifest.ts +59 -0
  46. package/src/resources/format-docs.ts +17 -9
  47. package/src/server.ts +115 -7
  48. package/src/story/story-graph.ts +392 -0
  49. package/src/validation/rules/custom-images.ts +23 -2
  50. package/src/validation/rules/package-name.ts +33 -0
  51. package/src/validation/rules/puzzles.ts +79 -0
  52. package/src/validation/validator.ts +4 -0
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "valkyrie-mom",
3
- "version": "2.1.0",
3
+ "version": "2.3.0",
4
4
  "description": "AI-assisted Mansions of Madness scenario editor for Valkyrie",
5
5
  "author": {
6
6
  "name": "Thijs Hakkenberg"
package/README.md CHANGED
@@ -8,7 +8,7 @@ MCP (Model Context Protocol) server and Claude Code plugin for AI-assisted Mansi
8
8
 
9
9
  This server exposes Valkyrie scenario editing as MCP tools, enabling AI assistants (Claude, etc.) to create, modify, validate, and build complete MoM scenarios. It auto-detects the Valkyrie editor directory so scenarios appear directly in the app.
10
10
 
11
- The plugin bundles 7 skills covering advanced patterns (event loops, mythos scaling, tile placement chains, custom puzzles, etc.) and an autonomous scenario designer agent.
11
+ The plugin bundles 8 skills covering advanced patterns (event loops, mythos scaling, tile placement chains, custom puzzles, generated artwork, etc.) and an autonomous scenario designer agent.
12
12
 
13
13
  ## Install
14
14
 
@@ -21,7 +21,7 @@ claude plugin install valkyrie-mom
21
21
 
22
22
  This gives you:
23
23
  - **MCP server** with 25 tools for scenario editing (auto-started)
24
- - **7 skills**: `/scenario`, `/event-patterns`, `/tile-placement`, `/variables-and-mythos`, `/custom-monsters`, `/ui-and-puzzles`, `/items-and-distribution`
24
+ - **8 skills**: `/scenario`, `/event-patterns`, `/tile-placement`, `/variables-and-mythos`, `/custom-monsters`, `/ui-and-puzzles`, `/items-and-distribution`, `/artwork`
25
25
  - **Scenario designer agent** for autonomous scenario creation
26
26
  - **5 MCP resources** for format documentation
27
27
 
@@ -53,6 +53,16 @@ Add to your MCP client config (e.g., `~/.claude/mcp.json` or Claude Desktop sett
53
53
 
54
54
  This gives you the MCP tools and resources, but not the skills or agent (those require Claude Code).
55
55
 
56
+ ### As a Hermes Agent plugin
57
+
58
+ [Hermes Agent](https://hermes-agent.nousresearch.com/docs/user-guide/features/plugins) installs the repository as a plugin with every tool and all skills:
59
+
60
+ ```bash
61
+ hermes plugins install thijs-hakkenberg/ValkyrieMCP --enable
62
+ ```
63
+
64
+ The plugin registers the MCP tools as native Hermes tools (toolset `valkyrie-mom`) and the skills as `valkyrie-mom:<skill>` (e.g. `skill_view("valkyrie-mom:artwork")`). On the first tool call it starts the matching `@thijshakkenberg/valkyrie-mom-mcp` version with `npx` (Node.js 20+ required) and keeps it running for the session, since the scenario being edited lives there. Pictures that tools return, such as `render_map`, are saved under `~/.hermes/cache/valkyrie-mom/` and their paths are given in the result. For a local checkout, set `VALKYRIE_MCP_COMMAND="npx tsx /path/to/ValkyrieMCP/src/index.ts"`.
65
+
56
66
  ### From source
57
67
 
58
68
  ```bash
@@ -73,6 +83,7 @@ npx tsx src/index.ts # Run MCP server via stdio
73
83
  | `/custom-monsters` | Custom activations, evade/horror events, round-based spawn triggering |
74
84
  | `/ui-and-puzzles` | Prologues, interactive journals, combination locks, built-in puzzle types |
75
85
  | `/items-and-distribution` | Random items, unique items, starting items, inspection events |
86
+ | `/artwork` | Generate pictures with a local ComfyUI (FLUX.2 [klein] 4B) and show them: cover, intro cutscene, handouts, scenes, monsters, tokens, image puzzles |
76
87
 
77
88
  ## MCP Tools
78
89
 
@@ -84,7 +95,8 @@ npx tsx src/index.ts # Run MCP server via stdio
84
95
  | `load_scenario` | Load an existing scenario from a directory |
85
96
  | `get_scenario_state` | Get current scenario component/localization summary |
86
97
  | `validate_scenario` | Run all validation rules |
87
- | `build_scenario` | Save and build `.valkyrie` package |
98
+ | `save_scenario` | Write the scenario to its folder (edits stay in memory until saved or built) |
99
+ | `build_scenario` | Save and build the `.valkyrie` package with Valkyrie's manifest `.ini` and cover image (default: `Desktop/<Package>/`, like Valkyrie's Create Package) |
88
100
  | `set_quest_config` | Set difficulty, play time, investigator count, cover image |
89
101
 
90
102
  ### Components
@@ -111,6 +123,29 @@ npx tsx src/index.ts # Run MCP server via stdio
111
123
  | `suggest_tile_layout` | Suggest coordinates for large (7x7) tiles in linear, L-shape, or hub-spoke layouts |
112
124
  | `place_tile_relative` | Position and rotation for a new tile against an existing one, with a door lined up |
113
125
 
126
+ ### Story
127
+ | Tool | Description |
128
+ |------|-------------|
129
+ | `story_graph` | Project the storyline as a graph: a condensed text outline (buttons, conditions, effects, placed tokens, puzzles, monster events, endings, never-reached events), Mermaid, or an HTML page with the rendered flowchart |
130
+
131
+ ### Artwork
132
+ | Tool | Description |
133
+ |------|-------------|
134
+ | `artwork_status` | Check a local ComfyUI server and the FLUX.2 [klein] 4B model files; prints comfy-cli setup and download commands for anything missing |
135
+ | `generate_artwork` | Generate an image (4 steps, CFG 1, size presets per use) and save it into the scenario folder, with a preview |
136
+
137
+ Artwork is optional and runs entirely on your machine. Setup with [comfy-cli](https://github.com/Comfy-Org/comfy-cli):
138
+
139
+ ```bash
140
+ pip install comfy-cli && comfy install
141
+ comfy model download --url https://huggingface.co/Comfy-Org/flux2-klein-4B/resolve/main/split_files/diffusion_models/flux-2-klein-4b.safetensors --relative-path models/diffusion_models
142
+ comfy model download --url https://huggingface.co/Comfy-Org/flux2-klein-4B/resolve/main/split_files/text_encoders/qwen_3_4b.safetensors --relative-path models/text_encoders
143
+ comfy model download --url https://huggingface.co/Comfy-Org/flux2-dev/resolve/main/split_files/vae/flux2-vae.safetensors --relative-path models/vae
144
+ comfy launch --background
145
+ ```
146
+
147
+ On NVIDIA GPUs with less VRAM, the fp8 model (`black-forest-labs/FLUX.2-klein-4b-fp8`) is smaller. Set `VALKYRIE_COMFYUI_URL` if ComfyUI runs somewhere other than `http://127.0.0.1:8188`. The `/artwork` skill covers prompts and where Valkyrie shows images.
148
+
114
149
  ### Reference
115
150
  | Tool | Description |
116
151
  |------|-------------|
@@ -191,24 +226,29 @@ The server validates scenarios against 18 rule categories, checked against Valky
191
226
  ## Development
192
227
 
193
228
  ```bash
194
- npm test # Run all tests (1067 tests across 44 files)
229
+ npm test # Run all tests
195
230
  npm run test:watch # Watch mode
196
231
  npm run lint # Type check
197
232
  npm run build # Compile to dist/
233
+ npm run hermes:tools # Re-export the Hermes plugin tool list after changing tools or the version
198
234
  ```
199
235
 
200
236
  ## Project Structure
201
237
 
202
238
  ```
203
- .claude-plugin/ Plugin manifest
204
- skills/ 7 skill SKILL.md files
239
+ .claude-plugin/ Claude Code plugin manifest
240
+ plugin.yaml Hermes Agent plugin manifest (+ __init__.py entry point)
241
+ hermes_bridge/ Hermes plugin: MCP stdio client, tool registration, exported tools.json
242
+ skills/ 8 skill SKILL.md files (Claude Code and Hermes)
205
243
  agents/ Scenario designer agent
206
244
  src/
207
245
  io/ INI parser/writer, localization CSV, ZIP packager
208
246
  model/ ScenarioModel, LocalizationStore, component types
209
- validation/ 15 rules + orchestrator
247
+ validation/ Rules + orchestrator
210
248
  rules/ Individual validation rule implementations
211
249
  tools/ MCP tool implementations
250
+ story/ Storyline graph: outline, Mermaid, HTML
251
+ artwork/ ComfyUI (FLUX.2 [klein]) artwork generation
212
252
  resources/ Format documentation resources
213
253
  catalogs/ 846-entry game content catalog
214
254
  diagnostics/ Bug report builder, session trace, ring buffer
@@ -27,6 +27,7 @@ skills:
27
27
  - custom-monsters
28
28
  - ui-and-puzzles
29
29
  - items-and-distribution
30
+ - artwork
30
31
  ---
31
32
 
32
33
  # Scenario Designer Agent
@@ -40,9 +41,11 @@ You are an autonomous Mansions of Madness 2nd Edition scenario designer. You cre
40
41
  - Place tokens for exploration, searches, and encounters
41
42
  - Configure monster spawns with appropriate difficulty scaling
42
43
  - Build custom puzzles and UI overlays
44
+ - Generate scenario artwork (cover, intro, handouts) when a local ComfyUI is available (`artwork_status`)
43
45
  - Set up mythos scaling for tension progression
44
46
  - Write atmospheric narrative text in the Lovecraftian horror style
45
47
  - Validate scenarios for correctness and completeness
48
+ - Review the storyline as a condensed event tree (`story_graph`) and explain it to the user
46
49
 
47
50
  ## Available Skills
48
51
 
@@ -54,6 +57,7 @@ Use these skills for detailed pattern guidance:
54
57
  - `/custom-monsters` — Custom activations, evade/horror events, spawn triggering
55
58
  - `/ui-and-puzzles` — Prologues, interactive journals, combination locks, built-in puzzles
56
59
  - `/items-and-distribution` — Random items, unique items, starting items, inspection events
60
+ - `/artwork` — Generate pictures with ComfyUI (FLUX.2 [klein]) and show them: cover, intro cutscene, handouts, scenes, monsters, tokens, image puzzles
57
61
 
58
62
  ## Design Principles
59
63
 
@@ -93,7 +97,8 @@ Use these skills for detailed pattern guidance:
93
97
  - Use `{rnd:hero}` for random hero selection, `{c:EventName}` for recall
94
98
 
95
99
  ### UI & Puzzles
96
- - Always use `vunits=True` for resolution independence
100
+ - Always use `vunits=True` for resolution independence; positions are offsets from the screen centre
101
+ - A puzzle is an event started from a button (`event1=PuzzleX`); tell its story in the event before it
97
102
  - Layering order matters: background first, buttons LAST
98
103
  - Clean up all UI elements when dismissing overlays
99
104
 
@@ -108,8 +113,9 @@ Use these skills for detailed pattern guidance:
108
113
  7. Add spawns with `upsert_spawn`
109
114
  8. Configure items with `upsert_item`
110
115
  9. Write all narrative with `set_localization`
111
- 10. Validate with `validate_scenario`
112
- 11. Build with `build_scenario`
116
+ 10. Validate with `validate_scenario`, then read the plot back with `story_graph` (outline) to check branches, endings and never-reached events
117
+ 11. Save with `save_scenario` (edits stay in memory until saved or built)
118
+ 12. Build with `build_scenario`
113
119
 
114
120
  ## Available MCP Tools
115
121
 
@@ -0,0 +1,146 @@
1
+ /**
2
+ * Scenario artwork through a local ComfyUI server running FLUX.2 [klein] 4B.
3
+ * The workflow is ComfyUI's API format; the settings are the ones the distilled
4
+ * model is built for (4 steps, CFG 1, euler), which take ~25 s per image on an M1 Pro
5
+ * once the model is loaded (the first image also loads ~15 GB of weights).
6
+ */
7
+ export declare const DEFAULT_COMFYUI_URL: string;
8
+ /** Image sizes per use in a scenario (width x height, multiples of 16) */
9
+ export declare const ARTWORK_PRESETS: {
10
+ /** Scenario list picture (quest.ini image=) and the intro cutscene's left panel */
11
+ readonly cover: {
12
+ readonly width: 896;
13
+ readonly height: 896;
14
+ };
15
+ readonly intro: {
16
+ readonly width: 896;
17
+ readonly height: 896;
18
+ };
19
+ /** Letters, parchments, photographs, journal pages: portrait handouts shown during play */
20
+ readonly handout: {
21
+ readonly width: 768;
22
+ readonly height: 1024;
23
+ };
24
+ /** Landscape pictures shown during play (a room, a revelation, the ending) */
25
+ readonly scene: {
26
+ readonly width: 1024;
27
+ readonly height: 768;
28
+ };
29
+ /** Custom monster portrait (CustomMonster image=) */
30
+ readonly monster: {
31
+ readonly width: 768;
32
+ readonly height: 768;
33
+ };
34
+ /** Board token artwork (Token customImage=) */
35
+ readonly token: {
36
+ readonly width: 512;
37
+ readonly height: 512;
38
+ };
39
+ };
40
+ export type ArtworkPreset = keyof typeof ARTWORK_PRESETS;
41
+ /** Appended to every prompt unless a style is given, so a scenario's pictures look like one set */
42
+ export declare const DEFAULT_STYLE: string;
43
+ /** The three files of the FLUX.2 [klein] 4B setup and where to get them */
44
+ export declare const FLUX2_KLEIN_MODELS: {
45
+ readonly diffusion: {
46
+ readonly folder: "diffusion_models";
47
+ readonly match: RegExp;
48
+ readonly downloads: readonly [{
49
+ readonly file: "flux-2-klein-4b.safetensors";
50
+ readonly note: "bf16, 7.2 GB; use this on Apple Silicon (MPS has no fp8)";
51
+ readonly url: "https://huggingface.co/Comfy-Org/flux2-klein-4B/resolve/main/split_files/diffusion_models/flux-2-klein-4b.safetensors";
52
+ }, {
53
+ readonly file: "flux-2-klein-4b-fp8.safetensors";
54
+ readonly note: "fp8, ~4 GB; for NVIDIA GPUs with less VRAM";
55
+ readonly url: "https://huggingface.co/black-forest-labs/FLUX.2-klein-4b-fp8/resolve/main/flux-2-klein-4b-fp8.safetensors";
56
+ }];
57
+ };
58
+ readonly textEncoder: {
59
+ readonly folder: "text_encoders";
60
+ readonly match: RegExp;
61
+ readonly downloads: readonly [{
62
+ readonly file: "qwen_3_4b.safetensors";
63
+ readonly note: "7.5 GB";
64
+ readonly url: "https://huggingface.co/Comfy-Org/flux2-klein-4B/resolve/main/split_files/text_encoders/qwen_3_4b.safetensors";
65
+ }];
66
+ };
67
+ readonly vae: {
68
+ readonly folder: "vae";
69
+ readonly match: RegExp;
70
+ readonly downloads: readonly [{
71
+ readonly file: "flux2-vae.safetensors";
72
+ readonly note: "321 MB; FLUX.1 and SDXL VAEs give distorted colours";
73
+ readonly url: "https://huggingface.co/Comfy-Org/flux2-dev/resolve/main/split_files/vae/flux2-vae.safetensors";
74
+ }];
75
+ };
76
+ };
77
+ export interface Flux2KleinSettings {
78
+ diffusionModel: string;
79
+ textEncoder: string;
80
+ vae: string;
81
+ prompt: string;
82
+ width: number;
83
+ height: number;
84
+ seed: number;
85
+ steps: number;
86
+ cfg: number;
87
+ filenamePrefix: string;
88
+ }
89
+ /** Recommended sampling for the distilled model; the undistilled "base" model needs more steps and real CFG */
90
+ export declare function recommendedSampling(diffusionModel: string): {
91
+ steps: number;
92
+ cfg: number;
93
+ };
94
+ /** ComfyUI API-format workflow: FLUX.2 [klein] text-to-image */
95
+ export declare function buildFlux2KleinWorkflow(s: Flux2KleinSettings): Record<string, unknown>;
96
+ type Fetch = typeof fetch;
97
+ export interface ArtworkStatus {
98
+ reachable: boolean;
99
+ url: string;
100
+ error?: string;
101
+ comfyuiVersion?: string;
102
+ device?: string;
103
+ models: {
104
+ diffusion?: string;
105
+ textEncoder?: string;
106
+ vae?: string;
107
+ };
108
+ missing: Array<keyof typeof FLUX2_KLEIN_MODELS>;
109
+ }
110
+ /** Checks the ComfyUI server and which of the FLUX.2 [klein] files it can load */
111
+ export declare function getArtworkStatus(url?: string, fetchFn?: Fetch): Promise<ArtworkStatus>;
112
+ /** Human-readable setup instructions for what getArtworkStatus found missing */
113
+ export declare function setupInstructions(status: ArtworkStatus): string;
114
+ export interface GenerateArtworkOptions {
115
+ prompt: string;
116
+ /** Where to save the image; .jpg/.jpeg saves a JPEG (much smaller in the package), otherwise PNG */
117
+ outputFile: string;
118
+ preset?: ArtworkPreset;
119
+ width?: number;
120
+ height?: number;
121
+ seed?: number;
122
+ steps?: number;
123
+ cfg?: number;
124
+ /** Replaces DEFAULT_STYLE; pass '' for no style suffix */
125
+ style?: string;
126
+ url?: string;
127
+ timeoutMs?: number;
128
+ pollMs?: number;
129
+ fetchFn?: Fetch;
130
+ }
131
+ export interface GenerateArtworkResult {
132
+ file: string;
133
+ width: number;
134
+ height: number;
135
+ seed: number;
136
+ steps: number;
137
+ cfg: number;
138
+ diffusionModel: string;
139
+ seconds: number;
140
+ /** Compact JPEG of the result, for showing the image back to the caller */
141
+ preview: Buffer;
142
+ }
143
+ /** Generates one image with FLUX.2 [klein] on a running ComfyUI and saves it to outputFile */
144
+ export declare function generateArtwork(opts: GenerateArtworkOptions): Promise<GenerateArtworkResult>;
145
+ export {};
146
+ //# sourceMappingURL=comfyui.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"comfyui.d.ts","sourceRoot":"","sources":["../../src/artwork/comfyui.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,214 @@
1
+ import * as fs from 'node:fs';
2
+ import * as path from 'node:path';
3
+ /**
4
+ * Scenario artwork through a local ComfyUI server running FLUX.2 [klein] 4B.
5
+ * The workflow is ComfyUI's API format; the settings are the ones the distilled
6
+ * model is built for (4 steps, CFG 1, euler), which take ~25 s per image on an M1 Pro
7
+ * once the model is loaded (the first image also loads ~15 GB of weights).
8
+ */
9
+ export const DEFAULT_COMFYUI_URL = process.env.VALKYRIE_COMFYUI_URL ?? 'http://127.0.0.1:8188';
10
+ /** Image sizes per use in a scenario (width x height, multiples of 16) */
11
+ export const ARTWORK_PRESETS = {
12
+ /** Scenario list picture (quest.ini image=) and the intro cutscene's left panel */
13
+ cover: { width: 896, height: 896 },
14
+ intro: { width: 896, height: 896 },
15
+ /** Letters, parchments, photographs, journal pages: portrait handouts shown during play */
16
+ handout: { width: 768, height: 1024 },
17
+ /** Landscape pictures shown during play (a room, a revelation, the ending) */
18
+ scene: { width: 1024, height: 768 },
19
+ /** Custom monster portrait (CustomMonster image=) */
20
+ monster: { width: 768, height: 768 },
21
+ /** Board token artwork (Token customImage=) */
22
+ token: { width: 512, height: 512 },
23
+ };
24
+ /** Appended to every prompt unless a style is given, so a scenario's pictures look like one set */
25
+ export const DEFAULT_STYLE = 'Dark painterly Lovecraftian horror illustration in the style of a 1920s Mansions of Madness board game card, '
26
+ + 'muted desaturated palette, deep shadows, eerie atmosphere, no text, no letters, no watermark.';
27
+ /** The three files of the FLUX.2 [klein] 4B setup and where to get them */
28
+ export const FLUX2_KLEIN_MODELS = {
29
+ diffusion: {
30
+ folder: 'diffusion_models',
31
+ match: /flux-?2-klein-4b/i,
32
+ downloads: [
33
+ { file: 'flux-2-klein-4b.safetensors', note: 'bf16, 7.2 GB; use this on Apple Silicon (MPS has no fp8)', url: 'https://huggingface.co/Comfy-Org/flux2-klein-4B/resolve/main/split_files/diffusion_models/flux-2-klein-4b.safetensors' },
34
+ { file: 'flux-2-klein-4b-fp8.safetensors', note: 'fp8, ~4 GB; for NVIDIA GPUs with less VRAM', url: 'https://huggingface.co/black-forest-labs/FLUX.2-klein-4b-fp8/resolve/main/flux-2-klein-4b-fp8.safetensors' },
35
+ ],
36
+ },
37
+ textEncoder: {
38
+ folder: 'text_encoders',
39
+ match: /qwen_?3_?4b/i,
40
+ downloads: [
41
+ { file: 'qwen_3_4b.safetensors', note: '7.5 GB', url: 'https://huggingface.co/Comfy-Org/flux2-klein-4B/resolve/main/split_files/text_encoders/qwen_3_4b.safetensors' },
42
+ ],
43
+ },
44
+ vae: {
45
+ folder: 'vae',
46
+ match: /flux2-vae/i,
47
+ downloads: [
48
+ { file: 'flux2-vae.safetensors', note: '321 MB; FLUX.1 and SDXL VAEs give distorted colours', url: 'https://huggingface.co/Comfy-Org/flux2-dev/resolve/main/split_files/vae/flux2-vae.safetensors' },
49
+ ],
50
+ },
51
+ };
52
+ /** Recommended sampling for the distilled model; the undistilled "base" model needs more steps and real CFG */
53
+ export function recommendedSampling(diffusionModel) {
54
+ return /base/i.test(diffusionModel) ? { steps: 20, cfg: 4 } : { steps: 4, cfg: 1 };
55
+ }
56
+ /** ComfyUI API-format workflow: FLUX.2 [klein] text-to-image */
57
+ export function buildFlux2KleinWorkflow(s) {
58
+ return {
59
+ '1': { class_type: 'UNETLoader', inputs: { unet_name: s.diffusionModel, weight_dtype: 'default' } },
60
+ '2': { class_type: 'CLIPLoader', inputs: { clip_name: s.textEncoder, type: 'flux2' } },
61
+ '3': { class_type: 'VAELoader', inputs: { vae_name: s.vae } },
62
+ '4': { class_type: 'CLIPTextEncode', inputs: { clip: ['2', 0], text: s.prompt } },
63
+ '5': { class_type: 'ConditioningZeroOut', inputs: { conditioning: ['4', 0] } },
64
+ '6': { class_type: 'EmptyFlux2LatentImage', inputs: { width: s.width, height: s.height, batch_size: 1 } },
65
+ '7': { class_type: 'Flux2Scheduler', inputs: { steps: s.steps, width: s.width, height: s.height } },
66
+ '8': { class_type: 'KSamplerSelect', inputs: { sampler_name: 'euler' } },
67
+ '9': { class_type: 'RandomNoise', inputs: { noise_seed: s.seed } },
68
+ '10': { class_type: 'CFGGuider', inputs: { model: ['1', 0], positive: ['4', 0], negative: ['5', 0], cfg: s.cfg } },
69
+ '11': { class_type: 'SamplerCustomAdvanced', inputs: { noise: ['9', 0], guider: ['10', 0], sampler: ['8', 0], sigmas: ['7', 0], latent_image: ['6', 0] } },
70
+ '12': { class_type: 'VAEDecode', inputs: { samples: ['11', 0], vae: ['3', 0] } },
71
+ '13': { class_type: 'SaveImage', inputs: { images: ['12', 0], filename_prefix: s.filenamePrefix } },
72
+ };
73
+ }
74
+ async function getJson(fetchFn, url) {
75
+ const res = await fetchFn(url, { signal: AbortSignal.timeout(10_000) });
76
+ if (!res.ok)
77
+ throw new Error(`${url} answered ${res.status}`);
78
+ return res.json();
79
+ }
80
+ /** Picks the preferred file: the distilled model over "base", then the first match */
81
+ function pickModel(files, match) {
82
+ const candidates = files.filter(f => match.test(f));
83
+ return candidates.find(f => !/base/i.test(f)) ?? candidates[0];
84
+ }
85
+ /** Checks the ComfyUI server and which of the FLUX.2 [klein] files it can load */
86
+ export async function getArtworkStatus(url = DEFAULT_COMFYUI_URL, fetchFn = fetch) {
87
+ const status = { reachable: false, url, models: {}, missing: [] };
88
+ try {
89
+ const stats = await getJson(fetchFn, `${url}/system_stats`);
90
+ status.reachable = true;
91
+ status.comfyuiVersion = stats.system?.comfyui_version;
92
+ status.device = stats.devices?.[0]?.name;
93
+ }
94
+ catch (e) {
95
+ status.error = e.message;
96
+ status.missing = ['diffusion', 'textEncoder', 'vae'];
97
+ return status;
98
+ }
99
+ for (const key of ['diffusion', 'textEncoder', 'vae']) {
100
+ const spec = FLUX2_KLEIN_MODELS[key];
101
+ let files = [];
102
+ try {
103
+ files = await getJson(fetchFn, `${url}/models/${spec.folder}`);
104
+ }
105
+ catch {
106
+ // Older ComfyUI without /models/<folder>: treat as missing so the setup hint is shown
107
+ }
108
+ const found = pickModel(files, spec.match);
109
+ if (found)
110
+ status.models[key] = found;
111
+ else
112
+ status.missing.push(key);
113
+ }
114
+ return status;
115
+ }
116
+ /** Human-readable setup instructions for what getArtworkStatus found missing */
117
+ export function setupInstructions(status) {
118
+ const lines = [];
119
+ if (!status.reachable) {
120
+ lines.push(`ComfyUI is not reachable at ${status.url}${status.error ? ` (${status.error})` : ''}. With comfy-cli:`, ' pip install comfy-cli (or: uv tool install comfy-cli)', ' comfy install (once; installs ComfyUI into a workspace)', ' comfy launch --background', 'Models kept elsewhere: comfy launch --background -- --extra-model-paths-config <yaml listing diffusion_models, text_encoders, vae>.', 'Set VALKYRIE_COMFYUI_URL if ComfyUI runs on another address.');
121
+ }
122
+ for (const key of status.missing) {
123
+ const spec = FLUX2_KLEIN_MODELS[key];
124
+ lines.push(`Missing ${spec.folder} model. Download one of:`);
125
+ for (const d of spec.downloads) {
126
+ lines.push(` ${d.file} (${d.note}):`, ` comfy model download --url ${d.url} --relative-path models/${spec.folder}`);
127
+ }
128
+ }
129
+ return lines.join('\n');
130
+ }
131
+ function roundTo16(n) {
132
+ return Math.max(256, Math.round(n / 16) * 16);
133
+ }
134
+ /** Generates one image with FLUX.2 [klein] on a running ComfyUI and saves it to outputFile */
135
+ export async function generateArtwork(opts) {
136
+ const url = opts.url ?? DEFAULT_COMFYUI_URL;
137
+ const fetchFn = opts.fetchFn ?? fetch;
138
+ const status = await getArtworkStatus(url, fetchFn);
139
+ if (!status.reachable || status.missing.length > 0) {
140
+ throw new Error(`ComfyUI is not ready for FLUX.2 [klein].\n${setupInstructions(status)}`);
141
+ }
142
+ const diffusionModel = status.models.diffusion;
143
+ const size = ARTWORK_PRESETS[opts.preset ?? 'scene'];
144
+ const width = roundTo16(opts.width ?? size.width);
145
+ const height = roundTo16(opts.height ?? size.height);
146
+ const sampling = recommendedSampling(diffusionModel);
147
+ const style = opts.style ?? DEFAULT_STYLE;
148
+ const settings = {
149
+ diffusionModel,
150
+ textEncoder: status.models.textEncoder,
151
+ vae: status.models.vae,
152
+ prompt: style ? `${opts.prompt.trim()} ${style}` : opts.prompt.trim(),
153
+ width,
154
+ height,
155
+ seed: opts.seed ?? Math.floor(Math.random() * 2 ** 32),
156
+ steps: opts.steps ?? sampling.steps,
157
+ cfg: opts.cfg ?? sampling.cfg,
158
+ filenamePrefix: `valkyrie_${path.basename(opts.outputFile, path.extname(opts.outputFile)).replace(/[^\w-]/g, '_')}`,
159
+ };
160
+ const started = Date.now();
161
+ const submit = await fetchFn(`${url}/prompt`, {
162
+ method: 'POST',
163
+ headers: { 'Content-Type': 'application/json' },
164
+ body: JSON.stringify({ prompt: buildFlux2KleinWorkflow(settings) }),
165
+ signal: AbortSignal.timeout(30_000),
166
+ });
167
+ const submitted = await submit.json();
168
+ if (!submit.ok || !submitted.prompt_id) {
169
+ throw new Error(`ComfyUI rejected the workflow: ${submitted.error?.message ?? submit.status} ${JSON.stringify(submitted.node_errors ?? {})}`);
170
+ }
171
+ // The first image of a session also loads the models, which can take minutes
172
+ const timeoutMs = opts.timeoutMs ?? 15 * 60_000;
173
+ const pollMs = opts.pollMs ?? 2000;
174
+ let image;
175
+ while (!image) {
176
+ if (Date.now() - started > timeoutMs)
177
+ throw new Error(`ComfyUI did not finish within ${Math.round(timeoutMs / 1000)} s (prompt ${submitted.prompt_id})`);
178
+ await new Promise(r => setTimeout(r, pollMs));
179
+ const history = await getJson(fetchFn, `${url}/history/${submitted.prompt_id}`);
180
+ const entry = history[submitted.prompt_id];
181
+ if (!entry)
182
+ continue;
183
+ if (entry.status?.status_str === 'error') {
184
+ throw new Error(`ComfyUI failed: ${JSON.stringify(entry.status.messages ?? []).slice(0, 1000)}`);
185
+ }
186
+ image = Object.values(entry.outputs ?? {}).flatMap(o => o.images ?? [])[0];
187
+ if (!image && entry.status?.status_str === 'success')
188
+ throw new Error('ComfyUI finished without an image');
189
+ }
190
+ const view = (extra = '') => `${url}/view?filename=${encodeURIComponent(image.filename)}&subfolder=${encodeURIComponent(image.subfolder)}&type=${image.type}${extra}`;
191
+ const download = async (u) => {
192
+ const res = await fetchFn(u, { signal: AbortSignal.timeout(60_000) });
193
+ if (!res.ok)
194
+ throw new Error(`Could not download the image from ComfyUI (${res.status})`);
195
+ return Buffer.from(await res.arrayBuffer());
196
+ };
197
+ const jpeg = /\.jpe?g$/i.test(opts.outputFile);
198
+ const full = await download(view(jpeg ? '&preview=jpeg;90' : ''));
199
+ const preview = jpeg ? full : await download(view('&preview=jpeg;80'));
200
+ fs.mkdirSync(path.dirname(opts.outputFile), { recursive: true });
201
+ fs.writeFileSync(opts.outputFile, full);
202
+ return {
203
+ file: opts.outputFile,
204
+ width,
205
+ height,
206
+ seed: settings.seed,
207
+ steps: settings.steps,
208
+ cfg: settings.cfg,
209
+ diffusionModel,
210
+ seconds: Math.round((Date.now() - started) / 1000),
211
+ preview,
212
+ };
213
+ }
214
+ //# sourceMappingURL=comfyui.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"comfyui.js","sourceRoot":"","sources":["../../src/artwork/comfyui.ts"],"names":[],"mappings":"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"}
@@ -105,7 +105,10 @@ function generateCatalogSource(catalogs) {
105
105
  const isMainModule = process.argv[1] && (process.argv[1].endsWith('extract-catalogs.ts') ||
106
106
  process.argv[1].endsWith('extract-catalogs.js'));
107
107
  if (isMainModule) {
108
- const valkyrieContentDir = path.resolve(import.meta.dirname ?? '.', '../../../valkyrie/unity/Assets/StreamingAssets/content/MoM');
108
+ // The Valkyrie source checkout, by default next to this repository
109
+ const valkyrieRepo = process.env.VALKYRIE_SOURCE_DIR
110
+ ?? path.join(path.dirname(path.dirname(path.dirname(import.meta.dirname ?? '.'))), 'valkyrie');
111
+ const valkyrieContentDir = path.join(valkyrieRepo, 'unity', 'Assets', 'StreamingAssets', 'content', 'MoM');
109
112
  if (!fs.existsSync(valkyrieContentDir)) {
110
113
  console.error(`Valkyrie content not found at: ${valkyrieContentDir}`);
111
114
  console.error('Make sure the Valkyrie repo is cloned at the expected path.');
@@ -1 +1 @@
1
- {"version":3,"file":"extract-catalogs.js","sourceRoot":"","sources":["../../src/catalogs/extract-catalogs.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"extract-catalogs.js","sourceRoot":"","sources":["../../src/catalogs/extract-catalogs.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import type { ScenarioModel } from '../model/scenario-model.js';
2
+ /**
3
+ * Package name Valkyrie can publish: the scenario folder name, which must not contain spaces
4
+ * (it becomes the package and manifest file name, and the key in the download list).
5
+ * "The Wrath of Elder Claude" → "TheWrathOfElderClaude".
6
+ */
7
+ export declare function toPackageName(name: string): string;
8
+ /**
9
+ * Writes what Valkyrie's editor "Create Package" writes next to the .valkyrie file
10
+ * (EditorTools.CreatePackage): <Package>.ini, the manifest a scenario list entry is made from,
11
+ * and a copy of the cover image. version is the SHA-256 of the package, as .NET's
12
+ * BitConverter.ToString prints it ("AB-CD-...").
13
+ */
14
+ export declare function writePackageManifest(model: ScenarioModel, packagePath: string): {
15
+ manifest: string;
16
+ icon?: string;
17
+ };
18
+ //# sourceMappingURL=package-manifest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"package-manifest.d.ts","sourceRoot":"","sources":["../../src/io/package-manifest.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAEhE;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAGlD;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAoCnH"}