@clipwright/core 0.33.0 → 0.35.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.
Files changed (236) hide show
  1. package/CHANGELOG.md +251 -0
  2. package/README.md +3 -1
  3. package/dist/account-actors.d.ts +173 -14
  4. package/dist/account-actors.js +142 -10
  5. package/dist/account-actors.js.map +1 -1
  6. package/dist/actor-bounds.d.ts +4 -0
  7. package/dist/actor-bounds.js +4 -0
  8. package/dist/actor-bounds.js.map +1 -1
  9. package/dist/actors.d.ts +31 -0
  10. package/dist/actors.js +26 -0
  11. package/dist/actors.js.map +1 -1
  12. package/dist/api-failure.js +2 -1
  13. package/dist/api-failure.js.map +1 -1
  14. package/dist/asset-identity.d.ts +6 -0
  15. package/dist/asset-identity.js +7 -0
  16. package/dist/asset-identity.js.map +1 -0
  17. package/dist/assets.d.ts +403 -8
  18. package/dist/assets.js +132 -22
  19. package/dist/assets.js.map +1 -1
  20. package/dist/billing-terms.d.ts +69 -0
  21. package/dist/billing-terms.js +8 -0
  22. package/dist/billing-terms.js.map +1 -1
  23. package/dist/caption-language.d.ts +2 -0
  24. package/dist/caption-language.js +17 -0
  25. package/dist/caption-language.js.map +1 -0
  26. package/dist/contract-dispositions.d.ts +1617 -8
  27. package/dist/contract-dispositions.js +75 -11
  28. package/dist/contract-dispositions.js.map +1 -1
  29. package/dist/contracts/v1/workflow-brief.d.ts +3166 -78
  30. package/dist/contracts/v1/workflow-brief.js +4 -0
  31. package/dist/contracts/v1/workflow-brief.js.map +1 -1
  32. package/dist/contracts/v1/workflow-catalog.d.ts +3712 -8
  33. package/dist/contracts/v1/workflow-catalog.js +4 -2
  34. package/dist/contracts/v1/workflow-catalog.js.map +1 -1
  35. package/dist/contracts/v1/workflow-client.d.ts +2466 -4
  36. package/dist/contracts/v1/workflow-client.js +6 -3
  37. package/dist/contracts/v1/workflow-client.js.map +1 -1
  38. package/dist/contracts/v1/workflow-execution.d.ts +163 -9
  39. package/dist/contracts/v1/workflow-execution.js +15 -7
  40. package/dist/contracts/v1/workflow-execution.js.map +1 -1
  41. package/dist/contracts/v1/workflow-plan.d.ts +6014 -487
  42. package/dist/contracts/v1/workflow-primitives.d.ts +3 -1
  43. package/dist/contracts/v1/workflow-primitives.js +1 -1
  44. package/dist/contracts/v1/workflow-primitives.js.map +1 -1
  45. package/dist/contracts/v1/workflow-run-read.d.ts +114 -1
  46. package/dist/edit-billing.d.ts +12 -0
  47. package/dist/edit-billing.js +8 -0
  48. package/dist/edit-billing.js.map +1 -1
  49. package/dist/edit-long-form.d.ts +1 -1
  50. package/dist/edit-long-form.js +12 -2
  51. package/dist/edit-long-form.js.map +1 -1
  52. package/dist/endpoint-notes.d.ts +3 -0
  53. package/dist/endpoint-notes.js +66 -0
  54. package/dist/endpoint-notes.js.map +1 -0
  55. package/dist/endpoints.d.ts +4 -0
  56. package/dist/endpoints.js +15 -0
  57. package/dist/endpoints.js.map +1 -1
  58. package/dist/errors.d.ts +1 -1
  59. package/dist/errors.js +7 -0
  60. package/dist/errors.js.map +1 -1
  61. package/dist/face-billing.d.ts +55 -0
  62. package/dist/face-billing.js +22 -0
  63. package/dist/face-billing.js.map +1 -1
  64. package/dist/faceless-price.d.ts +26 -2
  65. package/dist/faceless-price.js +33 -6
  66. package/dist/faceless-price.js.map +1 -1
  67. package/dist/faceless-public.d.ts +6 -1
  68. package/dist/faceless-public.js +2 -2
  69. package/dist/faceless-public.js.map +1 -1
  70. package/dist/generations.d.ts +32 -6
  71. package/dist/generations.js +82 -27
  72. package/dist/generations.js.map +1 -1
  73. package/dist/idempotency.d.ts +2 -0
  74. package/dist/idempotency.js +7 -4
  75. package/dist/idempotency.js.map +1 -1
  76. package/dist/index.d.ts +15 -0
  77. package/dist/index.js +17 -0
  78. package/dist/index.js.map +1 -1
  79. package/dist/long-form-pricing.d.ts +7 -4
  80. package/dist/long-form-pricing.js +13 -10
  81. package/dist/long-form-pricing.js.map +1 -1
  82. package/dist/long-form-revision.js +1 -1
  83. package/dist/long-form-revision.js.map +1 -1
  84. package/dist/openapi.d.ts +154 -0
  85. package/dist/openapi.js +334 -0
  86. package/dist/openapi.js.map +1 -0
  87. package/dist/pacing.d.ts +15 -0
  88. package/dist/pacing.js +30 -0
  89. package/dist/pacing.js.map +1 -1
  90. package/dist/parts-pricing.d.ts +84 -0
  91. package/dist/parts-pricing.js +105 -0
  92. package/dist/parts-pricing.js.map +1 -0
  93. package/dist/presenter-beats.d.ts +45 -0
  94. package/dist/presenter-beats.js +144 -0
  95. package/dist/presenter-beats.js.map +1 -0
  96. package/dist/prices.d.ts +98 -0
  97. package/dist/prices.js +189 -0
  98. package/dist/prices.js.map +1 -0
  99. package/dist/public-endpoints.d.ts +2 -0
  100. package/dist/public-endpoints.js +2 -0
  101. package/dist/public-endpoints.js.map +1 -1
  102. package/dist/public-responses.d.ts +23 -0
  103. package/dist/public-responses.js +11 -0
  104. package/dist/public-responses.js.map +1 -0
  105. package/dist/reference-analysis.d.ts +683 -0
  106. package/dist/reference-analysis.js +91 -0
  107. package/dist/reference-analysis.js.map +1 -0
  108. package/dist/reference-kinds.d.ts +6 -0
  109. package/dist/reference-kinds.js +8 -0
  110. package/dist/reference-kinds.js.map +1 -0
  111. package/dist/reference-profile.d.ts +633 -0
  112. package/dist/reference-profile.js +151 -0
  113. package/dist/reference-profile.js.map +1 -0
  114. package/dist/reference-staging.d.ts +571 -0
  115. package/dist/reference-staging.js +151 -0
  116. package/dist/reference-staging.js.map +1 -0
  117. package/dist/reference-voice.d.ts +305 -0
  118. package/dist/reference-voice.js +108 -0
  119. package/dist/reference-voice.js.map +1 -0
  120. package/dist/resolved-timeline.d.ts +206 -1
  121. package/dist/resolved-timeline.js +96 -4
  122. package/dist/resolved-timeline.js.map +1 -1
  123. package/dist/run-static-warnings.js +19 -7
  124. package/dist/run-static-warnings.js.map +1 -1
  125. package/dist/runs.d.ts +75 -3
  126. package/dist/runs.js +6 -1
  127. package/dist/runs.js.map +1 -1
  128. package/dist/semantic-inserts.d.ts +7 -0
  129. package/dist/semantic-inserts.js +19 -9
  130. package/dist/semantic-inserts.js.map +1 -1
  131. package/dist/skills.d.ts +5838 -22
  132. package/dist/skills.js +380 -25
  133. package/dist/skills.js.map +1 -1
  134. package/dist/templates/callout.d.ts +34 -0
  135. package/dist/templates/callout.js +51 -0
  136. package/dist/templates/callout.js.map +1 -0
  137. package/dist/templates/checklist.d.ts +42 -0
  138. package/dist/templates/checklist.js +47 -0
  139. package/dist/templates/checklist.js.map +1 -0
  140. package/dist/templates/compare.d.ts +26 -0
  141. package/dist/templates/compare.js +35 -0
  142. package/dist/templates/compare.js.map +1 -0
  143. package/dist/templates/end-card.d.ts +16 -0
  144. package/dist/templates/end-card.js +25 -0
  145. package/dist/templates/end-card.js.map +1 -0
  146. package/dist/templates/index.d.ts +171 -0
  147. package/dist/templates/index.js +394 -0
  148. package/dist/templates/index.js.map +1 -0
  149. package/dist/templates/lower-third.d.ts +18 -0
  150. package/dist/templates/lower-third.js +26 -0
  151. package/dist/templates/lower-third.js.map +1 -0
  152. package/dist/templates/notification.d.ts +30 -0
  153. package/dist/templates/notification.js +32 -0
  154. package/dist/templates/notification.js.map +1 -0
  155. package/dist/templates/phone-call.d.ts +27 -0
  156. package/dist/templates/phone-call.js +43 -0
  157. package/dist/templates/phone-call.js.map +1 -0
  158. package/dist/templates/progress.d.ts +22 -0
  159. package/dist/templates/progress.js +42 -0
  160. package/dist/templates/progress.js.map +1 -0
  161. package/dist/templates/quote.d.ts +21 -0
  162. package/dist/templates/quote.js +29 -0
  163. package/dist/templates/quote.js.map +1 -0
  164. package/dist/templates/rating.d.ts +22 -0
  165. package/dist/templates/rating.js +29 -0
  166. package/dist/templates/rating.js.map +1 -0
  167. package/dist/templates/size.d.ts +13 -0
  168. package/dist/templates/size.js +10 -0
  169. package/dist/templates/size.js.map +1 -0
  170. package/dist/templates/slot.d.ts +10 -0
  171. package/dist/templates/slot.js +5 -0
  172. package/dist/templates/slot.js.map +1 -0
  173. package/dist/templates/sounds.d.ts +701 -0
  174. package/dist/templates/sounds.js +89 -0
  175. package/dist/templates/sounds.js.map +1 -0
  176. package/dist/templates/stat.d.ts +20 -0
  177. package/dist/templates/stat.js +33 -0
  178. package/dist/templates/stat.js.map +1 -0
  179. package/dist/templates/tag.d.ts +23 -0
  180. package/dist/templates/tag.js +31 -0
  181. package/dist/templates/tag.js.map +1 -0
  182. package/dist/templates/theme.d.ts +29 -0
  183. package/dist/templates/theme.js +47 -0
  184. package/dist/templates/theme.js.map +1 -0
  185. package/dist/templates/title-card.d.ts +21 -0
  186. package/dist/templates/title-card.js +30 -0
  187. package/dist/templates/title-card.js.map +1 -0
  188. package/dist/tts-backend.d.ts +9 -0
  189. package/dist/tts-backend.js +21 -0
  190. package/dist/tts-backend.js.map +1 -1
  191. package/dist/ugc-call.d.ts +89 -0
  192. package/dist/ugc-call.js +111 -0
  193. package/dist/ugc-call.js.map +1 -0
  194. package/dist/ugc-framing.d.ts +26 -0
  195. package/dist/ugc-framing.js +64 -0
  196. package/dist/ugc-framing.js.map +1 -0
  197. package/dist/ugc-layers.d.ts +88 -0
  198. package/dist/ugc-layers.js +142 -0
  199. package/dist/ugc-layers.js.map +1 -0
  200. package/dist/ugc-video-media.d.ts +12 -0
  201. package/dist/ugc-video-media.js +39 -0
  202. package/dist/ugc-video-media.js.map +1 -0
  203. package/dist/vendor-response.d.ts +4 -0
  204. package/dist/vendor-response.js +12 -0
  205. package/dist/vendor-response.js.map +1 -1
  206. package/dist/voice-admission.d.ts +1244 -1
  207. package/dist/voice-listing.js +7 -1
  208. package/dist/voice-listing.js.map +1 -1
  209. package/dist/voice-pace.d.ts +34 -0
  210. package/dist/voice-pace.generated.json +72 -0
  211. package/dist/voice-pace.js +34 -0
  212. package/dist/voice-pace.js.map +1 -0
  213. package/dist/voices.d.ts +21 -8
  214. package/dist/voices.js +44 -19
  215. package/dist/voices.js.map +1 -1
  216. package/dist/workflows/catalog.js +2 -1
  217. package/dist/workflows/catalog.js.map +1 -1
  218. package/dist/workflows/index.d.ts +2 -0
  219. package/dist/workflows/index.js +2 -0
  220. package/dist/workflows/index.js.map +1 -1
  221. package/dist/workflows/methods/faceless-explainer.d.ts +697 -3
  222. package/dist/workflows/methods/kinetic-launch.d.ts +697 -3
  223. package/dist/workflows/methods/product-image-story.d.ts +697 -3
  224. package/dist/workflows/methods/reference-remake.d.ts +870 -0
  225. package/dist/workflows/methods/reference-remake.js +26 -0
  226. package/dist/workflows/methods/reference-remake.js.map +1 -0
  227. package/dist/workflows/methods/shared.d.ts +697 -3
  228. package/dist/workflows/methods/ugc-faq-answer.d.ts +697 -3
  229. package/dist/workflows/methods/ugc-product-intro.d.ts +697 -3
  230. package/dist/workflows/methods/website-proof-demo.d.ts +697 -3
  231. package/dist/workflows/reference-remake.d.ts +663 -0
  232. package/dist/workflows/reference-remake.js +598 -0
  233. package/dist/workflows/reference-remake.js.map +1 -0
  234. package/dist/workflows/validate.js +19 -11
  235. package/dist/workflows/validate.js.map +1 -1
  236. package/package.json +9 -3
@@ -0,0 +1,111 @@
1
+ import { lexicalTokens } from "./semantic-inserts.js";
2
+ import { layerWordRange } from "./ugc-layers.js";
3
+ // A phone call over a hold (#857 S5): two voices after a quote, the presenter listening, then frozen, until the call ends.
4
+ // Numbers are the reference's, measured in `.make-feature/refel-s5b-call/scene-spec-call.json`.
5
+ export const CALL_SPEAKERS = ["agent", "caller"];
6
+ export const MAX_CALL_LINES = 12;
7
+ export const MAX_CALL_LINE_CHARS = 400;
8
+ export const MAX_CALL_CHARS = 1500;
9
+ /** A call's length before synthesis, at the reference's 19 characters a second (D10). */
10
+ export const CALL_CHARS_PER_SEC = 19;
11
+ export const MAX_CALL_SEC = 45;
12
+ /** Past this the presenter holds still long enough to name it (D1). */
13
+ export const CALL_WARN_SEC = 20;
14
+ /** The bake-off's pair (S5-0): agent Cassidy, caller Mark; the agent is never the narration's voice. */
15
+ export const DEFAULT_CALL_VOICES = Object.freeze({ agent: "en_female_cassidy", caller: "en_male_mark" });
16
+ export const SECOND_CALL_AGENT = "sarah";
17
+ /** The reference's in-call screen (D8): a US number shown only to its area code and the hold banner, generic phone UI. */
18
+ export const CALL_PHONE_DEFAULTS = Object.freeze({ caller: "+1 (305) 555-0147", banner: "Hold This Call?", banner_note: "You'll be notified to pick up.",
19
+ mask_number: true });
20
+ /** The phone the worker draws over a call: an id no client template can spell, so it never meets one. */
21
+ export const CALL_PHONE_ID = "call.phone";
22
+ /** The ring starts this long after the phone enters, rings for CALL_RING_SEC (the `ring_double` file) and the first word follows it. */
23
+ export const CALL_RING_LEAD_SEC = 0.07;
24
+ export const CALL_RING_SEC = 1.35;
25
+ export const CALL_RING_TO_VOICE_SEC = 0.1;
26
+ /** From the call's last word to the end of the freeze. */
27
+ export const CALL_TAIL_SEC = 0.4;
28
+ /** The presenter's live listening before the freeze (S4d), and how far before the freeze the phone enters behind it. */
29
+ export const CALL_LIVE_SEC = 3.58;
30
+ export const CALL_PHONE_LEAD_SEC = 3.96;
31
+ /** A staged phone (#914 D1e) rises from one of these sides, within these bounds; the composition draws no other entry for it. */
32
+ export const CALL_STAGE_SIDES = ["bottom", "lower_left", "lower_right"];
33
+ export const CALL_STAGE_MAX_ENTER_SEC = 5;
34
+ export const CALL_STAGE_MAX_LEAD_SEC = 10;
35
+ export const callChars = (call) => call.lines.reduce((sum, line) => sum + line.text.length, 0);
36
+ export const callEstimateSec = (call) => Math.ceil(callChars(call) / CALL_CHARS_PER_SEC);
37
+ /** The seconds a call adds to the video: its lines, the ring before them and the tail after (D10). */
38
+ export const callGapEstimateSec = (call) => callEstimateSec(call) + Math.ceil(CALL_RING_LEAD_SEC + CALL_RING_SEC + CALL_RING_TO_VOICE_SEC + CALL_TAIL_SEC);
39
+ /** The lexical word the presenter resumes on: the one after the quote's last word, or why there is none. */
40
+ export function callResumeWord(script, after) {
41
+ const tokens = lexicalTokens(script), range = layerWordRange(tokens, { id: "call", anchor: after });
42
+ if (typeof range === "string")
43
+ return range;
44
+ return range.coverWord < tokens.length ? range.coverWord : "the call needs words after it: the presenter resumes on the word after its quote";
45
+ }
46
+ /** The agent and caller voices: the named ones, else the defaults, the agent kept off the narration's voice. */
47
+ export function callVoices(call, narrationVoice) {
48
+ const agent = call.voices?.agent ?? (narrationVoice === DEFAULT_CALL_VOICES.agent ? SECOND_CALL_AGENT : DEFAULT_CALL_VOICES.agent);
49
+ return { agent, caller: call.voices?.caller ?? DEFAULT_CALL_VOICES.caller };
50
+ }
51
+ /** Every refusal of `call` before money, named by path (C1); the schema already bounds each line and the count. */
52
+ export function callRefusals(input) {
53
+ const call = input.call;
54
+ if (call === undefined)
55
+ return [];
56
+ if (input.script === undefined || input.segments !== undefined)
57
+ return [{ path: ["call"], message: "call requires script and cannot be combined with segments" }];
58
+ const refusals = [];
59
+ if (input.aspect_ratio !== undefined && input.aspect_ratio !== "9:16") {
60
+ refusals.push({ path: ["call"], message: `call needs a 9:16 frame: the phone and the listening presenter are staged for it, not ${input.aspect_ratio}` });
61
+ }
62
+ const resume = callResumeWord(input.script, call.after);
63
+ if (typeof resume === "string")
64
+ refusals.push({ path: ["call", "after"], message: resume });
65
+ else {
66
+ const tokens = lexicalTokens(input.script);
67
+ const cover = (input.inserts ?? []).find(item => {
68
+ const range = layerWordRange(tokens, item);
69
+ return typeof range !== "string" && range.startWord < resume && resume - 1 < range.coverWord;
70
+ });
71
+ if (cover)
72
+ refusals.push({ path: ["call", "after"], message: `the call opens after words insert "${cover.id}" covers: the presenter must be on screen to listen` });
73
+ }
74
+ if (call.lines.length >= 2 && new Set(call.lines.map(line => line.speaker)).size < 2) {
75
+ refusals.push({ path: ["call", "lines"], message: "a call needs lines from both the agent and the caller" });
76
+ }
77
+ const chars = callChars(call);
78
+ if (chars > MAX_CALL_CHARS)
79
+ refusals.push({ path: ["call", "lines"], message: `the call's lines hold ${chars} characters, more than ${MAX_CALL_CHARS}` });
80
+ else if (callEstimateSec(call) > MAX_CALL_SEC) {
81
+ refusals.push({ path: ["call", "lines"], message: `the call runs about ${callEstimateSec(call)} s, longer than ${MAX_CALL_SEC} s: shorten its lines` });
82
+ }
83
+ if (call.voices?.agent !== undefined && call.voices.agent === input.voice) {
84
+ refusals.push({ path: ["call", "voices", "agent"], message: "the call's agent needs a voice other than the narration's, or the presenter seems to answer in their own voice" });
85
+ }
86
+ return refusals;
87
+ }
88
+ /** A long call is delivered, and named (rule 3). */
89
+ export function callWarnings(input) {
90
+ const call = input.call;
91
+ if (!Array.isArray(call?.lines))
92
+ return [];
93
+ const seconds = callEstimateSec({ lines: call.lines });
94
+ return seconds > CALL_WARN_SEC ? [`the call runs about ${seconds} s, longer than ${CALL_WARN_SEC} s: the presenter holds still through all of it`] : [];
95
+ }
96
+ /** Where a call sits in its gap, in frames from the presenter's last word before it (D2): the phone enters, the ring starts, the first word,
97
+ * and the gap and hold lengths. Gap = ring lead + ring + call + tail after the phone; hold = gap − live. */
98
+ export function callGapFrames(args) {
99
+ const { callFrames, liveFrames, fps } = args;
100
+ if (![callFrames, liveFrames, fps].every(Number.isSafeInteger) || callFrames < 1 || liveFrames < 0 || fps < 1) {
101
+ throw new Error("a call's gap needs whole frames");
102
+ }
103
+ // Never before the gap: over the talking take the phone is not drawn, and a ring there plays over the last word (#924).
104
+ const phoneEntry = Math.max(0, liveFrames - Math.round(CALL_PHONE_LEAD_SEC * fps));
105
+ const ringFrom = phoneEntry + Math.round(CALL_RING_LEAD_SEC * fps);
106
+ const voiceFrom = phoneEntry + Math.round((CALL_RING_LEAD_SEC + CALL_RING_SEC + CALL_RING_TO_VOICE_SEC) * fps);
107
+ // A call too short to outlast the listening keeps a hold of one tail.
108
+ const gapFrames = Math.max(voiceFrom + callFrames + Math.round(CALL_TAIL_SEC * fps), liveFrames + Math.round(CALL_TAIL_SEC * fps));
109
+ return { phoneEntry, ringFrom, voiceFrom, gapFrames, holdFrames: gapFrames - liveFrames };
110
+ }
111
+ //# sourceMappingURL=ugc-call.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ugc-call.js","sourceRoot":"","sources":["../src/ugc-call.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAwC,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEvF,2HAA2H;AAC3H,gGAAgG;AAEhG,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,OAAO,EAAE,QAAQ,CAAU,CAAC;AAE1D,MAAM,CAAC,MAAM,cAAc,GAAG,EAAE,CAAC;AACjC,MAAM,CAAC,MAAM,mBAAmB,GAAG,GAAG,CAAC;AACvC,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,CAAC;AACnC,yFAAyF;AACzF,MAAM,CAAC,MAAM,kBAAkB,GAAG,EAAE,CAAC;AACrC,MAAM,CAAC,MAAM,YAAY,GAAG,EAAE,CAAC;AAC/B,uEAAuE;AACvE,MAAM,CAAC,MAAM,aAAa,GAAG,EAAE,CAAC;AAChC,wGAAwG;AACxG,MAAM,CAAC,MAAM,mBAAmB,GAA0C,MAAM,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,mBAAmB,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC,CAAC;AAChJ,MAAM,CAAC,MAAM,iBAAiB,GAAG,OAAO,CAAC;AACzC,0HAA0H;AAC1H,MAAM,CAAC,MAAM,mBAAmB,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,mBAAmB,EAAE,MAAM,EAAE,iBAAiB,EAAE,WAAW,EAAE,gCAAgC;IACtJ,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC;AACvB,yGAAyG;AACzG,MAAM,CAAC,MAAM,aAAa,GAAG,YAAY,CAAC;AAE1C,wIAAwI;AACxI,MAAM,CAAC,MAAM,kBAAkB,GAAG,IAAI,CAAC;AACvC,MAAM,CAAC,MAAM,aAAa,GAAG,IAAI,CAAC;AAClC,MAAM,CAAC,MAAM,sBAAsB,GAAG,GAAG,CAAC;AAC1C,0DAA0D;AAC1D,MAAM,CAAC,MAAM,aAAa,GAAG,GAAG,CAAC;AACjC,wHAAwH;AACxH,MAAM,CAAC,MAAM,aAAa,GAAG,IAAI,CAAC;AAClC,MAAM,CAAC,MAAM,mBAAmB,GAAG,IAAI,CAAC;AACxC,iIAAiI;AACjI,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,QAAQ,EAAE,YAAY,EAAE,aAAa,CAAU,CAAC;AACjF,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,CAAC;AAC1C,MAAM,CAAC,MAAM,uBAAuB,GAAG,EAAE,CAAC;AAM1C,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,IAA8B,EAAU,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;AACjI,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,IAA8B,EAAU,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,kBAAkB,CAAC,CAAC;AAC3H,sGAAsG;AACtG,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,IAA8B,EAAU,EAAE,CAC3E,eAAe,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,kBAAkB,GAAG,aAAa,GAAG,sBAAsB,GAAG,aAAa,CAAC,CAAC;AAEjH,4GAA4G;AAC5G,MAAM,UAAU,cAAc,CAAC,MAAc,EAAE,KAAyB;IACtE,MAAM,MAAM,GAAG,aAAa,CAAC,MAAM,CAAC,EAAE,KAAK,GAAG,cAAc,CAAC,MAAM,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;IACpG,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC5C,OAAO,KAAK,CAAC,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,kFAAkF,CAAC;AAChJ,CAAC;AAED,gHAAgH;AAChH,MAAM,UAAU,UAAU,CAAC,IAA+B,EAAE,cAAkC;IAC5F,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,cAAc,KAAK,mBAAmB,CAAC,KAAK,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC;IACnI,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,MAAM,IAAI,mBAAmB,CAAC,MAAM,EAAE,CAAC;AAC9E,CAAC;AAOD,mHAAmH;AACnH,MAAM,UAAU,YAAY,CAAC,KAAqB;IAChD,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;IACxB,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,EAAE,CAAC;IAClC,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS,IAAI,KAAK,CAAC,QAAQ,KAAK,SAAS;QAAE,OAAO,CAAC,EAAE,IAAI,EAAE,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,2DAA2D,EAAE,CAAC,CAAC;IAClK,MAAM,QAAQ,GAAmB,EAAE,CAAC;IACpC,IAAI,KAAK,CAAC,YAAY,KAAK,SAAS,IAAI,KAAK,CAAC,YAAY,KAAK,MAAM,EAAE,CAAC;QACtE,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,yFAAyF,KAAK,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;IAC5J,CAAC;IACD,MAAM,MAAM,GAAG,cAAc,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;IACxD,IAAI,OAAO,MAAM,KAAK,QAAQ;QAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;SACvF,CAAC;QACJ,MAAM,MAAM,GAAG,aAAa,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAC3C,MAAM,KAAK,GAAG,CAAC,KAAK,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;YAC9C,MAAM,KAAK,GAAG,cAAc,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;YAC3C,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,SAAS,GAAG,MAAM,IAAI,MAAM,GAAG,CAAC,GAAG,KAAK,CAAC,SAAS,CAAC;QAC/F,CAAC,CAAC,CAAC;QACH,IAAI,KAAK;YAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,sCAAsC,KAAK,CAAC,EAAE,qDAAqD,EAAE,CAAC,CAAC;IACtK,CAAC;IACD,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,IAAI,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;QACrF,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,uDAAuD,EAAE,CAAC,CAAC;IAC/G,CAAC;IACD,MAAM,KAAK,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IAC9B,IAAI,KAAK,GAAG,cAAc;QAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,yBAAyB,KAAK,0BAA0B,cAAc,EAAE,EAAE,CAAC,CAAC;SACrJ,IAAI,eAAe,CAAC,IAAI,CAAC,GAAG,YAAY,EAAE,CAAC;QAC9C,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,uBAAuB,eAAe,CAAC,IAAI,CAAC,mBAAmB,YAAY,uBAAuB,EAAE,CAAC,CAAC;IAC1J,CAAC;IACD,IAAI,IAAI,CAAC,MAAM,EAAE,KAAK,KAAK,SAAS,IAAI,IAAI,CAAC,MAAM,CAAC,KAAK,KAAK,KAAK,CAAC,KAAK,EAAE,CAAC;QAC1E,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,gHAAgH,EAAE,CAAC,CAAC;IAClL,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,oDAAoD;AACpD,MAAM,UAAU,YAAY,CAAC,KAAyB;IACpD,MAAM,IAAI,GAAG,KAAK,CAAC,IAAsC,CAAC;IAC1D,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAC3C,MAAM,OAAO,GAAG,eAAe,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;IACvD,OAAO,OAAO,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC,uBAAuB,OAAO,mBAAmB,aAAa,iDAAiD,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AAC1J,CAAC;AAED;6GAC6G;AAC7G,MAAM,UAAU,aAAa,CAAC,IAA6D;IACzF,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;IAC7C,IAAI,CAAC,CAAC,UAAU,EAAE,UAAU,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,UAAU,GAAG,CAAC,IAAI,UAAU,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC,EAAE,CAAC;QAC9G,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;IACrD,CAAC;IACD,wHAAwH;IACxH,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,mBAAmB,GAAG,GAAG,CAAC,CAAC,CAAC;IACnF,MAAM,QAAQ,GAAG,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,kBAAkB,GAAG,GAAG,CAAC,CAAC;IACnE,MAAM,SAAS,GAAG,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,kBAAkB,GAAG,aAAa,GAAG,sBAAsB,CAAC,GAAG,GAAG,CAAC,CAAC;IAC/G,sEAAsE;IACtE,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,GAAG,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,aAAa,GAAG,GAAG,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,aAAa,GAAG,GAAG,CAAC,CAAC,CAAC;IACnI,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,EAAE,SAAS,GAAG,UAAU,EAAE,CAAC;AAC5F,CAAC"}
@@ -0,0 +1,26 @@
1
+ import { type AnchoredItem, type LayerRefusal, type LayoutWindowKind } from "./ugc-layers.js";
2
+ export declare const FRAMING_SIZES: readonly ["close", "medium"];
3
+ export type FramingSize = (typeof FRAMING_SIZES)[number];
4
+ export declare const FRAMING_TRANSITIONS: readonly ["cut", "flash"];
5
+ export type FramingTransition = (typeof FRAMING_TRANSITIONS)[number];
6
+ export declare const MAX_FRAMING = 20;
7
+ /** The presenter's scale about the face: close clears a scene detector's 10% with margin and stays under the ×1.25 a 720p take stands. */
8
+ export declare const FRAMING_SCALE: Readonly<Record<FramingSize, number>>;
9
+ export interface FramingCheckInput {
10
+ script: string;
11
+ inserts?: readonly AnchoredItem[] | undefined;
12
+ overlays?: readonly AnchoredItem[] | undefined;
13
+ layout_windows?: readonly (AnchoredItem & {
14
+ layout: LayoutWindowKind;
15
+ })[] | undefined;
16
+ templates?: readonly AnchoredItem[] | undefined;
17
+ framing?: readonly AnchoredItem[] | undefined;
18
+ }
19
+ /** Every refusal of `framing` against the script and the run's other parts, named by path; empty when it renders. */
20
+ export declare function framingRefusals(input: FramingCheckInput): LayerRefusal[];
21
+ /** A framing that never shows, named for the quote and the run (rule 3): it lies wholly under full-frame templates. */
22
+ export declare function framingWarnings(input: {
23
+ script?: unknown;
24
+ framing?: unknown;
25
+ templates?: unknown;
26
+ }): string[];
@@ -0,0 +1,64 @@
1
+ import { lexicalTokens } from "./semantic-inserts.js";
2
+ import { TEMPLATE_KINDS } from "./templates/index.js";
3
+ import { layerWordRange } from "./ugc-layers.js";
4
+ // Framing (reference-elements S2): word-anchored presenter sizes, cut or flashed in, drawn by the composition over the actor slots.
5
+ export const FRAMING_SIZES = ["close", "medium"];
6
+ export const FRAMING_TRANSITIONS = ["cut", "flash"];
7
+ export const MAX_FRAMING = 20;
8
+ /** The presenter's scale about the face: close clears a scene detector's 10% with margin and stays under the ×1.25 a 720p take stands. */
9
+ export const FRAMING_SCALE = Object.freeze({ close: 1.18, medium: 1 });
10
+ const overlaps = (a, b) => a.startWord < b.coverWord && b.startWord < a.coverWord;
11
+ const coveredBy = (range, cover) => Array.from({ length: range.coverWord - range.startWord }, (_, offset) => range.startWord + offset).every(word => cover.some(other => word >= other.startWord && word < other.coverWord));
12
+ const ID_FIELDS = ["inserts", "overlays", "layout_windows", "templates"];
13
+ /** Every refusal of `framing` against the script and the run's other parts, named by path; empty when it renders. */
14
+ export function framingRefusals(input) {
15
+ const refusals = [];
16
+ const tokens = lexicalTokens(input.script);
17
+ const used = new Map(ID_FIELDS.flatMap(field => (input[field] ?? []).map(item => [item.id, field])));
18
+ const ranged = (items) => (items ?? []).flatMap(item => { const range = layerWordRange(tokens, item); return typeof range === "string" ? [] : [{ item, range }]; });
19
+ const inserts = ranged(input.inserts), windows = ranged(input.layout_windows);
20
+ const placed = [];
21
+ for (const [index, item] of (input.framing ?? []).entries()) {
22
+ const owner = used.get(item.id);
23
+ if (owner !== undefined) {
24
+ refusals.push({ path: ["framing", index, "id"], message: `id "${item.id}" is already used in ${owner}: ids are unique across inserts, overlays, layout_windows, templates and framing` });
25
+ }
26
+ used.set(item.id, "framing");
27
+ const range = layerWordRange(tokens, item);
28
+ if (typeof range === "string") {
29
+ refusals.push({ path: ["framing", index, "anchor"], message: `framing "${item.id}": ${range}` });
30
+ continue;
31
+ }
32
+ const refuse = (message) => refusals.push({ path: ["framing", index], message: `framing "${item.id}" ${message}` });
33
+ const insert = inserts.find(other => overlaps(other.range, range));
34
+ if (insert)
35
+ refuse(`overlaps insert "${insert.item.id}": it reframes the presenter, who is not on screen during a full-frame insert`);
36
+ const window = windows.find(other => overlaps(other.range, range));
37
+ if (window) {
38
+ refuse(`overlaps ${window.item.layout} window "${window.item.id}": ${window.item.layout === "split"
39
+ ? "a split crops the presenter to the top half and cannot scale it as well" : "a window reframes the presenter, and framing does not share the frame with it"}`);
40
+ }
41
+ const earlier = placed.find(other => overlaps(other.range, range));
42
+ if (earlier)
43
+ refuse(`overlaps framing "${earlier.id}": one framing holds the presenter at a time`);
44
+ placed.push({ id: item.id, range });
45
+ }
46
+ return refusals;
47
+ }
48
+ /** A framing that never shows, named for the quote and the run (rule 3): it lies wholly under full-frame templates. */
49
+ export function framingWarnings(input) {
50
+ if (typeof input.script !== "string" || !Array.isArray(input.framing) || !Array.isArray(input.templates))
51
+ return [];
52
+ const tokens = lexicalTokens(input.script);
53
+ const fulls = input.templates.flatMap(item => {
54
+ const placement = item.placement ?? TEMPLATE_KINDS.find(entry => entry.kind === item.kind)?.placements[0];
55
+ const range = placement === "full" ? layerWordRange(tokens, item) : "over";
56
+ return typeof range === "string" ? [] : [range];
57
+ });
58
+ return input.framing.flatMap(item => {
59
+ const range = layerWordRange(tokens, item);
60
+ return typeof range !== "string" && coveredBy(range, fulls)
61
+ ? [`framing "${item.id}" is not drawn: it lies wholly under full-frame templates, where the presenter is not on screen`] : [];
62
+ });
63
+ }
64
+ //# sourceMappingURL=ugc-framing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ugc-framing.js","sourceRoot":"","sources":["../src/ugc-framing.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAwC,cAAc,EAAyC,MAAM,iBAAiB,CAAC;AAE9H,oIAAoI;AAEpI,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,OAAO,EAAE,QAAQ,CAAU,CAAC;AAE1D,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,KAAK,EAAE,OAAO,CAAU,CAAC;AAE7D,MAAM,CAAC,MAAM,WAAW,GAAG,EAAE,CAAC;AAC9B,0IAA0I;AAC1I,MAAM,CAAC,MAAM,aAAa,GAA0C,MAAM,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC;AAE9G,MAAM,QAAQ,GAAG,CAAC,CAAY,EAAE,CAAY,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,SAAS,CAAC;AACxG,MAAM,SAAS,GAAG,CAAC,KAAgB,EAAE,KAA2B,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,SAAS,GAAG,KAAK,CAAC,SAAS,EAAE,EAC3H,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,KAAK,CAAC,SAAS,GAAG,MAAM,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,IAAI,KAAK,CAAC,SAAS,IAAI,IAAI,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC;AACjI,MAAM,SAAS,GAAG,CAAC,SAAS,EAAE,UAAU,EAAE,gBAAgB,EAAE,WAAW,CAAU,CAAC;AAWlF,qHAAqH;AACrH,MAAM,UAAU,eAAe,CAAC,KAAwB;IACtD,MAAM,QAAQ,GAAmB,EAAE,CAAC;IACpC,MAAM,MAAM,GAAG,aAAa,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC3C,MAAM,IAAI,GAAG,IAAI,GAAG,CAAiB,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,CAAU,CAAC,CAAC,CAAC,CAAC;IAC9H,MAAM,MAAM,GAAG,CAAyB,KAA+B,EAAE,EAAE,CACzE,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,MAAM,KAAK,GAAG,cAAc,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5I,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;IAC9E,MAAM,MAAM,GAAuC,EAAE,CAAC;IACtD,KAAK,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC;QAC5D,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAChC,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,SAAS,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,OAAO,IAAI,CAAC,EAAE,wBAAwB,KAAK,kFAAkF,EAAE,CAAC,CAAC;QAC5L,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,CAAC,CAAC;QAC7B,MAAM,KAAK,GAAG,cAAc,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QAC3C,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,SAAS,EAAE,KAAK,EAAE,QAAQ,CAAC,EAAE,OAAO,EAAE,YAAY,IAAI,CAAC,EAAE,MAAM,KAAK,EAAE,EAAE,CAAC,CAAC;YAAC,SAAS;QAAC,CAAC;QAC9I,MAAM,MAAM,GAAG,CAAC,OAAe,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,SAAS,EAAE,KAAK,CAAC,EAAE,OAAO,EAAE,YAAY,IAAI,CAAC,EAAE,KAAK,OAAO,EAAE,EAAE,CAAC,CAAC;QAC5H,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;QACnE,IAAI,MAAM;YAAE,MAAM,CAAC,oBAAoB,MAAM,CAAC,IAAI,CAAC,EAAE,+EAA+E,CAAC,CAAC;QACtI,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;QACnE,IAAI,MAAM,EAAE,CAAC;YACX,MAAM,CAAC,YAAY,MAAM,CAAC,IAAI,CAAC,MAAM,YAAY,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,MAAM,CAAC,IAAI,CAAC,MAAM,KAAK,OAAO;gBACjG,CAAC,CAAC,yEAAyE,CAAC,CAAC,CAAC,+EAA+E,EAAE,CAAC,CAAC;QACrK,CAAC;QACD,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;QACnE,IAAI,OAAO;YAAE,MAAM,CAAC,qBAAqB,OAAO,CAAC,EAAE,8CAA8C,CAAC,CAAC;QACnG,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;IACtC,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,uHAAuH;AACvH,MAAM,UAAU,eAAe,CAAC,KAAmE;IACjG,IAAI,OAAO,KAAK,CAAC,MAAM,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC;QAAE,OAAO,EAAE,CAAC;IACpH,MAAM,MAAM,GAAG,aAAa,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC3C,MAAM,KAAK,GAAI,KAAK,CAAC,SAAwE,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;QAC3G,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC;QAC1G,MAAM,KAAK,GAAG,SAAS,KAAK,MAAM,CAAC,CAAC,CAAC,cAAc,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;QAC3E,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;IACH,OAAQ,KAAK,CAAC,OAA0B,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;QACtD,MAAM,KAAK,GAAG,cAAc,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QAC3C,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,SAAS,CAAC,KAAK,EAAE,KAAK,CAAC;YACzD,CAAC,CAAC,CAAC,YAAY,IAAI,CAAC,EAAE,iGAAiG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAClI,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,88 @@
1
+ import type { WordTiming } from "./tts-backend.js";
2
+ export declare const OVERLAY_POSITIONS: readonly ["top_left", "top_right", "bottom_left", "bottom_right", "top", "bottom"];
3
+ export type OverlayPosition = (typeof OVERLAY_POSITIONS)[number];
4
+ export declare const LAYER_ENTERS: readonly ["cut", "fade", "slide", "tilt_in"];
5
+ export type LayerEnter = (typeof LAYER_ENTERS)[number];
6
+ export declare const LAYOUT_WINDOW_KINDS: readonly ["split", "card"];
7
+ export type LayoutWindowKind = (typeof LAYOUT_WINDOW_KINDS)[number];
8
+ export declare const INSERT_TRANSITIONS: readonly ["cut", "wipe", "flash", "zoom"];
9
+ export type InsertTransition = (typeof INSERT_TRANSITIONS)[number];
10
+ export declare const MAX_OVERLAYS = 10;
11
+ export declare const MAX_LAYOUT_WINDOWS = 5;
12
+ export declare const MAX_OVERLAYS_AT_ONCE = 2;
13
+ /** A footprint on the frame, in shares of its width and height (#778 S3 D5). */
14
+ export interface LayerRect {
15
+ left: number;
16
+ top: number;
17
+ width: number;
18
+ height: number;
19
+ }
20
+ /** The frame of a `W:H` format in pixels, as the composition's `canvasForRatio` derives it: the short side 1080, both sides even. */
21
+ export declare function frameCanvasOf(aspectRatio: string): {
22
+ width: number;
23
+ height: number;
24
+ };
25
+ /** The most an overlay at `position` takes, as `overlayBox` draws it: a corner 42% wide, a band the width less margins, 30% high. */
26
+ export declare function overlayRect(position: OverlayPosition, canvas: {
27
+ width: number;
28
+ height: number;
29
+ }): LayerRect;
30
+ /** Two footprints collide when they share an area; touching edges do not. */
31
+ export declare function rectsOverlap(a: LayerRect, b: LayerRect): boolean;
32
+ /** How the presenter is framed: close as every portrait was, or wide, lower with room above, a 9:16 view only (#884 S5d). */
33
+ export declare const PRESENTER_FRAMINGS: readonly ["close", "wide"];
34
+ export type PresenterFraming = (typeof PRESENTER_FRAMINGS)[number];
35
+ /** Where the presenter's face sits: 12–48% of the height and the middle 60% of a 9:16 clip, which other formats fit whole and centre (#778 S3). */
36
+ /** A wide 9:16 view puts it at 33–58% and the middle half, as measured on a HeyGen render (#884 S5d). */
37
+ export declare function faceZone(aspectRatio: string, framing?: PresenterFraming): LayerRect;
38
+ type WordAnchor = {
39
+ startWord: number;
40
+ endWord: number;
41
+ } | {
42
+ quote: string;
43
+ occurrence?: number | undefined;
44
+ };
45
+ export interface AnchoredItem {
46
+ id: string;
47
+ anchor: WordAnchor;
48
+ cover_words?: number | undefined;
49
+ }
50
+ export interface WordRange {
51
+ startWord: number;
52
+ coverWord: number;
53
+ }
54
+ /** The words an item covers, `[startWord, coverWord)`, as an insert anchor resolves; a string names why it does not resolve. */
55
+ export declare function layerWordRange(tokens: readonly string[], item: AnchoredItem): WordRange | string;
56
+ export interface LayerRefusal {
57
+ path: (string | number)[];
58
+ message: string;
59
+ }
60
+ export interface LayerCheckInput {
61
+ script: string;
62
+ aspect_ratio?: string | undefined;
63
+ inserts?: readonly AnchoredItem[] | undefined;
64
+ overlays?: readonly (AnchoredItem & {
65
+ position: OverlayPosition;
66
+ })[] | undefined;
67
+ layout_windows?: readonly (AnchoredItem & {
68
+ layout: LayoutWindowKind;
69
+ })[] | undefined;
70
+ }
71
+ /** Every refusal of overlays and layout windows against the script, named by path; empty when they render. */
72
+ export declare function layerRefusals(input: LayerCheckInput): LayerRefusal[];
73
+ export interface LayerFrames {
74
+ id: string;
75
+ startFrame: number;
76
+ endFrame: number;
77
+ }
78
+ /** Frames of each word range on the run's narration, by the rule inserts follow: a range ends where its first uncovered word starts. */
79
+ export declare function resolveLayerFrames(input: {
80
+ tokens: readonly string[];
81
+ words: readonly WordTiming[];
82
+ totalFrames: number;
83
+ fps: number;
84
+ layers: readonly (WordRange & {
85
+ id: string;
86
+ })[];
87
+ }): LayerFrames[];
88
+ export {};
@@ -0,0 +1,142 @@
1
+ import { lexicalTokens, quoteOccurrences } from "./semantic-inserts.js";
2
+ // Overlays and layout windows of a long-form `make_ugc` run (#778 S2b): drawn over the actor slots, never planned as inserts.
3
+ export const OVERLAY_POSITIONS = ["top_left", "top_right", "bottom_left", "bottom_right", "top", "bottom"];
4
+ export const LAYER_ENTERS = ["cut", "fade", "slide", "tilt_in"];
5
+ export const LAYOUT_WINDOW_KINDS = ["split", "card"];
6
+ export const INSERT_TRANSITIONS = ["cut", "wipe", "flash", "zoom"];
7
+ export const MAX_OVERLAYS = 10;
8
+ export const MAX_LAYOUT_WINDOWS = 5;
9
+ export const MAX_OVERLAYS_AT_ONCE = 2;
10
+ /** The frame of a `W:H` format in pixels, as the composition's `canvasForRatio` derives it: the short side 1080, both sides even. */
11
+ export function frameCanvasOf(aspectRatio) {
12
+ const [w, h] = aspectRatio.split(":").map(Number);
13
+ const even = (value) => { const rounded = Math.round(value); return rounded % 2 === 0 ? rounded : rounded + 1; };
14
+ return w >= h ? { width: even((1080 * w) / h), height: 1080 } : { width: 1080, height: even((1080 * h) / w) };
15
+ }
16
+ /** The most an overlay at `position` takes, as `overlayBox` draws it: a corner 42% wide, a band the width less margins, 30% high. */
17
+ export function overlayRect(position, canvas) {
18
+ const margin = Math.round(0.04 * Math.min(canvas.width, canvas.height));
19
+ const band = position === "top" || position === "bottom";
20
+ const width = band ? canvas.width - 2 * margin : Math.round(0.42 * canvas.width), height = Math.round(0.3 * canvas.height);
21
+ const left = band || position.endsWith("left") ? margin : canvas.width - margin - width;
22
+ const top = position.startsWith("top") ? margin : canvas.height - margin - height;
23
+ return { left: left / canvas.width, top: top / canvas.height, width: width / canvas.width, height: height / canvas.height };
24
+ }
25
+ /** Two footprints collide when they share an area; touching edges do not. */
26
+ export function rectsOverlap(a, b) {
27
+ return a.left < b.left + b.width && b.left < a.left + a.width && a.top < b.top + b.height && b.top < a.top + a.height;
28
+ }
29
+ /** How the presenter is framed: close as every portrait was, or wide, lower with room above, a 9:16 view only (#884 S5d). */
30
+ export const PRESENTER_FRAMINGS = ["close", "wide"];
31
+ /** Where the presenter's face sits: 12–48% of the height and the middle 60% of a 9:16 clip, which other formats fit whole and centre (#778 S3). */
32
+ /** A wide 9:16 view puts it at 33–58% and the middle half, as measured on a HeyGen render (#884 S5d). */
33
+ export function faceZone(aspectRatio, framing = "close") {
34
+ if (framing === "wide" && aspectRatio === "9:16")
35
+ return { left: 0.25, top: 0.33, width: 0.5, height: 0.25 };
36
+ const { width, height } = frameCanvasOf(aspectRatio);
37
+ const share = 0.6 * Math.min(1, (9 / 16) / (width / height));
38
+ return { left: (1 - share) / 2, top: 0.12, width: share, height: 0.36 };
39
+ }
40
+ /** The words an item covers, `[startWord, coverWord)`, as an insert anchor resolves; a string names why it does not resolve. */
41
+ export function layerWordRange(tokens, item) {
42
+ let range;
43
+ if ("startWord" in item.anchor) {
44
+ range = { startWord: item.anchor.startWord, endWord: item.anchor.endWord };
45
+ if (range.endWord > tokens.length)
46
+ return `anchor ends at word ${range.endWord}, past the script's ${tokens.length} words`;
47
+ }
48
+ else {
49
+ const matches = quoteOccurrences(tokens, item.anchor.quote);
50
+ if (matches.length === 0)
51
+ return `anchor quote "${item.anchor.quote}" does not occur in script`;
52
+ if (item.anchor.occurrence === undefined && matches.length > 1) {
53
+ return `anchor quote "${item.anchor.quote}" occurs ${matches.length} times in script: pass occurrence`;
54
+ }
55
+ const picked = matches[item.anchor.occurrence ?? 0];
56
+ if (!picked)
57
+ return `anchor quote "${item.anchor.quote}" has no occurrence ${item.anchor.occurrence}`;
58
+ range = picked;
59
+ }
60
+ const coverWord = item.cover_words === undefined ? range.endWord : range.startWord + item.cover_words;
61
+ if (coverWord < range.endWord)
62
+ return `cover_words ${item.cover_words} is fewer than the ${range.endWord - range.startWord} words the anchor names`;
63
+ if (coverWord > tokens.length)
64
+ return `cover_words runs past the script's ${tokens.length} words`;
65
+ return { startWord: range.startWord, coverWord };
66
+ }
67
+ const overlaps = (a, b) => a.startWord < b.coverWord && b.startWord < a.coverWord;
68
+ const coveredBy = (range, cover) => Array.from({ length: range.coverWord - range.startWord }, (_, offset) => range.startWord + offset).every(word => cover.some(other => word >= other.startWord && word < other.coverWord));
69
+ /** Every refusal of overlays and layout windows against the script, named by path; empty when they render. */
70
+ export function layerRefusals(input) {
71
+ const refusals = [];
72
+ const tokens = lexicalTokens(input.script);
73
+ const canvas = frameCanvasOf(input.aspect_ratio ?? "9:16");
74
+ const seen = new Map();
75
+ for (const field of ["inserts", "overlays", "layout_windows"]) {
76
+ for (const [index, item] of (input[field] ?? []).entries()) {
77
+ const owner = seen.get(item.id);
78
+ if (owner !== undefined && field !== "inserts") {
79
+ refusals.push({ path: [field, index, "id"], message: `id "${item.id}" is already used in ${owner}: ids are unique across inserts, overlays and layout_windows` });
80
+ }
81
+ seen.set(item.id, owner ?? field);
82
+ }
83
+ }
84
+ const ranged = (field, items) => (items ?? []).flatMap((item, index) => {
85
+ const range = layerWordRange(tokens, item);
86
+ if (typeof range === "string") {
87
+ refusals.push({ path: [field, index, "anchor"], message: `${field === "overlays" ? "overlay" : "layout window"} "${item.id}": ${range}` });
88
+ return [];
89
+ }
90
+ return [{ item, index, range }];
91
+ });
92
+ const overlays = ranged("overlays", input.overlays);
93
+ const windows = ranged("layout_windows", input.layout_windows);
94
+ const inserts = (input.inserts ?? []).flatMap(item => { const range = layerWordRange(tokens, item); return typeof range === "string" ? [] : [{ item, range }]; });
95
+ for (const [at, layout] of windows.entries()) {
96
+ if (layout.item.layout === "split" && input.aspect_ratio !== undefined && input.aspect_ratio !== "9:16") {
97
+ refusals.push({ path: ["layout_windows", layout.index, "layout"], message: `layout window "${layout.item.id}": split works in 9:16 only, and aspect_ratio is ${input.aspect_ratio}` });
98
+ }
99
+ const earlier = windows.slice(0, at).find(other => overlaps(other.range, layout.range));
100
+ if (earlier) {
101
+ refusals.push({ path: ["layout_windows", layout.index], message: `layout window "${layout.item.id}" overlaps layout window "${earlier.item.id}": windows take the frame one at a time` });
102
+ }
103
+ const insert = inserts.find(other => overlaps(other.range, layout.range));
104
+ if (insert) {
105
+ refusals.push({ path: ["layout_windows", layout.index], message: `layout window "${layout.item.id}" overlaps insert "${insert.item.id}": a window reframes the presenter, who is not on screen during a full-frame insert` });
106
+ }
107
+ }
108
+ for (const [at, overlay] of overlays.entries()) {
109
+ const under = inserts.filter(other => overlaps(other.range, overlay.range));
110
+ if (under.length && coveredBy(overlay.range, under.map(other => other.range))) {
111
+ refusals.push({ path: ["overlays", overlay.index], message: `overlay "${overlay.item.id}" lies wholly under insert "${under[0].item.id}": an overlay draws over the presenter, who is not on screen during a full-frame insert` });
112
+ }
113
+ const together = overlays.slice(0, at).filter(other => overlaps(other.range, overlay.range));
114
+ const clash = together.find(other => rectsOverlap(overlayRect(other.item.position, canvas), overlayRect(overlay.item.position, canvas)));
115
+ if (clash) {
116
+ refusals.push({ path: ["overlays", overlay.index, "position"], message: `overlay "${overlay.item.id}" (${overlay.item.position}) shares the screen with overlay "${clash.item.id}" (${clash.item.position}) at the same time: overlays on screen together need different positions` });
117
+ continue;
118
+ }
119
+ const crowd = together.flatMap((a, i) => together.slice(i + 1).filter(b => Math.max(a.range.startWord, b.range.startWord, overlay.range.startWord) <
120
+ Math.min(a.range.coverWord, b.range.coverWord, overlay.range.coverWord)).map(b => [a, b]))[0];
121
+ if (crowd) {
122
+ refusals.push({ path: ["overlays", overlay.index], message: `overlay "${overlay.item.id}" would be on screen together with "${crowd[0].item.id}" and "${crowd[1].item.id}": at most ${MAX_OVERLAYS_AT_ONCE} overlays show at once` });
123
+ }
124
+ }
125
+ return refusals;
126
+ }
127
+ /** Frames of each word range on the run's narration, by the rule inserts follow: a range ends where its first uncovered word starts. */
128
+ export function resolveLayerFrames(input) {
129
+ const lexical = input.words.filter(word => !/^\p{P}+$/u.test(word.word));
130
+ if (lexical.length !== input.tokens.length || lexical.some((word, index) => lexicalTokens(word.word)[0] !== input.tokens[index])) {
131
+ throw new Error("layer word timings do not follow the script's words");
132
+ }
133
+ return input.layers.map(layer => {
134
+ const startFrame = layer.startWord === 0 ? 0 : Math.round(lexical[layer.startWord].startSec * input.fps);
135
+ const endFrame = layer.coverWord >= lexical.length ? input.totalFrames : Math.round(lexical[layer.coverWord].startSec * input.fps);
136
+ if (!Number.isSafeInteger(startFrame) || endFrame <= startFrame || endFrame > input.totalFrames) {
137
+ throw new Error(`layer ${layer.id} has no frames on the narration`);
138
+ }
139
+ return { id: layer.id, startFrame, endFrame };
140
+ });
141
+ }
142
+ //# sourceMappingURL=ugc-layers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ugc-layers.js","sourceRoot":"","sources":["../src/ugc-layers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import type { MakeUgcInput, PinnedInsertAsset } from "./skills.js";
2
+ /** Codecs Remotion's OffthreadVideo decodes with its bundled FFmpeg, locally and on Lambda; asset ingest takes the same two. */
3
+ export declare const MEDIA_VIDEO_CODECS: readonly ["h264", "hevc"];
4
+ export interface VideoSourceFacts {
5
+ codec?: string | null | undefined;
6
+ pixFmt?: string | null | undefined;
7
+ colorTransfer?: string | null | undefined;
8
+ }
9
+ /** Why a video source cannot be drawn, or `null`. A fact that is not known is not refused here; the worker measures it. */
10
+ export declare function videoMediaRefusal(facts: VideoSourceFacts): string | null;
11
+ /** The quote's warning for a pinned video asset the narration may outlast; the slow speech edge gives the longest its words can take. */
12
+ export declare function videoHoldWarnings(input: Pick<MakeUgcInput, "script" | "inserts" | "overlays" | "layout_windows">, pinned: readonly PinnedInsertAsset[] | undefined): string[];
@@ -0,0 +1,39 @@
1
+ import { WORDS_PER_SECOND_MIN } from "./pacing.js";
2
+ import { lexicalTokens } from "./semantic-inserts.js";
3
+ import { layerWordRange } from "./ugc-layers.js";
4
+ // Video media in inserts, overlays and layout windows of a long-form `make_ugc` run (#778 S2c): muted, held on its last frame when short.
5
+ /** Codecs Remotion's OffthreadVideo decodes with its bundled FFmpeg, locally and on Lambda; asset ingest takes the same two. */
6
+ export const MEDIA_VIDEO_CODECS = ["h264", "hevc"];
7
+ const HDR_TRANSFERS = { smpte2084: "PQ", "arib-std-b67": "HLG" };
8
+ /** Why a video source cannot be drawn, or `null`. A fact that is not known is not refused here; the worker measures it. */
9
+ export function videoMediaRefusal(facts) {
10
+ if (facts.codec && !MEDIA_VIDEO_CODECS.includes(facts.codec)) {
11
+ return `is ${facts.codec} video: video media takes H.264 or HEVC; re-encode it as H.264`;
12
+ }
13
+ const depth = facts.pixFmt ? /(9|1[0-6])(le|be)$/.exec(facts.pixFmt)?.[1] : undefined;
14
+ if (depth)
15
+ return `is ${depth}-bit video (${facts.pixFmt}): video media takes 8-bit video; re-encode it as 8-bit H.264 (yuv420p)`;
16
+ const hdr = facts.colorTransfer ? HDR_TRANSFERS[facts.colorTransfer] : undefined;
17
+ if (hdr)
18
+ return `is HDR video (${hdr}, transfer ${facts.colorTransfer}): video media takes SDR video; re-encode it as SDR BT.709`;
19
+ return null;
20
+ }
21
+ const LISTS = [["inserts", "insert"], ["overlays", "overlay"], ["layout_windows", "layout window"]];
22
+ /** The quote's warning for a pinned video asset the narration may outlast; the slow speech edge gives the longest its words can take. */
23
+ export function videoHoldWarnings(input, pinned) {
24
+ if (!pinned?.length || typeof input.script !== "string")
25
+ return [];
26
+ const tokens = lexicalTokens(input.script);
27
+ return LISTS.flatMap(([list, noun]) => (input[list] ?? []).flatMap((item, index) => {
28
+ const asset = pinned.find(one => one.insert_id === item.id);
29
+ if (item.media_type !== "video" || asset?.kind !== "video" || !asset.duration_frames || !asset.fps)
30
+ return [];
31
+ const range = layerWordRange(tokens, item);
32
+ if (typeof range === "string")
33
+ return [];
34
+ const words = range.coverWord - range.startWord, clipSec = asset.duration_frames / asset.fps, longestSec = words / WORDS_PER_SECOND_MIN;
35
+ return clipSec < longestSec ? [`${list}[${index}] ${noun} ${item.id}: its video asset runs ${clipSec.toFixed(1)} s, and the ${words} words ` +
36
+ `it covers can take up to ${longestSec.toFixed(1)} s; if the narration outlasts the clip, its last frame holds to the end`] : [];
37
+ }));
38
+ }
39
+ //# sourceMappingURL=ugc-video-media.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ugc-video-media.js","sourceRoot":"","sources":["../src/ugc-video-media.ts"],"names":[],"mappings":"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"}
@@ -21,6 +21,10 @@ export declare function markVendorJobVerdict<E>(error: E, verdict: VendorJobVerd
21
21
  /** The vendor's verdict on the job. `undefined`: nothing terminal was said (polling broke, */
22
22
  /** timed out, wrong status). That is ignorance, and an operation must not be closed on it. */
23
23
  export declare function vendorJobVerdict(error: unknown): VendorJobVerdict | undefined;
24
+ /** Marks a failed job the vendor itself reports as not billed (kie: no `creditsConsumed`, #857 S3). */
25
+ /** Only the adapter that read the vendor's answer sets it; no mark means the job may be billed. */
26
+ export declare function markVendorJobUnbilled<E>(error: E): E;
27
+ export declare function vendorJobUnbilled(error: unknown): boolean;
24
28
  /** Whose fault a vendor refusal is. `unknown` is the honest answer and keeps the previous */
25
29
  /** behavior (not zero). */
26
30
  export type VendorRefusalClass = "account_standing" | "vendor" | "unknown";
@@ -69,6 +69,18 @@ export function vendorJobVerdict(error) {
69
69
  const value = error[VENDOR_JOB_VERDICT];
70
70
  return value === "succeeded" || value === "failed" ? value : undefined;
71
71
  }
72
+ const VENDOR_JOB_UNBILLED = "clipwrightVendorJobUnbilled";
73
+ /** Marks a failed job the vendor itself reports as not billed (kie: no `creditsConsumed`, #857 S3). */
74
+ /** Only the adapter that read the vendor's answer sets it; no mark means the job may be billed. */
75
+ export function markVendorJobUnbilled(error) {
76
+ if (typeof error !== "object" || error === null)
77
+ return error;
78
+ Object.defineProperty(error, VENDOR_JOB_UNBILLED, { value: true, enumerable: false, writable: false, configurable: true });
79
+ return error;
80
+ }
81
+ export function vendorJobUnbilled(error) {
82
+ return typeof error === "object" && error !== null && error[VENDOR_JOB_UNBILLED] === true;
83
+ }
72
84
  const VENDOR_REFUSAL_CLASS = "clipwrightVendorRefusalClass";
73
85
  /** Marks the error with what the vendor itself said about the refusal cause. */
74
86
  export function markVendorRefusal(error, refusal) {
@@ -1 +1 @@
1
- {"version":3,"file":"vendor-response.js","sourceRoot":"","sources":["../src/vendor-response.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"vendor-response.js","sourceRoot":"","sources":["../src/vendor-response.ts"],"names":[],"mappings":"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"}