vidspotai-shared 1.0.95 → 1.0.97
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/lib/globals/aiModels/enums.d.ts +3 -0
- package/lib/globals/aiModels/enums.d.ts.map +1 -1
- package/lib/globals/aiModels/enums.js +9 -0
- package/lib/globals/aiModels/index.d.ts.map +1 -1
- package/lib/globals/aiModels/index.js +2 -0
- package/lib/globals/aiModels/providers/hostedAvatars.d.ts +22 -0
- package/lib/globals/aiModels/providers/hostedAvatars.d.ts.map +1 -0
- package/lib/globals/aiModels/providers/hostedAvatars.js +129 -0
- package/lib/globals/aiModels/providers/kling.d.ts.map +1 -1
- package/lib/globals/aiModels/providers/kling.js +85 -1
- package/lib/globals/creditUnit.d.ts +29 -0
- package/lib/globals/creditUnit.d.ts.map +1 -1
- package/lib/globals/creditUnit.js +30 -1
- package/lib/globals/types.d.ts +58 -1
- package/lib/globals/types.d.ts.map +1 -1
- package/lib/globals/types.js +61 -1
- package/lib/models/demoVideoProject.model.d.ts +244 -0
- package/lib/models/demoVideoProject.model.d.ts.map +1 -0
- package/lib/models/demoVideoProject.model.js +2 -0
- package/lib/models/githubConnection.model.d.ts +35 -0
- package/lib/models/githubConnection.model.d.ts.map +1 -0
- package/lib/models/githubConnection.model.js +2 -0
- package/lib/models/index.d.ts +3 -0
- package/lib/models/index.d.ts.map +1 -1
- package/lib/models/index.js +3 -0
- package/lib/models/outreach.model.d.ts +175 -0
- package/lib/models/outreach.model.d.ts.map +1 -0
- package/lib/models/outreach.model.js +2 -0
- package/lib/models/video.model.d.ts +4 -0
- package/lib/models/video.model.d.ts.map +1 -1
- package/lib/schemas/brandKit.schema.d.ts +4 -0
- package/lib/schemas/brandKit.schema.d.ts.map +1 -1
- package/lib/schemas/brandKit.schema.js +10 -0
- package/lib/schemas/demoQuestion.schema.d.ts +286 -0
- package/lib/schemas/demoQuestion.schema.d.ts.map +1 -0
- package/lib/schemas/demoQuestion.schema.js +210 -0
- package/lib/schemas/demoSpec.schema.d.ts +109 -6
- package/lib/schemas/demoSpec.schema.d.ts.map +1 -1
- package/lib/schemas/demoSpec.schema.js +95 -7
- package/lib/schemas/index.d.ts +1 -0
- package/lib/schemas/index.d.ts.map +1 -1
- package/lib/schemas/index.js +1 -0
- package/lib/services/agent/providerFallback/chains.d.ts.map +1 -1
- package/lib/services/agent/providerFallback/chains.js +9 -1
- package/lib/services/agent/taskPoller.d.ts.map +1 -1
- package/lib/services/agent/taskPoller.js +17 -6
- package/lib/services/agent/tools/generateAvatarVideo.tool.d.ts +21 -9
- package/lib/services/agent/tools/generateAvatarVideo.tool.d.ts.map +1 -1
- package/lib/services/agent/tools/generateAvatarVideo.tool.js +135 -39
- package/lib/services/aiGen/aiGenFactory.service.d.ts +1 -1
- package/lib/services/aiGen/aiGenFactory.service.d.ts.map +1 -1
- package/lib/services/aiGen/aiGenFactory.service.js +11 -2
- package/lib/services/aiGen/providers/kling/kling.service.d.ts +36 -1
- package/lib/services/aiGen/providers/kling/kling.service.d.ts.map +1 -1
- package/lib/services/aiGen/providers/kling/kling.service.js +62 -5
- package/lib/services/aiGen/providers/kling/klingCredits.d.ts.map +1 -1
- package/lib/services/aiGen/providers/kling/klingCredits.js +12 -0
- package/lib/services/aiGen/providers/kling/klingRequests.d.ts +14 -1
- package/lib/services/aiGen/providers/kling/klingRequests.d.ts.map +1 -1
- package/lib/services/aiGen/providers/kling/klingRequests.js +44 -0
- package/lib/services/aiGen/providers/kling/klingStatus.d.ts +13 -1
- package/lib/services/aiGen/providers/kling/klingStatus.d.ts.map +1 -1
- package/lib/services/aiGen/providers/kling/klingStatus.js +111 -0
- package/lib/services/aiGen/providers/kling/types.d.ts +71 -0
- package/lib/services/aiGen/providers/kling/types.d.ts.map +1 -1
- package/lib/services/avatarGen/IAvatarVideoProvider.d.ts +136 -0
- package/lib/services/avatarGen/IAvatarVideoProvider.d.ts.map +1 -0
- package/lib/services/avatarGen/IAvatarVideoProvider.js +42 -0
- package/lib/services/avatarGen/avatarProviderFactory.d.ts +18 -0
- package/lib/services/avatarGen/avatarProviderFactory.d.ts.map +1 -0
- package/lib/services/avatarGen/avatarProviderFactory.js +54 -0
- package/lib/services/avatarGen/index.d.ts +6 -0
- package/lib/services/avatarGen/index.d.ts.map +1 -0
- package/lib/services/avatarGen/index.js +21 -0
- package/lib/services/avatarGen/providers/heygenAvatarProvider.d.ts +45 -0
- package/lib/services/avatarGen/providers/heygenAvatarProvider.d.ts.map +1 -0
- package/lib/services/avatarGen/providers/heygenAvatarProvider.js +190 -0
- package/lib/services/avatarGen/providers/klingAvatarProvider.d.ts +32 -0
- package/lib/services/avatarGen/providers/klingAvatarProvider.d.ts.map +1 -0
- package/lib/services/avatarGen/providers/klingAvatarProvider.js +69 -0
- package/lib/services/avatarGen/providers/tavusAvatarProvider.d.ts +56 -0
- package/lib/services/avatarGen/providers/tavusAvatarProvider.d.ts.map +1 -0
- package/lib/services/avatarGen/providers/tavusAvatarProvider.js +183 -0
- package/lib/services/demo/demoAuthor.d.ts +45 -0
- package/lib/services/demo/demoAuthor.d.ts.map +1 -0
- package/lib/services/demo/demoAuthor.js +75 -0
- package/lib/services/demo/demoAuthorNormalize.d.ts +49 -0
- package/lib/services/demo/demoAuthorNormalize.d.ts.map +1 -0
- package/lib/services/demo/demoAuthorNormalize.js +327 -0
- package/lib/services/demo/demoAuthorPrompt.d.ts +102 -0
- package/lib/services/demo/demoAuthorPrompt.d.ts.map +1 -0
- package/lib/services/demo/demoAuthorPrompt.js +243 -0
- package/lib/services/demo/demoCredits.d.ts +20 -0
- package/lib/services/demo/demoCredits.d.ts.map +1 -0
- package/lib/services/demo/demoCredits.js +51 -0
- package/lib/services/demo/demoMediaGuard.d.ts +43 -0
- package/lib/services/demo/demoMediaGuard.d.ts.map +1 -0
- package/lib/services/demo/demoMediaGuard.js +207 -0
- package/lib/services/demo/demoMusic.d.ts +13 -0
- package/lib/services/demo/demoMusic.d.ts.map +1 -0
- package/lib/services/demo/demoMusic.js +93 -0
- package/lib/services/demo/demoPrefill.d.ts +76 -0
- package/lib/services/demo/demoPrefill.d.ts.map +1 -0
- package/lib/services/demo/demoPrefill.js +435 -0
- package/lib/services/demo/demoRevisePrompt.d.ts +17 -0
- package/lib/services/demo/demoRevisePrompt.d.ts.map +1 -0
- package/lib/services/demo/demoRevisePrompt.js +85 -0
- package/lib/services/demo/demoReviser.d.ts +63 -0
- package/lib/services/demo/demoReviser.d.ts.map +1 -0
- package/lib/services/demo/demoReviser.js +81 -0
- package/lib/services/demo/demoScriptPrompt.d.ts +63 -0
- package/lib/services/demo/demoScriptPrompt.d.ts.map +1 -0
- package/lib/services/demo/demoScriptPrompt.js +234 -0
- package/lib/services/demo/demoScriptWriter.d.ts +65 -0
- package/lib/services/demo/demoScriptWriter.d.ts.map +1 -0
- package/lib/services/demo/demoScriptWriter.js +211 -0
- package/lib/services/demo/demoTriage.d.ts +65 -0
- package/lib/services/demo/demoTriage.d.ts.map +1 -0
- package/lib/services/demo/demoTriage.js +130 -0
- package/lib/services/demo/githubOAuth.d.ts +78 -0
- package/lib/services/demo/githubOAuth.d.ts.map +1 -0
- package/lib/services/demo/githubOAuth.js +209 -0
- package/lib/services/demo/githubOAuthState.d.ts +10 -0
- package/lib/services/demo/githubOAuthState.d.ts.map +1 -0
- package/lib/services/demo/githubOAuthState.js +63 -0
- package/lib/services/demo/index.d.ts +24 -0
- package/lib/services/demo/index.d.ts.map +1 -0
- package/lib/services/demo/index.js +39 -0
- package/lib/services/firestore.service.d.ts +11 -0
- package/lib/services/firestore.service.d.ts.map +1 -1
- package/lib/services/firestore.service.js +24 -0
- package/lib/services/index.d.ts +2 -0
- package/lib/services/index.d.ts.map +1 -1
- package/lib/services/index.js +2 -0
- package/lib/services/tts/providers/elevenlabs.service.d.ts.map +1 -1
- package/lib/services/tts/providers/elevenlabs.service.js +16 -8
- package/lib/utils/index.d.ts +1 -0
- package/lib/utils/index.d.ts.map +1 -1
- package/lib/utils/index.js +1 -0
- package/lib/utils/outreachTemplate.d.ts +46 -0
- package/lib/utils/outreachTemplate.d.ts.map +1 -0
- package/lib/utils/outreachTemplate.js +174 -0
- package/package.json +1 -1
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.authorDemoSpec = authorDemoSpec;
|
|
4
|
+
const demoSpec_schema_1 = require("../../schemas/demoSpec.schema");
|
|
5
|
+
const llmCallerRegistry_1 = require("../agent/llmCallerRegistry");
|
|
6
|
+
const modelRouter_1 = require("../agent/modelRouter");
|
|
7
|
+
const demoAuthorPrompt_1 = require("./demoAuthorPrompt");
|
|
8
|
+
const demoAuthorNormalize_1 = require("./demoAuthorNormalize");
|
|
9
|
+
/**
|
|
10
|
+
* DemoSpec author — the "plan" stage of the SaaS Demo Video pipeline (plan
|
|
11
|
+
* Phase 3 / §4 stage 2).
|
|
12
|
+
*
|
|
13
|
+
* ONE Claude `.structured<DemoSpec>()` call turns the user's product facts +
|
|
14
|
+
* brand tokens + product screenshots (as vision) + wizard answers into a valid,
|
|
15
|
+
* render-ready DemoSpec that the Layer-A engine renders to MP4. This is the
|
|
16
|
+
* equivalent of the agent Planner (`bibleBuilder`/`planner`) but for the demo
|
|
17
|
+
* generator: provider-agnostic (injected `LlmCaller`), model-routed, and
|
|
18
|
+
* hardened by a deterministic normalize pass (see demoAuthorNormalize.ts) that
|
|
19
|
+
* enforces the invariants a prompt can only request.
|
|
20
|
+
*
|
|
21
|
+
* The orchestration worker (Phase 4) calls `authorDemoSpec` at the plan stage;
|
|
22
|
+
* the returned `spec` is persisted on `demoVideoProjects.demoSpec` and rendered.
|
|
23
|
+
*/
|
|
24
|
+
/** Cap screenshots sent as vision (and thus citable) to bound token cost (plan §10). */
|
|
25
|
+
const MAX_VISION_SCREENSHOTS = 6;
|
|
26
|
+
/**
|
|
27
|
+
* Author a render-ready DemoSpec from inputs. Pure orchestration: build the
|
|
28
|
+
* prompt, attach screenshots as vision, call `.structured(DemoSpec)`, then
|
|
29
|
+
* normalize. Throws if the caller is unconfigured or the model returns an
|
|
30
|
+
* unparseable / scene-less spec (the normalize pass is the last guard).
|
|
31
|
+
*/
|
|
32
|
+
async function authorDemoSpec(input, deps = {}) {
|
|
33
|
+
const llm = deps.llm ?? (0, llmCallerRegistry_1.getLlmCaller)();
|
|
34
|
+
const router = deps.router ?? new modelRouter_1.ModelRouter();
|
|
35
|
+
const model = router.pickFor("planner", { premium: deps.premium });
|
|
36
|
+
const fallbackModel = router.fallbackFor("planner");
|
|
37
|
+
// Cap the screenshot set BEFORE prompting so the citable list matches exactly
|
|
38
|
+
// what the model can see (never advertise a URL we didn't attach as vision).
|
|
39
|
+
const visionScreenshots = (input.screenshotUrls ?? []).slice(0, MAX_VISION_SCREENSHOTS);
|
|
40
|
+
const cappedInput = {
|
|
41
|
+
...input,
|
|
42
|
+
screenshotUrls: visionScreenshots.length ? visionScreenshots : undefined,
|
|
43
|
+
};
|
|
44
|
+
const system = (0, demoAuthorPrompt_1.buildDemoAuthorSystemPrompt)({
|
|
45
|
+
allowCustomScenes: deps.allowCustomScenes,
|
|
46
|
+
allowGeneratedAssets: deps.allowGeneratedAssets,
|
|
47
|
+
});
|
|
48
|
+
const userText = (0, demoAuthorPrompt_1.buildDemoAuthorUserText)(cappedInput);
|
|
49
|
+
const result = await llm.structured({
|
|
50
|
+
model,
|
|
51
|
+
fallbackModel,
|
|
52
|
+
messages: [
|
|
53
|
+
{ role: "system", content: system },
|
|
54
|
+
{
|
|
55
|
+
role: "user",
|
|
56
|
+
content: userText,
|
|
57
|
+
imageUrls: visionScreenshots.length ? visionScreenshots : undefined,
|
|
58
|
+
},
|
|
59
|
+
],
|
|
60
|
+
schema: demoSpec_schema_1.DemoSpecSchema,
|
|
61
|
+
schemaName: "DemoSpec",
|
|
62
|
+
temperature: deps.temperature ?? 0.5,
|
|
63
|
+
maxTokens: deps.maxTokens ?? 8000,
|
|
64
|
+
});
|
|
65
|
+
// The caller already validated against DemoSpecSchema; parse again defensively
|
|
66
|
+
// to get a concrete typed value before the deterministic normalize pass.
|
|
67
|
+
const raw = demoSpec_schema_1.DemoSpecSchema.parse(result.data);
|
|
68
|
+
const normalized = (0, demoAuthorNormalize_1.normalizeDemoSpec)(raw, cappedInput);
|
|
69
|
+
return {
|
|
70
|
+
...normalized,
|
|
71
|
+
modelUsed: result.usedFallback && fallbackModel ? fallbackModel : model,
|
|
72
|
+
usedFallback: result.usedFallback,
|
|
73
|
+
usage: result.usage,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { DemoScene, DemoSpec } from "../../schemas/demoSpec.schema";
|
|
2
|
+
import { DemoAuthorInput } from "./demoAuthorPrompt";
|
|
3
|
+
/**
|
|
4
|
+
* Deterministic post-processing for the authored DemoSpec (plan Phase 3).
|
|
5
|
+
*
|
|
6
|
+
* The prompt REQUESTS these invariants; this pass GUARANTEES them, because an
|
|
7
|
+
* LLM can (and occasionally will) drift on exactly the things that break a
|
|
8
|
+
* render or the brand:
|
|
9
|
+
* 1. Wizard pins — any axis the user explicitly locked wins over the model's pick.
|
|
10
|
+
* 2. Screenshot URLs — the model may only cite real uploaded URLs; anything else
|
|
11
|
+
* is stripped (and screenshot-only scenes with no valid URL are dropped).
|
|
12
|
+
* 3. Brand colors — forced back to the user's tokens (copy is the model's, palette isn't).
|
|
13
|
+
* 4. Duration budget — total timeline scaled to land inside the target window.
|
|
14
|
+
* 5. Structural — >=1 scene, correct productName, schema-valid (defaults applied).
|
|
15
|
+
*
|
|
16
|
+
* Everything here is pure + typed (no `any`), so it's unit-testable without an LLM.
|
|
17
|
+
*/
|
|
18
|
+
export interface NormalizeResult {
|
|
19
|
+
spec: DemoSpec;
|
|
20
|
+
/** Human-readable notes on what the normalize pass changed (for logs/observability). */
|
|
21
|
+
adjustments: string[];
|
|
22
|
+
}
|
|
23
|
+
/** Hard caps on planner-requested AI media per spec (cost + wall-clock bound). */
|
|
24
|
+
export declare const DEMO_GEN_ASSET_MAX_IMAGES = 4;
|
|
25
|
+
export declare const DEMO_GEN_ASSET_MAX_VIDEOS = 1;
|
|
26
|
+
/** Is this URL-slot value a reference to a declared generated asset? */
|
|
27
|
+
export declare function isGenAssetRef(url: string | undefined): url is string;
|
|
28
|
+
/** `gen://hero-shot` → `hero-shot` (undefined when not a gen ref). */
|
|
29
|
+
export declare function genAssetIdFromRef(url: string): string;
|
|
30
|
+
export interface GenAssetCitations {
|
|
31
|
+
/** Asset ids cited via `gen://<id>`. */
|
|
32
|
+
ids: Set<string>;
|
|
33
|
+
/** Raw string values cited in media slots — lets a READY asset that scenes
|
|
34
|
+
* now cite by its resolved URL still count as referenced. */
|
|
35
|
+
urls: Set<string>;
|
|
36
|
+
}
|
|
37
|
+
/** Every `gen://` ref AND every raw media string cited anywhere in a scene list
|
|
38
|
+
* (typed media slots + custom-scene prop bags, walked deeply so codegen props
|
|
39
|
+
* count as usage). */
|
|
40
|
+
export declare function collectGenAssetRefs(scenes: DemoScene[]): GenAssetCitations;
|
|
41
|
+
/**
|
|
42
|
+
* Run the full deterministic normalize pipeline on a raw authored spec and
|
|
43
|
+
* return a schema-valid, render-ready DemoSpec plus the list of adjustments.
|
|
44
|
+
* Throws only if the model produced something with zero scenes (unrecoverable).
|
|
45
|
+
*/
|
|
46
|
+
export declare function normalizeDemoSpec(raw: DemoSpec, input: DemoAuthorInput): NormalizeResult;
|
|
47
|
+
/** Convenience — total timeline of a normalized spec (ms). */
|
|
48
|
+
export declare function specTotalMs(spec: DemoSpec): number;
|
|
49
|
+
//# sourceMappingURL=demoAuthorNormalize.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"demoAuthorNormalize.d.ts","sourceRoot":"","sources":["../../../src/services/demo/demoAuthorNormalize.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,SAAS,EACT,QAAQ,EAIT,MAAM,+BAA+B,CAAC;AAEvC,OAAO,EAAE,eAAe,EAAmC,MAAM,oBAAoB,CAAC;AAEtF;;;;;;;;;;;;;;GAcG;AAEH,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,QAAQ,CAAC;IACf,wFAAwF;IACxF,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AA6CD,kFAAkF;AAClF,eAAO,MAAM,yBAAyB,IAAI,CAAC;AAC3C,eAAO,MAAM,yBAAyB,IAAI,CAAC;AAE3C,wEAAwE;AACxE,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,GAAG,IAAI,MAAM,CAEpE;AAED,sEAAsE;AACtE,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAErD;AAED,MAAM,WAAW,iBAAiB;IAChC,wCAAwC;IACxC,GAAG,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACjB;kEAC8D;IAC9D,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CACnB;AAED;;uBAEuB;AACvB,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,iBAAiB,CA2C1E;AA0MD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,eAAe,GAAG,eAAe,CAsExF;AAED,8DAA8D;AAC9D,wBAAgB,WAAW,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,CAElD"}
|
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DEMO_GEN_ASSET_MAX_VIDEOS = exports.DEMO_GEN_ASSET_MAX_IMAGES = void 0;
|
|
4
|
+
exports.isGenAssetRef = isGenAssetRef;
|
|
5
|
+
exports.genAssetIdFromRef = genAssetIdFromRef;
|
|
6
|
+
exports.collectGenAssetRefs = collectGenAssetRefs;
|
|
7
|
+
exports.normalizeDemoSpec = normalizeDemoSpec;
|
|
8
|
+
exports.specTotalMs = specTotalMs;
|
|
9
|
+
const demoSpec_schema_1 = require("../../schemas/demoSpec.schema");
|
|
10
|
+
const demoAuthorPrompt_1 = require("./demoAuthorPrompt");
|
|
11
|
+
// ─── 1. wizard pins ──────────────────────────────────────────────────────────
|
|
12
|
+
/** Overwrite style/narrative/aspect axes the user explicitly locked. */
|
|
13
|
+
function applyWizardPins(spec, answers, notes) {
|
|
14
|
+
if (!answers)
|
|
15
|
+
return spec;
|
|
16
|
+
const style = { ...spec.style };
|
|
17
|
+
let narrative = spec.narrative;
|
|
18
|
+
let aspect = spec.aspect;
|
|
19
|
+
if (answers.visualStyle && style.visual !== answers.visualStyle) {
|
|
20
|
+
notes.push(`visual: ${style.visual} → ${answers.visualStyle} (wizard pin)`);
|
|
21
|
+
style.visual = answers.visualStyle;
|
|
22
|
+
}
|
|
23
|
+
if (answers.pace && style.pace !== answers.pace) {
|
|
24
|
+
notes.push(`pace: ${style.pace} → ${answers.pace} (wizard pin)`);
|
|
25
|
+
style.pace = answers.pace;
|
|
26
|
+
}
|
|
27
|
+
if (answers.colorMood && style.colorMood !== answers.colorMood) {
|
|
28
|
+
notes.push(`colorMood: ${style.colorMood} → ${answers.colorMood} (wizard pin)`);
|
|
29
|
+
style.colorMood = answers.colorMood;
|
|
30
|
+
}
|
|
31
|
+
if (answers.audioIntent && style.audioIntent !== answers.audioIntent) {
|
|
32
|
+
notes.push(`audioIntent: ${style.audioIntent} → ${answers.audioIntent} (wizard pin)`);
|
|
33
|
+
style.audioIntent = answers.audioIntent;
|
|
34
|
+
}
|
|
35
|
+
if (answers.narrative && narrative !== answers.narrative) {
|
|
36
|
+
notes.push(`narrative: ${narrative} → ${answers.narrative} (wizard pin)`);
|
|
37
|
+
narrative = answers.narrative;
|
|
38
|
+
}
|
|
39
|
+
if (answers.aspect && aspect !== answers.aspect) {
|
|
40
|
+
notes.push(`aspect: ${aspect} → ${answers.aspect} (wizard pin)`);
|
|
41
|
+
aspect = answers.aspect;
|
|
42
|
+
}
|
|
43
|
+
return { ...spec, style, narrative, aspect };
|
|
44
|
+
}
|
|
45
|
+
// ─── 1.5 generated-asset requests (caps + reference accounting) ──────────────
|
|
46
|
+
/** Hard caps on planner-requested AI media per spec (cost + wall-clock bound). */
|
|
47
|
+
exports.DEMO_GEN_ASSET_MAX_IMAGES = 4;
|
|
48
|
+
exports.DEMO_GEN_ASSET_MAX_VIDEOS = 1;
|
|
49
|
+
/** Is this URL-slot value a reference to a declared generated asset? */
|
|
50
|
+
function isGenAssetRef(url) {
|
|
51
|
+
return !!url && url.startsWith(demoSpec_schema_1.GEN_ASSET_URI_PREFIX);
|
|
52
|
+
}
|
|
53
|
+
/** `gen://hero-shot` → `hero-shot` (undefined when not a gen ref). */
|
|
54
|
+
function genAssetIdFromRef(url) {
|
|
55
|
+
return url.slice(demoSpec_schema_1.GEN_ASSET_URI_PREFIX.length);
|
|
56
|
+
}
|
|
57
|
+
/** Every `gen://` ref AND every raw media string cited anywhere in a scene list
|
|
58
|
+
* (typed media slots + custom-scene prop bags, walked deeply so codegen props
|
|
59
|
+
* count as usage). */
|
|
60
|
+
function collectGenAssetRefs(scenes) {
|
|
61
|
+
const ids = new Set();
|
|
62
|
+
const urls = new Set();
|
|
63
|
+
const visit = (value, depth) => {
|
|
64
|
+
if (depth > 6 || value == null)
|
|
65
|
+
return;
|
|
66
|
+
if (typeof value === "string") {
|
|
67
|
+
if (isGenAssetRef(value))
|
|
68
|
+
ids.add(genAssetIdFromRef(value));
|
|
69
|
+
else if (value)
|
|
70
|
+
urls.add(value);
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
if (Array.isArray(value)) {
|
|
74
|
+
for (const v of value)
|
|
75
|
+
visit(v, depth + 1);
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
if (typeof value === "object") {
|
|
79
|
+
for (const v of Object.values(value)) {
|
|
80
|
+
visit(v, depth + 1);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
for (const scene of scenes) {
|
|
85
|
+
switch (scene.type) {
|
|
86
|
+
case "deviceMockup":
|
|
87
|
+
scene.screenshotUrls.forEach((u) => visit(u, 0));
|
|
88
|
+
visit(scene.videoUrl, 0);
|
|
89
|
+
break;
|
|
90
|
+
case "featureShowcase":
|
|
91
|
+
case "splitFeature":
|
|
92
|
+
visit(scene.screenshotUrl, 0);
|
|
93
|
+
visit(scene.videoUrl, 0);
|
|
94
|
+
break;
|
|
95
|
+
case "mediaShot":
|
|
96
|
+
visit(scene.imageUrl, 0);
|
|
97
|
+
visit(scene.videoUrl, 0);
|
|
98
|
+
break;
|
|
99
|
+
case "custom":
|
|
100
|
+
visit(scene.props, 0);
|
|
101
|
+
break;
|
|
102
|
+
default:
|
|
103
|
+
break;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return { ids, urls };
|
|
107
|
+
}
|
|
108
|
+
/** Dedupe ids (first declaration wins) + enforce the per-kind caps. READY
|
|
109
|
+
* assets (already generated + paid for on a prior pass/revise) take cap
|
|
110
|
+
* priority over pending requests; within each group, declaration order wins —
|
|
111
|
+
* the planner is told to list by importance. Original order is preserved. */
|
|
112
|
+
function capGeneratedAssets(assets, notes) {
|
|
113
|
+
const seen = new Set();
|
|
114
|
+
const deduped = [];
|
|
115
|
+
for (const asset of assets) {
|
|
116
|
+
if (seen.has(asset.id)) {
|
|
117
|
+
notes.push(`generatedAssets — dropped duplicate id "${asset.id}"`);
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
seen.add(asset.id);
|
|
121
|
+
deduped.push(asset);
|
|
122
|
+
}
|
|
123
|
+
const kept = new Set();
|
|
124
|
+
const counts = { image: 0, video: 0 };
|
|
125
|
+
const caps = { image: exports.DEMO_GEN_ASSET_MAX_IMAGES, video: exports.DEMO_GEN_ASSET_MAX_VIDEOS };
|
|
126
|
+
const isReady = (a) => a.status === "ready" && !!a.url;
|
|
127
|
+
for (const asset of [...deduped.filter(isReady), ...deduped.filter((a) => !isReady(a))]) {
|
|
128
|
+
if (counts[asset.kind] >= caps[asset.kind]) {
|
|
129
|
+
notes.push(`generatedAssets — dropped ${asset.kind} "${asset.id}" (cap ${caps[asset.kind]})`);
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
counts[asset.kind]++;
|
|
133
|
+
kept.add(asset.id);
|
|
134
|
+
}
|
|
135
|
+
return deduped.filter((a) => kept.has(a.id));
|
|
136
|
+
}
|
|
137
|
+
function sanitizeScreenshots(scenes, allowed, notes) {
|
|
138
|
+
// Placement policy: deviceMockup + featureShowcase present media AS the
|
|
139
|
+
// product's real screen, so they accept REAL media only — a generated image
|
|
140
|
+
// there would fabricate product UI. splitFeature side visuals and mediaShot
|
|
141
|
+
// full-bleed moments may cite generated assets (that's what they're for).
|
|
142
|
+
const images = allowed.realImages;
|
|
143
|
+
const videos = allowed.realVideos;
|
|
144
|
+
const anyImages = new Set([...allowed.realImages, ...allowed.genImages]);
|
|
145
|
+
const anyVideos = new Set([...allowed.realVideos, ...allowed.genVideos]);
|
|
146
|
+
const isImage = (u) => !!u && images.has(u);
|
|
147
|
+
const isVideo = (u) => !!u && videos.has(u);
|
|
148
|
+
const isAnyImage = (u) => !!u && anyImages.has(u);
|
|
149
|
+
const isAnyVideo = (u) => !!u && anyVideos.has(u);
|
|
150
|
+
const out = [];
|
|
151
|
+
for (const scene of scenes) {
|
|
152
|
+
switch (scene.type) {
|
|
153
|
+
case "deviceMockup": {
|
|
154
|
+
const valid = scene.screenshotUrls.filter((u) => images.has(u));
|
|
155
|
+
const validVideo = isVideo(scene.videoUrl) ? scene.videoUrl : undefined;
|
|
156
|
+
if (valid.length === 0 && !validVideo) {
|
|
157
|
+
notes.push(`dropped deviceMockup "${scene.id}" — no valid media URLs`);
|
|
158
|
+
continue; // drop the scene entirely
|
|
159
|
+
}
|
|
160
|
+
if (valid.length !== scene.screenshotUrls.length) {
|
|
161
|
+
notes.push(`deviceMockup "${scene.id}" — removed ${scene.screenshotUrls.length - valid.length} invalid screenshot URL(s)`);
|
|
162
|
+
}
|
|
163
|
+
if (scene.videoUrl && !validVideo) {
|
|
164
|
+
notes.push(`deviceMockup "${scene.id}" — stripped invented videoUrl`);
|
|
165
|
+
}
|
|
166
|
+
out.push({
|
|
167
|
+
...scene,
|
|
168
|
+
screenshotUrls: valid,
|
|
169
|
+
...(validVideo ? { videoUrl: validVideo } : { videoUrl: undefined }),
|
|
170
|
+
});
|
|
171
|
+
break;
|
|
172
|
+
}
|
|
173
|
+
case "featureShowcase":
|
|
174
|
+
case "splitFeature": {
|
|
175
|
+
// splitFeature side visuals may cite generated assets; featureShowcase
|
|
176
|
+
// (media inside the fake-app surface = "the product's screen") may not.
|
|
177
|
+
const okImage = scene.type === "splitFeature" ? isAnyImage : isImage;
|
|
178
|
+
const okVideo = scene.type === "splitFeature" ? isAnyVideo : isVideo;
|
|
179
|
+
let next = scene;
|
|
180
|
+
if (scene.screenshotUrl && !okImage(scene.screenshotUrl)) {
|
|
181
|
+
notes.push(`${scene.type} "${scene.id}" — stripped invented screenshotUrl (falls back to coded surface)`);
|
|
182
|
+
const { screenshotUrl: _drop, ...rest } = next;
|
|
183
|
+
next = rest;
|
|
184
|
+
}
|
|
185
|
+
if (scene.videoUrl && !okVideo(scene.videoUrl)) {
|
|
186
|
+
notes.push(`${scene.type} "${scene.id}" — stripped invented videoUrl`);
|
|
187
|
+
const { videoUrl: _dropV, ...rest } = next;
|
|
188
|
+
next = rest;
|
|
189
|
+
}
|
|
190
|
+
out.push(next);
|
|
191
|
+
break;
|
|
192
|
+
}
|
|
193
|
+
case "mediaShot": {
|
|
194
|
+
// The full-bleed media home: real uploads AND generated assets both fine.
|
|
195
|
+
const validImage = isAnyImage(scene.imageUrl) ? scene.imageUrl : undefined;
|
|
196
|
+
const validVideo = isAnyVideo(scene.videoUrl) ? scene.videoUrl : undefined;
|
|
197
|
+
if (!validImage && !validVideo) {
|
|
198
|
+
notes.push(`dropped mediaShot "${scene.id}" — no valid media URLs`);
|
|
199
|
+
continue;
|
|
200
|
+
}
|
|
201
|
+
if (scene.imageUrl && !validImage) {
|
|
202
|
+
notes.push(`mediaShot "${scene.id}" — stripped invented imageUrl`);
|
|
203
|
+
}
|
|
204
|
+
if (scene.videoUrl && !validVideo) {
|
|
205
|
+
notes.push(`mediaShot "${scene.id}" — stripped invented videoUrl`);
|
|
206
|
+
}
|
|
207
|
+
out.push({ ...scene, imageUrl: validImage, videoUrl: validVideo });
|
|
208
|
+
break;
|
|
209
|
+
}
|
|
210
|
+
default:
|
|
211
|
+
out.push(scene);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
return out;
|
|
215
|
+
}
|
|
216
|
+
// ─── 3. brand colors ─────────────────────────────────────────────────────────
|
|
217
|
+
/** Force the user's brand tokens back onto the spec (the model authors copy, not palette). */
|
|
218
|
+
function forceBrandColors(spec, input, notes) {
|
|
219
|
+
const given = input.brand.colors;
|
|
220
|
+
if (!given)
|
|
221
|
+
return spec;
|
|
222
|
+
const colors = { ...spec.brand.colors };
|
|
223
|
+
let changed = false;
|
|
224
|
+
if (given.primary && colors.primary !== given.primary) {
|
|
225
|
+
colors.primary = given.primary;
|
|
226
|
+
changed = true;
|
|
227
|
+
}
|
|
228
|
+
if (given.accent && colors.accent !== given.accent) {
|
|
229
|
+
colors.accent = given.accent;
|
|
230
|
+
changed = true;
|
|
231
|
+
}
|
|
232
|
+
if (given.palette?.length) {
|
|
233
|
+
colors.palette = given.palette;
|
|
234
|
+
}
|
|
235
|
+
if (changed)
|
|
236
|
+
notes.push(`brand colors forced to user tokens`);
|
|
237
|
+
return { ...spec, brand: { ...spec.brand, colors } };
|
|
238
|
+
}
|
|
239
|
+
// ─── 4. duration budget ──────────────────────────────────────────────────────
|
|
240
|
+
/**
|
|
241
|
+
* Scale every scene's duration by a single factor so the total lands inside the
|
|
242
|
+
* budget window. Proportional scaling preserves the author's intended pacing
|
|
243
|
+
* (a 4s hero beat stays ~2× a 2s cut). Only scales when the total is outside
|
|
244
|
+
* [min,max]; snaps to `target` when it does. Enforces a per-scene floor.
|
|
245
|
+
*/
|
|
246
|
+
const MIN_SCENE_MS = 700;
|
|
247
|
+
function fitDuration(scenes, budget, notes) {
|
|
248
|
+
const total = scenes.reduce((acc, s) => acc + s.durationMs, 0);
|
|
249
|
+
if (total >= budget.min && total <= budget.max)
|
|
250
|
+
return scenes;
|
|
251
|
+
const factor = budget.target / Math.max(total, 1);
|
|
252
|
+
notes.push(`total duration ${Math.round(total / 1000)}s outside ${Math.round(budget.min / 1000)}–${Math.round(budget.max / 1000)}s → scaled ×${factor.toFixed(2)} to ~${Math.round(budget.target / 1000)}s`);
|
|
253
|
+
return scenes.map((s) => ({
|
|
254
|
+
...s,
|
|
255
|
+
durationMs: Math.max(MIN_SCENE_MS, Math.round(s.durationMs * factor)),
|
|
256
|
+
}));
|
|
257
|
+
}
|
|
258
|
+
// ─── orchestration ───────────────────────────────────────────────────────────
|
|
259
|
+
/**
|
|
260
|
+
* Run the full deterministic normalize pipeline on a raw authored spec and
|
|
261
|
+
* return a schema-valid, render-ready DemoSpec plus the list of adjustments.
|
|
262
|
+
* Throws only if the model produced something with zero scenes (unrecoverable).
|
|
263
|
+
*/
|
|
264
|
+
function normalizeDemoSpec(raw, input) {
|
|
265
|
+
const notes = [];
|
|
266
|
+
const budget = (0, demoAuthorPrompt_1.budgetForLength)(input.answers?.targetLength);
|
|
267
|
+
// productName is authoritative from the caller, never the model.
|
|
268
|
+
let spec = { ...raw, productName: input.productName };
|
|
269
|
+
spec = applyWizardPins(spec, input.answers, notes);
|
|
270
|
+
spec = forceBrandColors(spec, input, notes);
|
|
271
|
+
// Planner-requested AI media: dedupe + cap FIRST so refs to dropped requests
|
|
272
|
+
// are treated as invented URLs by the sanitizer below.
|
|
273
|
+
const generatedAssets = capGeneratedAssets(spec.generatedAssets ?? [], notes);
|
|
274
|
+
// Allowed media sets: images = uploaded/captured screenshots + image assets;
|
|
275
|
+
// videos = the user's video assets. Only these URLs may survive on scene props.
|
|
276
|
+
// `gen://<id>` refs are allowed iff they point at a surviving declared asset of
|
|
277
|
+
// the matching kind — the asset-generation stage resolves them to real URLs.
|
|
278
|
+
// Which slots accept gen refs is decided per scene type in sanitizeScreenshots.
|
|
279
|
+
const imageAssetUrls = (input.mediaAssets ?? [])
|
|
280
|
+
.filter((a) => a.kind === "image")
|
|
281
|
+
.map((a) => a.url);
|
|
282
|
+
// Ready assets' RESOLVED urls are also allowed (in the gen sets, so placement
|
|
283
|
+
// policy still holds): on revise, the incoming spec's scenes already carry the
|
|
284
|
+
// substituted GCS URLs, and stripping them as "invented" would throw away
|
|
285
|
+
// media we already paid for.
|
|
286
|
+
const readyGenUrls = (kind) => generatedAssets
|
|
287
|
+
.filter((a) => a.kind === kind && a.status === "ready" && !!a.url)
|
|
288
|
+
.map((a) => a.url);
|
|
289
|
+
const genRef = (a) => `${demoSpec_schema_1.GEN_ASSET_URI_PREFIX}${a.id}`;
|
|
290
|
+
const allowed = {
|
|
291
|
+
realImages: new Set([...(input.screenshotUrls ?? []), ...imageAssetUrls]),
|
|
292
|
+
realVideos: new Set((input.mediaAssets ?? []).filter((a) => a.kind === "video").map((a) => a.url)),
|
|
293
|
+
genImages: new Set([
|
|
294
|
+
...generatedAssets.filter((a) => a.kind === "image").map(genRef),
|
|
295
|
+
...readyGenUrls("image"),
|
|
296
|
+
]),
|
|
297
|
+
genVideos: new Set([
|
|
298
|
+
...generatedAssets.filter((a) => a.kind === "video").map(genRef),
|
|
299
|
+
...readyGenUrls("video"),
|
|
300
|
+
]),
|
|
301
|
+
};
|
|
302
|
+
let scenes = sanitizeScreenshots(spec.scenes, allowed, notes);
|
|
303
|
+
if (scenes.length === 0) {
|
|
304
|
+
throw new Error("normalizeDemoSpec: authored spec has no renderable scenes after media sanitation");
|
|
305
|
+
}
|
|
306
|
+
scenes = fitDuration(scenes, budget, notes);
|
|
307
|
+
// Drop asset requests nothing cites anymore (refs may have been stripped or
|
|
308
|
+
// their scene dropped) — an unreferenced request is pure provider spend. A
|
|
309
|
+
// ready asset cited by its RESOLVED url (post-materialization spec) counts.
|
|
310
|
+
const cited = collectGenAssetRefs(scenes);
|
|
311
|
+
const referencedAssets = generatedAssets.filter((a) => {
|
|
312
|
+
if (cited.ids.has(a.id))
|
|
313
|
+
return true;
|
|
314
|
+
if (a.status === "ready" && a.url && cited.urls.has(a.url))
|
|
315
|
+
return true;
|
|
316
|
+
notes.push(`generatedAssets — dropped unreferenced "${a.id}"`);
|
|
317
|
+
return false;
|
|
318
|
+
});
|
|
319
|
+
spec = { ...spec, scenes, generatedAssets: referencedAssets };
|
|
320
|
+
// Final schema pass applies all defaults + guarantees a valid contract.
|
|
321
|
+
const parsed = demoSpec_schema_1.DemoSpecSchema.parse(spec);
|
|
322
|
+
return { spec: parsed, adjustments: notes };
|
|
323
|
+
}
|
|
324
|
+
/** Convenience — total timeline of a normalized spec (ms). */
|
|
325
|
+
function specTotalMs(spec) {
|
|
326
|
+
return (0, demoSpec_schema_1.demoSpecDurationMs)(spec);
|
|
327
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { DemoBrand } from "../../schemas/demoSpec.schema";
|
|
2
|
+
import { IDemoClarifyAnswerValue, IDemoMediaAsset, IDemoVideoWizardAnswers } from "../../models/demoVideoProject.model";
|
|
3
|
+
/**
|
|
4
|
+
* Prompt construction for the SaaS Demo Video author (plan Phase 3 / §4 stage 2).
|
|
5
|
+
*
|
|
6
|
+
* The author is a single Claude `.structured<DemoSpec>()` call: it turns the
|
|
7
|
+
* user's product facts + brand tokens + product screenshots (as vision) + the
|
|
8
|
+
* clarifying-wizard answers into a valid, render-ready `DemoSpec` that the
|
|
9
|
+
* Layer-A scene-template engine renders to MP4 with zero manual effort.
|
|
10
|
+
*
|
|
11
|
+
* Kept separate from `demoAuthor.ts` because the system prompt is the largest,
|
|
12
|
+
* most-iterated surface — it encodes the scene vocabulary, the §2.6 style
|
|
13
|
+
* taxonomy, the anti-overfit rule, and the screenshot-vs-coded-chrome guidance.
|
|
14
|
+
* The prompt only DESCRIBES the contract; the zod schema is what actually
|
|
15
|
+
* constrains the output (passed as the tool `input_schema`), and a
|
|
16
|
+
* deterministic normalize pass (demoAuthor.ts) enforces the invariants a prompt
|
|
17
|
+
* can only request (wizard pins, real screenshot URLs, duration budget).
|
|
18
|
+
*/
|
|
19
|
+
export interface DurationBudget {
|
|
20
|
+
min: number;
|
|
21
|
+
target: number;
|
|
22
|
+
max: number;
|
|
23
|
+
/** Rough scene-count guidance handed to the author for pacing. */
|
|
24
|
+
sceneHint: string;
|
|
25
|
+
}
|
|
26
|
+
export declare const DURATION_BUDGETS: Record<NonNullable<IDemoVideoWizardAnswers["targetLength"]>, DurationBudget>;
|
|
27
|
+
/** Default when the user left targetLength on "decide for me". */
|
|
28
|
+
export declare const DEFAULT_DURATION_BUDGET: DurationBudget;
|
|
29
|
+
export declare function budgetForLength(targetLength: IDemoVideoWizardAnswers["targetLength"] | undefined): DurationBudget;
|
|
30
|
+
/**
|
|
31
|
+
* Everything the author needs to write a DemoSpec. Product facts + resolved
|
|
32
|
+
* brand + the raw inputs (screenshots/website) + wizard answers. Brand colors
|
|
33
|
+
* are honored verbatim (never re-invented); copy + scene structure are authored.
|
|
34
|
+
*/
|
|
35
|
+
export interface DemoAuthorInput {
|
|
36
|
+
/** Product display name — overlay text only, never AI-rendered into pixels. */
|
|
37
|
+
productName: string;
|
|
38
|
+
/** One-line value proposition, if the user gave one. */
|
|
39
|
+
tagline?: string;
|
|
40
|
+
/** Short product description / what it does. */
|
|
41
|
+
description?: string;
|
|
42
|
+
/** Feature labels to highlight (from the wizard "which features" multi-select). */
|
|
43
|
+
features?: string[];
|
|
44
|
+
/** Target-audience hint for script tone. */
|
|
45
|
+
audience?: string;
|
|
46
|
+
/** Resolved brand tokens (colors/fonts/identity). Colors are used as-is. */
|
|
47
|
+
brand: DemoBrand;
|
|
48
|
+
/** Real product screenshot URLs (GCS). Fed as vision AND the ONLY image URLs the author may cite. */
|
|
49
|
+
screenshotUrls?: string[];
|
|
50
|
+
/**
|
|
51
|
+
* Media the user wants FEATURED in the video (images + video clips). Unlike
|
|
52
|
+
* screenshots (reference the author MAY use), these SHOULD appear on the
|
|
53
|
+
* timeline. Video clips are placed via *.videoUrl scene props; image assets are
|
|
54
|
+
* merged into the screenshot set upstream. The author is told they exist + must
|
|
55
|
+
* surface them. See [[IDemoMediaAsset]].
|
|
56
|
+
*/
|
|
57
|
+
mediaAssets?: IDemoMediaAsset[];
|
|
58
|
+
/** Product website, for context. The worker's gather stage fetches it (see `pageSummary`). */
|
|
59
|
+
websiteUrl?: string;
|
|
60
|
+
/**
|
|
61
|
+
* A compact, LLM-free summary of the product page's copy (title/description +
|
|
62
|
+
* visible-text lead), extracted by the worker during gather even when the user
|
|
63
|
+
* never clicked "Autofill". Steering context for the script — NOT rendered
|
|
64
|
+
* verbatim on screen. See [[gatherPageSignals]].
|
|
65
|
+
*/
|
|
66
|
+
pageSummary?: string;
|
|
67
|
+
/** User's free-text notes about the repo/product — steering context, not rendered verbatim. */
|
|
68
|
+
repoNotes?: string;
|
|
69
|
+
/** Clarifying-wizard answers. Omitted fields === "decide for me" (author picks). */
|
|
70
|
+
answers?: IDemoVideoWizardAnswers;
|
|
71
|
+
/**
|
|
72
|
+
* Answers to the agent's DYNAMIC clarifying questions (triage/mid-run loop),
|
|
73
|
+
* keyed by question id. Authoritative steering context — the author should honor
|
|
74
|
+
* them. See [[DemoQuestion]].
|
|
75
|
+
*/
|
|
76
|
+
clarifyAnswers?: Record<string, IDemoClarifyAnswerValue>;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* The system prompt. Deliberately opinionated about quality (invented realistic
|
|
80
|
+
* domain data, cursor-synced walkthroughs, staggered reveals, on-brand color)
|
|
81
|
+
* and about the two hard reliability rules a prompt CAN enforce by instruction:
|
|
82
|
+
* never invent screenshot URLs, never render the product name as pixels.
|
|
83
|
+
*/
|
|
84
|
+
export interface DemoAuthorPromptOpts {
|
|
85
|
+
/**
|
|
86
|
+
* Allow the planner to PROPOSE `custom` scenes (with an `intent` brief the
|
|
87
|
+
* Layer-B codegen agent later authors). Mirrors the worker's
|
|
88
|
+
* `DEMO_CODEGEN_ENABLED` gate — default false, so the prompt keeps the hard
|
|
89
|
+
* "no custom scenes" rule and behavior is unchanged until the flag is on.
|
|
90
|
+
*/
|
|
91
|
+
allowCustomScenes?: boolean;
|
|
92
|
+
/**
|
|
93
|
+
* Allow the planner to COMMISSION AI-generated media (`generatedAssets` +
|
|
94
|
+
* `gen://` refs). Default true — the deterministic caps bound the cost; the
|
|
95
|
+
* worker passes false only under the DEMO_GEN_ASSETS_DISABLED kill-switch.
|
|
96
|
+
*/
|
|
97
|
+
allowGeneratedAssets?: boolean;
|
|
98
|
+
}
|
|
99
|
+
export declare function buildDemoAuthorSystemPrompt(opts?: DemoAuthorPromptOpts): string;
|
|
100
|
+
/** Build the user-turn text (images are attached separately as imageUrls). */
|
|
101
|
+
export declare function buildDemoAuthorUserText(input: DemoAuthorInput): string;
|
|
102
|
+
//# sourceMappingURL=demoAuthorPrompt.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"demoAuthorPrompt.d.ts","sourceRoot":"","sources":["../../../src/services/demo/demoAuthorPrompt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAC1D,OAAO,EACL,uBAAuB,EACvB,eAAe,EACf,uBAAuB,EACxB,MAAM,qCAAqC,CAAC;AAE7C;;;;;;;;;;;;;;;GAeG;AAMH,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,kEAAkE;IAClE,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,eAAO,MAAM,gBAAgB,EAAE,MAAM,CACnC,WAAW,CAAC,uBAAuB,CAAC,cAAc,CAAC,CAAC,EACpD,cAAc,CAQf,CAAC;AAEF,kEAAkE;AAClE,eAAO,MAAM,uBAAuB,EAAE,cAA6C,CAAC;AAEpF,wBAAgB,eAAe,CAC7B,YAAY,EAAE,uBAAuB,CAAC,cAAc,CAAC,GAAG,SAAS,GAChE,cAAc,CAEhB;AAID;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC9B,+EAA+E;IAC/E,WAAW,EAAE,MAAM,CAAC;IACpB,wDAAwD;IACxD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gDAAgD;IAChD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mFAAmF;IACnF,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,4CAA4C;IAC5C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4EAA4E;IAC5E,KAAK,EAAE,SAAS,CAAC;IACjB,qGAAqG;IACrG,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,eAAe,EAAE,CAAC;IAChC,8FAA8F;IAC9F,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,+FAA+F;IAC/F,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oFAAoF;IACpF,OAAO,CAAC,EAAE,uBAAuB,CAAC;IAClC;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,uBAAuB,CAAC,CAAC;CAC1D;AAwFD;;;;;GAKG;AACH,MAAM,WAAW,oBAAoB;IACnC;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B;;;;OAIG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC;AAED,wBAAgB,2BAA2B,CAAC,IAAI,GAAE,oBAAyB,GAAG,MAAM,CA0CnF;AAmED,8EAA8E;AAC9E,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,eAAe,GAAG,MAAM,CA+CtE"}
|