@nebutra/brand-genesis 0.2.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.
- package/.nebutra/debug/brand-genesis.jsonl +6 -0
- package/.nebutra/debug/content-store.jsonl +6 -0
- package/.nebutra/debug/event-log.jsonl +1 -0
- package/.turbo/turbo-build.log +22 -0
- package/.turbo/turbo-test.log +17 -0
- package/.turbo/turbo-typecheck.log +4 -0
- package/CHANGELOG.md +7 -0
- package/LICENSE +676 -0
- package/README.md +31 -0
- package/dist/chunk-SB4N3ZZW.js +397 -0
- package/dist/chunk-SB4N3ZZW.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +70 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +88 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -0
- package/examples/brand-context-only.ts +9 -0
- package/examples/doctor.ts +11 -0
- package/examples/quickstart.ts +27 -0
- package/package.json +70 -0
- package/plays/brand_film_60s/SKILL.md +84 -0
- package/plays/brand_film_60s/fixtures/input_1.json +5 -0
- package/plays/brand_film_60s/fixtures/input_2.json +5 -0
- package/plays/brand_film_60s/fixtures/input_3.json +5 -0
- package/plays/brand_film_60s/templates/BRAND.md.tmpl +29 -0
- package/plays/brand_film_60s/templates/palette.json.tmpl +4 -0
- package/src/cli.ts +64 -0
- package/src/index.test.ts +123 -0
- package/src/index.ts +515 -0
- package/tsconfig.json +9 -0
- package/tsup.config.ts +11 -0
package/README.md
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# @nebutra/brand-genesis
|
|
2
|
+
|
|
3
|
+
`brand-genesis` is the flagship Play package. It distills a one-sentence
|
|
4
|
+
company idea into a `BrandContext`, writes `company/BRAND.md`, then delegates
|
|
5
|
+
asset generation to existing media capabilities.
|
|
6
|
+
|
|
7
|
+
It intentionally does not own image, video, audio, voice, mesh, or landing-page
|
|
8
|
+
generation primitives.
|
|
9
|
+
|
|
10
|
+
```ts
|
|
11
|
+
import { BrandGenesis } from "@nebutra/brand-genesis";
|
|
12
|
+
|
|
13
|
+
const genesis = await BrandGenesis.open(".nebutra/brand-genesis", {
|
|
14
|
+
tenantId: "tenant_demo",
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
const result = await genesis.run({
|
|
18
|
+
idea: "AI debugging for indie devs called Loop",
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
console.log(result.brand.name, result.film.path);
|
|
22
|
+
await genesis.close();
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Commands:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
pnpm brand-genesis:doctor
|
|
29
|
+
pnpm brand-genesis:quickstart "AI debugging for indie devs called Loop"
|
|
30
|
+
pnpm brand-genesis:debug
|
|
31
|
+
```
|
|
@@ -0,0 +1,397 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
import { mkdir } from "fs/promises";
|
|
3
|
+
import { dirname, join } from "path";
|
|
4
|
+
import { MeshPipeline } from "@nebutra/3d-pipeline";
|
|
5
|
+
import { AudioPipeline } from "@nebutra/audio-pipeline";
|
|
6
|
+
import { appendCapabilityDebug, readCapabilityDebug } from "@nebutra/capability-kit/debug";
|
|
7
|
+
import { ContentStore, serializeContentFrontmatter } from "@nebutra/content-store";
|
|
8
|
+
import { CapabilityError } from "@nebutra/errors";
|
|
9
|
+
import { EventLog } from "@nebutra/event-log";
|
|
10
|
+
import {
|
|
11
|
+
assetId
|
|
12
|
+
} from "@nebutra/generation-context";
|
|
13
|
+
import { ImagePipeline } from "@nebutra/image-pipeline";
|
|
14
|
+
import { VideoPipeline } from "@nebutra/video-pipeline";
|
|
15
|
+
import { VoiceRealtime } from "@nebutra/voice-realtime";
|
|
16
|
+
var PLAY_NAME = "brand_film_60s";
|
|
17
|
+
var CHECKPOINTS = [
|
|
18
|
+
"brand_distillation",
|
|
19
|
+
"visual_direction",
|
|
20
|
+
"assets_generated",
|
|
21
|
+
"video_rendered",
|
|
22
|
+
"final_compose"
|
|
23
|
+
];
|
|
24
|
+
function requireTenant(explicit, fallback) {
|
|
25
|
+
const tenantId = explicit ?? fallback;
|
|
26
|
+
if (!tenantId?.trim()) {
|
|
27
|
+
throw new CapabilityError("brand-genesis", "Brand Genesis requires tenant context", {
|
|
28
|
+
suggestion: "Pass tenantId on the input or construct BrandGenesis with tenantId.",
|
|
29
|
+
statusCode: 400
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
return tenantId;
|
|
33
|
+
}
|
|
34
|
+
function normalizeBrandId(name) {
|
|
35
|
+
return name.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "").slice(0, 32);
|
|
36
|
+
}
|
|
37
|
+
function pickName(idea) {
|
|
38
|
+
const called = idea.match(/\bcalled\s+([A-Z][a-zA-Z0-9]*(?:\s+[A-Z][a-zA-Z0-9]*)?)/);
|
|
39
|
+
if (called?.[1]) return called[1].trim();
|
|
40
|
+
const capitalized = [...idea.matchAll(/\b[A-Z][a-zA-Z0-9]{2,}\b/g)].map((match) => match[0]).filter((value) => !["AI", "SaaS", "API"].includes(value));
|
|
41
|
+
return capitalized.at(-1) ?? "Venture";
|
|
42
|
+
}
|
|
43
|
+
function paletteFor(hint) {
|
|
44
|
+
switch (hint) {
|
|
45
|
+
case "cyberpunk":
|
|
46
|
+
case "futurist":
|
|
47
|
+
return [
|
|
48
|
+
{ name: "electric cyan", hex: "#00D4FF", role: "primary" },
|
|
49
|
+
{ name: "carbon black", hex: "#111318", role: "background" },
|
|
50
|
+
{ name: "signal amber", hex: "#F3C14B", role: "accent" }
|
|
51
|
+
];
|
|
52
|
+
case "organic":
|
|
53
|
+
return [
|
|
54
|
+
{ name: "moss", hex: "#3D7A57", role: "primary" },
|
|
55
|
+
{ name: "paper", hex: "#F7F4EA", role: "background" },
|
|
56
|
+
{ name: "clay", hex: "#C86B4A", role: "accent" }
|
|
57
|
+
];
|
|
58
|
+
case "playful":
|
|
59
|
+
return [
|
|
60
|
+
{ name: "coral", hex: "#FF6B6B", role: "primary" },
|
|
61
|
+
{ name: "ink", hex: "#202124", role: "neutral" },
|
|
62
|
+
{ name: "mint", hex: "#7CE2C6", role: "accent" }
|
|
63
|
+
];
|
|
64
|
+
case "corporate":
|
|
65
|
+
return [
|
|
66
|
+
{ name: "trust blue", hex: "#2454D6", role: "primary" },
|
|
67
|
+
{ name: "slate", hex: "#202A36", role: "neutral" },
|
|
68
|
+
{ name: "clear sky", hex: "#E8F0FF", role: "background" }
|
|
69
|
+
];
|
|
70
|
+
case "retro":
|
|
71
|
+
return [
|
|
72
|
+
{ name: "oxide", hex: "#B95F3B", role: "primary" },
|
|
73
|
+
{ name: "night ink", hex: "#18202A", role: "neutral" },
|
|
74
|
+
{ name: "cream light", hex: "#F8E7C9", role: "background" }
|
|
75
|
+
];
|
|
76
|
+
default:
|
|
77
|
+
return [
|
|
78
|
+
{ name: "graphite", hex: "#1F2933", role: "primary" },
|
|
79
|
+
{ name: "white", hex: "#FFFFFF", role: "background" },
|
|
80
|
+
{ name: "signal green", hex: "#00A693", role: "accent" }
|
|
81
|
+
];
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
function styleFor(hint) {
|
|
85
|
+
const name = hint ?? "minimal";
|
|
86
|
+
const keywordsByHint = {
|
|
87
|
+
cyberpunk: ["electric", "terminal-native", "high-contrast"],
|
|
88
|
+
minimal: ["calm", "precise", "spacious"],
|
|
89
|
+
organic: ["warm", "natural", "human"],
|
|
90
|
+
playful: ["bright", "friendly", "kinetic"],
|
|
91
|
+
corporate: ["credible", "structured", "clear"],
|
|
92
|
+
retro: ["nostalgic", "tactile", "characterful"],
|
|
93
|
+
futurist: ["clean", "technical", "forward"]
|
|
94
|
+
};
|
|
95
|
+
return {
|
|
96
|
+
name,
|
|
97
|
+
keywords: keywordsByHint[name],
|
|
98
|
+
avoid: ["generic stock", "dark horror", "visual clutter"]
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
function distillBrandIdea(input) {
|
|
102
|
+
const idea = input.idea.trim();
|
|
103
|
+
if (idea.length === 0) {
|
|
104
|
+
throw new CapabilityError("brand-genesis", "Brand idea is empty", {
|
|
105
|
+
suggestion: "Pass a one-sentence company idea before running Brand Genesis.",
|
|
106
|
+
statusCode: 400
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
const name = pickName(idea);
|
|
110
|
+
const devAudience = /\bdev|debug|code|developer|engineering/i.test(idea);
|
|
111
|
+
const audience = devAudience ? "Independent developers and small engineering teams shipping software quickly" : "Early-stage founders validating a focused product wedge";
|
|
112
|
+
const toneKeywords = devAudience ? ["technical", "direct", "warm"] : ["clear", "confident", "useful"];
|
|
113
|
+
return {
|
|
114
|
+
name,
|
|
115
|
+
oneLiner: idea,
|
|
116
|
+
tagline: devAudience ? "Debug like it is a conversation" : `${name} turns intent into launch`,
|
|
117
|
+
targetAudience: audience,
|
|
118
|
+
toneKeywords,
|
|
119
|
+
differentiation: devAudience ? "Understands the full production context instead of treating each error as an isolated message" : "Combines brand, execution, and company memory in one repeatable workflow",
|
|
120
|
+
visualStyle: styleFor(input.visualDirectionHint)
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
function brandContextFromDraft(draft, tenantId, sourcePath = "company/BRAND.md", palette = paletteFor(draft.visualStyle.name)) {
|
|
124
|
+
return {
|
|
125
|
+
tenantId,
|
|
126
|
+
brandId: normalizeBrandId(draft.name),
|
|
127
|
+
name: draft.name,
|
|
128
|
+
palette,
|
|
129
|
+
typography: {
|
|
130
|
+
heading: draft.visualStyle.name === "cyberpunk" ? "Geist Mono" : "Geist Sans",
|
|
131
|
+
body: "Geist Sans",
|
|
132
|
+
accent: "Geist Mono"
|
|
133
|
+
},
|
|
134
|
+
visualStyle: draft.visualStyle,
|
|
135
|
+
referenceImages: [],
|
|
136
|
+
forbidden: draft.visualStyle.avoid ?? [],
|
|
137
|
+
toneKeywords: draft.toneKeywords,
|
|
138
|
+
sourcePath
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
function renderBrandMarkdown(draft, brand) {
|
|
142
|
+
return serializeContentFrontmatter(
|
|
143
|
+
{
|
|
144
|
+
type: "brand_profile",
|
|
145
|
+
brand_id: brand.brandId,
|
|
146
|
+
name: brand.name
|
|
147
|
+
},
|
|
148
|
+
[
|
|
149
|
+
`# ${brand.name}`,
|
|
150
|
+
"",
|
|
151
|
+
draft.oneLiner,
|
|
152
|
+
"",
|
|
153
|
+
"## Tagline",
|
|
154
|
+
"",
|
|
155
|
+
draft.tagline,
|
|
156
|
+
"",
|
|
157
|
+
"## Audience",
|
|
158
|
+
"",
|
|
159
|
+
draft.targetAudience,
|
|
160
|
+
"",
|
|
161
|
+
"## Tone",
|
|
162
|
+
"",
|
|
163
|
+
brand.toneKeywords.join(", "),
|
|
164
|
+
"",
|
|
165
|
+
"## Visual Direction",
|
|
166
|
+
"",
|
|
167
|
+
`${brand.visualStyle.name}: ${brand.visualStyle.keywords.join(", ")}`,
|
|
168
|
+
"",
|
|
169
|
+
"## Differentiation",
|
|
170
|
+
"",
|
|
171
|
+
draft.differentiation,
|
|
172
|
+
""
|
|
173
|
+
].join("\n")
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
function renderLandingManifest(draft, brand) {
|
|
177
|
+
return [
|
|
178
|
+
"<!doctype html>",
|
|
179
|
+
'<html lang="en">',
|
|
180
|
+
"<head>",
|
|
181
|
+
' <meta charset="utf-8" />',
|
|
182
|
+
` <title>${brand.name}</title>`,
|
|
183
|
+
"</head>",
|
|
184
|
+
"<body>",
|
|
185
|
+
` <main data-brand-id="${brand.brandId}">`,
|
|
186
|
+
` <h1>${brand.name}</h1>`,
|
|
187
|
+
` <p>${draft.tagline}</p>`,
|
|
188
|
+
` <p>${draft.oneLiner}</p>`,
|
|
189
|
+
" </main>",
|
|
190
|
+
"</body>",
|
|
191
|
+
"</html>",
|
|
192
|
+
""
|
|
193
|
+
].join("\n");
|
|
194
|
+
}
|
|
195
|
+
var BrandGenesis = class _BrandGenesis {
|
|
196
|
+
#tenantId;
|
|
197
|
+
#root;
|
|
198
|
+
#debugRoot;
|
|
199
|
+
#contentStore;
|
|
200
|
+
#eventLog;
|
|
201
|
+
#image;
|
|
202
|
+
#video;
|
|
203
|
+
#audio;
|
|
204
|
+
#voice;
|
|
205
|
+
#mesh;
|
|
206
|
+
constructor(options) {
|
|
207
|
+
this.#tenantId = options.tenantId;
|
|
208
|
+
this.#root = options.root ?? join(process.cwd(), ".nebutra", "brand-genesis");
|
|
209
|
+
this.#debugRoot = options.debugRoot ?? process.cwd();
|
|
210
|
+
this.#contentStore = options.contentStore;
|
|
211
|
+
this.#eventLog = options.eventLog;
|
|
212
|
+
this.#image = options.imagePipeline ?? new ImagePipeline({ root: this.#root });
|
|
213
|
+
this.#video = options.videoPipeline ?? new VideoPipeline({ root: this.#root });
|
|
214
|
+
this.#audio = options.audioPipeline ?? new AudioPipeline({ root: this.#root });
|
|
215
|
+
this.#voice = options.voiceRealtime ?? new VoiceRealtime({ root: this.#root });
|
|
216
|
+
this.#mesh = options.meshPipeline ?? new MeshPipeline({ root: this.#root });
|
|
217
|
+
}
|
|
218
|
+
static async open(root = ".nebutra/brand-genesis", options = {}) {
|
|
219
|
+
const tenantId = options.tenantId ?? "local";
|
|
220
|
+
await mkdir(root, { recursive: true });
|
|
221
|
+
const contentStore = await ContentStore.open(join(root, "content"), { tenantId });
|
|
222
|
+
const eventLog = await EventLog.open(join(root, "event-log"), { tenantId });
|
|
223
|
+
return new _BrandGenesis({ ...options, tenantId, root, contentStore, eventLog });
|
|
224
|
+
}
|
|
225
|
+
async run(input) {
|
|
226
|
+
const tenantId = requireTenant(input.tenantId, this.#tenantId);
|
|
227
|
+
const draft = distillBrandIdea(input);
|
|
228
|
+
const brand = brandContextFromDraft(draft, tenantId);
|
|
229
|
+
const brandMarkdown = renderBrandMarkdown(draft, brand);
|
|
230
|
+
await this.#contentStore.write(brand.sourcePath, brandMarkdown);
|
|
231
|
+
const palettePath = "company/assets/palette.json";
|
|
232
|
+
await this.#contentStore.write(
|
|
233
|
+
palettePath,
|
|
234
|
+
`${JSON.stringify({ brandId: brand.brandId, colors: brand.palette }, null, 2)}
|
|
235
|
+
`
|
|
236
|
+
);
|
|
237
|
+
await this.#debug({
|
|
238
|
+
type: "checkpoint",
|
|
239
|
+
step: CHECKPOINTS[0],
|
|
240
|
+
tenantId,
|
|
241
|
+
brandId: brand.brandId
|
|
242
|
+
});
|
|
243
|
+
await this.#debug({
|
|
244
|
+
type: "checkpoint",
|
|
245
|
+
step: CHECKPOINTS[1],
|
|
246
|
+
tenantId,
|
|
247
|
+
brandId: brand.brandId
|
|
248
|
+
});
|
|
249
|
+
const [logo, hero, icon] = await Promise.all([
|
|
250
|
+
this.#image.generate({ type: "logo", company: brand.name, oneLiner: draft.oneLiner }, brand),
|
|
251
|
+
this.#image.generate({ type: "hero", headline: draft.tagline }, brand),
|
|
252
|
+
this.#image.generate({ type: "icon", subject: brand.name }, brand)
|
|
253
|
+
]);
|
|
254
|
+
const mesh = await this.#mesh.fromImage(logo, brand);
|
|
255
|
+
await this.#debug({
|
|
256
|
+
type: "checkpoint",
|
|
257
|
+
step: CHECKPOINTS[2],
|
|
258
|
+
tenantId,
|
|
259
|
+
brandId: brand.brandId
|
|
260
|
+
});
|
|
261
|
+
const storyboard = await this.#video.plan(
|
|
262
|
+
{ type: "brand-film", durationS: 60, theme: draft.tagline },
|
|
263
|
+
brand
|
|
264
|
+
);
|
|
265
|
+
const rendered = await this.#video.render(storyboard, brand);
|
|
266
|
+
await this.#debug({
|
|
267
|
+
type: "checkpoint",
|
|
268
|
+
step: CHECKPOINTS[3],
|
|
269
|
+
tenantId,
|
|
270
|
+
brandId: brand.brandId
|
|
271
|
+
});
|
|
272
|
+
const bgm = await this.#audio.generate(
|
|
273
|
+
{ type: "bgm", durationS: rendered.durationS, mood: brand.toneKeywords.join(" ") },
|
|
274
|
+
brand,
|
|
275
|
+
true
|
|
276
|
+
);
|
|
277
|
+
const narration = await this.#voice.synthesizeNarration(
|
|
278
|
+
{
|
|
279
|
+
script: `${draft.tagline}. ${draft.oneLiner}. ${draft.differentiation}.`,
|
|
280
|
+
targetDurationS: Math.max(8, Math.min(20, rendered.durationS - 3)),
|
|
281
|
+
...input.founderVoiceId !== void 0 ? { voiceProfileId: input.founderVoiceId } : {}
|
|
282
|
+
},
|
|
283
|
+
brand
|
|
284
|
+
);
|
|
285
|
+
const film = await this.#video.compose({
|
|
286
|
+
videoTrack: [rendered],
|
|
287
|
+
audioTrack: [bgm],
|
|
288
|
+
voiceTrack: [narration],
|
|
289
|
+
captionTrack: [{ startS: 0, endS: narration.durationS, text: narration.transcript }]
|
|
290
|
+
});
|
|
291
|
+
const landingPath = "company/landing/index.html";
|
|
292
|
+
await this.#contentStore.write(landingPath, renderLandingManifest(draft, brand));
|
|
293
|
+
await this.#debug({
|
|
294
|
+
type: "checkpoint",
|
|
295
|
+
step: CHECKPOINTS[4],
|
|
296
|
+
tenantId,
|
|
297
|
+
brandId: brand.brandId
|
|
298
|
+
});
|
|
299
|
+
const eventId = await this.#eventLog.commit({
|
|
300
|
+
traceId: assetId("brand_genesis", brand.brandId),
|
|
301
|
+
kind: "content_write",
|
|
302
|
+
affected: [
|
|
303
|
+
brand.sourcePath,
|
|
304
|
+
palettePath,
|
|
305
|
+
landingPath,
|
|
306
|
+
logo.path,
|
|
307
|
+
hero.path,
|
|
308
|
+
icon.path,
|
|
309
|
+
film.path
|
|
310
|
+
],
|
|
311
|
+
parent: null,
|
|
312
|
+
snapshot: {
|
|
313
|
+
[brand.sourcePath]: brandMarkdown,
|
|
314
|
+
[palettePath]: JSON.stringify({ brandId: brand.brandId, colors: brand.palette }, null, 2),
|
|
315
|
+
[landingPath]: renderLandingManifest(draft, brand)
|
|
316
|
+
}
|
|
317
|
+
});
|
|
318
|
+
const result = {
|
|
319
|
+
tenantId,
|
|
320
|
+
play: PLAY_NAME,
|
|
321
|
+
brand,
|
|
322
|
+
draft,
|
|
323
|
+
brandMdPath: brand.sourcePath,
|
|
324
|
+
palettePath,
|
|
325
|
+
landingPath,
|
|
326
|
+
logo,
|
|
327
|
+
hero,
|
|
328
|
+
icon,
|
|
329
|
+
mesh,
|
|
330
|
+
storyboard,
|
|
331
|
+
film,
|
|
332
|
+
bgm,
|
|
333
|
+
narration,
|
|
334
|
+
eventId,
|
|
335
|
+
checkpoints: CHECKPOINTS
|
|
336
|
+
};
|
|
337
|
+
await this.#debug({ type: "run", tenantId, brandId: brand.brandId, eventId });
|
|
338
|
+
return result;
|
|
339
|
+
}
|
|
340
|
+
async doctor() {
|
|
341
|
+
const [image, video, audio, rawVoice, mesh] = await Promise.all([
|
|
342
|
+
this.#image.doctor(),
|
|
343
|
+
this.#video.doctor(),
|
|
344
|
+
this.#audio.doctor(),
|
|
345
|
+
this.#voice.doctor(),
|
|
346
|
+
this.#mesh.doctor()
|
|
347
|
+
]);
|
|
348
|
+
const voice = [{ provider: "narration-local", ok: true }, ...rawVoice];
|
|
349
|
+
const localOk = [image, video, audio, voice, mesh].every(
|
|
350
|
+
(checks) => checks.some((check) => Boolean(check.ok))
|
|
351
|
+
);
|
|
352
|
+
return {
|
|
353
|
+
capability: "brand-genesis",
|
|
354
|
+
ok: localOk,
|
|
355
|
+
checkedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
356
|
+
play: {
|
|
357
|
+
ok: true,
|
|
358
|
+
name: PLAY_NAME,
|
|
359
|
+
requiredSkills: [
|
|
360
|
+
"image_pipeline.generate",
|
|
361
|
+
"video_pipeline.plan",
|
|
362
|
+
"video_pipeline.render",
|
|
363
|
+
"video_pipeline.compose",
|
|
364
|
+
"audio_pipeline.generate",
|
|
365
|
+
"voice_realtime.synthesize_narration",
|
|
366
|
+
"mesh_pipeline.from_image",
|
|
367
|
+
"content_store.write"
|
|
368
|
+
]
|
|
369
|
+
},
|
|
370
|
+
media: { image, video, audio, voice, mesh },
|
|
371
|
+
...!localOk ? {
|
|
372
|
+
suggestion: "Run the individual media doctor commands and configure missing local or remote providers."
|
|
373
|
+
} : {}
|
|
374
|
+
};
|
|
375
|
+
}
|
|
376
|
+
async close() {
|
|
377
|
+
await this.#contentStore.close();
|
|
378
|
+
}
|
|
379
|
+
async #debug(entry) {
|
|
380
|
+
await mkdir(dirname(join(this.#debugRoot, ".nebutra", "debug", "brand-genesis.jsonl")), {
|
|
381
|
+
recursive: true
|
|
382
|
+
});
|
|
383
|
+
await appendCapabilityDebug("brand-genesis", entry, { root: this.#debugRoot });
|
|
384
|
+
}
|
|
385
|
+
};
|
|
386
|
+
async function readBrandGenesisDebug(root = process.cwd(), limit = 20) {
|
|
387
|
+
return readCapabilityDebug("brand-genesis", { root, limit });
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
export {
|
|
391
|
+
distillBrandIdea,
|
|
392
|
+
brandContextFromDraft,
|
|
393
|
+
renderBrandMarkdown,
|
|
394
|
+
BrandGenesis,
|
|
395
|
+
readBrandGenesisDebug
|
|
396
|
+
};
|
|
397
|
+
//# sourceMappingURL=chunk-SB4N3ZZW.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { mkdir } from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\nimport { type MeshAsset, MeshPipeline } from \"@nebutra/3d-pipeline\";\nimport { type AudioAsset, AudioPipeline } from \"@nebutra/audio-pipeline\";\nimport { appendCapabilityDebug, readCapabilityDebug } from \"@nebutra/capability-kit/debug\";\nimport { ContentStore, serializeContentFrontmatter } from \"@nebutra/content-store\";\nimport { CapabilityError } from \"@nebutra/errors\";\nimport { EventLog } from \"@nebutra/event-log\";\nimport {\n assetId,\n type BrandColor,\n type BrandContext,\n type VisualStyle,\n} from \"@nebutra/generation-context\";\nimport { type ImageAsset, ImagePipeline } from \"@nebutra/image-pipeline\";\nimport { type Storyboard, type VideoAsset, VideoPipeline } from \"@nebutra/video-pipeline\";\nimport { type VoiceAsset, VoiceRealtime } from \"@nebutra/voice-realtime\";\n\nexport type VisualDirectionHint =\n | \"cyberpunk\"\n | \"minimal\"\n | \"organic\"\n | \"playful\"\n | \"corporate\"\n | \"retro\"\n | \"futurist\";\n\nexport interface BrandFilmInput {\n readonly tenantId?: string;\n readonly idea: string;\n readonly founderVoiceId?: string;\n readonly visualDirectionHint?: VisualDirectionHint;\n}\n\nexport interface BrandIdentityDraft {\n readonly name: string;\n readonly oneLiner: string;\n readonly tagline: string;\n readonly targetAudience: string;\n readonly toneKeywords: readonly string[];\n readonly differentiation: string;\n readonly visualStyle: VisualStyle;\n}\n\nexport interface BrandPackage {\n readonly tenantId: string;\n readonly play: \"brand_film_60s\";\n readonly brand: BrandContext;\n readonly draft: BrandIdentityDraft;\n readonly brandMdPath: string;\n readonly palettePath: string;\n readonly landingPath: string;\n readonly logo: ImageAsset;\n readonly hero: ImageAsset;\n readonly icon: ImageAsset;\n readonly mesh: MeshAsset;\n readonly storyboard: Storyboard;\n readonly film: VideoAsset;\n readonly bgm: AudioAsset;\n readonly narration: VoiceAsset;\n readonly eventId: string;\n readonly checkpoints: readonly string[];\n}\n\nexport interface BrandGenesisDoctorReport {\n readonly capability: \"brand-genesis\";\n readonly ok: boolean;\n readonly checkedAt: string;\n readonly play: {\n readonly ok: boolean;\n readonly name: \"brand_film_60s\";\n readonly requiredSkills: readonly string[];\n };\n readonly media: {\n readonly image: readonly unknown[];\n readonly video: readonly unknown[];\n readonly audio: readonly unknown[];\n readonly voice: readonly unknown[];\n readonly mesh: readonly unknown[];\n };\n readonly suggestion?: string;\n}\n\nexport interface BrandGenesisOptions {\n readonly tenantId?: string;\n readonly root?: string;\n readonly debugRoot?: string;\n readonly contentStore?: ContentStore;\n readonly eventLog?: EventLog;\n readonly imagePipeline?: ImagePipeline;\n readonly videoPipeline?: VideoPipeline;\n readonly audioPipeline?: AudioPipeline;\n readonly voiceRealtime?: VoiceRealtime;\n readonly meshPipeline?: MeshPipeline;\n}\n\nconst PLAY_NAME = \"brand_film_60s\" as const;\nconst CHECKPOINTS = [\n \"brand_distillation\",\n \"visual_direction\",\n \"assets_generated\",\n \"video_rendered\",\n \"final_compose\",\n] as const;\n\nfunction requireTenant(explicit: string | undefined, fallback: string | undefined): string {\n const tenantId = explicit ?? fallback;\n if (!tenantId?.trim()) {\n throw new CapabilityError(\"brand-genesis\", \"Brand Genesis requires tenant context\", {\n suggestion: \"Pass tenantId on the input or construct BrandGenesis with tenantId.\",\n statusCode: 400,\n });\n }\n return tenantId;\n}\n\nfunction normalizeBrandId(name: string): string {\n return name\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"_\")\n .replace(/^_+|_+$/g, \"\")\n .slice(0, 32);\n}\n\nfunction pickName(idea: string): string {\n const called = idea.match(/\\bcalled\\s+([A-Z][a-zA-Z0-9]*(?:\\s+[A-Z][a-zA-Z0-9]*)?)/);\n if (called?.[1]) return called[1].trim();\n const capitalized = [...idea.matchAll(/\\b[A-Z][a-zA-Z0-9]{2,}\\b/g)]\n .map((match) => match[0])\n .filter((value) => ![\"AI\", \"SaaS\", \"API\"].includes(value));\n return capitalized.at(-1) ?? \"Venture\";\n}\n\nfunction paletteFor(hint: VisualDirectionHint | undefined): readonly BrandColor[] {\n switch (hint) {\n case \"cyberpunk\":\n case \"futurist\":\n return [\n { name: \"electric cyan\", hex: \"#00D4FF\", role: \"primary\" },\n { name: \"carbon black\", hex: \"#111318\", role: \"background\" },\n { name: \"signal amber\", hex: \"#F3C14B\", role: \"accent\" },\n ];\n case \"organic\":\n return [\n { name: \"moss\", hex: \"#3D7A57\", role: \"primary\" },\n { name: \"paper\", hex: \"#F7F4EA\", role: \"background\" },\n { name: \"clay\", hex: \"#C86B4A\", role: \"accent\" },\n ];\n case \"playful\":\n return [\n { name: \"coral\", hex: \"#FF6B6B\", role: \"primary\" },\n { name: \"ink\", hex: \"#202124\", role: \"neutral\" },\n { name: \"mint\", hex: \"#7CE2C6\", role: \"accent\" },\n ];\n case \"corporate\":\n return [\n { name: \"trust blue\", hex: \"#2454D6\", role: \"primary\" },\n { name: \"slate\", hex: \"#202A36\", role: \"neutral\" },\n { name: \"clear sky\", hex: \"#E8F0FF\", role: \"background\" },\n ];\n case \"retro\":\n return [\n { name: \"oxide\", hex: \"#B95F3B\", role: \"primary\" },\n { name: \"night ink\", hex: \"#18202A\", role: \"neutral\" },\n { name: \"cream light\", hex: \"#F8E7C9\", role: \"background\" },\n ];\n default:\n return [\n { name: \"graphite\", hex: \"#1F2933\", role: \"primary\" },\n { name: \"white\", hex: \"#FFFFFF\", role: \"background\" },\n { name: \"signal green\", hex: \"#00A693\", role: \"accent\" },\n ];\n }\n}\n\nfunction styleFor(hint: VisualDirectionHint | undefined): VisualStyle {\n const name = hint ?? \"minimal\";\n const keywordsByHint: Record<VisualDirectionHint, readonly string[]> = {\n cyberpunk: [\"electric\", \"terminal-native\", \"high-contrast\"],\n minimal: [\"calm\", \"precise\", \"spacious\"],\n organic: [\"warm\", \"natural\", \"human\"],\n playful: [\"bright\", \"friendly\", \"kinetic\"],\n corporate: [\"credible\", \"structured\", \"clear\"],\n retro: [\"nostalgic\", \"tactile\", \"characterful\"],\n futurist: [\"clean\", \"technical\", \"forward\"],\n };\n return {\n name,\n keywords: keywordsByHint[name],\n avoid: [\"generic stock\", \"dark horror\", \"visual clutter\"],\n };\n}\n\nexport function distillBrandIdea(input: BrandFilmInput): BrandIdentityDraft {\n const idea = input.idea.trim();\n if (idea.length === 0) {\n throw new CapabilityError(\"brand-genesis\", \"Brand idea is empty\", {\n suggestion: \"Pass a one-sentence company idea before running Brand Genesis.\",\n statusCode: 400,\n });\n }\n const name = pickName(idea);\n const devAudience = /\\bdev|debug|code|developer|engineering/i.test(idea);\n const audience = devAudience\n ? \"Independent developers and small engineering teams shipping software quickly\"\n : \"Early-stage founders validating a focused product wedge\";\n const toneKeywords = devAudience\n ? [\"technical\", \"direct\", \"warm\"]\n : [\"clear\", \"confident\", \"useful\"];\n return {\n name,\n oneLiner: idea,\n tagline: devAudience ? \"Debug like it is a conversation\" : `${name} turns intent into launch`,\n targetAudience: audience,\n toneKeywords,\n differentiation: devAudience\n ? \"Understands the full production context instead of treating each error as an isolated message\"\n : \"Combines brand, execution, and company memory in one repeatable workflow\",\n visualStyle: styleFor(input.visualDirectionHint),\n };\n}\n\nexport function brandContextFromDraft(\n draft: BrandIdentityDraft,\n tenantId: string,\n sourcePath = \"company/BRAND.md\",\n palette = paletteFor(draft.visualStyle.name as VisualDirectionHint),\n): BrandContext {\n return {\n tenantId,\n brandId: normalizeBrandId(draft.name),\n name: draft.name,\n palette,\n typography: {\n heading: draft.visualStyle.name === \"cyberpunk\" ? \"Geist Mono\" : \"Geist Sans\",\n body: \"Geist Sans\",\n accent: \"Geist Mono\",\n },\n visualStyle: draft.visualStyle,\n referenceImages: [],\n forbidden: draft.visualStyle.avoid ?? [],\n toneKeywords: draft.toneKeywords,\n sourcePath,\n };\n}\n\nexport function renderBrandMarkdown(draft: BrandIdentityDraft, brand: BrandContext): string {\n return serializeContentFrontmatter(\n {\n type: \"brand_profile\",\n brand_id: brand.brandId,\n name: brand.name,\n },\n [\n `# ${brand.name}`,\n \"\",\n draft.oneLiner,\n \"\",\n \"## Tagline\",\n \"\",\n draft.tagline,\n \"\",\n \"## Audience\",\n \"\",\n draft.targetAudience,\n \"\",\n \"## Tone\",\n \"\",\n brand.toneKeywords.join(\", \"),\n \"\",\n \"## Visual Direction\",\n \"\",\n `${brand.visualStyle.name}: ${brand.visualStyle.keywords.join(\", \")}`,\n \"\",\n \"## Differentiation\",\n \"\",\n draft.differentiation,\n \"\",\n ].join(\"\\n\"),\n );\n}\n\nfunction renderLandingManifest(draft: BrandIdentityDraft, brand: BrandContext): string {\n return [\n \"<!doctype html>\",\n '<html lang=\"en\">',\n \"<head>\",\n ' <meta charset=\"utf-8\" />',\n ` <title>${brand.name}</title>`,\n \"</head>\",\n \"<body>\",\n ` <main data-brand-id=\"${brand.brandId}\">`,\n ` <h1>${brand.name}</h1>`,\n ` <p>${draft.tagline}</p>`,\n ` <p>${draft.oneLiner}</p>`,\n \" </main>\",\n \"</body>\",\n \"</html>\",\n \"\",\n ].join(\"\\n\");\n}\n\nexport class BrandGenesis {\n readonly #tenantId: string | undefined;\n readonly #root: string;\n readonly #debugRoot: string;\n readonly #contentStore: ContentStore;\n readonly #eventLog: EventLog;\n readonly #image: ImagePipeline;\n readonly #video: VideoPipeline;\n readonly #audio: AudioPipeline;\n readonly #voice: VoiceRealtime;\n readonly #mesh: MeshPipeline;\n\n private constructor(\n options: BrandGenesisOptions & { contentStore: ContentStore; eventLog: EventLog },\n ) {\n this.#tenantId = options.tenantId;\n this.#root = options.root ?? join(process.cwd(), \".nebutra\", \"brand-genesis\");\n this.#debugRoot = options.debugRoot ?? process.cwd();\n this.#contentStore = options.contentStore;\n this.#eventLog = options.eventLog;\n this.#image = options.imagePipeline ?? new ImagePipeline({ root: this.#root });\n this.#video = options.videoPipeline ?? new VideoPipeline({ root: this.#root });\n this.#audio = options.audioPipeline ?? new AudioPipeline({ root: this.#root });\n this.#voice = options.voiceRealtime ?? new VoiceRealtime({ root: this.#root });\n this.#mesh = options.meshPipeline ?? new MeshPipeline({ root: this.#root });\n }\n\n static async open(\n root = \".nebutra/brand-genesis\",\n options: Omit<BrandGenesisOptions, \"root\" | \"contentStore\" | \"eventLog\"> = {},\n ): Promise<BrandGenesis> {\n const tenantId = options.tenantId ?? \"local\";\n await mkdir(root, { recursive: true });\n const contentStore = await ContentStore.open(join(root, \"content\"), { tenantId });\n const eventLog = await EventLog.open(join(root, \"event-log\"), { tenantId });\n return new BrandGenesis({ ...options, tenantId, root, contentStore, eventLog });\n }\n\n async run(input: BrandFilmInput): Promise<BrandPackage> {\n const tenantId = requireTenant(input.tenantId, this.#tenantId);\n const draft = distillBrandIdea(input);\n const brand = brandContextFromDraft(draft, tenantId);\n const brandMarkdown = renderBrandMarkdown(draft, brand);\n await this.#contentStore.write(brand.sourcePath, brandMarkdown);\n const palettePath = \"company/assets/palette.json\";\n await this.#contentStore.write(\n palettePath,\n `${JSON.stringify({ brandId: brand.brandId, colors: brand.palette }, null, 2)}\\n`,\n );\n await this.#debug({\n type: \"checkpoint\",\n step: CHECKPOINTS[0],\n tenantId,\n brandId: brand.brandId,\n });\n await this.#debug({\n type: \"checkpoint\",\n step: CHECKPOINTS[1],\n tenantId,\n brandId: brand.brandId,\n });\n\n const [logo, hero, icon] = await Promise.all([\n this.#image.generate({ type: \"logo\", company: brand.name, oneLiner: draft.oneLiner }, brand),\n this.#image.generate({ type: \"hero\", headline: draft.tagline }, brand),\n this.#image.generate({ type: \"icon\", subject: brand.name }, brand),\n ]);\n const mesh = await this.#mesh.fromImage(logo, brand);\n await this.#debug({\n type: \"checkpoint\",\n step: CHECKPOINTS[2],\n tenantId,\n brandId: brand.brandId,\n });\n\n const storyboard = await this.#video.plan(\n { type: \"brand-film\", durationS: 60, theme: draft.tagline },\n brand,\n );\n const rendered = await this.#video.render(storyboard, brand);\n await this.#debug({\n type: \"checkpoint\",\n step: CHECKPOINTS[3],\n tenantId,\n brandId: brand.brandId,\n });\n\n const bgm = await this.#audio.generate(\n { type: \"bgm\", durationS: rendered.durationS, mood: brand.toneKeywords.join(\" \") },\n brand,\n true,\n );\n const narration = await this.#voice.synthesizeNarration(\n {\n script: `${draft.tagline}. ${draft.oneLiner}. ${draft.differentiation}.`,\n targetDurationS: Math.max(8, Math.min(20, rendered.durationS - 3)),\n ...(input.founderVoiceId !== undefined ? { voiceProfileId: input.founderVoiceId } : {}),\n },\n brand,\n );\n const film = await this.#video.compose({\n videoTrack: [rendered],\n audioTrack: [bgm],\n voiceTrack: [narration],\n captionTrack: [{ startS: 0, endS: narration.durationS, text: narration.transcript }],\n });\n const landingPath = \"company/landing/index.html\";\n await this.#contentStore.write(landingPath, renderLandingManifest(draft, brand));\n await this.#debug({\n type: \"checkpoint\",\n step: CHECKPOINTS[4],\n tenantId,\n brandId: brand.brandId,\n });\n\n const eventId = await this.#eventLog.commit({\n traceId: assetId(\"brand_genesis\", brand.brandId),\n kind: \"content_write\",\n affected: [\n brand.sourcePath,\n palettePath,\n landingPath,\n logo.path,\n hero.path,\n icon.path,\n film.path,\n ],\n parent: null,\n snapshot: {\n [brand.sourcePath]: brandMarkdown,\n [palettePath]: JSON.stringify({ brandId: brand.brandId, colors: brand.palette }, null, 2),\n [landingPath]: renderLandingManifest(draft, brand),\n },\n });\n\n const result: BrandPackage = {\n tenantId,\n play: PLAY_NAME,\n brand,\n draft,\n brandMdPath: brand.sourcePath,\n palettePath,\n landingPath,\n logo,\n hero,\n icon,\n mesh,\n storyboard,\n film,\n bgm,\n narration,\n eventId,\n checkpoints: CHECKPOINTS,\n };\n await this.#debug({ type: \"run\", tenantId, brandId: brand.brandId, eventId });\n return result;\n }\n\n async doctor(): Promise<BrandGenesisDoctorReport> {\n const [image, video, audio, rawVoice, mesh] = await Promise.all([\n this.#image.doctor(),\n this.#video.doctor(),\n this.#audio.doctor(),\n this.#voice.doctor(),\n this.#mesh.doctor(),\n ]);\n const voice = [{ provider: \"narration-local\", ok: true }, ...rawVoice];\n const localOk = [image, video, audio, voice, mesh].every((checks) =>\n checks.some((check) => Boolean((check as { ok?: boolean }).ok)),\n );\n return {\n capability: \"brand-genesis\",\n ok: localOk,\n checkedAt: new Date().toISOString(),\n play: {\n ok: true,\n name: PLAY_NAME,\n requiredSkills: [\n \"image_pipeline.generate\",\n \"video_pipeline.plan\",\n \"video_pipeline.render\",\n \"video_pipeline.compose\",\n \"audio_pipeline.generate\",\n \"voice_realtime.synthesize_narration\",\n \"mesh_pipeline.from_image\",\n \"content_store.write\",\n ],\n },\n media: { image, video, audio, voice, mesh },\n ...(!localOk\n ? {\n suggestion:\n \"Run the individual media doctor commands and configure missing local or remote providers.\",\n }\n : {}),\n };\n }\n\n async close(): Promise<void> {\n await this.#contentStore.close();\n }\n\n async #debug(entry: Record<string, unknown>): Promise<void> {\n await mkdir(dirname(join(this.#debugRoot, \".nebutra\", \"debug\", \"brand-genesis.jsonl\")), {\n recursive: true,\n });\n await appendCapabilityDebug(\"brand-genesis\", entry, { root: this.#debugRoot });\n }\n}\n\nexport async function readBrandGenesisDebug(root = process.cwd(), limit = 20): Promise<unknown[]> {\n return readCapabilityDebug(\"brand-genesis\", { root, limit });\n}\n"],"mappings":"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","names":[]}
|
package/dist/cli.d.ts
ADDED
package/dist/cli.js
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BrandGenesis,
|
|
3
|
+
readBrandGenesisDebug
|
|
4
|
+
} from "./chunk-SB4N3ZZW.js";
|
|
5
|
+
|
|
6
|
+
// src/cli.ts
|
|
7
|
+
import { mkdir, rm, stat } from "fs/promises";
|
|
8
|
+
import { join } from "path";
|
|
9
|
+
var command = process.argv[2] ?? "doctor";
|
|
10
|
+
var root = process.env.BRAND_GENESIS_ROOT ?? ".nebutra/brand-genesis";
|
|
11
|
+
var tenantId = process.env.NEBUTRA_TENANT_ID ?? "local";
|
|
12
|
+
async function sleep(ms) {
|
|
13
|
+
await new Promise((resolve) => setTimeout(resolve, ms));
|
|
14
|
+
}
|
|
15
|
+
async function acquireCliLock(rootPath) {
|
|
16
|
+
const lockPath = join(rootPath, ".cli.lock");
|
|
17
|
+
await mkdir(rootPath, { recursive: true });
|
|
18
|
+
for (let attempt = 0; attempt < 40; attempt += 1) {
|
|
19
|
+
try {
|
|
20
|
+
await mkdir(lockPath);
|
|
21
|
+
return async () => {
|
|
22
|
+
await rm(lockPath, { recursive: true, force: true });
|
|
23
|
+
};
|
|
24
|
+
} catch (error) {
|
|
25
|
+
const code = error.code;
|
|
26
|
+
if (code !== "EEXIST") throw error;
|
|
27
|
+
const lockStat = await stat(lockPath).catch(() => ({ mtimeMs: Date.now() }));
|
|
28
|
+
if (Date.now() - lockStat.mtimeMs > 3e4) {
|
|
29
|
+
await rm(lockPath, { recursive: true, force: true });
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
await sleep(50);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
throw new Error("brand-genesis CLI is busy. Suggestion: wait a moment and retry the command.");
|
|
36
|
+
}
|
|
37
|
+
if (command === "doctor") {
|
|
38
|
+
const releaseLock = await acquireCliLock(root);
|
|
39
|
+
const genesis = await BrandGenesis.open(root, { tenantId });
|
|
40
|
+
try {
|
|
41
|
+
process.stdout.write(`${JSON.stringify(await genesis.doctor(), null, 2)}
|
|
42
|
+
`);
|
|
43
|
+
} finally {
|
|
44
|
+
await genesis.close();
|
|
45
|
+
await releaseLock();
|
|
46
|
+
}
|
|
47
|
+
} else if (command === "quickstart") {
|
|
48
|
+
const idea = process.argv.slice(3).join(" ") || "AI debugging for indie devs called Loop";
|
|
49
|
+
const releaseLock = await acquireCliLock(root);
|
|
50
|
+
const genesis = await BrandGenesis.open(root, { tenantId });
|
|
51
|
+
try {
|
|
52
|
+
process.stdout.write(
|
|
53
|
+
`${JSON.stringify({ capability: "brand-genesis", result: await genesis.run({ idea }) }, null, 2)}
|
|
54
|
+
`
|
|
55
|
+
);
|
|
56
|
+
} finally {
|
|
57
|
+
await genesis.close();
|
|
58
|
+
await releaseLock();
|
|
59
|
+
}
|
|
60
|
+
} else if (command === "debug") {
|
|
61
|
+
process.stdout.write(
|
|
62
|
+
`${JSON.stringify({ capability: "brand-genesis", entries: await readBrandGenesisDebug() }, null, 2)}
|
|
63
|
+
`
|
|
64
|
+
);
|
|
65
|
+
} else {
|
|
66
|
+
process.stderr.write(`Unknown brand-genesis command: ${command}
|
|
67
|
+
`);
|
|
68
|
+
process.exitCode = 1;
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts"],"sourcesContent":["import { mkdir, rm, stat } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { BrandGenesis, readBrandGenesisDebug } from \"./index\";\n\nconst command = process.argv[2] ?? \"doctor\";\nconst root = process.env.BRAND_GENESIS_ROOT ?? \".nebutra/brand-genesis\";\nconst tenantId = process.env.NEBUTRA_TENANT_ID ?? \"local\";\n\nasync function sleep(ms: number): Promise<void> {\n await new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nasync function acquireCliLock(rootPath: string): Promise<() => Promise<void>> {\n const lockPath = join(rootPath, \".cli.lock\");\n await mkdir(rootPath, { recursive: true });\n for (let attempt = 0; attempt < 40; attempt += 1) {\n try {\n await mkdir(lockPath);\n return async () => {\n await rm(lockPath, { recursive: true, force: true });\n };\n } catch (error) {\n const code = (error as NodeJS.ErrnoException).code;\n if (code !== \"EEXIST\") throw error;\n const lockStat = await stat(lockPath).catch(() => ({ mtimeMs: Date.now() }));\n if (Date.now() - lockStat.mtimeMs > 30_000) {\n await rm(lockPath, { recursive: true, force: true });\n continue;\n }\n await sleep(50);\n }\n }\n throw new Error(\"brand-genesis CLI is busy. Suggestion: wait a moment and retry the command.\");\n}\n\nif (command === \"doctor\") {\n const releaseLock = await acquireCliLock(root);\n const genesis = await BrandGenesis.open(root, { tenantId });\n try {\n process.stdout.write(`${JSON.stringify(await genesis.doctor(), null, 2)}\\n`);\n } finally {\n await genesis.close();\n await releaseLock();\n }\n} else if (command === \"quickstart\") {\n const idea = process.argv.slice(3).join(\" \") || \"AI debugging for indie devs called Loop\";\n const releaseLock = await acquireCliLock(root);\n const genesis = await BrandGenesis.open(root, { tenantId });\n try {\n process.stdout.write(\n `${JSON.stringify({ capability: \"brand-genesis\", result: await genesis.run({ idea }) }, null, 2)}\\n`,\n );\n } finally {\n await genesis.close();\n await releaseLock();\n }\n} else if (command === \"debug\") {\n process.stdout.write(\n `${JSON.stringify({ capability: \"brand-genesis\", entries: await readBrandGenesisDebug() }, null, 2)}\\n`,\n );\n} else {\n process.stderr.write(`Unknown brand-genesis command: ${command}\\n`);\n process.exitCode = 1;\n}\n"],"mappings":";;;;;;AAAA,SAAS,OAAO,IAAI,YAAY;AAChC,SAAS,YAAY;AAGrB,IAAM,UAAU,QAAQ,KAAK,CAAC,KAAK;AACnC,IAAM,OAAO,QAAQ,IAAI,sBAAsB;AAC/C,IAAM,WAAW,QAAQ,IAAI,qBAAqB;AAElD,eAAe,MAAM,IAA2B;AAC9C,QAAM,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,EAAE,CAAC;AACxD;AAEA,eAAe,eAAe,UAAgD;AAC5E,QAAM,WAAW,KAAK,UAAU,WAAW;AAC3C,QAAM,MAAM,UAAU,EAAE,WAAW,KAAK,CAAC;AACzC,WAAS,UAAU,GAAG,UAAU,IAAI,WAAW,GAAG;AAChD,QAAI;AACF,YAAM,MAAM,QAAQ;AACpB,aAAO,YAAY;AACjB,cAAM,GAAG,UAAU,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAAA,MACrD;AAAA,IACF,SAAS,OAAO;AACd,YAAM,OAAQ,MAAgC;AAC9C,UAAI,SAAS,SAAU,OAAM;AAC7B,YAAM,WAAW,MAAM,KAAK,QAAQ,EAAE,MAAM,OAAO,EAAE,SAAS,KAAK,IAAI,EAAE,EAAE;AAC3E,UAAI,KAAK,IAAI,IAAI,SAAS,UAAU,KAAQ;AAC1C,cAAM,GAAG,UAAU,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AACnD;AAAA,MACF;AACA,YAAM,MAAM,EAAE;AAAA,IAChB;AAAA,EACF;AACA,QAAM,IAAI,MAAM,6EAA6E;AAC/F;AAEA,IAAI,YAAY,UAAU;AACxB,QAAM,cAAc,MAAM,eAAe,IAAI;AAC7C,QAAM,UAAU,MAAM,aAAa,KAAK,MAAM,EAAE,SAAS,CAAC;AAC1D,MAAI;AACF,YAAQ,OAAO,MAAM,GAAG,KAAK,UAAU,MAAM,QAAQ,OAAO,GAAG,MAAM,CAAC,CAAC;AAAA,CAAI;AAAA,EAC7E,UAAE;AACA,UAAM,QAAQ,MAAM;AACpB,UAAM,YAAY;AAAA,EACpB;AACF,WAAW,YAAY,cAAc;AACnC,QAAM,OAAO,QAAQ,KAAK,MAAM,CAAC,EAAE,KAAK,GAAG,KAAK;AAChD,QAAM,cAAc,MAAM,eAAe,IAAI;AAC7C,QAAM,UAAU,MAAM,aAAa,KAAK,MAAM,EAAE,SAAS,CAAC;AAC1D,MAAI;AACF,YAAQ,OAAO;AAAA,MACb,GAAG,KAAK,UAAU,EAAE,YAAY,iBAAiB,QAAQ,MAAM,QAAQ,IAAI,EAAE,KAAK,CAAC,EAAE,GAAG,MAAM,CAAC,CAAC;AAAA;AAAA,IAClG;AAAA,EACF,UAAE;AACA,UAAM,QAAQ,MAAM;AACpB,UAAM,YAAY;AAAA,EACpB;AACF,WAAW,YAAY,SAAS;AAC9B,UAAQ,OAAO;AAAA,IACb,GAAG,KAAK,UAAU,EAAE,YAAY,iBAAiB,SAAS,MAAM,sBAAsB,EAAE,GAAG,MAAM,CAAC,CAAC;AAAA;AAAA,EACrG;AACF,OAAO;AACL,UAAQ,OAAO,MAAM,kCAAkC,OAAO;AAAA,CAAI;AAClE,UAAQ,WAAW;AACrB;","names":[]}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { MeshPipeline, MeshAsset } from '@nebutra/3d-pipeline';
|
|
2
|
+
import { AudioPipeline, AudioAsset } from '@nebutra/audio-pipeline';
|
|
3
|
+
import { ContentStore } from '@nebutra/content-store';
|
|
4
|
+
import { EventLog } from '@nebutra/event-log';
|
|
5
|
+
import { BrandContext, VisualStyle, BrandColor } from '@nebutra/generation-context';
|
|
6
|
+
import { ImagePipeline, ImageAsset } from '@nebutra/image-pipeline';
|
|
7
|
+
import { VideoPipeline, Storyboard, VideoAsset } from '@nebutra/video-pipeline';
|
|
8
|
+
import { VoiceRealtime, VoiceAsset } from '@nebutra/voice-realtime';
|
|
9
|
+
|
|
10
|
+
type VisualDirectionHint = "cyberpunk" | "minimal" | "organic" | "playful" | "corporate" | "retro" | "futurist";
|
|
11
|
+
interface BrandFilmInput {
|
|
12
|
+
readonly tenantId?: string;
|
|
13
|
+
readonly idea: string;
|
|
14
|
+
readonly founderVoiceId?: string;
|
|
15
|
+
readonly visualDirectionHint?: VisualDirectionHint;
|
|
16
|
+
}
|
|
17
|
+
interface BrandIdentityDraft {
|
|
18
|
+
readonly name: string;
|
|
19
|
+
readonly oneLiner: string;
|
|
20
|
+
readonly tagline: string;
|
|
21
|
+
readonly targetAudience: string;
|
|
22
|
+
readonly toneKeywords: readonly string[];
|
|
23
|
+
readonly differentiation: string;
|
|
24
|
+
readonly visualStyle: VisualStyle;
|
|
25
|
+
}
|
|
26
|
+
interface BrandPackage {
|
|
27
|
+
readonly tenantId: string;
|
|
28
|
+
readonly play: "brand_film_60s";
|
|
29
|
+
readonly brand: BrandContext;
|
|
30
|
+
readonly draft: BrandIdentityDraft;
|
|
31
|
+
readonly brandMdPath: string;
|
|
32
|
+
readonly palettePath: string;
|
|
33
|
+
readonly landingPath: string;
|
|
34
|
+
readonly logo: ImageAsset;
|
|
35
|
+
readonly hero: ImageAsset;
|
|
36
|
+
readonly icon: ImageAsset;
|
|
37
|
+
readonly mesh: MeshAsset;
|
|
38
|
+
readonly storyboard: Storyboard;
|
|
39
|
+
readonly film: VideoAsset;
|
|
40
|
+
readonly bgm: AudioAsset;
|
|
41
|
+
readonly narration: VoiceAsset;
|
|
42
|
+
readonly eventId: string;
|
|
43
|
+
readonly checkpoints: readonly string[];
|
|
44
|
+
}
|
|
45
|
+
interface BrandGenesisDoctorReport {
|
|
46
|
+
readonly capability: "brand-genesis";
|
|
47
|
+
readonly ok: boolean;
|
|
48
|
+
readonly checkedAt: string;
|
|
49
|
+
readonly play: {
|
|
50
|
+
readonly ok: boolean;
|
|
51
|
+
readonly name: "brand_film_60s";
|
|
52
|
+
readonly requiredSkills: readonly string[];
|
|
53
|
+
};
|
|
54
|
+
readonly media: {
|
|
55
|
+
readonly image: readonly unknown[];
|
|
56
|
+
readonly video: readonly unknown[];
|
|
57
|
+
readonly audio: readonly unknown[];
|
|
58
|
+
readonly voice: readonly unknown[];
|
|
59
|
+
readonly mesh: readonly unknown[];
|
|
60
|
+
};
|
|
61
|
+
readonly suggestion?: string;
|
|
62
|
+
}
|
|
63
|
+
interface BrandGenesisOptions {
|
|
64
|
+
readonly tenantId?: string;
|
|
65
|
+
readonly root?: string;
|
|
66
|
+
readonly debugRoot?: string;
|
|
67
|
+
readonly contentStore?: ContentStore;
|
|
68
|
+
readonly eventLog?: EventLog;
|
|
69
|
+
readonly imagePipeline?: ImagePipeline;
|
|
70
|
+
readonly videoPipeline?: VideoPipeline;
|
|
71
|
+
readonly audioPipeline?: AudioPipeline;
|
|
72
|
+
readonly voiceRealtime?: VoiceRealtime;
|
|
73
|
+
readonly meshPipeline?: MeshPipeline;
|
|
74
|
+
}
|
|
75
|
+
declare function distillBrandIdea(input: BrandFilmInput): BrandIdentityDraft;
|
|
76
|
+
declare function brandContextFromDraft(draft: BrandIdentityDraft, tenantId: string, sourcePath?: string, palette?: readonly BrandColor[]): BrandContext;
|
|
77
|
+
declare function renderBrandMarkdown(draft: BrandIdentityDraft, brand: BrandContext): string;
|
|
78
|
+
declare class BrandGenesis {
|
|
79
|
+
#private;
|
|
80
|
+
private constructor();
|
|
81
|
+
static open(root?: string, options?: Omit<BrandGenesisOptions, "root" | "contentStore" | "eventLog">): Promise<BrandGenesis>;
|
|
82
|
+
run(input: BrandFilmInput): Promise<BrandPackage>;
|
|
83
|
+
doctor(): Promise<BrandGenesisDoctorReport>;
|
|
84
|
+
close(): Promise<void>;
|
|
85
|
+
}
|
|
86
|
+
declare function readBrandGenesisDebug(root?: string, limit?: number): Promise<unknown[]>;
|
|
87
|
+
|
|
88
|
+
export { type BrandFilmInput, BrandGenesis, type BrandGenesisDoctorReport, type BrandGenesisOptions, type BrandIdentityDraft, type BrandPackage, type VisualDirectionHint, brandContextFromDraft, distillBrandIdea, readBrandGenesisDebug, renderBrandMarkdown };
|