@nodaro/shared 2.5.0 → 2.8.0

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/index.cjs CHANGED
@@ -729,6 +729,44 @@ var IMAGE_MODELS = {
729
729
  useCases: ["upscale"],
730
730
  pricing: [{ identifier: "grok-upscale", credits: 25 }]
731
731
  },
732
+ // Grok Imagine Image 2.0 — t2i plus task-chained region editing. The edit
733
+ // and segment-map endpoints take a PRIOR grok-2 generation's task id (the
734
+ // job's `kieTaskId` output), not an image URL — same contract as
735
+ // grok-upscale (see TASK_CHAINED_EDIT_PROVIDERS in model-constants).
736
+ "grok-2": {
737
+ id: "grok-2",
738
+ kind: "image",
739
+ modes: ["t2i"],
740
+ family: "xAI",
741
+ label: "Grok Imagine 2",
742
+ series: "Grok",
743
+ description: "Grok Imagine Image 2.0 \u2014 expressive, high-contrast t2i. Generations chain into grok-2-segment (free named region masks) and grok-2-edit (region-targeted edits).",
744
+ useCases: ["stylized", "expressive", "general"],
745
+ aspectRatios: GROK_RATIOS,
746
+ pricing: [{ identifier: "grok-2", credits: 10 }]
747
+ },
748
+ "grok-2-edit": {
749
+ id: "grok-2-edit",
750
+ kind: "image",
751
+ modes: ["edit"],
752
+ family: "xAI",
753
+ label: "Grok Imagine 2 Edit",
754
+ series: "Grok",
755
+ description: "Prompt-edit a prior grok-2 generation by task id. Optional mask indexes (from grok-2-segment) restrict the edit to named regions.",
756
+ useCases: ["edit", "region-edit"],
757
+ pricing: [{ identifier: "grok-2-edit", credits: 10 }]
758
+ },
759
+ "grok-2-segment": {
760
+ id: "grok-2-segment",
761
+ kind: "image",
762
+ modes: ["edit"],
763
+ family: "xAI",
764
+ label: "Grok Imagine 2 Segment Map",
765
+ series: "Grok",
766
+ description: "FREE semantic segment map of a prior grok-2 generation \u2014 named region masks whose indexes feed grok-2-edit's region targeting.",
767
+ useCases: ["segmentation", "region-edit"],
768
+ pricing: [{ identifier: "grok-2-segment", credits: 0, note: "free" }]
769
+ },
732
770
  // ── Utilities ──
733
771
  "recraft-remove-bg": {
734
772
  id: "recraft-remove-bg",
@@ -1203,7 +1241,8 @@ var VIDEO_MODELS = {
1203
1241
  },
1204
1242
  // Seedance 2.5 — the next Seedance generation, not a tier of the 2.0 ladder.
1205
1243
  // Two levers differ from every 2.0 SKU and drive its own entries throughout:
1206
- // durations run to 30s (2.0 caps at 15s) and there is NO 1080p/4K tier.
1244
+ // durations run to 30s (2.0 caps at 15s) and there is NO 4K tier (1080p
1245
+ // arrived on KIE 2026-08-17 — probe-verified; 4k/2k/1440p still rejected).
1207
1246
  // Reference caps are also wider (30 images / 10 videos / 10 audio) — see
1208
1247
  // SEEDANCE_2_5_REF_LIMITS in model-constants.
1209
1248
  "seedance-2-5": {
@@ -1213,20 +1252,23 @@ var VIDEO_MODELS = {
1213
1252
  family: "Bytedance",
1214
1253
  label: "Seedance 2.5",
1215
1254
  series: "Seedance",
1216
- description: "Seedance 2.5 \u2014 up to 30s in one shot, native audio, wide multimodal references. 480p/720p.",
1255
+ description: "Seedance 2.5 \u2014 up to 30s in one shot, native audio, wide multimodal references. 480p/720p/1080p.",
1217
1256
  useCases: ["premium", "narrative", "long-form"],
1218
1257
  features: ["end-frame", "audio", "reference-image", "video-reference"],
1219
1258
  aspectRatios: VIDEO_RATIOS_SEEDANCE_2,
1220
1259
  durations: [4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30],
1221
- resolutions: ["480p", "720p"],
1260
+ resolutions: ["480p", "720p", "1080p"],
1222
1261
  pricing: [
1223
1262
  { identifier: "seedance-2-5", credits: 1260, note: "default 8s 720p \u2014 see :Ns:res variants for exact" },
1224
1263
  { identifier: "seedance-2-5:8s:480p", credits: 560, note: "8s 480p" },
1225
1264
  { identifier: "seedance-2-5:8s:720p", credits: 1260, note: "8s 720p" },
1265
+ { identifier: "seedance-2-5:8s:1080p", credits: 2280, note: "8s 1080p" },
1226
1266
  { identifier: "seedance-2-5:8s:480p-ref", credits: 340, note: "8s 480p with reference video" },
1227
1267
  { identifier: "seedance-2-5:8s:720p-ref", credits: 760, note: "8s 720p with reference video" },
1268
+ { identifier: "seedance-2-5:8s:1080p-ref", credits: 1370, note: "8s 1080p with reference video" },
1228
1269
  { identifier: "seedance-2-5:30s:480p", credits: 2100, note: "30s 480p (max)" },
1229
- { identifier: "seedance-2-5:30s:720p", credits: 4730, note: "30s 720p (max)" }
1270
+ { identifier: "seedance-2-5:30s:720p", credits: 4730, note: "30s 720p (max)" },
1271
+ { identifier: "seedance-2-5:30s:1080p", credits: 8550, note: "30s 1080p (max)" }
1230
1272
  ]
1231
1273
  },
1232
1274
  // ── Wan ──
@@ -2688,6 +2730,7 @@ var IMAGE_GEN_PROVIDERS = [
2688
2730
  "nano-banana-2",
2689
2731
  "nano-banana-2-lite",
2690
2732
  "grok",
2733
+ "grok-2",
2691
2734
  "gpt-image",
2692
2735
  "gpt-image-2",
2693
2736
  "imagen4",
@@ -2748,8 +2791,19 @@ var IMAGE_EDIT_PROVIDERS = [
2748
2791
  "topaz-image-upscale",
2749
2792
  // grok-upscale takes a prior Grok generation's task_id (NOT an image URL) —
2750
2793
  // see edit-image route for the taskId-vs-imageUrl branching.
2751
- "grok-upscale"
2794
+ "grok-upscale",
2795
+ // Grok Imagine 2 task-chained ops — same task_id contract as grok-upscale.
2796
+ // grok-2-edit: prompt edit of a prior grok-2 generation, optionally region-
2797
+ // targeted via mask indexes from grok-2-segment. grok-2-segment: FREE named
2798
+ // segment-mask map of a prior grok-2 generation.
2799
+ "grok-2-edit",
2800
+ "grok-2-segment"
2752
2801
  ];
2802
+ var TASK_CHAINED_EDIT_PROVIDERS = /* @__PURE__ */ new Set([
2803
+ "grok-upscale",
2804
+ "grok-2-edit",
2805
+ "grok-2-segment"
2806
+ ]);
2753
2807
  var MODIFY_IMAGE_PROVIDERS = [
2754
2808
  ...IMAGE_I2I_PROVIDERS,
2755
2809
  "nano-banana-edit"
@@ -3048,6 +3102,7 @@ var IMAGE_MASK_MODE = {
3048
3102
  "flux": "composite",
3049
3103
  "flux-flex": "composite",
3050
3104
  "grok": "composite",
3105
+ "grok-2": "composite",
3051
3106
  "imagen4": "composite",
3052
3107
  "imagen4-fast": "composite",
3053
3108
  "imagen4-ultra": "composite",
@@ -4698,6 +4753,16 @@ function buildChildrenByParent(nodes) {
4698
4753
  function isCollectInEdge(e) {
4699
4754
  return (e.targetHandle ?? COLLECT_IN_HANDLE) === COLLECT_IN_HANDLE;
4700
4755
  }
4756
+ function computeAggregateLanes(nodeId, wiredTypes, buckets, edges) {
4757
+ const present = new Set(wiredTypes);
4758
+ for (const t2 of presentTypes(buckets)) present.add(t2);
4759
+ for (const e of edges) {
4760
+ if (e.source !== nodeId) continue;
4761
+ const lane = parseGroupHandle(e.sourceHandle);
4762
+ if (lane) present.add(lane);
4763
+ }
4764
+ return AGGREGATEABLE_TYPES.filter((t2) => present.has(t2));
4765
+ }
4701
4766
 
4702
4767
  // src/llm-models.ts
4703
4768
  var LLM_REASONING_EFFORTS = ["none", "low", "medium", "high", "xhigh", "max"];
@@ -4753,6 +4818,30 @@ var LLM_MODELS = [
4753
4818
  // direct is the reliability fallback only.
4754
4819
  directGeminiModel: "gemini-3.6-flash"
4755
4820
  },
4821
+ {
4822
+ id: "gemini-3.7-flash",
4823
+ displayName: "Gemini 3.7 Flash",
4824
+ desc: "Newest fast Gemini, agentic-tuned",
4825
+ tier: "economy",
4826
+ kieFormat: "chat-completions",
4827
+ // KIE serves it on the OpenAI-compatible dialect under this slug
4828
+ // (docs.kie.ai/market/gemini/gemini-3-7-flash-openai.md) — same
4829
+ // chat-completions path shape as gemini-3.6-flash.
4830
+ kieSlugOrModel: "gemini-3-7-flash-openai",
4831
+ vendor: "google",
4832
+ structuredOutputMode: "kie-response-format",
4833
+ supportsImages: true,
4834
+ // Google's own cap is 65,536, but the field feeds BOTH lanes and the KIE
4835
+ // flash endpoints cap at 8192 (the measured 3.6 posture) — stay at the
4836
+ // KIE-safe intersection, same reasoning as `reasoningEfforts` below.
4837
+ maxOutputTokens: 8192,
4838
+ // KIE's 3.7 endpoint enumerates reasoning_effort low | high (verified
4839
+ // against its OpenAPI spec 2026-08-18), identical to 3.6.
4840
+ reasoningEfforts: ["low", "high"],
4841
+ // Assumed parity with 3.6 pending a live probe on the direct lane.
4842
+ directReasoningEfforts: ["none", "low", "medium", "high"],
4843
+ directGeminiModel: "gemini-3.7-flash"
4844
+ },
4756
4845
  {
4757
4846
  id: "claude-haiku-4.5",
4758
4847
  displayName: "Claude Haiku 4.5",
@@ -4915,7 +5004,35 @@ var LLM_MODELS = [
4915
5004
  reasoningEfforts: ["none", "low", "medium", "high", "xhigh", "max"],
4916
5005
  supportsTemperature: false
4917
5006
  },
4918
- // grok-4.5 deferred — KIE chat endpoint not yet live (2026-07-13); add entry + rate row + docs when it activates.
5007
+ {
5008
+ id: "grok-4.6",
5009
+ displayName: "Grok 4.6",
5010
+ desc: "xAI flagship, strong reasoning",
5011
+ tier: "standard",
5012
+ kieFormat: "responses",
5013
+ // KIE serves Grok on the responses dialect under its own family path —
5014
+ // grok/v1/responses, NOT codex/v1/responses (llm-client derives the path
5015
+ // from `vendor`). Live-verified end-to-end 2026-08-18: array `input`,
5016
+ // `developer` system role, `input_image` URL vision, `text.format`
5017
+ // json_schema enforcement, SSE `response.output_text.delta` stream, and
5018
+ // `credits_consumed` actual-cost capture. (grok-4.5 was deferred 2026-07-13
5019
+ // because none of this was live; 4.6 is its activation.)
5020
+ kieSlugOrModel: "grok-4-6",
5021
+ vendor: "xai",
5022
+ structuredOutputMode: "responses-json-schema",
5023
+ supportsImages: true,
5024
+ maxOutputTokens: 16384,
5025
+ // KIE's documented enum, each level live-verified (echoed back) 2026-08-18.
5026
+ // No `none`: the endpoint reasons unconditionally (see thinkingDefaultOn).
5027
+ reasoningEfforts: ["low", "medium", "high", "xhigh"],
5028
+ // Live-probed 2026-08-18: `temperature` is silently IGNORED (request echo
5029
+ // stays at the 0.7 default), so never send it — same treatment as GPT-5.5+.
5030
+ supportsTemperature: false,
5031
+ // Reasons with NO reasoning param sent (effort defaults to "low" server-side
5032
+ // — a trivial probe spent 169 of 170 output tokens on reasoning), so every
5033
+ // call needs output headroom, not just xhigh.
5034
+ thinkingDefaultOn: true
5035
+ },
4919
5036
  {
4920
5037
  id: "claude-sonnet-5",
4921
5038
  displayName: "Claude Sonnet 5",
@@ -4991,6 +5108,25 @@ var LLM_MODEL_IDS = LLM_MODELS.map((m) => m.id);
4991
5108
  var STRUCTURED_VISION_MODELS = LLM_MODELS.filter(
4992
5109
  (m) => m.supportsImages && m.structuredOutputMode != null
4993
5110
  );
5111
+ var LLM_VENDOR_ORDER = ["anthropic", "google", "openai", "xai"];
5112
+ var LLM_VENDOR_LABELS = {
5113
+ anthropic: "Anthropic",
5114
+ google: "Google",
5115
+ openai: "OpenAI",
5116
+ xai: "xAI"
5117
+ };
5118
+ var TIER_RANK = { economy: 0, standard: 1, premium: 2 };
5119
+ function groupLlmModelsByVendor(models = LLM_MODELS) {
5120
+ const groups = [];
5121
+ for (const vendor of LLM_VENDOR_ORDER) {
5122
+ const members = models.filter((m) => m.vendor === vendor).sort((a, b) => TIER_RANK[a.tier] - TIER_RANK[b.tier]);
5123
+ if (members.length > 0) groups.push({ vendor, label: LLM_VENDOR_LABELS[vendor], models: members });
5124
+ }
5125
+ return groups;
5126
+ }
5127
+ function orderedLlmModels(models = LLM_MODELS) {
5128
+ return groupLlmModelsByVendor(models).flatMap((g) => g.models);
5129
+ }
4994
5130
  function motionGraphicsFeature(engine) {
4995
5131
  return engine === "lottie" ? "motion-graphics-lottie" : "motion-graphics";
4996
5132
  }
@@ -5009,11 +5145,18 @@ var LLM_FEATURE_DEFAULTS = {
5009
5145
  "qa-check": "gemini-3.6-flash",
5010
5146
  "generate-script": "gemini-3.6-flash",
5011
5147
  "translate": "gemini-3.6-flash",
5012
- "image-critic": "claude-sonnet-4.6"
5148
+ "image-critic": "claude-sonnet-4.6",
5149
+ "pick-best-llm": "claude-sonnet-4.6"
5013
5150
  };
5014
5151
  var LLM_MODALITY_CAPS = {
5015
5152
  "gemini-3-flash": { image: true, video: true, audio: true },
5016
5153
  "gemini-3.6-flash": { image: true, video: true, audio: true },
5154
+ // gemini-3.7-flash is IMAGE-ONLY by DECISION, not omission: full video+audio
5155
+ // caps would auto-enroll it in VIDEO_ANALYSIS_LLM_MODELS (derived below) and
5156
+ // force a video-analysis tier + pricing decision that is deliberately
5157
+ // deferred while the smart-family A/B routes this model internally (#747).
5158
+ // Flip these two flags ONLY together with that VA-side decision.
5159
+ "gemini-3.7-flash": { image: true, video: false, audio: false },
5017
5160
  "gemini-3.1-pro": { image: true, video: true, audio: true },
5018
5161
  "claude-haiku-4.5": { image: true, video: false, audio: false },
5019
5162
  "claude-sonnet-4.6": { image: true, video: false, audio: false },
@@ -5024,6 +5167,7 @@ var LLM_MODALITY_CAPS = {
5024
5167
  "gpt-5.6-luna": { image: true, video: false, audio: false },
5025
5168
  "gpt-5.6-terra": { image: true, video: false, audio: false },
5026
5169
  "gpt-5.6-sol": { image: true, video: false, audio: false },
5170
+ "grok-4.6": { image: true, video: false, audio: false },
5027
5171
  "claude-sonnet-5": { image: true, video: false, audio: false },
5028
5172
  "claude-opus-4.8": { image: true, video: false, audio: false },
5029
5173
  "claude-opus-5": { image: true, video: false, audio: false },
@@ -7753,8 +7897,9 @@ var QUALITY_MAP = {
7753
7897
  "seedance-2": { field: "resolution", values: { low: "720p", mid: "1080p", high: "1080p" } },
7754
7898
  "seedance-2-fast": { field: "resolution", values: { low: "480p", mid: "720p", high: "720p" } },
7755
7899
  "seedance-2-mini": { field: "resolution", values: { low: "480p", mid: "720p", high: "720p" } },
7756
- // Seedance 2.5 tops out at 720p on KIE (1080p/4k probe-rejected 2026-08-08).
7757
- "seedance-2-5": { field: "resolution", values: { low: "480p", mid: "720p", high: "720p" } },
7900
+ // Seedance 2.5 spans 480p/720p/1080p on KIE (1080p accepted since the
7901
+ // 2026-08-17 re-probe; 4k still rejected), so each quality rung gets its own tier.
7902
+ "seedance-2-5": { field: "resolution", values: { low: "480p", mid: "720p", high: "1080p" } },
7758
7903
  "wan-2.7-i2v": { field: "resolution", values: { low: "720p", mid: "1080p", high: "1080p" } },
7759
7904
  "wan-2.7-t2v": { field: "resolution", values: { low: "720p", mid: "1080p", high: "1080p" } },
7760
7905
  "happyhorse": { field: "resolution", values: { low: "720p", mid: "1080p", high: "1080p" } },
@@ -11222,24 +11367,31 @@ function selectLoraRoutingForMentions(refs) {
11222
11367
  }
11223
11368
  var PICK_BEST_LLM_STRATEGY = {
11224
11369
  id: "pick-best-llm",
11225
- label: "Pick best (LLM judge)",
11226
- description: "Sonnet picks the best item against your criteria.",
11370
+ label: "AI picks the best",
11371
+ description: "AI compares every candidate against your criteria and picks one.",
11227
11372
  configSchema: zod.z.object({
11228
11373
  // Default to the sensible "best quality" criteria when omitted (matches
11229
11374
  // defaultConfig) so a reduce({strategyId:"pick-best-llm"}) call with no
11230
11375
  // criteria degrades gracefully instead of erroring. An explicit "" still
11231
11376
  // rejects via min(1).
11232
11377
  criteria: zod.z.string().min(1, "criteria cannot be empty").default("Pick the highest-quality result."),
11233
- inputKind: zod.z.enum(["text", "image-url"]).default("text")
11378
+ inputKind: zod.z.enum(["text", "image-url"]).default("text"),
11379
+ // The judge model, like every other LLM node (llmModel + LlmModelSelect).
11380
+ // Optional: omitted → LLM_FEATURE_DEFAULTS["pick-best-llm"]. Validated
11381
+ // against LLM_MODEL_IDS at the route (the registry can't import the model
11382
+ // list without a cycle), and its tier drives the credit price via
11383
+ // buildLlmCreditIdentifier — economy / standard / premium.
11384
+ llmModel: zod.z.string().optional()
11234
11385
  }),
11235
11386
  defaultConfig: { criteria: "Pick the highest-quality result.", inputKind: "text" },
11236
11387
  outputType: "text",
11237
- creditCostKey: "reduce:pick-best-llm"
11388
+ creditCostKey: "reduce:pick-best-llm",
11389
+ usesLlm: true
11238
11390
  };
11239
11391
  var CONCAT_STRATEGY = {
11240
11392
  id: "concat",
11241
- label: "Concatenate",
11242
- description: "Join all survivors with a separator.",
11393
+ label: "Join into one text",
11394
+ description: "Puts every candidate into a single text, one after another, with a separator between them.",
11243
11395
  configSchema: zod.z.object({ separator: zod.z.string().default("\n\n") }),
11244
11396
  defaultConfig: { separator: "\n\n" },
11245
11397
  outputType: "text",
@@ -11247,8 +11399,8 @@ var CONCAT_STRATEGY = {
11247
11399
  };
11248
11400
  var FIRST_NON_EMPTY_STRATEGY = {
11249
11401
  id: "first-non-empty",
11250
- label: "First non-empty",
11251
- description: "Return the first survivor (empty strings filtered).",
11402
+ label: "First that has content",
11403
+ description: "Takes the first candidate that is not empty and ignores the rest.",
11252
11404
  configSchema: zod.z.object({}),
11253
11405
  defaultConfig: {},
11254
11406
  outputType: "text",
@@ -11256,8 +11408,8 @@ var FIRST_NON_EMPTY_STRATEGY = {
11256
11408
  };
11257
11409
  var COUNT_STRATEGY = {
11258
11410
  id: "count",
11259
- label: "Count",
11260
- description: "Return how many survivors came through.",
11411
+ label: "Count them",
11412
+ description: "Outputs how many candidates arrived.",
11261
11413
  configSchema: zod.z.object({}),
11262
11414
  defaultConfig: {},
11263
11415
  outputType: "data",
@@ -11265,8 +11417,8 @@ var COUNT_STRATEGY = {
11265
11417
  };
11266
11418
  var VOTE_STRATEGY = {
11267
11419
  id: "vote",
11268
- label: "Majority vote",
11269
- description: "Return the most common survivor (ties \u2192 first).",
11420
+ label: "Most common answer",
11421
+ description: "Picks the candidate that appears most often (ties go to the first).",
11270
11422
  configSchema: zod.z.object({ caseSensitive: zod.z.boolean().default(false) }),
11271
11423
  defaultConfig: { caseSensitive: false },
11272
11424
  outputType: "text",
@@ -11274,8 +11426,8 @@ var VOTE_STRATEGY = {
11274
11426
  };
11275
11427
  var MERGE_JSON_STRATEGY = {
11276
11428
  id: "merge-json",
11277
- label: "Merge JSON",
11278
- description: "Parse each survivor as JSON and merge into one object.",
11429
+ label: "Merge JSON objects",
11430
+ description: "Reads every candidate as JSON and merges them into one object.",
11279
11431
  configSchema: zod.z.object({ strategy: zod.z.enum(["deep", "shallow"]).default("deep") }),
11280
11432
  defaultConfig: { strategy: "deep" },
11281
11433
  outputType: "data",
@@ -12700,10 +12852,21 @@ var ENTITY_IMAGE_HANDLE_TYPES = /* @__PURE__ */ new Set([
12700
12852
  "object",
12701
12853
  "creature"
12702
12854
  ]);
12855
+ var AGGREGATE_LANE_SOURCE_TYPES = /* @__PURE__ */ new Set(["group", "collect"]);
12856
+ var AGGREGATE_LANE_EFFECTIVE_TYPE = {
12857
+ "out-image": "upload-image",
12858
+ "out-video": "upload-video",
12859
+ "out-audio": "upload-audio",
12860
+ "out-text": "list"
12861
+ };
12703
12862
  function resolveEffectiveSourceType(rawSourceType, sourceHandleId) {
12704
12863
  if (sourceHandleId === "image" && ENTITY_IMAGE_HANDLE_TYPES.has(rawSourceType ?? "")) {
12705
12864
  return "upload-image";
12706
12865
  }
12866
+ if (AGGREGATE_LANE_SOURCE_TYPES.has(rawSourceType ?? "")) {
12867
+ const effective = AGGREGATE_LANE_EFFECTIVE_TYPE[sourceHandleId ?? ""];
12868
+ if (effective) return effective;
12869
+ }
12707
12870
  return rawSourceType ?? "";
12708
12871
  }
12709
12872
  function sourceRefKey(nodeId, sourceHandleId, rawSourceType) {
@@ -12788,6 +12951,8 @@ var VIDEO_ANALYSIS_VISUAL_EFFECTS = [
12788
12951
  ];
12789
12952
  var VIDEO_ANALYSIS_TRANSITIONS = ["cut", "fade", "dissolve", "wipe", "whip"];
12790
12953
  var VIDEO_ANALYSIS_SPEED_EFFECTS = ["slow-motion", "ramp-in", "ramp-out", "timelapse", "freeze", "reverse"];
12954
+ var VIDEO_ANALYSIS_TIMES_OF_DAY = ["dawn", "day", "dusk", "night", "ambiguous"];
12955
+ var VIDEO_ANALYSIS_STORY_JUMPS = ["continuous", "same-day", "another-day", "years-later", "unclear"];
12791
12956
  var clipLookSchema = zod.z.object({
12792
12957
  /**
12793
12958
  * The rendering MEDIUM — "live-action photoreal", "2D anime", "stop-motion
@@ -12912,6 +13077,12 @@ var windowSceneBase = zod.z.object({
12912
13077
  angle: zod.z.enum(VIDEO_ANALYSIS_SHOT_ANGLES).optional(),
12913
13078
  /** Time manipulation. Absent ⇒ normal speed. */
12914
13079
  speed: zod.z.enum(VIDEO_ANALYSIS_SPEED_EFFECTS).optional(),
13080
+ /** CHRONICLE TIME (2026-08-17) — see the consts' docstrings. Both optional:
13081
+ * absent on every pre-2.6.0 analysis, and legitimately absent when the
13082
+ * analyser cannot read the clock. Enum + optional keeps the window decode
13083
+ * grammar congruence-safe (no ints, no maxItems). */
13084
+ timeOfDay: zod.z.enum(VIDEO_ANALYSIS_TIMES_OF_DAY).optional(),
13085
+ storyJump: zod.z.enum(VIDEO_ANALYSIS_STORY_JUMPS).optional(),
12915
13086
  visual: zod.z.string().min(1),
12916
13087
  /**
12917
13088
  * Text burned into the PICTURE of this shot — titles, captions, lower-thirds,
@@ -13079,6 +13250,23 @@ function aspectRatioFromDims(w, h) {
13079
13250
  const g = gcd(Math.round(w), Math.round(h));
13080
13251
  return `${Math.round(w) / g}:${Math.round(h) / g}`;
13081
13252
  }
13253
+ var MUSIC_VOCAL_RE = /\b(?:lyrics?|sung|sings?|singing|vocals?|chorus|verse|rap(?:ping|ped)?|a cappella)\b/i;
13254
+ var MUSIC_VOCAL_QUOTE_RE = /["\u201c][^"\u201d]{6,}["\u201d]/;
13255
+ var MUSIC_NO_VOCAL_RE = /\b(?:no|without|non)[- ](?:vocals?|lyrics?|singing)\b|\binstrumental\b|\bwordless\b/i;
13256
+ function inferMusicVideo(analysis) {
13257
+ const scenes = analysis?.scenes ?? [];
13258
+ if (scenes.length < 4) return false;
13259
+ const musicLayers = (sc) => (sc.audio ?? []).filter((a) => a?.mode === "music");
13260
+ const withMusic = scenes.filter((sc) => musicLayers(sc).length > 0).length;
13261
+ if (withMusic / scenes.length < 0.8) return false;
13262
+ return scenes.some(
13263
+ (sc) => musicLayers(sc).some((a) => {
13264
+ const content = typeof a.content === "string" ? a.content : "";
13265
+ if (MUSIC_NO_VOCAL_RE.test(content)) return false;
13266
+ return MUSIC_VOCAL_RE.test(content) || MUSIC_VOCAL_QUOTE_RE.test(content);
13267
+ })
13268
+ );
13269
+ }
13082
13270
 
13083
13271
  // src/video-analysis-pricing.ts
13084
13272
  var VIDEO_ANALYSIS_DURATION_BUCKETS = [60, 180, 360, 600];
@@ -13181,6 +13369,7 @@ function clampSmartCutWindow(value) {
13181
13369
  exports.ACTIVE_SCENE_HELPERS = ACTIVE_SCENE_HELPERS;
13182
13370
  exports.ADVANCED_MODE_UNAVAILABLE_REASON = ADVANCED_MODE_UNAVAILABLE_REASON;
13183
13371
  exports.AGGREGATEABLE_TYPES = AGGREGATEABLE_TYPES;
13372
+ exports.AGGREGATE_LANE_SOURCE_TYPES = AGGREGATE_LANE_SOURCE_TYPES;
13184
13373
  exports.AI_AVATAR_DURATION_BUCKETS = AI_AVATAR_DURATION_BUCKETS;
13185
13374
  exports.AI_AVATAR_MAX_AUDIO_SEC = AI_AVATAR_MAX_AUDIO_SEC;
13186
13375
  exports.AI_AVATAR_MAX_DURATION_SEC = AI_AVATAR_MAX_DURATION_SEC;
@@ -13367,6 +13556,8 @@ exports.LLM_MODEL_IDS = LLM_MODEL_IDS;
13367
13556
  exports.LLM_REASONING_EFFORTS = LLM_REASONING_EFFORTS;
13368
13557
  exports.LLM_ROUTE_DEFAULTS = LLM_ROUTE_DEFAULTS;
13369
13558
  exports.LLM_TEXT_INPUT_MAX = LLM_TEXT_INPUT_MAX;
13559
+ exports.LLM_VENDOR_LABELS = LLM_VENDOR_LABELS;
13560
+ exports.LLM_VENDOR_ORDER = LLM_VENDOR_ORDER;
13370
13561
  exports.LOCATION_ASSET_TYPES = LOCATION_ASSET_TYPES;
13371
13562
  exports.LOCATION_ASSET_VARIANTS = LOCATION_ASSET_VARIANTS;
13372
13563
  exports.LOCATION_ATMOSPHERE_PROVIDERS = LOCATION_ATMOSPHERE_PROVIDERS;
@@ -13536,6 +13727,7 @@ exports.StoryboardCohesionCriticVerdictSchema = StoryboardCohesionCriticVerdictS
13536
13727
  exports.StyleDirectivesSchema = StyleDirectivesSchema;
13537
13728
  exports.SubGateNameSchema = SubGateNameSchema;
13538
13729
  exports.T2I_TO_I2I_VARIANT = T2I_TO_I2I_VARIANT;
13730
+ exports.TASK_CHAINED_EDIT_PROVIDERS = TASK_CHAINED_EDIT_PROVIDERS;
13539
13731
  exports.TEXT_TO_AUDIO_PROVIDERS = TEXT_TO_AUDIO_PROVIDERS;
13540
13732
  exports.TEXT_TO_VIDEO_PROVIDERS = TEXT_TO_VIDEO_PROVIDERS;
13541
13733
  exports.TIER_MAX_PIPELINE_COST_CREDITS = TIER_MAX_PIPELINE_COST_CREDITS;
@@ -13569,9 +13761,11 @@ exports.VIDEO_ANALYSIS_MAX_VARIATIONS = VIDEO_ANALYSIS_MAX_VARIATIONS;
13569
13761
  exports.VIDEO_ANALYSIS_MIXED_TIERS = VIDEO_ANALYSIS_MIXED_TIERS;
13570
13762
  exports.VIDEO_ANALYSIS_SHOT_ANGLES = VIDEO_ANALYSIS_SHOT_ANGLES;
13571
13763
  exports.VIDEO_ANALYSIS_SPEED_EFFECTS = VIDEO_ANALYSIS_SPEED_EFFECTS;
13764
+ exports.VIDEO_ANALYSIS_STORY_JUMPS = VIDEO_ANALYSIS_STORY_JUMPS;
13572
13765
  exports.VIDEO_ANALYSIS_TIERS = VIDEO_ANALYSIS_TIERS;
13573
13766
  exports.VIDEO_ANALYSIS_TIER_LABELS = VIDEO_ANALYSIS_TIER_LABELS;
13574
13767
  exports.VIDEO_ANALYSIS_TIER_ORDER = VIDEO_ANALYSIS_TIER_ORDER;
13768
+ exports.VIDEO_ANALYSIS_TIMES_OF_DAY = VIDEO_ANALYSIS_TIMES_OF_DAY;
13575
13769
  exports.VIDEO_ANALYSIS_TRANSITIONS = VIDEO_ANALYSIS_TRANSITIONS;
13576
13770
  exports.VIDEO_ANALYSIS_VARIATION_SLUGS = VIDEO_ANALYSIS_VARIATION_SLUGS;
13577
13771
  exports.VIDEO_ANALYSIS_VISUAL_EFFECTS = VIDEO_ANALYSIS_VISUAL_EFFECTS;
@@ -13666,6 +13860,7 @@ exports.clearVideoCriticMetadata = clearVideoCriticMetadata;
13666
13860
  exports.clipLookSchema = clipLookSchema;
13667
13861
  exports.collectAncestorRefs = collectAncestorRefs;
13668
13862
  exports.combineSameLabelRefs = combineSameLabelRefs;
13863
+ exports.computeAggregateLanes = computeAggregateLanes;
13669
13864
  exports.countRefModalityEdges = countRefModalityEdges;
13670
13865
  exports.creditRangesAll = creditRangesAll;
13671
13866
  exports.creditsToUsd = creditsToUsd;
@@ -13760,11 +13955,13 @@ exports.getWeapon = getWeapon;
13760
13955
  exports.getWeaponLabel = getWeaponLabel;
13761
13956
  exports.groupByFamily = groupByFamily;
13762
13957
  exports.groupHandleId = groupHandleId;
13958
+ exports.groupLlmModelsByVendor = groupLlmModelsByVendor;
13763
13959
  exports.hasContiguousSegmentDurations = hasContiguousSegmentDurations;
13764
13960
  exports.hasFeature = hasFeature;
13765
13961
  exports.hexToRgbaArray = hexToRgbaArray;
13766
13962
  exports.humanizeSlotSid = humanizeSlotSid;
13767
13963
  exports.imageReferenceLimit = imageReferenceLimit;
13964
+ exports.inferMusicVideo = inferMusicVideo;
13768
13965
  exports.isAggregateableType = isAggregateableType;
13769
13966
  exports.isCharacterAspectRatio = isCharacterAspectRatio;
13770
13967
  exports.isCollectInEdge = isCollectInEdge;
@@ -13817,6 +14014,7 @@ exports.normalizeModelInput = normalizeModelInput;
13817
14014
  exports.normalizeNodeModelParams = normalizeNodeModelParams;
13818
14015
  exports.normalizePinterestUrl = normalizePinterestUrl;
13819
14016
  exports.normalizeRoleSlug = normalizeRoleSlug;
14017
+ exports.orderedLlmModels = orderedLlmModels;
13820
14018
  exports.parseAttributedDialogue = parseAttributedDialogue;
13821
14019
  exports.parseCharacterMentionToken = parseCharacterMentionToken;
13822
14020
  exports.parseGroupHandle = parseGroupHandle;