@sogni-ai/sogni-intelligence-client 3.0.4 → 3.0.6
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/dist/billing/spendGate.d.ts.map +1 -1
- package/dist/billing/spendGate.js.map +1 -1
- package/dist/contracts/data/promptContracts.d.ts.map +1 -1
- package/dist/contracts/data/promptContracts.js +4 -1
- package/dist/contracts/data/promptContracts.js.map +1 -1
- package/dist/events/runEvent.d.ts.map +1 -1
- package/dist/events/runEvent.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -1
- package/dist/index.js.map +1 -1
- package/dist/public-skill-runtime/index.d.ts.map +1 -1
- package/dist/public-skill-runtime/index.js +143 -6
- package/dist/public-skill-runtime/index.js.map +1 -1
- package/dist/workflows/index.d.ts +2 -2
- package/dist/workflows/index.d.ts.map +1 -1
- package/dist/workflows/index.js +13 -1
- package/dist/workflows/index.js.map +1 -1
- package/dist/workflows/primitives/sanitizer.d.ts +21 -0
- package/dist/workflows/primitives/sanitizer.d.ts.map +1 -1
- package/dist/workflows/primitives/sanitizer.js +68 -3
- package/dist/workflows/primitives/sanitizer.js.map +1 -1
- package/dist-esm/billing/spendGate.js.map +1 -1
- package/dist-esm/contracts/data/promptContracts.js +4 -1
- package/dist-esm/contracts/data/promptContracts.js.map +1 -1
- package/dist-esm/events/runEvent.js.map +1 -1
- package/dist-esm/index.js +1 -1
- package/dist-esm/index.js.map +1 -1
- package/dist-esm/public-skill-runtime/index.js +143 -6
- package/dist-esm/public-skill-runtime/index.js.map +1 -1
- package/dist-esm/workflows/index.js +1 -1
- package/dist-esm/workflows/index.js.map +1 -1
- package/dist-esm/workflows/primitives/sanitizer.js +67 -2
- package/dist-esm/workflows/primitives/sanitizer.js.map +1 -1
- package/package.json +7 -1
|
@@ -4600,6 +4600,118 @@ function splitStoryboardSections(text) {
|
|
|
4600
4600
|
return inlineSections;
|
|
4601
4601
|
return sectionHeadings.length > 0 ? sectionHeadings : tableSections;
|
|
4602
4602
|
}
|
|
4603
|
+
function extractPlainNarrationScriptText(text) {
|
|
4604
|
+
const source = text.trim();
|
|
4605
|
+
if (!source)
|
|
4606
|
+
return '';
|
|
4607
|
+
const markers = Array.from(source.matchAll(/^\s*(?:#{1,6}\s*)?(?:voice[-\s]?over\s+|narration\s+)?script\s*:\s*$/gim));
|
|
4608
|
+
const marker = markers[markers.length - 1];
|
|
4609
|
+
if (!marker || marker.index === undefined)
|
|
4610
|
+
return '';
|
|
4611
|
+
const body = source.slice(marker.index + marker[0].length).trim();
|
|
4612
|
+
return body
|
|
4613
|
+
.split(/\r?\n/)
|
|
4614
|
+
.map(line => stripStoryboardMarkup(line).trim())
|
|
4615
|
+
.filter(Boolean)
|
|
4616
|
+
.join('\n\n')
|
|
4617
|
+
.trim();
|
|
4618
|
+
}
|
|
4619
|
+
function splitPlainNarrationPhrases(text) {
|
|
4620
|
+
const normalized = text
|
|
4621
|
+
.replace(/\s+/g, ' ')
|
|
4622
|
+
.trim();
|
|
4623
|
+
if (!normalized)
|
|
4624
|
+
return [];
|
|
4625
|
+
const sentenceMatches = normalized.match(/[^.!?]+[.!?]+(?:["')\]]+)?|[^.!?]+$/g) ?? [normalized];
|
|
4626
|
+
return sentenceMatches
|
|
4627
|
+
.flatMap(sentence => sentence
|
|
4628
|
+
.split(/\s*(?:;|:\s+|,\s+(?=(?:and|but|so|whether|from|across|under|while|as)\b))\s*/i)
|
|
4629
|
+
.map(part => compactStoryboardLine(part)))
|
|
4630
|
+
.filter(part => countWords(part) > 0);
|
|
4631
|
+
}
|
|
4632
|
+
function splitPhraseAtWordMidpoint(value) {
|
|
4633
|
+
const words = value.match(/\S+/g) ?? [];
|
|
4634
|
+
if (words.length < 8)
|
|
4635
|
+
return null;
|
|
4636
|
+
const midpoint = Math.floor(words.length / 2);
|
|
4637
|
+
const left = words.slice(0, midpoint).join(' ').trim();
|
|
4638
|
+
const right = words.slice(midpoint).join(' ').trim();
|
|
4639
|
+
return left && right ? [left, right] : null;
|
|
4640
|
+
}
|
|
4641
|
+
function normalizeNarrationSegmentCount(phrases, frameCount) {
|
|
4642
|
+
if (frameCount <= 0)
|
|
4643
|
+
return [];
|
|
4644
|
+
let segments = phrases.slice();
|
|
4645
|
+
while (segments.length < frameCount) {
|
|
4646
|
+
let longestIndex = -1;
|
|
4647
|
+
let longestCount = 0;
|
|
4648
|
+
for (let index = 0; index < segments.length; index += 1) {
|
|
4649
|
+
const words = countWords(segments[index]);
|
|
4650
|
+
if (words > longestCount) {
|
|
4651
|
+
longestCount = words;
|
|
4652
|
+
longestIndex = index;
|
|
4653
|
+
}
|
|
4654
|
+
}
|
|
4655
|
+
if (longestIndex < 0)
|
|
4656
|
+
break;
|
|
4657
|
+
const split = splitPhraseAtWordMidpoint(segments[longestIndex]);
|
|
4658
|
+
if (!split)
|
|
4659
|
+
break;
|
|
4660
|
+
segments.splice(longestIndex, 1, split[0], split[1]);
|
|
4661
|
+
}
|
|
4662
|
+
if (segments.length <= frameCount)
|
|
4663
|
+
return segments;
|
|
4664
|
+
const merged = [];
|
|
4665
|
+
for (let index = 0; index < frameCount; index += 1) {
|
|
4666
|
+
const start = Math.floor(index * segments.length / frameCount);
|
|
4667
|
+
const end = Math.floor((index + 1) * segments.length / frameCount);
|
|
4668
|
+
const chunk = segments.slice(start, Math.max(start + 1, end)).join(' ');
|
|
4669
|
+
if (chunk.trim())
|
|
4670
|
+
merged.push(chunk.trim());
|
|
4671
|
+
}
|
|
4672
|
+
return merged;
|
|
4673
|
+
}
|
|
4674
|
+
function titleFromNarrationSegment(segment, index) {
|
|
4675
|
+
const words = compactStoryboardLine(segment)
|
|
4676
|
+
.replace(/["'()]/g, '')
|
|
4677
|
+
.split(/\s+/)
|
|
4678
|
+
.filter(Boolean)
|
|
4679
|
+
.slice(0, 6)
|
|
4680
|
+
.join(' ');
|
|
4681
|
+
return words || `Narration Beat ${index + 1}`;
|
|
4682
|
+
}
|
|
4683
|
+
function synthesizeStoryboardSectionsFromPlainNarration(sourceText, frameCount, references) {
|
|
4684
|
+
const script = extractPlainNarrationScriptText(sourceText);
|
|
4685
|
+
if (!script || countWords(script) < 8)
|
|
4686
|
+
return [];
|
|
4687
|
+
const phrases = splitPlainNarrationPhrases(script);
|
|
4688
|
+
const segments = normalizeNarrationSegmentCount(phrases, frameCount).slice(0, frameCount);
|
|
4689
|
+
if (segments.length === 0)
|
|
4690
|
+
return [];
|
|
4691
|
+
const referenceLine = references.length > 0
|
|
4692
|
+
? `Reference usage: ${references.map(ref => `Image ${ref.index ?? references.indexOf(ref) + 1}`).join(', ')}.`
|
|
4693
|
+
: '';
|
|
4694
|
+
const cameraPresets = [
|
|
4695
|
+
'Wide establishing composition that introduces the setting, subject, or idea named in the narration.',
|
|
4696
|
+
'Medium composition focused on the active subject, action, or relationship in this beat.',
|
|
4697
|
+
'Detail insert on concrete objects, gestures, text, environment, or visual evidence named in the narration.',
|
|
4698
|
+
'Tracking or reveal-style composition that moves the story into the next idea.',
|
|
4699
|
+
];
|
|
4700
|
+
return segments.map((segment, index) => ({
|
|
4701
|
+
number: index + 1,
|
|
4702
|
+
heading: `Scene ${index + 1} - ${titleFromNarrationSegment(segment, index)}`,
|
|
4703
|
+
body: [
|
|
4704
|
+
`Purpose: Translate narration beat ${index + 1} into a concrete ordered storyboard moment.`,
|
|
4705
|
+
`Visual/Action: Create a concrete visual moment using only this narration beat and the supplied references: ${segment}`,
|
|
4706
|
+
`Camera/Motion: ${cameraPresets[index % cameraPresets.length]}`,
|
|
4707
|
+
'Lighting/Style: Match the visual style, genre, and tone implied by the user request and supplied references; keep the frame cinematic but readable as a storyboard panel.',
|
|
4708
|
+
'Transition: Maintain continuity from the previous beat through subject, setting, gesture, camera direction, color, or motion when those cues are present.',
|
|
4709
|
+
`Dialogue/VO: ${segment}`,
|
|
4710
|
+
'Audio/SFX: Use only audio cues implied by the narration or user request; otherwise keep ambience or music generic and unobtrusive.',
|
|
4711
|
+
referenceLine,
|
|
4712
|
+
].filter(Boolean).join('\n'),
|
|
4713
|
+
}));
|
|
4714
|
+
}
|
|
4603
4715
|
function storyboardSectionsHavePreservableExplicitTiming(sections) {
|
|
4604
4716
|
return sections.length > 1
|
|
4605
4717
|
&& sections.some(section => extractStoryboardTiming(`${section.heading}\n${section.body}`) !== null);
|
|
@@ -5434,8 +5546,14 @@ export function buildStoryboardProject(options) {
|
|
|
5434
5546
|
: assistantDraftUndercounted || assistantApprovedDraftUndercounted
|
|
5435
5547
|
? []
|
|
5436
5548
|
: sourceSections;
|
|
5437
|
-
const
|
|
5438
|
-
|
|
5549
|
+
const selectedSectionsHaveExplicitTiming = sections.length > 0 && storyboardSectionsHavePreservableExplicitTiming(sections);
|
|
5550
|
+
const preserveAssistantExplicitTiming = options.promptAuthorship === 'assistant' && selectedSectionsHaveExplicitTiming;
|
|
5551
|
+
const synthesizedSections = sections.length === 0
|
|
5552
|
+
? synthesizeStoryboardSectionsFromPlainNarration(`${sourceText}\n\n${narrativeUserIntentText}`, options.frameCount, references)
|
|
5553
|
+
: [];
|
|
5554
|
+
const storyboardSections = sections.length > 0 ? sections : synthesizedSections;
|
|
5555
|
+
const parsedScenes = storyboardSections.length > 0
|
|
5556
|
+
? storyboardSections.map((section) => {
|
|
5439
5557
|
return buildSceneFromSection(section, references, null, storyboardScenePlanningContractForIndex(options.planningContract, section.number));
|
|
5440
5558
|
})
|
|
5441
5559
|
: [];
|
|
@@ -5445,12 +5563,17 @@ export function buildStoryboardProject(options) {
|
|
|
5445
5563
|
}));
|
|
5446
5564
|
const timingNormalizedScenes = normalizeAssistantStoryboardSceneTiming(scenes, durationSec, options.promptAuthorship);
|
|
5447
5565
|
const dialogueAlignment = alignAssistantStoryboardDialogueWithUserSource(timingNormalizedScenes, userIntentText, options.promptAuthorship);
|
|
5448
|
-
const
|
|
5566
|
+
const canPreserveAssistantExplicitTiming = preserveAssistantExplicitTiming && !dialogueAlignment.shouldRetime;
|
|
5567
|
+
const dialogueTimedScenes = (!canPreserveAssistantExplicitTiming
|
|
5568
|
+
&& (options.promptAuthorship === 'assistant' || dialogueAlignment.shouldRetime))
|
|
5449
5569
|
? retimeStoryboardScenesForDialogue(dialogueAlignment.scenes, durationSec)
|
|
5450
5570
|
: dialogueAlignment.scenes;
|
|
5451
5571
|
const userConstraintSource = buildStoryboardUserConstraintSource(narrativeUserIntentText, cleanStoryboardNarrativeSourceText(primarySourceBrief), options);
|
|
5452
5572
|
const { mustIncludeText, endCardText } = storyboardRequiredTextForProject(options, userConstraintSource, dialogueTimedScenes);
|
|
5453
|
-
const
|
|
5573
|
+
const scenesWithEndCardText = applyStoryboardEndCardTextToScenes(dialogueTimedScenes, endCardText);
|
|
5574
|
+
const normalizedScenes = canPreserveAssistantExplicitTiming
|
|
5575
|
+
? scenesWithEndCardText
|
|
5576
|
+
: retimeStoryboardScenesForDialogue(scenesWithEndCardText, durationSec);
|
|
5454
5577
|
const voiceLines = assignVoiceLinesToScenes(normalizedScenes, sourceText);
|
|
5455
5578
|
const storySpineFallback = approvedScriptContext
|
|
5456
5579
|
|| (options.promptAuthorship === 'assistant' ? narrativeUserIntentText : cleanStoryboardNarrativeSourceText(primarySourceBrief))
|
|
@@ -5480,8 +5603,8 @@ export function buildStoryboardProject(options) {
|
|
|
5480
5603
|
}
|
|
5481
5604
|
const recognizedSectionCount = directBeatMarkerCount > 0
|
|
5482
5605
|
? directBeatMarkerCount
|
|
5483
|
-
:
|
|
5484
|
-
?
|
|
5606
|
+
: storyboardSections.length > 0
|
|
5607
|
+
? storyboardSections.length
|
|
5485
5608
|
: Math.max(approvedSections.length, sourceSections.length);
|
|
5486
5609
|
return {
|
|
5487
5610
|
title: inferStoryboardTitle(allText),
|
|
@@ -5819,6 +5942,19 @@ function storyboardLayoutSpecFromProject(project, frameCount) {
|
|
|
5819
5942
|
...(project.boardDimensions ? { boardDimensions: project.boardDimensions } : {}),
|
|
5820
5943
|
};
|
|
5821
5944
|
}
|
|
5945
|
+
function compileStoryboardFrameGeometrySection(layout) {
|
|
5946
|
+
const cellOrientation = parseAspectRatioOrientation(layout.cellAspectRatio);
|
|
5947
|
+
if (cellOrientation === 'portrait') {
|
|
5948
|
+
return [
|
|
5949
|
+
'PORTRAIT FRAME GEOMETRY:',
|
|
5950
|
+
`Every cinematic artwork area inside a panel must remain a ${layout.cellAspectRatio} portrait video-frame rectangle matching the final video frame.`,
|
|
5951
|
+
`Inside every numbered scene slot, draw one identical upright ${layout.cellAspectRatio} video-frame rectangle whose height is visibly greater than its width.`,
|
|
5952
|
+
`Square cells violate the requested ${layout.targetVideoAspectRatio} final video format.`,
|
|
5953
|
+
'Unused grid slots must remain blank margin/notes space only; do not fill them with extra scenes, duplicate frames, or decorative artwork.',
|
|
5954
|
+
];
|
|
5955
|
+
}
|
|
5956
|
+
return [];
|
|
5957
|
+
}
|
|
5822
5958
|
export function compileVideoStoryboardImagePrompt(options) {
|
|
5823
5959
|
const rawUserIntentText = options.userIntentText.trim();
|
|
5824
5960
|
const userIntentText = canonicalStoryboardScriptContext(rawUserIntentText) || rawUserIntentText;
|
|
@@ -5852,6 +5988,7 @@ export function compileVideoStoryboardImagePrompt(options) {
|
|
|
5852
5988
|
`Each panel must contain one distinct ${layout.cellAspectRatio} cinematic video-frame rectangle with compact notes outside the frame.`,
|
|
5853
5989
|
'Keep scene numbers, timecodes, titles, dialogue/VO, audio notes, and production notes outside the video-frame rectangles.',
|
|
5854
5990
|
'Do not merge panels, create inset thumbnails, make panels square, or overlay storyboard metadata inside the artwork frames.',
|
|
5991
|
+
...compileStoryboardFrameGeometrySection(layout),
|
|
5855
5992
|
'',
|
|
5856
5993
|
...compileStoryboardReferenceSection(project),
|
|
5857
5994
|
'',
|