@agent-native/creative-context 0.1.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 (618) hide show
  1. package/README.md +108 -0
  2. package/agent-native.package.json +104 -0
  3. package/dist/actions/confirm-canonical-logo.d.ts +6 -0
  4. package/dist/actions/confirm-canonical-logo.d.ts.map +1 -0
  5. package/dist/actions/confirm-canonical-logo.js +19 -0
  6. package/dist/actions/confirm-canonical-logo.js.map +1 -0
  7. package/dist/actions/continue-context-import.d.ts +7 -0
  8. package/dist/actions/continue-context-import.d.ts.map +1 -0
  9. package/dist/actions/continue-context-import.js +10 -0
  10. package/dist/actions/continue-context-import.js.map +1 -0
  11. package/dist/actions/creative-context-a2a.d.ts +10 -0
  12. package/dist/actions/creative-context-a2a.d.ts.map +1 -0
  13. package/dist/actions/creative-context-a2a.js +66 -0
  14. package/dist/actions/creative-context-a2a.js.map +1 -0
  15. package/dist/actions/get-brand-profile.d.ts +33 -0
  16. package/dist/actions/get-brand-profile.d.ts.map +1 -0
  17. package/dist/actions/get-brand-profile.js +13 -0
  18. package/dist/actions/get-brand-profile.js.map +1 -0
  19. package/dist/actions/get-context-import-status.d.ts +22 -0
  20. package/dist/actions/get-context-import-status.d.ts.map +1 -0
  21. package/dist/actions/get-context-import-status.js +12 -0
  22. package/dist/actions/get-context-import-status.js.map +1 -0
  23. package/dist/actions/get-context-item.d.ts +2 -0
  24. package/dist/actions/get-context-item.d.ts.map +1 -0
  25. package/dist/actions/get-context-item.js +2 -0
  26. package/dist/actions/get-context-item.js.map +1 -0
  27. package/dist/actions/get-context-pack.d.ts +7 -0
  28. package/dist/actions/get-context-pack.d.ts.map +1 -0
  29. package/dist/actions/get-context-pack.js +12 -0
  30. package/dist/actions/get-context-pack.js.map +1 -0
  31. package/dist/actions/get-creative-context.d.ts +119 -0
  32. package/dist/actions/get-creative-context.d.ts.map +1 -0
  33. package/dist/actions/get-creative-context.js +112 -0
  34. package/dist/actions/get-creative-context.js.map +1 -0
  35. package/dist/actions/index.d.ts +3 -0
  36. package/dist/actions/index.d.ts.map +1 -0
  37. package/dist/actions/index.js +63 -0
  38. package/dist/actions/index.js.map +1 -0
  39. package/dist/actions/infer-brand-dna.d.ts +52 -0
  40. package/dist/actions/infer-brand-dna.d.ts.map +1 -0
  41. package/dist/actions/infer-brand-dna.js +13 -0
  42. package/dist/actions/infer-brand-dna.js.map +1 -0
  43. package/dist/actions/list-canonical-logo-candidates.d.ts +9 -0
  44. package/dist/actions/list-canonical-logo-candidates.d.ts.map +1 -0
  45. package/dist/actions/list-canonical-logo-candidates.js +82 -0
  46. package/dist/actions/list-canonical-logo-candidates.js.map +1 -0
  47. package/dist/actions/list-context-connections.d.ts +22 -0
  48. package/dist/actions/list-context-connections.d.ts.map +1 -0
  49. package/dist/actions/list-context-connections.js +43 -0
  50. package/dist/actions/list-context-connections.js.map +1 -0
  51. package/dist/actions/list-context-packs.d.ts +10 -0
  52. package/dist/actions/list-context-packs.d.ts.map +1 -0
  53. package/dist/actions/list-context-packs.js +16 -0
  54. package/dist/actions/list-context-packs.js.map +1 -0
  55. package/dist/actions/list-context-sources.d.ts +12 -0
  56. package/dist/actions/list-context-sources.d.ts.map +1 -0
  57. package/dist/actions/list-context-sources.js +20 -0
  58. package/dist/actions/list-context-sources.js.map +1 -0
  59. package/dist/actions/list-context-suggestions.d.ts +13 -0
  60. package/dist/actions/list-context-suggestions.d.ts.map +1 -0
  61. package/dist/actions/list-context-suggestions.js +28 -0
  62. package/dist/actions/list-context-suggestions.js.map +1 -0
  63. package/dist/actions/manage-brand-profile.d.ts +28 -0
  64. package/dist/actions/manage-brand-profile.d.ts.map +1 -0
  65. package/dist/actions/manage-brand-profile.js +47 -0
  66. package/dist/actions/manage-brand-profile.js.map +1 -0
  67. package/dist/actions/manage-context-pack.d.ts +33 -0
  68. package/dist/actions/manage-context-pack.d.ts.map +1 -0
  69. package/dist/actions/manage-context-pack.js +65 -0
  70. package/dist/actions/manage-context-pack.js.map +1 -0
  71. package/dist/actions/manage-context-source.d.ts +51 -0
  72. package/dist/actions/manage-context-source.d.ts.map +1 -0
  73. package/dist/actions/manage-context-source.js +137 -0
  74. package/dist/actions/manage-context-source.js.map +1 -0
  75. package/dist/actions/manage-layout-template.d.ts +13 -0
  76. package/dist/actions/manage-layout-template.d.ts.map +1 -0
  77. package/dist/actions/manage-layout-template.js +43 -0
  78. package/dist/actions/manage-layout-template.js.map +1 -0
  79. package/dist/actions/preview-context-import.d.ts +23 -0
  80. package/dist/actions/preview-context-import.d.ts.map +1 -0
  81. package/dist/actions/preview-context-import.js +57 -0
  82. package/dist/actions/preview-context-import.js.map +1 -0
  83. package/dist/actions/process-context-purge.d.ts +22 -0
  84. package/dist/actions/process-context-purge.d.ts.map +1 -0
  85. package/dist/actions/process-context-purge.js +19 -0
  86. package/dist/actions/process-context-purge.js.map +1 -0
  87. package/dist/actions/propose-brand-dna.d.ts +15 -0
  88. package/dist/actions/propose-brand-dna.d.ts.map +1 -0
  89. package/dist/actions/propose-brand-dna.js +19 -0
  90. package/dist/actions/propose-brand-dna.js.map +1 -0
  91. package/dist/actions/propose-canonical-logo.d.ts +9 -0
  92. package/dist/actions/propose-canonical-logo.d.ts.map +1 -0
  93. package/dist/actions/propose-canonical-logo.js +16 -0
  94. package/dist/actions/propose-canonical-logo.js.map +1 -0
  95. package/dist/actions/publish-brand-dna.d.ts +13 -0
  96. package/dist/actions/publish-brand-dna.d.ts.map +1 -0
  97. package/dist/actions/publish-brand-dna.js +23 -0
  98. package/dist/actions/publish-brand-dna.js.map +1 -0
  99. package/dist/actions/recommend-context-roots.d.ts +14 -0
  100. package/dist/actions/recommend-context-roots.d.ts.map +1 -0
  101. package/dist/actions/recommend-context-roots.js +22 -0
  102. package/dist/actions/recommend-context-roots.js.map +1 -0
  103. package/dist/actions/record-context-feedback.d.ts +10 -0
  104. package/dist/actions/record-context-feedback.d.ts.map +1 -0
  105. package/dist/actions/record-context-feedback.js +14 -0
  106. package/dist/actions/record-context-feedback.js.map +1 -0
  107. package/dist/actions/review-context-items.d.ts +35 -0
  108. package/dist/actions/review-context-items.d.ts.map +1 -0
  109. package/dist/actions/review-context-items.js +65 -0
  110. package/dist/actions/review-context-items.js.map +1 -0
  111. package/dist/actions/run-embedding-bakeoff.d.ts +15 -0
  112. package/dist/actions/run-embedding-bakeoff.d.ts.map +1 -0
  113. package/dist/actions/run-embedding-bakeoff.js +72 -0
  114. package/dist/actions/run-embedding-bakeoff.js.map +1 -0
  115. package/dist/actions/search-creative-context.d.ts +75 -0
  116. package/dist/actions/search-creative-context.d.ts.map +1 -0
  117. package/dist/actions/search-creative-context.js +41 -0
  118. package/dist/actions/search-creative-context.js.map +1 -0
  119. package/dist/actions/set-brand-dna.d.ts +15 -0
  120. package/dist/actions/set-brand-dna.d.ts.map +1 -0
  121. package/dist/actions/set-brand-dna.js +19 -0
  122. package/dist/actions/set-brand-dna.js.map +1 -0
  123. package/dist/actions/start-context-enrichment.d.ts +10 -0
  124. package/dist/actions/start-context-enrichment.d.ts.map +1 -0
  125. package/dist/actions/start-context-enrichment.js +46 -0
  126. package/dist/actions/start-context-enrichment.js.map +1 -0
  127. package/dist/actions/start-context-import.d.ts +9 -0
  128. package/dist/actions/start-context-import.d.ts.map +1 -0
  129. package/dist/actions/start-context-import.js +36 -0
  130. package/dist/actions/start-context-import.js.map +1 -0
  131. package/dist/client/CreativeContextChip.d.ts +13 -0
  132. package/dist/client/CreativeContextChip.d.ts.map +1 -0
  133. package/dist/client/CreativeContextChip.js +45 -0
  134. package/dist/client/CreativeContextChip.js.map +1 -0
  135. package/dist/client/CreativeContextPanel.d.ts +131 -0
  136. package/dist/client/CreativeContextPanel.d.ts.map +1 -0
  137. package/dist/client/CreativeContextPanel.js +778 -0
  138. package/dist/client/CreativeContextPanel.js.map +1 -0
  139. package/dist/client/CreativeContextSettingsLink.d.ts +4 -0
  140. package/dist/client/CreativeContextSettingsLink.d.ts.map +1 -0
  141. package/dist/client/CreativeContextSettingsLink.js +8 -0
  142. package/dist/client/CreativeContextSettingsLink.js.map +1 -0
  143. package/dist/client/actions.d.ts +256 -0
  144. package/dist/client/actions.d.ts.map +1 -0
  145. package/dist/client/actions.js +89 -0
  146. package/dist/client/actions.js.map +1 -0
  147. package/dist/client/agent-tab.d.ts +9 -0
  148. package/dist/client/agent-tab.d.ts.map +1 -0
  149. package/dist/client/agent-tab.js +32 -0
  150. package/dist/client/agent-tab.js.map +1 -0
  151. package/dist/client/application-state.d.ts +22 -0
  152. package/dist/client/application-state.d.ts.map +1 -0
  153. package/dist/client/application-state.js +88 -0
  154. package/dist/client/application-state.js.map +1 -0
  155. package/dist/client/index.d.ts +8 -0
  156. package/dist/client/index.d.ts.map +1 -0
  157. package/dist/client/index.js +8 -0
  158. package/dist/client/index.js.map +1 -0
  159. package/dist/client/messages.d.ts +5 -0
  160. package/dist/client/messages.d.ts.map +1 -0
  161. package/dist/client/messages.js +1059 -0
  162. package/dist/client/messages.js.map +1 -0
  163. package/dist/connectors/context.d.ts +9 -0
  164. package/dist/connectors/context.d.ts.map +1 -0
  165. package/dist/connectors/context.js +59 -0
  166. package/dist/connectors/context.js.map +1 -0
  167. package/dist/connectors/document-parser.d.ts +2 -0
  168. package/dist/connectors/document-parser.d.ts.map +1 -0
  169. package/dist/connectors/document-parser.js +2 -0
  170. package/dist/connectors/document-parser.js.map +1 -0
  171. package/dist/connectors/figma-native.d.ts +18 -0
  172. package/dist/connectors/figma-native.d.ts.map +1 -0
  173. package/dist/connectors/figma-native.js +883 -0
  174. package/dist/connectors/figma-native.js.map +1 -0
  175. package/dist/connectors/figma.d.ts +10 -0
  176. package/dist/connectors/figma.d.ts.map +1 -0
  177. package/dist/connectors/figma.js +166 -0
  178. package/dist/connectors/figma.js.map +1 -0
  179. package/dist/connectors/google-slides-native.d.ts +58 -0
  180. package/dist/connectors/google-slides-native.d.ts.map +1 -0
  181. package/dist/connectors/google-slides-native.js +1118 -0
  182. package/dist/connectors/google-slides-native.js.map +1 -0
  183. package/dist/connectors/google-slides.d.ts +15 -0
  184. package/dist/connectors/google-slides.d.ts.map +1 -0
  185. package/dist/connectors/google-slides.js +896 -0
  186. package/dist/connectors/google-slides.js.map +1 -0
  187. package/dist/connectors/index.d.ts +20 -0
  188. package/dist/connectors/index.d.ts.map +1 -0
  189. package/dist/connectors/index.js +44 -0
  190. package/dist/connectors/index.js.map +1 -0
  191. package/dist/connectors/manual.d.ts +9 -0
  192. package/dist/connectors/manual.d.ts.map +1 -0
  193. package/dist/connectors/manual.js +91 -0
  194. package/dist/connectors/manual.js.map +1 -0
  195. package/dist/connectors/normalize.d.ts +35 -0
  196. package/dist/connectors/normalize.d.ts.map +1 -0
  197. package/dist/connectors/normalize.js +216 -0
  198. package/dist/connectors/normalize.js.map +1 -0
  199. package/dist/connectors/notion.d.ts +10 -0
  200. package/dist/connectors/notion.d.ts.map +1 -0
  201. package/dist/connectors/notion.js +393 -0
  202. package/dist/connectors/notion.js.map +1 -0
  203. package/dist/connectors/private-artifacts.d.ts +39 -0
  204. package/dist/connectors/private-artifacts.d.ts.map +1 -0
  205. package/dist/connectors/private-artifacts.js +175 -0
  206. package/dist/connectors/private-artifacts.js.map +1 -0
  207. package/dist/connectors/provider-response.d.ts +20 -0
  208. package/dist/connectors/provider-response.d.ts.map +1 -0
  209. package/dist/connectors/provider-response.js +98 -0
  210. package/dist/connectors/provider-response.js.map +1 -0
  211. package/dist/connectors/recommendations.d.ts +25 -0
  212. package/dist/connectors/recommendations.d.ts.map +1 -0
  213. package/dist/connectors/recommendations.js +172 -0
  214. package/dist/connectors/recommendations.js.map +1 -0
  215. package/dist/connectors/registry.d.ts +10 -0
  216. package/dist/connectors/registry.d.ts.map +1 -0
  217. package/dist/connectors/registry.js +34 -0
  218. package/dist/connectors/registry.js.map +1 -0
  219. package/dist/connectors/rendered-page.d.ts +101 -0
  220. package/dist/connectors/rendered-page.d.ts.map +1 -0
  221. package/dist/connectors/rendered-page.js +504 -0
  222. package/dist/connectors/rendered-page.js.map +1 -0
  223. package/dist/connectors/smart-defaults.d.ts +9 -0
  224. package/dist/connectors/smart-defaults.d.ts.map +1 -0
  225. package/dist/connectors/smart-defaults.js +72 -0
  226. package/dist/connectors/smart-defaults.js.map +1 -0
  227. package/dist/connectors/types.d.ts +79 -0
  228. package/dist/connectors/types.d.ts.map +1 -0
  229. package/dist/connectors/types.js +2 -0
  230. package/dist/connectors/types.js.map +1 -0
  231. package/dist/connectors/upload.d.ts +9 -0
  232. package/dist/connectors/upload.d.ts.map +1 -0
  233. package/dist/connectors/upload.js +440 -0
  234. package/dist/connectors/upload.js.map +1 -0
  235. package/dist/connectors/website.d.ts +20 -0
  236. package/dist/connectors/website.d.ts.map +1 -0
  237. package/dist/connectors/website.js +616 -0
  238. package/dist/connectors/website.js.map +1 -0
  239. package/dist/embeddings/index.d.ts +3 -0
  240. package/dist/embeddings/index.d.ts.map +1 -0
  241. package/dist/embeddings/index.js +3 -0
  242. package/dist/embeddings/index.js.map +1 -0
  243. package/dist/embeddings/providers.d.ts +7 -0
  244. package/dist/embeddings/providers.d.ts.map +1 -0
  245. package/dist/embeddings/providers.js +176 -0
  246. package/dist/embeddings/providers.js.map +1 -0
  247. package/dist/embeddings/types.d.ts +19 -0
  248. package/dist/embeddings/types.d.ts.map +1 -0
  249. package/dist/embeddings/types.js +2 -0
  250. package/dist/embeddings/types.js.map +1 -0
  251. package/dist/eval/acceptance-fixtures.d.ts +3 -0
  252. package/dist/eval/acceptance-fixtures.d.ts.map +1 -0
  253. package/dist/eval/acceptance-fixtures.js +84 -0
  254. package/dist/eval/acceptance-fixtures.js.map +1 -0
  255. package/dist/eval/acceptance.d.ts +114 -0
  256. package/dist/eval/acceptance.d.ts.map +1 -0
  257. package/dist/eval/acceptance.js +260 -0
  258. package/dist/eval/acceptance.js.map +1 -0
  259. package/dist/eval/fixtures.d.ts +16 -0
  260. package/dist/eval/fixtures.d.ts.map +1 -0
  261. package/dist/eval/fixtures.js +119 -0
  262. package/dist/eval/fixtures.js.map +1 -0
  263. package/dist/eval/index.d.ts +63 -0
  264. package/dist/eval/index.d.ts.map +1 -0
  265. package/dist/eval/index.js +174 -0
  266. package/dist/eval/index.js.map +1 -0
  267. package/dist/index.d.ts +5 -0
  268. package/dist/index.d.ts.map +1 -0
  269. package/dist/index.js +5 -0
  270. package/dist/index.js.map +1 -0
  271. package/dist/jobs/background-worker.d.ts +31 -0
  272. package/dist/jobs/background-worker.d.ts.map +1 -0
  273. package/dist/jobs/background-worker.js +315 -0
  274. package/dist/jobs/background-worker.js.map +1 -0
  275. package/dist/jobs/import-runner.d.ts +3 -0
  276. package/dist/jobs/import-runner.d.ts.map +1 -0
  277. package/dist/jobs/import-runner.js +613 -0
  278. package/dist/jobs/import-runner.js.map +1 -0
  279. package/dist/jobs/index.d.ts +9 -0
  280. package/dist/jobs/index.d.ts.map +1 -0
  281. package/dist/jobs/index.js +8 -0
  282. package/dist/jobs/index.js.map +1 -0
  283. package/dist/jobs/progress.d.ts +3 -0
  284. package/dist/jobs/progress.d.ts.map +1 -0
  285. package/dist/jobs/progress.js +30 -0
  286. package/dist/jobs/progress.js.map +1 -0
  287. package/dist/jobs/rebuild.d.ts +13 -0
  288. package/dist/jobs/rebuild.d.ts.map +1 -0
  289. package/dist/jobs/rebuild.js +178 -0
  290. package/dist/jobs/rebuild.js.map +1 -0
  291. package/dist/jobs/server-worker.d.ts +16 -0
  292. package/dist/jobs/server-worker.d.ts.map +1 -0
  293. package/dist/jobs/server-worker.js +252 -0
  294. package/dist/jobs/server-worker.js.map +1 -0
  295. package/dist/jobs/store-adapter.d.ts +3 -0
  296. package/dist/jobs/store-adapter.d.ts.map +1 -0
  297. package/dist/jobs/store-adapter.js +37 -0
  298. package/dist/jobs/store-adapter.js.map +1 -0
  299. package/dist/jobs/types.d.ts +138 -0
  300. package/dist/jobs/types.d.ts.map +1 -0
  301. package/dist/jobs/types.js +2 -0
  302. package/dist/jobs/types.js.map +1 -0
  303. package/dist/jobs/worker.d.ts +27 -0
  304. package/dist/jobs/worker.d.ts.map +1 -0
  305. package/dist/jobs/worker.js +90 -0
  306. package/dist/jobs/worker.js.map +1 -0
  307. package/dist/media-url.d.ts +7 -0
  308. package/dist/media-url.d.ts.map +1 -0
  309. package/dist/media-url.js +15 -0
  310. package/dist/media-url.js.map +1 -0
  311. package/dist/native-artifact-reassembly.d.ts +25 -0
  312. package/dist/native-artifact-reassembly.d.ts.map +1 -0
  313. package/dist/native-artifact-reassembly.js +262 -0
  314. package/dist/native-artifact-reassembly.js.map +1 -0
  315. package/dist/native-artifact.d.ts +88 -0
  316. package/dist/native-artifact.d.ts.map +1 -0
  317. package/dist/native-artifact.js +86 -0
  318. package/dist/native-artifact.js.map +1 -0
  319. package/dist/schema/index.d.ts +5519 -0
  320. package/dist/schema/index.d.ts.map +1 -0
  321. package/dist/schema/index.js +374 -0
  322. package/dist/schema/index.js.map +1 -0
  323. package/dist/schema/migrations.d.ts +10 -0
  324. package/dist/schema/migrations.d.ts.map +1 -0
  325. package/dist/schema/migrations.js +253 -0
  326. package/dist/schema/migrations.js.map +1 -0
  327. package/dist/search/fusion.d.ts +15 -0
  328. package/dist/search/fusion.d.ts.map +1 -0
  329. package/dist/search/fusion.js +25 -0
  330. package/dist/search/fusion.js.map +1 -0
  331. package/dist/search/mode.d.ts +4 -0
  332. package/dist/search/mode.d.ts.map +1 -0
  333. package/dist/search/mode.js +13 -0
  334. package/dist/search/mode.js.map +1 -0
  335. package/dist/search/postgres-fts.d.ts +22 -0
  336. package/dist/search/postgres-fts.d.ts.map +1 -0
  337. package/dist/search/postgres-fts.js +83 -0
  338. package/dist/search/postgres-fts.js.map +1 -0
  339. package/dist/server/brand-context.d.ts +15 -0
  340. package/dist/server/brand-context.d.ts.map +1 -0
  341. package/dist/server/brand-context.js +149 -0
  342. package/dist/server/brand-context.js.map +1 -0
  343. package/dist/server/context.d.ts +77 -0
  344. package/dist/server/context.d.ts.map +1 -0
  345. package/dist/server/context.js +63 -0
  346. package/dist/server/context.js.map +1 -0
  347. package/dist/server/enrichment.d.ts +23 -0
  348. package/dist/server/enrichment.d.ts.map +1 -0
  349. package/dist/server/enrichment.js +136 -0
  350. package/dist/server/enrichment.js.map +1 -0
  351. package/dist/server/generation-artifact-access.d.ts +21 -0
  352. package/dist/server/generation-artifact-access.d.ts.map +1 -0
  353. package/dist/server/generation-artifact-access.js +111 -0
  354. package/dist/server/generation-artifact-access.js.map +1 -0
  355. package/dist/server/generation-context.d.ts +204 -0
  356. package/dist/server/generation-context.d.ts.map +1 -0
  357. package/dist/server/generation-context.js +310 -0
  358. package/dist/server/generation-context.js.map +1 -0
  359. package/dist/server/index.d.ts +22 -0
  360. package/dist/server/index.d.ts.map +1 -0
  361. package/dist/server/index.js +96 -0
  362. package/dist/server/index.js.map +1 -0
  363. package/dist/server/isolated-a2a.d.ts +172 -0
  364. package/dist/server/isolated-a2a.d.ts.map +1 -0
  365. package/dist/server/isolated-a2a.js +310 -0
  366. package/dist/server/isolated-a2a.js.map +1 -0
  367. package/dist/server/media.d.ts +15 -0
  368. package/dist/server/media.d.ts.map +1 -0
  369. package/dist/server/media.js +93 -0
  370. package/dist/server/media.js.map +1 -0
  371. package/dist/server/prompt-provider.d.ts +5 -0
  372. package/dist/server/prompt-provider.d.ts.map +1 -0
  373. package/dist/server/prompt-provider.js +59 -0
  374. package/dist/server/prompt-provider.js.map +1 -0
  375. package/dist/server/public-serialization.d.ts +160 -0
  376. package/dist/server/public-serialization.d.ts.map +1 -0
  377. package/dist/server/public-serialization.js +108 -0
  378. package/dist/server/public-serialization.js.map +1 -0
  379. package/dist/server/resource-paths.d.ts +3 -0
  380. package/dist/server/resource-paths.d.ts.map +1 -0
  381. package/dist/server/resource-paths.js +5 -0
  382. package/dist/server/resource-paths.js.map +1 -0
  383. package/dist/server/retrieval.d.ts +78 -0
  384. package/dist/server/retrieval.d.ts.map +1 -0
  385. package/dist/server/retrieval.js +443 -0
  386. package/dist/server/retrieval.js.map +1 -0
  387. package/dist/server/untrusted-reference.d.ts +8 -0
  388. package/dist/server/untrusted-reference.d.ts.map +1 -0
  389. package/dist/server/untrusted-reference.js +19 -0
  390. package/dist/server/untrusted-reference.js.map +1 -0
  391. package/dist/store/brand.d.ts +47 -0
  392. package/dist/store/brand.d.ts.map +1 -0
  393. package/dist/store/brand.js +360 -0
  394. package/dist/store/brand.js.map +1 -0
  395. package/dist/store/content.d.ts +120 -0
  396. package/dist/store/content.d.ts.map +1 -0
  397. package/dist/store/content.js +1437 -0
  398. package/dist/store/content.js.map +1 -0
  399. package/dist/store/generation.d.ts +28 -0
  400. package/dist/store/generation.d.ts.map +1 -0
  401. package/dist/store/generation.js +140 -0
  402. package/dist/store/generation.js.map +1 -0
  403. package/dist/store/helpers.d.ts +12 -0
  404. package/dist/store/helpers.d.ts.map +1 -0
  405. package/dist/store/helpers.js +41 -0
  406. package/dist/store/helpers.js.map +1 -0
  407. package/dist/store/index.d.ts +10 -0
  408. package/dist/store/index.d.ts.map +1 -0
  409. package/dist/store/index.js +10 -0
  410. package/dist/store/index.js.map +1 -0
  411. package/dist/store/inference.d.ts +57 -0
  412. package/dist/store/inference.d.ts.map +1 -0
  413. package/dist/store/inference.js +279 -0
  414. package/dist/store/inference.js.map +1 -0
  415. package/dist/store/jobs.d.ts +80 -0
  416. package/dist/store/jobs.d.ts.map +1 -0
  417. package/dist/store/jobs.js +428 -0
  418. package/dist/store/jobs.js.map +1 -0
  419. package/dist/store/packs.d.ts +33 -0
  420. package/dist/store/packs.d.ts.map +1 -0
  421. package/dist/store/packs.js +321 -0
  422. package/dist/store/packs.js.map +1 -0
  423. package/dist/store/purge.d.ts +16 -0
  424. package/dist/store/purge.d.ts.map +1 -0
  425. package/dist/store/purge.js +256 -0
  426. package/dist/store/purge.js.map +1 -0
  427. package/dist/store/sources.d.ts +76 -0
  428. package/dist/store/sources.d.ts.map +1 -0
  429. package/dist/store/sources.js +538 -0
  430. package/dist/store/sources.js.map +1 -0
  431. package/dist/store/suggestions.d.ts +28 -0
  432. package/dist/store/suggestions.d.ts.map +1 -0
  433. package/dist/store/suggestions.js +250 -0
  434. package/dist/store/suggestions.js.map +1 -0
  435. package/dist/types.d.ts +493 -0
  436. package/dist/types.d.ts.map +1 -0
  437. package/dist/types.js +2 -0
  438. package/dist/types.js.map +1 -0
  439. package/dist/vector/index.d.ts +2 -0
  440. package/dist/vector/index.d.ts.map +1 -0
  441. package/dist/vector/index.js +2 -0
  442. package/dist/vector/index.js.map +1 -0
  443. package/dist/vector/pgvector.d.ts +28 -0
  444. package/dist/vector/pgvector.d.ts.map +1 -0
  445. package/dist/vector/pgvector.js +117 -0
  446. package/dist/vector/pgvector.js.map +1 -0
  447. package/docs/evaluation.md +92 -0
  448. package/docs/llms-full.txt +168 -0
  449. package/docs/llms.txt +76 -0
  450. package/docs/skills/creative-context/SKILL.md +74 -0
  451. package/package.json +91 -0
  452. package/src/actions/agent-input-schemas.spec.ts +46 -0
  453. package/src/actions/confirm-canonical-logo.ts +20 -0
  454. package/src/actions/continue-context-import.ts +12 -0
  455. package/src/actions/creative-context-a2a.spec.ts +64 -0
  456. package/src/actions/creative-context-a2a.ts +88 -0
  457. package/src/actions/get-brand-profile.ts +16 -0
  458. package/src/actions/get-context-import-status.ts +13 -0
  459. package/src/actions/get-context-item.ts +1 -0
  460. package/src/actions/get-context-pack.ts +14 -0
  461. package/src/actions/get-creative-context.spec.ts +315 -0
  462. package/src/actions/get-creative-context.ts +148 -0
  463. package/src/actions/index.ts +65 -0
  464. package/src/actions/infer-brand-dna.ts +15 -0
  465. package/src/actions/list-canonical-logo-candidates.ts +121 -0
  466. package/src/actions/list-context-connections.spec.ts +23 -0
  467. package/src/actions/list-context-connections.ts +51 -0
  468. package/src/actions/list-context-packs.ts +17 -0
  469. package/src/actions/list-context-sources.ts +21 -0
  470. package/src/actions/list-context-suggestions.ts +30 -0
  471. package/src/actions/manage-brand-profile.ts +58 -0
  472. package/src/actions/manage-context-pack.ts +75 -0
  473. package/src/actions/manage-context-source.ts +154 -0
  474. package/src/actions/manage-layout-template.ts +51 -0
  475. package/src/actions/preview-context-import.spec.ts +64 -0
  476. package/src/actions/preview-context-import.ts +61 -0
  477. package/src/actions/process-context-purge.ts +25 -0
  478. package/src/actions/propose-brand-dna.ts +22 -0
  479. package/src/actions/propose-canonical-logo.ts +19 -0
  480. package/src/actions/publish-brand-dna.ts +25 -0
  481. package/src/actions/recommend-context-roots.ts +24 -0
  482. package/src/actions/record-context-feedback.ts +16 -0
  483. package/src/actions/review-context-items.ts +69 -0
  484. package/src/actions/run-embedding-bakeoff.ts +90 -0
  485. package/src/actions/search-creative-context.ts +47 -0
  486. package/src/actions/set-brand-dna.ts +22 -0
  487. package/src/actions/start-context-enrichment.ts +50 -0
  488. package/src/actions/start-context-import.ts +37 -0
  489. package/src/client/CreativeContextChip.tsx +162 -0
  490. package/src/client/CreativeContextPanel.tsx +2442 -0
  491. package/src/client/CreativeContextSettingsLink.tsx +30 -0
  492. package/src/client/actions.ts +438 -0
  493. package/src/client/agent-tab.tsx +58 -0
  494. package/src/client/application-state.spec.ts +41 -0
  495. package/src/client/application-state.ts +130 -0
  496. package/src/client/index.ts +62 -0
  497. package/src/client/messages.ts +1240 -0
  498. package/src/client/source-config.spec.ts +152 -0
  499. package/src/connectors/connectors.spec.ts +778 -0
  500. package/src/connectors/context.ts +83 -0
  501. package/src/connectors/document-parser.ts +5 -0
  502. package/src/connectors/figma-native.ts +1192 -0
  503. package/src/connectors/figma-native.visual.spec.ts +221 -0
  504. package/src/connectors/figma.spec.ts +812 -0
  505. package/src/connectors/figma.ts +257 -0
  506. package/src/connectors/fixtures/google-slides-native.json +353 -0
  507. package/src/connectors/google-slides-native.spec.ts +804 -0
  508. package/src/connectors/google-slides-native.ts +1656 -0
  509. package/src/connectors/google-slides-native.visual.spec.ts +119 -0
  510. package/src/connectors/google-slides.ts +1172 -0
  511. package/src/connectors/index.ts +103 -0
  512. package/src/connectors/manual.ts +132 -0
  513. package/src/connectors/normalize.ts +277 -0
  514. package/src/connectors/notion.ts +529 -0
  515. package/src/connectors/private-artifacts.spec.ts +95 -0
  516. package/src/connectors/private-artifacts.ts +248 -0
  517. package/src/connectors/provider-response.ts +144 -0
  518. package/src/connectors/recommendations.ts +237 -0
  519. package/src/connectors/registry.ts +48 -0
  520. package/src/connectors/rendered-page.ts +705 -0
  521. package/src/connectors/smart-defaults.spec.ts +135 -0
  522. package/src/connectors/smart-defaults.ts +87 -0
  523. package/src/connectors/types.ts +115 -0
  524. package/src/connectors/upload.spec.ts +175 -0
  525. package/src/connectors/upload.ts +548 -0
  526. package/src/connectors/website.spec.ts +509 -0
  527. package/src/connectors/website.ts +777 -0
  528. package/src/embeddings/index.ts +2 -0
  529. package/src/embeddings/providers.spec.ts +73 -0
  530. package/src/embeddings/providers.ts +228 -0
  531. package/src/embeddings/types.ts +24 -0
  532. package/src/eval/acceptance-fixtures.ts +97 -0
  533. package/src/eval/acceptance.spec.ts +92 -0
  534. package/src/eval/acceptance.ts +371 -0
  535. package/src/eval/connectors-golden.spec.ts +421 -0
  536. package/src/eval/eval.spec.ts +166 -0
  537. package/src/eval/fixtures/README.md +17 -0
  538. package/src/eval/fixtures/figma-brand-system-v1.json +140 -0
  539. package/src/eval/fixtures/figma-brand-system-v2.json +127 -0
  540. package/src/eval/fixtures/launch-hero.png +0 -0
  541. package/src/eval/fixtures/launch-system-v1.pptx +0 -0
  542. package/src/eval/fixtures/launch-system-v2.pptx +0 -0
  543. package/src/eval/fixtures/notion-brand-root.json +218 -0
  544. package/src/eval/fixtures/pricing-hero.png +0 -0
  545. package/src/eval/fixtures/rendered-brand-page.html +76 -0
  546. package/src/eval/fixtures.spec.ts +43 -0
  547. package/src/eval/fixtures.ts +136 -0
  548. package/src/eval/index.ts +291 -0
  549. package/src/eval/library-flow.acceptance.spec.tsx +141 -0
  550. package/src/index.ts +4 -0
  551. package/src/jobs/background-worker.ts +423 -0
  552. package/src/jobs/import-runner.spec.ts +582 -0
  553. package/src/jobs/import-runner.ts +792 -0
  554. package/src/jobs/index.ts +40 -0
  555. package/src/jobs/progress.ts +37 -0
  556. package/src/jobs/rebuild.ts +245 -0
  557. package/src/jobs/server-worker.spec.ts +159 -0
  558. package/src/jobs/server-worker.ts +344 -0
  559. package/src/jobs/store-adapter.ts +52 -0
  560. package/src/jobs/types.ts +147 -0
  561. package/src/jobs/worker.ts +152 -0
  562. package/src/manifest.spec.ts +26 -0
  563. package/src/media-url.ts +17 -0
  564. package/src/native-artifact-reassembly.spec.ts +386 -0
  565. package/src/native-artifact-reassembly.ts +406 -0
  566. package/src/native-artifact.ts +102 -0
  567. package/src/schema/index.ts +411 -0
  568. package/src/schema/migrations.spec.ts +41 -0
  569. package/src/schema/migrations.ts +258 -0
  570. package/src/search/fusion.spec.ts +21 -0
  571. package/src/search/fusion.ts +39 -0
  572. package/src/search/mode.spec.ts +28 -0
  573. package/src/search/mode.ts +21 -0
  574. package/src/search/postgres-fts.spec.ts +71 -0
  575. package/src/search/postgres-fts.ts +112 -0
  576. package/src/server/brand-context.spec.ts +43 -0
  577. package/src/server/brand-context.ts +160 -0
  578. package/src/server/context.ts +162 -0
  579. package/src/server/enrichment.ts +163 -0
  580. package/src/server/generation-artifact-access.ts +216 -0
  581. package/src/server/generation-context-a2a.spec.ts +131 -0
  582. package/src/server/generation-context-off.spec.ts +213 -0
  583. package/src/server/generation-context.spec.ts +124 -0
  584. package/src/server/generation-context.ts +493 -0
  585. package/src/server/index.ts +135 -0
  586. package/src/server/isolated-a2a.spec.ts +164 -0
  587. package/src/server/isolated-a2a.ts +413 -0
  588. package/src/server/media.spec.ts +92 -0
  589. package/src/server/media.ts +117 -0
  590. package/src/server/prompt-provider.spec.ts +78 -0
  591. package/src/server/prompt-provider.ts +73 -0
  592. package/src/server/public-serialization.spec.ts +149 -0
  593. package/src/server/public-serialization.ts +130 -0
  594. package/src/server/resource-paths.spec.ts +9 -0
  595. package/src/server/resource-paths.ts +5 -0
  596. package/src/server/retrieval-vector.spec.ts +180 -0
  597. package/src/server/retrieval.ts +587 -0
  598. package/src/server/untrusted-reference.spec.ts +22 -0
  599. package/src/server/untrusted-reference.ts +24 -0
  600. package/src/store/access.integration.spec.ts +1922 -0
  601. package/src/store/brand.ts +477 -0
  602. package/src/store/content.ts +1900 -0
  603. package/src/store/generation.ts +226 -0
  604. package/src/store/helpers.ts +53 -0
  605. package/src/store/index.ts +9 -0
  606. package/src/store/inference.spec.ts +84 -0
  607. package/src/store/inference.ts +339 -0
  608. package/src/store/invariants.spec.ts +119 -0
  609. package/src/store/jobs.ts +672 -0
  610. package/src/store/packs.ts +466 -0
  611. package/src/store/purge.ts +321 -0
  612. package/src/store/sources.spec.ts +102 -0
  613. package/src/store/sources.ts +708 -0
  614. package/src/store/suggestions.ts +333 -0
  615. package/src/types.ts +571 -0
  616. package/src/vector/index.ts +1 -0
  617. package/src/vector/pgvector.spec.ts +98 -0
  618. package/src/vector/pgvector.ts +164 -0
@@ -0,0 +1,812 @@
1
+ import { describe, expect, it, vi } from "vitest";
2
+
3
+ const ssrfSafeFetch = vi.hoisted(() =>
4
+ vi.fn(async (url: string) =>
5
+ url.includes(".svg")
6
+ ? new Response(
7
+ '<svg xmlns="http://www.w3.org/2000/svg"><path d="M0 0h10v10z"/></svg>',
8
+ { status: 200, headers: { "content-type": "image/svg+xml" } },
9
+ )
10
+ : new Response(new Uint8Array([137, 80, 78, 71]), {
11
+ status: 200,
12
+ headers: { "content-type": "image/png" },
13
+ }),
14
+ ),
15
+ );
16
+
17
+ vi.mock("@agent-native/core/extensions/url-safety", () => ({
18
+ ssrfSafeFetch,
19
+ }));
20
+
21
+ const { FigmaContextConnector } = await import("./figma.js");
22
+ const { nativeFidelityReportFromEntries } = await import("./figma-native.js");
23
+
24
+ describe("Figma context connector", () => {
25
+ it("compiles editable frames, privately rehosts only localized fallbacks, and records provenance", async () => {
26
+ const providerRequest = vi.fn(async (input: Record<string, unknown>) => {
27
+ if (String(input.path).startsWith("/images/")) {
28
+ return {
29
+ images: {
30
+ "logo-1":
31
+ "https://cdn.example.com/logo-fallback.png?token=secret-logo",
32
+ },
33
+ };
34
+ }
35
+ if (String(input.path).endsWith("/nodes")) {
36
+ return {
37
+ nodes: {
38
+ "frame-1": { document: FRAME },
39
+ },
40
+ };
41
+ }
42
+ if (String(input.path).endsWith("/images")) {
43
+ return {
44
+ images: {
45
+ "image-fill-1":
46
+ "https://cdn.example.com/texture.png?token=secret-fill",
47
+ },
48
+ };
49
+ }
50
+ return {
51
+ name: "Design system",
52
+ version: "42",
53
+ lastModified: "2026-07-01T00:00:00.000Z",
54
+ editorType: "figma",
55
+ role: "viewer",
56
+ document: {
57
+ id: "document",
58
+ name: "Document",
59
+ type: "DOCUMENT",
60
+ children: [
61
+ {
62
+ id: "page-1",
63
+ name: "Page",
64
+ type: "CANVAS",
65
+ children: [FRAME],
66
+ },
67
+ ],
68
+ },
69
+ };
70
+ });
71
+ const putPrivateBlob = vi.fn(async () => ({
72
+ id: "private-render-1",
73
+ provider: "fixture",
74
+ opaque: true as const,
75
+ encrypted: true,
76
+ mimeType: "image/png",
77
+ }));
78
+ const connector = new FigmaContextConnector();
79
+ const executionContext = {
80
+ appId: "design",
81
+ ownerEmail: "owner@example.com",
82
+ resolveConnection: async () => "figma-connection",
83
+ providerApi: { executeRequest: providerRequest } as never,
84
+ putPrivateBlob,
85
+ };
86
+ const inventory = await connector.inventory(
87
+ { sourceId: "source-1", config: { fileKeys: ["file-key"] } },
88
+ executionContext,
89
+ );
90
+ const fetched = await connector.fetch(
91
+ {
92
+ sourceId: "source-1",
93
+ config: { fileKeys: ["file-key"] },
94
+ item: inventory.items[0],
95
+ },
96
+ executionContext,
97
+ );
98
+
99
+ expect(fetched.items[0]).toMatchObject({
100
+ externalId: "file-key",
101
+ kind: "figma-file",
102
+ parseStatus: "parsed",
103
+ sourceVersion: "42",
104
+ metadata: {
105
+ artifactCount: 1,
106
+ childExternalIds: ["file-key:frame-1"],
107
+ },
108
+ edges: [
109
+ {
110
+ relation: "contains-native-artifact",
111
+ toExternalId: "file-key:frame-1",
112
+ },
113
+ ],
114
+ });
115
+ const frame = fetched.items.find(
116
+ (item) => item.externalId === "file-key:frame-1",
117
+ );
118
+ expect(frame).toMatchObject({
119
+ externalId: "file-key:frame-1",
120
+ kind: "figma-frame",
121
+ sourceVersion: "42",
122
+ mimeType: "text/html",
123
+ metadata: {
124
+ nativeArtifact: {
125
+ app: "design",
126
+ format: "design-html",
127
+ fidelityReport: {
128
+ imageFallback: { count: 1 },
129
+ },
130
+ },
131
+ },
132
+ media: [
133
+ expect.objectContaining({
134
+ kind: "image",
135
+ accessMode: "private",
136
+ provenanceUrl: "https://www.figma.com/design/file-key",
137
+ captionStatus: "pending",
138
+ }),
139
+ expect.objectContaining({
140
+ kind: "image",
141
+ accessMode: "private",
142
+ metadata: expect.objectContaining({ role: "image-fill" }),
143
+ }),
144
+ ],
145
+ edges: expect.arrayContaining([
146
+ { relation: "part-of-figma-file", toExternalId: "file-key" },
147
+ {
148
+ relation: "instance-of-component",
149
+ toExternalId: "file-key:component-7",
150
+ },
151
+ expect.objectContaining({
152
+ relation: "uses-figma-token",
153
+ toExternalId: "file-key:style:style-type",
154
+ }),
155
+ ]),
156
+ });
157
+ expect(frame?.content).toContain("Build beautiful things");
158
+ expect(frame?.chunks).toEqual(
159
+ expect.arrayContaining([
160
+ expect.objectContaining({
161
+ kind: "code",
162
+ text: expect.stringContaining("frame"),
163
+ metadata: { role: "code-tokens", format: "design-html" },
164
+ }),
165
+ ]),
166
+ );
167
+ expect(frame?.content).toContain(
168
+ "/_agent-native/creative-context/media?mediaId=",
169
+ );
170
+ expect(frame?.content).toContain("linear-gradient");
171
+ expect(frame?.content).toContain("box-shadow");
172
+ expect(ssrfSafeFetch).toHaveBeenCalledWith(
173
+ "https://cdn.example.com/logo-fallback.png?token=secret-logo",
174
+ expect.any(Object),
175
+ { maxRedirects: 5 },
176
+ );
177
+ expect(JSON.stringify(fetched.items)).not.toContain("secret-logo");
178
+ expect(JSON.stringify(fetched.items)).not.toContain("secret-fill");
179
+ expect(putPrivateBlob).toHaveBeenCalledWith(
180
+ expect.objectContaining({ ownerEmail: "owner@example.com" }),
181
+ );
182
+ expect(putPrivateBlob).toHaveBeenCalledTimes(2);
183
+ expect(
184
+ ssrfSafeFetch.mock.calls.filter(([url]) =>
185
+ String(url).includes("texture.png"),
186
+ ),
187
+ ).toHaveLength(1);
188
+ });
189
+
190
+ it("falls back to per-page shallow inventory when the file depth-2 response is oversized", async () => {
191
+ const frame = {
192
+ id: "frame-1",
193
+ name: "Recovered frame",
194
+ type: "FRAME",
195
+ absoluteBoundingBox: { x: 0, y: 0, width: 800, height: 600 },
196
+ children: [],
197
+ };
198
+ const page = {
199
+ id: "page-1",
200
+ name: "Page 1",
201
+ type: "CANVAS",
202
+ children: [frame],
203
+ };
204
+ const providerRequest = vi.fn(async (input: Record<string, unknown>) => {
205
+ if (String(input.path).endsWith("/nodes")) {
206
+ const id = String((input.query as { ids?: string }).ids);
207
+ const node = id === "page-1" ? page : frame;
208
+ return { nodes: { [id]: { document: node } } };
209
+ }
210
+ if ((input.query as { depth?: number }).depth === 2) {
211
+ throw new Error("response too large: maximum response limit");
212
+ }
213
+ return {
214
+ name: "Large inventory file",
215
+ version: "inventory-v1",
216
+ document: {
217
+ id: "document",
218
+ type: "DOCUMENT",
219
+ children: [{ id: "page-1", name: "Page 1", type: "CANVAS" }],
220
+ },
221
+ };
222
+ });
223
+ const connector = new FigmaContextConnector();
224
+ const context = {
225
+ appId: "design",
226
+ ownerEmail: "owner@example.com",
227
+ resolveConnection: async () => "figma-connection",
228
+ providerApi: { executeRequest: providerRequest } as never,
229
+ };
230
+ const [item] = (
231
+ await connector.inventory(
232
+ { sourceId: "source-1", config: { fileKeys: ["large-file"] } },
233
+ context,
234
+ )
235
+ ).items;
236
+
237
+ const fetched = await connector.fetch(
238
+ { sourceId: "source-1", config: {}, item: item! },
239
+ context,
240
+ );
241
+
242
+ expect(
243
+ fetched.items.find((entry) => entry.externalId === "large-file:frame-1"),
244
+ ).toMatchObject({ kind: "figma-frame", mimeType: "text/html" });
245
+ expect(fetched.warnings).toEqual([
246
+ expect.stringContaining("pages were inventoried independently"),
247
+ ]);
248
+ });
249
+
250
+ it("splits a huge artboard only at safe child boundaries and records reassembly geometry", async () => {
251
+ const background = {
252
+ id: "background",
253
+ name: "Background",
254
+ type: "RECTANGLE",
255
+ absoluteBoundingBox: { x: 100, y: 200, width: 20_000, height: 4_000 },
256
+ fills: [{ type: "SOLID", color: { r: 1, g: 1, b: 1, a: 1 } }],
257
+ children: [],
258
+ };
259
+ const childOne = {
260
+ id: "section-1",
261
+ name: "Section one",
262
+ type: "FRAME",
263
+ absoluteBoundingBox: { x: 100, y: 200, width: 1200, height: 800 },
264
+ relativeTransform: [
265
+ [1, 0, 100],
266
+ [0, 1, 200],
267
+ ],
268
+ children: [],
269
+ };
270
+ const childTwo = {
271
+ id: "section-2",
272
+ name: "Section two",
273
+ type: "FRAME",
274
+ absoluteBoundingBox: { x: 1400, y: 200, width: 1200, height: 800 },
275
+ children: [],
276
+ };
277
+ const huge = {
278
+ id: "huge-1",
279
+ name: "Huge campaign board",
280
+ type: "FRAME",
281
+ absoluteBoundingBox: { x: 100, y: 200, width: 20_000, height: 4_000 },
282
+ effects: [
283
+ {
284
+ type: "DROP_SHADOW",
285
+ visible: true,
286
+ radius: 8,
287
+ offset: { x: 0, y: 4 },
288
+ color: { r: 0, g: 0, b: 0, a: 0.2 },
289
+ },
290
+ ],
291
+ children: [background, childOne, childTwo],
292
+ };
293
+ const providerRequest = vi.fn(async (input: Record<string, unknown>) => {
294
+ if (String(input.path).endsWith("/nodes")) {
295
+ const id = String((input.query as { ids?: string }).ids);
296
+ const node =
297
+ id === "huge-1"
298
+ ? huge
299
+ : id === "background"
300
+ ? background
301
+ : id === "section-1"
302
+ ? childOne
303
+ : childTwo;
304
+ return { nodes: { [id]: { document: node } } };
305
+ }
306
+ return {
307
+ name: "Huge file",
308
+ version: "huge-v1",
309
+ document: {
310
+ id: "document",
311
+ type: "DOCUMENT",
312
+ children: [{ id: "page", type: "CANVAS", children: [huge] }],
313
+ },
314
+ };
315
+ });
316
+ const connector = new FigmaContextConnector();
317
+ const context = {
318
+ appId: "design",
319
+ ownerEmail: "owner@example.com",
320
+ resolveConnection: async () => "figma-connection",
321
+ providerApi: { executeRequest: providerRequest } as never,
322
+ putPrivateBlob: vi.fn(),
323
+ };
324
+ const [item] = (
325
+ await connector.inventory(
326
+ { sourceId: "source-1", config: { fileKeys: ["huge-file"] } },
327
+ context,
328
+ )
329
+ ).items;
330
+ const fetched = await connector.fetch(
331
+ { sourceId: "source-1", config: {}, item: item! },
332
+ context,
333
+ );
334
+ const parent = fetched.items.find(
335
+ (entry) => entry.externalId === "huge-file:huge-1",
336
+ );
337
+ expect(parent).toMatchObject({
338
+ kind: "figma-artboard-manifest",
339
+ metadata: {
340
+ nativeArtifact: {
341
+ manifest: {
342
+ kind: "hierarchical-artboard",
343
+ children: [
344
+ {
345
+ externalId: "huge-file:background",
346
+ bounds: { x: 0, y: 0, width: 20_000, height: 4_000 },
347
+ zOrder: 0,
348
+ },
349
+ {
350
+ externalId: "huge-file:section-1",
351
+ bounds: { x: 0, y: 0, width: 1200, height: 800 },
352
+ transform: [1, 0, 100, 0, 1, 200],
353
+ zOrder: 1,
354
+ },
355
+ {
356
+ externalId: "huge-file:section-2",
357
+ bounds: { x: 1300, y: 0, width: 1200, height: 800 },
358
+ zOrder: 2,
359
+ },
360
+ ],
361
+ },
362
+ },
363
+ },
364
+ });
365
+ expect(parent?.content).toContain(
366
+ 'data-creative-context-child="huge-file:section-1"',
367
+ );
368
+ expect(
369
+ providerRequest.mock.calls.filter(
370
+ ([request]) =>
371
+ String(request.path).endsWith("/nodes") &&
372
+ (request.query as { ids?: string; depth?: number }).ids ===
373
+ "huge-1" &&
374
+ !(request.query as { depth?: number }).depth,
375
+ ),
376
+ ).toHaveLength(0);
377
+ });
378
+
379
+ it("recursively buckets an oversized hierarchical shell without flattening editable children", async () => {
380
+ const children = Array.from({ length: 1_000 }, (_, index) => ({
381
+ id: `section-${index}`,
382
+ name: `Section ${index}`,
383
+ type: "FRAME",
384
+ absoluteBoundingBox: {
385
+ x: index * 120,
386
+ y: 0,
387
+ width: 100,
388
+ height: 100,
389
+ },
390
+ children: [],
391
+ }));
392
+ const wide = {
393
+ id: "wide-1",
394
+ name: "Wide campaign map",
395
+ type: "FRAME",
396
+ absoluteBoundingBox: { x: 0, y: 0, width: 120_000, height: 1_000 },
397
+ children,
398
+ };
399
+ const providerRequest = vi.fn(async (input: Record<string, unknown>) => {
400
+ if (String(input.path).startsWith("/images/")) {
401
+ return {
402
+ images: {
403
+ "wide-1": "https://cdn.example.com/wide-1.png",
404
+ },
405
+ };
406
+ }
407
+ if (String(input.path).endsWith("/nodes")) {
408
+ const id = String((input.query as { ids?: string }).ids);
409
+ const node =
410
+ id === "wide-1" ? wide : children.find((child) => child.id === id);
411
+ return { nodes: { [id]: { document: node } } };
412
+ }
413
+ return {
414
+ name: "Wide file",
415
+ version: "wide-v1",
416
+ document: {
417
+ id: "document",
418
+ type: "DOCUMENT",
419
+ children: [{ id: "page", type: "CANVAS", children: [wide] }],
420
+ },
421
+ };
422
+ });
423
+ const connector = new FigmaContextConnector();
424
+ const context = {
425
+ appId: "design",
426
+ ownerEmail: "owner@example.com",
427
+ resolveConnection: async () => "figma-connection",
428
+ providerApi: { executeRequest: providerRequest } as never,
429
+ putPrivateBlob: vi.fn(async () => ({
430
+ id: "private-wide",
431
+ provider: "fixture",
432
+ opaque: true as const,
433
+ encrypted: true,
434
+ mimeType: "image/png",
435
+ })),
436
+ };
437
+ const [item] = (
438
+ await connector.inventory(
439
+ { sourceId: "source-1", config: { fileKeys: ["wide-file"] } },
440
+ context,
441
+ )
442
+ ).items;
443
+
444
+ const fetched = await connector.fetch(
445
+ { sourceId: "source-1", config: {}, item: item! },
446
+ context,
447
+ );
448
+ const parent = fetched.items.find(
449
+ (entry) => entry.externalId === "wide-file:wide-1",
450
+ );
451
+
452
+ expect(Buffer.byteLength(parent!.content, "utf8")).toBeLessThanOrEqual(
453
+ 128 * 1024,
454
+ );
455
+ expect(parent).toMatchObject({
456
+ kind: "figma-artboard-manifest",
457
+ metadata: {
458
+ nativeArtifact: {
459
+ manifest: { kind: "hierarchical-artboard" },
460
+ fidelityReport: { imageFallback: { count: 0 } },
461
+ },
462
+ },
463
+ });
464
+ expect(
465
+ (
466
+ parent?.metadata.nativeArtifact as {
467
+ manifest?: { children?: unknown[] };
468
+ }
469
+ ).manifest?.children,
470
+ ).toHaveLength(Math.ceil(children.length / 64));
471
+ expect(
472
+ fetched.items
473
+ .filter((entry) => entry.mimeType === "text/html")
474
+ .every(
475
+ (entry) => Buffer.byteLength(entry.content, "utf8") <= 128 * 1024,
476
+ ),
477
+ ).toBe(true);
478
+ expect(
479
+ fetched.items.filter((entry) =>
480
+ entry.externalId.includes(":manifest-bucket:"),
481
+ ),
482
+ ).toHaveLength(Math.ceil(children.length / 64));
483
+ expect(fetched.warnings).not.toEqual(
484
+ expect.arrayContaining([expect.stringContaining("localized rendered")]),
485
+ );
486
+ expect(
487
+ providerRequest.mock.calls.filter(
488
+ ([request]) =>
489
+ String(request.path).endsWith("/nodes") &&
490
+ (request.query as { ids?: string; depth?: number }).ids ===
491
+ "wide-1" &&
492
+ !(request.query as { depth?: number }).depth,
493
+ ),
494
+ ).toHaveLength(0);
495
+ });
496
+
497
+ it("never splits masks or groups and localizes fallback for an indivisible oversized group", async () => {
498
+ const maskFrame = {
499
+ id: "mask-frame",
500
+ name: "Masked composition",
501
+ type: "FRAME",
502
+ absoluteBoundingBox: { x: 0, y: 0, width: 20_000, height: 3_000 },
503
+ children: [
504
+ {
505
+ id: "mask-node",
506
+ name: "Mask",
507
+ type: "FRAME",
508
+ isMask: true,
509
+ absoluteBoundingBox: { x: 0, y: 0, width: 500, height: 500 },
510
+ children: [],
511
+ },
512
+ {
513
+ id: "masked-content",
514
+ name: "Masked content",
515
+ type: "FRAME",
516
+ absoluteBoundingBox: { x: 0, y: 0, width: 500, height: 500 },
517
+ children: [],
518
+ },
519
+ ],
520
+ };
521
+ const group = {
522
+ id: "group-1",
523
+ name: "Indivisible group",
524
+ type: "GROUP",
525
+ absoluteBoundingBox: { x: 0, y: 4_000, width: 20_000, height: 3_000 },
526
+ children: [
527
+ {
528
+ id: "group-child-1",
529
+ name: "First",
530
+ type: "FRAME",
531
+ absoluteBoundingBox: { x: 0, y: 4_000, width: 500, height: 500 },
532
+ children: [],
533
+ },
534
+ {
535
+ id: "group-child-2",
536
+ name: "Second",
537
+ type: "FRAME",
538
+ absoluteBoundingBox: { x: 600, y: 4_000, width: 500, height: 500 },
539
+ children: [],
540
+ },
541
+ ],
542
+ };
543
+ const providerRequest = vi.fn(async (input: Record<string, unknown>) => {
544
+ if (String(input.path).startsWith("/images/")) {
545
+ const ids = String((input.query as { ids?: string }).ids).split(",");
546
+ return {
547
+ images: Object.fromEntries(
548
+ ids.map((id) => [id, `https://cdn.example.com/${id}.png`]),
549
+ ),
550
+ };
551
+ }
552
+ if (String(input.path).endsWith("/nodes")) {
553
+ const query = input.query as { ids?: string; depth?: number };
554
+ if (query.ids === "group-1" && !query.depth) {
555
+ throw new Error("response too large: maximum response limit");
556
+ }
557
+ const node = query.ids === "group-1" ? group : maskFrame;
558
+ return { nodes: { [query.ids!]: { document: node } } };
559
+ }
560
+ if (String(input.path).endsWith("/images")) return { images: {} };
561
+ return {
562
+ name: "Composition file",
563
+ version: "composition-v1",
564
+ document: {
565
+ id: "document",
566
+ type: "DOCUMENT",
567
+ children: [
568
+ { id: "page", type: "CANVAS", children: [maskFrame, group] },
569
+ ],
570
+ },
571
+ };
572
+ });
573
+ const connector = new FigmaContextConnector();
574
+ const context = {
575
+ appId: "design",
576
+ ownerEmail: "owner@example.com",
577
+ resolveConnection: async () => "figma-connection",
578
+ providerApi: { executeRequest: providerRequest } as never,
579
+ putPrivateBlob: vi.fn(async () => ({
580
+ id: "private",
581
+ provider: "fixture",
582
+ opaque: true as const,
583
+ encrypted: true,
584
+ mimeType: "image/png",
585
+ })),
586
+ };
587
+ const [item] = (
588
+ await connector.inventory(
589
+ { sourceId: "source-1", config: { fileKeys: ["composition"] } },
590
+ context,
591
+ )
592
+ ).items;
593
+ const fetched = await connector.fetch(
594
+ { sourceId: "source-1", config: {}, item: item! },
595
+ context,
596
+ );
597
+ const masked = fetched.items.find(
598
+ (entry) => entry.externalId === "composition:mask-frame",
599
+ );
600
+ const grouped = fetched.items.find(
601
+ (entry) => entry.externalId === "composition:group-1",
602
+ );
603
+ expect(masked?.metadata.nativeArtifact).not.toHaveProperty("manifest");
604
+ expect(grouped).toMatchObject({
605
+ kind: "figma-frame",
606
+ metadata: {
607
+ nativeArtifact: {
608
+ fidelityReport: { imageFallback: { count: 1 } },
609
+ },
610
+ },
611
+ });
612
+ expect(grouped?.metadata.nativeArtifact).not.toHaveProperty("manifest");
613
+ expect(fetched.warnings).toEqual(
614
+ expect.arrayContaining([
615
+ expect.stringContaining("localized rendered fallback"),
616
+ ]),
617
+ );
618
+ });
619
+
620
+ it("keeps content-addressed asset routes stable across source versions", async () => {
621
+ let sourceVersion = "asset-v1";
622
+ let assetBytes = new Uint8Array([137, 80, 78, 71, 1]);
623
+ ssrfSafeFetch.mockImplementation(
624
+ async () =>
625
+ new Response(assetBytes, {
626
+ status: 200,
627
+ headers: { "content-type": "image/png" },
628
+ }),
629
+ );
630
+ const imageFrame = {
631
+ id: "asset-frame",
632
+ name: "Asset frame",
633
+ type: "FRAME",
634
+ absoluteBoundingBox: { x: 0, y: 0, width: 400, height: 300 },
635
+ fills: [{ type: "IMAGE", imageRef: "stable-fill", scaleMode: "FILL" }],
636
+ children: [],
637
+ };
638
+ const providerRequest = vi.fn(async (input: Record<string, unknown>) => {
639
+ if (String(input.path).endsWith("/nodes")) {
640
+ return { nodes: { "asset-frame": { document: imageFrame } } };
641
+ }
642
+ if (String(input.path).endsWith("/images")) {
643
+ return {
644
+ images: { "stable-fill": "https://cdn.example.com/stable.png" },
645
+ };
646
+ }
647
+ return {
648
+ name: "Asset file",
649
+ version: sourceVersion,
650
+ document: {
651
+ id: "document",
652
+ type: "DOCUMENT",
653
+ children: [{ id: "page", type: "CANVAS", children: [imageFrame] }],
654
+ },
655
+ };
656
+ });
657
+ const putPrivateBlob = vi.fn(
658
+ async (input: { key?: string; mimeType?: string }) => ({
659
+ id: input.key ?? "private-asset",
660
+ provider: "fixture",
661
+ opaque: true as const,
662
+ encrypted: true,
663
+ mimeType: input.mimeType,
664
+ }),
665
+ );
666
+ const context = {
667
+ appId: "design",
668
+ ownerEmail: "owner@example.com",
669
+ resolveConnection: async () => "figma-connection",
670
+ providerApi: { executeRequest: providerRequest } as never,
671
+ putPrivateBlob,
672
+ };
673
+ const connector = new FigmaContextConnector();
674
+ const fetchVersion = async () => {
675
+ const [item] = (
676
+ await connector.inventory(
677
+ { sourceId: "source-1", config: { fileKeys: ["asset-file"] } },
678
+ context,
679
+ )
680
+ ).items;
681
+ const fetched = await connector.fetch(
682
+ { sourceId: "source-1", config: {}, item: item! },
683
+ context,
684
+ );
685
+ return fetched.items.find(
686
+ (entry) => entry.externalId === "asset-file:asset-frame",
687
+ )!;
688
+ };
689
+
690
+ const first = await fetchVersion();
691
+ sourceVersion = "asset-v2";
692
+ const unchanged = await fetchVersion();
693
+ assetBytes = new Uint8Array([137, 80, 78, 71, 2]);
694
+ sourceVersion = "asset-v3";
695
+ const changed = await fetchVersion();
696
+
697
+ expect(unchanged.metadata.nativeArtifact).toMatchObject({
698
+ assetRefs: first.metadata.nativeArtifact.assetRefs,
699
+ });
700
+ expect(changed.metadata.nativeArtifact.assetRefs).not.toEqual(
701
+ first.metadata.nativeArtifact.assetRefs,
702
+ );
703
+ expect(putPrivateBlob.mock.calls[1]?.[0].key).toBe(
704
+ putPrivateBlob.mock.calls[0]?.[0].key,
705
+ );
706
+ expect(putPrivateBlob.mock.calls[2]?.[0].key).not.toBe(
707
+ putPrivateBlob.mock.calls[0]?.[0].key,
708
+ );
709
+ });
710
+ });
711
+
712
+ describe("Figma native fidelity reports", () => {
713
+ it("counts every fidelity entry while bounding only the detailed reasons", () => {
714
+ const approximated = Array.from({ length: 1_001 }, (_, index) => ({
715
+ nodeId: `approx-${index}`,
716
+ nodeName: `Approximation ${index}`,
717
+ nodeType: "FRAME",
718
+ level: "approximated" as const,
719
+ notes: ["Approximation detail"],
720
+ }));
721
+ const imageFallback = Array.from({ length: 1_002 }, (_, index) => ({
722
+ nodeId: `fallback-${index}`,
723
+ nodeName: `Fallback ${index}`,
724
+ nodeType: "VECTOR",
725
+ level: "image-fallback" as const,
726
+ notes: ["Rendered fallback detail"],
727
+ }));
728
+
729
+ const report = nativeFidelityReportFromEntries([
730
+ {
731
+ nodeId: "exact-1",
732
+ nodeName: "Exact",
733
+ nodeType: "RECTANGLE",
734
+ level: "exact",
735
+ notes: [],
736
+ },
737
+ ...approximated,
738
+ ...imageFallback,
739
+ ]);
740
+
741
+ expect(report.exact.count).toBe(1);
742
+ expect(report.approximated).toMatchObject({ count: 1_001 });
743
+ expect(report.approximated.reasons).toHaveLength(1_000);
744
+ expect(report.imageFallback).toMatchObject({ count: 1_002 });
745
+ expect(report.imageFallback.reasons).toHaveLength(1_000);
746
+ });
747
+ });
748
+
749
+ const FRAME = {
750
+ id: "frame-1",
751
+ name: "Hero",
752
+ type: "FRAME",
753
+ absoluteBoundingBox: { x: 0, y: 0, width: 1440, height: 900 },
754
+ layoutMode: "VERTICAL",
755
+ itemSpacing: 16,
756
+ styles: { fill: "style-root" },
757
+ fills: [
758
+ {
759
+ type: "GRADIENT_LINEAR",
760
+ gradientHandlePositions: [
761
+ { x: 0, y: 0 },
762
+ { x: 1, y: 0 },
763
+ ],
764
+ gradientStops: [
765
+ { position: 0, color: { r: 1, g: 0, b: 0, a: 1 } },
766
+ { position: 1, color: { r: 0, g: 0, b: 1, a: 1 } },
767
+ ],
768
+ },
769
+ ],
770
+ effects: [
771
+ {
772
+ type: "DROP_SHADOW",
773
+ visible: true,
774
+ radius: 12,
775
+ offset: { x: 0, y: 6 },
776
+ color: { r: 0, g: 0, b: 0, a: 0.25 },
777
+ },
778
+ ],
779
+ children: [
780
+ {
781
+ id: "logo-1",
782
+ name: "Primary Logo",
783
+ type: "VECTOR",
784
+ absoluteBoundingBox: { x: 0, y: 0, width: 120, height: 40 },
785
+ },
786
+ {
787
+ id: "text-1",
788
+ name: "Headline",
789
+ type: "TEXT",
790
+ absoluteBoundingBox: { x: 0, y: 60, width: 800, height: 80 },
791
+ characters: "Build beautiful things",
792
+ componentId: "component-7",
793
+ styles: { text: "style-type" },
794
+ style: { fontFamily: "Inter", fontSize: 48, fontWeight: 700 },
795
+ fills: [{ type: "SOLID", color: { r: 1, g: 0, b: 0 } }],
796
+ },
797
+ {
798
+ id: "image-1",
799
+ name: "Texture one",
800
+ type: "RECTANGLE",
801
+ absoluteBoundingBox: { x: 0, y: 180, width: 300, height: 200 },
802
+ fills: [{ type: "IMAGE", imageRef: "image-fill-1", scaleMode: "FILL" }],
803
+ },
804
+ {
805
+ id: "image-2",
806
+ name: "Texture two",
807
+ type: "RECTANGLE",
808
+ absoluteBoundingBox: { x: 320, y: 180, width: 300, height: 200 },
809
+ fills: [{ type: "IMAGE", imageRef: "image-fill-1", scaleMode: "FILL" }],
810
+ },
811
+ ],
812
+ };