@sogni-ai/sogni-intelligence-client 3.22.3 → 3.22.5

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.
@@ -798,7 +798,7 @@ function compileStoryboardImagePromptFromProject(project) {
798
798
  project.endCard.logoUsage ? `Logo usage: ${project.endCard.logoUsage}` : '',
799
799
  '',
800
800
  'NEGATIVE / AVOID:',
801
- ...compileStoryboardAvoidSection(project.creativeBrief.concept).map(item => `- ${item}`),
801
+ ...compileStoryboardAvoidConstraints(project.creativeBrief.mustAvoid).map(item => `- ${item}`),
802
802
  ].join('\n');
803
803
  }
804
804
  function scenePromptText(scene) {
@@ -3847,13 +3847,24 @@ function compileStoryboardReferenceSection(project) {
3847
3847
  }
3848
3848
  function extractStoryboardAvoidConstraints(text) {
3849
3849
  const constraints = [];
3850
- for (const match of text.matchAll(/\b(?:avoid|do not include|don't include|without|less)\b[\s\S]{0,220}(?:\.|$)/gi)) {
3850
+ for (const match of text.matchAll(/\b(?:avoid|do not include|don't include|without|less)\b(?:(?!\b(?:avoid|do not include|don't include|without|less)\b)[^.!?\n]){0,220}/gi)) {
3851
3851
  const value = normalizeStoryboardAvoidConstraint(match[0]);
3852
- if (value && !constraints.includes(value))
3852
+ if (value
3853
+ && !storyboardAvoidConstraintIsWorkflowControl(value)
3854
+ && !constraints.includes(value)) {
3853
3855
  constraints.push(value);
3856
+ }
3854
3857
  }
3855
3858
  return constraints;
3856
3859
  }
3860
+ function storyboardAvoidConstraintIsWorkflowControl(value) {
3861
+ const interaction = /\b(?:approval|confirmation|review|feedback|permission|user\s+input|user\s+response)\b/i;
3862
+ if (!interaction.test(value))
3863
+ return false;
3864
+ const processAction = /\b(?:ask(?:ing)?|await(?:ing)?|wait(?:ing)?|pause|pausing|stop(?:ping)?|hold(?:ing)?|seek(?:ing)?|request(?:ing)?|require|requiring|check(?:ing)?|confirm(?:ing)?|approve|approving)\b/i;
3865
+ const workflowBoundary = /\b(?:workflow|stage|step|phase|round|generation|render|between|before|after|proceed|continu(?:e|ing))\b/i;
3866
+ return processAction.test(value) || workflowBoundary.test(value);
3867
+ }
3857
3868
  function normalizeStoryboardAvoidConstraint(value) {
3858
3869
  const cleaned = compactStoryboardLine(stripStoryboardMarkup(value))
3859
3870
  .replace(/^[*\-_\s]+|[*\-_\s]+$/g, '')
@@ -5679,10 +5690,11 @@ function inferStoryboardStorySpineFromHeading(text) {
5679
5690
  }
5680
5691
  function inferStoryboardStorySpine(text, fallbackBrief) {
5681
5692
  const explicit = cleanStoryboardStorySpine(text.match(/\b(?:story\s+spine|narrative\s+spine|throughline|story\s+arc|creative\s+intent)\s*:\s*([^\n]{1,360})/i)?.[1] || '');
5682
- if (explicit)
5693
+ const generatedFallbackPrefix = 'One continuous progression from the source brief:';
5694
+ if (explicit && !explicit.startsWith(generatedFallbackPrefix))
5683
5695
  return explicit;
5684
5696
  const fromHeading = inferStoryboardStorySpineFromHeading(text);
5685
- if (fromHeading)
5697
+ if (fromHeading && !fromHeading.startsWith(generatedFallbackPrefix))
5686
5698
  return fromHeading;
5687
5699
  const compactFallback = sanitizeStoryboardExternalAudioReferences(truncateStoryboardText(cleanStoryboardNarrativeSourceText(fallbackBrief || text), 260));
5688
5700
  if (compactFallback) {
@@ -5690,6 +5702,17 @@ function inferStoryboardStorySpine(text, fallbackBrief) {
5690
5702
  }
5691
5703
  return 'A coherent sequence where every scene follows from the previous beat and supports the requested final video outcome.';
5692
5704
  }
5705
+ function inferStoryboardStorySpineFromScenes(scenes) {
5706
+ const beats = scenes
5707
+ .map(scene => meaningfulStoryboardPromptField(scene.purpose
5708
+ || scene.visual
5709
+ || scene.action
5710
+ || scene.title))
5711
+ .filter(Boolean);
5712
+ if (beats.length === 0)
5713
+ return '';
5714
+ return truncateStoryboardText(uniqueStoryboardStrings(beats).join(' -> '), 260);
5715
+ }
5693
5716
  function inferStoryboardProductFeatureMap(text, scenes) {
5694
5717
  const explicitLines = text
5695
5718
  .split(/\r?\n/)
@@ -5893,11 +5916,22 @@ export function buildStoryboardProject(options) {
5893
5916
  ? scenesWithEndCardText
5894
5917
  : retimeStoryboardScenesForDialogue(scenesWithEndCardText, durationSec);
5895
5918
  const voiceLines = assignVoiceLinesToScenes(normalizedScenes, sourceText);
5896
- const storySpineFallback = approvedScriptContext
5897
- || (options.promptAuthorship === 'assistant' ? narrativeUserIntentText : cleanStoryboardNarrativeSourceText(primarySourceBrief))
5919
+ const authoredStorySpineSections = approvedSections.length > 0
5920
+ ? approvedSections
5921
+ : sourceSections;
5922
+ const authoredStorySpineScenes = authoredStorySpineSections.map(section => buildSceneFromSection(section, references, null, storyboardScenePlanningContractForIndex(options.planningContract, section.number)));
5923
+ const structuredSceneStorySpine = inferStoryboardStorySpineFromScenes(authoredStorySpineScenes.length > 0 ? authoredStorySpineScenes : normalizedScenes);
5924
+ const assistantStorySpineSource = approvedScriptContext || sourceText;
5925
+ const storySpineFallback = (options.promptAuthorship === 'assistant'
5926
+ ? structuredSceneStorySpine
5927
+ || cleanStoryboardNarrativeSourceText(primarySourceBrief)
5928
+ || approvedScriptContext
5929
+ : approvedScriptContext || cleanStoryboardNarrativeSourceText(primarySourceBrief))
5898
5930
  || prompt
5899
5931
  || narrativeUserIntentText;
5900
- const storySpine = inferStoryboardStorySpine(allText, storySpineFallback);
5932
+ const storySpine = inferStoryboardStorySpine(options.promptAuthorship === 'assistant' && assistantStorySpineSource
5933
+ ? assistantStorySpineSource
5934
+ : allText, storySpineFallback);
5901
5935
  const productFeatureMap = inferStoryboardProductFeatureMap(allText, normalizedScenes);
5902
5936
  const beatMarkerScripts = [approvedScriptContext, sourceText];
5903
5937
  let directBeatMarkerCount = 0;
@@ -6102,13 +6136,13 @@ function compileStoryboardCriticalRequirements() {
6102
6136
  'Keep character, product, logo, and style references consistent with their assigned scenes.',
6103
6137
  ];
6104
6138
  }
6105
- function compileStoryboardAvoidSection(userIntentText) {
6139
+ function compileStoryboardAvoidConstraints(constraints) {
6106
6140
  const avoidLines = [
6107
6141
  'Avoid malformed text, misspelled brand words, inconsistent reference identities, missing scene cells, wrong timings, and mismatched board/cell aspect ratios.',
6108
6142
  'Avoid scene numbers, timing badges, timecodes, production tables, Dialogue/VO labels, Audio/SFX labels, or other production notes overlaid inside the video frame artwork.',
6109
6143
  'Avoid in-frame comic-book SFX/action text such as Whoosh!, Impact!, Boom!, Thud!, Slash!, Crack!, or Pop!; keep those words in the production notes only.',
6110
6144
  ];
6111
- for (const constraint of extractStoryboardAvoidConstraints(userIntentText)) {
6145
+ for (const constraint of constraints) {
6112
6146
  const normalized = constraint.replace(/[.]+$/g, '').trim();
6113
6147
  avoidLines.push(/^(?:avoid|without|less|do\s+not|don't)\b/i.test(normalized)
6114
6148
  ? `${normalized}.`
@@ -6116,6 +6150,9 @@ function compileStoryboardAvoidSection(userIntentText) {
6116
6150
  }
6117
6151
  return avoidLines;
6118
6152
  }
6153
+ function compileStoryboardAvoidSection(userIntentText) {
6154
+ return compileStoryboardAvoidConstraints(extractStoryboardAvoidConstraints(userIntentText));
6155
+ }
6119
6156
  function formatStoryboardSeconds(value) {
6120
6157
  return value === null ? 'unspecified' : `${Number(value.toFixed(2))}s`;
6121
6158
  }
@@ -6157,7 +6194,10 @@ function removeStoryboardMetadataLabelsFromPromptText(value, metadataLabels) {
6157
6194
  .filter(Boolean)
6158
6195
  .sort((a, b) => b.length - a.length);
6159
6196
  for (const label of aliases) {
6160
- cleaned = cleaned.replace(new RegExp(escapeStoryboardRegExp(label), 'gi'), '');
6197
+ const escaped = escapeStoryboardRegExp(label);
6198
+ const leadingBoundary = /^[\p{L}\p{N}_]/u.test(label) ? '(?<![\\p{L}\\p{N}_])' : '';
6199
+ const trailingBoundary = /[\p{L}\p{N}_]$/u.test(label) ? '(?![\\p{L}\\p{N}_])' : '';
6200
+ cleaned = cleaned.replace(new RegExp(`${leadingBoundary}${escaped}${trailingBoundary}`, 'giu'), '');
6161
6201
  }
6162
6202
  return compactStoryboardLine(cleaned)
6163
6203
  .replace(/\s+([,.;:])/g, '$1')