@cueframe/kernel 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (355) hide show
  1. package/LICENSE +661 -0
  2. package/dist/_members/composition/ops/compositionOps.d.ts +1 -0
  3. package/dist/_members/composition/projection/behind-readiness.d.ts +127 -0
  4. package/dist/_members/composition/projection/index.d.ts +2 -0
  5. package/dist/_members/composition/projection/reframe-readiness.d.ts +156 -0
  6. package/dist/_members/composition/validators/composition.d.ts +42 -25
  7. package/dist/_members/composition/validators/render.d.ts +32 -0
  8. package/dist/_members/core/render/compositionRender.d.ts +17 -1
  9. package/dist/_members/core/render/types.d.ts +31 -0
  10. package/dist/authoring/build-tools.js +6 -6
  11. package/dist/authoring/context.js +4 -4
  12. package/dist/authoring/tools.js +5 -5
  13. package/dist/authoring.js +11 -9
  14. package/dist/{chunk-ZB3C3HM7.js → chunk-7FO3ZJ43.js} +3 -0
  15. package/dist/{chunk-ODL7GQJG.js → chunk-AP6ZIVAV.js} +2 -2
  16. package/dist/{chunk-IBYQG46O.js → chunk-AQBREB5O.js} +1 -1
  17. package/dist/{chunk-YIOY2XEO.js → chunk-DK2ODBNT.js} +15 -5
  18. package/dist/{chunk-JRQVPFLF.js → chunk-HY3RIEZW.js} +1 -1
  19. package/dist/{chunk-GEA7E2FL.js → chunk-JJ6XD7NG.js} +151 -1
  20. package/dist/{chunk-COYMZ76S.js → chunk-MBCXCJOE.js} +1 -1
  21. package/dist/{chunk-37NJ27UU.js → chunk-OCFDUCF4.js} +3 -0
  22. package/dist/{chunk-VOO5FQSS.js → chunk-PDYO3DOJ.js} +5 -5
  23. package/dist/{chunk-MXFAADCQ.js → chunk-PODIYN2K.js} +9 -2
  24. package/dist/{chunk-NFEGPWGS.js → chunk-TOJEXFXL.js} +1 -1
  25. package/dist/{chunk-LM4WDUQJ.js → chunk-UHGSZZDI.js} +1 -1
  26. package/dist/{chunk-XWKZB5U5.js → chunk-ZWMV6DD2.js} +24 -1
  27. package/dist/compose/renderer.js +3 -3
  28. package/dist/compose.js +6 -6
  29. package/dist/composition/graphics-plan.js +1 -1
  30. package/dist/composition/ops.js +3 -3
  31. package/dist/composition/primitive-catalog.js +1 -1
  32. package/dist/composition/projection.js +19 -3
  33. package/dist/composition/validators.js +6 -4
  34. package/dist/composition-ops.js +8 -6
  35. package/dist/composition.js +24 -6
  36. package/dist/{context-OKX3HHFS.js → context-YWUZDG5X.js} +4 -4
  37. package/dist/core/render.js +3 -3
  38. package/dist/core/select.js +2 -2
  39. package/dist/core.js +3 -3
  40. package/dist/errors.js +1 -1
  41. package/dist/mcp/adapter.js +1 -0
  42. package/dist/media-model/testing.js +1071 -718
  43. package/dist/nle-export/server.js +328 -130
  44. package/dist/nle-export.js +7 -6
  45. package/package.json +13 -14
  46. package/dist/_members/account-model/index.js +0 -4
  47. package/dist/_members/account-model/testing/conversationStoreContract.js +0 -168
  48. package/dist/_members/account-model/testing/index.js +0 -7
  49. package/dist/_members/account-model/testing/restorePointStoreContract.js +0 -69
  50. package/dist/_members/account-model/types/index.js +0 -1
  51. package/dist/_members/account-model/validators/contextFile.js +0 -18
  52. package/dist/_members/account-model/validators/conversation.js +0 -95
  53. package/dist/_members/account-model/validators/dashboardInsight.js +0 -16
  54. package/dist/_members/account-model/validators/index.js +0 -7
  55. package/dist/_members/account-model/validators/sessionToken.js +0 -49
  56. package/dist/_members/account-model/validators/uploadToken.js +0 -16
  57. package/dist/_members/account-model/validators/userSettings.js +0 -12
  58. package/dist/_members/account-model/validators/workingComposition.js +0 -20
  59. package/dist/_members/brand-derivation/constants.js +0 -20
  60. package/dist/_members/brand-derivation/contrastSafe.js +0 -114
  61. package/dist/_members/brand-derivation/index.js +0 -1
  62. package/dist/_members/cloud-import/chunk-XKO6ZSWI.js +0 -162
  63. package/dist/_members/cloud-import/chunk-XKO6ZSWI.js.map +0 -1
  64. package/dist/_members/cloud-import/index.js +0 -241
  65. package/dist/_members/cloud-import/index.js.map +0 -1
  66. package/dist/_members/cloud-import/multipartUpload.js +0 -7
  67. package/dist/_members/cloud-import/multipartUpload.js.map +0 -1
  68. package/dist/_members/composition/audio/audioMix.js +0 -61
  69. package/dist/_members/composition/audio/index.js +0 -5
  70. package/dist/_members/composition/audio/mixStaging.js +0 -195
  71. package/dist/_members/composition/audio/musicPack.generated.js +0 -136
  72. package/dist/_members/composition/audio/musicPack.js +0 -36
  73. package/dist/_members/composition/audio/pack.generated.js +0 -603
  74. package/dist/_members/composition/audio/pack.js +0 -48
  75. package/dist/_members/composition/audio/palette.js +0 -134
  76. package/dist/_members/composition/autozoom/index.js +0 -83
  77. package/dist/_members/composition/brand-kit.js +0 -45
  78. package/dist/_members/composition/brief/contract.js +0 -209
  79. package/dist/_members/composition/color-grade.js +0 -80
  80. package/dist/_members/composition/depth.js +0 -8
  81. package/dist/_members/composition/fixtures/index.js +0 -143
  82. package/dist/_members/composition/fixtures/vaayaErrored.d.ts +0 -25
  83. package/dist/_members/composition/fixtures/vaayaErrored.js +0 -203
  84. package/dist/_members/composition/fonts.js +0 -162
  85. package/dist/_members/composition/graphics-plan/compile.js +0 -221
  86. package/dist/_members/composition/graphics-plan/index.js +0 -10
  87. package/dist/_members/composition/graphics-plan/instantiateMotif.js +0 -44
  88. package/dist/_members/composition/graphics-plan/motion.js +0 -66
  89. package/dist/_members/composition/graphics-plan/schemas.js +0 -261
  90. package/dist/_members/composition/graphics-plan/solve.js +0 -145
  91. package/dist/_members/composition/index.js +0 -5
  92. package/dist/_members/composition/invariants/clipPlacement.js +0 -69
  93. package/dist/_members/composition/invariants/composition.js +0 -28
  94. package/dist/_members/composition/invariants/errors.js +0 -10
  95. package/dist/_members/composition/invariants/etag.js +0 -38
  96. package/dist/_members/composition/invariants/ids.js +0 -33
  97. package/dist/_members/composition/invariants/index.js +0 -9
  98. package/dist/_members/composition/invariants/keyframes.js +0 -45
  99. package/dist/_members/composition/invariants/markers.js +0 -29
  100. package/dist/_members/composition/invariants/time.js +0 -20
  101. package/dist/_members/composition/invariants/tracks.js +0 -304
  102. package/dist/_members/composition/ops/compositionOps.js +0 -1056
  103. package/dist/_members/composition/ops/headlessStore.js +0 -94
  104. package/dist/_members/composition/ops/index.js +0 -4
  105. package/dist/_members/composition/ops/selectors.js +0 -118
  106. package/dist/_members/composition/ops/timeline-word.js +0 -1
  107. package/dist/_members/composition/ops/transcript.js +0 -77
  108. package/dist/_members/composition/ops/types.js +0 -16
  109. package/dist/_members/composition/primitive-catalog/catalogQuery.js +0 -150
  110. package/dist/_members/composition/primitive-catalog/disabled.js +0 -32
  111. package/dist/_members/composition/primitive-catalog/generated/meta.js +0 -15161
  112. package/dist/_members/composition/primitive-catalog/index.js +0 -46
  113. package/dist/_members/composition/primitive-catalog/paramValidation.js +0 -231
  114. package/dist/_members/composition/primitive-catalog/projection.js +0 -164
  115. package/dist/_members/composition/primitive-catalog/types.js +0 -14
  116. package/dist/_members/composition/projection/behind-placement.js +0 -62
  117. package/dist/_members/composition/projection/brandKit.js +0 -482
  118. package/dist/_members/composition/projection/cardTokens.js +0 -209
  119. package/dist/_members/composition/projection/composition-floor.js +0 -582
  120. package/dist/_members/composition/projection/cropProjection.js +0 -257
  121. package/dist/_members/composition/projection/index.js +0 -7
  122. package/dist/_members/composition/projection/occlusion-budget.js +0 -104
  123. package/dist/_members/composition/projection/safe-zones.js +0 -99
  124. package/dist/_members/composition/reframe/aspectLoss.js +0 -115
  125. package/dist/_members/composition/reframe/coverage.js +0 -62
  126. package/dist/_members/composition/reframe/derive.js +0 -73
  127. package/dist/_members/composition/reframe/index.js +0 -109
  128. package/dist/_members/composition/reframe/kenBurns.js +0 -64
  129. package/dist/_members/composition/reframe/shotScale.js +0 -176
  130. package/dist/_members/composition/reframe/trajectory.js +0 -124
  131. package/dist/_members/composition/timeline/compound.js +0 -134
  132. package/dist/_members/composition/timeline/index.js +0 -9
  133. package/dist/_members/composition/timeline/intent.js +0 -228
  134. package/dist/_members/composition/timeline/keyframes.js +0 -121
  135. package/dist/_members/composition/timeline/link.js +0 -59
  136. package/dist/_members/composition/timeline/occupancy.js +0 -36
  137. package/dist/_members/composition/timeline/placement.js +0 -74
  138. package/dist/_members/composition/timeline/plan.js +0 -31
  139. package/dist/_members/composition/timeline/resolve.js +0 -170
  140. package/dist/_members/composition/timeline/trims.js +0 -278
  141. package/dist/_members/composition/types/index.js +0 -1
  142. package/dist/_members/composition/validators/brandKit.js +0 -295
  143. package/dist/_members/composition/validators/composePlan.js +0 -113
  144. package/dist/_members/composition/validators/composition.js +0 -703
  145. package/dist/_members/composition/validators/font.js +0 -34
  146. package/dist/_members/composition/validators/graphicKinds.js +0 -30
  147. package/dist/_members/composition/validators/index.js +0 -9
  148. package/dist/_members/composition/validators/project.js +0 -29
  149. package/dist/_members/composition/validators/registry.js +0 -41
  150. package/dist/_members/composition/validators/render.js +0 -139
  151. package/dist/_members/composition/validators/session.js +0 -37
  152. package/dist/_members/composition/validators/webhook.js +0 -72
  153. package/dist/_members/composition-ops/alphaLayers.js +0 -141
  154. package/dist/_members/composition-ops/index.js +0 -637
  155. package/dist/_members/composition-ops/materializeGrid.js +0 -99
  156. package/dist/_members/composition-ops/opRecorder.js +0 -196
  157. package/dist/_members/composition-ops/recordingStore.js +0 -14
  158. package/dist/_members/composition-ops/replaceRegion.js +0 -102
  159. package/dist/_members/composition-ops/testFixtures.js +0 -19
  160. package/dist/_members/core/index.js +0 -5
  161. package/dist/_members/core/render/bookends.js +0 -53
  162. package/dist/_members/core/render/captions.js +0 -127
  163. package/dist/_members/core/render/compositionRender.js +0 -1249
  164. package/dist/_members/core/render/deriveTrajectory.js +0 -889
  165. package/dist/_members/core/render/emphasis.js +0 -16
  166. package/dist/_members/core/render/eval/cropBox.js +0 -139
  167. package/dist/_members/core/render/eval/inclusion.js +0 -96
  168. package/dist/_members/core/render/eval/index.js +0 -146
  169. package/dist/_members/core/render/eval/metrics.js +0 -94
  170. package/dist/_members/core/render/exportSettings.js +0 -65
  171. package/dist/_members/core/render/index.js +0 -20
  172. package/dist/_members/core/render/mapFaceToPerson.js +0 -73
  173. package/dist/_members/core/render/types.js +0 -8
  174. package/dist/_members/core/render/vcam/cameraPath.js +0 -248
  175. package/dist/_members/core/render/vcam/constants.js +0 -115
  176. package/dist/_members/core/render/vcam/errorCodes.js +0 -39
  177. package/dist/_members/core/render/vcam/framing.js +0 -136
  178. package/dist/_members/core/render/vcam/requiredRegion.js +0 -137
  179. package/dist/_members/core/render/vcam/shots.js +0 -53
  180. package/dist/_members/core/render/vcam/subjectSet.js +0 -388
  181. package/dist/_members/core/select/errorCodes.js +0 -38
  182. package/dist/_members/core/select/index.js +0 -26
  183. package/dist/_members/core/select/model.js +0 -18
  184. package/dist/_members/core/select/select.js +0 -244
  185. package/dist/_members/core/select/stabilize.js +0 -242
  186. package/dist/_members/core/types.js +0 -7
  187. package/dist/_members/errors/index.js +0 -1
  188. package/dist/_members/errors/registry.js +0 -560
  189. package/dist/_members/foundation/codes/index.js +0 -31
  190. package/dist/_members/foundation/index.js +0 -2
  191. package/dist/_members/foundation/primitives/index.js +0 -5
  192. package/dist/_members/mcp/adapter.js +0 -771
  193. package/dist/_members/mcp/burnedNames.js +0 -73
  194. package/dist/_members/mcp/core.js +0 -390
  195. package/dist/_members/mcp/curation.js +0 -792
  196. package/dist/_members/mcp/executor.js +0 -142
  197. package/dist/_members/mcp/format.js +0 -9
  198. package/dist/_members/mcp/generated/catalogPreviews.js +0 -95
  199. package/dist/_members/mcp/generated/harness.js +0 -81
  200. package/dist/_members/mcp/generated/operations.js +0 -131
  201. package/dist/_members/mcp/index.js +0 -50
  202. package/dist/_members/mcp/internalLoopTools.js +0 -109
  203. package/dist/_members/mcp/prompts.js +0 -45
  204. package/dist/_members/mcp/resources.js +0 -166
  205. package/dist/_members/mcp/server.js +0 -340
  206. package/dist/_members/mcp/wait.js +0 -378
  207. package/dist/_members/mcp/x402Meta.js +0 -66
  208. package/dist/_members/media-model/api.js +0 -175
  209. package/dist/_members/media-model/index.js +0 -1
  210. package/dist/_members/media-model/media-kind.js +0 -116
  211. package/dist/_members/media-model/testing/index.js +0 -1
  212. package/dist/_members/media-model/testing/mediaStoreContract.js +0 -82
  213. package/dist/_members/media-model/transcriptSearch.js +0 -70
  214. package/dist/_members/media-model/transcriptSearchCases.json +0 -79
  215. package/dist/_members/nle-export/compact-timeline.js +0 -73
  216. package/dist/_members/nle-export/compact-timeline.js.map +0 -1
  217. package/dist/_members/nle-export/composition-to-input.js +0 -147
  218. package/dist/_members/nle-export/composition-to-input.js.map +0 -1
  219. package/dist/_members/nle-export/fcpxml.js +0 -159
  220. package/dist/_members/nle-export/fcpxml.js.map +0 -1
  221. package/dist/_members/nle-export/index.js +0 -12
  222. package/dist/_members/nle-export/index.js.map +0 -1
  223. package/dist/_members/nle-export/premiere.js +0 -161
  224. package/dist/_members/nle-export/premiere.js.map +0 -1
  225. package/dist/_members/nle-export/server/index.js +0 -2
  226. package/dist/_members/nle-export/server/index.js.map +0 -1
  227. package/dist/_members/nle-export/server/pack-zip.js +0 -38
  228. package/dist/_members/nle-export/server/pack-zip.js.map +0 -1
  229. package/dist/_members/nle-export/srt.js +0 -50
  230. package/dist/_members/nle-export/srt.js.map +0 -1
  231. package/dist/_members/nle-export/types.js +0 -9
  232. package/dist/_members/nle-export/types.js.map +0 -1
  233. package/dist/_members/nle-export/xml/index.js +0 -11
  234. package/dist/_members/nle-export/xml/index.js.map +0 -1
  235. package/dist/_members/nle-export/xml-utils.js +0 -48
  236. package/dist/_members/nle-export/xml-utils.js.map +0 -1
  237. package/dist/_members/perception/activeSpeaker.js +0 -103
  238. package/dist/_members/perception/audioQuality.js +0 -76
  239. package/dist/_members/perception/energyBeat.js +0 -99
  240. package/dist/_members/perception/identityMatch.js +0 -91
  241. package/dist/_members/perception/index.js +0 -48
  242. package/dist/_members/perception/visualQuality.js +0 -95
  243. package/dist/_members/plane/conformance.js +0 -90
  244. package/dist/_members/plane/contract.js +0 -49
  245. package/dist/_members/plane/index.js +0 -16
  246. package/dist/_members/primitives/backgrounds/index.js +0 -32
  247. package/dist/_members/primitives/backgrounds/index.js.map +0 -1
  248. package/dist/_members/primitives/captions/index.js +0 -398
  249. package/dist/_members/primitives/captions/index.js.map +0 -1
  250. package/dist/_members/primitives/chunk-2LVE4UIT.js +0 -139
  251. package/dist/_members/primitives/chunk-2LVE4UIT.js.map +0 -1
  252. package/dist/_members/primitives/chunk-3IQUH6KK.js +0 -20
  253. package/dist/_members/primitives/chunk-3IQUH6KK.js.map +0 -1
  254. package/dist/_members/primitives/chunk-3OMURV6Q.js +0 -112
  255. package/dist/_members/primitives/chunk-3OMURV6Q.js.map +0 -1
  256. package/dist/_members/primitives/chunk-4IS6TMEG.js +0 -21
  257. package/dist/_members/primitives/chunk-4IS6TMEG.js.map +0 -1
  258. package/dist/_members/primitives/chunk-5MWGAEGQ.js +0 -1644
  259. package/dist/_members/primitives/chunk-5MWGAEGQ.js.map +0 -1
  260. package/dist/_members/primitives/chunk-7RRPFPQK.js +0 -15
  261. package/dist/_members/primitives/chunk-7RRPFPQK.js.map +0 -1
  262. package/dist/_members/primitives/chunk-DH5TRZK2.js +0 -125
  263. package/dist/_members/primitives/chunk-DH5TRZK2.js.map +0 -1
  264. package/dist/_members/primitives/chunk-E3KNUSFG.js +0 -2337
  265. package/dist/_members/primitives/chunk-E3KNUSFG.js.map +0 -1
  266. package/dist/_members/primitives/chunk-G2B3G4HK.js +0 -47
  267. package/dist/_members/primitives/chunk-G2B3G4HK.js.map +0 -1
  268. package/dist/_members/primitives/chunk-HFPFGZXT.js +0 -1494
  269. package/dist/_members/primitives/chunk-HFPFGZXT.js.map +0 -1
  270. package/dist/_members/primitives/chunk-HIWVFZVH.js +0 -19
  271. package/dist/_members/primitives/chunk-HIWVFZVH.js.map +0 -1
  272. package/dist/_members/primitives/chunk-IDAL6G3Y.js +0 -134
  273. package/dist/_members/primitives/chunk-IDAL6G3Y.js.map +0 -1
  274. package/dist/_members/primitives/chunk-KNC6JP5F.js +0 -34
  275. package/dist/_members/primitives/chunk-KNC6JP5F.js.map +0 -1
  276. package/dist/_members/primitives/chunk-KYRDVZST.js +0 -459
  277. package/dist/_members/primitives/chunk-KYRDVZST.js.map +0 -1
  278. package/dist/_members/primitives/chunk-LWLHS2NS.js +0 -3410
  279. package/dist/_members/primitives/chunk-LWLHS2NS.js.map +0 -1
  280. package/dist/_members/primitives/chunk-QAQ3P7DR.js +0 -8855
  281. package/dist/_members/primitives/chunk-QAQ3P7DR.js.map +0 -1
  282. package/dist/_members/primitives/chunk-ROV2ODWC.js +0 -81
  283. package/dist/_members/primitives/chunk-ROV2ODWC.js.map +0 -1
  284. package/dist/_members/primitives/chunk-TCRC2FH3.js +0 -183
  285. package/dist/_members/primitives/chunk-TCRC2FH3.js.map +0 -1
  286. package/dist/_members/primitives/chunk-US4YEDAA.js +0 -96
  287. package/dist/_members/primitives/chunk-US4YEDAA.js.map +0 -1
  288. package/dist/_members/primitives/chunk-UVKRO5ER.js +0 -13
  289. package/dist/_members/primitives/chunk-UVKRO5ER.js.map +0 -1
  290. package/dist/_members/primitives/chunk-W4EIIF2I.js +0 -10
  291. package/dist/_members/primitives/chunk-W4EIIF2I.js.map +0 -1
  292. package/dist/_members/primitives/chunk-WPGKIPCO.js +0 -3563
  293. package/dist/_members/primitives/chunk-WPGKIPCO.js.map +0 -1
  294. package/dist/_members/primitives/chunk-WZFLEGMD.js +0 -1435
  295. package/dist/_members/primitives/chunk-WZFLEGMD.js.map +0 -1
  296. package/dist/_members/primitives/chunk-XHU3WBEI.js +0 -33
  297. package/dist/_members/primitives/chunk-XHU3WBEI.js.map +0 -1
  298. package/dist/_members/primitives/chunk-YN7WTZZ7.js +0 -46
  299. package/dist/_members/primitives/chunk-YN7WTZZ7.js.map +0 -1
  300. package/dist/_members/primitives/effects/index.js +0 -30
  301. package/dist/_members/primitives/effects/index.js.map +0 -1
  302. package/dist/_members/primitives/hero-text/index.js +0 -14
  303. package/dist/_members/primitives/hero-text/index.js.map +0 -1
  304. package/dist/_members/primitives/index.js +0 -64
  305. package/dist/_members/primitives/index.js.map +0 -1
  306. package/dist/_members/primitives/layouts/index.js +0 -24
  307. package/dist/_members/primitives/layouts/index.js.map +0 -1
  308. package/dist/_members/primitives/lib/easings.js +0 -26
  309. package/dist/_members/primitives/lib/easings.js.map +0 -1
  310. package/dist/_members/primitives/lib/index.js +0 -74
  311. package/dist/_members/primitives/lib/index.js.map +0 -1
  312. package/dist/_members/primitives/lib/palette.js +0 -72
  313. package/dist/_members/primitives/lib/palette.js.map +0 -1
  314. package/dist/_members/primitives/lib/preview.js +0 -8
  315. package/dist/_members/primitives/lib/preview.js.map +0 -1
  316. package/dist/_members/primitives/lib/schema.js +0 -12
  317. package/dist/_members/primitives/lib/schema.js.map +0 -1
  318. package/dist/_members/primitives/lib/seeded-random.js +0 -14
  319. package/dist/_members/primitives/lib/seeded-random.js.map +0 -1
  320. package/dist/_members/primitives/lib/text/contrast.js +0 -12
  321. package/dist/_members/primitives/lib/text/contrast.js.map +0 -1
  322. package/dist/_members/primitives/lib/text/fill.js +0 -8
  323. package/dist/_members/primitives/lib/text/fill.js.map +0 -1
  324. package/dist/_members/primitives/lib/text/fitText.js +0 -10
  325. package/dist/_members/primitives/lib/text/fitText.js.map +0 -1
  326. package/dist/_members/primitives/lib/text/marker.js +0 -8
  327. package/dist/_members/primitives/lib/text/marker.js.map +0 -1
  328. package/dist/_members/primitives/lib/text/motion.js +0 -16
  329. package/dist/_members/primitives/lib/text/motion.js.map +0 -1
  330. package/dist/_members/primitives/lib/text/recolor.js +0 -8
  331. package/dist/_members/primitives/lib/text/recolor.js.map +0 -1
  332. package/dist/_members/primitives/lib/text/spec.js +0 -1
  333. package/dist/_members/primitives/lib/text/spec.js.map +0 -1
  334. package/dist/_members/primitives/lib/text/stage.js +0 -8
  335. package/dist/_members/primitives/lib/text/stage.js.map +0 -1
  336. package/dist/_members/primitives/lib/text/typeface.js +0 -8
  337. package/dist/_members/primitives/lib/text/typeface.js.map +0 -1
  338. package/dist/_members/primitives/lib/tokens.js +0 -24
  339. package/dist/_members/primitives/lib/tokens.js.map +0 -1
  340. package/dist/_members/primitives/lib/types.js +0 -1
  341. package/dist/_members/primitives/lib/types.js.map +0 -1
  342. package/dist/_members/primitives/params-required.json +0 -153
  343. package/dist/_members/primitives/scenes/index.js +0 -25
  344. package/dist/_members/primitives/scenes/index.js.map +0 -1
  345. package/dist/_members/primitives/subject-foreground/index.js +0 -30
  346. package/dist/_members/primitives/subject-foreground/index.js.map +0 -1
  347. package/dist/_members/primitives/text/index.js +0 -57
  348. package/dist/_members/primitives/text/index.js.map +0 -1
  349. package/dist/_members/primitives/transitions/index.js +0 -67
  350. package/dist/_members/primitives/transitions/index.js.map +0 -1
  351. package/dist/_members/primitives/ui-blocks/index.js +0 -76
  352. package/dist/_members/primitives/ui-blocks/index.js.map +0 -1
  353. package/dist/_members/primitives/version-map.json +0 -105
  354. package/dist/_members/primitives/workspace.js +0 -60
  355. package/dist/_members/primitives/workspace.js.map +0 -1
@@ -1,771 +0,0 @@
1
- /**
2
- * Director-onto-MCP adapter — turns the curated SSOT (curation.ts) into an
3
- * `ai`-SDK `ToolSet` the Director's author LLM can drive over the real `/v1`
4
- * network surface (the dogfood), instead of the in-process `buildDirectorTools`
5
- * store. One `ai` `tool()` per phase-1 curated name; each `execute()` runs the
6
- * op through the injected `Executor` (server.ts:registerCuratedTools is the
7
- * parallel SSOT consumer for the MCP-server transport).
8
- *
9
- * Correctness contracts preserved from buildTools.ts:107-200:
10
- * (a) execute() returns errors as a JSON-STRING tool output, never throws —
11
- * the LLM must SEE the error as tool output.
12
- * (b) images never leave execute() as content-shaped objects (T4).
13
- * (c/d) role filtering + dedup/progress/heartbeat stay external to tool-building.
14
- */
15
- import { z } from 'zod';
16
- import { tool } from 'ai';
17
- import { invokeOp, opById, bodySchemaFor, isOk, apiErrorFrom, fmtErr, safeParse, sniffImageMediaType, fetchPreviews, } from './core.js';
18
- import { CURATED_TOOLS } from './curation.js';
19
- import { INTERNAL_LOOP_TOOLS } from './internalLoopTools.js';
20
- import { waitForJob } from './wait.js';
21
- // Re-exported for surface MIRRORS (e.g. @cueframe/local-harness's
22
- // buildLocalToolSet): a mirror must serve the SAME names, descriptions and
23
- // operationIds as this adapter — importing the specs is the only non-drifting
24
- // way to do that.
25
- export { CURATED_TOOLS } from './curation.js';
26
- export { INTERNAL_LOOP_TOOLS } from './internalLoopTools.js';
27
- /**
28
- * B6 (spec 2026-07-11-preview-capture-unification §B6): INFRA-class error codes
29
- * the author/designer LLM cannot fix — there is no tool it could call to create
30
- * a missing scratch or revive a dead session. Returning these as Contract-3(a)
31
- * tool output makes the model flail (prod dogfood: ×49 scratch_not_found renders
32
- * ending in design-lock, 49 calls from the cause). A CLOSED set: adaptable
33
- * errors (bad params, over budget, timestamp_out_of_bounds, component compile
34
- * errors) keep the tool-output contract.
35
- */
36
- const INFRA_TOOL_ERROR_CODES = new Set([
37
- 'scratch_not_found',
38
- 'session_not_found',
39
- 'session_not_ready',
40
- // Version-gate timeout: the box's daemon/subscription is dead — no tool call
41
- // can revive it (2026-07-12: 234 dead renders, two 24-min blind designer
42
- // attempts before design-lock).
43
- 'session_version_timeout',
44
- ]);
45
- /**
46
- * The typed sentinel for infra-class tool failures. Thrown from a curated
47
- * tool's execute(); the AI SDK catches it into a `tool-error` step part, so the
48
- * throw ALONE changes nothing — the agent loop (authoring/agent.ts) detects the
49
- * sentinel STRUCTURALLY (name+infra, no package import — mcp↔authoring stay
50
- * decoupled per Constraint 3(d)), halts the run, and rethrows; the director
51
- * (mcpSurface) maps it to a nonRetryable ApplicationFailure so the candidate
52
- * fails loud with the REAL code instead of a design-lock 49 renders later.
53
- */
54
- export class InfraToolError extends Error {
55
- code;
56
- infra = true;
57
- constructor(code, message) {
58
- super(message);
59
- this.code = code;
60
- this.name = 'InfraToolError';
61
- }
62
- }
63
- /** Structural guard (mirror of the authoring-side local guard). */
64
- export function isInfraToolError(v) {
65
- return (v instanceof Error &&
66
- v.name === 'InfraToolError' &&
67
- v.infra === true &&
68
- typeof v.code === 'string');
69
- }
70
- /**
71
- * Classify a non-2xx op response: an infra-class code returns the sentinel to
72
- * THROW; anything else returns null (caller keeps the Contract-3(a) JSON-string
73
- * return). Pure + exported for tests. Parses the error envelope itself so it
74
- * has no dependency on ApiError's shape.
75
- */
76
- export function infraToolErrorFromResponse(res) {
77
- if (isOk(res.status))
78
- return null;
79
- let code;
80
- try {
81
- code = JSON.parse(res.text)?.error?.code;
82
- }
83
- catch {
84
- return null;
85
- }
86
- if (typeof code !== 'string' || !INFRA_TOOL_ERROR_CODES.has(code))
87
- return null;
88
- return new InfraToolError(code, fmtErr(apiErrorFrom(res)));
89
- }
90
- /** Default per-run in-loop budget — mirrors director.ts:282/290. */
91
- const DEFAULT_BUDGETS = { captures: 10, verifies: 3, styleViews: 4 };
92
- /** Async-job poll defaults: a verify renders eval beats + runs the vision judge
93
- * (~1-3 min); a preview is one still (~10-60s). One generous ceiling for both. */
94
- const JOB_POLL_MS = 4_000;
95
- const JOB_TIMEOUT_MS = 240_000;
96
- /**
97
- * Poll the generic jobs resource (GET /v1/jobs/{id}) until terminal or the
98
- * deadline. Mirrors wait.ts's loop, but returns the RAW job JSON so each
99
- * caller formats its own kind-specific result (verify → scores text,
100
- * preview → result.url still). 4xx while polling → failed (fail loud);
101
- * transient 5xx → keep polling.
102
- */
103
- async function pollJobToTerminal(ex, jobId, jobPoll) {
104
- const op = opById('getJob');
105
- const sleep = jobPoll?.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
106
- const pollMs = jobPoll?.pollMs ?? JOB_POLL_MS;
107
- const timeoutMs = jobPoll?.timeoutMs ?? JOB_TIMEOUT_MS;
108
- const deadline = Date.now() + timeoutMs;
109
- for (;;) {
110
- const res = await invokeOp(ex, op, () => jobId, undefined);
111
- if (!isOk(res.status)) {
112
- if (res.status >= 400 && res.status < 500) {
113
- return { outcome: 'failed', pollError: fmtErr(apiErrorFrom(res)) };
114
- }
115
- // transient 5xx: fall through to sleep + retry
116
- }
117
- else {
118
- const job = safeParse(res.text);
119
- const s = String(job?.status ?? '');
120
- if (s === 'succeeded')
121
- return { outcome: 'succeeded', job };
122
- if (s === 'failed')
123
- return { outcome: 'failed', job };
124
- }
125
- if (Date.now() + pollMs >= deadline)
126
- return { outcome: 'timeout' };
127
- await sleep(pollMs);
128
- }
129
- }
130
- /** Format a terminal verify job as the scores text the author acts on —
131
- * mirrors wait.ts's verify terminal formatting. */
132
- function formatVerifyResult(job) {
133
- const r = (job?.result ?? {});
134
- const lines = ['Verify complete.'];
135
- if (typeof r.composite === 'number')
136
- lines.push(`Composite score: ${r.composite}`);
137
- if (r.perCriterion && typeof r.perCriterion === 'object') {
138
- for (const [criterion, v] of Object.entries(r.perCriterion)) {
139
- if (typeof v?.score === 'number') {
140
- lines.push(`- ${criterion}: ${v.score}${v?.critique ? ` — ${v.critique}` : ''}`);
141
- }
142
- }
143
- }
144
- if (typeof r.critique === 'string' && r.critique.length > 0) {
145
- lines.push(`\nWorst-first critique: ${r.critique}`);
146
- }
147
- lines.push('\nFix the lowest criterion via apply_composition, then re-verify.');
148
- return lines.join('\n');
149
- }
150
- /**
151
- * Stream a presigned still to base64 — mirrors inLoopCapture.ts:173-174.
152
- *
153
- * `btoa` + chunking rather than `Buffer.from(buf).toString('base64')`: this
154
- * adapter now also builds tool sets inside the DESKTOP WEBVIEW (the local /v1
155
- * lane), where `Buffer` does not exist. `btoa` is present in Node ≥16, the
156
- * Convex isolate and every browser; the 8k chunk keeps `String.fromCharCode`
157
- * under its argument limit on multi-MB stills. Byte-identical output.
158
- */
159
- async function defaultFetchImage(url) {
160
- const buf = await (await fetch(url)).arrayBuffer();
161
- const bytes = new Uint8Array(buf);
162
- const chunks = [];
163
- for (let i = 0; i < bytes.length; i += 8192) {
164
- chunks.push(String.fromCharCode(...bytes.subarray(i, i + 8192)));
165
- }
166
- return btoa(chunks.join(''));
167
- }
168
- /**
169
- * Friendly path-arg names the adapter injects from `opts.session` and strips from
170
- * the tool schema. Any other path arg (e.g. `mediaItemId`) stays LLM-supplied.
171
- */
172
- const SESSION_PATH_ARGS = new Set(['projectId', 'sessionId']);
173
- /** Resolve a session-managed path arg from opts.session, else undefined. */
174
- function sessionPathValue(friendly, opts) {
175
- if (!opts?.session)
176
- return undefined;
177
- if (friendly === 'projectId')
178
- return opts.session.projectId;
179
- if (friendly === 'sessionId')
180
- return opts.session.sessionId;
181
- return undefined;
182
- }
183
- /**
184
- * Compute the effective request body for a tool. Under a session, every tool
185
- * that reads or writes "the composition being worked on" stamps
186
- * `body.session_id` so the op targets the session SCRATCH:
187
- * - `apply_composition` writes the scratch;
188
- * - `verify_composition` judges it. Before this, verifies resolved the
189
- * project's ACTIVE row — the session author's edits were invisible to its
190
- * own in-loop judge (the scratch-blind class, prod 2026-07-14; render_frame
191
- * had the same hole and stamps in buildRenderFrameTool).
192
- * Every other tool passes its body through untouched (bodyless stay bodyless).
193
- */
194
- const SESSION_STAMPED_TOOLS = new Set(['apply_composition', 'verify_composition']);
195
- function injectSession(spec, args, opts) {
196
- if (opts?.session && SESSION_STAMPED_TOOLS.has(spec.name)) {
197
- return { ...(args.body ?? {}), session_id: opts.session.sessionId };
198
- }
199
- return args.body;
200
- }
201
- /**
202
- * Vision inlining, shared by `render_frame` (whole-composition stills) and
203
- * `preview_component` (one graphic still). Fetch each presigned PNG url → base64
204
- * and return them RAW as `string[]`. Finding 3: a 2xx that yields ZERO usable
205
- * urls must NOT return an empty `string[]` — that becomes an empty
206
- * `{type:'content', value:[]}` block the model API can reject — so return a
207
- * JSON-string `{note}` (a TEXT tool result) instead. The base64 bytes never leave
208
- * execute() content-shaped (Constraint 3(b)); they become a vision block only in
209
- * `imageVisionModelOutput`.
210
- */
211
- async function inlineStillsOrNote(urls, fetchImage, emptyNote) {
212
- const out = [];
213
- for (const u of urls)
214
- if (u)
215
- out.push(await fetchImage(u));
216
- if (out.length === 0)
217
- return JSON.stringify({ note: emptyNote });
218
- return out;
219
- }
220
- /**
221
- * The `toModelOutput` shared by the vision tools: a base64 `string[]` becomes
222
- * image content blocks (the pixels the model SEES); anything else (an
223
- * `{error}` / `{note}` JSON string) renders as TEXT. The media type is SNIFFED
224
- * per image from its magic bytes (`sniffImageMediaType`), not hardcoded — PNG
225
- * stills stay png, JPEG exemplars label jpeg, so the adapter never mislabels the
226
- * bytes it inlines (and does not inherit buildTools.ts:37's hardcoded image/jpeg).
227
- */
228
- function imageVisionModelOutput({ output }) {
229
- return Array.isArray(output)
230
- ? {
231
- type: 'content',
232
- value: output.map((data) => ({
233
- type: 'image-data',
234
- mediaType: sniffImageMediaType(data),
235
- data,
236
- })),
237
- }
238
- : {
239
- type: 'text',
240
- value: typeof output === 'string' ? output : JSON.stringify(output),
241
- };
242
- }
243
- function isPreviewAugmented(v) {
244
- return !!v && typeof v === 'object' && v.__preview === true;
245
- }
246
- function previewVisionModelOutput({ output }) {
247
- if (isPreviewAugmented(output)) {
248
- return {
249
- type: 'content',
250
- value: [
251
- { type: 'text', text: output.text },
252
- ...output.images.map((data) => ({
253
- type: 'image-data',
254
- mediaType: sniffImageMediaType(data),
255
- data,
256
- })),
257
- ],
258
- };
259
- }
260
- return {
261
- type: 'text',
262
- value: typeof output === 'string' ? output : JSON.stringify(output),
263
- };
264
- }
265
- /**
266
- * `render_frame` vision special-case (T4). Renders whole-composition still(s) in
267
- * the warm box, fetches each presigned PNG, and inlines it as base64. The bytes
268
- * are returned RAW as `string[]` from execute() and only become a vision block in
269
- * `toModelOutput` — a content-shaped object leaving execute() would be JSON-
270
- * stringified by the AI SDK (~50k text tokens/image → window overflow) AND the
271
- * model still couldn't see the pixels (Constraint 3(b)).
272
- */
273
- function buildRenderFrameTool(spec, ex, budget, opts) {
274
- const op = opById(spec.operationId);
275
- const fetchImage = opts?.fetchImage ?? defaultFetchImage;
276
- // Path args (projectId/sessionId) come from the scratch session — never LLM-managed.
277
- const reverse = {};
278
- for (const [friendly, opParam] of Object.entries(spec.pathArgs ?? {})) {
279
- reverse[opParam] = friendly;
280
- }
281
- const mapArg = (p) => sessionPathValue(reverse[p], opts) ?? undefined;
282
- return tool({
283
- description: spec.description,
284
- // composition is omitted; session_id (stamped below) makes the server render
285
- // the session SCRATCH — the composition this agent is actually editing. The
286
- // box cutover left this body bare and previewFrame fell back to the project's
287
- // ACTIVE row, so the designer refined against stills WITHOUT its own edits
288
- // until the capture budget refused (prod 2026-07-14, rs7fanev…).
289
- inputSchema: z.object({ body: z.object({ timestamps: z.array(z.number()).min(1) }) }),
290
- // K4: teach BATCHED inspection — several timestamps bracketing the edited
291
- // window in ONE call (the measured anti-pattern: repeated single-frame
292
- // renders, each costing a capture from the same budget).
293
- inputExamples: [{ input: { body: { timestamps: [14.2, 14.8, 15.6] } } }],
294
- execute: async (args) => {
295
- // Budget (T5): a capture costs COGS — over budget returns a tool-output error, never throws.
296
- if (++budget.used.captures > budget.caps.captures) {
297
- return JSON.stringify({
298
- error: `capture budget exhausted; you have used all ${budget.caps.captures} in-loop renders — finalize from your current composition.`,
299
- });
300
- }
301
- const res = await invokeOp(ex, op, mapArg, {
302
- timestamps: args.body.timestamps,
303
- // Vision-bound shrink (2026-07-17 trace audit): this tool is the AGENT's
304
- // eyes — full-res PNG stills base64'd into context cost +10k tokens per
305
- // look and slower renders. The judge grades jpeg/0.5/70; the agent sees
306
- // the same. The PUBLIC preview_frame (human preview) stays full-res —
307
- // this body rides the dedicated internal-loop builder only.
308
- imageFormat: 'jpeg',
309
- scale: 0.5,
310
- jpegQuality: 70,
311
- ...(opts?.session ? { session_id: opts.session.sessionId } : {}),
312
- });
313
- // B6: an INFRA-class code (dead scratch/session) is unfixable by the model —
314
- // throw the sentinel (loop-halt + loud candidate failure), never tool output.
315
- const infra = infraToolErrorFromResponse(res);
316
- if (infra)
317
- throw infra;
318
- // Contract 3(a): any OTHER non-2xx is RETURNED as a JSON-string, never thrown / never an image.
319
- if (!isOk(res.status))
320
- return JSON.stringify({ error: fmtErr(apiErrorFrom(res)) });
321
- const json = safeParse(res.text);
322
- // The capture budget was already charged above; a zero-still 2xx returns a
323
- // {note} (charge stands) rather than an empty content block (Finding 3).
324
- return inlineStillsOrNote((json?.stills ?? []).map((s) => s.url), fetchImage, 'no stills returned for the requested timestamps');
325
- },
326
- toModelOutput: imageVisionModelOutput,
327
- });
328
- }
329
- /**
330
- * `preview_component` vision special-case. Renders ONE org-installed component as
331
- * a single still in the warm box and returns a presigned PNG `{ url }` — the
332
- * designer's author→preview→fix loop for a graphic. WITHOUT this the generic tool
333
- * path returns the `{url}` JSON as TEXT and the designer LLM never SEES the
334
- * pixels; here we inline it exactly like render_frame (base64 `string[]` from
335
- * execute → a vision block only in `toModelOutput`). Un-budgeted (a preview is not
336
- * charged against the in-loop capture cap; the agent's step cap is the backstop).
337
- * A non-2xx — the 422 `component_does_not_compile` / `component_runtime_error` the
338
- * designer self-fixes from — is RETURNED as a JSON `{error}` string, never thrown, never an image
339
- * (Constraint 3(a)); a 2xx with no url returns a `{note}` (Finding 3), never an
340
- * empty content block. The body schema (componentId + params/width/height) comes
341
- * from the manifest, so a param rename fails loud at codegen, not at runtime.
342
- */
343
- function buildPreviewComponentTool(spec, ex, opts) {
344
- const op = opById(spec.operationId);
345
- const fetchImage = opts?.fetchImage ?? defaultFetchImage;
346
- // Path args (projectId/sessionId) come from the scratch session — never LLM-managed.
347
- const reverse = {};
348
- for (const [friendly, opParam] of Object.entries(spec.pathArgs ?? {})) {
349
- reverse[opParam] = friendly;
350
- }
351
- const shape = {};
352
- for (const friendly of Object.keys(spec.pathArgs ?? {})) {
353
- // Session-managed path args are injected from opts.session — never exposed.
354
- if (opts?.session && SESSION_PATH_ARGS.has(friendly))
355
- continue;
356
- shape[friendly] = z.string().describe(`${friendly} (path).`);
357
- }
358
- const bodySchema = bodySchemaFor(op);
359
- if (bodySchema)
360
- shape.body = bodySchema;
361
- return tool({
362
- description: spec.description,
363
- inputSchema: z.object(shape),
364
- execute: async (args) => {
365
- const res = await invokeOp(ex, op, (p) => sessionPathValue(reverse[p], opts) ?? args[reverse[p]], args.body);
366
- // Contract 3(a): a non-2xx (422 component_does_not_compile /
367
- // component_runtime_error / 5xx) is RETURNED as a JSON-string {error}, never
368
- // thrown / never an image — the designer reads the compile-or-runtime error
369
- // message and fixes the source via create_component. EXCEPT infra-class
370
- // codes (B6): a dead session is not author-fixable — sentinel throw.
371
- {
372
- const infra = infraToolErrorFromResponse(res);
373
- if (infra)
374
- throw infra;
375
- }
376
- if (!isOk(res.status))
377
- return JSON.stringify({ error: fmtErr(apiErrorFrom(res)) });
378
- const json = safeParse(res.text);
379
- // Async-jobs migration: the op ENQUEUES a preview job and returns a
380
- // receipt. The designer has no wait_job, so BLOCK here until terminal and
381
- // inline the resulting still (a sync {url} response — older API — still
382
- // takes the fast path).
383
- let url = json?.url;
384
- if (!url && json?.jobId) {
385
- const done = await pollJobToTerminal(ex, json.jobId, opts?.jobPoll);
386
- if (done.outcome === 'failed') {
387
- const err = done.pollError ??
388
- (done.job?.error
389
- ? `${done.job.error.code ?? 'preview_failed'}: ${done.job.error.message ?? ''}`
390
- : 'preview job failed');
391
- // The author-fixable compile/runtime message rides job.error — return
392
- // it as {error} text so the designer fixes the source via create_component.
393
- return JSON.stringify({ error: err });
394
- }
395
- if (done.outcome === 'timeout') {
396
- return JSON.stringify({
397
- note: `component preview still rendering after ${Math.round((opts?.jobPoll?.timeoutMs ?? JOB_TIMEOUT_MS) / 1000)}s — proceed, or re-preview later`,
398
- });
399
- }
400
- url = done.job?.result?.url;
401
- }
402
- return inlineStillsOrNote([url], fetchImage, 'component preview returned no still url');
403
- },
404
- toModelOutput: imageVisionModelOutput,
405
- });
406
- }
407
- /**
408
- * `verify_composition` blocking special-case. The API op ENQUEUES the judge and
409
- * returns a receipt ("call wait_job…") — but wait_job is NOT on the curated
410
- * author/designer surface, so via the generic tool path the agent can never
411
- * read its own score (the 2026-07-07 prod LBO run called verify once and the
412
- * verdict evaporated). Here the tool blocks until the verify job is terminal
413
- * and returns the per-criterion scores + worst-first critique as TEXT — one
414
- * call, one verdict, same contract as the in-process score_composition.
415
- * Budgeted (a verify = eval-beat renders + the vision judge).
416
- */
417
- function buildVerifyCompositionTool(spec, ex, budget, opts) {
418
- const op = opById(spec.operationId);
419
- const onProgress = opts?.onProgress;
420
- const reverse = {};
421
- for (const [friendly, opParam] of Object.entries(spec.pathArgs ?? {})) {
422
- reverse[opParam] = friendly;
423
- }
424
- const shape = {};
425
- for (const friendly of Object.keys(spec.pathArgs ?? {})) {
426
- if (opts?.session && SESSION_PATH_ARGS.has(friendly))
427
- continue;
428
- shape[friendly] = z.string().describe(`${friendly} (path).`);
429
- }
430
- const bodySchema = bodySchemaFor(op);
431
- if (bodySchema)
432
- shape.body = bodySchema;
433
- return tool({
434
- description: 'Score the current composition on the judge\'s own rubric — BLOCKS until the scores are ready (1-3 min) and returns per-criterion scores 0-10 (editorial / spatial / brand / caption), the weighted composite, and a worst-first critique. Fix the lowest criterion via apply_composition, then re-verify. Do NOT apply/render while it runs.',
435
- inputSchema: z.object(shape),
436
- execute: async (args) => {
437
- if (++budget.used.verifies > budget.caps.verifies) {
438
- return JSON.stringify({
439
- error: `verify budget exhausted; you have used all ${budget.caps.verifies} in-loop verifies — commit your best composition.`,
440
- });
441
- }
442
- const toolCallId = `tc_${crypto.randomUUID().slice(0, 8)}`;
443
- onProgress?.({
444
- type: 'tool-call',
445
- agent: 'router',
446
- toolName: spec.name,
447
- args,
448
- toolCallId,
449
- timestamp: Date.now(),
450
- });
451
- const finish = (output, ok) => {
452
- onProgress?.({
453
- type: 'tool-result',
454
- agent: 'router',
455
- toolName: spec.name,
456
- success: ok,
457
- message: output.slice(0, 200),
458
- toolCallId,
459
- timestamp: Date.now(),
460
- });
461
- return output;
462
- };
463
- const res = await invokeOp(ex, op, (p) => sessionPathValue(reverse[p], opts) ?? args[reverse[p]], injectSession(spec, args, opts));
464
- {
465
- // B6: infra-class enqueue failure (dead session) — sentinel throw.
466
- const infra = infraToolErrorFromResponse(res);
467
- if (infra)
468
- throw infra;
469
- }
470
- if (!isOk(res.status)) {
471
- return finish(JSON.stringify({ error: fmtErr(apiErrorFrom(res)) }), false);
472
- }
473
- const receipt = safeParse(res.text);
474
- if (!receipt?.jobId) {
475
- // Older sync API shape (scores inline) — pass it through unchanged.
476
- return finish(res.text || 'verify returned no result', true);
477
- }
478
- const done = await pollJobToTerminal(ex, receipt.jobId, opts?.jobPoll);
479
- if (done.outcome === 'succeeded')
480
- return finish(formatVerifyResult(done.job), true);
481
- if (done.outcome === 'timeout') {
482
- return finish(JSON.stringify({
483
- error: `verify still running after ${Math.round((opts?.jobPoll?.timeoutMs ?? JOB_TIMEOUT_MS) / 1000)}s — proceed with your best judgment; the final judge scores the cut regardless.`,
484
- }), false);
485
- }
486
- const err = done.pollError ??
487
- (done.job?.error
488
- ? `${done.job.error.code ?? 'verify_failed'}: ${done.job.error.message ?? ''}`
489
- : 'verify job failed');
490
- return finish(JSON.stringify({ error: err }), false);
491
- },
492
- });
493
- }
494
- /**
495
- * `view_style_reference` vision special-case (T3, brand-kit-from-inspiration).
496
- * Presigns the BOUND brand kit's inspiration exemplar frames (optionally scoped to
497
- * one motif) and inlines them as base64 `string[]` — the reference pixels the maker
498
- * conditions on and the judge grades against. The kit id comes from `opts.brandKitId`
499
- * (the project's bound kit, threaded by the director), NEVER the LLM — so the tool
500
- * cannot peek at another project's kit. No kit bound ⇒ a `{note}` (not an error: the
501
- * kit is optional). Budgeted (`styleViews`): the vision window is finite, so past the
502
- * cap it returns a tool-output error (never throws — Constraint 3(a)) so the maker
503
- * designs from what it has already seen. Same base64→vision contract as render_frame.
504
- */
505
- function buildViewStyleReferenceTool(spec, ex, budget, opts) {
506
- const op = opById(spec.operationId);
507
- const fetchImage = opts?.fetchImage ?? defaultFetchImage;
508
- return tool({
509
- description: spec.description,
510
- inputSchema: z.object({
511
- motifId: z.string().optional().describe('Filter to the frames this motif was observed in.'),
512
- }),
513
- execute: async (args) => {
514
- if (!opts?.brandKitId) {
515
- return JSON.stringify({ note: 'no brand kit bound to this project — no style reference available' });
516
- }
517
- if (++budget.used.styleViews > budget.caps.styleViews) {
518
- return JSON.stringify({ error: `style-reference budget exhausted (${budget.caps.styleViews} views) — design from what you have seen` });
519
- }
520
- const res = await invokeOp(ex, op, () => opts.brandKitId, { ...(args.motifId ? { motifId: args.motifId } : {}), limit: 6 });
521
- {
522
- const infra = infraToolErrorFromResponse(res);
523
- if (infra)
524
- throw infra;
525
- }
526
- if (!isOk(res.status))
527
- return JSON.stringify({ error: fmtErr(apiErrorFrom(res)) });
528
- const json = safeParse(res.text);
529
- return inlineStillsOrNote((json?.exemplars ?? []).map((e) => e.url), fetchImage, 'kit has no exemplar frames');
530
- },
531
- toModelOutput: imageVisionModelOutput,
532
- });
533
- }
534
- const WAIT_KINDS = [
535
- 'render',
536
- 'compose',
537
- 'suggestions',
538
- 'verify',
539
- 'preview',
540
- 'brand_kit_extract',
541
- 'consult',
542
- ];
543
- /**
544
- * `wait_job` — the adapter twin of server.ts:registerWaitJob, over the SAME
545
- * `waitForJob` poll loop (one implementation, two transports). It is not a
546
- * generic single-op tool: `waitForJob` picks the status op PER KIND (wait.ts
547
- * `KINDS`), so `spec.operationId` is representative only and is never invoked
548
- * here.
549
- *
550
- * BOUNDED on purpose. The MCP transport caps this with `waitCapMs` because a
551
- * 30-minute synchronous poll outlives the request; the adapter's callers are
552
- * Convex actions and Temporal activities with the same problem, so the ceiling
553
- * is `opts.jobPoll.timeoutMs` (default `JOB_TIMEOUT_MS`) and the caller's own
554
- * `timeoutMs` may only lower it. Hitting the window is a CONTINUATION, not a
555
- * failure — the returned text says to call again with the same arguments.
556
- */
557
- function buildWaitJobTool(spec, ex, opts) {
558
- const onProgress = opts?.onProgress;
559
- const capMs = opts?.jobPoll?.timeoutMs ?? JOB_TIMEOUT_MS;
560
- const fetchImage = opts?.fetchImage;
561
- return tool({
562
- description: spec.description,
563
- inputSchema: z.object({
564
- kind: z
565
- .enum(WAIT_KINDS)
566
- .describe('What to wait on: a render job, a compose job, a consult advisory, AI clip-suggestion analysis, or a generic async job (verify / preview / brand_kit_extract — the kind is named in the enqueue receipt).'),
567
- id: z.string().describe('The job id from the enqueue call (renderId / composeJobId / jobId / mediaItemId for suggestions).'),
568
- projectId: z.string().optional().describe('Required for render / compose / consult (their status routes are project-scoped).'),
569
- timeoutMs: z
570
- .number()
571
- .optional()
572
- .describe(`Maximum wait in ms. Capped at ${capMs}; a longer value is clamped, not honoured.`),
573
- }),
574
- execute: async (args) => {
575
- const toolCallId = `tc_${crypto.randomUUID().slice(0, 8)}`;
576
- onProgress?.({
577
- type: 'tool-call',
578
- agent: 'router',
579
- toolName: spec.name,
580
- args,
581
- toolCallId,
582
- timestamp: Date.now(),
583
- });
584
- const finish = (output, ok) => {
585
- onProgress?.({
586
- type: 'tool-result',
587
- agent: 'router',
588
- toolName: spec.name,
589
- success: ok,
590
- message: output.slice(0, 200),
591
- toolCallId,
592
- timestamp: Date.now(),
593
- });
594
- return output;
595
- };
596
- // The project-scoped kinds cannot be polled without a projectId — say so
597
- // instead of issuing a request to `/projects/undefined/...`.
598
- if (!args.projectId && (args.kind === 'render' || args.kind === 'compose' || args.kind === 'consult')) {
599
- return finish(JSON.stringify({ error: `wait_job(kind="${args.kind}") requires a projectId.` }), false);
600
- }
601
- const deadline = Date.now() + Math.min(args.timeoutMs ?? capMs, capMs);
602
- const res = await waitForJob(ex, args.kind, args.id, args.projectId, deadline, opts?.jobPoll?.sleep || opts?.jobPoll?.pollMs
603
- ? { ...(opts.jobPoll?.sleep ? { sleep: opts.jobPoll.sleep } : {}), ...(opts.jobPoll?.pollMs ? { pollMs: opts.jobPoll.pollMs } : {}) }
604
- : undefined);
605
- // An async tool's PIXELS arrive here, not at the enqueue call (a 202 carries
606
- // only a jobId). Inline them the same way spec.preview does on the generic
607
- // path, or the agent judges a preview it was only told about.
608
- if (res.mediaUrls?.length) {
609
- const images = await fetchPreviews(res.mediaUrls, 12, fetchImage ? { fetchOne: fetchImage } : undefined);
610
- if (images.length) {
611
- finish(res.text, res.ok);
612
- return { __preview: true, text: res.text, images };
613
- }
614
- }
615
- return finish(res.text, res.ok);
616
- },
617
- toModelOutput: previewVisionModelOutput,
618
- });
619
- }
620
- /** Build one `ai` tool from a curated spec, executing through `ex`. */
621
- function buildOneTool(spec, ex, budget, opts) {
622
- if (spec.name === 'render_frame')
623
- return buildRenderFrameTool(spec, ex, budget, opts);
624
- // wait_job polls a DIFFERENT status op per kind — it has no single op to
625
- // dispatch, so the generic path cannot build it.
626
- if (spec.name === 'wait_job')
627
- return buildWaitJobTool(spec, ex, opts);
628
- // preview_component returns a presigned PNG `{ url }`; inline it so the designer
629
- // LLM SEES the graphic (the generic path below would return the url as TEXT).
630
- if (spec.name === 'preview_component')
631
- return buildPreviewComponentTool(spec, ex, opts);
632
- // verify_composition enqueues the judge; block until terminal and return the
633
- // SCORES (the surface has no wait_job — a receipt is a verdict the LLM can
634
- // never read).
635
- if (spec.name === 'verify_composition')
636
- return buildVerifyCompositionTool(spec, ex, budget, opts);
637
- // view_style_reference presigns the BOUND kit's exemplar frames and inlines
638
- // them as vision blocks (the reference pixels) — the generic path would return
639
- // the {exemplars:[{url}]} JSON as TEXT and the maker would never SEE the frames.
640
- if (spec.name === 'view_style_reference')
641
- return buildViewStyleReferenceTool(spec, ex, budget, opts);
642
- const op = opById(spec.operationId);
643
- const onProgress = opts?.onProgress;
644
- // friendly input arg name → op path-param name, reversed for mapArg lookup.
645
- const reverse = {};
646
- for (const [friendly, opParam] of Object.entries(spec.pathArgs ?? {})) {
647
- reverse[opParam] = friendly;
648
- }
649
- const shape = {};
650
- for (const friendly of Object.keys(spec.pathArgs ?? {})) {
651
- // Session-managed path args are injected from opts.session — never exposed.
652
- if (opts?.session && SESSION_PATH_ARGS.has(friendly))
653
- continue;
654
- shape[friendly] = z.string().describe(`${friendly} (path).`);
655
- }
656
- // Query filters (curation queryArgs): optional strings threaded onto the
657
- // request URL — the arg name IS the query-param name. Without this a
658
- // description teaching a filter returned the UNFILTERED page silently.
659
- for (const [qArg, qDesc] of Object.entries(spec.queryArgs ?? {})) {
660
- shape[qArg] = z.string().optional().describe(qDesc);
661
- }
662
- const bodySchema = bodySchemaFor(op);
663
- if (bodySchema)
664
- shape.body = bodySchema;
665
- // K4 examples are authored for the SESSION-injected surface (path args
666
- // hidden). On a sessionless build the path args are part of the schema, and
667
- // Anthropic VALIDATES every example against input_schema — one example
668
- // missing a required `projectId` 400s the entire request ("tools.N.custom:
669
- // Example at index 0 is invalid"). Keep only examples that carry every
670
- // exposed path arg; with a session none are exposed, so all examples pass
671
- // through unchanged (the Director path is unaffected).
672
- const exposedPathArgs = Object.keys(spec.pathArgs ?? {}).filter((friendly) => !(opts?.session && SESSION_PATH_ARGS.has(friendly)));
673
- const schemaSafeExamples = spec.inputExamples?.filter((exm) => exposedPathArgs.every((a) => exm.input[a] !== undefined));
674
- return tool({
675
- description: spec.description,
676
- inputSchema: z.object(shape),
677
- // K4: worked examples from the curated spec (apply_composition teaches the
678
- // targeted patch). Serialized as Anthropic input_examples; the provider
679
- // adds the advanced-tool-use beta itself.
680
- ...(schemaSafeExamples?.length ? { inputExamples: schemaSafeExamples } : {}),
681
- execute: async (args) => {
682
- // Budgets live in the special-cased tools (render_frame / verify_composition);
683
- // every generic read/mutate tool (apply_composition, get_media_context, …) is
684
- // un-budgeted.
685
- const toolCallId = `tc_${crypto.randomUUID().slice(0, 8)}`;
686
- // Progress: tool-call (before the network op — buildTools.ts:131-134).
687
- onProgress?.({
688
- type: 'tool-call',
689
- agent: 'router',
690
- toolName: spec.name,
691
- args,
692
- toolCallId,
693
- timestamp: Date.now(),
694
- });
695
- const queryPairs = Object.keys(spec.queryArgs ?? {})
696
- .filter((qArg) => args[qArg] !== undefined && args[qArg] !== null && args[qArg] !== '')
697
- .map((qArg) => `${encodeURIComponent(qArg)}=${encodeURIComponent(String(args[qArg]))}`);
698
- const res = await invokeOp(ex, op, (p) => sessionPathValue(reverse[p], opts) ?? args[reverse[p]], injectSession(spec, args, opts), undefined, queryPairs.length > 0 ? queryPairs.join('&') : undefined);
699
- const ok = isOk(res.status);
700
- const json = ok && res.text ? safeParse(res.text) : undefined;
701
- // Contract 3(a): a non-2xx is RETURNED as a JSON-string tool output, NOT thrown.
702
- const output = ok
703
- ? spec.okText
704
- ? spec.okText(args)
705
- : spec.okFormat
706
- ? spec.okFormat(json ?? {}, args)
707
- : res.text || `${op.method} → ${res.status}`
708
- : JSON.stringify({ error: fmtErr(apiErrorFrom(res)) });
709
- // Progress: tool-result (message capped at 200 chars — buildTools.ts:160).
710
- onProgress?.({
711
- type: 'tool-result',
712
- agent: 'router',
713
- toolName: spec.name,
714
- success: ok,
715
- message: output.slice(0, 200),
716
- toolCallId,
717
- timestamp: Date.now(),
718
- });
719
- // spec.preview — the generic-path twin of server.ts:202: attach the
720
- // pixels the JSON already links (preview_frame stills, checkpoint
721
- // storyboards) so the model judges what it can SEE. ADDITIVE (text
722
- // unchanged), gated by `attach` BEFORE any bytes move, and a failed
723
- // fetch drops silently — a dead thumbnail never fails the call it
724
- // decorates. Audio previews stay URL-as-text (tool results carry
725
- // image blocks only).
726
- if (ok && spec.preview && json && (spec.preview.attach?.(json) ?? true)) {
727
- const kind = typeof spec.preview.kind === 'function'
728
- ? spec.preview.kind(json)
729
- : spec.preview.kind ?? 'image';
730
- if (kind === 'image') {
731
- // fetchPreviews (not defaultFetchImage): isolate-safe base64 — the
732
- // Convex V8 runtime has no Buffer — plus the byte budget and cache.
733
- const images = await fetchPreviews(spec.preview.urls(json), spec.preview.cap ?? 12, opts?.fetchImage ? { fetchOne: opts.fetchImage } : undefined);
734
- if (images.length)
735
- return { __preview: true, text: output, images };
736
- }
737
- }
738
- return output;
739
- },
740
- ...(spec.preview ? { toModelOutput: previewVisionModelOutput } : {}),
741
- });
742
- }
743
- /**
744
- * Build an `ai` `ToolSet` from the curated SSOT, filtered to the caller's
745
- * `allowedNames`. Uses the REAL generated manifest (via opById) so a
746
- * missing/renamed operationId fails loud — that is the drift signal.
747
- */
748
- export function buildCuratedToolSet(ex, opts) {
749
- const allowed = new Set(opts.allowedNames);
750
- // One budget per build → one budget spans the whole author run (T5). A fresh
751
- // ToolSet is built per author invocation, so counters reset per run — matching
752
- // the in-process per-run caps (director.ts:282/290).
753
- const budget = {
754
- caps: opts?.budgets ?? DEFAULT_BUDGETS,
755
- used: { captures: 0, verifies: 0, styleViews: 0 },
756
- };
757
- const tools = {};
758
- // Internal loop entries FIRST, then the public curated set — the in-loop
759
- // session-scoped names (A11/A12-internal) resolve even though they left the
760
- // client surface at the 2026-07 verb cutover. `preview_component` exists in
761
- // BOTH (public = sessionless managed box; internal = the run's own box) —
762
- // internal wins here because this builder only serves the in-loop surface.
763
- for (const spec of [...INTERNAL_LOOP_TOOLS, ...CURATED_TOOLS]) {
764
- if (!allowed.has(spec.name))
765
- continue;
766
- if (tools[spec.name])
767
- continue;
768
- tools[spec.name] = buildOneTool(spec, ex, budget, opts);
769
- }
770
- return tools;
771
- }