@waits/cadence 0.5.0 → 0.6.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.
- package/package.json +1 -1
- package/prompts/art/compose.ts +11 -2
- package/scripts/generate-art.ts +15 -2
- package/scripts/theme.ts +2 -2
package/package.json
CHANGED
package/prompts/art/compose.ts
CHANGED
|
@@ -7,21 +7,30 @@ import { FANTASY, type FantasyLevel } from "./fantasy";
|
|
|
7
7
|
* Build the full image-gen prompt for a freeform subject × fantasy level × format.
|
|
8
8
|
* `style`/`negatives` default to the built-in luminist look; a pack or `--style-file`
|
|
9
9
|
* can override them. `COMPOSITION` (UI-safe framing) is always engine-supplied.
|
|
10
|
+
* `brand` (from `--brand`, a project's theme palette) appends a last, explicit
|
|
11
|
+
* palette nudge so it dominates any color the base style mentions.
|
|
10
12
|
*/
|
|
11
13
|
export function composePrompt(opts: {
|
|
12
14
|
subject: string;
|
|
13
15
|
level: FantasyLevel;
|
|
14
|
-
format: Format;
|
|
15
16
|
style?: string;
|
|
16
17
|
negatives?: string;
|
|
18
|
+
format: Format;
|
|
19
|
+
brand?: { accent?: string; paper?: string };
|
|
17
20
|
}): string {
|
|
21
|
+
const brand = opts.brand?.accent
|
|
22
|
+
? `Tune the palette toward the brand: a ${opts.brand.accent} accent${opts.brand.paper ? ` over ${opts.brand.paper}-toned light` : ""} — cohesive and harmonious, never garish.`
|
|
23
|
+
: "";
|
|
18
24
|
return [
|
|
19
25
|
opts.style ?? STYLE,
|
|
20
26
|
`Subject: ${opts.subject}.`,
|
|
21
27
|
FANTASY[opts.level],
|
|
22
28
|
COMPOSITION[opts.format],
|
|
29
|
+
brand,
|
|
23
30
|
opts.negatives ?? NEGATIVES,
|
|
24
|
-
]
|
|
31
|
+
]
|
|
32
|
+
.filter(Boolean)
|
|
33
|
+
.join(" ");
|
|
25
34
|
}
|
|
26
35
|
|
|
27
36
|
export { LANDMARKS, FANTASY };
|
package/scripts/generate-art.ts
CHANGED
|
@@ -18,7 +18,7 @@ import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "
|
|
|
18
18
|
import { join } from "node:path";
|
|
19
19
|
import { composePrompt, LANDMARKS, type FantasyLevel } from "../prompts/art/compose";
|
|
20
20
|
import type { Format } from "../src/schema/beats";
|
|
21
|
-
import { findCadenceDir } from "./_theme";
|
|
21
|
+
import { discoverProjectTheme, findCadenceDir } from "./_theme";
|
|
22
22
|
|
|
23
23
|
const SIZE: Record<Format, string> = { "16x9": "1536x1024", "1x1": "1024x1024", "9x16": "1024x1536" };
|
|
24
24
|
|
|
@@ -79,6 +79,19 @@ const styleFile = flag("--style-file");
|
|
|
79
79
|
const style = styleFile ? readFileSync(styleFile, "utf8") : pack.style;
|
|
80
80
|
const negatives = pack.negatives;
|
|
81
81
|
|
|
82
|
+
// --brand: tint generated art toward the project's theme palette (accent + paper).
|
|
83
|
+
let brand: { accent?: string; paper?: string } | undefined;
|
|
84
|
+
if (has("--brand")) {
|
|
85
|
+
const tf = discoverProjectTheme(process.cwd());
|
|
86
|
+
if (tf) {
|
|
87
|
+
const colors = (JSON.parse(readFileSync(tf, "utf8")).colors ?? {}) as Record<string, string>;
|
|
88
|
+
brand = { accent: colors.signalBlue, paper: colors.paper };
|
|
89
|
+
console.error(`· --brand: ${tf} (accent ${brand.accent ?? "—"})`);
|
|
90
|
+
} else {
|
|
91
|
+
console.error("· --brand: no .cadence/theme.json found — generating unbranded");
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
82
95
|
// A job = one image to generate. Freeform `--prompt` (needs `--name`) wins;
|
|
83
96
|
// otherwise pull subjects from the pack via --landmark/--all.
|
|
84
97
|
type Job = { subject: string; slug: string; label: string };
|
|
@@ -117,7 +130,7 @@ if (!process.env.OPENAI_API_KEY) {
|
|
|
117
130
|
}
|
|
118
131
|
|
|
119
132
|
async function generate(job: Job) {
|
|
120
|
-
const prompt = composePrompt({ subject: job.subject, level, format, style, negatives });
|
|
133
|
+
const prompt = composePrompt({ subject: job.subject, level, format, style, negatives, brand });
|
|
121
134
|
const fname = `${job.slug}-${level}-${format}.png`;
|
|
122
135
|
process.stdout.write(`· ${fname} … `);
|
|
123
136
|
const res = await fetch("https://api.openai.com/v1/images/generations", {
|
package/scripts/theme.ts
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* the palette and writes a themes/<name>.json. See the cadence skill.
|
|
13
13
|
*/
|
|
14
14
|
import { mkdirSync, writeFileSync } from "node:fs";
|
|
15
|
-
import { join } from "node:path";
|
|
15
|
+
import { dirname, join } from "node:path";
|
|
16
16
|
import { deriveTheme } from "../src/theme/derive";
|
|
17
17
|
|
|
18
18
|
const args = process.argv.slice(2);
|
|
@@ -61,8 +61,8 @@ if (!accent) {
|
|
|
61
61
|
const name = flag("--name") ?? "brand";
|
|
62
62
|
const theme = deriveTheme({ name, accent, ink: flag("--ink"), paper: flag("--paper"), gold: flag("--gold") });
|
|
63
63
|
|
|
64
|
-
mkdirSync("themes", { recursive: true });
|
|
65
64
|
const out = flag("--out") ?? join("themes", `${name}.json`);
|
|
65
|
+
mkdirSync(dirname(out), { recursive: true });
|
|
66
66
|
writeFileSync(out, JSON.stringify(theme, null, 2));
|
|
67
67
|
|
|
68
68
|
// Portable design summary — a human-readable companion to the JSON.
|