vidspotai-shared 1.0.122 → 1.0.124
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/schemas/brief.schema.d.ts +56 -0
- package/lib/schemas/brief.schema.d.ts.map +1 -1
- package/lib/schemas/brief.schema.js +33 -1
- package/lib/schemas/videoPlan.schema.d.ts +2 -2
- package/lib/schemas/videoPlan.schema.d.ts.map +1 -1
- package/lib/schemas/videoPlan.schema.js +15 -2
- package/lib/services/agent/eval/types.d.ts +22 -0
- package/lib/services/agent/eval/types.d.ts.map +1 -1
- package/lib/services/agent/mentionedRefs.d.ts +20 -0
- package/lib/services/agent/mentionedRefs.d.ts.map +1 -0
- package/lib/services/agent/mentionedRefs.js +129 -0
- package/lib/services/agent/planner/plannerMessages.d.ts.map +1 -1
- package/lib/services/agent/planner/plannerMessages.js +7 -0
- package/lib/services/agent/planner/promptSections.d.ts.map +1 -1
- package/lib/services/agent/planner/promptSections.js +8 -1
- package/lib/services/agent/runPlanning.d.ts.map +1 -1
- package/lib/services/agent/runPlanning.js +9 -2
- package/lib/services/agent/tools/generateScript.tool.d.ts +23 -1
- package/lib/services/agent/tools/generateScript.tool.d.ts.map +1 -1
- package/lib/services/agent/tools/planVideo.tool.d.ts +23 -1
- package/lib/services/agent/tools/planVideo.tool.d.ts.map +1 -1
- package/lib/services/translation/translation.service.d.ts +11 -3
- package/lib/services/translation/translation.service.d.ts.map +1 -1
- package/lib/services/translation/translation.service.js +113 -12
- package/package.json +1 -1
|
@@ -158,6 +158,39 @@ export declare const ReferenceLinkSchema: z.ZodObject<{
|
|
|
158
158
|
transcriptExcerpt: z.ZodOptional<z.ZodString>;
|
|
159
159
|
}, z.core.$strip>>;
|
|
160
160
|
}, z.core.$strip>;
|
|
161
|
+
/**
|
|
162
|
+
* One Reference Library item the user @-mentioned in the composer (a built-in
|
|
163
|
+
* seed or one of their own refs), flattened across kinds by the frontend's
|
|
164
|
+
* `collectMentionedRefs` (wt-dev-frontend refs/tokens.ts — keep in sync).
|
|
165
|
+
*
|
|
166
|
+
* Unlike `references` (bare URLs), this carries what the item MEANS so the
|
|
167
|
+
* pipeline can honor it: characters / elements are pinned into the Visual
|
|
168
|
+
* Bible with their image (→ threaded as inputImageUrls on every scene they
|
|
169
|
+
* appear in, see mentionedRefs.ts), and style / effect / color / camera
|
|
170
|
+
* instructions are applied by the planner scene by scene.
|
|
171
|
+
*/
|
|
172
|
+
export declare const MentionedRefSchema: z.ZodObject<{
|
|
173
|
+
kind: z.ZodEnum<{
|
|
174
|
+
element: "element";
|
|
175
|
+
motion: "motion";
|
|
176
|
+
color: "color";
|
|
177
|
+
style: "style";
|
|
178
|
+
character: "character";
|
|
179
|
+
effect: "effect";
|
|
180
|
+
camera: "camera";
|
|
181
|
+
voice: "voice";
|
|
182
|
+
model: "model";
|
|
183
|
+
}>;
|
|
184
|
+
slug: z.ZodString;
|
|
185
|
+
name: z.ZodString;
|
|
186
|
+
instruction: z.ZodOptional<z.ZodString>;
|
|
187
|
+
imageUrls: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
188
|
+
subkind: z.ZodOptional<z.ZodString>;
|
|
189
|
+
presetKey: z.ZodOptional<z.ZodString>;
|
|
190
|
+
swatches: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
191
|
+
voiceId: z.ZodOptional<z.ZodString>;
|
|
192
|
+
modelKey: z.ZodOptional<z.ZodString>;
|
|
193
|
+
}, z.core.$strip>;
|
|
161
194
|
export declare const VideoBriefSchema: z.ZodObject<{
|
|
162
195
|
rawPrompt: z.ZodString;
|
|
163
196
|
goal: z.ZodOptional<z.ZodString>;
|
|
@@ -278,6 +311,28 @@ export declare const VideoBriefSchema: z.ZodObject<{
|
|
|
278
311
|
transcriptExcerpt: z.ZodOptional<z.ZodString>;
|
|
279
312
|
}, z.core.$strip>>;
|
|
280
313
|
}, z.core.$strip>>>;
|
|
314
|
+
mentionedRefs: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
315
|
+
kind: z.ZodEnum<{
|
|
316
|
+
element: "element";
|
|
317
|
+
motion: "motion";
|
|
318
|
+
color: "color";
|
|
319
|
+
style: "style";
|
|
320
|
+
character: "character";
|
|
321
|
+
effect: "effect";
|
|
322
|
+
camera: "camera";
|
|
323
|
+
voice: "voice";
|
|
324
|
+
model: "model";
|
|
325
|
+
}>;
|
|
326
|
+
slug: z.ZodString;
|
|
327
|
+
name: z.ZodString;
|
|
328
|
+
instruction: z.ZodOptional<z.ZodString>;
|
|
329
|
+
imageUrls: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
330
|
+
subkind: z.ZodOptional<z.ZodString>;
|
|
331
|
+
presetKey: z.ZodOptional<z.ZodString>;
|
|
332
|
+
swatches: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
333
|
+
voiceId: z.ZodOptional<z.ZodString>;
|
|
334
|
+
modelKey: z.ZodOptional<z.ZodString>;
|
|
335
|
+
}, z.core.$strip>>>;
|
|
281
336
|
preferredModelKeys: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
282
337
|
tierBudget: z.ZodDefault<z.ZodEnum<{
|
|
283
338
|
T0: "T0";
|
|
@@ -303,6 +358,7 @@ export type VoiceProfile = z.infer<typeof VoiceProfileSchema>;
|
|
|
303
358
|
export type VoiceStyle = z.infer<typeof VoiceStyleSchema>;
|
|
304
359
|
export type MusicProfile = z.infer<typeof MusicProfileSchema>;
|
|
305
360
|
export type ReferenceLink = z.infer<typeof ReferenceLinkSchema>;
|
|
361
|
+
export type MentionedRef = z.infer<typeof MentionedRefSchema>;
|
|
306
362
|
export type VideoNiche = z.infer<typeof VideoNicheSchema>;
|
|
307
363
|
export type Tone = z.infer<typeof ToneSchema>;
|
|
308
364
|
export type HookStyle = z.infer<typeof HookStyleSchema>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"brief.schema.d.ts","sourceRoot":"","sources":["../../src/schemas/brief.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB;;;;;;;;;;;GAWG;AAEH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;EAc3B,CAAC;AAEH,eAAO,MAAM,UAAU;;;;;;;;;;EAUrB,CAAC;AAEH,eAAO,MAAM,eAAe;;;;;;;;EAQ1B,CAAC;AAEH,eAAO,MAAM,YAAY;;;;;EAAkD,CAAC;AAE5E;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,gBAAgB;;;;;;;EAA+C,CAAC;AAC7E,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE1D;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,UAAU,CASjE;AAKD,eAAO,MAAM,gBAAgB;;;;;;;;;;;EAW3B,CAAC;AAEH,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAkB7B,CAAC;AAEH,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;iBAiB7B,CAAC;AAEH,eAAO,MAAM,YAAY;;;iBAKvB,CAAC;AAEH,eAAO,MAAM,mBAAmB;;;;;;;;;;iBAa9B,CAAC;AAEH,eAAO,MAAM,gBAAgB
|
|
1
|
+
{"version":3,"file":"brief.schema.d.ts","sourceRoot":"","sources":["../../src/schemas/brief.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB;;;;;;;;;;;GAWG;AAEH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;EAc3B,CAAC;AAEH,eAAO,MAAM,UAAU;;;;;;;;;;EAUrB,CAAC;AAEH,eAAO,MAAM,eAAe;;;;;;;;EAQ1B,CAAC;AAEH,eAAO,MAAM,YAAY;;;;;EAAkD,CAAC;AAE5E;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,gBAAgB;;;;;;;EAA+C,CAAC;AAC7E,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE1D;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,UAAU,CASjE;AAKD,eAAO,MAAM,gBAAgB;;;;;;;;;;;EAW3B,CAAC;AAEH,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAkB7B,CAAC;AAEH,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;iBAiB7B,CAAC;AAEH,eAAO,MAAM,YAAY;;;iBAKvB,CAAC;AAEH,eAAO,MAAM,mBAAmB;;;;;;;;;;iBAa9B,CAAC;AAEH;;;;;;;;;;GAUG;AACH,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;iBAe7B,CAAC;AAEH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAwG3B,CAAC;AAEH,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAC1D,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAC9D,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAC1D,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAC9D,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAChE,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAC9D,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAC1D,MAAM,MAAM,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,UAAU,CAAC,CAAC;AAC9C,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AACxD,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.VideoBriefSchema = exports.ReferenceLinkSchema = exports.ClaimsSchema = exports.MusicProfileSchema = exports.VoiceProfileSchema = exports.VoiceStyleSchema = exports.LengthTierSchema = exports.PacingSchema = exports.HookStyleSchema = exports.ToneSchema = exports.VideoNicheSchema = void 0;
|
|
3
|
+
exports.VideoBriefSchema = exports.MentionedRefSchema = exports.ReferenceLinkSchema = exports.ClaimsSchema = exports.MusicProfileSchema = exports.VoiceProfileSchema = exports.VoiceStyleSchema = exports.LengthTierSchema = exports.PacingSchema = exports.HookStyleSchema = exports.ToneSchema = exports.VideoNicheSchema = void 0;
|
|
4
4
|
exports.deriveLengthTier = deriveLengthTier;
|
|
5
5
|
const zod_1 = require("zod");
|
|
6
6
|
const project_schema_1 = require("./project.schema");
|
|
@@ -163,6 +163,33 @@ exports.ReferenceLinkSchema = zod_1.z.object({
|
|
|
163
163
|
})
|
|
164
164
|
.optional(),
|
|
165
165
|
});
|
|
166
|
+
/**
|
|
167
|
+
* One Reference Library item the user @-mentioned in the composer (a built-in
|
|
168
|
+
* seed or one of their own refs), flattened across kinds by the frontend's
|
|
169
|
+
* `collectMentionedRefs` (wt-dev-frontend refs/tokens.ts — keep in sync).
|
|
170
|
+
*
|
|
171
|
+
* Unlike `references` (bare URLs), this carries what the item MEANS so the
|
|
172
|
+
* pipeline can honor it: characters / elements are pinned into the Visual
|
|
173
|
+
* Bible with their image (→ threaded as inputImageUrls on every scene they
|
|
174
|
+
* appear in, see mentionedRefs.ts), and style / effect / color / camera
|
|
175
|
+
* instructions are applied by the planner scene by scene.
|
|
176
|
+
*/
|
|
177
|
+
exports.MentionedRefSchema = zod_1.z.object({
|
|
178
|
+
kind: zod_1.z.enum(["character", "style", "color", "element", "effect", "camera", "motion", "voice", "model"]),
|
|
179
|
+
slug: zod_1.z.string().max(120),
|
|
180
|
+
name: zod_1.z.string().max(120),
|
|
181
|
+
/** The look / recipe / direction this ref stands for. */
|
|
182
|
+
instruction: zod_1.z.string().max(2000).optional(),
|
|
183
|
+
/** Absolute reference image URLs (character / style / element). */
|
|
184
|
+
imageUrls: zod_1.z.array(zod_1.z.string().url()).max(4).optional(),
|
|
185
|
+
/** Element sub-kind — "location" pins as an environment, else an object. */
|
|
186
|
+
subkind: zod_1.z.string().max(40).optional(),
|
|
187
|
+
/** Canonical model camera-control preset (camera / motion refs). */
|
|
188
|
+
presetKey: zod_1.z.string().max(60).optional(),
|
|
189
|
+
swatches: zod_1.z.array(zod_1.z.string().max(20)).max(12).optional(),
|
|
190
|
+
voiceId: zod_1.z.string().max(120).optional(),
|
|
191
|
+
modelKey: zod_1.z.string().max(120).optional(),
|
|
192
|
+
});
|
|
166
193
|
exports.VideoBriefSchema = zod_1.z.object({
|
|
167
194
|
/** Free-text user request, kept verbatim. */
|
|
168
195
|
rawPrompt: zod_1.z.string(),
|
|
@@ -199,6 +226,11 @@ exports.VideoBriefSchema = zod_1.z.object({
|
|
|
199
226
|
cta: zod_1.z.string().optional(),
|
|
200
227
|
claims: exports.ClaimsSchema.default({ allow: [], block: [] }),
|
|
201
228
|
references: zod_1.z.array(exports.ReferenceLinkSchema).default([]),
|
|
229
|
+
/**
|
|
230
|
+
* Reference Library items the user @-mentioned (see MentionedRefSchema).
|
|
231
|
+
* Optional (not defaulted) so existing briefs and eval seeds are unchanged.
|
|
232
|
+
*/
|
|
233
|
+
mentionedRefs: zod_1.z.array(exports.MentionedRefSchema).max(24).optional(),
|
|
202
234
|
/**
|
|
203
235
|
* Soft generation-model preference supplied by the user (via the composer's
|
|
204
236
|
* "@Models" mention category). These are real catalog keys (e.g.
|
|
@@ -485,7 +485,7 @@ export declare const ScriptSchema: z.ZodObject<{
|
|
|
485
485
|
fullText: z.ZodString;
|
|
486
486
|
wordCount: z.ZodOptional<z.ZodNumber>;
|
|
487
487
|
estimatedDurationMs: z.ZodOptional<z.ZodNumber>;
|
|
488
|
-
wpm: z.ZodOptional<z.ZodNumber
|
|
488
|
+
wpm: z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodOptional<z.ZodNumber>>;
|
|
489
489
|
}, z.core.$strip>;
|
|
490
490
|
export type Script = z.infer<typeof ScriptSchema>;
|
|
491
491
|
export declare const VideoPlanSchema: z.ZodObject<{
|
|
@@ -680,7 +680,7 @@ export declare const VideoPlanSchema: z.ZodObject<{
|
|
|
680
680
|
fullText: z.ZodString;
|
|
681
681
|
wordCount: z.ZodOptional<z.ZodNumber>;
|
|
682
682
|
estimatedDurationMs: z.ZodOptional<z.ZodNumber>;
|
|
683
|
-
wpm: z.ZodOptional<z.ZodNumber
|
|
683
|
+
wpm: z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodOptional<z.ZodNumber>>;
|
|
684
684
|
}, z.core.$strip>>>;
|
|
685
685
|
music: z.ZodOptional<z.ZodObject<{
|
|
686
686
|
strategy: z.ZodEnum<{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"videoPlan.schema.d.ts","sourceRoot":"","sources":["../../src/schemas/videoPlan.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAUxB;;;;;;;GAOG;AAEH;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,iBAAiB;;;;;iBAc5B,CAAC;AAEH,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;iBASjC,CAAC;AAEH,eAAO,MAAM,wBAAwB;;;;;;;;;EASnC,CAAC;AAEH,eAAO,MAAM,oBAAoB;;;;;;;;;EAS/B,CAAC;AAEH;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,cAAc;;;;;;;;EAQzB,CAAC;AAEH,eAAO,MAAM,kBAAkB;;;;;;;;;;;;EAY7B,CAAC;AAEH,eAAO,MAAM,mBAAmB;;;;;;;;EAQ9B,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB;;;;;;EAM5B,CAAC;AAEH;;;;;;;GAOG;AACH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAsC5B,CAAC;AACH,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAC5D,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AACtD,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAC9D,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAChE,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAE5D;;;;;;;;;GASG;AACH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;iBAqC5B,CAAC;AACH,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAE5D;;;;;;;;;;GAUG;AACH;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB;;;;;;EAM9B,CAAC;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEhE,eAAO,MAAM,kBAAkB;;;;;;;;;;;;iBAQ7B,CAAC;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAE9D,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA+I7B,CAAC;AAEH;;;;;;;GAOG;AACH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;iBAa/B,CAAC;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE;;;;;;;;GAQG;AACH,eAAO,MAAM,aAAa;;;;;;iBAkBxB,CAAC;AACH,MAAM,MAAM,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC;AAEpD;;;;;;GAMG;AACH,eAAO,MAAM,YAAY;;;;;
|
|
1
|
+
{"version":3,"file":"videoPlan.schema.d.ts","sourceRoot":"","sources":["../../src/schemas/videoPlan.schema.ts"],"names":[],"mappings":"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"}
|
|
@@ -451,8 +451,21 @@ exports.ScriptSchema = zod_1.z.object({
|
|
|
451
451
|
wordCount: zod_1.z.number().int().nonnegative().optional(),
|
|
452
452
|
/** Estimated spoken duration in ms at `wpm`. */
|
|
453
453
|
estimatedDurationMs: zod_1.z.number().nonnegative().optional(),
|
|
454
|
-
/**
|
|
455
|
-
|
|
454
|
+
/**
|
|
455
|
+
* Words-per-minute used for the estimate (typical narration ≈ 150).
|
|
456
|
+
*
|
|
457
|
+
* Coercion: the scene-first planner prompt (S1/S2/M1) never mentions this
|
|
458
|
+
* field, yet the LLM occasionally emits a `script` object on a scene-first
|
|
459
|
+
* plan anyway and invents a `wpm` value from nothing — observed in prod as
|
|
460
|
+
* `0`, which fails `positive()` and burns all 3 retries with the same
|
|
461
|
+
* generic duration-shaped correction text, killing the whole project
|
|
462
|
+
* (2026-09-28 incident). Every consumer already falls back with
|
|
463
|
+
* `?? TTS_DEFAULT_WPM` when `wpm` is absent (generateScript/chapterOutline/
|
|
464
|
+
* matchBrollToScript tools), so a non-positive value is strictly worse than
|
|
465
|
+
* no value — drop it at the schema boundary instead of hard-failing.
|
|
466
|
+
*/
|
|
467
|
+
wpm: zod_1.z
|
|
468
|
+
.preprocess((v) => (typeof v === "number" && v <= 0 ? undefined : v), zod_1.z.number().int().positive().optional()),
|
|
456
469
|
});
|
|
457
470
|
exports.VideoPlanSchema = zod_1.z.object({
|
|
458
471
|
briefId: zod_1.z.string().optional(),
|
|
@@ -143,6 +143,28 @@ export declare const EvalBriefSchema: z.ZodObject<{
|
|
|
143
143
|
transcriptExcerpt: z.ZodOptional<z.ZodString>;
|
|
144
144
|
}, z.core.$strip>>;
|
|
145
145
|
}, z.core.$strip>>>;
|
|
146
|
+
mentionedRefs: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
147
|
+
kind: z.ZodEnum<{
|
|
148
|
+
element: "element";
|
|
149
|
+
motion: "motion";
|
|
150
|
+
color: "color";
|
|
151
|
+
style: "style";
|
|
152
|
+
character: "character";
|
|
153
|
+
effect: "effect";
|
|
154
|
+
camera: "camera";
|
|
155
|
+
voice: "voice";
|
|
156
|
+
model: "model";
|
|
157
|
+
}>;
|
|
158
|
+
slug: z.ZodString;
|
|
159
|
+
name: z.ZodString;
|
|
160
|
+
instruction: z.ZodOptional<z.ZodString>;
|
|
161
|
+
imageUrls: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
162
|
+
subkind: z.ZodOptional<z.ZodString>;
|
|
163
|
+
presetKey: z.ZodOptional<z.ZodString>;
|
|
164
|
+
swatches: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
165
|
+
voiceId: z.ZodOptional<z.ZodString>;
|
|
166
|
+
modelKey: z.ZodOptional<z.ZodString>;
|
|
167
|
+
}, z.core.$strip>>>;
|
|
146
168
|
preferredModelKeys: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
147
169
|
tierBudget: z.ZodDefault<z.ZodEnum<{
|
|
148
170
|
T0: "T0";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/services/agent/eval/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB;;;;;;;;;;GAUG;AAEH,4CAA4C;AAC5C,eAAO,MAAM,gBAAgB;;;;;;;iBAQ3B,CAAC;AACH,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE1D,eAAO,MAAM,eAAe
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/services/agent/eval/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB;;;;;;;;;;GAUG;AAEH,4CAA4C;AAC5C,eAAO,MAAM,gBAAgB;;;;;;;iBAQ3B,CAAC;AACH,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE1D,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAM1B,CAAC;AACH,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAExD,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;iBAY9B,CAAC;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEhE,+DAA+D;AAC/D,eAAO,MAAM,iBAAiB;;;;iBAI5B,CAAC;AACH,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAE5D,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAW9B,CAAC;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEhE,eAAO,MAAM,eAAe;;;;;;;;;;;;;;iBAQ1B,CAAC;AACH,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { VideoBrief } from "../../schemas/brief.schema";
|
|
2
|
+
import { AgentVisualBible } from "../../schemas/videoPlan.schema";
|
|
3
|
+
/**
|
|
4
|
+
* Pin every mentioned character / element into the bible. When the bible
|
|
5
|
+
* builder already made an entity for it (matched by name — the brief text
|
|
6
|
+
* names the ref, since tokens resolve to names), that entity keeps its id and
|
|
7
|
+
* gains the ref's image + description; otherwise a new entity is appended.
|
|
8
|
+
*
|
|
9
|
+
* Creates a bible when there is none (C0 briefs skip the builder, and the
|
|
10
|
+
* builder soft-fails to undefined) — a user who picked a character expects
|
|
11
|
+
* that face even on the cheapest tier, and the bible is how it gets there.
|
|
12
|
+
* Returns the input untouched when nothing is pinnable.
|
|
13
|
+
*/
|
|
14
|
+
export declare function pinMentionedRefsIntoBible(bible: AgentVisualBible | undefined, brief: VideoBrief): AgentVisualBible | undefined;
|
|
15
|
+
/**
|
|
16
|
+
* Planner system-prompt section for the user's @-mentioned refs. Empty string
|
|
17
|
+
* when there are none (the common path adds zero tokens).
|
|
18
|
+
*/
|
|
19
|
+
export declare function buildMentionedRefsSection(brief: VideoBrief, bible: AgentVisualBible | null): string;
|
|
20
|
+
//# sourceMappingURL=mentionedRefs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mentionedRefs.d.ts","sourceRoot":"","sources":["../../../src/services/agent/mentionedRefs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,UAAU,EAAE,MAAM,4BAA4B,CAAC;AACtE,OAAO,EAAE,gBAAgB,EAAe,MAAM,gCAAgC,CAAC;AAgD/E;;;;;;;;;;GAUG;AACH,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,gBAAgB,GAAG,SAAS,EACnC,KAAK,EAAE,UAAU,GAChB,gBAAgB,GAAG,SAAS,CAwC9B;AAID;;;GAGG;AACH,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,UAAU,EACjB,KAAK,EAAE,gBAAgB,GAAG,IAAI,GAC7B,MAAM,CAmER"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.pinMentionedRefsIntoBible = pinMentionedRefsIntoBible;
|
|
4
|
+
exports.buildMentionedRefsSection = buildMentionedRefsSection;
|
|
5
|
+
const ID_PREFIX = {
|
|
6
|
+
characters: "CHAR",
|
|
7
|
+
objects: "OBJ",
|
|
8
|
+
environments: "ENV",
|
|
9
|
+
};
|
|
10
|
+
function entityKindFor(ref) {
|
|
11
|
+
if (ref.kind === "character")
|
|
12
|
+
return "characters";
|
|
13
|
+
if (ref.kind === "element")
|
|
14
|
+
return ref.subkind === "location" ? "environments" : "objects";
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
function nextId(entities, prefix) {
|
|
18
|
+
const max = entities.reduce((m, e) => {
|
|
19
|
+
const n = Number(e.id.split("_")[1]);
|
|
20
|
+
return Number.isFinite(n) && n > m ? n : m;
|
|
21
|
+
}, 0);
|
|
22
|
+
return `${prefix}_${max + 1}`;
|
|
23
|
+
}
|
|
24
|
+
const norm = (s) => s.trim().toLowerCase();
|
|
25
|
+
/**
|
|
26
|
+
* Pin every mentioned character / element into the bible. When the bible
|
|
27
|
+
* builder already made an entity for it (matched by name — the brief text
|
|
28
|
+
* names the ref, since tokens resolve to names), that entity keeps its id and
|
|
29
|
+
* gains the ref's image + description; otherwise a new entity is appended.
|
|
30
|
+
*
|
|
31
|
+
* Creates a bible when there is none (C0 briefs skip the builder, and the
|
|
32
|
+
* builder soft-fails to undefined) — a user who picked a character expects
|
|
33
|
+
* that face even on the cheapest tier, and the bible is how it gets there.
|
|
34
|
+
* Returns the input untouched when nothing is pinnable.
|
|
35
|
+
*/
|
|
36
|
+
function pinMentionedRefsIntoBible(bible, brief) {
|
|
37
|
+
const pinnable = (brief.mentionedRefs ?? []).filter((r) => entityKindFor(r));
|
|
38
|
+
if (pinnable.length === 0)
|
|
39
|
+
return bible;
|
|
40
|
+
const tier = brief.consistencyTier ?? "C1";
|
|
41
|
+
const out = {
|
|
42
|
+
characters: [...(bible?.characters ?? [])],
|
|
43
|
+
objects: [...(bible?.objects ?? [])],
|
|
44
|
+
environments: [...(bible?.environments ?? [])],
|
|
45
|
+
consistencyTier: bible?.consistencyTier ?? (tier === "C0" ? "C1" : tier),
|
|
46
|
+
};
|
|
47
|
+
for (const ref of pinnable) {
|
|
48
|
+
const kind = entityKindFor(ref);
|
|
49
|
+
const list = out[kind];
|
|
50
|
+
const imageUrl = ref.imageUrls?.[0];
|
|
51
|
+
const description = ref.instruction?.trim() || ref.name;
|
|
52
|
+
const idx = list.findIndex((e) => norm(e.name) === norm(ref.name) || norm(e.name).includes(norm(ref.name)));
|
|
53
|
+
const existing = idx >= 0 ? list[idx] : undefined;
|
|
54
|
+
if (existing) {
|
|
55
|
+
list[idx] = {
|
|
56
|
+
...existing,
|
|
57
|
+
name: ref.name,
|
|
58
|
+
// The ref's description matches its image; the builder's was
|
|
59
|
+
// inferred from the brief text alone.
|
|
60
|
+
description: imageUrl ? description : existing.description,
|
|
61
|
+
...(imageUrl ? { referenceImageUrl: imageUrl } : {}),
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
list.push({
|
|
66
|
+
id: nextId(list, ID_PREFIX[kind]),
|
|
67
|
+
name: ref.name,
|
|
68
|
+
description,
|
|
69
|
+
...(imageUrl ? { referenceImageUrl: imageUrl } : {}),
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return out;
|
|
74
|
+
}
|
|
75
|
+
const DIRECTION_KINDS = ["style", "effect", "color", "camera", "motion"];
|
|
76
|
+
/**
|
|
77
|
+
* Planner system-prompt section for the user's @-mentioned refs. Empty string
|
|
78
|
+
* when there are none (the common path adds zero tokens).
|
|
79
|
+
*/
|
|
80
|
+
function buildMentionedRefsSection(brief, bible) {
|
|
81
|
+
const refs = brief.mentionedRefs ?? [];
|
|
82
|
+
if (refs.length === 0)
|
|
83
|
+
return "";
|
|
84
|
+
const allEntities = bible
|
|
85
|
+
? [...bible.characters, ...bible.objects, ...bible.environments]
|
|
86
|
+
: [];
|
|
87
|
+
const pinned = refs
|
|
88
|
+
.filter((r) => entityKindFor(r))
|
|
89
|
+
.map((r) => ({ ref: r, entity: allEntities.find((e) => norm(e.name) === norm(r.name)) }))
|
|
90
|
+
.filter((p) => p.entity);
|
|
91
|
+
const by = (k) => refs.filter((r) => r.kind === k && (r.instruction || r.swatches?.length));
|
|
92
|
+
const lines = [
|
|
93
|
+
"",
|
|
94
|
+
"USER-SELECTED REFERENCES — the user explicitly picked these from their Reference Library by",
|
|
95
|
+
"@-mentioning them in the brief. They are requirements, not suggestions; the brief text names",
|
|
96
|
+
"each one where the user wants it.",
|
|
97
|
+
];
|
|
98
|
+
if (pinned.length) {
|
|
99
|
+
lines.push(" Pinned subjects (each carries a reference image the generator receives):");
|
|
100
|
+
pinned.forEach(({ ref, entity }) => lines.push(` ${entity.id} — ${ref.name} (${ref.kind === "character" ? "character" : ref.subkind ?? "element"})`));
|
|
101
|
+
lines.push(" Every scene that shows one of these MUST list its id in scene.bibleEntityIds — that is how", " the reference image reaches the generator. A scene that omits the id renders a stranger.", " Scenes showing a pinned subject must use an AI-generated strategy (not stock / user-asset).");
|
|
102
|
+
}
|
|
103
|
+
const styles = by("style");
|
|
104
|
+
if (styles.length) {
|
|
105
|
+
lines.push(" Visual style — apply to EVERY scene prompt, verbatim:");
|
|
106
|
+
styles.forEach((r) => lines.push(` ${r.name}: ${r.instruction}`));
|
|
107
|
+
}
|
|
108
|
+
const colors = by("color");
|
|
109
|
+
if (colors.length) {
|
|
110
|
+
lines.push(" Color palette — grade every scene toward these colors:");
|
|
111
|
+
colors.forEach((r) => lines.push(` ${r.name}: ${r.swatches?.join(", ") ?? r.instruction}`));
|
|
112
|
+
}
|
|
113
|
+
const effects = by("effect");
|
|
114
|
+
if (effects.length) {
|
|
115
|
+
lines.push(" Effects — add to every scene prompt unless the brief ties one to a specific moment:");
|
|
116
|
+
effects.forEach((r) => lines.push(` ${r.name}: ${r.instruction}`));
|
|
117
|
+
}
|
|
118
|
+
const angles = by("camera");
|
|
119
|
+
if (angles.length) {
|
|
120
|
+
lines.push(" Camera angles / framing — use on the scene(s) the brief ties them to; if the brief doesn't say", " where, use it on the opening scene. Put the framing text in scene.prompt:");
|
|
121
|
+
angles.forEach((r) => lines.push(` ${r.name}: ${r.instruction}`));
|
|
122
|
+
}
|
|
123
|
+
const moves = by("motion");
|
|
124
|
+
if (moves.length) {
|
|
125
|
+
lines.push(" Camera moves — same placement rule as angles. Copy the direction into scene.prompt verbatim.", " A still can't carry a camera move, so those scenes must use ai-image-to-video or", " ai-text-to-video (never ai-image-static / stock-image-ken-burns):");
|
|
126
|
+
moves.forEach((r) => lines.push(` ${r.name}: ${r.instruction}`));
|
|
127
|
+
}
|
|
128
|
+
return lines.join("\n");
|
|
129
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plannerMessages.d.ts","sourceRoot":"","sources":["../../../../src/services/agent/planner/plannerMessages.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,sCAAsC,CAAC;AACpE,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AACrE,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"plannerMessages.d.ts","sourceRoot":"","sources":["../../../../src/services/agent/planner/plannerMessages.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,sCAAsC,CAAC;AACpE,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AACrE,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAgBhF;;;;;GAKG;AAEH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,UAAU,EACjB,OAAO,EAAE,YAAY,GAAG,SAAS,EACjC,QAAQ,EAAE,cAAc,GAAG,IAAI,EAC/B,WAAW,EAAE,iBAAiB,GAAG,IAAI,EACrC,KAAK,EAAE,gBAAgB,GAAG,IAAI,EAC9B,UAAU,CAAC,EAAE,MAAM,EACnB,eAAe,UAAQ;;;;;;KA4JxB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAiChE"}
|
|
@@ -7,6 +7,7 @@ const modelQualityNotes_1 = require("../modelQualityNotes");
|
|
|
7
7
|
const outputLanguage_1 = require("../../translation/outputLanguage");
|
|
8
8
|
const promptSections_1 = require("./promptSections");
|
|
9
9
|
const structuralRules_1 = require("./structuralRules");
|
|
10
|
+
const mentionedRefs_1 = require("../mentionedRefs");
|
|
10
11
|
/**
|
|
11
12
|
* Planner prompt assembly + the web-research heuristic. Pure functions (no LLM
|
|
12
13
|
* call, no class state) so the Planner class stays focused on the
|
|
@@ -32,6 +33,7 @@ function buildPlannerMessages(brief, persona, brandKit, styleMemory, bible, last
|
|
|
32
33
|
const brandKitSection = (0, promptSections_1.buildBrandKitSection)(brandKit);
|
|
33
34
|
const styleMemorySection = (0, promptSections_1.buildStyleMemorySection)(styleMemory);
|
|
34
35
|
const bibleSection = (0, promptSections_1.buildBibleSection)(bible);
|
|
36
|
+
const mentionedRefsSection = (0, mentionedRefs_1.buildMentionedRefsSection)(brief, bible);
|
|
35
37
|
const modelCatalogSection = (0, promptSections_1.buildModelCatalogSection)();
|
|
36
38
|
const preferredModelsSection = (0, promptSections_1.buildPreferredModelsSection)(brief.preferredModelKeys);
|
|
37
39
|
const videoStrategySection = (0, promptSections_1.buildVideoStrategySection)(brief.videoStrategy);
|
|
@@ -63,6 +65,10 @@ function buildPlannerMessages(brief, persona, brandKit, styleMemory, bible, last
|
|
|
63
65
|
"You are a video-production planner.",
|
|
64
66
|
"Given a VideoBrief, produce a VideoPlan: an ordered list of scenes",
|
|
65
67
|
"with per-scene asset strategy, tier, prompt, duration, and voiceover.",
|
|
68
|
+
"Do NOT set the top-level `script` field — it is only used by long-form",
|
|
69
|
+
"script-first authoring and is populated by a separate pipeline step, not",
|
|
70
|
+
"by you. Leave it out entirely; per-scene voiceoverLine is where narration",
|
|
71
|
+
"goes for this plan.",
|
|
66
72
|
researchSection,
|
|
67
73
|
"",
|
|
68
74
|
"Tier rules — respect brief.tierBudget as the maximum tier:",
|
|
@@ -123,6 +129,7 @@ function buildPlannerMessages(brief, persona, brandKit, styleMemory, bible, last
|
|
|
123
129
|
personaSection,
|
|
124
130
|
structuralRulesSection,
|
|
125
131
|
bibleSection,
|
|
132
|
+
mentionedRefsSection,
|
|
126
133
|
brandKitSection,
|
|
127
134
|
styleMemorySection,
|
|
128
135
|
"",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"promptSections.d.ts","sourceRoot":"","sources":["../../../../src/services/agent/planner/promptSections.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AACrE,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAShF,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAGjE;AAED;;;;;;;GAOG;AACH,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,QAAQ,GAAG,UAAU,GAAG,MAAM,GAAG,SAAS,GACnD,MAAM,CAkCR;AAED,wBAAgB,wBAAwB,IAAI,MAAM,CAWjD;AAYD;;;;;;;;;;GAUG;AACH,wBAAgB,2BAA2B,CACzC,kBAAkB,EAAE,MAAM,EAAE,GAAG,SAAS,GACvC,MAAM,CAmCR;AAED,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,cAAc,GAAG,IAAI,GAAG,MAAM,CAgC5E;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,gBAAgB,GAAG,IAAI,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"promptSections.d.ts","sourceRoot":"","sources":["../../../../src/services/agent/planner/promptSections.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AACrE,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAShF,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAGjE;AAED;;;;;;;GAOG;AACH,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,QAAQ,GAAG,UAAU,GAAG,MAAM,GAAG,SAAS,GACnD,MAAM,CAkCR;AAED,wBAAgB,wBAAwB,IAAI,MAAM,CAWjD;AAYD;;;;;;;;;;GAUG;AACH,wBAAgB,2BAA2B,CACzC,kBAAkB,EAAE,MAAM,EAAE,GAAG,SAAS,GACvC,MAAM,CAmCR;AAED,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,cAAc,GAAG,IAAI,GAAG,MAAM,CAgC5E;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,gBAAgB,GAAG,IAAI,GAAG,MAAM,CA6CxE;AAED,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,iBAAiB,GAAG,IAAI,GAAG,MAAM,CAsBhF"}
|
|
@@ -181,6 +181,11 @@ function buildBibleSection(bible) {
|
|
|
181
181
|
const environments = bible.environments ?? [];
|
|
182
182
|
if (!characters.length && !objects.length && !environments.length)
|
|
183
183
|
return "";
|
|
184
|
+
// Entities pinned from the user's @-mentioned refs arrive with an image even
|
|
185
|
+
// below C2 (see mentionedRefs.ts).
|
|
186
|
+
const withImages = [...characters, ...objects, ...environments]
|
|
187
|
+
.filter((e) => e.referenceImageUrl)
|
|
188
|
+
.map((e) => e.id);
|
|
184
189
|
const formatEntity = (e) => ` ${e.id} — ${e.name}: ${e.description}`;
|
|
185
190
|
const lines = [
|
|
186
191
|
"",
|
|
@@ -200,7 +205,9 @@ function buildBibleSection(bible) {
|
|
|
200
205
|
}
|
|
201
206
|
lines.push("", "Bible usage contract (hard rule):", " - For every scene, set scene.bibleEntityIds to the list of entity ids that appear in that scene (e.g. [\"CHAR_1\", \"OBJ_1\"]).", " - For every entity in scene.bibleEntityIds, re-state its description verbatim in scene.prompt. Do NOT paraphrase — copy the exact words from the bible. Different scenes referencing the same entity must use IDENTICAL description text.", " - characterAnchorSceneIndex (AG-11) is still useful as a backup signal but the bible is primary. If both are set, both should agree.", bible.consistencyTier === "C2"
|
|
202
207
|
? " - C2 note: entities will additionally get pre-rendered reference images (executor threads them as inputImageUrls on image-gen calls). Your descriptions seed those reference images, so be visually specific."
|
|
203
|
-
:
|
|
208
|
+
: withImages.length
|
|
209
|
+
? ` - C1 note: ${withImages.join(", ")} carry user-supplied reference images (threaded as inputImageUrls on every scene that lists them); for the rest, descriptions are the only consistency signal — be as visually specific as possible.`
|
|
210
|
+
: " - C1 note: descriptions are the ONLY consistency signal — no reference images. Be as visually specific as possible.");
|
|
204
211
|
return lines.join("\n");
|
|
205
212
|
}
|
|
206
213
|
function buildStyleMemorySection(memory) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runPlanning.d.ts","sourceRoot":"","sources":["../../../src/services/agent/runPlanning.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,UAAU,EAAoB,MAAM,4BAA4B,CAAC;AAC1E,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,gCAAgC,CAAC;AAC7E,OAAO,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAC;AACjE,OAAO,EACL,kBAAkB,EAClB,cAAc,EACd,iBAAiB,EACjB,SAAS,EACV,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"runPlanning.d.ts","sourceRoot":"","sources":["../../../src/services/agent/runPlanning.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,UAAU,EAAoB,MAAM,4BAA4B,CAAC;AAC1E,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,gCAAgC,CAAC;AAC7E,OAAO,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAC;AACjE,OAAO,EACL,kBAAkB,EAClB,cAAc,EACd,iBAAiB,EACjB,SAAS,EACV,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAyBnD;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,UAAU,EACjB,QAAQ,EAAE,cAAc,GAAG,IAAI,GAC9B,MAAM,CAaR;AAiED;;;;;GAKG;AACH,wBAAsB,iBAAiB,CAAC,IAAI,EAAE;IAC5C,OAAO,EAAE,kBAAkB,CAAC;IAC5B,KAAK,EAAE,UAAU,CAAC;IAClB,OAAO,EAAE,YAAY,GAAG,SAAS,CAAC;IAClC,QAAQ,EAAE,cAAc,GAAG,IAAI,CAAC;IAChC,GAAG,EAAE,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;IACrC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,CAAC;CACtC,GAAG,OAAO,CAAC;IAAE,KAAK,EAAE,gBAAgB,GAAG,SAAS,CAAC;IAAC,KAAK,EAAE,OAAO,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC,CAuBhF;AAED,sDAAsD;AACtD,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE;IACtC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,UAAU,CAAC;IAClB,IAAI,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAAC,MAAM,CAAC,EAAE,OAAO,EAAE,CAAA;KAAE,CAAC;IAC7D,OAAO,EAAE,gBAAgB,CAAC;IAC1B,aAAa,EAAE,OAAO,CAAC;IACvB,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,OAAO,CAAC;CACjB,GAAG,IAAI,CAkCP;AAED,wDAAwD;AACxD,MAAM,WAAW,iBAAiB;IAChC,0CAA0C;IAC1C,IAAI,EAAE,SAAS,CAAC;IAChB,6EAA6E;IAC7E,KAAK,EAAE,gBAAgB,GAAG,SAAS,CAAC;IACpC,wGAAwG;IACxG,UAAU,EAAE,OAAO,CAAC;IACpB,+EAA+E;IAC/E,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;GAMG;AACH,wBAAsB,WAAW,CAAC,IAAI,EAAE;IACtC,8CAA8C;IAC9C,OAAO,EAAE,kBAAkB,CAAC;IAC5B,KAAK,EAAE,UAAU,CAAC;IAClB,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,QAAQ,EAAE,cAAc,GAAG,IAAI,CAAC;IAChC,WAAW,EAAE,iBAAiB,GAAG,IAAI,CAAC;IACtC,qEAAqE;IACrE,cAAc,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAClC,2EAA2E;IAC3E,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,qEAAqE;IACrE,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,CAAC;CACtC,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAuD7B"}
|
|
@@ -11,6 +11,7 @@ const brief_schema_1 = require("../../schemas/brief.schema");
|
|
|
11
11
|
const llmCallerRegistry_1 = require("./llmCallerRegistry");
|
|
12
12
|
const bibleBuilder_1 = require("./bibleBuilder");
|
|
13
13
|
const bibleImageVision_1 = require("./bibleImageVision");
|
|
14
|
+
const mentionedRefs_1 = require("./mentionedRefs");
|
|
14
15
|
const planner_1 = require("./planner");
|
|
15
16
|
const musicSelect_1 = require("./musicSelect");
|
|
16
17
|
const beatSnap_1 = require("./beatSnap");
|
|
@@ -37,7 +38,10 @@ const isoNow = () => new Date().toISOString();
|
|
|
37
38
|
* we never cache nothing as something.
|
|
38
39
|
*/
|
|
39
40
|
function computeBibleCacheKey(brief, brandKit) {
|
|
40
|
-
|
|
41
|
+
// C0 builds no bible — unless the user @-mentioned a character/element,
|
|
42
|
+
// which gets pinned into one (see pinMentionedRefsIntoBible).
|
|
43
|
+
const pins = (brief.mentionedRefs ?? []).some((r) => r.kind === "character" || r.kind === "element");
|
|
44
|
+
if ((brief.consistencyTier ?? "C1") === "C0" && !pins)
|
|
41
45
|
return "";
|
|
42
46
|
return (0, crypto_1.createHash)("sha256")
|
|
43
47
|
.update(JSON.stringify({
|
|
@@ -125,8 +129,11 @@ async function getBibleWithCache(args) {
|
|
|
125
129
|
persona: args.persona,
|
|
126
130
|
brandKit: args.brandKit,
|
|
127
131
|
});
|
|
132
|
+
// Pin @-mentioned characters/elements (with their reference images) before
|
|
133
|
+
// the vision pass, so their descriptions get re-read from the image too.
|
|
134
|
+
const pinned = (0, mentionedRefs_1.pinMentionedRefsIntoBible)(built, args.brief);
|
|
128
135
|
args.onStage?.("aligning_bible_with_images");
|
|
129
|
-
const bible = await safeBibleImageVision(
|
|
136
|
+
const bible = await safeBibleImageVision(pinned);
|
|
130
137
|
return { bible, fresh: true, key };
|
|
131
138
|
}
|
|
132
139
|
/**
|
|
@@ -140,6 +140,28 @@ declare const InputSchema: z.ZodObject<{
|
|
|
140
140
|
transcriptExcerpt: z.ZodOptional<z.ZodString>;
|
|
141
141
|
}, z.core.$strip>>;
|
|
142
142
|
}, z.core.$strip>>>;
|
|
143
|
+
mentionedRefs: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
144
|
+
kind: z.ZodEnum<{
|
|
145
|
+
element: "element";
|
|
146
|
+
motion: "motion";
|
|
147
|
+
color: "color";
|
|
148
|
+
style: "style";
|
|
149
|
+
character: "character";
|
|
150
|
+
effect: "effect";
|
|
151
|
+
camera: "camera";
|
|
152
|
+
voice: "voice";
|
|
153
|
+
model: "model";
|
|
154
|
+
}>;
|
|
155
|
+
slug: z.ZodString;
|
|
156
|
+
name: z.ZodString;
|
|
157
|
+
instruction: z.ZodOptional<z.ZodString>;
|
|
158
|
+
imageUrls: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
159
|
+
subkind: z.ZodOptional<z.ZodString>;
|
|
160
|
+
presetKey: z.ZodOptional<z.ZodString>;
|
|
161
|
+
swatches: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
162
|
+
voiceId: z.ZodOptional<z.ZodString>;
|
|
163
|
+
modelKey: z.ZodOptional<z.ZodString>;
|
|
164
|
+
}, z.core.$strip>>>;
|
|
143
165
|
preferredModelKeys: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
144
166
|
tierBudget: z.ZodDefault<z.ZodEnum<{
|
|
145
167
|
T0: "T0";
|
|
@@ -167,7 +189,7 @@ declare const OutputSchema: z.ZodObject<{
|
|
|
167
189
|
fullText: z.ZodString;
|
|
168
190
|
wordCount: z.ZodOptional<z.ZodNumber>;
|
|
169
191
|
estimatedDurationMs: z.ZodOptional<z.ZodNumber>;
|
|
170
|
-
wpm: z.ZodOptional<z.ZodNumber
|
|
192
|
+
wpm: z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodOptional<z.ZodNumber>>;
|
|
171
193
|
}, z.core.$strip>;
|
|
172
194
|
suggestedTitle: z.ZodOptional<z.ZodString>;
|
|
173
195
|
}, z.core.$strip>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generateScript.tool.d.ts","sourceRoot":"","sources":["../../../../src/services/agent/tools/generateScript.tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,UAAU,EAAoB,MAAM,+BAA+B,CAAC;AAC7E,OAAO,EAAE,MAAM,EAAgB,MAAM,mCAAmC,CAAC;AACzE,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAIzC,OAAO,EAAgB,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAG/D;;;;;;;;;;;;;;;GAeG;AAEH,QAAA,MAAM,WAAW
|
|
1
|
+
{"version":3,"file":"generateScript.tool.d.ts","sourceRoot":"","sources":["../../../../src/services/agent/tools/generateScript.tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,UAAU,EAAoB,MAAM,+BAA+B,CAAC;AAC7E,OAAO,EAAE,MAAM,EAAgB,MAAM,mCAAmC,CAAC;AACzE,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAIzC,OAAO,EAAgB,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAG/D;;;;;;;;;;;;;;;GAeG;AAEH,QAAA,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAUf,CAAC;AAeH,QAAA,MAAM,YAAY;;;;;;;;iBAGhB,CAAC;AAEH;;;;GAIG;AACH,wBAAsB,kBAAkB,CACtC,GAAG,EAAE,SAAS,EACd,KAAK,EAAE,UAAU,EACjB,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,cAAc,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAoEtD;AAED,eAAO,MAAM,kBAAkB,EAAE,cAAc,CAC7C,OAAO,WAAW,EAClB,OAAO,YAAY,CAcpB,CAAC"}
|
|
@@ -123,6 +123,28 @@ declare const InputSchema: z.ZodObject<{
|
|
|
123
123
|
transcriptExcerpt: z.ZodOptional<z.ZodString>;
|
|
124
124
|
}, z.core.$strip>>;
|
|
125
125
|
}, z.core.$strip>>>;
|
|
126
|
+
mentionedRefs: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
127
|
+
kind: z.ZodEnum<{
|
|
128
|
+
element: "element";
|
|
129
|
+
motion: "motion";
|
|
130
|
+
color: "color";
|
|
131
|
+
style: "style";
|
|
132
|
+
character: "character";
|
|
133
|
+
effect: "effect";
|
|
134
|
+
camera: "camera";
|
|
135
|
+
voice: "voice";
|
|
136
|
+
model: "model";
|
|
137
|
+
}>;
|
|
138
|
+
slug: z.ZodString;
|
|
139
|
+
name: z.ZodString;
|
|
140
|
+
instruction: z.ZodOptional<z.ZodString>;
|
|
141
|
+
imageUrls: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
142
|
+
subkind: z.ZodOptional<z.ZodString>;
|
|
143
|
+
presetKey: z.ZodOptional<z.ZodString>;
|
|
144
|
+
swatches: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
145
|
+
voiceId: z.ZodOptional<z.ZodString>;
|
|
146
|
+
modelKey: z.ZodOptional<z.ZodString>;
|
|
147
|
+
}, z.core.$strip>>>;
|
|
126
148
|
preferredModelKeys: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
127
149
|
tierBudget: z.ZodDefault<z.ZodEnum<{
|
|
128
150
|
T0: "T0";
|
|
@@ -337,7 +359,7 @@ declare const OutputSchema: z.ZodObject<{
|
|
|
337
359
|
fullText: z.ZodString;
|
|
338
360
|
wordCount: z.ZodOptional<z.ZodNumber>;
|
|
339
361
|
estimatedDurationMs: z.ZodOptional<z.ZodNumber>;
|
|
340
|
-
wpm: z.ZodOptional<z.ZodNumber
|
|
362
|
+
wpm: z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodOptional<z.ZodNumber>>;
|
|
341
363
|
}, z.core.$strip>>>;
|
|
342
364
|
music: z.ZodOptional<z.ZodObject<{
|
|
343
365
|
strategy: z.ZodEnum<{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"planVideo.tool.d.ts","sourceRoot":"","sources":["../../../../src/services/agent/tools/planVideo.tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,OAAO,EAAgB,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAQ/D,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,SAAS,GAAG,IAAI,CAExD;AAED,QAAA,MAAM,WAAW
|
|
1
|
+
{"version":3,"file":"planVideo.tool.d.ts","sourceRoot":"","sources":["../../../../src/services/agent/tools/planVideo.tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,OAAO,EAAgB,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAQ/D,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,SAAS,GAAG,IAAI,CAExD;AAED,QAAA,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAIf,CAAC;AAEH,QAAA,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAEhB,CAAC;AAEH,eAAO,MAAM,aAAa,EAAE,cAAc,CACxC,OAAO,WAAW,EAClB,OAAO,YAAY,CAuBpB,CAAC"}
|
|
@@ -28,9 +28,17 @@ import { ELANGUAGE_CODE, IDetectLang } from "../../globals/types";
|
|
|
28
28
|
*/
|
|
29
29
|
export declare const TRANSLATION_FAILED = "TRANSLATION_FAILED";
|
|
30
30
|
/**
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
31
|
+
* Split `text` into pieces of at most `max` chars whose concatenation is
|
|
32
|
+
* exactly `text`. Breaks at sentence / line ends where possible; a single
|
|
33
|
+
* over-long sentence is hard-split at the last whitespace before `max`.
|
|
34
|
+
*/
|
|
35
|
+
export declare function splitForTranslation(text: string, max?: number): string[];
|
|
36
|
+
/**
|
|
37
|
+
* Translate `text` from → to (default English). Long text is split into
|
|
38
|
+
* chunks translated in parallel (see CHUNK_MAX_CHARS); each chunk goes
|
|
39
|
+
* primary CF first (with a quick retry), then a cheap LLM. Throws
|
|
40
|
+
* Error(TRANSLATION_FAILED) only if BOTH layers fail for some chunk; `.cause`
|
|
41
|
+
* carries the last error.
|
|
34
42
|
*/
|
|
35
43
|
declare function translate(text: string, from: ELANGUAGE_CODE, to?: ELANGUAGE_CODE, version?: "v1" | "v2"): Promise<string>;
|
|
36
44
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"translation.service.d.ts","sourceRoot":"","sources":["../../../src/services/translation/translation.service.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAGlE;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,eAAO,MAAM,kBAAkB,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"translation.service.d.ts","sourceRoot":"","sources":["../../../src/services/translation/translation.service.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAGlE;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,eAAO,MAAM,kBAAkB,uBAAuB,CAAC;AAiDvD;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,SAAkB,GAAG,MAAM,EAAE,CA8BjF;AA4ID;;;;;;GAMG;AACH,iBAAe,SAAS,CACtB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,cAAc,EACpB,EAAE,GAAE,cAAkC,EACtC,OAAO,GAAE,IAAI,GAAG,IAAW,GAC1B,OAAO,CAAC,MAAM,CAAC,CAiBjB;AAiGD;;;;;;;;;;;;;;GAcG;AACH,iBAAe,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CA8ChE;AAOD,eAAO,MAAM,kBAAkB;;;CAG9B,CAAC;AAGF,qDAAqD;AACrD,eAAO,MAAM,qBAAqB,kBAAY,CAAC;AAC/C,0DAA0D;AAC1D,eAAO,MAAM,UAAU,uBAAiB,CAAC"}
|
|
@@ -37,6 +37,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
37
37
|
};
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
39
|
exports.detectLang = exports.getTranslationWrapper = exports.translationService = exports.TRANSLATION_FAILED = void 0;
|
|
40
|
+
exports.splitForTranslation = splitForTranslation;
|
|
40
41
|
const axios_1 = __importDefault(require("axios"));
|
|
41
42
|
const enums_1 = require("../../globals/aiModels/enums");
|
|
42
43
|
const types_1 = require("../../globals/types");
|
|
@@ -90,6 +91,76 @@ const PRIMARY_MAX_ATTEMPTS = 2;
|
|
|
90
91
|
// handshake) gets a second, fresh try instead of being fatal.
|
|
91
92
|
const FALLBACK_ATTEMPT_TIMEOUT_MS = 8000;
|
|
92
93
|
const FALLBACK_MAX_ATTEMPTS = 2;
|
|
94
|
+
// 2026-09-28 ROOT CAUSE of the recurring "BOTH primary and LLM fallback"
|
|
95
|
+
// Slack alerts: fixed timeouts vs. LONG prompts. 14 days of prod logs: every
|
|
96
|
+
// sampled both-layer failure was a 483–2523-word prompt; every fast success
|
|
97
|
+
// was ≤~100 words. Neither upstream was down — a healthy gpt-4o-mini call on
|
|
98
|
+
// a real failed 726-word `id` prompt took 17s (1141 output tokens), so an 8s
|
|
99
|
+
// attempt could never win, and retrying just repeated the doomed call.
|
|
100
|
+
//
|
|
101
|
+
// Fix: split long text on paragraph/sentence boundaries into ≤CHUNK_MAX_CHARS
|
|
102
|
+
// pieces and translate them IN PARALLEL, so wall time tracks one chunk rather
|
|
103
|
+
// than the whole prompt. Per-attempt timeouts also scale with chunk length
|
|
104
|
+
// (base + per-char) so a max-size chunk has real headroom.
|
|
105
|
+
const CHUNK_MAX_CHARS = 1200;
|
|
106
|
+
const CHUNK_CONCURRENCY = 6;
|
|
107
|
+
const PRIMARY_TIMEOUT_PER_CHAR_MS = 2;
|
|
108
|
+
const FALLBACK_TIMEOUT_PER_CHAR_MS = 5;
|
|
109
|
+
function primaryTimeoutFor(text) {
|
|
110
|
+
return PRIMARY_TIMEOUT_MS + text.length * PRIMARY_TIMEOUT_PER_CHAR_MS;
|
|
111
|
+
}
|
|
112
|
+
function fallbackTimeoutFor(text) {
|
|
113
|
+
return FALLBACK_ATTEMPT_TIMEOUT_MS + text.length * FALLBACK_TIMEOUT_PER_CHAR_MS;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Split `text` into pieces of at most `max` chars whose concatenation is
|
|
117
|
+
* exactly `text`. Breaks at sentence / line ends where possible; a single
|
|
118
|
+
* over-long sentence is hard-split at the last whitespace before `max`.
|
|
119
|
+
*/
|
|
120
|
+
function splitForTranslation(text, max = CHUNK_MAX_CHARS) {
|
|
121
|
+
if (text.length <= max)
|
|
122
|
+
return [text];
|
|
123
|
+
// Sentence-ish units, each carrying its trailing whitespace/newlines.
|
|
124
|
+
const units = text.match(/[^.!?。!?\n]*(?:[.!?。!?]+["'”’)\]]*|\n|$)\s*/g) ?? [text];
|
|
125
|
+
const pieces = [];
|
|
126
|
+
for (const unit of units) {
|
|
127
|
+
if (!unit)
|
|
128
|
+
continue;
|
|
129
|
+
let rest = unit;
|
|
130
|
+
while (rest.length > max) {
|
|
131
|
+
const cut = rest.lastIndexOf(" ", max);
|
|
132
|
+
const at = cut > max / 2 ? cut + 1 : max;
|
|
133
|
+
pieces.push(rest.slice(0, at));
|
|
134
|
+
rest = rest.slice(at);
|
|
135
|
+
}
|
|
136
|
+
if (rest)
|
|
137
|
+
pieces.push(rest);
|
|
138
|
+
}
|
|
139
|
+
const chunks = [];
|
|
140
|
+
let cur = "";
|
|
141
|
+
for (const p of pieces) {
|
|
142
|
+
if (cur && cur.length + p.length > max) {
|
|
143
|
+
chunks.push(cur);
|
|
144
|
+
cur = "";
|
|
145
|
+
}
|
|
146
|
+
cur += p;
|
|
147
|
+
}
|
|
148
|
+
if (cur)
|
|
149
|
+
chunks.push(cur);
|
|
150
|
+
return chunks;
|
|
151
|
+
}
|
|
152
|
+
/** Runs `fn` over `items` with at most `limit` in flight; preserves order. */
|
|
153
|
+
async function mapWithConcurrency(items, limit, fn) {
|
|
154
|
+
const out = new Array(items.length);
|
|
155
|
+
let next = 0;
|
|
156
|
+
const worker = async () => {
|
|
157
|
+
for (let i = next++; i < items.length; i = next++) {
|
|
158
|
+
out[i] = await fn(items[i]);
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
await Promise.all(Array.from({ length: Math.min(limit, items.length) }, worker));
|
|
162
|
+
return out;
|
|
163
|
+
}
|
|
93
164
|
// gpt-4o-mini: cheap (~$0.15/1M in, $0.60/1M out → fractions of a cent per
|
|
94
165
|
// prompt), reliable, and independent of the Google video quota. Swap here if a
|
|
95
166
|
// cheaper effective model becomes available.
|
|
@@ -105,7 +176,7 @@ function languageLabel(code) {
|
|
|
105
176
|
async function callPrimaryTranslate(text, from, to, version) {
|
|
106
177
|
const res = await axios_1.default.post(`${PRIMARY_BASE}/translate`, { text, from, to, version }, {
|
|
107
178
|
headers: { "internal-key": process.env.TRANSLATION_SERVICE_KEY || "" },
|
|
108
|
-
timeout:
|
|
179
|
+
timeout: primaryTimeoutFor(text),
|
|
109
180
|
});
|
|
110
181
|
const translated = res.data?.translated;
|
|
111
182
|
if (typeof translated !== "string" || !translated.length) {
|
|
@@ -130,12 +201,21 @@ async function withTimeout(promise, ms, label) {
|
|
|
130
201
|
clearTimeout(timer);
|
|
131
202
|
}
|
|
132
203
|
}
|
|
133
|
-
/**
|
|
134
|
-
*
|
|
135
|
-
*
|
|
136
|
-
|
|
204
|
+
/** Lazy-loads the provider factory so this module stays light (utils/helpers
|
|
205
|
+
* re-exports it) and to avoid an import cycle with the aiGen layer.
|
|
206
|
+
*
|
|
207
|
+
* 2026-09-28: the retry loops await this BEFORE starting the per-attempt
|
|
208
|
+
* timer. The import pulls in the whole provider graph, and on a cold or busy
|
|
209
|
+
* api instance (concurrency 80) that alone could burn most of an 8s attempt —
|
|
210
|
+
* prod logged both attempts "timed out after 8000ms" (kk→en) while OpenAI
|
|
211
|
+
* itself answers the same prompt in ~2-4s. */
|
|
212
|
+
async function loadFallbackService() {
|
|
137
213
|
const { getAiGenProviderService } = await Promise.resolve().then(() => __importStar(require("../aiGen/aiGenFactory.service")));
|
|
138
|
-
|
|
214
|
+
return getAiGenProviderService(FALLBACK_MODEL);
|
|
215
|
+
}
|
|
216
|
+
/** One un-retried LLM translate attempt. */
|
|
217
|
+
async function callLlmTranslateOnce(text, from, to) {
|
|
218
|
+
const service = await loadFallbackService();
|
|
139
219
|
const target = languageLabel(to);
|
|
140
220
|
const system = `You are a professional translation engine. Translate the user's text into ${target}. ` +
|
|
141
221
|
`Preserve meaning, tone, names, numbers, hashtags, emojis and line breaks. ` +
|
|
@@ -158,10 +238,11 @@ async function callLlmTranslateOnce(text, from, to) {
|
|
|
158
238
|
/** FALLBACK: translate via a cheap LLM, with a real retry — see the
|
|
159
239
|
* FALLBACK_ATTEMPT_TIMEOUT_MS comment above for why one shot wasn't enough. */
|
|
160
240
|
async function callLlmTranslate(text, from, to) {
|
|
241
|
+
await loadFallbackService(); // outside the timer — see loadFallbackService
|
|
161
242
|
let lastErr;
|
|
162
243
|
for (let attempt = 1; attempt <= FALLBACK_MAX_ATTEMPTS; attempt++) {
|
|
163
244
|
try {
|
|
164
|
-
return await withTimeout(callLlmTranslateOnce(text, from, to),
|
|
245
|
+
return await withTimeout(callLlmTranslateOnce(text, from, to), fallbackTimeoutFor(text), "LLM fallback");
|
|
165
246
|
}
|
|
166
247
|
catch (err) {
|
|
167
248
|
lastErr = err;
|
|
@@ -170,13 +251,33 @@ async function callLlmTranslate(text, from, to) {
|
|
|
170
251
|
throw lastErr;
|
|
171
252
|
}
|
|
172
253
|
/**
|
|
173
|
-
* Translate `text` from → to (default English).
|
|
174
|
-
*
|
|
175
|
-
*
|
|
254
|
+
* Translate `text` from → to (default English). Long text is split into
|
|
255
|
+
* chunks translated in parallel (see CHUNK_MAX_CHARS); each chunk goes
|
|
256
|
+
* primary CF first (with a quick retry), then a cheap LLM. Throws
|
|
257
|
+
* Error(TRANSLATION_FAILED) only if BOTH layers fail for some chunk; `.cause`
|
|
258
|
+
* carries the last error.
|
|
176
259
|
*/
|
|
177
260
|
async function translate(text, from, to = types_1.ELANGUAGE_CODE.en, version = "v2") {
|
|
178
261
|
if (!text || !text.trim())
|
|
179
262
|
return text;
|
|
263
|
+
const chunks = splitForTranslation(text);
|
|
264
|
+
if (chunks.length === 1)
|
|
265
|
+
return translateChunk(text, from, to, version);
|
|
266
|
+
const translated = await mapWithConcurrency(chunks, CHUNK_CONCURRENCY, async (chunk) => {
|
|
267
|
+
// Translate the trimmed core and re-attach the chunk's own boundary
|
|
268
|
+
// whitespace — both layers trim, which would otherwise glue sentences
|
|
269
|
+
// together or drop paragraph breaks at chunk seams.
|
|
270
|
+
const lead = chunk.match(/^\s*/)?.[0] ?? "";
|
|
271
|
+
const trail = chunk.match(/\s*$/)?.[0] ?? "";
|
|
272
|
+
const core = chunk.trim();
|
|
273
|
+
if (!core)
|
|
274
|
+
return chunk;
|
|
275
|
+
return lead + (await translateChunk(core, from, to, version)).trim() + trail;
|
|
276
|
+
});
|
|
277
|
+
return translated.join("");
|
|
278
|
+
}
|
|
279
|
+
/** One chunk through primary → LLM fallback. */
|
|
280
|
+
async function translateChunk(text, from, to, version) {
|
|
180
281
|
// ── Layer 1: primary Cloud Function ──────────────────────────────────────
|
|
181
282
|
let primaryErr;
|
|
182
283
|
for (let attempt = 1; attempt <= PRIMARY_MAX_ATTEMPTS; attempt++) {
|
|
@@ -216,8 +317,7 @@ async function translate(text, from, to = types_1.ELANGUAGE_CODE.en, version = "
|
|
|
216
317
|
}
|
|
217
318
|
/** One un-retried LLM detect attempt. */
|
|
218
319
|
async function callLlmDetectOnce(text) {
|
|
219
|
-
const
|
|
220
|
-
const service = getAiGenProviderService(FALLBACK_MODEL);
|
|
320
|
+
const service = await loadFallbackService();
|
|
221
321
|
const system = "You are a language identification engine. Reply with ONLY the ISO 639-1 " +
|
|
222
322
|
"code of the language the user's text is written in — two lowercase " +
|
|
223
323
|
'letters, nothing else (e.g. "es", "ja", "ar"). Use "zh-cn" or "zh-tw" ' +
|
|
@@ -248,6 +348,7 @@ async function callLlmDetectOnce(text) {
|
|
|
248
348
|
* "default to en" path below — hence the same per-attempt bound as translate.
|
|
249
349
|
*/
|
|
250
350
|
async function callLlmDetect(text) {
|
|
351
|
+
await loadFallbackService(); // outside the timer — see loadFallbackService
|
|
251
352
|
let lastErr;
|
|
252
353
|
for (let attempt = 1; attempt <= FALLBACK_MAX_ATTEMPTS; attempt++) {
|
|
253
354
|
try {
|