@sogni-ai/sogni-intelligence-client 2.2.0 → 2.2.1

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.
@@ -3006,8 +3006,13 @@ function applyStoryboardPlanningLayoutContract(fallback, contract, frameCount, u
3006
3006
  ?? cellAspectRatio
3007
3007
  ?? fallback.targetVideoAspectRatio;
3008
3008
  const layout = describeStoryboardLayout(boardAspectRatio, cellAspectRatio, frameCount);
3009
- const boardDimensions = contractOwnsCanvas
3009
+ const contractBoardDimensions = contractOwnsCanvas
3010
3010
  ? normalizeStoryboardBoardDimensions(layoutContract.boardDimensions)
3011
+ : null;
3012
+ const boardDimensions = contractOwnsCanvas
3013
+ ? (storyboardBoardDimensionsMatchAspect(contractBoardDimensions, boardAspectRatio)
3014
+ ? contractBoardDimensions
3015
+ : null)
3011
3016
  ?? (userDefinedCanvas ? fallback.boardDimensions : undefined)
3012
3017
  : fallback.boardDimensions;
3013
3018
  return {
@@ -3018,6 +3023,27 @@ function applyStoryboardPlanningLayoutContract(fallback, contract, frameCount, u
3018
3023
  ...(boardDimensions ? { boardDimensions } : {}),
3019
3024
  };
3020
3025
  }
3026
+ function storyboardBoardDimensionsMatchAspect(boardDimensions, boardAspectRatio) {
3027
+ if (!boardDimensions)
3028
+ return false;
3029
+ const match = boardDimensions.match(/^(\d+)x(\d+)$/i);
3030
+ if (!match)
3031
+ return false;
3032
+ const width = Number(match[1]);
3033
+ const height = Number(match[2]);
3034
+ if (!Number.isFinite(width) || !Number.isFinite(height) || width <= 0 || height <= 0)
3035
+ return false;
3036
+ const normalized = normalizeAspectRatio(boardAspectRatio);
3037
+ const targetPair = normalized ? parseAspectRatioPair(normalized) : null;
3038
+ if (!targetPair)
3039
+ return true;
3040
+ const targetRatio = targetPair.width / targetPair.height;
3041
+ const actualRatio = width / height;
3042
+ if (!Number.isFinite(targetRatio) || targetRatio <= 0)
3043
+ return true;
3044
+ const ratioError = Math.abs(actualRatio - targetRatio) / targetRatio;
3045
+ return ratioError <= 0.1;
3046
+ }
3021
3047
  export function inferStoryboardLayoutSpec(userIntentText, frameCount, planningContract) {
3022
3048
  const planningLayout = planningContract?.layout;
3023
3049
  const userDefinedCanvas = typeof planningLayout?.storyboardCanvasSpecifiedByUser === 'boolean'
@@ -3731,7 +3757,8 @@ function extractStoryboardField(section, labels) {
3731
3757
  function removeStoryboardTimingText(value) {
3732
3758
  return value
3733
3759
  .replace(/\b\d{1,2}:\d{2}(?:\.\d+)?\s*(?:-|to|\u2013|\u2014)\s*\d{1,2}:\d{2}(?:\.\d+)?\b/gi, ' ')
3734
- .replace(/\b\d{1,3}(?:\.\d+)?\s*(?:s|sec|secs|seconds?)?\s*(?:-|to|\u2013|\u2014)\s*\d{1,3}(?:\.\d+)?\s*(?:s|sec|secs|seconds?)?\b/gi, ' ')
3760
+ .replace(/\b\d{1,3}(?:\.\d+)?\s*(?:s|sec|secs|seconds?)\s*(?:-|to|\u2013|\u2014)\s*\d{1,3}(?:\.\d+)?\s*(?:s|sec|secs|seconds?)\b/gi, ' ')
3761
+ .replace(/\b\d{1,3}(?:\.\d+)?(?:-|\u2013|\u2014)\d{1,3}(?:\.\d+)?\s*(?:s|sec|secs|seconds?)\b/gi, ' ')
3735
3762
  .replace(/\(\s*\)|\[\s*\]/g, ' ')
3736
3763
  .replace(/\s*[|]\s*/g, ' ')
3737
3764
  .replace(/^[-:.\s|]+|[-:.\s|]+$/g, ' ')
@@ -3805,20 +3832,29 @@ function parseStoryboardTimeValue(value) {
3805
3832
  return Number.isFinite(numeric) ? numeric : null;
3806
3833
  }
3807
3834
  function extractStoryboardTiming(text) {
3808
- const match = text.match(/(\d{1,2}:\d{1,2}(?:\.\d+)?|\d{1,3}(?:\.\d+)?)\s*(?:s|sec|secs|seconds?)?\s*(?:-|to|\u2013|\u2014)\s*(\d{1,2}:\d{1,2}(?:\.\d+)?|\d{1,3}(?:\.\d+)?)\s*(?:s|sec|secs|seconds?)?/i);
3809
- if (!match)
3810
- return null;
3811
- const startSec = parseStoryboardTimeValue(match[1]);
3812
- const endSec = parseStoryboardTimeValue(match[2]);
3813
- if (startSec === null || endSec === null)
3814
- return null;
3815
- if (!Number.isFinite(startSec) || !Number.isFinite(endSec) || endSec <= startSec)
3816
- return null;
3817
- return {
3818
- startSec,
3819
- endSec,
3820
- durationSec: Math.round((endSec - startSec) * 100) / 100,
3821
- };
3835
+ const patterns = [
3836
+ /(\d{1,2}:\d{1,2}(?:\.\d+)?)\s*(?:-|to|\u2013|\u2014)\s*(\d{1,2}:\d{1,2}(?:\.\d+)?)/i,
3837
+ /(\d{1,3}(?:\.\d+)?)\s*(?:s|sec|secs|seconds?)\s*(?:-|to|\u2013|\u2014)\s*(\d{1,3}(?:\.\d+)?)\s*(?:s|sec|secs|seconds?)/i,
3838
+ /(\d{1,3}(?:\.\d+)?)(?:-|\u2013|\u2014)(\d{1,3}(?:\.\d+)?)\s*(?:s|sec|secs|seconds?)/i,
3839
+ /(\d{1,2}:\d{1,2}(?:\.\d+)?|\d{1,3}(?:\.\d+)?)\s*(?:s|sec|secs|seconds?)?\s*(?:-|to|\u2013|\u2014)\s*(\d{1,2}:\d{1,2}(?:\.\d+)?|\d{1,3}(?:\.\d+)?)\s*(?:s|sec|secs|seconds?)?/i,
3840
+ ];
3841
+ for (const pattern of patterns) {
3842
+ const match = text.match(pattern);
3843
+ if (!match)
3844
+ continue;
3845
+ const startSec = parseStoryboardTimeValue(match[1]);
3846
+ const endSec = parseStoryboardTimeValue(match[2]);
3847
+ if (startSec === null || endSec === null)
3848
+ continue;
3849
+ if (!Number.isFinite(startSec) || !Number.isFinite(endSec) || endSec <= startSec)
3850
+ continue;
3851
+ return {
3852
+ startSec,
3853
+ endSec,
3854
+ durationSec: Math.round((endSec - startSec) * 100) / 100,
3855
+ };
3856
+ }
3857
+ return null;
3822
3858
  }
3823
3859
  function extractStoryboardTimingMarker(text) {
3824
3860
  const match = text.match(/(\d{1,2}:\d{1,2}(?:\.\d+)?|\d{1,3}(?:\.\d+)?)\s*(?:s|sec|secs|seconds?)?\s*(?:-|to|\u2013|\u2014)\s*(\d{1,2}:\d{1,2}(?:\.\d+)?|\d{1,3}(?:\.\d+)?)\s*(?:s|sec|secs|seconds?)?/i);