@koda-sl/baker-cli 0.575.0-dev.85f21462e → 0.576.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 (879) hide show
  1. package/README.md +1 -1
  2. package/dist/account-H44DUS4O.js +82 -0
  3. package/dist/account-WFAMHUCQ.js +82 -0
  4. package/dist/account-reads-JPQ2K343.js +219 -0
  5. package/dist/account-users-R3CIZPV5.js +64 -0
  6. package/dist/account-writes-EEKHPF5I.js +68 -0
  7. package/dist/accounts-GGP5J2FI.js +498 -0
  8. package/dist/accounts-H3KO5AEN.js +119 -0
  9. package/dist/accounts-K5IASJQV.js +80 -0
  10. package/dist/actions-JXDJOGSY.js +55 -0
  11. package/dist/activecampaign-LXLAD2PF.js +938 -0
  12. package/dist/ad-group-writes-UDQ4563V.js +172 -0
  13. package/dist/ad-groups-RXT2XKSE.js +70 -0
  14. package/dist/ad-writes-SHLTL2FY.js +176 -0
  15. package/dist/add-DJQ5B245.js +305 -0
  16. package/dist/add-MPXVC7L3.js +107 -0
  17. package/dist/ads-2TUJH4L3.js +48 -0
  18. package/dist/ads-CUMOMBI3.js +79 -0
  19. package/dist/advertisers-EWSPWD6I.js +123 -0
  20. package/dist/alerts-4FE3PUUK.js +151 -0
  21. package/dist/analytics-HZDE5TKC.js +447 -0
  22. package/dist/analytics-QEYAVXZB.js +2397 -0
  23. package/dist/animate-MBNFCDUZ.js +480 -0
  24. package/dist/assign-JZ5E7XRJ.js +80 -0
  25. package/dist/audience-size-UXIGBCIO.js +76 -0
  26. package/dist/audiences-KBW2UAOP.js +280 -0
  27. package/dist/audit-B2X3ON7Y.js +154 -0
  28. package/dist/autocomplete-VB74AP3J.js +114 -0
  29. package/dist/avatars-WINNSCJK.js +38 -0
  30. package/dist/bid-pricing-JAR4EBDA.js +103 -0
  31. package/dist/brand-ZLBQSOKD.js +22 -0
  32. package/dist/brief-35KFM74X.js +543 -0
  33. package/dist/campaign-groups-2HUFNJK6.js +99 -0
  34. package/dist/campaign-writes-JYMQF6CK.js +176 -0
  35. package/dist/campaign-writes-SZX7DHNE.js +168 -0
  36. package/dist/campaigns-6NWQZXBM.js +113 -0
  37. package/dist/campaigns-DIP7NUSQ.js +111 -0
  38. package/dist/campaigns-TMHFCPAZ.js +78 -0
  39. package/dist/canvas-JP5EFSGB.js +46 -0
  40. package/dist/capabilities-2SLWTKI5.js +147 -0
  41. package/dist/catalog-2P422WOQ.js +66 -0
  42. package/dist/catalogs-XFYYY3CS.js +130 -0
  43. package/dist/changes-GFJITHF6.js +167 -0
  44. package/dist/chatgpt-KNLATOZ6.js +47 -0
  45. package/dist/chats-FID6CLCA.js +589 -0
  46. package/dist/check-M337BOPG.js +107 -0
  47. package/dist/chunk-2QAYZXPI.js +494 -0
  48. package/dist/chunk-37QNC344.js +843 -0
  49. package/dist/chunk-3WLUQ7DM.js +757 -0
  50. package/dist/chunk-3XGZFZVD.js +454 -0
  51. package/dist/chunk-4DHHMWP4.js +24026 -0
  52. package/dist/chunk-4DHHMWP4.js.map +1 -0
  53. package/dist/chunk-4GRVNPHA.js +274 -0
  54. package/dist/chunk-4HQR2O2K.js +479 -0
  55. package/dist/chunk-6CRNIIYN.js +604 -0
  56. package/dist/chunk-6LDG4LFO.js +455 -0
  57. package/dist/chunk-6LLA6IF6.js +285 -0
  58. package/dist/chunk-6PJGHPXG.js +131 -0
  59. package/dist/chunk-73NWLLZ3.js +8998 -0
  60. package/dist/chunk-73NWLLZ3.js.map +1 -0
  61. package/dist/chunk-7CVBEA7J.js +61 -0
  62. package/dist/chunk-7HZTVVO7.js +504 -0
  63. package/dist/chunk-7LFOSBF4.js +3510 -0
  64. package/dist/chunk-A7ICTIR5.js +51 -0
  65. package/dist/chunk-AUFQAR3V.js +220 -0
  66. package/dist/chunk-AYOTYURE.js +1518 -0
  67. package/dist/chunk-B2S5TT4L.js +547 -0
  68. package/dist/chunk-BMMXYR7A.js +238 -0
  69. package/dist/chunk-BNEWJXKU.js +638 -0
  70. package/dist/chunk-BS4VGXTM.js +19 -0
  71. package/dist/chunk-BUNG52KH.js +432 -0
  72. package/dist/chunk-BYV4VS5E.js +5471 -0
  73. package/dist/chunk-DCBCEYSH.js +98 -0
  74. package/dist/chunk-DWJV6IOW.js +224 -0
  75. package/dist/chunk-DZIP5OQX.js +142 -0
  76. package/dist/chunk-E7LNNUKD.js +23 -0
  77. package/dist/chunk-FTP6NDOU.js +1320 -0
  78. package/dist/chunk-FZQU47P4.js +163 -0
  79. package/dist/chunk-G624WZD6.js +66 -0
  80. package/dist/chunk-GBXTEXVK.js +297 -0
  81. package/dist/chunk-HFQSTIM5.js +344 -0
  82. package/dist/chunk-IGCS3X4F.js +150 -0
  83. package/dist/chunk-IPDDXD5K.js +8141 -0
  84. package/dist/chunk-IPDDXD5K.js.map +1 -0
  85. package/dist/chunk-IQ2V4ENC.js +91 -0
  86. package/dist/chunk-JAC6JVCI.js +26 -0
  87. package/dist/chunk-JMTCCPK6.js +930 -0
  88. package/dist/chunk-JTYD7A3C.js +225 -0
  89. package/dist/chunk-L3MNDL6D.js +392 -0
  90. package/dist/chunk-LJ4AMUHS.js +309 -0
  91. package/dist/chunk-LRIP2J5S.js +5368 -0
  92. package/dist/chunk-M7BSXJNL.js +167 -0
  93. package/dist/chunk-MCJ5I5LR.js +3187 -0
  94. package/dist/chunk-MCJ5I5LR.js.map +1 -0
  95. package/dist/chunk-MI327KRO.js +399 -0
  96. package/dist/chunk-MJCOTA6T.js +312 -0
  97. package/dist/chunk-MQU4LNYG.js +46 -0
  98. package/dist/chunk-MZPS46OR.js +76 -0
  99. package/dist/chunk-N24ZFIEW.js +169 -0
  100. package/dist/chunk-N6OIIBTB.js +170 -0
  101. package/dist/chunk-NEALLMDP.js +1919 -0
  102. package/dist/chunk-NGHOYXJD.js +962 -0
  103. package/dist/chunk-NPAXHLAP.js +351 -0
  104. package/dist/chunk-OG76GZU3.js +78 -0
  105. package/dist/chunk-OU542F66.js +819 -0
  106. package/dist/chunk-OWO3CB6D.js +103 -0
  107. package/dist/chunk-OXH63BGJ.js +57 -0
  108. package/dist/chunk-Q45FEJZ6.js +249 -0
  109. package/dist/chunk-QENSBNRJ.js +1258 -0
  110. package/dist/chunk-QKGIXXXB.js +89 -0
  111. package/dist/chunk-SR65SC66.js +91 -0
  112. package/dist/chunk-T5TJJJGI.js +156 -0
  113. package/dist/chunk-TQIEDVJB.js +218 -0
  114. package/dist/chunk-UWWL7QIQ.js +197 -0
  115. package/dist/chunk-WPBXN37A.js +2234 -0
  116. package/dist/chunk-XHWHBGKX.js +4277 -0
  117. package/dist/chunk-XHWHBGKX.js.map +1 -0
  118. package/dist/chunk-XQNWHPRV.js +685 -0
  119. package/dist/chunk-XWWX3WFJ.js +259 -0
  120. package/dist/chunk-Y25W6RSY.js +203 -0
  121. package/dist/chunk-YP5SD6O2.js +148 -0
  122. package/dist/chunk-Z3KRNKEA.js +64 -0
  123. package/dist/chunk-ZWFYBQ7N.js +1920 -0
  124. package/dist/claim-DXDA6XRM.js +200 -0
  125. package/dist/cli.js +32 -32
  126. package/dist/companies-UNAN4THP.js +34 -0
  127. package/dist/company-ALE2HVTA.js +308 -0
  128. package/dist/complete-GZC6MQD2.js +84 -0
  129. package/dist/connect-664TAEG6.js +45 -0
  130. package/dist/conversation-AYXZYWMG.js +96 -0
  131. package/dist/conversion-report-6SVHPLHT.js +127 -0
  132. package/dist/conversion-upload-command-J3STKMAL.js +439 -0
  133. package/dist/conversion-writes-PEKNBIDQ.js +122 -0
  134. package/dist/conversions-ICSKSSLX.js +78 -0
  135. package/dist/conversions-SHKCWNNC.js +140 -0
  136. package/dist/create-2FCQZ7PD.js +239 -0
  137. package/dist/create-42TY74QW.js +62 -0
  138. package/dist/create-7EJEY5EK.js +135 -0
  139. package/dist/create-SKI4H2XI.js +218 -0
  140. package/dist/creatives-OBKNNJAI.js +229 -0
  141. package/dist/creatives-QNPP5S4Q.js +58 -0
  142. package/dist/credentials-BCMMD3XG.js +290 -0
  143. package/dist/critique-KSQKDC7Y.js +232 -0
  144. package/dist/critique-NWZIHUBH.js +1451 -0
  145. package/dist/crm-ANNNZDM5.js +323 -0
  146. package/dist/crm-NP5LXKMN.js +313 -0
  147. package/dist/currency-YZBACARU.js +88 -0
  148. package/dist/customers-IUS7M6PJ.js +65 -0
  149. package/dist/delete-NBHAHWZ7.js +57 -0
  150. package/dist/delete-OJPKAYMV.js +69 -0
  151. package/dist/delete-Y75QNAE4.js +67 -0
  152. package/dist/demographics-HDUPFELB.js +141 -0
  153. package/dist/discard-32HKP4BV.js +69 -0
  154. package/dist/discover-RKW25QME.js +172 -0
  155. package/dist/domain-ODCRVC6V.js +101 -0
  156. package/dist/download-75W2T7R7.js +172 -0
  157. package/dist/draft-3KPRQ3YL.js +374 -0
  158. package/dist/draft-EHDIVMWL.js +615 -0
  159. package/dist/draft-VJPB5MFJ.js +332 -0
  160. package/dist/draft-X6Y62O3Y.js +220 -0
  161. package/dist/draft-ZDS6KFZ3.js +315 -0
  162. package/dist/engine/index.js +8 -8
  163. package/dist/experiments-GECLY35Q.js +236 -0
  164. package/dist/extract-KYD4M3XU.js +143 -0
  165. package/dist/facets-CA7J44EY.js +117 -0
  166. package/dist/feedback-FB2QIIRX.js +115 -0
  167. package/dist/feedback-P36JL2MA.js +114 -0
  168. package/dist/feedback-record-O4KVZAOF.js +269 -0
  169. package/dist/fetch-Z42TLLI4.js +204 -0
  170. package/dist/fit-ANYF4UJ2.js +65 -0
  171. package/dist/flows-3KUFFMLO.js +340 -0
  172. package/dist/fonts-TAJRK4HZ.js +39 -0
  173. package/dist/forecast-327XLLZ3.js +169 -0
  174. package/dist/forecast-FIYKBAEW.js +121 -0
  175. package/dist/funnel-OGQVXGM7.js +397 -0
  176. package/dist/generate-GBFLO76C.js +263 -0
  177. package/dist/get-LM4KTWKF.js +82 -0
  178. package/dist/get-OSBYMC2N.js +62 -0
  179. package/dist/google-FMGXNCW3.js +3300 -0
  180. package/dist/google-RHPQWNMK.js +163 -0
  181. package/dist/google-ads-EHJBMUJ4.js +198 -0
  182. package/dist/history-6X3VIQP3.js +102 -0
  183. package/dist/history-CDHA25XG.js +153 -0
  184. package/dist/history-K4VYVCZC.js +69 -0
  185. package/dist/hubspot-7E6EAUIV.js +817 -0
  186. package/dist/ideas-3UNEUSMO.js +45 -0
  187. package/dist/images-7KJX5JFY.js +92 -0
  188. package/dist/ingest-4Y35DBZV.js +28 -0
  189. package/dist/ingest-LGZ3R4OI.js +131 -0
  190. package/dist/insights-RHOCF7VR.js +132 -0
  191. package/dist/inspect-WYOMSTBG.js +192 -0
  192. package/dist/intent-TKFH57DZ.js +95 -0
  193. package/dist/keyword-gap-7I2CIUTK.js +130 -0
  194. package/dist/keyword-metrics-35TFEXA5.js +200 -0
  195. package/dist/keywords-for-site-IMHNWTTB.js +131 -0
  196. package/dist/landing-RKUGZ3LB.js +28 -0
  197. package/dist/languages-FMHPUVOL.js +40 -0
  198. package/dist/leads-C46ZXIXF.js +115 -0
  199. package/dist/learn-WDPCW5ZD.js +207 -0
  200. package/dist/line-item-writes-IZKFY3GR.js +211 -0
  201. package/dist/line-items-CBVRZ43V.js +107 -0
  202. package/dist/link-GEPIZSVI.js +67 -0
  203. package/dist/linkedin-FHEYMG4M.js +1381 -0
  204. package/dist/linkedin-person-2M3WBL66.js +139 -0
  205. package/dist/list-APJDJZL7.js +154 -0
  206. package/dist/list-CLJN4YN5.js +67 -0
  207. package/dist/list-LE6DJG44.js +306 -0
  208. package/dist/locations-DD3JRZ4C.js +69 -0
  209. package/dist/locations-HWMEJ64P.js +40 -0
  210. package/dist/log-FC2GLXIK.js +95 -0
  211. package/dist/make-4IIUKMLK.js +1367 -0
  212. package/dist/map-DGS5KKDJ.js +445 -0
  213. package/dist/mcp-IRG5E6U3.js +729 -0
  214. package/dist/media-sources-SXUKFPBW.js +35 -0
  215. package/dist/members-TNY3CQSI.js +47 -0
  216. package/dist/metrics-KXTFXSWK.js +152 -0
  217. package/dist/models-2ZEM64H5.js +155 -0
  218. package/dist/normalize-74VF6BZV.js +144 -0
  219. package/dist/options-LNJH5LJR.js +125 -0
  220. package/dist/organization-DHYTS3KH.js +949 -0
  221. package/dist/people-R3YTQXYH.js +164 -0
  222. package/dist/people-U6EP77HS.js +171 -0
  223. package/dist/performance-AZGVR3IG.js +27 -0
  224. package/dist/performance-LYBUVYLQ.js +5565 -0
  225. package/dist/pixels-3CINROKJ.js +62 -0
  226. package/dist/preview-3OGMMUT4.js +101 -0
  227. package/dist/promoted-tweet-writes-EPNO2VUY.js +183 -0
  228. package/dist/promoted-tweets-UNG4FV3M.js +119 -0
  229. package/dist/publish-YHU5K76M.js +350 -0
  230. package/dist/query-NYH5PMQF.js +62 -0
  231. package/dist/reddit-BYHNEZWI.js +29 -0
  232. package/dist/refresh-3L4DCDVG.js +97 -0
  233. package/dist/release-LIDQL3KW.js +63 -0
  234. package/dist/relevant-pages-QIF35NBQ.js +99 -0
  235. package/dist/remove-RZSRYB4K.js +53 -0
  236. package/dist/reopen-C2SDKYRQ.js +66 -0
  237. package/dist/rerun-5JHAKEXF.js +97 -0
  238. package/dist/research-BNUMVIBI.js +265 -0
  239. package/dist/research-JQGHHTHS.js +78 -0
  240. package/dist/reset-FZ475DZK.js +57 -0
  241. package/dist/reset-MES3UU3L.js +57 -0
  242. package/dist/resolve-3EJ2ZI64.js +124 -0
  243. package/dist/retry-IMGUCVDF.js +63 -0
  244. package/dist/retry-OFFHBZG2.js +65 -0
  245. package/dist/revenue-IACHOM7M.js +91 -0
  246. package/dist/rules-C72VPDXE.js +99 -0
  247. package/dist/rules-add-A3PKTQNR.js +465 -0
  248. package/dist/run-XVULTREI.js +72 -0
  249. package/dist/run-XYRUAAJH.js +69 -0
  250. package/dist/scaffold-ad-Y4FKVKVJ.js +1513 -0
  251. package/dist/scaffold-static-ad-TVMEGBHZ.js +1012 -0
  252. package/dist/scaffold-video-JYUGPW2L.js +885 -0
  253. package/dist/schedule-NMMJZXZH.js +64 -0
  254. package/dist/scheduled-agents-NFVSFOPB.js +56 -0
  255. package/dist/schema-MIWJBYFP.js +135 -0
  256. package/dist/search-B3EI65TS.js +177 -0
  257. package/dist/select-UH73L657.js +110 -0
  258. package/dist/set-prompt-Y3IPUFUH.js +199 -0
  259. package/dist/setup-links-2Y3A676T.js +144 -0
  260. package/dist/shopify-5LZ5IWSB.js +4009 -0
  261. package/dist/site-GXH6QLNZ.js +180 -0
  262. package/dist/sources-7VWSZZHQ.js +30 -0
  263. package/dist/sources-KYAVCA5P.js +457 -0
  264. package/dist/stale-TDAEKOJB.js +90 -0
  265. package/dist/status-II4PTBUU.js +65 -0
  266. package/dist/stock-WZN53KCQ.js +212 -0
  267. package/dist/studio-TG2UAKFI.js +49 -0
  268. package/dist/sync-OSHJH7TD.js +57 -0
  269. package/dist/sync-definition-AP6CA6BU.js +70 -0
  270. package/dist/tags-36OYKBFE.js +227 -0
  271. package/dist/tags-3K6QGK5B.js +26 -0
  272. package/dist/tags-53FUK4HL.js +23 -0
  273. package/dist/tags-B3Z3OQ6G.js +23 -0
  274. package/dist/tags-DXKEOOGL.js +23 -0
  275. package/dist/targeting-criteria-UFE3MLWR.js +113 -0
  276. package/dist/targets-JSBKVSRO.js +106 -0
  277. package/dist/testimonials-6KYRLQVP.js +32 -0
  278. package/dist/themes-7XHHY4XY.js +95 -0
  279. package/dist/top-companies-W3GBGJGL.js +246 -0
  280. package/dist/transcript-VTVLH4VV.js +165 -0
  281. package/dist/translate-TIFUZLPE.js +603 -0
  282. package/dist/triggers-ULFGRFHQ.js +144 -0
  283. package/dist/unlink-FGUCQNNF.js +70 -0
  284. package/dist/unstage-UHKSQUPR.js +88 -0
  285. package/dist/update-CF6437MN.js +192 -0
  286. package/dist/update-G2IRXCSJ.js +66 -0
  287. package/dist/update-KO5VEPRN.js +101 -0
  288. package/dist/update-OQUIUKSX.js +155 -0
  289. package/dist/upload-GD552SG7.js +137 -0
  290. package/dist/url-options-RTTLWCU5.js +131 -0
  291. package/dist/url-params-ZFX3EBLE.js +101 -0
  292. package/dist/validate-BBXOFK4S.js +135 -0
  293. package/dist/videos-OA3PSDF6.js +41 -0
  294. package/dist/viewer-check-OIORNTQG.js +83 -0
  295. package/dist/web-RKEKSDU3.js +173 -0
  296. package/dist/winning-ads-CJQEQ6JQ.js +86 -0
  297. package/dist/write-commands-CPAOTG6H.js +1524 -0
  298. package/dist/x-PF3FDWKU.js +47 -0
  299. package/package.json +1 -1
  300. package/dist/account-MDLPCIDQ.js +0 -82
  301. package/dist/account-VRXCDDXY.js +0 -82
  302. package/dist/account-reads-FSOURMSH.js +0 -219
  303. package/dist/account-users-FXOWESWY.js +0 -64
  304. package/dist/account-writes-SRTOKSMT.js +0 -68
  305. package/dist/accounts-5YJZVSTB.js +0 -498
  306. package/dist/accounts-AT2UB2L3.js +0 -80
  307. package/dist/accounts-NR3ARJ72.js +0 -119
  308. package/dist/actions-766X6XRB.js +0 -55
  309. package/dist/activecampaign-MC4FYCCF.js +0 -938
  310. package/dist/ad-group-writes-UFBFB2PL.js +0 -172
  311. package/dist/ad-groups-KRKMZPF3.js +0 -70
  312. package/dist/ad-writes-SIAGGUDJ.js +0 -176
  313. package/dist/add-DWKVVW76.js +0 -305
  314. package/dist/add-MYX3BSUJ.js +0 -107
  315. package/dist/ads-3T4C4BBH.js +0 -79
  316. package/dist/ads-UGMHE33I.js +0 -48
  317. package/dist/advertisers-UFOLIRIK.js +0 -123
  318. package/dist/alerts-2GMBX6JV.js +0 -151
  319. package/dist/analytics-3EWNAHNG.js +0 -2397
  320. package/dist/analytics-G4WFP37R.js +0 -447
  321. package/dist/animate-PSOAMA52.js +0 -480
  322. package/dist/assign-5FALEZYD.js +0 -80
  323. package/dist/audience-size-VRYRLPO5.js +0 -76
  324. package/dist/audiences-EH426E3T.js +0 -280
  325. package/dist/audit-WHIVWMAI.js +0 -154
  326. package/dist/autocomplete-3HCLXTGK.js +0 -114
  327. package/dist/avatars-HN74FWDF.js +0 -38
  328. package/dist/bid-pricing-NN5JKZS4.js +0 -103
  329. package/dist/brand-MWU5IVEZ.js +0 -22
  330. package/dist/brief-6TXWQWHJ.js +0 -543
  331. package/dist/campaign-groups-MGEKCP7J.js +0 -99
  332. package/dist/campaign-writes-ORUT54WL.js +0 -168
  333. package/dist/campaign-writes-Z7B6V6Q3.js +0 -176
  334. package/dist/campaigns-3BDIHUSW.js +0 -78
  335. package/dist/campaigns-E7YC762Q.js +0 -111
  336. package/dist/campaigns-WLOJFSLV.js +0 -113
  337. package/dist/canvas-SEVIQRXN.js +0 -46
  338. package/dist/capabilities-KWJYBYQO.js +0 -147
  339. package/dist/catalog-DHTZDVWS.js +0 -66
  340. package/dist/catalogs-R4QFA5XO.js +0 -130
  341. package/dist/changes-F2GP72MO.js +0 -167
  342. package/dist/chatgpt-MN4XHO6L.js +0 -47
  343. package/dist/chats-IBMO724I.js +0 -589
  344. package/dist/check-EZI4OF3Q.js +0 -107
  345. package/dist/chunk-2CSNR4U7.js +0 -8954
  346. package/dist/chunk-2CSNR4U7.js.map +0 -1
  347. package/dist/chunk-2VUD4CIW.js +0 -64
  348. package/dist/chunk-423G75A7.js +0 -494
  349. package/dist/chunk-4ZAHRAWL.js +0 -454
  350. package/dist/chunk-5WOZ7OGU.js +0 -1919
  351. package/dist/chunk-66LUQENO.js +0 -197
  352. package/dist/chunk-6J2UZJ6F.js +0 -962
  353. package/dist/chunk-6OIKNJ7G.js +0 -26
  354. package/dist/chunk-7EPR7L2D.js +0 -203
  355. package/dist/chunk-AFWLBOIN.js +0 -757
  356. package/dist/chunk-ALCRXFIZ.js +0 -351
  357. package/dist/chunk-BJH2G3QF.js +0 -312
  358. package/dist/chunk-BTOGDXA4.js +0 -8141
  359. package/dist/chunk-BTOGDXA4.js.map +0 -1
  360. package/dist/chunk-BZXIDMV7.js +0 -91
  361. package/dist/chunk-C57NXUM2.js +0 -24026
  362. package/dist/chunk-C57NXUM2.js.map +0 -1
  363. package/dist/chunk-CNZ5KS4I.js +0 -344
  364. package/dist/chunk-D32EWSMB.js +0 -150
  365. package/dist/chunk-DAXBST7G.js +0 -51
  366. package/dist/chunk-DD6X3AZB.js +0 -1258
  367. package/dist/chunk-DI7M2JUA.js +0 -167
  368. package/dist/chunk-EA3643ET.js +0 -392
  369. package/dist/chunk-EBFKPGTL.js +0 -220
  370. package/dist/chunk-ETHUDFUY.js +0 -169
  371. package/dist/chunk-EZ3YSJTP.js +0 -685
  372. package/dist/chunk-F3CZFUXZ.js +0 -3187
  373. package/dist/chunk-F3CZFUXZ.js.map +0 -1
  374. package/dist/chunk-G6CLJ3WL.js +0 -3510
  375. package/dist/chunk-GLY3CB2F.js +0 -78
  376. package/dist/chunk-HXHGDFXA.js +0 -103
  377. package/dist/chunk-IEUF733F.js +0 -5471
  378. package/dist/chunk-IEX4RRHJ.js +0 -163
  379. package/dist/chunk-IMS53EQU.js +0 -4277
  380. package/dist/chunk-IMS53EQU.js.map +0 -1
  381. package/dist/chunk-IR2NRXHA.js +0 -309
  382. package/dist/chunk-J7L457MF.js +0 -1518
  383. package/dist/chunk-JFWTQDZL.js +0 -604
  384. package/dist/chunk-JGMQD3PX.js +0 -274
  385. package/dist/chunk-JTAPNHW5.js +0 -98
  386. package/dist/chunk-K2DKQ52D.js +0 -89
  387. package/dist/chunk-K3VMHRLJ.js +0 -61
  388. package/dist/chunk-LBPJDFFN.js +0 -19
  389. package/dist/chunk-LNRYMWXE.js +0 -930
  390. package/dist/chunk-LQRPFL2N.js +0 -218
  391. package/dist/chunk-LY7PDE76.js +0 -285
  392. package/dist/chunk-NOCBNING.js +0 -638
  393. package/dist/chunk-PEPLYJWK.js +0 -91
  394. package/dist/chunk-PK2U2ALQ.js +0 -57
  395. package/dist/chunk-PKSIPLMS.js +0 -399
  396. package/dist/chunk-QNY4IK3C.js +0 -297
  397. package/dist/chunk-QORVZUMT.js +0 -2234
  398. package/dist/chunk-RDIZCSTV.js +0 -156
  399. package/dist/chunk-RQ43VL2X.js +0 -148
  400. package/dist/chunk-S4QGD7PV.js +0 -170
  401. package/dist/chunk-S7WFZYKP.js +0 -46
  402. package/dist/chunk-SIKCVWM3.js +0 -76
  403. package/dist/chunk-SRMQCQ7T.js +0 -142
  404. package/dist/chunk-SZFWQVAC.js +0 -819
  405. package/dist/chunk-TBBAHTP3.js +0 -1320
  406. package/dist/chunk-U6EQMX3B.js +0 -131
  407. package/dist/chunk-UECTXVAO.js +0 -479
  408. package/dist/chunk-UQTINFCP.js +0 -455
  409. package/dist/chunk-UUUYWBTR.js +0 -225
  410. package/dist/chunk-UZ5ZC43B.js +0 -259
  411. package/dist/chunk-VSHXHSIW.js +0 -249
  412. package/dist/chunk-VTLW24DM.js +0 -23
  413. package/dist/chunk-WZXMZFVB.js +0 -238
  414. package/dist/chunk-X7NRAGJ5.js +0 -504
  415. package/dist/chunk-XYHAIEAF.js +0 -5368
  416. package/dist/chunk-XZJK2QB3.js +0 -1920
  417. package/dist/chunk-YLHWZOW7.js +0 -224
  418. package/dist/chunk-YNWBIAXJ.js +0 -843
  419. package/dist/chunk-YYYGUO2E.js +0 -66
  420. package/dist/chunk-ZAQQBVEM.js +0 -432
  421. package/dist/chunk-ZHQSXEJ2.js +0 -547
  422. package/dist/claim-JQCSXR4C.js +0 -200
  423. package/dist/companies-GHBIZKOK.js +0 -34
  424. package/dist/company-KNCYMQIA.js +0 -308
  425. package/dist/complete-V53XRNEQ.js +0 -84
  426. package/dist/connect-NUZQSIGL.js +0 -45
  427. package/dist/conversation-LBYO6ONM.js +0 -96
  428. package/dist/conversion-report-SRHJGIMT.js +0 -127
  429. package/dist/conversion-upload-command-5EKILBP2.js +0 -439
  430. package/dist/conversion-writes-P5FDTA6Y.js +0 -122
  431. package/dist/conversions-BXCGFNRK.js +0 -140
  432. package/dist/conversions-WJBOEPOO.js +0 -78
  433. package/dist/create-3PNWKXLP.js +0 -239
  434. package/dist/create-6FZR7JZT.js +0 -135
  435. package/dist/create-QXJ3UEOT.js +0 -218
  436. package/dist/create-XO7HUNPB.js +0 -62
  437. package/dist/creatives-O6TA2DOG.js +0 -58
  438. package/dist/creatives-YRYPXOCS.js +0 -229
  439. package/dist/credentials-ATAP54ZI.js +0 -290
  440. package/dist/critique-3UY7TUVQ.js +0 -232
  441. package/dist/critique-UC6SBKGO.js +0 -1451
  442. package/dist/crm-AXK74BCO.js +0 -313
  443. package/dist/crm-MGVGQ7PK.js +0 -323
  444. package/dist/currency-335ARWP5.js +0 -88
  445. package/dist/customers-7NBNJCDC.js +0 -65
  446. package/dist/delete-EKGTJSLK.js +0 -69
  447. package/dist/delete-OFG7FBMA.js +0 -57
  448. package/dist/delete-QQDGR7DD.js +0 -67
  449. package/dist/demographics-QWFAMEC2.js +0 -141
  450. package/dist/discard-4VW3AWI3.js +0 -69
  451. package/dist/discover-O6322XPL.js +0 -172
  452. package/dist/domain-EDPDUVAX.js +0 -101
  453. package/dist/download-46GLVBYU.js +0 -172
  454. package/dist/draft-IBR2W6GZ.js +0 -332
  455. package/dist/draft-NCUQFRGS.js +0 -315
  456. package/dist/draft-RRUJU2ZR.js +0 -220
  457. package/dist/draft-SLGJRUOV.js +0 -615
  458. package/dist/draft-TJAD7P6W.js +0 -374
  459. package/dist/experiments-DUVO7C7A.js +0 -236
  460. package/dist/extract-WYNFE6TQ.js +0 -143
  461. package/dist/facets-WTY6NOUV.js +0 -117
  462. package/dist/feedback-57BP27NA.js +0 -115
  463. package/dist/feedback-XDREGDOK.js +0 -114
  464. package/dist/feedback-record-HXSBLAZD.js +0 -269
  465. package/dist/fetch-L27MLPXM.js +0 -204
  466. package/dist/fit-K3G7HIMK.js +0 -65
  467. package/dist/flows-VJTWU3SU.js +0 -340
  468. package/dist/fonts-SEMIVGXJ.js +0 -39
  469. package/dist/forecast-EHOMHLUH.js +0 -169
  470. package/dist/forecast-VODA7N3G.js +0 -121
  471. package/dist/funnel-BXJDMVMF.js +0 -397
  472. package/dist/generate-VCGSO7HI.js +0 -263
  473. package/dist/get-EASXXOQR.js +0 -62
  474. package/dist/get-EN4UQI7R.js +0 -82
  475. package/dist/google-ATEQHENA.js +0 -163
  476. package/dist/google-ZVVKAI7T.js +0 -3300
  477. package/dist/google-ads-OUNSPGRQ.js +0 -198
  478. package/dist/history-5OJVW2ZF.js +0 -153
  479. package/dist/history-RQMCZQSC.js +0 -69
  480. package/dist/history-TDGBO76N.js +0 -102
  481. package/dist/hubspot-VQGONQQU.js +0 -817
  482. package/dist/ideas-B7RQXWHQ.js +0 -45
  483. package/dist/images-Q45MP4Q2.js +0 -92
  484. package/dist/ingest-6MMY4KDM.js +0 -131
  485. package/dist/ingest-UMQQIINM.js +0 -28
  486. package/dist/insights-WDHDMULM.js +0 -132
  487. package/dist/inspect-W2BIGA5F.js +0 -192
  488. package/dist/intent-3S6SHAYC.js +0 -95
  489. package/dist/keyword-gap-MGHKWE6A.js +0 -130
  490. package/dist/keyword-metrics-6R5TSHCE.js +0 -200
  491. package/dist/keywords-for-site-EFBLFX6E.js +0 -131
  492. package/dist/landing-WC5FX3UP.js +0 -28
  493. package/dist/languages-4J7JHZNB.js +0 -40
  494. package/dist/leads-CBOQ5CNM.js +0 -115
  495. package/dist/learn-ZUP35H3T.js +0 -207
  496. package/dist/line-item-writes-W4UFIYEA.js +0 -211
  497. package/dist/line-items-SGCUJF3S.js +0 -107
  498. package/dist/link-KLJB7COB.js +0 -67
  499. package/dist/linkedin-TANR45ZZ.js +0 -1381
  500. package/dist/linkedin-person-ECWP4XPE.js +0 -139
  501. package/dist/list-PXEJMDB4.js +0 -67
  502. package/dist/list-SVR5HBLA.js +0 -306
  503. package/dist/list-XELB7UV2.js +0 -154
  504. package/dist/locations-KM4XY56A.js +0 -40
  505. package/dist/locations-SNK2NDH3.js +0 -69
  506. package/dist/log-PMPOO42C.js +0 -95
  507. package/dist/make-Q36WVKT3.js +0 -1367
  508. package/dist/map-DQ65PS65.js +0 -445
  509. package/dist/mcp-XMFKYN3E.js +0 -729
  510. package/dist/media-sources-HG524YO4.js +0 -35
  511. package/dist/members-D4DI2IFH.js +0 -47
  512. package/dist/metrics-QVDXMTEI.js +0 -152
  513. package/dist/models-VOSJJFO2.js +0 -155
  514. package/dist/normalize-XRVNJTML.js +0 -144
  515. package/dist/options-HT27WLNS.js +0 -125
  516. package/dist/organization-DYPTFZBA.js +0 -949
  517. package/dist/people-5MJXHC3D.js +0 -171
  518. package/dist/people-TTUIYT3L.js +0 -164
  519. package/dist/performance-2AQ34OPB.js +0 -27
  520. package/dist/performance-WE4LHJ2B.js +0 -5565
  521. package/dist/pixels-EWFDIDFA.js +0 -62
  522. package/dist/preview-JYVRWRTT.js +0 -101
  523. package/dist/promoted-tweet-writes-HCVRPH45.js +0 -183
  524. package/dist/promoted-tweets-P56ZU6OK.js +0 -119
  525. package/dist/publish-4VWZHRYO.js +0 -350
  526. package/dist/query-DK7WWCJJ.js +0 -62
  527. package/dist/reddit-NSKYHSAC.js +0 -29
  528. package/dist/refresh-O3CLJX4O.js +0 -97
  529. package/dist/release-6TQQW4HB.js +0 -63
  530. package/dist/relevant-pages-B3ZFOGHQ.js +0 -99
  531. package/dist/remove-R55VAM47.js +0 -53
  532. package/dist/reopen-S426N3OD.js +0 -66
  533. package/dist/rerun-5KHANQR3.js +0 -97
  534. package/dist/research-5REXCSSO.js +0 -265
  535. package/dist/research-DMZLXMM2.js +0 -78
  536. package/dist/reset-5N2IVHFL.js +0 -57
  537. package/dist/reset-D4NGVG35.js +0 -57
  538. package/dist/resolve-V75JGD75.js +0 -124
  539. package/dist/retry-SB7EIJBA.js +0 -65
  540. package/dist/retry-WIKW6CGT.js +0 -63
  541. package/dist/revenue-GZJU3XMD.js +0 -91
  542. package/dist/rules-WI6YKZA4.js +0 -99
  543. package/dist/rules-add-JCRB4AJR.js +0 -465
  544. package/dist/run-RDHTORWZ.js +0 -69
  545. package/dist/run-VVK23U5P.js +0 -72
  546. package/dist/scaffold-ad-QSVBY3XR.js +0 -1513
  547. package/dist/scaffold-static-ad-64BZMUHP.js +0 -1012
  548. package/dist/scaffold-video-X27MRW7R.js +0 -885
  549. package/dist/schedule-XHPIVUJ6.js +0 -64
  550. package/dist/scheduled-agents-OMUQCGDG.js +0 -56
  551. package/dist/schema-RDVJQ5VW.js +0 -135
  552. package/dist/search-VX5ATSCD.js +0 -177
  553. package/dist/select-NX3VHQTH.js +0 -110
  554. package/dist/set-prompt-QGEWZ3HD.js +0 -199
  555. package/dist/setup-links-LIDZVTSU.js +0 -144
  556. package/dist/shopify-LZU3MCDG.js +0 -4009
  557. package/dist/site-CEO2V3BI.js +0 -180
  558. package/dist/sources-C7AQCP2Z.js +0 -30
  559. package/dist/sources-SIGZVORA.js +0 -457
  560. package/dist/stale-BOUBKOAA.js +0 -90
  561. package/dist/status-NIG6OSAG.js +0 -65
  562. package/dist/stock-KY6BCN76.js +0 -212
  563. package/dist/studio-VQFYNK5O.js +0 -49
  564. package/dist/sync-3RS5E5ZI.js +0 -57
  565. package/dist/sync-definition-VHYZWLS5.js +0 -70
  566. package/dist/tags-F6DBHGIL.js +0 -26
  567. package/dist/tags-HGKEOIR7.js +0 -23
  568. package/dist/tags-I2LINXA7.js +0 -23
  569. package/dist/tags-UM6Y4DVQ.js +0 -227
  570. package/dist/tags-YCBZVXJQ.js +0 -23
  571. package/dist/targeting-criteria-XPK76HRH.js +0 -113
  572. package/dist/targets-KT4BNTKZ.js +0 -106
  573. package/dist/testimonials-QGXMSSWV.js +0 -32
  574. package/dist/themes-ZKUHKUZD.js +0 -95
  575. package/dist/top-companies-RC5KTWQ5.js +0 -246
  576. package/dist/transcript-OLF62WCH.js +0 -165
  577. package/dist/translate-NON5ZD3S.js +0 -603
  578. package/dist/triggers-UOQY4RFC.js +0 -144
  579. package/dist/unlink-RNIJPHHW.js +0 -70
  580. package/dist/unstage-QVDYVN77.js +0 -88
  581. package/dist/update-7KR5ABJP.js +0 -66
  582. package/dist/update-JAUWIWOH.js +0 -192
  583. package/dist/update-QZEF5MUW.js +0 -101
  584. package/dist/update-TRWHYXF4.js +0 -155
  585. package/dist/upload-MLK2MZB6.js +0 -137
  586. package/dist/url-options-2FVG55JF.js +0 -131
  587. package/dist/url-params-F4XNWPOD.js +0 -101
  588. package/dist/validate-P3AQVXG6.js +0 -135
  589. package/dist/videos-PAKAAFRD.js +0 -41
  590. package/dist/viewer-check-KXMDJH7R.js +0 -83
  591. package/dist/web-E5NHFG4Y.js +0 -173
  592. package/dist/winning-ads-P6PDTCCU.js +0 -86
  593. package/dist/write-commands-MBNO7DCX.js +0 -1524
  594. package/dist/x-5A74OD5P.js +0 -47
  595. /package/dist/{account-MDLPCIDQ.js.map → account-H44DUS4O.js.map} +0 -0
  596. /package/dist/{account-VRXCDDXY.js.map → account-WFAMHUCQ.js.map} +0 -0
  597. /package/dist/{account-reads-FSOURMSH.js.map → account-reads-JPQ2K343.js.map} +0 -0
  598. /package/dist/{account-users-FXOWESWY.js.map → account-users-R3CIZPV5.js.map} +0 -0
  599. /package/dist/{account-writes-SRTOKSMT.js.map → account-writes-EEKHPF5I.js.map} +0 -0
  600. /package/dist/{accounts-5YJZVSTB.js.map → accounts-GGP5J2FI.js.map} +0 -0
  601. /package/dist/{accounts-NR3ARJ72.js.map → accounts-H3KO5AEN.js.map} +0 -0
  602. /package/dist/{accounts-AT2UB2L3.js.map → accounts-K5IASJQV.js.map} +0 -0
  603. /package/dist/{actions-766X6XRB.js.map → actions-JXDJOGSY.js.map} +0 -0
  604. /package/dist/{activecampaign-MC4FYCCF.js.map → activecampaign-LXLAD2PF.js.map} +0 -0
  605. /package/dist/{ad-group-writes-UFBFB2PL.js.map → ad-group-writes-UDQ4563V.js.map} +0 -0
  606. /package/dist/{ad-groups-KRKMZPF3.js.map → ad-groups-RXT2XKSE.js.map} +0 -0
  607. /package/dist/{ad-writes-SIAGGUDJ.js.map → ad-writes-SHLTL2FY.js.map} +0 -0
  608. /package/dist/{add-DWKVVW76.js.map → add-DJQ5B245.js.map} +0 -0
  609. /package/dist/{add-MYX3BSUJ.js.map → add-MPXVC7L3.js.map} +0 -0
  610. /package/dist/{ads-UGMHE33I.js.map → ads-2TUJH4L3.js.map} +0 -0
  611. /package/dist/{ads-3T4C4BBH.js.map → ads-CUMOMBI3.js.map} +0 -0
  612. /package/dist/{advertisers-UFOLIRIK.js.map → advertisers-EWSPWD6I.js.map} +0 -0
  613. /package/dist/{alerts-2GMBX6JV.js.map → alerts-4FE3PUUK.js.map} +0 -0
  614. /package/dist/{analytics-G4WFP37R.js.map → analytics-HZDE5TKC.js.map} +0 -0
  615. /package/dist/{analytics-3EWNAHNG.js.map → analytics-QEYAVXZB.js.map} +0 -0
  616. /package/dist/{animate-PSOAMA52.js.map → animate-MBNFCDUZ.js.map} +0 -0
  617. /package/dist/{assign-5FALEZYD.js.map → assign-JZ5E7XRJ.js.map} +0 -0
  618. /package/dist/{audience-size-VRYRLPO5.js.map → audience-size-UXIGBCIO.js.map} +0 -0
  619. /package/dist/{audiences-EH426E3T.js.map → audiences-KBW2UAOP.js.map} +0 -0
  620. /package/dist/{audit-WHIVWMAI.js.map → audit-B2X3ON7Y.js.map} +0 -0
  621. /package/dist/{autocomplete-3HCLXTGK.js.map → autocomplete-VB74AP3J.js.map} +0 -0
  622. /package/dist/{avatars-HN74FWDF.js.map → avatars-WINNSCJK.js.map} +0 -0
  623. /package/dist/{bid-pricing-NN5JKZS4.js.map → bid-pricing-JAR4EBDA.js.map} +0 -0
  624. /package/dist/{brand-MWU5IVEZ.js.map → brand-ZLBQSOKD.js.map} +0 -0
  625. /package/dist/{brief-6TXWQWHJ.js.map → brief-35KFM74X.js.map} +0 -0
  626. /package/dist/{campaign-groups-MGEKCP7J.js.map → campaign-groups-2HUFNJK6.js.map} +0 -0
  627. /package/dist/{campaign-writes-Z7B6V6Q3.js.map → campaign-writes-JYMQF6CK.js.map} +0 -0
  628. /package/dist/{campaign-writes-ORUT54WL.js.map → campaign-writes-SZX7DHNE.js.map} +0 -0
  629. /package/dist/{campaigns-WLOJFSLV.js.map → campaigns-6NWQZXBM.js.map} +0 -0
  630. /package/dist/{campaigns-E7YC762Q.js.map → campaigns-DIP7NUSQ.js.map} +0 -0
  631. /package/dist/{campaigns-3BDIHUSW.js.map → campaigns-TMHFCPAZ.js.map} +0 -0
  632. /package/dist/{canvas-SEVIQRXN.js.map → canvas-JP5EFSGB.js.map} +0 -0
  633. /package/dist/{capabilities-KWJYBYQO.js.map → capabilities-2SLWTKI5.js.map} +0 -0
  634. /package/dist/{catalog-DHTZDVWS.js.map → catalog-2P422WOQ.js.map} +0 -0
  635. /package/dist/{catalogs-R4QFA5XO.js.map → catalogs-XFYYY3CS.js.map} +0 -0
  636. /package/dist/{changes-F2GP72MO.js.map → changes-GFJITHF6.js.map} +0 -0
  637. /package/dist/{chatgpt-MN4XHO6L.js.map → chatgpt-KNLATOZ6.js.map} +0 -0
  638. /package/dist/{chats-IBMO724I.js.map → chats-FID6CLCA.js.map} +0 -0
  639. /package/dist/{check-EZI4OF3Q.js.map → check-M337BOPG.js.map} +0 -0
  640. /package/dist/{chunk-423G75A7.js.map → chunk-2QAYZXPI.js.map} +0 -0
  641. /package/dist/{chunk-YNWBIAXJ.js.map → chunk-37QNC344.js.map} +0 -0
  642. /package/dist/{chunk-AFWLBOIN.js.map → chunk-3WLUQ7DM.js.map} +0 -0
  643. /package/dist/{chunk-4ZAHRAWL.js.map → chunk-3XGZFZVD.js.map} +0 -0
  644. /package/dist/{chunk-JGMQD3PX.js.map → chunk-4GRVNPHA.js.map} +0 -0
  645. /package/dist/{chunk-UECTXVAO.js.map → chunk-4HQR2O2K.js.map} +0 -0
  646. /package/dist/{chunk-JFWTQDZL.js.map → chunk-6CRNIIYN.js.map} +0 -0
  647. /package/dist/{chunk-UQTINFCP.js.map → chunk-6LDG4LFO.js.map} +0 -0
  648. /package/dist/{chunk-LY7PDE76.js.map → chunk-6LLA6IF6.js.map} +0 -0
  649. /package/dist/{chunk-U6EQMX3B.js.map → chunk-6PJGHPXG.js.map} +0 -0
  650. /package/dist/{chunk-K3VMHRLJ.js.map → chunk-7CVBEA7J.js.map} +0 -0
  651. /package/dist/{chunk-X7NRAGJ5.js.map → chunk-7HZTVVO7.js.map} +0 -0
  652. /package/dist/{chunk-G6CLJ3WL.js.map → chunk-7LFOSBF4.js.map} +0 -0
  653. /package/dist/{chunk-DAXBST7G.js.map → chunk-A7ICTIR5.js.map} +0 -0
  654. /package/dist/{chunk-EBFKPGTL.js.map → chunk-AUFQAR3V.js.map} +0 -0
  655. /package/dist/{chunk-J7L457MF.js.map → chunk-AYOTYURE.js.map} +0 -0
  656. /package/dist/{chunk-ZHQSXEJ2.js.map → chunk-B2S5TT4L.js.map} +0 -0
  657. /package/dist/{chunk-WZXMZFVB.js.map → chunk-BMMXYR7A.js.map} +0 -0
  658. /package/dist/{chunk-NOCBNING.js.map → chunk-BNEWJXKU.js.map} +0 -0
  659. /package/dist/{chunk-LBPJDFFN.js.map → chunk-BS4VGXTM.js.map} +0 -0
  660. /package/dist/{chunk-ZAQQBVEM.js.map → chunk-BUNG52KH.js.map} +0 -0
  661. /package/dist/{chunk-IEUF733F.js.map → chunk-BYV4VS5E.js.map} +0 -0
  662. /package/dist/{chunk-JTAPNHW5.js.map → chunk-DCBCEYSH.js.map} +0 -0
  663. /package/dist/{chunk-YLHWZOW7.js.map → chunk-DWJV6IOW.js.map} +0 -0
  664. /package/dist/{chunk-SRMQCQ7T.js.map → chunk-DZIP5OQX.js.map} +0 -0
  665. /package/dist/{chunk-VTLW24DM.js.map → chunk-E7LNNUKD.js.map} +0 -0
  666. /package/dist/{chunk-TBBAHTP3.js.map → chunk-FTP6NDOU.js.map} +0 -0
  667. /package/dist/{chunk-IEX4RRHJ.js.map → chunk-FZQU47P4.js.map} +0 -0
  668. /package/dist/{chunk-YYYGUO2E.js.map → chunk-G624WZD6.js.map} +0 -0
  669. /package/dist/{chunk-QNY4IK3C.js.map → chunk-GBXTEXVK.js.map} +0 -0
  670. /package/dist/{chunk-CNZ5KS4I.js.map → chunk-HFQSTIM5.js.map} +0 -0
  671. /package/dist/{chunk-D32EWSMB.js.map → chunk-IGCS3X4F.js.map} +0 -0
  672. /package/dist/{chunk-BZXIDMV7.js.map → chunk-IQ2V4ENC.js.map} +0 -0
  673. /package/dist/{chunk-6OIKNJ7G.js.map → chunk-JAC6JVCI.js.map} +0 -0
  674. /package/dist/{chunk-LNRYMWXE.js.map → chunk-JMTCCPK6.js.map} +0 -0
  675. /package/dist/{chunk-UUUYWBTR.js.map → chunk-JTYD7A3C.js.map} +0 -0
  676. /package/dist/{chunk-EA3643ET.js.map → chunk-L3MNDL6D.js.map} +0 -0
  677. /package/dist/{chunk-IR2NRXHA.js.map → chunk-LJ4AMUHS.js.map} +0 -0
  678. /package/dist/{chunk-XYHAIEAF.js.map → chunk-LRIP2J5S.js.map} +0 -0
  679. /package/dist/{chunk-DI7M2JUA.js.map → chunk-M7BSXJNL.js.map} +0 -0
  680. /package/dist/{chunk-PKSIPLMS.js.map → chunk-MI327KRO.js.map} +0 -0
  681. /package/dist/{chunk-BJH2G3QF.js.map → chunk-MJCOTA6T.js.map} +0 -0
  682. /package/dist/{chunk-S7WFZYKP.js.map → chunk-MQU4LNYG.js.map} +0 -0
  683. /package/dist/{chunk-SIKCVWM3.js.map → chunk-MZPS46OR.js.map} +0 -0
  684. /package/dist/{chunk-ETHUDFUY.js.map → chunk-N24ZFIEW.js.map} +0 -0
  685. /package/dist/{chunk-S4QGD7PV.js.map → chunk-N6OIIBTB.js.map} +0 -0
  686. /package/dist/{chunk-5WOZ7OGU.js.map → chunk-NEALLMDP.js.map} +0 -0
  687. /package/dist/{chunk-6J2UZJ6F.js.map → chunk-NGHOYXJD.js.map} +0 -0
  688. /package/dist/{chunk-ALCRXFIZ.js.map → chunk-NPAXHLAP.js.map} +0 -0
  689. /package/dist/{chunk-GLY3CB2F.js.map → chunk-OG76GZU3.js.map} +0 -0
  690. /package/dist/{chunk-SZFWQVAC.js.map → chunk-OU542F66.js.map} +0 -0
  691. /package/dist/{chunk-HXHGDFXA.js.map → chunk-OWO3CB6D.js.map} +0 -0
  692. /package/dist/{chunk-PK2U2ALQ.js.map → chunk-OXH63BGJ.js.map} +0 -0
  693. /package/dist/{chunk-VSHXHSIW.js.map → chunk-Q45FEJZ6.js.map} +0 -0
  694. /package/dist/{chunk-DD6X3AZB.js.map → chunk-QENSBNRJ.js.map} +0 -0
  695. /package/dist/{chunk-K2DKQ52D.js.map → chunk-QKGIXXXB.js.map} +0 -0
  696. /package/dist/{chunk-PEPLYJWK.js.map → chunk-SR65SC66.js.map} +0 -0
  697. /package/dist/{chunk-RDIZCSTV.js.map → chunk-T5TJJJGI.js.map} +0 -0
  698. /package/dist/{chunk-LQRPFL2N.js.map → chunk-TQIEDVJB.js.map} +0 -0
  699. /package/dist/{chunk-66LUQENO.js.map → chunk-UWWL7QIQ.js.map} +0 -0
  700. /package/dist/{chunk-QORVZUMT.js.map → chunk-WPBXN37A.js.map} +0 -0
  701. /package/dist/{chunk-EZ3YSJTP.js.map → chunk-XQNWHPRV.js.map} +0 -0
  702. /package/dist/{chunk-UZ5ZC43B.js.map → chunk-XWWX3WFJ.js.map} +0 -0
  703. /package/dist/{chunk-7EPR7L2D.js.map → chunk-Y25W6RSY.js.map} +0 -0
  704. /package/dist/{chunk-RQ43VL2X.js.map → chunk-YP5SD6O2.js.map} +0 -0
  705. /package/dist/{chunk-2VUD4CIW.js.map → chunk-Z3KRNKEA.js.map} +0 -0
  706. /package/dist/{chunk-XZJK2QB3.js.map → chunk-ZWFYBQ7N.js.map} +0 -0
  707. /package/dist/{claim-JQCSXR4C.js.map → claim-DXDA6XRM.js.map} +0 -0
  708. /package/dist/{companies-GHBIZKOK.js.map → companies-UNAN4THP.js.map} +0 -0
  709. /package/dist/{company-KNCYMQIA.js.map → company-ALE2HVTA.js.map} +0 -0
  710. /package/dist/{complete-V53XRNEQ.js.map → complete-GZC6MQD2.js.map} +0 -0
  711. /package/dist/{connect-NUZQSIGL.js.map → connect-664TAEG6.js.map} +0 -0
  712. /package/dist/{conversation-LBYO6ONM.js.map → conversation-AYXZYWMG.js.map} +0 -0
  713. /package/dist/{conversion-report-SRHJGIMT.js.map → conversion-report-6SVHPLHT.js.map} +0 -0
  714. /package/dist/{conversion-upload-command-5EKILBP2.js.map → conversion-upload-command-J3STKMAL.js.map} +0 -0
  715. /package/dist/{conversion-writes-P5FDTA6Y.js.map → conversion-writes-PEKNBIDQ.js.map} +0 -0
  716. /package/dist/{conversions-WJBOEPOO.js.map → conversions-ICSKSSLX.js.map} +0 -0
  717. /package/dist/{conversions-BXCGFNRK.js.map → conversions-SHKCWNNC.js.map} +0 -0
  718. /package/dist/{create-3PNWKXLP.js.map → create-2FCQZ7PD.js.map} +0 -0
  719. /package/dist/{create-XO7HUNPB.js.map → create-42TY74QW.js.map} +0 -0
  720. /package/dist/{create-6FZR7JZT.js.map → create-7EJEY5EK.js.map} +0 -0
  721. /package/dist/{create-QXJ3UEOT.js.map → create-SKI4H2XI.js.map} +0 -0
  722. /package/dist/{creatives-YRYPXOCS.js.map → creatives-OBKNNJAI.js.map} +0 -0
  723. /package/dist/{creatives-O6TA2DOG.js.map → creatives-QNPP5S4Q.js.map} +0 -0
  724. /package/dist/{credentials-ATAP54ZI.js.map → credentials-BCMMD3XG.js.map} +0 -0
  725. /package/dist/{critique-3UY7TUVQ.js.map → critique-KSQKDC7Y.js.map} +0 -0
  726. /package/dist/{critique-UC6SBKGO.js.map → critique-NWZIHUBH.js.map} +0 -0
  727. /package/dist/{crm-MGVGQ7PK.js.map → crm-ANNNZDM5.js.map} +0 -0
  728. /package/dist/{crm-AXK74BCO.js.map → crm-NP5LXKMN.js.map} +0 -0
  729. /package/dist/{currency-335ARWP5.js.map → currency-YZBACARU.js.map} +0 -0
  730. /package/dist/{customers-7NBNJCDC.js.map → customers-IUS7M6PJ.js.map} +0 -0
  731. /package/dist/{delete-OFG7FBMA.js.map → delete-NBHAHWZ7.js.map} +0 -0
  732. /package/dist/{delete-EKGTJSLK.js.map → delete-OJPKAYMV.js.map} +0 -0
  733. /package/dist/{delete-QQDGR7DD.js.map → delete-Y75QNAE4.js.map} +0 -0
  734. /package/dist/{demographics-QWFAMEC2.js.map → demographics-HDUPFELB.js.map} +0 -0
  735. /package/dist/{discard-4VW3AWI3.js.map → discard-32HKP4BV.js.map} +0 -0
  736. /package/dist/{discover-O6322XPL.js.map → discover-RKW25QME.js.map} +0 -0
  737. /package/dist/{domain-EDPDUVAX.js.map → domain-ODCRVC6V.js.map} +0 -0
  738. /package/dist/{download-46GLVBYU.js.map → download-75W2T7R7.js.map} +0 -0
  739. /package/dist/{draft-TJAD7P6W.js.map → draft-3KPRQ3YL.js.map} +0 -0
  740. /package/dist/{draft-SLGJRUOV.js.map → draft-EHDIVMWL.js.map} +0 -0
  741. /package/dist/{draft-IBR2W6GZ.js.map → draft-VJPB5MFJ.js.map} +0 -0
  742. /package/dist/{draft-RRUJU2ZR.js.map → draft-X6Y62O3Y.js.map} +0 -0
  743. /package/dist/{draft-NCUQFRGS.js.map → draft-ZDS6KFZ3.js.map} +0 -0
  744. /package/dist/{experiments-DUVO7C7A.js.map → experiments-GECLY35Q.js.map} +0 -0
  745. /package/dist/{extract-WYNFE6TQ.js.map → extract-KYD4M3XU.js.map} +0 -0
  746. /package/dist/{facets-WTY6NOUV.js.map → facets-CA7J44EY.js.map} +0 -0
  747. /package/dist/{feedback-57BP27NA.js.map → feedback-FB2QIIRX.js.map} +0 -0
  748. /package/dist/{feedback-XDREGDOK.js.map → feedback-P36JL2MA.js.map} +0 -0
  749. /package/dist/{feedback-record-HXSBLAZD.js.map → feedback-record-O4KVZAOF.js.map} +0 -0
  750. /package/dist/{fetch-L27MLPXM.js.map → fetch-Z42TLLI4.js.map} +0 -0
  751. /package/dist/{fit-K3G7HIMK.js.map → fit-ANYF4UJ2.js.map} +0 -0
  752. /package/dist/{flows-VJTWU3SU.js.map → flows-3KUFFMLO.js.map} +0 -0
  753. /package/dist/{fonts-SEMIVGXJ.js.map → fonts-TAJRK4HZ.js.map} +0 -0
  754. /package/dist/{forecast-EHOMHLUH.js.map → forecast-327XLLZ3.js.map} +0 -0
  755. /package/dist/{forecast-VODA7N3G.js.map → forecast-FIYKBAEW.js.map} +0 -0
  756. /package/dist/{funnel-BXJDMVMF.js.map → funnel-OGQVXGM7.js.map} +0 -0
  757. /package/dist/{generate-VCGSO7HI.js.map → generate-GBFLO76C.js.map} +0 -0
  758. /package/dist/{get-EN4UQI7R.js.map → get-LM4KTWKF.js.map} +0 -0
  759. /package/dist/{get-EASXXOQR.js.map → get-OSBYMC2N.js.map} +0 -0
  760. /package/dist/{google-ZVVKAI7T.js.map → google-FMGXNCW3.js.map} +0 -0
  761. /package/dist/{google-ATEQHENA.js.map → google-RHPQWNMK.js.map} +0 -0
  762. /package/dist/{google-ads-OUNSPGRQ.js.map → google-ads-EHJBMUJ4.js.map} +0 -0
  763. /package/dist/{history-TDGBO76N.js.map → history-6X3VIQP3.js.map} +0 -0
  764. /package/dist/{history-5OJVW2ZF.js.map → history-CDHA25XG.js.map} +0 -0
  765. /package/dist/{history-RQMCZQSC.js.map → history-K4VYVCZC.js.map} +0 -0
  766. /package/dist/{hubspot-VQGONQQU.js.map → hubspot-7E6EAUIV.js.map} +0 -0
  767. /package/dist/{ideas-B7RQXWHQ.js.map → ideas-3UNEUSMO.js.map} +0 -0
  768. /package/dist/{images-Q45MP4Q2.js.map → images-7KJX5JFY.js.map} +0 -0
  769. /package/dist/{ingest-UMQQIINM.js.map → ingest-4Y35DBZV.js.map} +0 -0
  770. /package/dist/{ingest-6MMY4KDM.js.map → ingest-LGZ3R4OI.js.map} +0 -0
  771. /package/dist/{insights-WDHDMULM.js.map → insights-RHOCF7VR.js.map} +0 -0
  772. /package/dist/{inspect-W2BIGA5F.js.map → inspect-WYOMSTBG.js.map} +0 -0
  773. /package/dist/{intent-3S6SHAYC.js.map → intent-TKFH57DZ.js.map} +0 -0
  774. /package/dist/{keyword-gap-MGHKWE6A.js.map → keyword-gap-7I2CIUTK.js.map} +0 -0
  775. /package/dist/{keyword-metrics-6R5TSHCE.js.map → keyword-metrics-35TFEXA5.js.map} +0 -0
  776. /package/dist/{keywords-for-site-EFBLFX6E.js.map → keywords-for-site-IMHNWTTB.js.map} +0 -0
  777. /package/dist/{landing-WC5FX3UP.js.map → landing-RKUGZ3LB.js.map} +0 -0
  778. /package/dist/{languages-4J7JHZNB.js.map → languages-FMHPUVOL.js.map} +0 -0
  779. /package/dist/{leads-CBOQ5CNM.js.map → leads-C46ZXIXF.js.map} +0 -0
  780. /package/dist/{learn-ZUP35H3T.js.map → learn-WDPCW5ZD.js.map} +0 -0
  781. /package/dist/{line-item-writes-W4UFIYEA.js.map → line-item-writes-IZKFY3GR.js.map} +0 -0
  782. /package/dist/{line-items-SGCUJF3S.js.map → line-items-CBVRZ43V.js.map} +0 -0
  783. /package/dist/{link-KLJB7COB.js.map → link-GEPIZSVI.js.map} +0 -0
  784. /package/dist/{linkedin-TANR45ZZ.js.map → linkedin-FHEYMG4M.js.map} +0 -0
  785. /package/dist/{linkedin-person-ECWP4XPE.js.map → linkedin-person-2M3WBL66.js.map} +0 -0
  786. /package/dist/{list-XELB7UV2.js.map → list-APJDJZL7.js.map} +0 -0
  787. /package/dist/{list-PXEJMDB4.js.map → list-CLJN4YN5.js.map} +0 -0
  788. /package/dist/{list-SVR5HBLA.js.map → list-LE6DJG44.js.map} +0 -0
  789. /package/dist/{locations-SNK2NDH3.js.map → locations-DD3JRZ4C.js.map} +0 -0
  790. /package/dist/{locations-KM4XY56A.js.map → locations-HWMEJ64P.js.map} +0 -0
  791. /package/dist/{log-PMPOO42C.js.map → log-FC2GLXIK.js.map} +0 -0
  792. /package/dist/{make-Q36WVKT3.js.map → make-4IIUKMLK.js.map} +0 -0
  793. /package/dist/{map-DQ65PS65.js.map → map-DGS5KKDJ.js.map} +0 -0
  794. /package/dist/{mcp-XMFKYN3E.js.map → mcp-IRG5E6U3.js.map} +0 -0
  795. /package/dist/{media-sources-HG524YO4.js.map → media-sources-SXUKFPBW.js.map} +0 -0
  796. /package/dist/{members-D4DI2IFH.js.map → members-TNY3CQSI.js.map} +0 -0
  797. /package/dist/{metrics-QVDXMTEI.js.map → metrics-KXTFXSWK.js.map} +0 -0
  798. /package/dist/{models-VOSJJFO2.js.map → models-2ZEM64H5.js.map} +0 -0
  799. /package/dist/{normalize-XRVNJTML.js.map → normalize-74VF6BZV.js.map} +0 -0
  800. /package/dist/{options-HT27WLNS.js.map → options-LNJH5LJR.js.map} +0 -0
  801. /package/dist/{organization-DYPTFZBA.js.map → organization-DHYTS3KH.js.map} +0 -0
  802. /package/dist/{people-TTUIYT3L.js.map → people-R3YTQXYH.js.map} +0 -0
  803. /package/dist/{people-5MJXHC3D.js.map → people-U6EP77HS.js.map} +0 -0
  804. /package/dist/{performance-2AQ34OPB.js.map → performance-AZGVR3IG.js.map} +0 -0
  805. /package/dist/{performance-WE4LHJ2B.js.map → performance-LYBUVYLQ.js.map} +0 -0
  806. /package/dist/{pixels-EWFDIDFA.js.map → pixels-3CINROKJ.js.map} +0 -0
  807. /package/dist/{preview-JYVRWRTT.js.map → preview-3OGMMUT4.js.map} +0 -0
  808. /package/dist/{promoted-tweet-writes-HCVRPH45.js.map → promoted-tweet-writes-EPNO2VUY.js.map} +0 -0
  809. /package/dist/{promoted-tweets-P56ZU6OK.js.map → promoted-tweets-UNG4FV3M.js.map} +0 -0
  810. /package/dist/{publish-4VWZHRYO.js.map → publish-YHU5K76M.js.map} +0 -0
  811. /package/dist/{query-DK7WWCJJ.js.map → query-NYH5PMQF.js.map} +0 -0
  812. /package/dist/{reddit-NSKYHSAC.js.map → reddit-BYHNEZWI.js.map} +0 -0
  813. /package/dist/{refresh-O3CLJX4O.js.map → refresh-3L4DCDVG.js.map} +0 -0
  814. /package/dist/{release-6TQQW4HB.js.map → release-LIDQL3KW.js.map} +0 -0
  815. /package/dist/{relevant-pages-B3ZFOGHQ.js.map → relevant-pages-QIF35NBQ.js.map} +0 -0
  816. /package/dist/{remove-R55VAM47.js.map → remove-RZSRYB4K.js.map} +0 -0
  817. /package/dist/{reopen-S426N3OD.js.map → reopen-C2SDKYRQ.js.map} +0 -0
  818. /package/dist/{rerun-5KHANQR3.js.map → rerun-5JHAKEXF.js.map} +0 -0
  819. /package/dist/{research-5REXCSSO.js.map → research-BNUMVIBI.js.map} +0 -0
  820. /package/dist/{research-DMZLXMM2.js.map → research-JQGHHTHS.js.map} +0 -0
  821. /package/dist/{reset-D4NGVG35.js.map → reset-FZ475DZK.js.map} +0 -0
  822. /package/dist/{reset-5N2IVHFL.js.map → reset-MES3UU3L.js.map} +0 -0
  823. /package/dist/{resolve-V75JGD75.js.map → resolve-3EJ2ZI64.js.map} +0 -0
  824. /package/dist/{retry-WIKW6CGT.js.map → retry-IMGUCVDF.js.map} +0 -0
  825. /package/dist/{retry-SB7EIJBA.js.map → retry-OFFHBZG2.js.map} +0 -0
  826. /package/dist/{revenue-GZJU3XMD.js.map → revenue-IACHOM7M.js.map} +0 -0
  827. /package/dist/{rules-WI6YKZA4.js.map → rules-C72VPDXE.js.map} +0 -0
  828. /package/dist/{rules-add-JCRB4AJR.js.map → rules-add-A3PKTQNR.js.map} +0 -0
  829. /package/dist/{run-VVK23U5P.js.map → run-XVULTREI.js.map} +0 -0
  830. /package/dist/{run-RDHTORWZ.js.map → run-XYRUAAJH.js.map} +0 -0
  831. /package/dist/{scaffold-ad-QSVBY3XR.js.map → scaffold-ad-Y4FKVKVJ.js.map} +0 -0
  832. /package/dist/{scaffold-static-ad-64BZMUHP.js.map → scaffold-static-ad-TVMEGBHZ.js.map} +0 -0
  833. /package/dist/{scaffold-video-X27MRW7R.js.map → scaffold-video-JYUGPW2L.js.map} +0 -0
  834. /package/dist/{schedule-XHPIVUJ6.js.map → schedule-NMMJZXZH.js.map} +0 -0
  835. /package/dist/{scheduled-agents-OMUQCGDG.js.map → scheduled-agents-NFVSFOPB.js.map} +0 -0
  836. /package/dist/{schema-RDVJQ5VW.js.map → schema-MIWJBYFP.js.map} +0 -0
  837. /package/dist/{search-VX5ATSCD.js.map → search-B3EI65TS.js.map} +0 -0
  838. /package/dist/{select-NX3VHQTH.js.map → select-UH73L657.js.map} +0 -0
  839. /package/dist/{set-prompt-QGEWZ3HD.js.map → set-prompt-Y3IPUFUH.js.map} +0 -0
  840. /package/dist/{setup-links-LIDZVTSU.js.map → setup-links-2Y3A676T.js.map} +0 -0
  841. /package/dist/{shopify-LZU3MCDG.js.map → shopify-5LZ5IWSB.js.map} +0 -0
  842. /package/dist/{site-CEO2V3BI.js.map → site-GXH6QLNZ.js.map} +0 -0
  843. /package/dist/{sources-C7AQCP2Z.js.map → sources-7VWSZZHQ.js.map} +0 -0
  844. /package/dist/{sources-SIGZVORA.js.map → sources-KYAVCA5P.js.map} +0 -0
  845. /package/dist/{stale-BOUBKOAA.js.map → stale-TDAEKOJB.js.map} +0 -0
  846. /package/dist/{status-NIG6OSAG.js.map → status-II4PTBUU.js.map} +0 -0
  847. /package/dist/{stock-KY6BCN76.js.map → stock-WZN53KCQ.js.map} +0 -0
  848. /package/dist/{studio-VQFYNK5O.js.map → studio-TG2UAKFI.js.map} +0 -0
  849. /package/dist/{sync-3RS5E5ZI.js.map → sync-OSHJH7TD.js.map} +0 -0
  850. /package/dist/{sync-definition-VHYZWLS5.js.map → sync-definition-AP6CA6BU.js.map} +0 -0
  851. /package/dist/{tags-UM6Y4DVQ.js.map → tags-36OYKBFE.js.map} +0 -0
  852. /package/dist/{tags-F6DBHGIL.js.map → tags-3K6QGK5B.js.map} +0 -0
  853. /package/dist/{tags-I2LINXA7.js.map → tags-53FUK4HL.js.map} +0 -0
  854. /package/dist/{tags-YCBZVXJQ.js.map → tags-B3Z3OQ6G.js.map} +0 -0
  855. /package/dist/{tags-HGKEOIR7.js.map → tags-DXKEOOGL.js.map} +0 -0
  856. /package/dist/{targeting-criteria-XPK76HRH.js.map → targeting-criteria-UFE3MLWR.js.map} +0 -0
  857. /package/dist/{targets-KT4BNTKZ.js.map → targets-JSBKVSRO.js.map} +0 -0
  858. /package/dist/{testimonials-QGXMSSWV.js.map → testimonials-6KYRLQVP.js.map} +0 -0
  859. /package/dist/{themes-ZKUHKUZD.js.map → themes-7XHHY4XY.js.map} +0 -0
  860. /package/dist/{top-companies-RC5KTWQ5.js.map → top-companies-W3GBGJGL.js.map} +0 -0
  861. /package/dist/{transcript-OLF62WCH.js.map → transcript-VTVLH4VV.js.map} +0 -0
  862. /package/dist/{translate-NON5ZD3S.js.map → translate-TIFUZLPE.js.map} +0 -0
  863. /package/dist/{triggers-UOQY4RFC.js.map → triggers-ULFGRFHQ.js.map} +0 -0
  864. /package/dist/{unlink-RNIJPHHW.js.map → unlink-FGUCQNNF.js.map} +0 -0
  865. /package/dist/{unstage-QVDYVN77.js.map → unstage-UHKSQUPR.js.map} +0 -0
  866. /package/dist/{update-JAUWIWOH.js.map → update-CF6437MN.js.map} +0 -0
  867. /package/dist/{update-7KR5ABJP.js.map → update-G2IRXCSJ.js.map} +0 -0
  868. /package/dist/{update-QZEF5MUW.js.map → update-KO5VEPRN.js.map} +0 -0
  869. /package/dist/{update-TRWHYXF4.js.map → update-OQUIUKSX.js.map} +0 -0
  870. /package/dist/{upload-MLK2MZB6.js.map → upload-GD552SG7.js.map} +0 -0
  871. /package/dist/{url-options-2FVG55JF.js.map → url-options-RTTLWCU5.js.map} +0 -0
  872. /package/dist/{url-params-F4XNWPOD.js.map → url-params-ZFX3EBLE.js.map} +0 -0
  873. /package/dist/{validate-P3AQVXG6.js.map → validate-BBXOFK4S.js.map} +0 -0
  874. /package/dist/{videos-PAKAAFRD.js.map → videos-OA3PSDF6.js.map} +0 -0
  875. /package/dist/{viewer-check-KXMDJH7R.js.map → viewer-check-OIORNTQG.js.map} +0 -0
  876. /package/dist/{web-E5NHFG4Y.js.map → web-RKEKSDU3.js.map} +0 -0
  877. /package/dist/{winning-ads-P6PDTCCU.js.map → winning-ads-CJQEQ6JQ.js.map} +0 -0
  878. /package/dist/{write-commands-MBNO7DCX.js.map → write-commands-CPAOTG6H.js.map} +0 -0
  879. /package/dist/{x-5A74OD5P.js.map → x-PF3FDWKU.js.map} +0 -0
@@ -0,0 +1,3187 @@
1
+ import {
2
+ __commonJS,
3
+ __toESM
4
+ } from "./chunk-YQSBHWOI.js";
5
+
6
+ // ../../node_modules/.pnpm/safe-stable-stringify@2.5.0/node_modules/safe-stable-stringify/index.js
7
+ var require_safe_stable_stringify = __commonJS({
8
+ "../../node_modules/.pnpm/safe-stable-stringify@2.5.0/node_modules/safe-stable-stringify/index.js"(exports, module) {
9
+ "use strict";
10
+ var { hasOwnProperty } = Object.prototype;
11
+ var stringify = configure2();
12
+ stringify.configure = configure2;
13
+ stringify.stringify = stringify;
14
+ stringify.default = stringify;
15
+ exports.stringify = stringify;
16
+ exports.configure = configure2;
17
+ module.exports = stringify;
18
+ var strEscapeSequencesRegExp = /[\u0000-\u001f\u0022\u005c\ud800-\udfff]/;
19
+ function strEscape(str) {
20
+ if (str.length < 5e3 && !strEscapeSequencesRegExp.test(str)) {
21
+ return `"${str}"`;
22
+ }
23
+ return JSON.stringify(str);
24
+ }
25
+ function sort(array, comparator) {
26
+ if (array.length > 200 || comparator) {
27
+ return array.sort(comparator);
28
+ }
29
+ for (let i = 1; i < array.length; i++) {
30
+ const currentValue = array[i];
31
+ let position = i;
32
+ while (position !== 0 && array[position - 1] > currentValue) {
33
+ array[position] = array[position - 1];
34
+ position--;
35
+ }
36
+ array[position] = currentValue;
37
+ }
38
+ return array;
39
+ }
40
+ var typedArrayPrototypeGetSymbolToStringTag = Object.getOwnPropertyDescriptor(
41
+ Object.getPrototypeOf(
42
+ Object.getPrototypeOf(
43
+ new Int8Array()
44
+ )
45
+ ),
46
+ Symbol.toStringTag
47
+ ).get;
48
+ function isTypedArrayWithEntries(value) {
49
+ return typedArrayPrototypeGetSymbolToStringTag.call(value) !== void 0 && value.length !== 0;
50
+ }
51
+ function stringifyTypedArray(array, separator, maximumBreadth) {
52
+ if (array.length < maximumBreadth) {
53
+ maximumBreadth = array.length;
54
+ }
55
+ const whitespace = separator === "," ? "" : " ";
56
+ let res = `"0":${whitespace}${array[0]}`;
57
+ for (let i = 1; i < maximumBreadth; i++) {
58
+ res += `${separator}"${i}":${whitespace}${array[i]}`;
59
+ }
60
+ return res;
61
+ }
62
+ function getCircularValueOption(options) {
63
+ if (hasOwnProperty.call(options, "circularValue")) {
64
+ const circularValue = options.circularValue;
65
+ if (typeof circularValue === "string") {
66
+ return `"${circularValue}"`;
67
+ }
68
+ if (circularValue == null) {
69
+ return circularValue;
70
+ }
71
+ if (circularValue === Error || circularValue === TypeError) {
72
+ return {
73
+ toString() {
74
+ throw new TypeError("Converting circular structure to JSON");
75
+ }
76
+ };
77
+ }
78
+ throw new TypeError('The "circularValue" argument must be of type string or the value null or undefined');
79
+ }
80
+ return '"[Circular]"';
81
+ }
82
+ function getDeterministicOption(options) {
83
+ let value;
84
+ if (hasOwnProperty.call(options, "deterministic")) {
85
+ value = options.deterministic;
86
+ if (typeof value !== "boolean" && typeof value !== "function") {
87
+ throw new TypeError('The "deterministic" argument must be of type boolean or comparator function');
88
+ }
89
+ }
90
+ return value === void 0 ? true : value;
91
+ }
92
+ function getBooleanOption(options, key) {
93
+ let value;
94
+ if (hasOwnProperty.call(options, key)) {
95
+ value = options[key];
96
+ if (typeof value !== "boolean") {
97
+ throw new TypeError(`The "${key}" argument must be of type boolean`);
98
+ }
99
+ }
100
+ return value === void 0 ? true : value;
101
+ }
102
+ function getPositiveIntegerOption(options, key) {
103
+ let value;
104
+ if (hasOwnProperty.call(options, key)) {
105
+ value = options[key];
106
+ if (typeof value !== "number") {
107
+ throw new TypeError(`The "${key}" argument must be of type number`);
108
+ }
109
+ if (!Number.isInteger(value)) {
110
+ throw new TypeError(`The "${key}" argument must be an integer`);
111
+ }
112
+ if (value < 1) {
113
+ throw new RangeError(`The "${key}" argument must be >= 1`);
114
+ }
115
+ }
116
+ return value === void 0 ? Infinity : value;
117
+ }
118
+ function getItemCount(number) {
119
+ if (number === 1) {
120
+ return "1 item";
121
+ }
122
+ return `${number} items`;
123
+ }
124
+ function getUniqueReplacerSet(replacerArray) {
125
+ const replacerSet = /* @__PURE__ */ new Set();
126
+ for (const value of replacerArray) {
127
+ if (typeof value === "string" || typeof value === "number") {
128
+ replacerSet.add(String(value));
129
+ }
130
+ }
131
+ return replacerSet;
132
+ }
133
+ function getStrictOption(options) {
134
+ if (hasOwnProperty.call(options, "strict")) {
135
+ const value = options.strict;
136
+ if (typeof value !== "boolean") {
137
+ throw new TypeError('The "strict" argument must be of type boolean');
138
+ }
139
+ if (value) {
140
+ return (value2) => {
141
+ let message = `Object can not safely be stringified. Received type ${typeof value2}`;
142
+ if (typeof value2 !== "function") message += ` (${value2.toString()})`;
143
+ throw new Error(message);
144
+ };
145
+ }
146
+ }
147
+ }
148
+ function configure2(options) {
149
+ options = { ...options };
150
+ const fail = getStrictOption(options);
151
+ if (fail) {
152
+ if (options.bigint === void 0) {
153
+ options.bigint = false;
154
+ }
155
+ if (!("circularValue" in options)) {
156
+ options.circularValue = Error;
157
+ }
158
+ }
159
+ const circularValue = getCircularValueOption(options);
160
+ const bigint = getBooleanOption(options, "bigint");
161
+ const deterministic = getDeterministicOption(options);
162
+ const comparator = typeof deterministic === "function" ? deterministic : void 0;
163
+ const maximumDepth = getPositiveIntegerOption(options, "maximumDepth");
164
+ const maximumBreadth = getPositiveIntegerOption(options, "maximumBreadth");
165
+ function stringifyFnReplacer(key, parent, stack, replacer, spacer, indentation) {
166
+ let value = parent[key];
167
+ if (typeof value === "object" && value !== null && typeof value.toJSON === "function") {
168
+ value = value.toJSON(key);
169
+ }
170
+ value = replacer.call(parent, key, value);
171
+ switch (typeof value) {
172
+ case "string":
173
+ return strEscape(value);
174
+ case "object": {
175
+ if (value === null) {
176
+ return "null";
177
+ }
178
+ if (stack.indexOf(value) !== -1) {
179
+ return circularValue;
180
+ }
181
+ let res = "";
182
+ let join = ",";
183
+ const originalIndentation = indentation;
184
+ if (Array.isArray(value)) {
185
+ if (value.length === 0) {
186
+ return "[]";
187
+ }
188
+ if (maximumDepth < stack.length + 1) {
189
+ return '"[Array]"';
190
+ }
191
+ stack.push(value);
192
+ if (spacer !== "") {
193
+ indentation += spacer;
194
+ res += `
195
+ ${indentation}`;
196
+ join = `,
197
+ ${indentation}`;
198
+ }
199
+ const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
200
+ let i = 0;
201
+ for (; i < maximumValuesToStringify - 1; i++) {
202
+ const tmp2 = stringifyFnReplacer(String(i), value, stack, replacer, spacer, indentation);
203
+ res += tmp2 !== void 0 ? tmp2 : "null";
204
+ res += join;
205
+ }
206
+ const tmp = stringifyFnReplacer(String(i), value, stack, replacer, spacer, indentation);
207
+ res += tmp !== void 0 ? tmp : "null";
208
+ if (value.length - 1 > maximumBreadth) {
209
+ const removedKeys = value.length - maximumBreadth - 1;
210
+ res += `${join}"... ${getItemCount(removedKeys)} not stringified"`;
211
+ }
212
+ if (spacer !== "") {
213
+ res += `
214
+ ${originalIndentation}`;
215
+ }
216
+ stack.pop();
217
+ return `[${res}]`;
218
+ }
219
+ let keys = Object.keys(value);
220
+ const keyLength = keys.length;
221
+ if (keyLength === 0) {
222
+ return "{}";
223
+ }
224
+ if (maximumDepth < stack.length + 1) {
225
+ return '"[Object]"';
226
+ }
227
+ let whitespace = "";
228
+ let separator = "";
229
+ if (spacer !== "") {
230
+ indentation += spacer;
231
+ join = `,
232
+ ${indentation}`;
233
+ whitespace = " ";
234
+ }
235
+ const maximumPropertiesToStringify = Math.min(keyLength, maximumBreadth);
236
+ if (deterministic && !isTypedArrayWithEntries(value)) {
237
+ keys = sort(keys, comparator);
238
+ }
239
+ stack.push(value);
240
+ for (let i = 0; i < maximumPropertiesToStringify; i++) {
241
+ const key2 = keys[i];
242
+ const tmp = stringifyFnReplacer(key2, value, stack, replacer, spacer, indentation);
243
+ if (tmp !== void 0) {
244
+ res += `${separator}${strEscape(key2)}:${whitespace}${tmp}`;
245
+ separator = join;
246
+ }
247
+ }
248
+ if (keyLength > maximumBreadth) {
249
+ const removedKeys = keyLength - maximumBreadth;
250
+ res += `${separator}"...":${whitespace}"${getItemCount(removedKeys)} not stringified"`;
251
+ separator = join;
252
+ }
253
+ if (spacer !== "" && separator.length > 1) {
254
+ res = `
255
+ ${indentation}${res}
256
+ ${originalIndentation}`;
257
+ }
258
+ stack.pop();
259
+ return `{${res}}`;
260
+ }
261
+ case "number":
262
+ return isFinite(value) ? String(value) : fail ? fail(value) : "null";
263
+ case "boolean":
264
+ return value === true ? "true" : "false";
265
+ case "undefined":
266
+ return void 0;
267
+ case "bigint":
268
+ if (bigint) {
269
+ return String(value);
270
+ }
271
+ // fallthrough
272
+ default:
273
+ return fail ? fail(value) : void 0;
274
+ }
275
+ }
276
+ function stringifyArrayReplacer(key, value, stack, replacer, spacer, indentation) {
277
+ if (typeof value === "object" && value !== null && typeof value.toJSON === "function") {
278
+ value = value.toJSON(key);
279
+ }
280
+ switch (typeof value) {
281
+ case "string":
282
+ return strEscape(value);
283
+ case "object": {
284
+ if (value === null) {
285
+ return "null";
286
+ }
287
+ if (stack.indexOf(value) !== -1) {
288
+ return circularValue;
289
+ }
290
+ const originalIndentation = indentation;
291
+ let res = "";
292
+ let join = ",";
293
+ if (Array.isArray(value)) {
294
+ if (value.length === 0) {
295
+ return "[]";
296
+ }
297
+ if (maximumDepth < stack.length + 1) {
298
+ return '"[Array]"';
299
+ }
300
+ stack.push(value);
301
+ if (spacer !== "") {
302
+ indentation += spacer;
303
+ res += `
304
+ ${indentation}`;
305
+ join = `,
306
+ ${indentation}`;
307
+ }
308
+ const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
309
+ let i = 0;
310
+ for (; i < maximumValuesToStringify - 1; i++) {
311
+ const tmp2 = stringifyArrayReplacer(String(i), value[i], stack, replacer, spacer, indentation);
312
+ res += tmp2 !== void 0 ? tmp2 : "null";
313
+ res += join;
314
+ }
315
+ const tmp = stringifyArrayReplacer(String(i), value[i], stack, replacer, spacer, indentation);
316
+ res += tmp !== void 0 ? tmp : "null";
317
+ if (value.length - 1 > maximumBreadth) {
318
+ const removedKeys = value.length - maximumBreadth - 1;
319
+ res += `${join}"... ${getItemCount(removedKeys)} not stringified"`;
320
+ }
321
+ if (spacer !== "") {
322
+ res += `
323
+ ${originalIndentation}`;
324
+ }
325
+ stack.pop();
326
+ return `[${res}]`;
327
+ }
328
+ stack.push(value);
329
+ let whitespace = "";
330
+ if (spacer !== "") {
331
+ indentation += spacer;
332
+ join = `,
333
+ ${indentation}`;
334
+ whitespace = " ";
335
+ }
336
+ let separator = "";
337
+ for (const key2 of replacer) {
338
+ const tmp = stringifyArrayReplacer(key2, value[key2], stack, replacer, spacer, indentation);
339
+ if (tmp !== void 0) {
340
+ res += `${separator}${strEscape(key2)}:${whitespace}${tmp}`;
341
+ separator = join;
342
+ }
343
+ }
344
+ if (spacer !== "" && separator.length > 1) {
345
+ res = `
346
+ ${indentation}${res}
347
+ ${originalIndentation}`;
348
+ }
349
+ stack.pop();
350
+ return `{${res}}`;
351
+ }
352
+ case "number":
353
+ return isFinite(value) ? String(value) : fail ? fail(value) : "null";
354
+ case "boolean":
355
+ return value === true ? "true" : "false";
356
+ case "undefined":
357
+ return void 0;
358
+ case "bigint":
359
+ if (bigint) {
360
+ return String(value);
361
+ }
362
+ // fallthrough
363
+ default:
364
+ return fail ? fail(value) : void 0;
365
+ }
366
+ }
367
+ function stringifyIndent(key, value, stack, spacer, indentation) {
368
+ switch (typeof value) {
369
+ case "string":
370
+ return strEscape(value);
371
+ case "object": {
372
+ if (value === null) {
373
+ return "null";
374
+ }
375
+ if (typeof value.toJSON === "function") {
376
+ value = value.toJSON(key);
377
+ if (typeof value !== "object") {
378
+ return stringifyIndent(key, value, stack, spacer, indentation);
379
+ }
380
+ if (value === null) {
381
+ return "null";
382
+ }
383
+ }
384
+ if (stack.indexOf(value) !== -1) {
385
+ return circularValue;
386
+ }
387
+ const originalIndentation = indentation;
388
+ if (Array.isArray(value)) {
389
+ if (value.length === 0) {
390
+ return "[]";
391
+ }
392
+ if (maximumDepth < stack.length + 1) {
393
+ return '"[Array]"';
394
+ }
395
+ stack.push(value);
396
+ indentation += spacer;
397
+ let res2 = `
398
+ ${indentation}`;
399
+ const join2 = `,
400
+ ${indentation}`;
401
+ const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
402
+ let i = 0;
403
+ for (; i < maximumValuesToStringify - 1; i++) {
404
+ const tmp2 = stringifyIndent(String(i), value[i], stack, spacer, indentation);
405
+ res2 += tmp2 !== void 0 ? tmp2 : "null";
406
+ res2 += join2;
407
+ }
408
+ const tmp = stringifyIndent(String(i), value[i], stack, spacer, indentation);
409
+ res2 += tmp !== void 0 ? tmp : "null";
410
+ if (value.length - 1 > maximumBreadth) {
411
+ const removedKeys = value.length - maximumBreadth - 1;
412
+ res2 += `${join2}"... ${getItemCount(removedKeys)} not stringified"`;
413
+ }
414
+ res2 += `
415
+ ${originalIndentation}`;
416
+ stack.pop();
417
+ return `[${res2}]`;
418
+ }
419
+ let keys = Object.keys(value);
420
+ const keyLength = keys.length;
421
+ if (keyLength === 0) {
422
+ return "{}";
423
+ }
424
+ if (maximumDepth < stack.length + 1) {
425
+ return '"[Object]"';
426
+ }
427
+ indentation += spacer;
428
+ const join = `,
429
+ ${indentation}`;
430
+ let res = "";
431
+ let separator = "";
432
+ let maximumPropertiesToStringify = Math.min(keyLength, maximumBreadth);
433
+ if (isTypedArrayWithEntries(value)) {
434
+ res += stringifyTypedArray(value, join, maximumBreadth);
435
+ keys = keys.slice(value.length);
436
+ maximumPropertiesToStringify -= value.length;
437
+ separator = join;
438
+ }
439
+ if (deterministic) {
440
+ keys = sort(keys, comparator);
441
+ }
442
+ stack.push(value);
443
+ for (let i = 0; i < maximumPropertiesToStringify; i++) {
444
+ const key2 = keys[i];
445
+ const tmp = stringifyIndent(key2, value[key2], stack, spacer, indentation);
446
+ if (tmp !== void 0) {
447
+ res += `${separator}${strEscape(key2)}: ${tmp}`;
448
+ separator = join;
449
+ }
450
+ }
451
+ if (keyLength > maximumBreadth) {
452
+ const removedKeys = keyLength - maximumBreadth;
453
+ res += `${separator}"...": "${getItemCount(removedKeys)} not stringified"`;
454
+ separator = join;
455
+ }
456
+ if (separator !== "") {
457
+ res = `
458
+ ${indentation}${res}
459
+ ${originalIndentation}`;
460
+ }
461
+ stack.pop();
462
+ return `{${res}}`;
463
+ }
464
+ case "number":
465
+ return isFinite(value) ? String(value) : fail ? fail(value) : "null";
466
+ case "boolean":
467
+ return value === true ? "true" : "false";
468
+ case "undefined":
469
+ return void 0;
470
+ case "bigint":
471
+ if (bigint) {
472
+ return String(value);
473
+ }
474
+ // fallthrough
475
+ default:
476
+ return fail ? fail(value) : void 0;
477
+ }
478
+ }
479
+ function stringifySimple(key, value, stack) {
480
+ switch (typeof value) {
481
+ case "string":
482
+ return strEscape(value);
483
+ case "object": {
484
+ if (value === null) {
485
+ return "null";
486
+ }
487
+ if (typeof value.toJSON === "function") {
488
+ value = value.toJSON(key);
489
+ if (typeof value !== "object") {
490
+ return stringifySimple(key, value, stack);
491
+ }
492
+ if (value === null) {
493
+ return "null";
494
+ }
495
+ }
496
+ if (stack.indexOf(value) !== -1) {
497
+ return circularValue;
498
+ }
499
+ let res = "";
500
+ const hasLength = value.length !== void 0;
501
+ if (hasLength && Array.isArray(value)) {
502
+ if (value.length === 0) {
503
+ return "[]";
504
+ }
505
+ if (maximumDepth < stack.length + 1) {
506
+ return '"[Array]"';
507
+ }
508
+ stack.push(value);
509
+ const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
510
+ let i = 0;
511
+ for (; i < maximumValuesToStringify - 1; i++) {
512
+ const tmp2 = stringifySimple(String(i), value[i], stack);
513
+ res += tmp2 !== void 0 ? tmp2 : "null";
514
+ res += ",";
515
+ }
516
+ const tmp = stringifySimple(String(i), value[i], stack);
517
+ res += tmp !== void 0 ? tmp : "null";
518
+ if (value.length - 1 > maximumBreadth) {
519
+ const removedKeys = value.length - maximumBreadth - 1;
520
+ res += `,"... ${getItemCount(removedKeys)} not stringified"`;
521
+ }
522
+ stack.pop();
523
+ return `[${res}]`;
524
+ }
525
+ let keys = Object.keys(value);
526
+ const keyLength = keys.length;
527
+ if (keyLength === 0) {
528
+ return "{}";
529
+ }
530
+ if (maximumDepth < stack.length + 1) {
531
+ return '"[Object]"';
532
+ }
533
+ let separator = "";
534
+ let maximumPropertiesToStringify = Math.min(keyLength, maximumBreadth);
535
+ if (hasLength && isTypedArrayWithEntries(value)) {
536
+ res += stringifyTypedArray(value, ",", maximumBreadth);
537
+ keys = keys.slice(value.length);
538
+ maximumPropertiesToStringify -= value.length;
539
+ separator = ",";
540
+ }
541
+ if (deterministic) {
542
+ keys = sort(keys, comparator);
543
+ }
544
+ stack.push(value);
545
+ for (let i = 0; i < maximumPropertiesToStringify; i++) {
546
+ const key2 = keys[i];
547
+ const tmp = stringifySimple(key2, value[key2], stack);
548
+ if (tmp !== void 0) {
549
+ res += `${separator}${strEscape(key2)}:${tmp}`;
550
+ separator = ",";
551
+ }
552
+ }
553
+ if (keyLength > maximumBreadth) {
554
+ const removedKeys = keyLength - maximumBreadth;
555
+ res += `${separator}"...":"${getItemCount(removedKeys)} not stringified"`;
556
+ }
557
+ stack.pop();
558
+ return `{${res}}`;
559
+ }
560
+ case "number":
561
+ return isFinite(value) ? String(value) : fail ? fail(value) : "null";
562
+ case "boolean":
563
+ return value === true ? "true" : "false";
564
+ case "undefined":
565
+ return void 0;
566
+ case "bigint":
567
+ if (bigint) {
568
+ return String(value);
569
+ }
570
+ // fallthrough
571
+ default:
572
+ return fail ? fail(value) : void 0;
573
+ }
574
+ }
575
+ function stringify2(value, replacer, space) {
576
+ if (arguments.length > 1) {
577
+ let spacer = "";
578
+ if (typeof space === "number") {
579
+ spacer = " ".repeat(Math.min(space, 10));
580
+ } else if (typeof space === "string") {
581
+ spacer = space.slice(0, 10);
582
+ }
583
+ if (replacer != null) {
584
+ if (typeof replacer === "function") {
585
+ return stringifyFnReplacer("", { "": value }, [], replacer, spacer, "");
586
+ }
587
+ if (Array.isArray(replacer)) {
588
+ return stringifyArrayReplacer("", value, [], getUniqueReplacerSet(replacer), spacer, "");
589
+ }
590
+ }
591
+ if (spacer.length !== 0) {
592
+ return stringifyIndent("", value, [], spacer, "");
593
+ }
594
+ }
595
+ return stringifySimple("", value, []);
596
+ }
597
+ return stringify2;
598
+ }
599
+ }
600
+ });
601
+
602
+ // ../canvas-contract/src/adPlacements.ts
603
+ var AD_PLATFORMS = [
604
+ "meta",
605
+ "google_display",
606
+ "google_pmax",
607
+ "google_demandgen",
608
+ "google_search",
609
+ "youtube",
610
+ "linkedin",
611
+ "tiktok",
612
+ "x",
613
+ "reddit",
614
+ "pinterest",
615
+ "snapchat",
616
+ "chatgpt"
617
+ ];
618
+ var AD_PLATFORM_LEAD = {
619
+ meta: "4:5",
620
+ google_display: "1:1",
621
+ google_pmax: "1:1",
622
+ google_demandgen: "1:1",
623
+ google_search: "1:1",
624
+ youtube: "1.91:1",
625
+ linkedin: "1:1",
626
+ tiktok: "9:16",
627
+ x: "1.91:1",
628
+ reddit: "1:1",
629
+ pinterest: "2:3",
630
+ snapchat: "9:16",
631
+ chatgpt: "1:1"
632
+ };
633
+ var AD_PLATFORM_NAMES = {
634
+ meta: "Meta",
635
+ google_display: "Google Display",
636
+ google_pmax: "Performance Max",
637
+ google_demandgen: "Demand Gen",
638
+ google_search: "Google Search",
639
+ youtube: "YouTube",
640
+ linkedin: "LinkedIn",
641
+ tiktok: "TikTok",
642
+ x: "X",
643
+ reddit: "Reddit",
644
+ pinterest: "Pinterest",
645
+ snapchat: "Snapchat",
646
+ chatgpt: "ChatGPT"
647
+ };
648
+ var FEED_MARGIN = { top: 0.04, bottom: 0.04, left: 0.04, right: 0.04 };
649
+ var size = (width, height, required = true) => ({ width, height, required });
650
+ var AD_PLACEMENTS = [
651
+ {
652
+ id: "meta_feed",
653
+ platform: "meta",
654
+ name: "Facebook and Instagram feeds",
655
+ sizes: [size(1080, 1350), size(1080, 1080, false)],
656
+ safe: FEED_MARGIN,
657
+ source: "https://www.facebook.com/business/ads-guide/update/image/instagram-feed"
658
+ },
659
+ {
660
+ id: "meta_stories",
661
+ platform: "meta",
662
+ name: "Facebook and Instagram Stories",
663
+ sizes: [size(1080, 1920)],
664
+ safe: { top: 0.16, bottom: 0.22, left: 0.04, right: 0.04 },
665
+ cover: { top: 0.09, bottom: 0.15 },
666
+ source: "https://www.facebook.com/business/ads-guide/update/image/instagram-story"
667
+ },
668
+ {
669
+ id: "meta_reels",
670
+ platform: "meta",
671
+ name: "Facebook and Instagram Reels",
672
+ sizes: [size(1080, 1920)],
673
+ safe: { top: 0.16, bottom: 0.37, left: 0.04, right: 0.04 },
674
+ cover: { top: 0.09, bottom: 0.32, rail: { width: 0.08, from: 0.6 } },
675
+ railMargin: { width: 0.1, from: 0.55 },
676
+ source: "https://www.facebook.com/business/ads-guide/update/image/instagram-reels"
677
+ },
678
+ {
679
+ id: "meta_right_column",
680
+ platform: "meta",
681
+ name: "Facebook right column, Marketplace and search results",
682
+ sizes: [size(1080, 1080), size(1200, 628, false)],
683
+ safe: FEED_MARGIN,
684
+ optIn: true,
685
+ source: "https://www.facebook.com/business/ads-guide/update/image/facebook-right-column"
686
+ },
687
+ {
688
+ id: "google_display_responsive",
689
+ platform: "google_display",
690
+ name: "Responsive display ads (Google Display Network)",
691
+ sizes: [size(1200, 628), size(1200, 1200), size(900, 1600, false)],
692
+ safe: FEED_MARGIN,
693
+ rule: "Text may cover at most 20% of the image; Google crops up to 5% from each side.",
694
+ source: "https://support.google.com/google-ads/answer/9823397"
695
+ },
696
+ {
697
+ id: "google_display_banners",
698
+ platform: "google_display",
699
+ name: "Uploaded display banners",
700
+ sizes: [
701
+ size(300, 250),
702
+ size(728, 90),
703
+ size(320, 50),
704
+ size(336, 280, false),
705
+ size(300, 600, false),
706
+ size(160, 600, false),
707
+ size(320, 100, false),
708
+ size(970, 250, false)
709
+ ],
710
+ safe: FEED_MARGIN,
711
+ rule: "Each banner is exactly its pixel size, 150 KB at most.",
712
+ source: "https://support.google.com/google-ads/answer/7031480"
713
+ },
714
+ {
715
+ id: "google_pmax",
716
+ platform: "google_pmax",
717
+ name: "Performance Max asset group",
718
+ sizes: [size(1200, 628), size(1200, 1200), size(960, 1200, false)],
719
+ safe: FEED_MARGIN,
720
+ rule: "Google crops up to 5% from each side; keep text and logos off the edges.",
721
+ source: "https://support.google.com/google-ads/answer/13676244"
722
+ },
723
+ {
724
+ id: "google_demandgen",
725
+ platform: "google_demandgen",
726
+ name: "Demand Gen (YouTube, Discover, Gmail)",
727
+ sizes: [size(1200, 628), size(1200, 1200), size(960, 1200, false)],
728
+ safe: FEED_MARGIN,
729
+ source: "https://support.google.com/google-ads/answer/13547298"
730
+ },
731
+ {
732
+ id: "google_search_images",
733
+ platform: "google_search",
734
+ name: "Image assets on Search ads",
735
+ sizes: [size(1200, 1200), size(1200, 628, false)],
736
+ safe: FEED_MARGIN,
737
+ rule: "No overlaid text, logos or buttons on the image.",
738
+ source: "https://support.google.com/google-ads/answer/12118270"
739
+ },
740
+ {
741
+ id: "youtube_feed",
742
+ platform: "youtube",
743
+ name: "YouTube home and watch-next feeds",
744
+ sizes: [size(1200, 628), size(1200, 1200, false)],
745
+ safe: FEED_MARGIN,
746
+ source: "https://support.google.com/google-ads/answer/13547298"
747
+ },
748
+ {
749
+ id: "youtube_shorts",
750
+ platform: "youtube",
751
+ name: "YouTube Shorts",
752
+ sizes: [size(1080, 1920)],
753
+ safe: { top: 0.12, bottom: 0.35, left: 0.05, right: 0.05 },
754
+ cover: { top: 0.08, bottom: 0.3, rail: { width: 0.14, from: 0.45 } },
755
+ railMargin: { width: 0.16, from: 0.4 },
756
+ source: "https://support.google.com/youtube/answer/10059070"
757
+ },
758
+ {
759
+ id: "linkedin_feed",
760
+ platform: "linkedin",
761
+ name: "LinkedIn feed (single image)",
762
+ sizes: [size(1200, 1200), size(1200, 627, false), size(720, 900, false)],
763
+ safe: FEED_MARGIN,
764
+ source: "https://www.linkedin.com/help/lms/answer/a426534"
765
+ },
766
+ {
767
+ id: "tiktok_feed",
768
+ platform: "tiktok",
769
+ name: "TikTok For You feed",
770
+ sizes: [size(1080, 1920)],
771
+ safe: { top: 0.1, bottom: 0.3, left: 0.06, right: 0.06 },
772
+ cover: { top: 0.07, bottom: 0.25, rail: { width: 0.13, from: 0.45 } },
773
+ railMargin: { width: 0.15, from: 0.4 },
774
+ source: "https://ads.tiktok.com/help/article/tiktok-ads-safe-zone"
775
+ },
776
+ {
777
+ id: "x_timeline",
778
+ platform: "x",
779
+ name: "X timeline (image and website card)",
780
+ sizes: [size(1200, 628), size(1200, 1200, false)],
781
+ safe: FEED_MARGIN,
782
+ source: "https://business.x.com/en/help/campaign-setup/creative-ad-specifications"
783
+ },
784
+ {
785
+ id: "reddit_feed",
786
+ platform: "reddit",
787
+ name: "Reddit feed and conversation pages",
788
+ sizes: [size(1080, 1080), size(1080, 1350, false), size(1200, 628, false)],
789
+ safe: FEED_MARGIN,
790
+ source: "https://business.reddithelp.com/s/article/image-ad-specs"
791
+ },
792
+ {
793
+ id: "pinterest_feed",
794
+ platform: "pinterest",
795
+ name: "Pinterest home feed and search (standard pin)",
796
+ sizes: [size(1e3, 1500), size(1e3, 1e3, false)],
797
+ safe: FEED_MARGIN,
798
+ source: "https://help.pinterest.com/en/business/article/pinterest-product-specs"
799
+ },
800
+ {
801
+ id: "snapchat_snap_ads",
802
+ platform: "snapchat",
803
+ name: "Snapchat Snap Ads",
804
+ sizes: [size(1080, 1920)],
805
+ safe: { top: 0.11, bottom: 0.21, left: 0.04, right: 0.04 },
806
+ cover: { top: 0.08, bottom: 0.18 },
807
+ source: "https://businesshelp.snapchat.com/s/article/single-image-video-specs"
808
+ },
809
+ {
810
+ id: "chatgpt_card",
811
+ platform: "chatgpt",
812
+ name: "ChatGPT sponsored card",
813
+ sizes: [size(1200, 1200)],
814
+ safe: FEED_MARGIN,
815
+ rule: "The card shows a square of the image; keep everything that matters inside it.",
816
+ source: "https://help.openai.com/en/articles/chatgpt-ads"
817
+ }
818
+ ];
819
+ var RATIOS = [
820
+ ["1:1", 1],
821
+ ["4:5", 4 / 5],
822
+ ["9:16", 9 / 16],
823
+ ["16:9", 16 / 9],
824
+ ["1.91:1", 1.91],
825
+ ["2:3", 2 / 3],
826
+ ["3:4", 3 / 4],
827
+ ["4:3", 4 / 3]
828
+ ];
829
+ function ratioLabel(width, height) {
830
+ const r = width / height;
831
+ const known = RATIOS.find(([, value]) => Math.abs(Math.log(r / value)) < 0.01);
832
+ return known ? known[0] : `${width}x${height}`;
833
+ }
834
+ function placementsFor(names) {
835
+ const placements = [];
836
+ const unknown = [];
837
+ for (const raw of names) {
838
+ const name = raw.trim().toLowerCase();
839
+ if (!name) continue;
840
+ const found = AD_PLACEMENTS.filter((p) => p.id === name || p.platform === name && !p.optIn);
841
+ if (found.length === 0) unknown.push(raw.trim());
842
+ for (const p of found) if (!placements.includes(p)) placements.push(p);
843
+ }
844
+ return { placements, unknown };
845
+ }
846
+ function addSize(into, format, size2, placement) {
847
+ const existing = into.find((f) => f.format === format);
848
+ if (!existing) {
849
+ into.push({ format, width: size2.width, height: size2.height, placements: [placement] });
850
+ return;
851
+ }
852
+ if (!existing.placements.includes(placement)) existing.placements.push(placement);
853
+ if (size2.width > existing.width) Object.assign(existing, { width: size2.width, height: size2.height });
854
+ }
855
+ function leadOf(names) {
856
+ for (const raw of names) {
857
+ const name = raw.trim().toLowerCase();
858
+ if (name in AD_PLATFORM_LEAD) return AD_PLATFORM_LEAD[name];
859
+ const placement = AD_PLACEMENTS.find((p) => p.id === name);
860
+ const first = placement?.sizes.find((s) => s.required);
861
+ if (first) return ratioLabel(first.width, first.height);
862
+ }
863
+ return void 0;
864
+ }
865
+ function leadFirst(formats, lead) {
866
+ const at = formats.findIndex((f) => f.format === lead);
867
+ return at <= 0 ? formats : [formats[at], ...formats.filter((_, i) => i !== at)];
868
+ }
869
+ function deliveryPlan(names, asked) {
870
+ const { placements, unknown } = placementsFor(names);
871
+ const { required, shown, banners } = sizesOf(placements);
872
+ const { formats, refused } = asked && asked.length > 0 ? askedSizes(asked, shown, placements) : { formats: required, refused: [] };
873
+ const platformLead = leadOf(names);
874
+ const lead = formats.some((f) => f.format === platformLead) ? platformLead : formats[0]?.format;
875
+ const delivered = leadFirst(formats, lead);
876
+ const served = new Set(delivered.flatMap((f) => f.placements));
877
+ return {
878
+ lead: lead ?? "",
879
+ formats: delivered,
880
+ banners,
881
+ placements: placements.map((p) => p.id).filter((id) => served.has(id)),
882
+ unknown,
883
+ refused,
884
+ cropped: placements.filter((p) => ratioSized(p) && !served.has(p.id)).map((p) => p.id)
885
+ };
886
+ }
887
+ function sizesOf(placements) {
888
+ const required = [];
889
+ const shown = [];
890
+ const banners = [];
891
+ for (const placement of placements) {
892
+ for (const s of placement.sizes) {
893
+ const format = ratioLabel(s.width, s.height);
894
+ if (isBanner(format)) {
895
+ if (s.required) addSize(banners, format, s, placement.id);
896
+ continue;
897
+ }
898
+ addSize(shown, format, s, placement.id);
899
+ if (s.required) addSize(required, format, s, placement.id);
900
+ }
901
+ }
902
+ return { required, shown, banners };
903
+ }
904
+ function askedSizes(asked, shown, placements) {
905
+ const where = [...new Set(placements.map((p) => AD_PLATFORM_NAMES[p.platform]))].join(" or ") || "No placement named";
906
+ const formats = [];
907
+ const refused = [];
908
+ for (const format of new Set(asked.map((f) => f.trim()))) {
909
+ const found = shown.find((f) => f.format === format);
910
+ if (found) formats.push(found);
911
+ else refused.push({ format, why: `${where} shows no ${format} picture` });
912
+ }
913
+ return { formats, refused };
914
+ }
915
+ var isBanner = (format) => format.includes("x");
916
+ var ratioSized = (p) => p.sizes.some((s) => s.required && !isBanner(ratioLabel(s.width, s.height)));
917
+ function verticalCover(placementIds) {
918
+ const covering = AD_PLACEMENTS.filter((p) => placementIds.includes(p.id) && p.cover);
919
+ if (covering.length === 0) return null;
920
+ const max = (pick) => Math.max(...covering.map((p) => pick(p) ?? 0));
921
+ const rails = covering.filter((p) => p.cover?.rail);
922
+ const margins = covering.filter((p) => p.railMargin);
923
+ return {
924
+ top: max((p) => p.cover?.top),
925
+ bottom: max((p) => p.cover?.bottom),
926
+ ...rails.length > 0 ? {
927
+ rail: {
928
+ width: max((p) => p.cover?.rail?.width),
929
+ from: Math.min(...rails.map((p) => p.cover?.rail?.from ?? 1))
930
+ }
931
+ } : {},
932
+ ...margins.length > 0 ? {
933
+ railMargin: {
934
+ width: max((p) => p.railMargin?.width),
935
+ from: Math.min(...margins.map((p) => p.railMargin?.from ?? 1))
936
+ }
937
+ } : {},
938
+ safe: {
939
+ top: max((p) => p.safe.top),
940
+ bottom: max((p) => p.safe.bottom),
941
+ left: max((p) => p.safe.left),
942
+ right: max((p) => p.safe.right)
943
+ }
944
+ };
945
+ }
946
+
947
+ // ../canvas-contract/src/adRead.ts
948
+ var AD_DESCRIBE_FOCUS = "FIRST, WHY THIS AD WINS, in layers, in `why_it_wins` { disguise (what it pretends to be: a note, a tweet, a newspaper, a chat, a plain ad), voice (who speaks, and how), trigger (the emotion or need it pulls: a free gift, a hidden loss, status, curiosity), attention (what stops the scroll), logic (why it convinces: reciprocity, social proof, a comparison, a price anchor) }, one short phrase each; and in `load_bearing` the 1-4 elements it stops working without (never decoration), each { element, needs: what it takes to carry it } (a free gift, a real peer's face, priced tiers, a native disguise). THEN the LAYOUT: the column/row grid, which region holds what (describe each by what fills it and where it sits, never by percentages or pixel figures), any panel splits, and for EVERY text block its string verbatim, its size relative to the other text (x_large | large | medium | small), weight, case, colour in words, and placement, including small bottom-corner fine print, and whether it is lettered on something in the scene (`surface`). Also: the EXPRESSION and emotion of every person/animal (capture exaggerated or AI-edited faces), the ad_intent, logos by brand, and all visible text verbatim. The TYPOGRAPHY as a first-class identity signal: for EVERY distinct typeface record a `fonts` entry (which text blocks use it, its classification, a best-guess family or close lookalike, its weight/case/styling), and whether the advertiser's LOGO appears in more than one lockup (a square/icon MARK and a horizontal WORDMARK are two assets: capture BOTH). Capture as a photographer would describe it in words (phone or studio, the height and angle, the light and its direction), never as lens or exposure figures. CRITICAL: name the MECHANISM, the one device that makes THIS ad work on a stranger rather than a generic ad (VERBAL: a rhyme, pun, repetition, antithesis; VISUAL: an unexpected crop or scale, a visual gag, a before/after or comparison, bold negative space; STRUCTURAL: an unusual hook, order or reveal). Record every device in `winning_mechanisms` as { kind: verbal|visual|structural, device, why_it_works } and the strongest one in `mechanism`. And read WHO the ad is for, in `audience`: the viewer it speaks to, their awareness stage, how warm they must already be, and whether the copy only works if they already know this brand or offer (`presumes_brand_knowledge`), so a rebuild for a different audience knows what to change";
949
+ var AD_SELECT_SYSTEM = 'You identify the MAIN, identity-critical visual elements of an advertisement from its JSON blueprint \u2014 the things a faithful reproduction must supply as REAL reference images instead of letting a model invent them. Output ONLY a JSON object of the form { "elements": [ ... ] }, no prose.';
950
+ var AD_SELECT_PROMPT = `AD BLUEPRINT (from image_describe):
951
+ {{blueprint}}
952
+
953
+ From this blueprint, list ONLY the elements that are prominent, important, and identity-bearing \u2014 the ones a reproduction must ground in a real asset:
954
+ - the brand logo/wordmark (from brands_logos with function_in_image = advertiser_brand) -> type "logo". A brand often ships its logo in TWO lockups \u2014 a square/icon MARK and a horizontal WORDMARK \u2014 and an ad may use both (e.g. an icon in a product mock plus the wordmark in the sign-off). When more than one distinct lockup of the SAME advertiser appears, emit a SEPARATE logo element for each (label them by lockup, e.g. LOGO_MARK and LOGO_WORDMARK) so the reproduction can drop the right file in each slot instead of stretching one logo to cover both.
955
+ - trust/rating/certification/app-store/review badges (brands_logos with function_in_image = trust_badge | review_platform | certification_or_seal | app_store_badge | payment_method) -> type "badge"
956
+ - a showcased/hero product or package (a foreground entry in subjects that the ad is selling) -> type "product"
957
+ - a foreground person (from people) \u2014 keep it when its identity matters OR it is the emotional/hero focal point of the ad, even a generic one with no brand identity -> type "person". Describe them as a castable, invented everyday person (age band, look, wardrobe, expression) \u2014 never the source person's identity: unless a company avatar is cast, the render draws this person from your words alone
958
+ - a foreground animal/character (from subjects) \u2014 keep it when it carries a specific expression OR it is the emotional/hero focal point, even a generic one -> type "animal"
959
+ (For an animal: a free-generated muzzle or teeth reads as AI and grows artifacts \u2014 malformed mouths, foam \u2014 so the emotional hero needs the STRONGEST real grounding, not the weakest; "it's just a generic dog/person" is never a reason to drop either.)
960
+
961
+ DROP background extras, decorative props, generic scenery, and anything small or incidental. Keep at most ~6. If there are none, return an empty list.
962
+
963
+ For each kept element return: { "type": one of logo|product|person|animal|badge, "label": a short UPPER_SNAKE_CASE name (e.g. LOGO, PRODUCT, HERO_DOG, TRUSTPILOT), "description": a concrete reusable description to source/shoot the real asset (include the exact expression for a living subject, and its castable attributes \u2014 breed/species for an animal, apparent age band, apparent origin/ethnicity, and wardrobe/setting for a person \u2014 so it can be recast to fit OUR audience/market), "expression": the facial expression for a living subject or null, "reason": why it is identity-critical, "locator": the blueprint entry this element came from as { "collection": one of "subjects" | "people" | "brands_logos", "index": its 0-based position in that array } (people -> people; logos/badges -> brands_logos; products/animals/objects -> subjects). Output ONLY the JSON object.`;
964
+
965
+ // ../canvas-contract/src/castName.ts
966
+ function withoutCastName(text, names) {
967
+ let out = text;
968
+ for (const name of names) {
969
+ const token = name.trim();
970
+ if (token.length < 3) continue;
971
+ const pattern = new RegExp(`(?<![\\p{L}\\p{N}])${escapeForPattern(token)}(?![\\p{L}\\p{N}])`, "giu");
972
+ out = out.replace(pattern, "the person in the reference");
973
+ }
974
+ return out;
975
+ }
976
+ function escapeForPattern(value) {
977
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
978
+ }
979
+
980
+ // ../canvas-contract/src/adPlatformFormats.ts
981
+ var AD_FORMAT_PLATFORMS = [
982
+ "meta_feed",
983
+ "meta_feed_stories",
984
+ "meta_all",
985
+ "linkedin",
986
+ "google_search",
987
+ "google_demandgen",
988
+ "tiktok",
989
+ "youtube"
990
+ ];
991
+ var AD_PLATFORM_FORMAT_PRESETS = {
992
+ meta_feed: { formats: ["4:5"], note: "Meta/Instagram feed static." },
993
+ meta_feed_stories: { formats: ["4:5", "9:16"], note: "Meta feed + Stories/Reels." },
994
+ meta_all: { formats: ["4:5", "9:16", "1:1"], note: "Meta feed + Stories/Reels + square." },
995
+ linkedin: { formats: ["1:1"], note: "LinkedIn single-image feed (square)." },
996
+ google_search: {
997
+ // Search image assets: 1:1 is the required one, 1.91:1 the optional landscape.
998
+ // 16:9 is rendered only as the crop source for that landscape — Search never serves 16:9 itself.
999
+ formats: ["1:1", "16:9"],
1000
+ offGrid: ["1.91:1"],
1001
+ note: "Google Search image assets (the image extension on a text ad); 1:1 required, 1.91:1 landscape \u2014 crop that from the rendered 16:9. Stage 3+ per campaign."
1002
+ },
1003
+ google_demandgen: {
1004
+ // Renders 16:9 too so the off-grid 1.91:1 landscape has a native source to crop from.
1005
+ formats: ["1:1", "4:5", "16:9"],
1006
+ offGrid: ["1.91:1"],
1007
+ note: "Google Demand Gen; also wants 1.91:1 landscape \u2014 crop that from the rendered 16:9."
1008
+ },
1009
+ tiktok: { formats: ["9:16"], note: "TikTok full-screen vertical." },
1010
+ youtube: { formats: ["16:9"], note: "YouTube in-stream / companion display." }
1011
+ };
1012
+ function platformFormats(platform) {
1013
+ return AD_PLATFORM_FORMAT_PRESETS[platform].formats;
1014
+ }
1015
+ function resolveAdaptFormats(params) {
1016
+ if (params.platform) return platformFormats(params.platform);
1017
+ return params.formats ?? [];
1018
+ }
1019
+
1020
+ // ../canvas-contract/src/registry.ts
1021
+ var OPENROUTER_ROUTE = { provider: "openrouter" };
1022
+ var USAGE_BILLED = { kind: "usage" };
1023
+ var MIN_BILLED_SECONDS = 5;
1024
+ var SEEDANCE_FACE_RECOVERY_ROUTE = {
1025
+ provider: "fal",
1026
+ wireModel: "bytedance/seedance-2.5/reference-to-video"
1027
+ };
1028
+ var OPENROUTER_IMAGE_AR = ["1:1", "2:3", "3:2", "3:4", "4:3", "4:5", "5:4", "9:16", "16:9", "21:9"];
1029
+ var OPENROUTER_IMAGE_AR_EXTREME = [...OPENROUTER_IMAGE_AR, "1:4", "4:1", "1:8", "8:1"];
1030
+ var OPENROUTER_IMAGE_AR_GPT = ["1:1", "2:3", "3:2", "3:4", "4:3", "9:16", "16:9", "21:9"];
1031
+ var GPT_IMAGE_PROMPT_MAX = 32e3;
1032
+ var RECRAFT_PROMPT_MAX = 1e4;
1033
+ var SEEDANCE_PROMPT_MAX = 4e3;
1034
+ var KLING_PROMPT_MAX = 2500;
1035
+ var UINT32_MAX = 4294967295;
1036
+ var VEO_SEED_MAX = UINT32_MAX;
1037
+ var GPT_IMAGE_MAX_REFERENCES = 16;
1038
+ var GEMINI_IMAGE_MAX_REFERENCES = 14;
1039
+ var RECRAFT_MAX_REFERENCES = 1;
1040
+ var SEEDANCE_MAX_REFERENCES = 9;
1041
+ var OPENROUTER_IMAGE_SIZE = ["1K", "2K", "4K"];
1042
+ var OPENROUTER_IMAGE_SIZES = ["0.5K", ...OPENROUTER_IMAGE_SIZE];
1043
+ var OPENROUTER_IMAGE_SIZE_EXTENDED = OPENROUTER_IMAGE_SIZES;
1044
+ var GEMINI_LITE_IMAGE_SIZE = ["1K"];
1045
+ var OPENROUTER_IMAGE_QUALITY = ["auto", "low", "medium", "high"];
1046
+ var OPENROUTER_IMAGE_QUALITY_25 = ["auto", "low", "medium", "high", "xhigh", "max"];
1047
+ var OPENROUTER_IMAGE_N = { kind: "number", integer: true, min: 1, max: 10 };
1048
+ var RECRAFT_IMAGE_AR = ["1:1", "4:3", "3:4", "16:9", "9:16"];
1049
+ var SEEDANCE_DURATIONS = [4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
1050
+ var SEEDANCE_25_DURATIONS = [
1051
+ 4,
1052
+ 5,
1053
+ 6,
1054
+ 7,
1055
+ 8,
1056
+ 9,
1057
+ 10,
1058
+ 11,
1059
+ 12,
1060
+ 13,
1061
+ 14,
1062
+ 15,
1063
+ 16,
1064
+ 17,
1065
+ 18,
1066
+ 19,
1067
+ 20,
1068
+ 21,
1069
+ 22,
1070
+ 23,
1071
+ 24,
1072
+ 25,
1073
+ 26,
1074
+ 27,
1075
+ 28,
1076
+ 29,
1077
+ 30
1078
+ ];
1079
+ var SEEDANCE_25_ASPECT_RATIOS = ["1:1", "3:4", "9:16", "4:3", "16:9", "21:9"];
1080
+ var SEEDANCE_25_RESOLUTIONS = ["480p", "720p"];
1081
+ var SEEDANCE_25_MAX_IMAGE_REFERENCES = 30;
1082
+ var SEEDANCE_25_MAX_VIDEO_REFERENCES = 10;
1083
+ var SEEDANCE_25_MAX_AUDIO_REFERENCES = 10;
1084
+ var KLING_DURATIONS = [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
1085
+ var GEMINI_OMNI_DURATIONS = [3, 4, 5, 6, 7, 8, 9, 10];
1086
+ var GEMINI_OMNI_ASPECT_RATIOS = ["16:9", "9:16"];
1087
+ var GEMINI_OMNI_RESOLUTIONS = ["360p", "720p", "1080p", "4k"];
1088
+ var GEMINI_OMNI_IMAGE_MIMES = ["image/png", "image/jpeg", "image/webp"];
1089
+ var GROK_IMAGINE_DURATIONS = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
1090
+ var WAN_27_DURATIONS = [2, 3, 4, 5, 6, 7, 8, 9, 10];
1091
+ var HAPPYHORSE_DURATIONS = [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
1092
+ var WAN_30_DURATIONS = [
1093
+ 2,
1094
+ 3,
1095
+ 4,
1096
+ 5,
1097
+ 6,
1098
+ 7,
1099
+ 8,
1100
+ 9,
1101
+ 10,
1102
+ 11,
1103
+ 12,
1104
+ 13,
1105
+ 14,
1106
+ 15,
1107
+ 16,
1108
+ 17,
1109
+ 18,
1110
+ 19,
1111
+ 20,
1112
+ 21,
1113
+ 22,
1114
+ 23,
1115
+ 24,
1116
+ 25,
1117
+ 26,
1118
+ 27,
1119
+ 28,
1120
+ 29,
1121
+ 30
1122
+ ];
1123
+ var GROK_IMAGINE_15_DURATIONS = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
1124
+ var RUNWAY_45_DURATIONS = [2, 3, 4, 5, 6, 7, 8, 9, 10];
1125
+ var ELEVENLABS_OUTPUT_FORMATS = [
1126
+ "mp3_22050_32",
1127
+ "mp3_44100_32",
1128
+ "mp3_44100_64",
1129
+ "mp3_44100_96",
1130
+ "mp3_44100_128",
1131
+ "mp3_44100_192"
1132
+ ];
1133
+ var ELEVENLABS_MAX_TEXT_CHARS = 45454;
1134
+ var ELEVENLABS_MAX_MUSIC_LENGTH_MS = 454545;
1135
+ var ELEVENLABS_MUSIC_ENGINE = "music_v2";
1136
+ var OPENROUTER_IMAGE_MIMES = ["image/png", "image/jpeg", "image/webp", "image/gif"];
1137
+ var OPENROUTER_VIDEO_REFERENCE_MIMES = ["video/mp4", "video/quicktime", "video/webm"];
1138
+ var OPENROUTER_AUDIO_REFERENCE_MIMES = ["audio/mpeg", "audio/mp3", "audio/wav"];
1139
+ var REPLICATE_IMAGE_MIMES = ["image/png", "image/jpeg", "image/webp"];
1140
+ var REPLICATE_VIDEO_MIMES = ["video/mp4", "video/webm", "video/quicktime"];
1141
+ var DECONSTRUCT_VIDEO_MIMES = ["video/mp4", "video/webm", "video/quicktime"];
1142
+ var REPLICATE_AUDIO_MIMES = ["audio/wav", "audio/mpeg", "audio/mp3"];
1143
+ var IMAGE_GENERATE_MODELS = [
1144
+ "openai/gpt-image-2.5-sunburst",
1145
+ "openai/gpt-image-2",
1146
+ "google/gemini-3.1-flash-image",
1147
+ "google/gemini-3.1-flash-lite-image",
1148
+ "google/gemini-3-pro-image",
1149
+ "recraft/recraft-v4.1-pro-vector"
1150
+ ];
1151
+ var DEFAULT_IMAGE_GENERATE_MODEL = "google/gemini-3.1-flash-image";
1152
+ var IMAGE_PRICE_TIER = {
1153
+ "openai/gpt-image-2.5-sunburst": "standard",
1154
+ "openai/gpt-image-2": "standard",
1155
+ "google/gemini-3.1-flash-image": "standard",
1156
+ "google/gemini-3.1-flash-lite-image": "standard",
1157
+ "google/gemini-3-pro-image": "pro",
1158
+ "recraft/recraft-v4.1-pro-vector": "standard"
1159
+ };
1160
+ var IMAGE_TIER_CREDITS = { pro: 20, standard: 5 };
1161
+ function imagePictureCredits(model) {
1162
+ const tier = IMAGE_PRICE_TIER[canonicalModelId(model)] ?? "standard";
1163
+ return IMAGE_TIER_CREDITS[tier];
1164
+ }
1165
+ var VIDEO_GENERATE_MODELS = [
1166
+ "bytedance/seedance-2.0",
1167
+ "bytedance/seedance-2.5",
1168
+ "google/gemini-omni-1.1-flash",
1169
+ "google/gemini-omni-flash",
1170
+ "google/veo-3.1",
1171
+ "google/veo-3.1-fast",
1172
+ "google/veo-3.1-lite",
1173
+ "kwaivgi/kling-v3.0-pro",
1174
+ "x-ai/grok-imagine-video",
1175
+ "x-ai/grok-imagine-video-1.5",
1176
+ "alibaba/wan-2.7",
1177
+ "alibaba/wan-3.0",
1178
+ "runway/gen-4.5",
1179
+ "alibaba/happyhorse-1.1"
1180
+ ];
1181
+ var DEFAULT_VIDEO_GENERATE_MODEL = "google/gemini-omni-1.1-flash";
1182
+ var REFERENCE_TO_VIDEO_MODELS = [
1183
+ "bytedance/seedance-2.0",
1184
+ "bytedance/seedance-2.5",
1185
+ "google/gemini-omni-1.1-flash",
1186
+ "google/gemini-omni-flash",
1187
+ "x-ai/grok-imagine-video",
1188
+ "alibaba/wan-2.7",
1189
+ "alibaba/happyhorse-1.1"
1190
+ ];
1191
+ function supportsReferenceToVideo(model) {
1192
+ return REFERENCE_TO_VIDEO_MODELS.includes(model);
1193
+ }
1194
+ var DEFAULT_AVATAR_VIDEO_MODEL = "x-ai/grok-imagine-video";
1195
+ function isGeminiOmniModel(model) {
1196
+ return model.startsWith("google/gemini-omni");
1197
+ }
1198
+ var GEMINI_OMNI_PREVIEW_MODEL = "google/gemini-omni-flash";
1199
+ function isGeminiOmniPreviewModel(model) {
1200
+ return model === GEMINI_OMNI_PREVIEW_MODEL;
1201
+ }
1202
+ function isSeedance25Model(model) {
1203
+ return model === "bytedance/seedance-2.5";
1204
+ }
1205
+ var LAST_FRAME_TO_VIDEO_MODELS = [
1206
+ "bytedance/seedance-2.0",
1207
+ "bytedance/seedance-2.5",
1208
+ "google/veo-3.1",
1209
+ "google/veo-3.1-fast",
1210
+ "kwaivgi/kling-v3.0-pro"
1211
+ ];
1212
+ function supportsLastFrame(model) {
1213
+ return LAST_FRAME_TO_VIDEO_MODELS.includes(model);
1214
+ }
1215
+ var MODEL_REGISTRY = {
1216
+ text_generate: {
1217
+ "~google/gemini-flash-latest": {
1218
+ label: "Google Gemini Flash (latest)",
1219
+ route: OPENROUTER_ROUTE,
1220
+ billing: USAGE_BILLED,
1221
+ inputs: [],
1222
+ required: ["prompt"],
1223
+ params: {
1224
+ prompt: { kind: "string" },
1225
+ system: { kind: "string" },
1226
+ response_format: { kind: "string", enum: ["text", "json_object"] },
1227
+ web_search: { kind: "boolean" },
1228
+ temperature: { kind: "number", min: 0, max: 2 },
1229
+ max_tokens: { kind: "number", min: 1 }
1230
+ }
1231
+ },
1232
+ "~google/gemini-pro-latest": {
1233
+ label: "Google Gemini Pro (latest)",
1234
+ route: OPENROUTER_ROUTE,
1235
+ billing: USAGE_BILLED,
1236
+ inputs: [],
1237
+ required: ["prompt"],
1238
+ params: {
1239
+ prompt: { kind: "string" },
1240
+ system: { kind: "string" },
1241
+ response_format: { kind: "string", enum: ["text", "json_object"] },
1242
+ web_search: { kind: "boolean" },
1243
+ temperature: { kind: "number", min: 0, max: 2 },
1244
+ max_tokens: { kind: "number", min: 1 }
1245
+ }
1246
+ }
1247
+ },
1248
+ image_describe: {
1249
+ // Vision extraction — the Visual Architect system prompt lives on the
1250
+ // backend, so there is no `prompt` param; `focus` appends emphasis only.
1251
+ "~google/gemini-pro-latest": {
1252
+ label: "Google Gemini Pro (latest, Vision)",
1253
+ route: OPENROUTER_ROUTE,
1254
+ billing: USAGE_BILLED,
1255
+ inputs: [{ kind: "image", mimes: OPENROUTER_IMAGE_MIMES }],
1256
+ required: [],
1257
+ params: {
1258
+ focus: { kind: "string" },
1259
+ context: { kind: "string" },
1260
+ temperature: { kind: "number", min: 0, max: 2 },
1261
+ max_tokens: { kind: "number", min: 1 }
1262
+ }
1263
+ },
1264
+ "~google/gemini-flash-latest": {
1265
+ label: "Google Gemini Flash (latest, Vision)",
1266
+ route: OPENROUTER_ROUTE,
1267
+ billing: USAGE_BILLED,
1268
+ inputs: [{ kind: "image", mimes: OPENROUTER_IMAGE_MIMES }],
1269
+ required: [],
1270
+ params: {
1271
+ focus: { kind: "string" },
1272
+ context: { kind: "string" },
1273
+ temperature: { kind: "number", min: 0, max: 2 },
1274
+ max_tokens: { kind: "number", min: 1 }
1275
+ }
1276
+ }
1277
+ },
1278
+ image_select: {
1279
+ // Vision judgement — the selection contract (numbered images, JSON
1280
+ // response) is baked into the backend prompt; `prompt` carries only the
1281
+ // selection criteria. `count` has an engine-side default of 1, so it is
1282
+ // not registry-required.
1283
+ "~google/gemini-flash-latest": {
1284
+ label: "Google Gemini Flash (latest, Vision)",
1285
+ route: OPENROUTER_ROUTE,
1286
+ billing: USAGE_BILLED,
1287
+ inputs: [{ kind: "image", mimes: OPENROUTER_IMAGE_MIMES }],
1288
+ required: ["prompt"],
1289
+ params: {
1290
+ prompt: { kind: "string" },
1291
+ count: { kind: "number", min: 1 },
1292
+ temperature: { kind: "number", min: 0, max: 2 },
1293
+ max_tokens: { kind: "number", min: 1 }
1294
+ }
1295
+ },
1296
+ "~google/gemini-pro-latest": {
1297
+ label: "Google Gemini Pro (latest, Vision)",
1298
+ route: OPENROUTER_ROUTE,
1299
+ billing: USAGE_BILLED,
1300
+ inputs: [{ kind: "image", mimes: OPENROUTER_IMAGE_MIMES }],
1301
+ required: ["prompt"],
1302
+ params: {
1303
+ prompt: { kind: "string" },
1304
+ count: { kind: "number", min: 1 },
1305
+ temperature: { kind: "number", min: 0, max: 2 },
1306
+ max_tokens: { kind: "number", min: 1 }
1307
+ }
1308
+ }
1309
+ },
1310
+ image_generate: {
1311
+ // `seed` is omitted on every entry — OpenRouter's `image_config` schema
1312
+ // has no `seed` slot for image-gen (different from video-gen), so passing
1313
+ // it would be a silent no-op.
1314
+ // The direct image model, not the `gpt-5.4-image-2` chat model that emitted
1315
+ // images as a side effect. Notable capability gaps vs the Gemini entries:
1316
+ // no `image_size` (OpenAI picks the pixel dimensions from the ratio, and a
1317
+ // `resolution` is silently ignored) and the narrower `..._AR_GPT` ratio set.
1318
+ "openai/gpt-image-2.5-sunburst": {
1319
+ // Identical to the gpt-image-2 entry below except for the quality ladder and `n`
1320
+ // (several images from one call) — the ratio set, the 16-reference ceiling, the missing `image_size` and the reasons
1321
+ // `background` / `output_compression` stay undeclared all carry over unchanged.
1322
+ label: "OpenAI GPT Image 2.5",
1323
+ route: OPENROUTER_ROUTE,
1324
+ billing: USAGE_BILLED,
1325
+ inputs: [],
1326
+ optional_inputs: [{ kind: "image", mimes: OPENROUTER_IMAGE_MIMES, max: GPT_IMAGE_MAX_REFERENCES }],
1327
+ required: ["prompt"],
1328
+ params: {
1329
+ prompt: { kind: "string", maxLength: GPT_IMAGE_PROMPT_MAX },
1330
+ aspect_ratio: { kind: "string", enum: OPENROUTER_IMAGE_AR_GPT },
1331
+ quality: { kind: "string", enum: OPENROUTER_IMAGE_QUALITY_25 },
1332
+ n: OPENROUTER_IMAGE_N
1333
+ }
1334
+ },
1335
+ "openai/gpt-image-2": {
1336
+ // Its live endpoint also advertises `background` (auto|opaque) and
1337
+ // `output_compression` (0-100), which we deliberately do not declare. Not an
1338
+ // oversight: a registry param is a promise the whole system keeps — the
1339
+ // canvas node schema, the dashboard control, the CLI flag and the cost model
1340
+ // all have to carry it — and neither knob changes what the picture IS.
1341
+ // Declaring them would widen four surfaces to expose a file-size dial.
1342
+ label: "OpenAI GPT Image 2",
1343
+ route: OPENROUTER_ROUTE,
1344
+ billing: USAGE_BILLED,
1345
+ inputs: [],
1346
+ optional_inputs: [{ kind: "image", mimes: OPENROUTER_IMAGE_MIMES, max: GPT_IMAGE_MAX_REFERENCES }],
1347
+ required: ["prompt"],
1348
+ params: {
1349
+ prompt: { kind: "string", maxLength: GPT_IMAGE_PROMPT_MAX },
1350
+ aspect_ratio: { kind: "string", enum: OPENROUTER_IMAGE_AR_GPT },
1351
+ quality: { kind: "string", enum: OPENROUTER_IMAGE_QUALITY }
1352
+ }
1353
+ },
1354
+ // The GA Nano Banana ids (2026-06-18). Same surface as the preview ids they replace
1355
+ // — read off GET /api/v1/images/models/google/gemini-3.1-flash-image/endpoints and
1356
+ // .../gemini-3-pro-image/endpoints — which is why those ids are plain aliases of
1357
+ // these (`MODEL_ALIASES`): a canvas moves between them unchanged.
1358
+ "google/gemini-3.1-flash-image": {
1359
+ label: "Google Gemini 3.1 Flash Image (Nano Banana 2)",
1360
+ route: OPENROUTER_ROUTE,
1361
+ billing: USAGE_BILLED,
1362
+ inputs: [],
1363
+ optional_inputs: [{ kind: "image", mimes: OPENROUTER_IMAGE_MIMES, max: GEMINI_IMAGE_MAX_REFERENCES }],
1364
+ required: ["prompt"],
1365
+ params: {
1366
+ prompt: { kind: "string" },
1367
+ aspect_ratio: { kind: "string", enum: OPENROUTER_IMAGE_AR_EXTREME },
1368
+ image_size: { kind: "string", enum: OPENROUTER_IMAGE_SIZE_EXTENDED }
1369
+ }
1370
+ },
1371
+ "google/gemini-3-pro-image": {
1372
+ label: "Google Gemini 3 Pro Image (Nano Banana Pro)",
1373
+ route: OPENROUTER_ROUTE,
1374
+ billing: USAGE_BILLED,
1375
+ inputs: [],
1376
+ optional_inputs: [{ kind: "image", mimes: OPENROUTER_IMAGE_MIMES, max: GEMINI_IMAGE_MAX_REFERENCES }],
1377
+ required: ["prompt"],
1378
+ params: {
1379
+ prompt: { kind: "string" },
1380
+ aspect_ratio: { kind: "string", enum: OPENROUTER_IMAGE_AR },
1381
+ image_size: { kind: "string", enum: OPENROUTER_IMAGE_SIZE }
1382
+ // No `quality`: OpenRouter's per-endpoint schema lists it for gpt-image and for
1383
+ // NO Gemini image model, pro included. It is accepted-then-dropped, so declaring
1384
+ // it invites the scaffolder to emit a param that does nothing.
1385
+ }
1386
+ },
1387
+ "google/gemini-3.1-flash-lite-image": {
1388
+ // Nano Banana 2 Lite. Same Gemini image family as the flash tier — same
1389
+ // extreme aspect-ratio set, same reference editing — at HALF the output-token
1390
+ // price ($0.00003 vs $0.00006 per output image token), which makes it the
1391
+ // cheap-iteration tier for image work the way `veo-3.1-fast` is for video.
1392
+ //
1393
+ // The one thing it gives up is resolution: it renders 1K and nothing else.
1394
+ // That is a hard provider 400, not a soft clamp, so it is gated here rather
1395
+ // than discovered at dispatch. A 2K/4K hero frame belongs on the flash or pro
1396
+ // tier. Unlike gpt-image it keeps 4:5 and 5:4, so Meta/Instagram portrait
1397
+ // formats still come straight out of it.
1398
+ //
1399
+ // Reached through the normal OpenRouter image gateway (Google Vertex and
1400
+ // Google AI Studio both serve it) — no direct-provider exception needed.
1401
+ // Source: GET /api/v1/images/models/google/gemini-3.1-flash-lite-image/endpoints.
1402
+ label: "Google Gemini 3.1 Flash Lite Image",
1403
+ route: OPENROUTER_ROUTE,
1404
+ billing: USAGE_BILLED,
1405
+ inputs: [],
1406
+ optional_inputs: [{ kind: "image", mimes: OPENROUTER_IMAGE_MIMES, max: GEMINI_IMAGE_MAX_REFERENCES }],
1407
+ required: ["prompt"],
1408
+ params: {
1409
+ prompt: { kind: "string" },
1410
+ aspect_ratio: { kind: "string", enum: OPENROUTER_IMAGE_AR_EXTREME },
1411
+ image_size: { kind: "string", enum: GEMINI_LITE_IMAGE_SIZE }
1412
+ }
1413
+ },
1414
+ "recraft/recraft-v4.1-pro-vector": {
1415
+ // The vector/logo tier, and the odd one out of this roster in three ways.
1416
+ // All three are read off its live endpoint schema, and all three are the
1417
+ // kind of fact that only shows up as a billed 400 if it is guessed:
1418
+ // - it renders FIVE ratios (no 4:5 / 5:4 / 2:3 / 3:2 / 21:9), so portrait
1419
+ // ad shapes snap to 3:4 rather than being sent as-is;
1420
+ // - it has NO resolution knob (`supported_parameters` lists none), so
1421
+ // `image_size` is refused here instead of accepted and ignored;
1422
+ // - it takes exactly ONE reference image, against 14-16 everywhere else.
1423
+ // Its palette levers are real but arrive as provider passthrough
1424
+ // (`controls`), which is why they are `json` rather than typed enums; the
1425
+ // backend adapter builds that block in `buildImageGenBody`.
1426
+ label: "Recraft v4.1 Pro Vector",
1427
+ route: OPENROUTER_ROUTE,
1428
+ billing: USAGE_BILLED,
1429
+ inputs: [],
1430
+ optional_inputs: [{ kind: "image", mimes: OPENROUTER_IMAGE_MIMES, max: RECRAFT_MAX_REFERENCES }],
1431
+ required: ["prompt"],
1432
+ params: {
1433
+ prompt: { kind: "string", maxLength: RECRAFT_PROMPT_MAX },
1434
+ aspect_ratio: { kind: "string", enum: RECRAFT_IMAGE_AR },
1435
+ strength: { kind: "number", min: 0, max: 1 },
1436
+ rgb_colors: { kind: "json" },
1437
+ background_rgb_color: { kind: "json" }
1438
+ }
1439
+ }
1440
+ },
1441
+ image_reference_sheet: {
1442
+ // Multi-view subject reference sheets (turnaround grids). The sheet prompt
1443
+ // is baked into the backend handler — params here are semantic levers
1444
+ // only. Both models consume MULTIPLE reference images via the `references`
1445
+ // input slot (required: a sheet without source images is just image_generate).
1446
+ "google/gemini-3-pro-image": {
1447
+ label: "Google Gemini 3 Pro Image (Nano Banana Pro)",
1448
+ route: OPENROUTER_ROUTE,
1449
+ billing: USAGE_BILLED,
1450
+ inputs: [{ kind: "image", mimes: OPENROUTER_IMAGE_MIMES }],
1451
+ required: ["subject_description", "subject_type"],
1452
+ params: {
1453
+ subject_description: { kind: "string" },
1454
+ subject_type: { kind: "string", enum: ["character", "person", "product", "location"] },
1455
+ views: { kind: "json" },
1456
+ style: { kind: "string" },
1457
+ prompt_override: { kind: "string" },
1458
+ aspect_ratio: { kind: "string", enum: OPENROUTER_IMAGE_AR },
1459
+ image_size: { kind: "string", enum: OPENROUTER_IMAGE_SIZE }
1460
+ }
1461
+ },
1462
+ "google/gemini-3.1-flash-image": {
1463
+ label: "Google Gemini 3.1 Flash Image (Nano Banana 2)",
1464
+ route: OPENROUTER_ROUTE,
1465
+ billing: USAGE_BILLED,
1466
+ inputs: [{ kind: "image", mimes: OPENROUTER_IMAGE_MIMES }],
1467
+ required: ["subject_description", "subject_type"],
1468
+ params: {
1469
+ subject_description: { kind: "string" },
1470
+ subject_type: { kind: "string", enum: ["character", "person", "product", "location"] },
1471
+ views: { kind: "json" },
1472
+ style: { kind: "string" },
1473
+ prompt_override: { kind: "string" },
1474
+ aspect_ratio: { kind: "string", enum: OPENROUTER_IMAGE_AR_EXTREME },
1475
+ image_size: { kind: "string", enum: OPENROUTER_IMAGE_SIZE_EXTENDED }
1476
+ }
1477
+ }
1478
+ },
1479
+ image_aspect_adapt: {
1480
+ // Multi-format adaptation of one creative. The recomposition prompt is
1481
+ // baked into the backend handler. The target ratios come from EITHER an
1482
+ // explicit `formats` list OR a `platform` preset that expands to the
1483
+ // canonical set; exactly one of the two is required — that "one of" gate,
1484
+ // and per-element ratio validation, live in the node's Zod schema (the
1485
+ // registry can't express "one of" or gate array elements), so `formats`
1486
+ // is not listed as registry-required. The source creative is a required
1487
+ // input slot. `copy` (the exact lines the ad carries) and `safe_areas` (per
1488
+ // format, the fractions each edge's interface covers) are set by the static
1489
+ // scaffold so the reframe keeps every word, once, where the platform shows it.
1490
+ "google/gemini-3-pro-image": {
1491
+ label: "Google Gemini 3 Pro Image (Nano Banana Pro)",
1492
+ route: OPENROUTER_ROUTE,
1493
+ billing: USAGE_BILLED,
1494
+ inputs: [{ kind: "image", mimes: OPENROUTER_IMAGE_MIMES }],
1495
+ required: [],
1496
+ params: {
1497
+ formats: { kind: "json" },
1498
+ platform: { kind: "string", enum: AD_FORMAT_PLATFORMS },
1499
+ guidance: { kind: "string" },
1500
+ copy: { kind: "json" },
1501
+ safe_areas: { kind: "json" },
1502
+ image_size: { kind: "string", enum: OPENROUTER_IMAGE_SIZE }
1503
+ }
1504
+ },
1505
+ "google/gemini-3.1-flash-image": {
1506
+ label: "Google Gemini 3.1 Flash Image (Nano Banana 2)",
1507
+ route: OPENROUTER_ROUTE,
1508
+ billing: USAGE_BILLED,
1509
+ inputs: [{ kind: "image", mimes: OPENROUTER_IMAGE_MIMES }],
1510
+ required: [],
1511
+ params: {
1512
+ formats: { kind: "json" },
1513
+ platform: { kind: "string", enum: AD_FORMAT_PLATFORMS },
1514
+ guidance: { kind: "string" },
1515
+ copy: { kind: "json" },
1516
+ safe_areas: { kind: "json" },
1517
+ image_size: { kind: "string", enum: OPENROUTER_IMAGE_SIZE_EXTENDED }
1518
+ }
1519
+ }
1520
+ },
1521
+ video_generate: {
1522
+ "bytedance/seedance-2.0": {
1523
+ // Routed via Replicate's official `bytedance/seedance-2.0` model. NOTE:
1524
+ // ByteDance's upstream likeness filter blocks photoreal human faces on ANY
1525
+ // reseller, and it does NOT care whether the person is real: it classifies
1526
+ // pixels, so an AI-generated face that looks photographic is refused
1527
+ // exactly like a photograph (E005 / content_policy_blocked). Confirmed in
1528
+ // production against faces we generated ourselves. The only escape is Veo
1529
+ // — NOT a synthetic presenter, which an earlier version of this note
1530
+ // wrongly recommended and which sends you round the same loop.
1531
+ label: "ByteDance Seedance 2.0",
1532
+ route: { provider: "replicate" },
1533
+ billing: { kind: "formula", formula: "seedance-2.0" },
1534
+ inputs: [],
1535
+ optional_inputs: [{ kind: "image", mimes: REPLICATE_IMAGE_MIMES, max: SEEDANCE_MAX_REFERENCES }],
1536
+ required: ["prompt"],
1537
+ params: {
1538
+ // Replicate's Seedance wrapper hard-caps the prompt at 4000 chars; gate
1539
+ // it here so an over-length prompt fails validate (free) not the billed call.
1540
+ prompt: { kind: "string", maxLength: SEEDANCE_PROMPT_MAX },
1541
+ aspect_ratio: {
1542
+ kind: "string",
1543
+ enum: ["1:1", "3:4", "9:16", "4:3", "16:9", "21:9", "9:21"]
1544
+ },
1545
+ resolution: { kind: "string", enum: ["480p", "720p", "1080p", "4k"] },
1546
+ duration: { kind: "number", enum: SEEDANCE_DURATIONS },
1547
+ // Replicate types this `integer`, and a fractional seed is a schema
1548
+ // rejection rather than a rounded one. No range is advertised, so none is
1549
+ // invented — see `InputSpec.max` on why absent must stay ungated.
1550
+ seed: { kind: "number", integer: true },
1551
+ generate_audio: { kind: "boolean" }
1552
+ }
1553
+ },
1554
+ "bytedance/seedance-2.5": {
1555
+ // Seedance 2.5 — the LONG-FORM, MULTIMODAL tier, and the only curated video
1556
+ // model reached through OpenRouter that is not frame-only.
1557
+ //
1558
+ // Routed through OpenRouter's video gateway (provider `seed`), NOT through
1559
+ // Replicate like 2.0 — the gateway carries the multimodal reference surface
1560
+ // 2.5 exists for, and Replicate's 2.0 wrapper only has `reference_images`.
1561
+ // The backend branches on the exact 2.0 id for the Replicate path, so this
1562
+ // model must never be folded into a `startsWith("bytedance/seedance")`
1563
+ // routing test: that is one character away from sending 2.5 to a wrapper
1564
+ // that cannot express half of what it is being asked to do.
1565
+ //
1566
+ // Same upstream likeness filter as 2.0 — ByteDance classifies PIXELS, so an
1567
+ // AI-generated face that reads photographic is refused exactly like a
1568
+ // photograph (content_policy_blocked). A reference-guided clip refused that
1569
+ // way is re-rendered on fal, which serves the same model under a licence that
1570
+ // takes faces; a frame-started one is reported, never moved to another model.
1571
+ //
1572
+ // No published prompt cap on this route, so none is invented: OpenRouter's
1573
+ // request schema declares no `maxLength` and the model is sold on long,
1574
+ // multi-shot briefs. A ceiling we made up would refuse the exact prompts
1575
+ // this tier exists to render.
1576
+ label: "ByteDance Seedance 2.5",
1577
+ route: OPENROUTER_ROUTE,
1578
+ billing: { kind: "formula", formula: "seedance-2.5" },
1579
+ recoveryRoute: SEEDANCE_FACE_RECOVERY_ROUTE,
1580
+ inputs: [],
1581
+ optional_inputs: [
1582
+ { kind: "image", mimes: OPENROUTER_IMAGE_MIMES, max: SEEDANCE_25_MAX_IMAGE_REFERENCES },
1583
+ { kind: "video", mimes: OPENROUTER_VIDEO_REFERENCE_MIMES, max: SEEDANCE_25_MAX_VIDEO_REFERENCES },
1584
+ { kind: "audio", mimes: OPENROUTER_AUDIO_REFERENCE_MIMES, max: SEEDANCE_25_MAX_AUDIO_REFERENCES }
1585
+ ],
1586
+ required: ["prompt"],
1587
+ params: {
1588
+ prompt: { kind: "string" },
1589
+ aspect_ratio: { kind: "string", enum: SEEDANCE_25_ASPECT_RATIOS },
1590
+ resolution: { kind: "string", enum: SEEDANCE_25_RESOLUTIONS },
1591
+ duration: { kind: "number", enum: SEEDANCE_25_DURATIONS },
1592
+ seed: { kind: "number", integer: true, min: 0, max: UINT32_MAX },
1593
+ generate_audio: { kind: "boolean" },
1594
+ // A visible AI watermark on an ad creative is a defect, and this is the
1595
+ // only curated model that lets us turn one off: `watermark` is named in
1596
+ // the model's own `allowed_passthrough_parameters`, so it rides as a
1597
+ // top-level body field exactly like Kling's `cfg_scale` does.
1598
+ watermark: { kind: "boolean" }
1599
+ }
1600
+ },
1601
+ "google/gemini-omni-1.1-flash": {
1602
+ // Google Gemini Omni 1.1 Flash — the DEFAULT video model. Natively
1603
+ // multimodal: it reasons over text + images and renders video WITH
1604
+ // synchronized audio in one call, and it is the only curated model that
1605
+ // takes reference images through its own first-party API (task
1606
+ // `reference_to_video`).
1607
+ //
1608
+ // It is a SEPARATE entry from `google/gemini-omni-flash` (the preview),
1609
+ // not a rolling upgrade of it, because the two do not render the same
1610
+ // things: 1.1 takes a `resolution` and the preview does not, and 1.1 bills
1611
+ // the seconds it renders where the preview bills its whole 10s window. One
1612
+ // shared key would have to promise the union of those, which means a canvas
1613
+ // could ask the preview for 360p and be quoted a third of what it charges.
1614
+ //
1615
+ // NOT on OpenRouter. `GET /api/v1/videos/models` lists 17 video models and
1616
+ // no Gemini Omni at either version, so this is the sanctioned direct-provider
1617
+ // exception (see `convex/lib/geminiOmni.ts`): Google's Interactions API,
1618
+ // `POST /v1beta/interactions`. Its own `generateContent` endpoint refuses it
1619
+ // ("This model only supports Interactions API"), so the Veo `predictLongRunning`
1620
+ // shape does not apply either.
1621
+ //
1622
+ // The param set below is deliberately short and was read off the live API,
1623
+ // not off the docs — the knobs absent here are rejected with a pre-dispatch
1624
+ // 400 (`Unknown parameter '<name>'`): no `seed`, no `negative_prompt`, no
1625
+ // `generate_audio`, no `person_generation` / `enhance_prompt` /
1626
+ // `conditioning_scale`. Audio is always on and cannot be turned off.
1627
+ // Widening this list does not widen the model; it just moves a free
1628
+ // validation error into a billed one.
1629
+ //
1630
+ // `duration` is the odd one out: Omni has no duration FIELD at any nesting
1631
+ // level, but it honours a length named in the prompt (3-10s), so the adapter
1632
+ // turns this param into a prompt directive. It is a real, billable knob.
1633
+ //
1634
+ // NO VIDEO INPUT SLOT, and that is a gate on our project rather than a gap
1635
+ // in the model or a mistake in how we ask. 1.1 advertises video references,
1636
+ // `edit` and `extend`, and every request carrying a video comes back 400
1637
+ // `content_blocked`.
1638
+ //
1639
+ // The controlled version, run through the shape Google's own docs use
1640
+ // (`{"type":"document","uri":<Files API uri>}`, no generation_config),
1641
+ // changing only the uploaded file: an IMAGE returns 200 and renders a clip;
1642
+ // a VIDEO returns `content_blocked`. Same route, same structure. So the
1643
+ // request shape is right and video input specifically is refused. Also
1644
+ // measured across inline base64, all three tasks, video AND text output,
1645
+ // synthetic clips, Omni's own output, real camera footage, and both our
1646
+ // keys. Full probe log: `.context/omni-1.1-measurements.md`.
1647
+ //
1648
+ // Adding `{ kind: "video", mimes: … }` below is the ONE line that turns the
1649
+ // whole feature on — the "Build on" control, the reference picker taking an
1650
+ // MP4, the drop target and the source-clip cost premium are all driven off
1651
+ // this slot. Add it the day the 400 stops, not before: until then it offers
1652
+ // a control whose every use is refused.
1653
+ label: "Google Gemini Omni 1.1 Flash",
1654
+ route: { provider: "google-interactions", wireModel: "gemini-omni-1.1-flash" },
1655
+ billing: { kind: "formula", formula: "gemini-omni" },
1656
+ inputs: [],
1657
+ optional_inputs: [{ kind: "image", mimes: GEMINI_OMNI_IMAGE_MIMES }],
1658
+ required: ["prompt"],
1659
+ params: {
1660
+ prompt: { kind: "string" },
1661
+ aspect_ratio: { kind: "string", enum: GEMINI_OMNI_ASPECT_RATIOS },
1662
+ resolution: { kind: "string", enum: GEMINI_OMNI_RESOLUTIONS },
1663
+ duration: { kind: "number", enum: GEMINI_OMNI_DURATIONS }
1664
+ }
1665
+ },
1666
+ "google/gemini-omni-flash": {
1667
+ // LEGACY — the Omni PREVIEW (`gemini-omni-flash-preview`), superseded by
1668
+ // `google/gemini-omni-1.1-flash` above. Kept so canvases authored before 1.1
1669
+ // still validate and re-run unchanged (`baker canvas run --slug` restores a
1670
+ // recorded canvas verbatim, so dropping this model would break every stored
1671
+ // creative that used it). Don't reach for it in new work.
1672
+ //
1673
+ // Its param surface is the ORIGINAL one on purpose, and the omission that
1674
+ // matters is `resolution`. This model renders 720p / 24fps and nothing else.
1675
+ //
1676
+ // It does NOT reject the field, which is the trap and the reason this is
1677
+ // enforced here rather than left to the provider: asked for `360p` it
1678
+ // returns HTTP 200, a 1280x720 clip, and a bill of 17,376 video tokens —
1679
+ // the 720p rate, three times the 5,793 that tier costs on 1.1. Accepted,
1680
+ // ignored, and charged for. Copying 1.1's enum across to make the two
1681
+ // entries match would hand a canvas a quality dial that does nothing and a
1682
+ // quote a third of the real charge.
1683
+ label: "Google Gemini Omni Flash (legacy preview)",
1684
+ route: { provider: "google-interactions", wireModel: "gemini-omni-flash-preview" },
1685
+ billing: { kind: "formula", formula: "gemini-omni" },
1686
+ inputs: [],
1687
+ optional_inputs: [{ kind: "image", mimes: GEMINI_OMNI_IMAGE_MIMES }],
1688
+ required: ["prompt"],
1689
+ params: {
1690
+ prompt: { kind: "string" },
1691
+ aspect_ratio: { kind: "string", enum: GEMINI_OMNI_ASPECT_RATIOS },
1692
+ duration: { kind: "number", enum: GEMINI_OMNI_DURATIONS }
1693
+ }
1694
+ },
1695
+ "google/veo-3.1": {
1696
+ // Photoreal CINE CEILING + the real-face fallback (Veo generates adult
1697
+ // humans from a keyframe, dodging ByteDance's real-person filter). Same
1698
+ // OpenRouter google-vertex routing as the fast tier; the quality dial is
1699
+ // `resolution: 1080p` + `generate_audio` + a real `negative_prompt`, not a
1700
+ // separate provider knob. Reach for this for hero beats and any clip that
1701
+ // must carry a real human likeness.
1702
+ label: "Google Veo 3.1",
1703
+ route: OPENROUTER_ROUTE,
1704
+ billing: {
1705
+ kind: "per_second",
1706
+ // Veo prices 4K far above the base tier, and 4K is a selectable resolution,
1707
+ // so folding it into the base rate under-quotes the dearest clip we can make.
1708
+ // A QUOTE only: the charge is the usage OpenRouter reports for the call.
1709
+ usd: { silent: 0.2, audio: 0.4, byResolution: { "4K": { silent: 0.4, audio: 0.6 } } }
1710
+ },
1711
+ inputs: [],
1712
+ optional_inputs: [{ kind: "image", mimes: OPENROUTER_IMAGE_MIMES }],
1713
+ required: ["prompt"],
1714
+ params: {
1715
+ prompt: { kind: "string" },
1716
+ negative_prompt: { kind: "string" },
1717
+ aspect_ratio: { kind: "string", enum: ["16:9", "9:16"] },
1718
+ resolution: { kind: "string", enum: ["720p", "1080p", "4K"] },
1719
+ duration: { kind: "number", enum: [4, 6, 8] },
1720
+ // Vertex declares `seed` a uint32: "accepted range 0-4294967295".
1721
+ seed: { kind: "number", integer: true, min: 0, max: VEO_SEED_MAX },
1722
+ generate_audio: { kind: "boolean" },
1723
+ person_generation: { kind: "string", enum: ["allow_all", "allow_adult"] },
1724
+ enhance_prompt: { kind: "boolean" },
1725
+ conditioning_scale: { kind: "number" }
1726
+ }
1727
+ },
1728
+ "kwaivgi/kling-v3.0-pro": {
1729
+ // Motion-transfer / dynamic multi-shot beats. Reachable through the default
1730
+ // OpenRouter gateway (generic video body — no google-vertex block), so it
1731
+ // needs no direct-provider exception. `cfg_scale` trades prompt adherence
1732
+ // vs motion freedom; higher = closer to prompt.
1733
+ //
1734
+ // Params below are the ones OpenRouter actually advertises for this model
1735
+ // (GET /api/v1/videos/models). Three were wrong before and each was a free
1736
+ // 400 or a silently unsupported knob: it renders 720p ONLY (1080p was
1737
+ // offered and rejected), it takes ANY duration from 3-15s (we allowed just
1738
+ // 5 and 10), and it does not support `seed` at all.
1739
+ label: "Kling 3.0",
1740
+ route: OPENROUTER_ROUTE,
1741
+ billing: {
1742
+ kind: "per_second",
1743
+ // One flat rate across every resolution and mode.
1744
+ usd: { silent: 0.112, audio: 0.168 }
1745
+ },
1746
+ inputs: [],
1747
+ optional_inputs: [{ kind: "image", mimes: OPENROUTER_IMAGE_MIMES }],
1748
+ required: ["prompt"],
1749
+ params: {
1750
+ // Kling caps the prompt shorter than Seedance; gate it here so an
1751
+ // over-length prompt fails validate (free) not the billed call. Its
1752
+ // negative prompt is a SEPARATE 2,500 budget, not a shared one.
1753
+ prompt: { kind: "string", maxLength: KLING_PROMPT_MAX },
1754
+ negative_prompt: { kind: "string", maxLength: KLING_PROMPT_MAX },
1755
+ aspect_ratio: { kind: "string", enum: ["16:9", "9:16", "1:1"] },
1756
+ resolution: { kind: "string", enum: ["720p"] },
1757
+ duration: { kind: "number", enum: KLING_DURATIONS },
1758
+ generate_audio: { kind: "boolean" },
1759
+ cfg_scale: { kind: "number", min: 0, max: 1 }
1760
+ }
1761
+ },
1762
+ "x-ai/grok-imagine-video": {
1763
+ // The avatar workhorse. Measured best of the reference-capable models on
1764
+ // identity retention AND aspect-ratio obedience, at the lowest rate of any
1765
+ // video model we carry ($0.05/s at 480p). No audio at all — `generate_audio`
1766
+ // is absent from its OpenRouter listing, so a talking head goes to Wan 2.7.
1767
+ // NOTE: `x-ai/grok-imagine-video-1.5` is NOT a drop-in upgrade — it is
1768
+ // described as plain image-to-video and drops the reference conditioning
1769
+ // this entry exists for.
1770
+ label: "Grok Imagine Video",
1771
+ route: OPENROUTER_ROUTE,
1772
+ billing: {
1773
+ kind: "per_second",
1774
+ usd: {
1775
+ silent: 0.07,
1776
+ audio: 0.07,
1777
+ byResolution: { "480p": { silent: 0.05, audio: 0.05 }, "720p": { silent: 0.07, audio: 0.07 } }
1778
+ }
1779
+ },
1780
+ inputs: [],
1781
+ optional_inputs: [{ kind: "image", mimes: OPENROUTER_IMAGE_MIMES }],
1782
+ required: ["prompt"],
1783
+ params: {
1784
+ prompt: { kind: "string" },
1785
+ aspect_ratio: { kind: "string", enum: ["16:9", "9:16", "1:1", "4:3", "3:4", "3:2", "2:3"] },
1786
+ resolution: { kind: "string", enum: ["480p", "720p"] },
1787
+ duration: { kind: "number", enum: GROK_IMAGINE_DURATIONS }
1788
+ }
1789
+ },
1790
+ "alibaba/wan-2.7": {
1791
+ // Reference-to-video AND native audio — the only model we carry with both,
1792
+ // which makes it the landscape talking-head option.
1793
+ //
1794
+ // LANDSCAPE ONLY, measured. It advertises 9:16, 1:1, 4:3 and 3:4, and
1795
+ // delivers 16:9 regardless: asked for vertical via `aspect_ratio: "9:16"`
1796
+ // it returned 1280x720, and asked again via an explicit
1797
+ // `size: "720x1280"` from its own `supported_sizes` it returned 1280x720
1798
+ // again. The enum below is therefore what it DOES, not what it claims, so
1799
+ // nobody pays for a vertical clip that comes back landscape. For a vertical
1800
+ // avatar clip use `x-ai/grok-imagine-video` (silent) or animate a generated
1801
+ // still with `google/veo-3.1-lite` (native audio, honours 9:16).
1802
+ label: "Alibaba Wan 2.7",
1803
+ route: OPENROUTER_ROUTE,
1804
+ billing: {
1805
+ kind: "per_second",
1806
+ // Flat $0.10/s across resolutions and modes, audio included.
1807
+ usd: { silent: 0.1, audio: 0.1 },
1808
+ minBilledSeconds: MIN_BILLED_SECONDS
1809
+ },
1810
+ inputs: [],
1811
+ optional_inputs: [{ kind: "image", mimes: OPENROUTER_IMAGE_MIMES }],
1812
+ required: ["prompt"],
1813
+ params: {
1814
+ prompt: { kind: "string" },
1815
+ negative_prompt: { kind: "string" },
1816
+ aspect_ratio: { kind: "string", enum: ["16:9"] },
1817
+ resolution: { kind: "string", enum: ["720p", "1080p"] },
1818
+ duration: { kind: "number", enum: WAN_27_DURATIONS },
1819
+ seed: { kind: "number" },
1820
+ generate_audio: { kind: "boolean" }
1821
+ }
1822
+ },
1823
+ "x-ai/grok-imagine-video-1.5": {
1824
+ // NOT a replacement for the entry above, and deliberately absent from
1825
+ // `AVATAR_VIDEO_MODELS` and `REFERENCE_TO_VIDEO_MODELS`: OpenRouter describes the
1826
+ // older Grok as "text-, image-, and reference-conditioned" and 1.5 as taking "an
1827
+ // optional starting image". Reference conditioning is the whole reason Grok carries
1828
+ // avatars — it is what holds a face from the identity sheet — so swapping them
1829
+ // would quietly cost every avatar clip its likeness.
1830
+ //
1831
+ // What it adds over the older one: 1080p, and 15s rather than 10.
1832
+ label: "Grok Imagine Video 1.5",
1833
+ route: OPENROUTER_ROUTE,
1834
+ billing: {
1835
+ kind: "per_second",
1836
+ // `cents_per_video_output_second_*`: 8c, 14c and 25c. No audio, so both
1837
+ // columns are the same rate rather than one being wrong.
1838
+ usd: {
1839
+ silent: 0.14,
1840
+ audio: 0.14,
1841
+ byResolution: {
1842
+ "480p": { silent: 0.08, audio: 0.08 },
1843
+ "720p": { silent: 0.14, audio: 0.14 },
1844
+ "1080p": { silent: 0.25, audio: 0.25 }
1845
+ }
1846
+ }
1847
+ },
1848
+ inputs: [],
1849
+ optional_inputs: [{ kind: "image", mimes: OPENROUTER_IMAGE_MIMES }],
1850
+ required: ["prompt"],
1851
+ params: {
1852
+ prompt: { kind: "string" },
1853
+ aspect_ratio: { kind: "string", enum: ["16:9", "9:16", "1:1", "4:3", "3:4", "3:2", "2:3"] },
1854
+ resolution: { kind: "string", enum: ["480p", "720p", "1080p"] },
1855
+ duration: { kind: "number", enum: GROK_IMAGINE_15_DURATIONS }
1856
+ }
1857
+ },
1858
+ "alibaba/wan-3.0": {
1859
+ // 2.7's successor on every axis that matters: 2–30s against 2–10, 1080p and 480p
1860
+ // as well as 720p, and it keeps the native audio that made 2.7 the landscape
1861
+ // talking-head option.
1862
+ //
1863
+ // The ratios are what it ADVERTISES. 2.7 advertised five and delivered 16:9 for
1864
+ // all of them — measured, twice, which is why its enum here is a single value. That
1865
+ // was a different model and this one is not gated on its predecessor's lie, but
1866
+ // the first vertical clip anyone renders here is worth looking at before a campaign
1867
+ // is built on it.
1868
+ //
1869
+ // No `last_frame`: 2.7 takes one and 3.0 does not, so a canvas that ends a shot on
1870
+ // a chosen frame stays on 2.7.
1871
+ label: "Alibaba Wan 3.0",
1872
+ route: OPENROUTER_ROUTE,
1873
+ billing: {
1874
+ kind: "per_second",
1875
+ // Priced per resolution where 2.7 was flat, and the rate still includes
1876
+ // audio: there is no separate audio SKU. `duration_seconds_480p|720p|1080p`.
1877
+ usd: {
1878
+ silent: 0.1,
1879
+ audio: 0.1,
1880
+ byResolution: {
1881
+ "480p": { silent: 0.05, audio: 0.05 },
1882
+ "720p": { silent: 0.1, audio: 0.1 },
1883
+ "1080p": { silent: 0.2, audio: 0.2 }
1884
+ }
1885
+ }
1886
+ },
1887
+ inputs: [],
1888
+ optional_inputs: [{ kind: "image", mimes: OPENROUTER_IMAGE_MIMES }],
1889
+ required: ["prompt"],
1890
+ params: {
1891
+ prompt: { kind: "string" },
1892
+ aspect_ratio: { kind: "string", enum: ["16:9", "9:16", "1:1", "4:3", "3:4"] },
1893
+ resolution: { kind: "string", enum: ["480p", "720p", "1080p"] },
1894
+ duration: { kind: "number", enum: WAN_30_DURATIONS },
1895
+ seed: { kind: "number" },
1896
+ generate_audio: { kind: "boolean" }
1897
+ }
1898
+ },
1899
+ "runway/gen-4.5": {
1900
+ // One resolution, two shapes, and silent — `generate_audio: false` in its listing,
1901
+ // so a talking head belongs on Wan or Omni. First frame only, no reference.
1902
+ label: "Runway Gen-4.5",
1903
+ route: OPENROUTER_ROUTE,
1904
+ billing: {
1905
+ kind: "per_second",
1906
+ // One flat rate, one resolution: `cents_per_second_output: 12`. Silent.
1907
+ usd: { silent: 0.12, audio: 0.12 }
1908
+ },
1909
+ inputs: [],
1910
+ optional_inputs: [{ kind: "image", mimes: OPENROUTER_IMAGE_MIMES }],
1911
+ required: ["prompt"],
1912
+ params: {
1913
+ prompt: { kind: "string" },
1914
+ aspect_ratio: { kind: "string", enum: ["16:9", "9:16"] },
1915
+ resolution: { kind: "string", enum: ["720p"] },
1916
+ duration: { kind: "number", enum: RUNWAY_45_DURATIONS },
1917
+ seed: { kind: "number" }
1918
+ }
1919
+ },
1920
+ "alibaba/happyhorse-1.1": {
1921
+ // Third reference-capable option: strong identity, correct ratios, no audio.
1922
+ // First-frame only (no `last_frame`), so it cannot close a beat on a
1923
+ // specified end pose the way Wan and Veo can.
1924
+ label: "Alibaba HappyHorse 1.1",
1925
+ route: OPENROUTER_ROUTE,
1926
+ billing: {
1927
+ kind: "per_second",
1928
+ usd: { silent: 0.1278, audio: 0.1278, byResolution: { "720p": { silent: 0.0988, audio: 0.0988 } } },
1929
+ minBilledSeconds: MIN_BILLED_SECONDS
1930
+ },
1931
+ inputs: [],
1932
+ optional_inputs: [{ kind: "image", mimes: OPENROUTER_IMAGE_MIMES }],
1933
+ required: ["prompt"],
1934
+ params: {
1935
+ prompt: { kind: "string" },
1936
+ aspect_ratio: { kind: "string", enum: ["16:9", "9:16", "1:1", "4:3", "3:4", "21:9", "9:21"] },
1937
+ resolution: { kind: "string", enum: ["720p", "1080p"] },
1938
+ duration: { kind: "number", enum: HAPPYHORSE_DURATIONS },
1939
+ seed: { kind: "number" }
1940
+ }
1941
+ },
1942
+ "google/veo-3.1-lite": {
1943
+ // The cheapest way to animate a still that carries a real face: same Veo
1944
+ // family and the same escape from ByteDance's filter, at $0.05/s with audio
1945
+ // at 720p against Veo 3.1's $0.40. That 8x is the difference between an
1946
+ // avatar clip you iterate on and one you think twice about.
1947
+ label: "Google Veo 3.1 Lite",
1948
+ route: OPENROUTER_ROUTE,
1949
+ billing: {
1950
+ kind: "per_second",
1951
+ usd: { silent: 0.05, audio: 0.08, byResolution: { "720p": { silent: 0.03, audio: 0.05 } } }
1952
+ },
1953
+ inputs: [],
1954
+ optional_inputs: [{ kind: "image", mimes: OPENROUTER_IMAGE_MIMES }],
1955
+ required: ["prompt"],
1956
+ params: {
1957
+ prompt: { kind: "string" },
1958
+ negative_prompt: { kind: "string" },
1959
+ aspect_ratio: { kind: "string", enum: ["16:9", "9:16"] },
1960
+ resolution: { kind: "string", enum: ["720p", "1080p"] },
1961
+ duration: { kind: "number", enum: [4, 6, 8] },
1962
+ seed: { kind: "number" },
1963
+ generate_audio: { kind: "boolean" },
1964
+ person_generation: { kind: "string", enum: ["allow_all", "allow_adult"] },
1965
+ enhance_prompt: { kind: "boolean" },
1966
+ conditioning_scale: { kind: "number" }
1967
+ }
1968
+ },
1969
+ "google/veo-3.1-fast": {
1970
+ // Cheap test/iteration model. Forwarded by the backend via
1971
+ // `provider.options.google-vertex.parameters` (camelCased on the wire).
1972
+ label: "Google Veo 3.1 Fast",
1973
+ route: OPENROUTER_ROUTE,
1974
+ billing: {
1975
+ kind: "per_second",
1976
+ usd: {
1977
+ silent: 0.1,
1978
+ audio: 0.12,
1979
+ byResolution: { "720p": { silent: 0.08, audio: 0.1 }, "4K": { silent: 0.25, audio: 0.3 } }
1980
+ }
1981
+ },
1982
+ inputs: [],
1983
+ optional_inputs: [{ kind: "image", mimes: OPENROUTER_IMAGE_MIMES }],
1984
+ required: ["prompt"],
1985
+ params: {
1986
+ prompt: { kind: "string" },
1987
+ negative_prompt: { kind: "string" },
1988
+ aspect_ratio: { kind: "string", enum: ["16:9", "9:16"] },
1989
+ resolution: { kind: "string", enum: ["720p", "1080p", "4K"] },
1990
+ duration: { kind: "number", enum: [4, 6, 8] },
1991
+ seed: { kind: "number", integer: true, min: 0, max: VEO_SEED_MAX },
1992
+ generate_audio: { kind: "boolean" },
1993
+ // Image-to-video and EU/UK/CH/MENA regions cap this at `allow_adult`;
1994
+ // `allow_all` is text-to-video only. Allow both so an image-conditioned
1995
+ // Veo clip (the real-face fallback) validates.
1996
+ person_generation: { kind: "string", enum: ["allow_all", "allow_adult"] },
1997
+ enhance_prompt: { kind: "boolean" },
1998
+ conditioning_scale: { kind: "number" }
1999
+ }
2000
+ }
2001
+ },
2002
+ video_deconstruct: {
2003
+ // Replication-grade video extraction — the forensic system prompts live on
2004
+ // the backend; `focus` appends emphasis only. Frames ride on a throwaway
2005
+ // Mux asset; analysis runs on Gemini with the video as a file part.
2006
+ "~google/gemini-flash-latest": {
2007
+ label: "Google Gemini Flash (latest, Video)",
2008
+ route: OPENROUTER_ROUTE,
2009
+ billing: USAGE_BILLED,
2010
+ inputs: [{ kind: "video", mimes: DECONSTRUCT_VIDEO_MIMES }],
2011
+ required: [],
2012
+ params: {
2013
+ mode: { kind: "string", enum: ["full", "index"] },
2014
+ language: { kind: "string" },
2015
+ max_scenes: { kind: "number", min: 1, max: 60 },
2016
+ focus: { kind: "string" },
2017
+ start_s: { kind: "number", min: 0 },
2018
+ end_s: { kind: "number", min: 0 },
2019
+ max_clip_s: { kind: "number", min: 1, max: 60 },
2020
+ transcriber: { kind: "string", enum: ["groq", "deepgram"] },
2021
+ // Real visual shot-cut timestamps (seconds) from local PySceneDetect;
2022
+ // scene boundaries snap onto them so frames never straddle a hard cut.
2023
+ // Shape (number[]) is enforced by the node + backend Zod schemas.
2024
+ shot_cuts: { kind: "json" }
2025
+ }
2026
+ },
2027
+ "~google/gemini-pro-latest": {
2028
+ label: "Google Gemini Pro (latest, Video)",
2029
+ route: OPENROUTER_ROUTE,
2030
+ billing: USAGE_BILLED,
2031
+ inputs: [{ kind: "video", mimes: DECONSTRUCT_VIDEO_MIMES }],
2032
+ required: [],
2033
+ params: {
2034
+ mode: { kind: "string", enum: ["full", "index"] },
2035
+ language: { kind: "string" },
2036
+ max_scenes: { kind: "number", min: 1, max: 60 },
2037
+ focus: { kind: "string" },
2038
+ start_s: { kind: "number", min: 0 },
2039
+ end_s: { kind: "number", min: 0 },
2040
+ max_clip_s: { kind: "number", min: 1, max: 60 },
2041
+ transcriber: { kind: "string", enum: ["groq", "deepgram"] },
2042
+ // See gemini-flash-latest above — local PySceneDetect shot-cut timestamps.
2043
+ shot_cuts: { kind: "json" }
2044
+ }
2045
+ }
2046
+ },
2047
+ video_lipsync: {
2048
+ // Formerly `fal/veed-lipsync`, which named a provider and a model it had stopped
2049
+ // running on; that id stays accepted through `MODEL_ALIASES`.
2050
+ "replicate/sync-lipsync-2": {
2051
+ label: "Sync Labs Lipsync 2 (Replicate)",
2052
+ route: { provider: "replicate", wireModel: "sync/lipsync-2" },
2053
+ billing: { kind: "formula", formula: "lipsync-minutes" },
2054
+ inputs: [
2055
+ { kind: "video", mimes: REPLICATE_VIDEO_MIMES },
2056
+ { kind: "audio", mimes: REPLICATE_AUDIO_MIMES }
2057
+ ],
2058
+ required: [],
2059
+ params: {}
2060
+ }
2061
+ },
2062
+ tts: {
2063
+ "elevenlabs/eleven_v3": {
2064
+ // eleven_v3 does NOT yet support context stitching
2065
+ // (previous_text/next_text/*_request_ids). ElevenLabs returns a clean
2066
+ // `unsupported_model` 400 if you pass them.
2067
+ label: "ElevenLabs Eleven v3",
2068
+ route: { provider: "elevenlabs", wireModel: "eleven_v3" },
2069
+ billing: { kind: "formula", formula: "elevenlabs-characters" },
2070
+ inputs: [],
2071
+ required: ["text", "voice"],
2072
+ params: {
2073
+ text: { kind: "string", maxLength: ELEVENLABS_MAX_TEXT_CHARS },
2074
+ voice: { kind: "string" },
2075
+ language_code: { kind: "string" },
2076
+ stability: { kind: "number", min: 0, max: 1 },
2077
+ similarity_boost: { kind: "number", min: 0, max: 1 },
2078
+ voice_settings: { kind: "json" },
2079
+ seed: { kind: "number", min: 0, max: 4294967295 },
2080
+ pronunciation_dictionary_locators: { kind: "json" },
2081
+ apply_text_normalization: { kind: "string", enum: ["auto", "on", "off"] },
2082
+ apply_language_text_normalization: { kind: "boolean" },
2083
+ with_timestamps: { kind: "boolean" },
2084
+ output_format: { kind: "string", enum: ELEVENLABS_OUTPUT_FORMATS }
2085
+ }
2086
+ }
2087
+ },
2088
+ audio_voice_convert: {
2089
+ "elevenlabs/eleven_multilingual_sts_v2": {
2090
+ // Speech-to-speech / Voice Changer: re-voice an existing audio clip in the
2091
+ // TARGET voice, preserving timing/prosody. Used to normalize a talking-head
2092
+ // clip's native (generator-chosen) voice into ONE consistent brand voice.
2093
+ label: "ElevenLabs Voice Changer (multilingual STS v2)",
2094
+ route: { provider: "elevenlabs", wireModel: "eleven_multilingual_sts_v2" },
2095
+ billing: { kind: "formula", formula: "elevenlabs-voice-convert-minutes" },
2096
+ inputs: [{ kind: "audio", mimes: REPLICATE_AUDIO_MIMES }],
2097
+ required: ["voice"],
2098
+ params: {
2099
+ voice: { kind: "string" },
2100
+ output_format: { kind: "string", enum: ELEVENLABS_OUTPUT_FORMATS },
2101
+ remove_background_noise: { kind: "boolean" }
2102
+ }
2103
+ }
2104
+ },
2105
+ music: {
2106
+ "elevenlabs/music-v1": {
2107
+ label: "ElevenLabs Music v1 (Compose)",
2108
+ route: { provider: "elevenlabs", wireModel: ELEVENLABS_MUSIC_ENGINE },
2109
+ billing: { kind: "formula", formula: "elevenlabs-music-seconds" },
2110
+ inputs: [],
2111
+ required: [],
2112
+ params: {
2113
+ prompt: { kind: "string" },
2114
+ composition_plan: { kind: "json" },
2115
+ music_length_ms: { kind: "number", min: 3e3, max: ELEVENLABS_MAX_MUSIC_LENGTH_MS },
2116
+ seed: { kind: "number" },
2117
+ force_instrumental: { kind: "boolean" },
2118
+ respect_sections_durations: { kind: "boolean" },
2119
+ with_timestamps: { kind: "boolean" },
2120
+ output_format: { kind: "string", enum: ELEVENLABS_OUTPUT_FORMATS }
2121
+ }
2122
+ },
2123
+ "elevenlabs/video-background-music-v1": {
2124
+ label: "ElevenLabs Video Background Music v1",
2125
+ route: { provider: "elevenlabs", wireModel: ELEVENLABS_MUSIC_ENGINE },
2126
+ billing: { kind: "formula", formula: "elevenlabs-music-seconds" },
2127
+ inputs: [{ kind: "video", mimes: REPLICATE_VIDEO_MIMES }],
2128
+ required: [],
2129
+ params: {
2130
+ description: { kind: "string" },
2131
+ tags: { kind: "json" },
2132
+ output_format: { kind: "string", enum: ELEVENLABS_OUTPUT_FORMATS }
2133
+ }
2134
+ }
2135
+ },
2136
+ dialogue: {
2137
+ "elevenlabs/eleven_v3": {
2138
+ label: "ElevenLabs Eleven v3 (Dialogue)",
2139
+ route: { provider: "elevenlabs", wireModel: "eleven_v3" },
2140
+ billing: { kind: "formula", formula: "elevenlabs-characters" },
2141
+ inputs: [],
2142
+ required: ["inputs"],
2143
+ params: {
2144
+ inputs: { kind: "json" },
2145
+ language_code: { kind: "string" },
2146
+ settings: { kind: "json" },
2147
+ seed: { kind: "number", min: 0, max: 4294967295 },
2148
+ apply_text_normalization: { kind: "string", enum: ["auto", "on", "off"] },
2149
+ with_timestamps: { kind: "boolean" },
2150
+ output_format: { kind: "string", enum: ELEVENLABS_OUTPUT_FORMATS }
2151
+ }
2152
+ }
2153
+ },
2154
+ sound_effect: {
2155
+ "elevenlabs/eleven_text_to_sound_v2": {
2156
+ label: "ElevenLabs Text-to-Sound v2",
2157
+ route: { provider: "elevenlabs", wireModel: "eleven_text_to_sound_v2" },
2158
+ billing: { kind: "formula", formula: "elevenlabs-sound-effect-seconds" },
2159
+ inputs: [],
2160
+ required: ["text"],
2161
+ params: {
2162
+ text: { kind: "string" },
2163
+ duration_seconds: { kind: "number", min: 0.5, max: 30 },
2164
+ prompt_influence: { kind: "number", min: 0, max: 1 },
2165
+ loop: { kind: "boolean" },
2166
+ output_format: { kind: "string", enum: ELEVENLABS_OUTPUT_FORMATS }
2167
+ }
2168
+ }
2169
+ }
2170
+ };
2171
+ var MODEL_ALIASES = {
2172
+ "fal/veed-lipsync": "replicate/sync-lipsync-2",
2173
+ "fal/veed-video-background-removal": "replicate/birefnet-video",
2174
+ "fal/birefnet-v2": "replicate/birefnet",
2175
+ "google/gemini-3.1-flash-image-preview": "google/gemini-3.1-flash-image",
2176
+ "google/gemini-3-pro-image-preview": "google/gemini-3-pro-image",
2177
+ "openai/gpt-5.4-image-2": "openai/gpt-image-2.5-sunburst"
2178
+ };
2179
+ function canonicalModelId(model) {
2180
+ return Object.keys(MODEL_ALIASES).includes(model) ? MODEL_ALIASES[model] : model;
2181
+ }
2182
+ function modelIdsAccepted(canonical) {
2183
+ return [canonical, ...Object.keys(MODEL_ALIASES).filter((legacy) => MODEL_ALIASES[legacy] === canonical)];
2184
+ }
2185
+ function modelSpec(kind, model) {
2186
+ return MODEL_REGISTRY[kind]?.[canonicalModelId(model)];
2187
+ }
2188
+ var NARROWED_ALIASES = ["openai/gpt-5.4-image-2"];
2189
+ function canonicalModelParams(kind, params) {
2190
+ const model = params.model;
2191
+ if (typeof model !== "string" || canonicalModelId(model) === model) return params;
2192
+ const successor = canonicalModelId(model);
2193
+ if (!NARROWED_ALIASES.includes(model)) return { ...params, model: successor };
2194
+ const fitted = { ...params, model: successor };
2195
+ if (typeof fitted.aspect_ratio === "string") {
2196
+ fitted.aspect_ratio = nearestSupportedAspectRatio(kind, successor, fitted.aspect_ratio);
2197
+ }
2198
+ if (typeof fitted.image_size === "string") {
2199
+ fitted.image_size = supportsParam(kind, successor, "image_size") ? nearestSupportedImageSize(kind, successor, fitted.image_size) : void 0;
2200
+ }
2201
+ if (typeof fitted.quality === "string") {
2202
+ fitted.quality = bestSupportedQuality(kind, successor, fitted.quality);
2203
+ }
2204
+ return Object.fromEntries(Object.entries(fitted).filter(([, value]) => value !== void 0));
2205
+ }
2206
+ function perSecondBilling(model) {
2207
+ const billing = MODEL_REGISTRY.video_generate[model]?.billing;
2208
+ return billing?.kind === "per_second" ? billing : void 0;
2209
+ }
2210
+ var MODEL_ROLES = {
2211
+ /** Ad frames and static-ad plates: the most faithful text and identity reproduction. */
2212
+ adImage: { kind: "image_generate", model: "openai/gpt-image-2.5-sunburst" },
2213
+ /**
2214
+ * The multi-view reference sheet a recurring element is fused on. Gemini 3 Pro makes
2215
+ * the cleanest, best-labelled turnaround, worth it for the ONE reference every frame
2216
+ * of an ad grounds on.
2217
+ */
2218
+ referenceSheet: { kind: "image_reference_sheet", model: "google/gemini-3-pro-image" },
2219
+ /** Re-framing a static ad whose copy is baked into the pixels. */
2220
+ aspectAdapt: { kind: "image_aspect_adapt", model: "google/gemini-3-pro-image" },
2221
+ /**
2222
+ * The judge comparing candidate plates. Flash, not Pro: Pro measured 5 credits for
2223
+ * one pick, a tenth of the render it judges.
2224
+ */
2225
+ plateJudge: { kind: "image_select", model: "~google/gemini-flash-latest" },
2226
+ /**
2227
+ * The static-ad blueprint extraction, and the fit of a reference to a company (`winning-ads fit`).
2228
+ * Flash, not Pro: measured on 16 proven ads (dev, Oct 2026), Flash read as well, answered 11 describes
2229
+ * of 12 (Pro 8: its preview model stopped answers part-way) and 16 fits of 16 (Pro 15), at under half
2230
+ * the describe's cost and a fifth of the fit's; the fit kept or rejected the same ads 14 times of 15.
2231
+ * A describe takes ~10 s longer (40 s), a fit ~12 s less (10 s).
2232
+ */
2233
+ adDescribe: { kind: "image_describe", model: "~google/gemini-flash-latest" },
2234
+ /** The element-selection and layout passes over a blueprint. */
2235
+ blueprintAnalysis: { kind: "text_generate", model: "~google/gemini-flash-latest" },
2236
+ /**
2237
+ * The viewer an ad reaches, played before a static ad renders (`baker canvas viewer-check`):
2238
+ * says from the copy and the scene what is offered, to whom, and what to do next. Text
2239
+ * only and asked once per ad and viewer, so Flash; the calibration set (E8) decides.
2240
+ */
2241
+ viewerCheck: { kind: "text_generate", model: "~google/gemini-flash-latest" },
2242
+ /**
2243
+ * Picks the customer truths out of reviews, testimonials and threads (`baker research
2244
+ * customers`): returns exact spans the code then checks against the source. Text only and
2245
+ * one call per batch, so Flash.
2246
+ */
2247
+ customerInsights: { kind: "text_generate", model: "~google/gemini-flash-latest" },
2248
+ /**
2249
+ * The same viewer shown the FINISHED static ad at phone size for about three seconds, with no
2250
+ * brand and no brief: what is sold, whether it is for them, what to do next, what stopped them
2251
+ * (`glance-check.ts`). One small picture per run, so Flash.
2252
+ */
2253
+ glanceCheck: { kind: "image_describe", model: "~google/gemini-flash-latest" },
2254
+ /**
2255
+ * Reads every line of text and the logo of a finished static ad WITH its box, for the
2256
+ * copy and safe-area checks. Bench E10 (2026-09-30): word F1 0.994, box IoU 0.937, 4.3 s,
2257
+ * about $0.005 an image on `google/gemini-3.8-flash`, which this alias resolves to;
2258
+ * tesseract and PaddleOCR missed the 0.95 F1 gate.
2259
+ */
2260
+ textBoxReader: { kind: "image_describe", model: "~google/gemini-flash-latest" },
2261
+ /**
2262
+ * Reads where every person, face, animal and product sits in a static ad's picture, WITH its
2263
+ * box, so each size is cut around them and its words kept off faces. The same reader and grid
2264
+ * as `textBoxReader` (Gemini's `box_2d`), asked once per chosen picture.
2265
+ */
2266
+ subjectBoxReader: { kind: "image_describe", model: "~google/gemini-flash-latest" },
2267
+ /**
2268
+ * Compares one size of a finished static ad with its main size for what boxes cannot say: the
2269
+ * same product and people, nothing shown twice, nobody stretched, never the main picture boxed in
2270
+ * a bigger frame (`size-consistency.ts`). Flash: one small pair per drawn size; on 29 production
2271
+ * pairs asked twice it flagged none and named 4 of 4 planted defects (Oct 2026).
2272
+ */
2273
+ sizeMatch: { kind: "image_describe", model: "~google/gemini-flash-latest" },
2274
+ /**
2275
+ * Scene-by-scene video extraction. Flash: ~2-3x faster per call than Pro, which keeps
2276
+ * each per-scene step inside the action time budget.
2277
+ */
2278
+ videoDeconstruct: { kind: "video_deconstruct", model: "~google/gemini-flash-latest" },
2279
+ /** The backend `image_search` agent loop that picks search tools and queries. */
2280
+ imageSearch: { kind: "text_generate", model: "~google/gemini-flash-latest" },
2281
+ voiceover: { kind: "tts", model: "elevenlabs/eleven_v3" },
2282
+ soundEffect: { kind: "sound_effect", model: "elevenlabs/eleven_text_to_sound_v2" },
2283
+ musicBed: { kind: "music", model: "elevenlabs/music-v1" },
2284
+ /** Re-voices a talking clip's native audio into one consistent brand voice. */
2285
+ voiceConvert: { kind: "audio_voice_convert", model: "elevenlabs/eleven_multilingual_sts_v2" },
2286
+ /** The scored video router's candidates, one per job it can route to. */
2287
+ videoRouterWorkhorse: { kind: "video_generate", model: "bytedance/seedance-2.0" },
2288
+ videoRouterRealFace: { kind: "video_generate", model: "google/veo-3.1" },
2289
+ videoRouterRealFaceEconomy: { kind: "video_generate", model: "google/veo-3.1-fast" },
2290
+ videoRouterMotion: { kind: "video_generate", model: "kwaivgi/kling-v3.0-pro" },
2291
+ imageDefault: { kind: "image_generate", model: DEFAULT_IMAGE_GENERATE_MODEL },
2292
+ videoDefault: { kind: "video_generate", model: DEFAULT_VIDEO_GENERATE_MODEL },
2293
+ avatarVideo: { kind: "video_generate", model: DEFAULT_AVATAR_VIDEO_MODEL }
2294
+ };
2295
+ var AD_IMAGE_MODEL = MODEL_ROLES.adImage.model;
2296
+ var REFERENCE_SHEET_MODEL = MODEL_ROLES.referenceSheet.model;
2297
+ var ASPECT_ADAPT_MODEL = MODEL_ROLES.aspectAdapt.model;
2298
+ var PLATE_JUDGE_MODEL = MODEL_ROLES.plateJudge.model;
2299
+ var AD_DESCRIBE_MODEL = MODEL_ROLES.adDescribe.model;
2300
+ var BLUEPRINT_ANALYSIS_MODEL = MODEL_ROLES.blueprintAnalysis.model;
2301
+ var VIEWER_CHECK_MODEL = MODEL_ROLES.viewerCheck.model;
2302
+ var CUSTOMER_INSIGHTS_MODEL = MODEL_ROLES.customerInsights.model;
2303
+ var GLANCE_CHECK_MODEL = MODEL_ROLES.glanceCheck.model;
2304
+ var TEXT_BOX_READER_MODEL = MODEL_ROLES.textBoxReader.model;
2305
+ var SUBJECT_BOX_READER_MODEL = MODEL_ROLES.subjectBoxReader.model;
2306
+ var SIZE_MATCH_MODEL = MODEL_ROLES.sizeMatch.model;
2307
+ var VIDEO_DECONSTRUCT_MODEL = MODEL_ROLES.videoDeconstruct.model;
2308
+ var IMAGE_SEARCH_MODEL = MODEL_ROLES.imageSearch.model;
2309
+ var VOICEOVER_MODEL = MODEL_ROLES.voiceover.model;
2310
+ var SOUND_EFFECT_MODEL = MODEL_ROLES.soundEffect.model;
2311
+ var MUSIC_BED_MODEL = MODEL_ROLES.musicBed.model;
2312
+ var VOICE_CONVERT_MODEL = MODEL_ROLES.voiceConvert.model;
2313
+ function isRegisteredModel(kind, model) {
2314
+ return MODEL_REGISTRY[kind]?.[canonicalModelId(model)] !== void 0;
2315
+ }
2316
+ function imageGenerateAspectRatios() {
2317
+ const seen = /* @__PURE__ */ new Set();
2318
+ for (const model of IMAGE_GENERATE_MODELS) {
2319
+ for (const ratio of supportedAspectRatios("image_generate", model) ?? []) seen.add(ratio);
2320
+ }
2321
+ return [...seen];
2322
+ }
2323
+ function supportsParam(kind, model, param) {
2324
+ return modelSpec(kind, model)?.params[param] !== void 0;
2325
+ }
2326
+ var DEFAULT_CLIP_DURATION_S = 5;
2327
+ var SPOKEN_WORDS_PER_SECOND = 2.5;
2328
+ var SPOKEN_LINE = new RegExp(`(?<![\\p{L}\\p{N}])['"\\u201c\\u201d\\u2018\\u2019]((?:[^'"\\u201c\\u201d\\u2018\\u2019]|(?<=\\p{L})['\\u2019](?=\\p{L})){8,})['"\\u201c\\u201d\\u2018\\u2019](?![\\p{L}\\p{N}])`, "gu");
2329
+ function spokenWordsIn(prompt) {
2330
+ if (!prompt) return 0;
2331
+ const quoted = [...prompt.matchAll(SPOKEN_LINE)].map((m) => m[1] ?? "");
2332
+ const text = quoted.join(" ").trim();
2333
+ return text ? text.split(/\s+/).filter(Boolean).length : 0;
2334
+ }
2335
+ var SPOKEN_CLIP_DURATION_S = 8;
2336
+ function nearestClipDuration(model, preferred) {
2337
+ const schema = MODEL_REGISTRY.video_generate[model]?.params.duration;
2338
+ const allowed = schema?.kind === "number" ? schema.enum : void 0;
2339
+ if (!allowed?.length || allowed.includes(preferred)) return preferred;
2340
+ return [...allowed].sort((a, b) => Math.abs(a - preferred) - Math.abs(b - preferred) || a - b)[0];
2341
+ }
2342
+ var SILENT_VIDEO_MODELS = /* @__PURE__ */ new Set([
2343
+ "runway/gen-4.5",
2344
+ "x-ai/grok-imagine-video",
2345
+ "x-ai/grok-imagine-video-1.5",
2346
+ "alibaba/happyhorse-1.1"
2347
+ ]);
2348
+ function clipAudioMode(model) {
2349
+ if (supportsParam("video_generate", model, "generate_audio")) return "toggle";
2350
+ return SILENT_VIDEO_MODELS.has(model) ? "never" : "always";
2351
+ }
2352
+ function clipDurationsFor(model) {
2353
+ const schema = MODEL_REGISTRY.video_generate[model]?.params.duration;
2354
+ const allowed = schema?.kind === "number" ? schema.enum : void 0;
2355
+ return allowed?.length ? [...allowed].sort((a, b) => a - b) : void 0;
2356
+ }
2357
+ function maxClipSeconds(model) {
2358
+ const allowed = clipDurationsFor(model);
2359
+ return allowed ? allowed[allowed.length - 1] : void 0;
2360
+ }
2361
+ function splitScriptFor(words, model) {
2362
+ const maxSeconds = maxClipSeconds(model);
2363
+ if (!maxSeconds) return null;
2364
+ const perClip = Math.floor(maxSeconds * SPOKEN_WORDS_PER_SECOND);
2365
+ if (words <= perClip) return null;
2366
+ const clips = Math.ceil(words / perClip);
2367
+ return { clips, wordsPerClip: Math.ceil(words / clips), maxSeconds };
2368
+ }
2369
+ function promptMaxLength(kind, model) {
2370
+ const schema = modelSpec(kind, model)?.params.prompt;
2371
+ return schema?.kind === "string" ? schema.maxLength : void 0;
2372
+ }
2373
+ function inputSlot(kind, model, inputKind) {
2374
+ const spec = modelSpec(kind, model);
2375
+ return spec?.optional_inputs?.find((input) => input.kind === inputKind) ?? spec?.inputs.find((input) => input.kind === inputKind);
2376
+ }
2377
+ function maxInputSlot(kind, model, inputKind) {
2378
+ return inputSlot(kind, model, inputKind)?.max;
2379
+ }
2380
+ function maxInputReferences(kind, model) {
2381
+ return maxInputSlot(kind, model, "image");
2382
+ }
2383
+ function supportedQualities(kind, model) {
2384
+ const schema = modelSpec(kind, model)?.params.quality;
2385
+ return schema?.kind === "string" ? schema.enum : void 0;
2386
+ }
2387
+ function bestSupportedQuality(kind, model, want) {
2388
+ const supported = supportedQualities(kind, model);
2389
+ if (!supported) return void 0;
2390
+ if (supported.includes(want)) return want;
2391
+ const ladder = supported.filter((step) => step !== "auto");
2392
+ const ceiling = ladder.indexOf(want);
2393
+ const reachable = ceiling === -1 ? ladder : ladder.slice(0, ceiling);
2394
+ return reachable[reachable.length - 1];
2395
+ }
2396
+ function supportedAspectRatios(kind, model) {
2397
+ const schema = modelSpec(kind, model)?.params.aspect_ratio;
2398
+ return schema?.kind === "string" ? schema.enum : void 0;
2399
+ }
2400
+ function ratioValue(ratio) {
2401
+ const [w, h] = ratio.split(":").map(Number);
2402
+ if (!w || !h || !Number.isFinite(w) || !Number.isFinite(h)) return null;
2403
+ return w / h;
2404
+ }
2405
+ function nearestSupportedAspectRatio(kind, model, target) {
2406
+ const supported = supportedAspectRatios(kind, model);
2407
+ if (!supported || supported.includes(target)) return target;
2408
+ const wanted = ratioValue(target);
2409
+ if (wanted === null) return target;
2410
+ let best = target;
2411
+ let bestDistance = Number.POSITIVE_INFINITY;
2412
+ for (const candidate of supported) {
2413
+ const value = ratioValue(candidate);
2414
+ if (value === null) continue;
2415
+ const distance = Math.abs(Math.log(value / wanted));
2416
+ if (distance < bestDistance) {
2417
+ bestDistance = distance;
2418
+ best = candidate;
2419
+ }
2420
+ }
2421
+ return best;
2422
+ }
2423
+ function supportedImageSizes(kind, model) {
2424
+ const schema = modelSpec(kind, model)?.params.image_size;
2425
+ return schema?.kind === "string" ? schema.enum : void 0;
2426
+ }
2427
+ var IMAGE_SIZE_ORDER = ["0.5K", "1K", "2K", "4K"];
2428
+ function nearestSupportedImageSize(kind, model, target) {
2429
+ const supported = supportedImageSizes(kind, model);
2430
+ if (!supported || supported.includes(target)) return target;
2431
+ const wanted = IMAGE_SIZE_ORDER.indexOf(target);
2432
+ if (wanted < 0) return target;
2433
+ const ranked = supported.filter((s) => IMAGE_SIZE_ORDER.includes(s)).sort((a, b) => IMAGE_SIZE_ORDER.indexOf(a) - IMAGE_SIZE_ORDER.indexOf(b));
2434
+ if (ranked.length === 0) return target;
2435
+ const belowOrEqual = ranked.filter((s) => IMAGE_SIZE_ORDER.indexOf(s) <= wanted);
2436
+ return belowOrEqual.length > 0 ? belowOrEqual[belowOrEqual.length - 1] : ranked[0];
2437
+ }
2438
+
2439
+ // ../canvas-contract/src/credits.ts
2440
+ var CREDITS_PER_USD = 100;
2441
+ function usdToCredits(usd) {
2442
+ if (!(usd > 0)) return 0;
2443
+ return Math.ceil(Number((usd * CREDITS_PER_USD).toFixed(6)));
2444
+ }
2445
+
2446
+ // ../canvas-contract/src/videoCost.ts
2447
+ var OPENING_FRAME_CREDITS = usdToCredits(0.03);
2448
+ var SEEDANCE_USD_PER_SECOND = {
2449
+ "480p": 0.18,
2450
+ "720p": 0.5,
2451
+ "1080p": 0.62,
2452
+ "4k": 0.62
2453
+ };
2454
+ var DEFAULT_VIDEO_RESOLUTION = "720p";
2455
+ var DEFAULT_VIDEO_DURATION_S = 5;
2456
+ function isSeedanceModel(model) {
2457
+ return model.startsWith("bytedance/seedance");
2458
+ }
2459
+ var SEEDANCE_25_USD_PER_SECOND = {
2460
+ "480p": 0.1075,
2461
+ "720p": 0.2326
2462
+ };
2463
+ var SEEDANCE_25_FALLBACK_USD_PER_SECOND = 0.2326;
2464
+ function seedance25UsdPerSecond(resolution) {
2465
+ return SEEDANCE_25_USD_PER_SECOND[resolution ?? DEFAULT_VIDEO_RESOLUTION] ?? SEEDANCE_25_FALLBACK_USD_PER_SECOND;
2466
+ }
2467
+ var FALLBACK_USD_PER_SECOND = 0.5;
2468
+ function billedSeconds(model, duration) {
2469
+ const floor = perSecondBilling(model)?.minBilledSeconds;
2470
+ return floor === void 0 ? duration : Math.max(duration, floor);
2471
+ }
2472
+ function seedanceUsdPerSecond(resolution) {
2473
+ return SEEDANCE_USD_PER_SECOND[resolution ?? DEFAULT_VIDEO_RESOLUTION] ?? FALLBACK_USD_PER_SECOND;
2474
+ }
2475
+ var GEMINI_OMNI_USD_PER_1M_VIDEO_TOKENS = 17.5;
2476
+ var GEMINI_OMNI_VIDEO_TOKENS_PER_SECOND = 5792;
2477
+ var GEMINI_OMNI_RESOLUTION_MULTIPLIER = {
2478
+ "360p": 1 / 3,
2479
+ "720p": 1,
2480
+ "1080p": 1.5,
2481
+ "4k": 3
2482
+ };
2483
+ var GEMINI_OMNI_DEFAULT_RESOLUTION = "720p";
2484
+ var GEMINI_OMNI_OVERHEAD_TOKENS = 600;
2485
+ var GEMINI_OMNI_WINDOW_SECONDS = 10;
2486
+ var GEMINI_OMNI_USD_PER_SECOND = GEMINI_OMNI_VIDEO_TOKENS_PER_SECOND * GEMINI_OMNI_USD_PER_1M_VIDEO_TOKENS / 1e6;
2487
+ function geminiOmniUsdPerSecond(resolution) {
2488
+ const multiplier = GEMINI_OMNI_RESOLUTION_MULTIPLIER[resolution ?? GEMINI_OMNI_DEFAULT_RESOLUTION] ?? 1;
2489
+ return GEMINI_OMNI_USD_PER_SECOND * multiplier;
2490
+ }
2491
+ var VIDEO_SOURCE_COST_MULTIPLIER = 2.5;
2492
+ var FAL_SEEDANCE_USD_PER_1K_TOKENS = 0.0214;
2493
+ var SEEDANCE_SOURCE_CLIP_DISCOUNT = 0.6;
2494
+ var SEEDANCE_DEAREST_FRAME = {
2495
+ "480p": { width: 992, height: 432 },
2496
+ "720p": { width: 1112, height: 834 }
2497
+ };
2498
+ function falSeedanceUsdPerSecond(resolution, buildsOnSourceClip = false) {
2499
+ const frame = SEEDANCE_DEAREST_FRAME[resolution ?? DEFAULT_VIDEO_RESOLUTION] ?? SEEDANCE_DEAREST_FRAME["720p"];
2500
+ const tokensPerSecond = (frame?.width ?? 1112) * (frame?.height ?? 834) * 24 / 1024;
2501
+ const rate = tokensPerSecond * FAL_SEEDANCE_USD_PER_1K_TOKENS / 1e3;
2502
+ return buildsOnSourceClip ? rate * SEEDANCE_SOURCE_CLIP_DISCOUNT : rate;
2503
+ }
2504
+ function geminiOmniCostUsd(model, duration, resolution) {
2505
+ const tier = isGeminiOmniPreviewModel(model) ? GEMINI_OMNI_DEFAULT_RESOLUTION : resolution;
2506
+ const footage = geminiOmniUsdPerSecond(tier) * (duration ?? GEMINI_OMNI_WINDOW_SECONDS);
2507
+ return footage + GEMINI_OMNI_OVERHEAD_TOKENS * GEMINI_OMNI_USD_PER_1M_VIDEO_TOKENS / 1e6;
2508
+ }
2509
+ function seedance20CostUsd(resolution, seconds, mayRouteToFal) {
2510
+ const viaReplicate = seedanceUsdPerSecond(resolution) * seconds;
2511
+ if (!mayRouteToFal) return viaReplicate;
2512
+ const falTier = resolution === "480p" || resolution === "720p" ? resolution : void 0;
2513
+ return Math.max(viaReplicate, falSeedanceUsdPerSecond(falTier) * seconds);
2514
+ }
2515
+ function estimateVideoCostUsd(input) {
2516
+ const { model, duration, resolution, generateAudio, buildsOnSourceClip } = input;
2517
+ const seconds = billedSeconds(model, duration ?? DEFAULT_VIDEO_DURATION_S);
2518
+ const sourceClipPremium = buildsOnSourceClip ? VIDEO_SOURCE_COST_MULTIPLIER : 1;
2519
+ if (isGeminiOmniModel(model)) return geminiOmniCostUsd(model, duration, resolution);
2520
+ if (isSeedance25Model(model)) {
2521
+ const viaOpenRouter = seedance25UsdPerSecond(resolution) * seconds * sourceClipPremium;
2522
+ if (!input.mayRouteToFal) return viaOpenRouter;
2523
+ return Math.max(viaOpenRouter, falSeedanceUsdPerSecond(resolution, buildsOnSourceClip) * seconds);
2524
+ }
2525
+ if (isSeedanceModel(model)) return seedance20CostUsd(resolution, seconds, input.mayRouteToFal === true);
2526
+ const published = perSecondBilling(model)?.usd;
2527
+ if (published) {
2528
+ const rate = (resolution ? published.byResolution?.[resolution] : void 0) ?? published;
2529
+ return (generateAudio ? rate.audio : rate.silent) * seconds;
2530
+ }
2531
+ const dearestKnownRate = Math.max(...Object.values(SEEDANCE_USD_PER_SECOND));
2532
+ return dearestKnownRate * seconds;
2533
+ }
2534
+ function estimateVideoCredits(input) {
2535
+ return usdToCredits(estimateVideoCostUsd(input));
2536
+ }
2537
+
2538
+ // ../../node_modules/.pnpm/safe-stable-stringify@2.5.0/node_modules/safe-stable-stringify/esm/wrapper.js
2539
+ var import__ = __toESM(require_safe_stable_stringify(), 1);
2540
+ var configure = import__.default.configure;
2541
+ var wrapper_default = import__.default;
2542
+
2543
+ // ../canvas-contract/src/canonical.ts
2544
+ function canonicalize(value) {
2545
+ const normalized = normalizeForCanonical(value);
2546
+ const out = wrapper_default(normalized);
2547
+ if (out === void 0) {
2548
+ throw new Error("canonicalize: value serialized to undefined (top-level undefined?)");
2549
+ }
2550
+ return out;
2551
+ }
2552
+ function normalizeForCanonical(value) {
2553
+ if (value === null) return null;
2554
+ if (typeof value === "string") return value.normalize("NFC");
2555
+ if (typeof value === "number") {
2556
+ if (!Number.isFinite(value)) {
2557
+ throw new Error(`canonicalize: non-finite number ${value}`);
2558
+ }
2559
+ return value;
2560
+ }
2561
+ if (typeof value === "boolean") return value;
2562
+ if (typeof value === "bigint") {
2563
+ throw new Error("canonicalize: bigint not supported");
2564
+ }
2565
+ if (Array.isArray(value)) {
2566
+ return value.map(normalizeForCanonical);
2567
+ }
2568
+ if (typeof value === "object") {
2569
+ const out = {};
2570
+ for (const [k, v] of Object.entries(value)) {
2571
+ if (v === void 0) continue;
2572
+ out[k.normalize("NFC")] = normalizeForCanonical(v);
2573
+ }
2574
+ return out;
2575
+ }
2576
+ return void 0;
2577
+ }
2578
+
2579
+ // ../canvas-contract/src/clipWeight.ts
2580
+ var MB_PER_SECOND_720P = 2.13;
2581
+ var RESOLUTION_WEIGHT = {
2582
+ "360p": 0.25,
2583
+ "480p": 0.44,
2584
+ "720p": 1,
2585
+ "1080p": 2.25,
2586
+ "4k": 9,
2587
+ "4K": 9
2588
+ };
2589
+ var MAX_CLIP_INGEST_MB = 120;
2590
+ function estimateClipMb(durationSeconds, resolution) {
2591
+ const weight = RESOLUTION_WEIGHT[resolution ?? "720p"] ?? 1;
2592
+ return durationSeconds * MB_PER_SECOND_720P * weight;
2593
+ }
2594
+ function clipTooHeavyToIngest(durationSeconds, resolution) {
2595
+ if (!durationSeconds) return null;
2596
+ const mb = estimateClipMb(durationSeconds, resolution);
2597
+ if (mb <= MAX_CLIP_INGEST_MB) return null;
2598
+ const fits = Math.floor(MAX_CLIP_INGEST_MB / (estimateClipMb(1, resolution) || 1));
2599
+ return `A ${durationSeconds}s clip at ${resolution ?? "720p"} comes to roughly ${Math.round(mb)} MB, more than the ${MAX_CLIP_INGEST_MB} MB we can take in \u2014 it would render, bill, and then fail on the way into the library. Shorten it to about ${fits}s at this resolution, or drop the resolution and keep the length.`;
2600
+ }
2601
+
2602
+ // ../canvas-contract/src/frameRealism.ts
2603
+ function frameRealismDirection(opts = {}) {
2604
+ return " Everything obeys real-world physics: paper, card and screens are OPAQUE with nothing showing through from behind, every object is at believable real-world scale next to the people handling it, and every object has its real-world form and construction \u2014 a phone has ONE screen and it is on the front." + // The worst of the three failures behind this, because the viewer reads the number: a
2605
+ // model invents one whenever a screen or a document is in shot, and it contradicts the
2606
+ // script it sits under. Frames simply do not get legible text; the captions carry the
2607
+ // numbers.
2608
+ //
2609
+ // Default ON, and asked for explicitly rather than inferred: an ad frame with no
2610
+ // person in it still sits under a script for an invented number to argue with. Only a
2611
+ // plain Studio picture opts out — it has no script, and it may BE the poster somebody
2612
+ // asked for, which the model picker sells GPT Image 2.5 on being able to render.
2613
+ (opts.readableText === "allowed" ? "" : " NO readable text or numbers anywhere in frame \u2014 phone screens, documents and signage stay illegible or out of focus, because any figure the model invents will contradict the script.") + // Measured: one finished ad reported malformed hands or limbs in 8 of 12 sampled frames;
2614
+ // another, a woman with an extra right arm and an unattached hand gripping a panel.
2615
+ // Fiddly work at close range is where a video model breaks, every time.
2616
+ " Hands are kept simple: no close-up of fingers manipulating small parts, no hand gripping the edge of an object, and each person has exactly TWO arms and TWO legs, all attached and all visible or all out of frame. Anyone working does so the way the trade actually does it: nobody stands or kneels on the equipment being installed, nothing is fitted overhanging an edge or floating unsupported, and every part rests on the structure that would really carry it." + // The newest clause, and the one no route had. A testimonial came back with the customer
2617
+ // repairing the panel herself: nothing said she was not the installer, so the model cast
2618
+ // her as one. Who someone IS in the picture has to be stated, or it is guessed.
2619
+ (opts.role ? ` The person on camera is ${opts.role} \u2014 they are shown as that and never doing somebody else's job.` : "") + (opts.currency ? ` If a currency is unavoidably visible it is ${opts.currency}.` : "");
2620
+ }
2621
+
2622
+ // ../canvas-contract/src/nodeCost.ts
2623
+ var ELEVENLABS_USD_PER_CHARACTER = 22e-5;
2624
+ var ELEVENLABS_MUSIC_USD_PER_SECOND = 0.022;
2625
+ var ELEVENLABS_SOUND_EFFECT_USD_PER_SECOND = 0.022;
2626
+ var ELEVENLABS_STS_USD_PER_MINUTE = 1e3 * ELEVENLABS_USD_PER_CHARACTER;
2627
+ var FALAI_LIPSYNC_PER_MIN_USD = 0.4;
2628
+ var FALAI_VIDEO_BG_REMOVE_REFINED_USD_PER_30_FRAMES = 0.012;
2629
+ var FALAI_VIDEO_BG_REMOVE_FAST_USD_PER_30_FRAMES = 8e-3;
2630
+ var FALAI_IMAGE_BG_REMOVE_USD_PER_CALL = 1e-3;
2631
+ var GROQ_WHISPER_COST_PER_HOUR = 0.04;
2632
+ var GROQ_WHISPER_MINIMUM_SECONDS = 10;
2633
+ var DEEPGRAM_NOVA3_COST_PER_MINUTE = 43e-4;
2634
+ var FIRECRAWL_COST_PER_SCRAPE = 1e-3;
2635
+ var DEFAULT_MUSIC_SECONDS = 30;
2636
+ var DEFAULT_SOUND_EFFECT_SECONDS = 5;
2637
+ var DEFAULT_BACKGROUND_REMOVE_SECONDS = 30;
2638
+ var DEFAULT_MEDIA_SECONDS = 60;
2639
+ function ttsCharactersUsd(characters) {
2640
+ return characters * ELEVENLABS_USD_PER_CHARACTER;
2641
+ }
2642
+ function musicSecondsUsd(seconds) {
2643
+ return seconds * ELEVENLABS_MUSIC_USD_PER_SECOND;
2644
+ }
2645
+ function soundEffectSecondsUsd(seconds) {
2646
+ return seconds * ELEVENLABS_SOUND_EFFECT_USD_PER_SECOND;
2647
+ }
2648
+ function voiceConvertMinutes(durationMs) {
2649
+ return Math.max(durationMs / 6e4, 0.1);
2650
+ }
2651
+ function voiceConvertUsd(minutes) {
2652
+ return minutes * ELEVENLABS_STS_USD_PER_MINUTE;
2653
+ }
2654
+ function lipsyncMinutes(audioMs, videoMs) {
2655
+ const durationMs = Math.max(audioMs ?? 0, videoMs ?? 0);
2656
+ return durationMs > 0 ? durationMs / 6e4 : 1;
2657
+ }
2658
+ function lipsyncUsd(minutes) {
2659
+ return minutes * FALAI_LIPSYNC_PER_MIN_USD;
2660
+ }
2661
+ function backgroundRemoveFrames(durationSeconds) {
2662
+ return Math.max(30, Math.ceil((durationSeconds ?? DEFAULT_BACKGROUND_REMOVE_SECONDS) * 30));
2663
+ }
2664
+ function videoBackgroundRemoveUsd(durationSeconds, edgeRefinement) {
2665
+ const unit = edgeRefinement ? FALAI_VIDEO_BG_REMOVE_REFINED_USD_PER_30_FRAMES : FALAI_VIDEO_BG_REMOVE_FAST_USD_PER_30_FRAMES;
2666
+ return backgroundRemoveFrames(durationSeconds) / 30 * unit;
2667
+ }
2668
+ function transcriptionUsd(transcriber, seconds) {
2669
+ if (seconds <= 0) return 0;
2670
+ if (transcriber === "deepgram") return seconds / 60 * DEEPGRAM_NOVA3_COST_PER_MINUTE;
2671
+ return Math.max(seconds, GROQ_WHISPER_MINIMUM_SECONDS) / 3600 * GROQ_WHISPER_COST_PER_HOUR;
2672
+ }
2673
+ function asBag(value) {
2674
+ return value && typeof value === "object" && !Array.isArray(value) ? value : {};
2675
+ }
2676
+ function num(value) {
2677
+ return typeof value === "number" && Number.isFinite(value) ? value : void 0;
2678
+ }
2679
+ function inputDurationMs(inputs, slot) {
2680
+ const ref = asBag(inputs[slot]);
2681
+ return num(ref.duration_ms) ?? num(asBag(ref.metadata).duration_ms);
2682
+ }
2683
+ function slotCount(inputs, slot) {
2684
+ const value = inputs[slot];
2685
+ if (Array.isArray(value)) return value.length;
2686
+ return value ? 1 : 0;
2687
+ }
2688
+ function textLength(value) {
2689
+ return typeof value === "string" ? value.length : 0;
2690
+ }
2691
+ function estimateVideoGenerateUsd(params, inputs, preferFal) {
2692
+ const model = params.model;
2693
+ if (typeof model !== "string") return null;
2694
+ const referenceOnly = slotCount(inputs, "references") > 0 && !inputs.first_frame;
2695
+ return estimateVideoCostUsd({
2696
+ model,
2697
+ duration: num(params.duration),
2698
+ resolution: typeof params.resolution === "string" ? params.resolution : void 0,
2699
+ generateAudio: typeof params.generate_audio === "boolean" ? params.generate_audio : void 0,
2700
+ buildsOnSourceClip: slotCount(inputs, "video_references") > 0,
2701
+ mayRouteToFal: isSeedanceModel(model) && (preferFal || referenceOnly)
2702
+ });
2703
+ }
2704
+ function estimateMusicUsd(params, inputs) {
2705
+ const pinnedMs = num(params.music_length_ms);
2706
+ const scoredMs = params.model === "elevenlabs/video-background-music-v1" ? inputDurationMs(inputs, "video") : void 0;
2707
+ const seconds = (pinnedMs ?? scoredMs ?? DEFAULT_MUSIC_SECONDS * 1e3) / 1e3;
2708
+ return musicSecondsUsd(seconds);
2709
+ }
2710
+ function estimateDialogueUsd(params) {
2711
+ if (!Array.isArray(params.inputs)) return null;
2712
+ const characters = params.inputs.reduce((sum, line) => sum + textLength(asBag(line).text), 0);
2713
+ return ttsCharactersUsd(characters);
2714
+ }
2715
+ function estimateNodeCostUsd(input) {
2716
+ const params = asBag(input.params);
2717
+ const inputs = asBag(input.inputs);
2718
+ switch (input.nodeType) {
2719
+ case "video_generate":
2720
+ return estimateVideoGenerateUsd(params, inputs, input.preferFal === true);
2721
+ case "tts":
2722
+ return typeof params.text === "string" ? ttsCharactersUsd(params.text.length) : null;
2723
+ case "dialogue":
2724
+ return estimateDialogueUsd(params);
2725
+ case "music":
2726
+ return estimateMusicUsd(params, inputs);
2727
+ case "sound_effect":
2728
+ return soundEffectSecondsUsd(num(params.duration_seconds) ?? DEFAULT_SOUND_EFFECT_SECONDS);
2729
+ case "audio_voice_convert": {
2730
+ const ms = inputDurationMs(inputs, "audio") ?? DEFAULT_MEDIA_SECONDS * 1e3;
2731
+ return voiceConvertUsd(voiceConvertMinutes(ms));
2732
+ }
2733
+ case "video_lipsync":
2734
+ return lipsyncUsd(lipsyncMinutes(inputDurationMs(inputs, "audio"), inputDurationMs(inputs, "video")));
2735
+ case "video_background_remove": {
2736
+ const ms = inputDurationMs(inputs, "video");
2737
+ return videoBackgroundRemoveUsd(ms === void 0 ? void 0 : ms / 1e3, params.edge_refinement !== false);
2738
+ }
2739
+ case "image_background_remove":
2740
+ return FALAI_IMAGE_BG_REMOVE_USD_PER_CALL;
2741
+ case "video_transcribe": {
2742
+ const ms = inputDurationMs(inputs, "video") ?? DEFAULT_MEDIA_SECONDS * 1e3;
2743
+ return transcriptionUsd(params.transcriber === "deepgram" ? "deepgram" : "groq", ms / 1e3);
2744
+ }
2745
+ case "ingest":
2746
+ return params.strategy === "firecrawl" ? FIRECRAWL_COST_PER_SCRAPE : 0;
2747
+ case "voice_select":
2748
+ case "load_artifact":
2749
+ case "save_artifact":
2750
+ case "resize":
2751
+ case "crop":
2752
+ return 0;
2753
+ default:
2754
+ return null;
2755
+ }
2756
+ }
2757
+ function estimateNodeCredits(input) {
2758
+ const usd = estimateNodeCostUsd(input);
2759
+ return usd === null ? null : usdToCredits(usd);
2760
+ }
2761
+
2762
+ // ../canvas-contract/src/personRealism.ts
2763
+ var PHONE_CAMERA = "Shot on a phone, an iPhone or a Samsung Galaxy, with the main camera in the default photo mode (not portrait mode): slightly wide angle, held by a friend about a metre away or at arm's length, the background mostly in focus the way phone photos are, the phone's own processing \u2014 HDR evening out a bright window, a touch of over-sharpening, smoothed noise in the shadows, punchy everyday colour. Slightly imperfect framing. Not a professional camera: no bokeh or creamy background blur, no lens compression, no studio or flash lighting, no colour grade.";
2764
+ var REAL_SKIN = "Real skin and a real face: visible pores, fine lines, uneven tone, small marks, stray hairs, slight asymmetry. Clothes with real creases.";
2765
+ var NOT_A_MODEL = "Not stock photography, not a model or an influencer: no beauty retouching, no glowing or plastic skin, no perfectly symmetrical features.";
2766
+ function candidPersonPortraitPrompt(p) {
2767
+ return [
2768
+ `An unretouched candid phone photo of one ordinary, real person: ${p.subject}`,
2769
+ p.wardrobe?.trim() ? `Wearing: ${p.wardrobe.trim()}` : null,
2770
+ `Where: ${p.setting?.trim() || "an everyday place that fits who they are, in daylight"}, available light only. They look toward the lens mid-conversation with a relaxed, unposed expression. Framed from the head to mid-torso, face clearly visible.`,
2771
+ PHONE_CAMERA,
2772
+ REAL_SKIN,
2773
+ NOT_A_MODEL,
2774
+ "No text, logos or watermarks. One person only."
2775
+ ].filter((line) => line !== null).join("\n");
2776
+ }
2777
+
2778
+ // ../canvas-contract/src/validateParams.ts
2779
+ function isManagedNodeKind(nodeType) {
2780
+ return Object.keys(MODEL_REGISTRY).includes(nodeType);
2781
+ }
2782
+ function checkRequiredParams(spec, params, model) {
2783
+ const errors = [];
2784
+ for (const req of spec.required) {
2785
+ if (params[req] === void 0 || params[req] === null) {
2786
+ errors.push({
2787
+ code: "missing_required_param",
2788
+ param: req,
2789
+ message: `missing required param "${req}" for model "${model}"`
2790
+ });
2791
+ }
2792
+ }
2793
+ return errors;
2794
+ }
2795
+ function checkParamValues(spec, params, model) {
2796
+ const errors = [];
2797
+ for (const [key, value] of Object.entries(params)) {
2798
+ if (key === "model") continue;
2799
+ if (value === void 0) continue;
2800
+ const schema = spec.params[key];
2801
+ if (!schema) {
2802
+ errors.push({
2803
+ code: "unknown_param",
2804
+ param: key,
2805
+ message: `param "${key}" is not supported by model "${model}"`
2806
+ });
2807
+ continue;
2808
+ }
2809
+ const valueErr = validateValue(key, value, schema, model);
2810
+ if (valueErr) errors.push(valueErr);
2811
+ }
2812
+ return errors;
2813
+ }
2814
+ function validateModelParams(nodeType, model, params) {
2815
+ const spec = MODEL_REGISTRY[nodeType][canonicalModelId(model)];
2816
+ if (!spec) {
2817
+ return {
2818
+ ok: false,
2819
+ errors: [{ code: "unknown_model", message: `unknown model "${model}" for node "${nodeType}"` }]
2820
+ };
2821
+ }
2822
+ const fitted = canonicalModelParams(nodeType, { ...params, model });
2823
+ const errors = [...checkRequiredParams(spec, fitted, model), ...checkParamValues(spec, fitted, model)];
2824
+ if (errors.length > 0) return { ok: false, errors };
2825
+ if (nodeType === "video_generate") {
2826
+ const tooHeavy = clipTooHeavyToIngest(
2827
+ typeof params.duration === "number" ? params.duration : void 0,
2828
+ typeof params.resolution === "string" ? params.resolution : void 0
2829
+ );
2830
+ if (tooHeavy) return { ok: false, errors: [{ code: "clip_too_heavy", message: tooHeavy }] };
2831
+ }
2832
+ return { ok: true };
2833
+ }
2834
+ function validateModelInputs(nodeType, model, providedKinds) {
2835
+ const spec = MODEL_REGISTRY[nodeType][canonicalModelId(model)];
2836
+ if (!spec) {
2837
+ return {
2838
+ ok: false,
2839
+ errors: [{ code: "unknown_model", message: `unknown model "${model}" for node "${nodeType}"` }]
2840
+ };
2841
+ }
2842
+ const have = new Set(providedKinds);
2843
+ const errors = [];
2844
+ for (const inputSpec of spec.inputs) {
2845
+ if (!have.has(inputSpec.kind)) {
2846
+ errors.push({
2847
+ code: "missing_input",
2848
+ input: inputSpec.kind,
2849
+ message: `model "${model}" requires input of kind "${inputSpec.kind}"`
2850
+ });
2851
+ }
2852
+ }
2853
+ if (errors.length > 0) return { ok: false, errors };
2854
+ return { ok: true };
2855
+ }
2856
+ function validateStringValue(key, value, schema, model) {
2857
+ if (typeof value !== "string") {
2858
+ return { code: "invalid_value", param: key, message: `${key}: expected string, got ${typeof value}` };
2859
+ }
2860
+ if (schema.enum && !schema.enum.includes(value)) {
2861
+ return {
2862
+ code: "invalid_value",
2863
+ param: key,
2864
+ message: `${key}: "${value}" not allowed by "${model}" (allowed: ${schema.enum.join(", ")})`
2865
+ };
2866
+ }
2867
+ if (schema.maxLength !== void 0 && value.length > schema.maxLength) {
2868
+ return {
2869
+ code: "invalid_value",
2870
+ param: key,
2871
+ message: `${key}: ${value.length} characters exceeds max ${schema.maxLength} for "${model}"`
2872
+ };
2873
+ }
2874
+ return null;
2875
+ }
2876
+ function validateNumberValue(key, value, schema, model) {
2877
+ if (typeof value !== "number" || Number.isNaN(value)) {
2878
+ return { code: "invalid_value", param: key, message: `${key}: expected number, got ${typeof value}` };
2879
+ }
2880
+ if (schema.enum && !schema.enum.includes(value)) {
2881
+ return {
2882
+ code: "invalid_value",
2883
+ param: key,
2884
+ message: `${key}: ${value} not allowed by "${model}" (allowed: ${schema.enum.join(", ")})`
2885
+ };
2886
+ }
2887
+ if (schema.integer && !Number.isInteger(value)) {
2888
+ return { code: "invalid_value", param: key, message: `${key}: ${value} must be a whole number` };
2889
+ }
2890
+ if (schema.min !== void 0 && value < schema.min) {
2891
+ return { code: "invalid_value", param: key, message: `${key}: ${value} below min ${schema.min}` };
2892
+ }
2893
+ if (schema.max !== void 0 && value > schema.max) {
2894
+ return { code: "invalid_value", param: key, message: `${key}: ${value} above max ${schema.max}` };
2895
+ }
2896
+ return null;
2897
+ }
2898
+ function validateValue(key, value, schema, model) {
2899
+ switch (schema.kind) {
2900
+ case "string":
2901
+ return validateStringValue(key, value, schema, model);
2902
+ case "number":
2903
+ return validateNumberValue(key, value, schema, model);
2904
+ case "boolean":
2905
+ if (typeof value !== "boolean") {
2906
+ return { code: "invalid_value", param: key, message: `${key}: expected boolean, got ${typeof value}` };
2907
+ }
2908
+ return null;
2909
+ case "json":
2910
+ return null;
2911
+ default: {
2912
+ const _exhaustive = schema;
2913
+ return _exhaustive;
2914
+ }
2915
+ }
2916
+ }
2917
+
2918
+ // ../canvas-contract/src/videoBlueprint.ts
2919
+ import { z } from "zod";
2920
+ var FrameAssetSchema = z.object({ url: z.string().optional() }).loose().optional();
2921
+ var BlueprintDialogueLineSchema = z.object({
2922
+ speaker: z.string().optional(),
2923
+ line: z.string().optional(),
2924
+ // Absolute seconds on the source timeline (the deconstruct emits both).
2925
+ start_s: z.number().optional(),
2926
+ end_s: z.number().optional(),
2927
+ delivery: z.string().optional(),
2928
+ voice_description: z.string().optional(),
2929
+ // DECON-supplied: is this speaker's FACE visibly speaking in THIS scene? Element
2930
+ // presence alone can't answer that — a founder pictured in a polaroid close-up is
2931
+ // "present" yet the line is voiceover, and treating it as on-camera produced a
2932
+ // native Seedance lip-sync clip of a still photograph. `false` pins the line to
2933
+ // the VO path; absent keeps the presence-based decision (old blueprints).
2934
+ on_camera: z.boolean().optional()
2935
+ }).loose();
2936
+ var SfxSchema = z.object({
2937
+ at_s: z.number().optional(),
2938
+ duration_s: z.number().optional(),
2939
+ sound_effect_prompt: z.string().optional(),
2940
+ description: z.string().optional()
2941
+ }).loose();
2942
+ var CompositionRegionSchema = z.object({
2943
+ // full | top | bottom | left | right | inset
2944
+ panel: z.string().optional(),
2945
+ // 9-grid anchor for an `inset` presenter box.
2946
+ position: z.string().optional(),
2947
+ is_presenter: z.boolean().optional(),
2948
+ // The cast id shown/speaking in this region (routes lip-sync + element refs).
2949
+ cast_ref: z.string().optional(),
2950
+ // What the region's content IS: camera | screen_capture | static_graphic |
2951
+ // generated. Authoritative for routing when present (regex-over-prose fallback
2952
+ // otherwise): screen_capture/static_graphic are rebuilt from REAL surfaces on the
2953
+ // overlay layer, never AI-generated.
2954
+ kind: z.string().optional(),
2955
+ // Opaque id naming the SPECIFIC on-screen document/note/app-state this
2956
+ // screen_capture region shows. Two scenes share it only when they show the SAME
2957
+ // recording continuing (scrolling/typing/waiting within it) — a genuinely
2958
+ // DIFFERENT document/note/recording (a source video splicing two screen captures)
2959
+ // gets a different id. Breaks a persistent-layout run into separate surface stubs
2960
+ // instead of asking the operator for one screenshot that can't cover both.
2961
+ surface_id: z.string().optional(),
2962
+ // Camera bubble(s)/inset(s) embedded INSIDE this region's surface (a Loom-style
2963
+ // presenter bubble inside a screen recording) — video-in-video the reproduction
2964
+ // must re-composite, not paint into the surface.
2965
+ nested: z.array(z.object({}).loose()).optional(),
2966
+ summary: z.string().optional(),
2967
+ frame_prompt: z.string().optional(),
2968
+ motion_prompt: z.string().optional()
2969
+ }).loose();
2970
+ var SceneCompositionSchema = z.object({
2971
+ // full_frame (default) | split_screen | pip | keyed_overlay
2972
+ layout: z.string().optional(),
2973
+ // split_screen only: vertical (top/bottom) | horizontal (left/right).
2974
+ split_axis: z.string().optional(),
2975
+ regions: z.array(CompositionRegionSchema).optional()
2976
+ }).loose();
2977
+ var CameraMotionSchema = z.object({ movement: z.string().optional(), detail: z.string().optional() }).loose();
2978
+ var TranscriptWordSchema = z.object({ text: z.string().optional() }).loose();
2979
+ var SCENE_ROUTE_HINTS = ["brand_card"];
2980
+ var VideoSceneSchema = z.object({
2981
+ start_s: z.number().optional(),
2982
+ end_s: z.number().optional(),
2983
+ duration_s: z.number().optional(),
2984
+ summary: z.string().optional(),
2985
+ action_detail: z.string().optional(),
2986
+ // The scene's spatial layout. Absent/full_frame ⇒ one uncut shot (default path).
2987
+ // A layered layout (split_screen/pip/keyed_overlay) with regions ⇒ the scaffold
2988
+ // builds one clip per region and stacks/overlays them into the scene picture.
2989
+ composition: SceneCompositionSchema.optional(),
2990
+ // The capture "look" for this scene — selected from the ad-native shoot-mode
2991
+ // grammar (the CLI's scaffold/lib/shoot-modes.ts). When absent the scaffold
2992
+ // auto-derives a UGC/product mode; a human can override per scene by setting this.
2993
+ shoot_mode: z.string().optional(),
2994
+ // Diegetic ambient the clip's native audio should carry (no music). When
2995
+ // absent the scene falls back to its shoot mode's default ambience.
2996
+ ambient: z.string().optional(),
2997
+ camera_motion: CameraMotionSchema.optional(),
2998
+ start_frame_prompt: z.string().optional(),
2999
+ end_frame_prompt: z.string().optional(),
3000
+ motion_prompt: z.string().optional(),
3001
+ // The scene's role in the ad's persuasion arc (DECON-supplied); drives the
3002
+ // script re-craft checklist. Inferred from position when absent.
3003
+ narrative_role: z.string().optional(),
3004
+ // See `SceneRouteHint`.
3005
+ route_hint: z.enum(SCENE_ROUTE_HINTS).optional(),
3006
+ // DECON-supplied on the HOOK scene: the engineered physical/emotional state that
3007
+ // makes the first frame stop the scroll (sweaty/breathless/urgent …). Injected
3008
+ // into the hook's start-frame description so the generator renders that state,
3009
+ // not a calm influencer (CCA-11).
3010
+ hook_mechanic: z.object({ mechanic: z.string().optional(), why_it_stops_scroll: z.string().optional() }).loose().optional(),
3011
+ // DECON-supplied per-scene location (so a gym hook isn't flattened to "home").
3012
+ scene_setting: z.string().optional(),
3013
+ // How this scene cuts to the next (DECON-supplied). A recognized non-cut type
3014
+ // (fade/whip/zoom/dissolve/swipe) is reproduced as an ffmpeg xfade at the
3015
+ // boundary; cut/match_cut/none/other stay hard cuts. The last scene's value is
3016
+ // ignored (nothing follows it).
3017
+ transition_out: z.object({ type: z.string().optional(), description: z.string().optional() }).loose().optional(),
3018
+ dialogue: z.array(BlueprintDialogueLineSchema).optional(),
3019
+ sfx: z.array(SfxSchema).optional(),
3020
+ // Parsed element by element where they are read (`BlueprintOverlaySchema`,
3021
+ // `BlueprintFloatingElementSchema`), so one malformed graphic never rejects the scene.
3022
+ overlays: z.array(z.unknown()).optional(),
3023
+ floating_elements: z.array(z.unknown()).optional(),
3024
+ // DECON-supplied: how much the picture itself moves within the shot. Gates the
3025
+ // flash-hold optimization — a sub-2s b-roll flash with REAL subject motion
3026
+ // (pouring, spreading, hands working) must stay a real clip; freezing it turns
3027
+ // a montage into a slideshow. Absent (old blueprints) keeps the cheap still.
3028
+ motion_level: z.enum(["static", "subtle", "dynamic"]).optional(),
3029
+ transcript_slice: z.array(TranscriptWordSchema).optional(),
3030
+ start_frame_asset: FrameAssetSchema,
3031
+ end_frame_asset: FrameAssetSchema,
3032
+ // DECON-supplied: true when this scene is a length-split CONTINUATION of the
3033
+ // previous one (the SAME physical shot, broken up only because it exceeded the
3034
+ // clip ceiling). The scaffold then shares the splice keyframe — this scene's
3035
+ // start frame IS the previous scene's end frame — so the join is seamless.
3036
+ continues_previous: z.boolean().optional()
3037
+ }).loose();
3038
+ var VideoBlueprintSchema = z.object({
3039
+ source: z.object({ aspect_ratio: z.string().optional(), duration_s: z.number().optional() }).loose().optional(),
3040
+ global: z.object({
3041
+ music: z.object({
3042
+ present: z.boolean().optional(),
3043
+ music_prompt: z.string().optional(),
3044
+ // Absolute second the music enters in the reference (the bed often
3045
+ // kicks in mid-ad, after the hook). We start the regenerated track here
3046
+ // instead of at 0 so the timing matches.
3047
+ starts_at_s: z.number().optional(),
3048
+ // Populated by the deconstruct when AudD (Shazam-style) recognizes the
3049
+ // reference track. We never reuse it — only style the regenerated bed.
3050
+ identified_track: z.object({ title: z.string().optional(), artist: z.string().optional() }).loose().nullish()
3051
+ }).loose().optional(),
3052
+ cast: z.array(
3053
+ z.object({
3054
+ id: z.string().optional(),
3055
+ description: z.string().optional(),
3056
+ // The deconstruct's note on the target-market localization (e.g. "native
3057
+ // French speaker") — read to derive the spoken-track language code.
3058
+ market_localization_note: z.string().optional()
3059
+ }).loose()
3060
+ ).optional(),
3061
+ voiceover: z.object({
3062
+ // on_camera | mixed → mouths are on screen (lip-sync candidates);
3063
+ // voiceover | none → narration over the picture (no lip-sync).
3064
+ mode: z.string().optional(),
3065
+ // Which variety of the language the speech is in. Stated because the model
3066
+ // picks one otherwise: ads set in Spain came back in Latin American Spanish,
3067
+ // and the pinned peninsular voice could not undo it — the re-voicing is
3068
+ // speech-to-speech, so it carries the accent across and swaps only the timbre.
3069
+ accent: z.string().optional(),
3070
+ voice_description: z.string().optional(),
3071
+ persona: z.string().optional()
3072
+ }).loose().optional(),
3073
+ // Visual palette — read only to colour a clean brand-card/CTA plate (the
3074
+ // first hex is the dominant brand colour); never to drive frame generation.
3075
+ style: z.object({ palette: z.array(z.object({ hex: z.string().optional() }).loose()).optional() }).loose().optional(),
3076
+ // Written by `scaffold-ad` (the deconstruct names its own fields, e.g. `branding.brand_name`):
3077
+ // the whole script as one string, where the ad is set, and the brand it closes on.
3078
+ transcript: z.string().optional(),
3079
+ market: z.string().optional(),
3080
+ branding: z.object({ name: z.string().optional(), logo_path: z.string().optional() }).loose().optional()
3081
+ }).loose().optional(),
3082
+ // Written by `scaffold-ad`: what the beats add up to, so a short ad is caught before it renders.
3083
+ estimated_duration_s: z.number().optional(),
3084
+ scenes: z.array(VideoSceneSchema).min(1)
3085
+ }).loose();
3086
+ var OverlayStyleSchema = z.object({ color_hex: z.string().optional(), background: z.string().optional(), size: z.string().optional() }).loose();
3087
+ var BlueprintOverlaySchema = z.object({
3088
+ text: z.string().optional(),
3089
+ appears_at_s: z.number().optional(),
3090
+ duration_s: z.number().optional(),
3091
+ position: z.string().optional(),
3092
+ role: z.string().optional(),
3093
+ animation: z.string().optional(),
3094
+ animation_detail: z.string().optional(),
3095
+ style: OverlayStyleSchema.optional()
3096
+ }).loose();
3097
+ var BlueprintFloatingElementSchema = z.object({
3098
+ kind: z.string().optional(),
3099
+ description: z.string().optional(),
3100
+ brand_name: z.string().nullish(),
3101
+ what_it_represents: z.string().optional(),
3102
+ appears_at_s: z.number().optional(),
3103
+ duration_s: z.number().optional(),
3104
+ position: z.string().optional()
3105
+ }).loose();
3106
+
3107
+ export {
3108
+ AD_PLATFORMS,
3109
+ AD_PLATFORM_LEAD,
3110
+ AD_PLACEMENTS,
3111
+ deliveryPlan,
3112
+ verticalCover,
3113
+ AD_FORMAT_PLATFORMS,
3114
+ platformFormats,
3115
+ resolveAdaptFormats,
3116
+ AD_DESCRIBE_FOCUS,
3117
+ AD_SELECT_SYSTEM,
3118
+ AD_SELECT_PROMPT,
3119
+ canonicalize,
3120
+ withoutCastName,
3121
+ frameRealismDirection,
3122
+ OPENROUTER_IMAGE_SIZES,
3123
+ SEEDANCE_DURATIONS,
3124
+ ELEVENLABS_OUTPUT_FORMATS,
3125
+ ELEVENLABS_MAX_TEXT_CHARS,
3126
+ ELEVENLABS_MAX_MUSIC_LENGTH_MS,
3127
+ IMAGE_GENERATE_MODELS,
3128
+ DEFAULT_IMAGE_GENERATE_MODEL,
3129
+ IMAGE_TIER_CREDITS,
3130
+ imagePictureCredits,
3131
+ VIDEO_GENERATE_MODELS,
3132
+ DEFAULT_VIDEO_GENERATE_MODEL,
3133
+ supportsReferenceToVideo,
3134
+ supportsLastFrame,
3135
+ MODEL_REGISTRY,
3136
+ canonicalModelId,
3137
+ modelIdsAccepted,
3138
+ MODEL_ROLES,
3139
+ AD_IMAGE_MODEL,
3140
+ REFERENCE_SHEET_MODEL,
3141
+ ASPECT_ADAPT_MODEL,
3142
+ PLATE_JUDGE_MODEL,
3143
+ AD_DESCRIBE_MODEL,
3144
+ BLUEPRINT_ANALYSIS_MODEL,
3145
+ VIEWER_CHECK_MODEL,
3146
+ CUSTOMER_INSIGHTS_MODEL,
3147
+ GLANCE_CHECK_MODEL,
3148
+ TEXT_BOX_READER_MODEL,
3149
+ SUBJECT_BOX_READER_MODEL,
3150
+ SIZE_MATCH_MODEL,
3151
+ VIDEO_DECONSTRUCT_MODEL,
3152
+ VOICEOVER_MODEL,
3153
+ SOUND_EFFECT_MODEL,
3154
+ MUSIC_BED_MODEL,
3155
+ VOICE_CONVERT_MODEL,
3156
+ isRegisteredModel,
3157
+ imageGenerateAspectRatios,
3158
+ supportsParam,
3159
+ DEFAULT_CLIP_DURATION_S,
3160
+ SPOKEN_WORDS_PER_SECOND,
3161
+ spokenWordsIn,
3162
+ SPOKEN_CLIP_DURATION_S,
3163
+ nearestClipDuration,
3164
+ clipAudioMode,
3165
+ clipDurationsFor,
3166
+ maxClipSeconds,
3167
+ splitScriptFor,
3168
+ promptMaxLength,
3169
+ maxInputSlot,
3170
+ maxInputReferences,
3171
+ bestSupportedQuality,
3172
+ supportedAspectRatios,
3173
+ nearestSupportedAspectRatio,
3174
+ nearestSupportedImageSize,
3175
+ estimateVideoCredits,
3176
+ DEFAULT_MUSIC_SECONDS,
3177
+ DEFAULT_SOUND_EFFECT_SECONDS,
3178
+ estimateNodeCredits,
3179
+ candidPersonPortraitPrompt,
3180
+ isManagedNodeKind,
3181
+ validateModelParams,
3182
+ validateModelInputs,
3183
+ VideoBlueprintSchema,
3184
+ BlueprintOverlaySchema,
3185
+ BlueprintFloatingElementSchema
3186
+ };
3187
+ //# sourceMappingURL=chunk-MCJ5I5LR.js.map