@agent-native/core 0.7.13 → 0.7.14

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 (381) hide show
  1. package/dist/a2a/client.d.ts +44 -1
  2. package/dist/a2a/client.d.ts.map +1 -1
  3. package/dist/a2a/client.js +88 -11
  4. package/dist/a2a/client.js.map +1 -1
  5. package/dist/a2a/handlers.d.ts +10 -0
  6. package/dist/a2a/handlers.d.ts.map +1 -1
  7. package/dist/a2a/handlers.js +287 -62
  8. package/dist/a2a/handlers.js.map +1 -1
  9. package/dist/a2a/server.d.ts.map +1 -1
  10. package/dist/a2a/server.js +95 -17
  11. package/dist/a2a/server.js.map +1 -1
  12. package/dist/a2a/task-store.d.ts +11 -1
  13. package/dist/a2a/task-store.d.ts.map +1 -1
  14. package/dist/a2a/task-store.js +38 -2
  15. package/dist/a2a/task-store.js.map +1 -1
  16. package/dist/agent/engine/builder-engine.d.ts +1 -1
  17. package/dist/agent/engine/builder-engine.d.ts.map +1 -1
  18. package/dist/agent/engine/builder-engine.js +7 -25
  19. package/dist/agent/engine/builder-engine.js.map +1 -1
  20. package/dist/agent/engine/builtin.js +1 -1
  21. package/dist/agent/engine/builtin.js.map +1 -1
  22. package/dist/chat-threads/store.d.ts +3 -0
  23. package/dist/chat-threads/store.d.ts.map +1 -1
  24. package/dist/chat-threads/store.js +32 -0
  25. package/dist/chat-threads/store.js.map +1 -1
  26. package/dist/cli/templates-meta.d.ts.map +1 -1
  27. package/dist/cli/templates-meta.js +11 -0
  28. package/dist/cli/templates-meta.js.map +1 -1
  29. package/dist/client/AgentPanel.d.ts +3 -1
  30. package/dist/client/AgentPanel.d.ts.map +1 -1
  31. package/dist/client/AgentPanel.js +21 -10
  32. package/dist/client/AgentPanel.js.map +1 -1
  33. package/dist/client/AgentTaskCard.d.ts.map +1 -1
  34. package/dist/client/AgentTaskCard.js +2 -0
  35. package/dist/client/AgentTaskCard.js.map +1 -1
  36. package/dist/client/AssistantChat.d.ts +2 -0
  37. package/dist/client/AssistantChat.d.ts.map +1 -1
  38. package/dist/client/AssistantChat.js +111 -75
  39. package/dist/client/AssistantChat.js.map +1 -1
  40. package/dist/client/ErrorBoundary.d.ts +1 -3
  41. package/dist/client/ErrorBoundary.d.ts.map +1 -1
  42. package/dist/client/ErrorBoundary.js +37 -9
  43. package/dist/client/ErrorBoundary.js.map +1 -1
  44. package/dist/client/FeedbackButton.d.ts.map +1 -1
  45. package/dist/client/FeedbackButton.js +4 -3
  46. package/dist/client/FeedbackButton.js.map +1 -1
  47. package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
  48. package/dist/client/MultiTabAssistantChat.js +145 -49
  49. package/dist/client/MultiTabAssistantChat.js.map +1 -1
  50. package/dist/client/agent-chat.d.ts +11 -0
  51. package/dist/client/agent-chat.d.ts.map +1 -1
  52. package/dist/client/agent-chat.js +1 -1
  53. package/dist/client/agent-chat.js.map +1 -1
  54. package/dist/client/components/AgentPresenceChip.d.ts +12 -0
  55. package/dist/client/components/AgentPresenceChip.d.ts.map +1 -0
  56. package/dist/client/components/AgentPresenceChip.js +42 -0
  57. package/dist/client/components/AgentPresenceChip.js.map +1 -0
  58. package/dist/client/components/PresenceBar.d.ts +17 -0
  59. package/dist/client/components/PresenceBar.d.ts.map +1 -0
  60. package/dist/client/components/PresenceBar.js +118 -0
  61. package/dist/client/components/PresenceBar.js.map +1 -0
  62. package/dist/client/composer/ComposerPlusMenu.d.ts +6 -1
  63. package/dist/client/composer/ComposerPlusMenu.d.ts.map +1 -1
  64. package/dist/client/composer/ComposerPlusMenu.js +22 -83
  65. package/dist/client/composer/ComposerPlusMenu.js.map +1 -1
  66. package/dist/client/composer/TiptapComposer.d.ts.map +1 -1
  67. package/dist/client/composer/TiptapComposer.js +237 -16
  68. package/dist/client/composer/TiptapComposer.js.map +1 -1
  69. package/dist/client/composer/types.d.ts +1 -0
  70. package/dist/client/composer/types.d.ts.map +1 -1
  71. package/dist/client/composer/useVoiceDictation.d.ts +2 -0
  72. package/dist/client/composer/useVoiceDictation.d.ts.map +1 -1
  73. package/dist/client/composer/useVoiceDictation.js +85 -10
  74. package/dist/client/composer/useVoiceDictation.js.map +1 -1
  75. package/dist/client/index.d.ts +3 -0
  76. package/dist/client/index.d.ts.map +1 -1
  77. package/dist/client/index.js +5 -0
  78. package/dist/client/index.js.map +1 -1
  79. package/dist/client/org/RequireActiveOrg.d.ts.map +1 -1
  80. package/dist/client/org/RequireActiveOrg.js +15 -10
  81. package/dist/client/org/RequireActiveOrg.js.map +1 -1
  82. package/dist/client/org/TeamPage.d.ts.map +1 -1
  83. package/dist/client/org/TeamPage.js +125 -4
  84. package/dist/client/org/TeamPage.js.map +1 -1
  85. package/dist/client/org/hooks.d.ts +30 -0
  86. package/dist/client/org/hooks.d.ts.map +1 -1
  87. package/dist/client/org/hooks.js +65 -0
  88. package/dist/client/org/hooks.js.map +1 -1
  89. package/dist/client/org/index.d.ts +2 -2
  90. package/dist/client/org/index.d.ts.map +1 -1
  91. package/dist/client/org/index.js +1 -1
  92. package/dist/client/org/index.js.map +1 -1
  93. package/dist/client/resources/ResourcesPanel.d.ts.map +1 -1
  94. package/dist/client/resources/ResourcesPanel.js +5 -1
  95. package/dist/client/resources/ResourcesPanel.js.map +1 -1
  96. package/dist/client/settings/AutomationsSection.d.ts.map +1 -1
  97. package/dist/client/settings/AutomationsSection.js +1 -0
  98. package/dist/client/settings/AutomationsSection.js.map +1 -1
  99. package/dist/client/settings/SettingsPanel.d.ts.map +1 -1
  100. package/dist/client/settings/SettingsPanel.js +24 -11
  101. package/dist/client/settings/SettingsPanel.js.map +1 -1
  102. package/dist/client/sse-event-processor.d.ts.map +1 -1
  103. package/dist/client/sse-event-processor.js +10 -0
  104. package/dist/client/sse-event-processor.js.map +1 -1
  105. package/dist/client/tools/ToolEditor.d.ts +5 -0
  106. package/dist/client/tools/ToolEditor.d.ts.map +1 -0
  107. package/dist/client/tools/ToolEditor.js +98 -0
  108. package/dist/client/tools/ToolEditor.js.map +1 -0
  109. package/dist/client/tools/ToolViewer.d.ts +5 -0
  110. package/dist/client/tools/ToolViewer.d.ts.map +1 -0
  111. package/dist/client/tools/ToolViewer.js +309 -0
  112. package/dist/client/tools/ToolViewer.js.map +1 -0
  113. package/dist/client/tools/ToolViewerPage.d.ts +2 -0
  114. package/dist/client/tools/ToolViewerPage.d.ts.map +1 -0
  115. package/dist/client/tools/ToolViewerPage.js +23 -0
  116. package/dist/client/tools/ToolViewerPage.js.map +1 -0
  117. package/dist/client/tools/ToolsListPage.d.ts +2 -0
  118. package/dist/client/tools/ToolsListPage.d.ts.map +1 -0
  119. package/dist/client/tools/ToolsListPage.js +72 -0
  120. package/dist/client/tools/ToolsListPage.js.map +1 -0
  121. package/dist/client/tools/ToolsSidebarSection.d.ts +2 -0
  122. package/dist/client/tools/ToolsSidebarSection.d.ts.map +1 -0
  123. package/dist/client/tools/ToolsSidebarSection.js +188 -0
  124. package/dist/client/tools/ToolsSidebarSection.js.map +1 -0
  125. package/dist/client/tools/index.d.ts +6 -0
  126. package/dist/client/tools/index.d.ts.map +1 -0
  127. package/dist/client/tools/index.js +6 -0
  128. package/dist/client/tools/index.js.map +1 -0
  129. package/dist/client/use-chat-threads.d.ts +1 -0
  130. package/dist/client/use-chat-threads.d.ts.map +1 -1
  131. package/dist/client/use-chat-threads.js +29 -0
  132. package/dist/client/use-chat-threads.js.map +1 -1
  133. package/dist/client/use-db-sync.js +6 -6
  134. package/dist/client/use-db-sync.js.map +1 -1
  135. package/dist/collab/agent-identity.d.ts +15 -0
  136. package/dist/collab/agent-identity.d.ts.map +1 -0
  137. package/dist/collab/agent-identity.js +14 -0
  138. package/dist/collab/agent-identity.js.map +1 -0
  139. package/dist/collab/agent-presence.d.ts +59 -0
  140. package/dist/collab/agent-presence.d.ts.map +1 -0
  141. package/dist/collab/agent-presence.js +165 -0
  142. package/dist/collab/agent-presence.js.map +1 -0
  143. package/dist/collab/awareness.d.ts +7 -0
  144. package/dist/collab/awareness.d.ts.map +1 -1
  145. package/dist/collab/awareness.js +2 -2
  146. package/dist/collab/awareness.js.map +1 -1
  147. package/dist/collab/client-struct.d.ts +43 -0
  148. package/dist/collab/client-struct.d.ts.map +1 -0
  149. package/dist/collab/client-struct.js +272 -0
  150. package/dist/collab/client-struct.js.map +1 -0
  151. package/dist/collab/client.d.ts +2 -0
  152. package/dist/collab/client.d.ts.map +1 -1
  153. package/dist/collab/client.js +15 -1
  154. package/dist/collab/client.js.map +1 -1
  155. package/dist/collab/index.d.ts +6 -1
  156. package/dist/collab/index.d.ts.map +1 -1
  157. package/dist/collab/index.js +11 -1
  158. package/dist/collab/index.js.map +1 -1
  159. package/dist/collab/json-to-yjs.d.ts +72 -0
  160. package/dist/collab/json-to-yjs.d.ts.map +1 -0
  161. package/dist/collab/json-to-yjs.js +456 -0
  162. package/dist/collab/json-to-yjs.js.map +1 -0
  163. package/dist/collab/struct-routes.d.ts +52 -0
  164. package/dist/collab/struct-routes.d.ts.map +1 -0
  165. package/dist/collab/struct-routes.js +74 -0
  166. package/dist/collab/struct-routes.js.map +1 -0
  167. package/dist/collab/ydoc-manager.d.ts +19 -0
  168. package/dist/collab/ydoc-manager.d.ts.map +1 -1
  169. package/dist/collab/ydoc-manager.js +49 -0
  170. package/dist/collab/ydoc-manager.js.map +1 -1
  171. package/dist/deploy/build.js +1 -1
  172. package/dist/file-upload/builder.d.ts.map +1 -1
  173. package/dist/file-upload/builder.js +2 -1
  174. package/dist/file-upload/builder.js.map +1 -1
  175. package/dist/integrations/adapters/email.d.ts +17 -0
  176. package/dist/integrations/adapters/email.d.ts.map +1 -0
  177. package/dist/integrations/adapters/email.js +620 -0
  178. package/dist/integrations/adapters/email.js.map +1 -0
  179. package/dist/integrations/adapters/telegram.d.ts.map +1 -1
  180. package/dist/integrations/adapters/telegram.js +19 -3
  181. package/dist/integrations/adapters/telegram.js.map +1 -1
  182. package/dist/integrations/index.d.ts +1 -0
  183. package/dist/integrations/index.d.ts.map +1 -1
  184. package/dist/integrations/index.js +1 -0
  185. package/dist/integrations/index.js.map +1 -1
  186. package/dist/integrations/internal-token.d.ts +18 -0
  187. package/dist/integrations/internal-token.d.ts.map +1 -0
  188. package/dist/integrations/internal-token.js +86 -0
  189. package/dist/integrations/internal-token.js.map +1 -0
  190. package/dist/integrations/pending-tasks-retry-job.d.ts +15 -0
  191. package/dist/integrations/pending-tasks-retry-job.d.ts.map +1 -0
  192. package/dist/integrations/pending-tasks-retry-job.js +199 -0
  193. package/dist/integrations/pending-tasks-retry-job.js.map +1 -0
  194. package/dist/integrations/pending-tasks-store.d.ts +40 -0
  195. package/dist/integrations/pending-tasks-store.d.ts.map +1 -0
  196. package/dist/integrations/pending-tasks-store.js +151 -0
  197. package/dist/integrations/pending-tasks-store.js.map +1 -0
  198. package/dist/integrations/plugin.d.ts.map +1 -1
  199. package/dist/integrations/plugin.js +151 -9
  200. package/dist/integrations/plugin.js.map +1 -1
  201. package/dist/integrations/task-queue-stats.d.ts +22 -0
  202. package/dist/integrations/task-queue-stats.d.ts.map +1 -0
  203. package/dist/integrations/task-queue-stats.js +117 -0
  204. package/dist/integrations/task-queue-stats.js.map +1 -0
  205. package/dist/integrations/types.d.ts +2 -0
  206. package/dist/integrations/types.d.ts.map +1 -1
  207. package/dist/integrations/webhook-handler.d.ts +23 -4
  208. package/dist/integrations/webhook-handler.d.ts.map +1 -1
  209. package/dist/integrations/webhook-handler.js +217 -59
  210. package/dist/integrations/webhook-handler.js.map +1 -1
  211. package/dist/mcp-client/manager.d.ts +3 -0
  212. package/dist/mcp-client/manager.d.ts.map +1 -1
  213. package/dist/mcp-client/manager.js +5 -0
  214. package/dist/mcp-client/manager.js.map +1 -1
  215. package/dist/oauth-tokens/google-refresh.d.ts.map +1 -1
  216. package/dist/oauth-tokens/google-refresh.js +6 -0
  217. package/dist/oauth-tokens/google-refresh.js.map +1 -1
  218. package/dist/onboarding/default-steps.d.ts.map +1 -1
  219. package/dist/onboarding/default-steps.js +10 -3
  220. package/dist/onboarding/default-steps.js.map +1 -1
  221. package/dist/org/context.d.ts +35 -0
  222. package/dist/org/context.d.ts.map +1 -1
  223. package/dist/org/context.js +136 -0
  224. package/dist/org/context.js.map +1 -1
  225. package/dist/org/handlers.d.ts +76 -0
  226. package/dist/org/handlers.d.ts.map +1 -1
  227. package/dist/org/handlers.js +411 -2
  228. package/dist/org/handlers.js.map +1 -1
  229. package/dist/org/index.d.ts +2 -2
  230. package/dist/org/index.d.ts.map +1 -1
  231. package/dist/org/index.js +2 -2
  232. package/dist/org/index.js.map +1 -1
  233. package/dist/org/migrations.d.ts.map +1 -1
  234. package/dist/org/migrations.js +8 -0
  235. package/dist/org/migrations.js.map +1 -1
  236. package/dist/org/plugin.d.ts +6 -0
  237. package/dist/org/plugin.d.ts.map +1 -1
  238. package/dist/org/plugin.js +71 -7
  239. package/dist/org/plugin.js.map +1 -1
  240. package/dist/org/schema.d.ts +38 -0
  241. package/dist/org/schema.d.ts.map +1 -1
  242. package/dist/org/schema.js +2 -0
  243. package/dist/org/schema.js.map +1 -1
  244. package/dist/org/types.d.ts +7 -0
  245. package/dist/org/types.d.ts.map +1 -1
  246. package/dist/scripts/call-agent.d.ts.map +1 -1
  247. package/dist/scripts/call-agent.js +90 -18
  248. package/dist/scripts/call-agent.js.map +1 -1
  249. package/dist/scripts/db/index.d.ts.map +1 -1
  250. package/dist/scripts/db/index.js +2 -0
  251. package/dist/scripts/db/index.js.map +1 -1
  252. package/dist/scripts/db/migrate-user-api-keys.d.ts +24 -0
  253. package/dist/scripts/db/migrate-user-api-keys.d.ts.map +1 -0
  254. package/dist/scripts/db/migrate-user-api-keys.js +224 -0
  255. package/dist/scripts/db/migrate-user-api-keys.js.map +1 -0
  256. package/dist/scripts/db/wipe-leaked-builder-keys.d.ts +27 -0
  257. package/dist/scripts/db/wipe-leaked-builder-keys.d.ts.map +1 -0
  258. package/dist/scripts/db/wipe-leaked-builder-keys.js +163 -0
  259. package/dist/scripts/db/wipe-leaked-builder-keys.js.map +1 -0
  260. package/dist/secrets/register-framework-secrets.d.ts +5 -0
  261. package/dist/secrets/register-framework-secrets.d.ts.map +1 -1
  262. package/dist/secrets/register-framework-secrets.js +7 -44
  263. package/dist/secrets/register-framework-secrets.js.map +1 -1
  264. package/dist/secrets/substitution.d.ts.map +1 -1
  265. package/dist/secrets/substitution.js +14 -2
  266. package/dist/secrets/substitution.js.map +1 -1
  267. package/dist/server/action-discovery.d.ts.map +1 -1
  268. package/dist/server/action-discovery.js +39 -0
  269. package/dist/server/action-discovery.js.map +1 -1
  270. package/dist/server/action-routes.js +1 -1
  271. package/dist/server/action-routes.js.map +1 -1
  272. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  273. package/dist/server/agent-chat-plugin.js +192 -45
  274. package/dist/server/agent-chat-plugin.js.map +1 -1
  275. package/dist/server/auth.d.ts +14 -0
  276. package/dist/server/auth.d.ts.map +1 -1
  277. package/dist/server/auth.js +232 -17
  278. package/dist/server/auth.js.map +1 -1
  279. package/dist/server/builder-browser.d.ts +1 -1
  280. package/dist/server/builder-browser.d.ts.map +1 -1
  281. package/dist/server/builder-browser.js +12 -12
  282. package/dist/server/builder-browser.js.map +1 -1
  283. package/dist/server/collab-plugin.d.ts +4 -0
  284. package/dist/server/collab-plugin.d.ts.map +1 -1
  285. package/dist/server/collab-plugin.js +30 -4
  286. package/dist/server/collab-plugin.js.map +1 -1
  287. package/dist/server/core-routes-plugin.d.ts.map +1 -1
  288. package/dist/server/core-routes-plugin.js +106 -100
  289. package/dist/server/core-routes-plugin.js.map +1 -1
  290. package/dist/server/credential-provider.d.ts +43 -2
  291. package/dist/server/credential-provider.d.ts.map +1 -1
  292. package/dist/server/credential-provider.js +115 -2
  293. package/dist/server/credential-provider.js.map +1 -1
  294. package/dist/server/design-token-utils.d.ts +132 -0
  295. package/dist/server/design-token-utils.d.ts.map +1 -0
  296. package/dist/server/design-token-utils.js +714 -0
  297. package/dist/server/design-token-utils.js.map +1 -0
  298. package/dist/server/email.d.ts +10 -0
  299. package/dist/server/email.d.ts.map +1 -1
  300. package/dist/server/email.js +63 -16
  301. package/dist/server/email.js.map +1 -1
  302. package/dist/server/framework-request-handler.d.ts.map +1 -1
  303. package/dist/server/framework-request-handler.js +38 -3
  304. package/dist/server/framework-request-handler.js.map +1 -1
  305. package/dist/server/google-oauth.d.ts +18 -1
  306. package/dist/server/google-oauth.d.ts.map +1 -1
  307. package/dist/server/google-oauth.js +21 -4
  308. package/dist/server/google-oauth.js.map +1 -1
  309. package/dist/server/index.d.ts +3 -3
  310. package/dist/server/index.d.ts.map +1 -1
  311. package/dist/server/index.js +3 -3
  312. package/dist/server/index.js.map +1 -1
  313. package/dist/server/onboarding-html.d.ts.map +1 -1
  314. package/dist/server/onboarding-html.js +14 -1
  315. package/dist/server/onboarding-html.js.map +1 -1
  316. package/dist/server/transcribe-voice.d.ts.map +1 -1
  317. package/dist/server/transcribe-voice.js +89 -24
  318. package/dist/server/transcribe-voice.js.map +1 -1
  319. package/dist/sharing/schema.d.ts +1 -1
  320. package/dist/styles/agent-native.css +5 -0
  321. package/dist/templates/default/app/root.tsx +50 -13
  322. package/dist/templates/default/react-router.config.ts +3 -0
  323. package/dist/terminal/terminal-plugin.d.ts.map +1 -1
  324. package/dist/terminal/terminal-plugin.js +23 -3
  325. package/dist/terminal/terminal-plugin.js.map +1 -1
  326. package/dist/tools/actions.d.ts +3 -0
  327. package/dist/tools/actions.d.ts.map +1 -0
  328. package/dist/tools/actions.js +140 -0
  329. package/dist/tools/actions.js.map +1 -0
  330. package/dist/tools/fetch-tool.js +1 -1
  331. package/dist/tools/fetch-tool.js.map +1 -1
  332. package/dist/tools/html-shell.d.ts +2 -0
  333. package/dist/tools/html-shell.d.ts.map +1 -0
  334. package/dist/tools/html-shell.js +387 -0
  335. package/dist/tools/html-shell.js.map +1 -0
  336. package/dist/tools/routes.d.ts +2 -0
  337. package/dist/tools/routes.d.ts.map +1 -0
  338. package/dist/tools/routes.js +576 -0
  339. package/dist/tools/routes.js.map +1 -0
  340. package/dist/tools/schema.d.ts +575 -0
  341. package/dist/tools/schema.d.ts.map +1 -0
  342. package/dist/tools/schema.js +112 -0
  343. package/dist/tools/schema.js.map +1 -0
  344. package/dist/tools/store.d.ts +40 -0
  345. package/dist/tools/store.d.ts.map +1 -0
  346. package/dist/tools/store.js +190 -0
  347. package/dist/tools/store.js.map +1 -0
  348. package/dist/tools/theme.d.ts +2 -0
  349. package/dist/tools/theme.d.ts.map +1 -0
  350. package/dist/tools/theme.js +67 -0
  351. package/dist/tools/theme.js.map +1 -0
  352. package/dist/transcription/builder-transcription.d.ts.map +1 -1
  353. package/dist/transcription/builder-transcription.js +26 -14
  354. package/dist/transcription/builder-transcription.js.map +1 -1
  355. package/dist/vite/action-types-plugin.d.ts.map +1 -1
  356. package/dist/vite/action-types-plugin.js +10 -2
  357. package/dist/vite/action-types-plugin.js.map +1 -1
  358. package/dist/vite/client.d.ts.map +1 -1
  359. package/dist/vite/client.js +26 -6
  360. package/dist/vite/client.js.map +1 -1
  361. package/docs/content/a2a-protocol.md +2 -2
  362. package/docs/content/authentication.md +51 -0
  363. package/docs/content/cloneable-saas.md +59 -62
  364. package/docs/content/faq.md +73 -43
  365. package/docs/content/getting-started.md +37 -61
  366. package/docs/content/mcp-clients.md +14 -1
  367. package/docs/content/messaging.md +284 -0
  368. package/docs/content/pure-agent-apps.md +55 -28
  369. package/docs/content/template-calendar.md +61 -56
  370. package/docs/content/template-clips.md +22 -18
  371. package/docs/content/template-content.md +36 -26
  372. package/docs/content/template-dispatch.md +2 -1
  373. package/docs/content/template-forms.md +13 -11
  374. package/docs/content/template-slides.md +43 -31
  375. package/docs/content/template-video.md +49 -22
  376. package/docs/content/tools.md +107 -0
  377. package/docs/content/what-is-agent-native.md +89 -105
  378. package/package.json +4 -1
  379. package/src/templates/default/app/root.tsx +50 -13
  380. package/src/templates/default/react-router.config.ts +3 -0
  381. package/docs/content/integrations.md +0 -198
@@ -0,0 +1,714 @@
1
+ /**
2
+ * Shared design-token extraction utilities.
3
+ *
4
+ * Pure functions for parsing Tailwind configs, CSS files, package.json,
5
+ * documents, and URLs to extract colors, fonts, spacing, border-radius,
6
+ * and CSS custom properties. Used by the import-* actions across all
7
+ * templates (design, slides, videos).
8
+ *
9
+ * No framework dependencies — no defineAction, no zod, no drizzle.
10
+ */
11
+ // ---------------------------------------------------------------------------
12
+ // Constants
13
+ // ---------------------------------------------------------------------------
14
+ /** Maximum number of files to fetch from a single GitHub repo. */
15
+ export const MAX_FILES = 10;
16
+ /** Maximum individual file size (100 KB). */
17
+ export const MAX_FILE_SIZE = 100 * 1024;
18
+ /** Timeout for GitHub API / URL fetch calls (ms). */
19
+ export const FETCH_TIMEOUT = 15000;
20
+ /** File-name patterns to look for at the repo root. */
21
+ export const ROOT_PATTERNS = [
22
+ /^tailwind\.config\.\w+$/,
23
+ /^postcss\.config\.\w+$/,
24
+ /^\.?theme\.\w+$/,
25
+ /^\.?tokens\.\w+$/,
26
+ /^package\.json$/,
27
+ /\.css$/,
28
+ ];
29
+ /** Secondary paths (files and directories) to check for design tokens. */
30
+ export const SECONDARY_PATHS = [
31
+ "src/styles",
32
+ "styles",
33
+ "src/theme",
34
+ "app/globals.css",
35
+ "src/globals.css",
36
+ "src/index.css",
37
+ "app/layout.tsx",
38
+ "src/app/globals.css",
39
+ ];
40
+ /** Maximum files accepted in import-code. */
41
+ export const CODE_MAX_FILES = 20;
42
+ /** Maximum total bytes accepted in import-code. */
43
+ export const CODE_MAX_TOTAL_BYTES = 500 * 1024;
44
+ /** Regex for hex colors (3-8 digit, including alpha). */
45
+ export const HEX_COLOR_RE = /#(?:[0-9a-fA-F]{3,4}){1,2}\b/g;
46
+ /** Regex for well-known named CSS colors. */
47
+ export const NAMED_COLOR_RE = /\b(red|blue|green|yellow|orange|purple|pink|cyan|magenta|teal|navy|maroon|coral|salmon|gold|silver|gray|grey|indigo|violet|lime|olive|aqua|fuchsia|crimson|turquoise|ivory|beige|lavender|tan|khaki|plum|orchid|sienna)\b/gi;
48
+ /** Regex for well-known font family names found in documents. */
49
+ export const FONT_NAME_RE = /\b(Helvetica|Arial|Times New Roman|Georgia|Garamond|Futura|Bodoni|Avenir|Proxima Nova|Montserrat|Open Sans|Lato|Poppins|Raleway|Playfair Display|Merriweather|Source Sans|Noto Sans|Work Sans|Nunito|Rubik|Oswald|Roboto|Inter|DM Sans|Space Grotesk|SF Pro|Segoe UI|Calibri|Cambria|Century Gothic|Franklin Gothic|Gill Sans|Fira Sans|Barlow|Manrope|Sora|Plus Jakarta Sans|IBM Plex Sans|IBM Plex Serif|Libre Baskerville|Cormorant|Crimson Text)\b/gi;
50
+ /** Regex matching CSS custom property values that look like colors. */
51
+ export const COLOR_VAR_PATTERN = /^(#[0-9a-fA-F]{3,8}|rgba?\(|hsla?\(|oklch\(|color\()/;
52
+ /** Well-known styling framework deps to detect in package.json. */
53
+ export const FRAMEWORK_DETECTORS = [
54
+ { name: "tailwindcss", label: "tailwind" },
55
+ { name: "@tailwindcss/cli", label: "tailwind" },
56
+ { name: "styled-components", label: "styled-components" },
57
+ { name: "@emotion/react", label: "emotion" },
58
+ { name: "@emotion/styled", label: "emotion" },
59
+ { name: "sass", label: "sass" },
60
+ { name: "less", label: "less" },
61
+ { name: "postcss", label: "postcss" },
62
+ { name: "css-modules", label: "css-modules" },
63
+ { name: "@vanilla-extract/css", label: "vanilla-extract" },
64
+ { name: "stitches", label: "stitches" },
65
+ { name: "panda-css", label: "panda-css" },
66
+ { name: "@pandacss/dev", label: "panda-css" },
67
+ { name: "unocss", label: "unocss" },
68
+ { name: "windicss", label: "windi" },
69
+ ];
70
+ // ---------------------------------------------------------------------------
71
+ // SSRF Guard
72
+ // ---------------------------------------------------------------------------
73
+ /** Validate a URL is safe to fetch (blocks localhost, private IPs, metadata endpoints). */
74
+ export function validateUrl(url) {
75
+ const parsed = new URL(url);
76
+ if (!["http:", "https:"].includes(parsed.protocol)) {
77
+ throw new Error("Only http and https URLs are allowed");
78
+ }
79
+ const hostname = parsed.hostname;
80
+ if (hostname === "localhost" ||
81
+ hostname === "127.0.0.1" ||
82
+ hostname === "0.0.0.0" ||
83
+ hostname === "[::1]" ||
84
+ hostname.startsWith("10.") ||
85
+ hostname.startsWith("172.16.") ||
86
+ hostname.startsWith("172.17.") ||
87
+ hostname.startsWith("172.18.") ||
88
+ hostname.startsWith("172.19.") ||
89
+ hostname.startsWith("172.2") ||
90
+ hostname.startsWith("172.30.") ||
91
+ hostname.startsWith("172.31.") ||
92
+ hostname.startsWith("192.168.") ||
93
+ hostname.endsWith(".internal") ||
94
+ hostname.endsWith(".local") ||
95
+ hostname === "metadata.google.internal" ||
96
+ hostname === "169.254.169.254") {
97
+ throw new Error("Internal/private URLs are not allowed");
98
+ }
99
+ }
100
+ // ---------------------------------------------------------------------------
101
+ // GitHub helpers
102
+ // ---------------------------------------------------------------------------
103
+ /** Parse a GitHub URL or "org/repo" shorthand into owner + repo. */
104
+ export function parseOwnerRepo(raw) {
105
+ const shorthand = raw.match(/^([^/]+)\/([^/]+)$/);
106
+ if (shorthand) {
107
+ return { owner: shorthand[1], repo: shorthand[2] };
108
+ }
109
+ const urlMatch = raw.match(/github\.com\/([^/]+)\/([^/]+?)(?:\.git)?(?:\/.*)?$/);
110
+ if (urlMatch) {
111
+ return { owner: urlMatch[1], repo: urlMatch[2] };
112
+ }
113
+ throw new Error("Could not parse GitHub owner/repo from URL. " +
114
+ 'Expected format: "https://github.com/org/repo" or "org/repo"');
115
+ }
116
+ /** Fetch a path from the GitHub Contents API as JSON. Returns null on error. */
117
+ export async function fetchGitHubJson(owner, repo, path) {
118
+ const url = `https://api.github.com/repos/${owner}/${repo}/contents/${path}`;
119
+ validateUrl(url);
120
+ const res = await fetch(url, {
121
+ headers: {
122
+ Accept: "application/vnd.github.v3+json",
123
+ "User-Agent": "AgentNative/1.0",
124
+ },
125
+ signal: AbortSignal.timeout(FETCH_TIMEOUT),
126
+ });
127
+ if (!res.ok)
128
+ return null;
129
+ return res.json();
130
+ }
131
+ /** Fetch raw file content from the GitHub Contents API. Returns null on error or oversize. */
132
+ export async function fetchGitHubRaw(owner, repo, path) {
133
+ const url = `https://api.github.com/repos/${owner}/${repo}/contents/${path}`;
134
+ validateUrl(url);
135
+ const res = await fetch(url, {
136
+ headers: {
137
+ Accept: "application/vnd.github.v3.raw",
138
+ "User-Agent": "AgentNative/1.0",
139
+ },
140
+ signal: AbortSignal.timeout(FETCH_TIMEOUT),
141
+ });
142
+ if (!res.ok)
143
+ return null;
144
+ const cl = res.headers.get("content-length");
145
+ if (cl && parseInt(cl, 10) > MAX_FILE_SIZE)
146
+ return null;
147
+ const text = await res.text();
148
+ if (text.length > MAX_FILE_SIZE)
149
+ return null;
150
+ return text;
151
+ }
152
+ // ---------------------------------------------------------------------------
153
+ // Tailwind config parser
154
+ // ---------------------------------------------------------------------------
155
+ /** Extract colors, fonts, spacing, borderRadius from a Tailwind config file string. */
156
+ export function parseTailwindConfig(content) {
157
+ const result = {};
158
+ const colorsMatch = content.match(/colors\s*:\s*(\{[\s\S]*?\n\s{4}\}|\{[^}]+\})/);
159
+ if (colorsMatch) {
160
+ try {
161
+ const colors = {};
162
+ const pairs = colorsMatch[1].matchAll(/['"]?([\w-]+)['"]?\s*:\s*['"]([^'"]+)['"]/g);
163
+ for (const p of pairs) {
164
+ colors[p[1]] = p[2];
165
+ }
166
+ if (Object.keys(colors).length > 0)
167
+ result.colors = colors;
168
+ }
169
+ catch {
170
+ // skip
171
+ }
172
+ }
173
+ const fontMatch = content.match(/fontFamily\s*:\s*(\{[\s\S]*?\n\s{4}\}|\{[^}]+\})/);
174
+ if (fontMatch) {
175
+ const fonts = {};
176
+ const pairs = fontMatch[1].matchAll(/['"]?([\w-]+)['"]?\s*:\s*\[?\s*['"]([^'"]+)['"]/g);
177
+ for (const p of pairs) {
178
+ fonts[p[1]] = p[2];
179
+ }
180
+ if (Object.keys(fonts).length > 0)
181
+ result.fontFamily = fonts;
182
+ }
183
+ const spacingMatch = content.match(/spacing\s*:\s*(\{[\s\S]*?\n\s{4}\}|\{[^}]+\})/);
184
+ if (spacingMatch) {
185
+ const spacing = {};
186
+ const pairs = spacingMatch[1].matchAll(/['"]?([\w.-]+)['"]?\s*:\s*['"]([^'"]+)['"]/g);
187
+ for (const p of pairs) {
188
+ spacing[p[1]] = p[2];
189
+ }
190
+ if (Object.keys(spacing).length > 0)
191
+ result.spacing = spacing;
192
+ }
193
+ const radiusMatch = content.match(/borderRadius\s*:\s*(\{[\s\S]*?\n\s{4}\}|\{[^}]+\})/);
194
+ if (radiusMatch) {
195
+ const radii = {};
196
+ const pairs = radiusMatch[1].matchAll(/['"]?([\w-]+)['"]?\s*:\s*['"]([^'"]+)['"]/g);
197
+ for (const p of pairs) {
198
+ radii[p[1]] = p[2];
199
+ }
200
+ if (Object.keys(radii).length > 0)
201
+ result.borderRadius = radii;
202
+ }
203
+ return result;
204
+ }
205
+ // ---------------------------------------------------------------------------
206
+ // CSS parser
207
+ // ---------------------------------------------------------------------------
208
+ /** Extract CSS custom properties and @font-face / Google Fonts from CSS content. */
209
+ export function parseCss(content) {
210
+ const cssCustomProperties = {};
211
+ const varMatches = content.matchAll(/--([\w-]+)\s*:\s*([^;}\n]+)/g);
212
+ for (const m of varMatches) {
213
+ cssCustomProperties[`--${m[1]}`] = m[2].trim();
214
+ }
215
+ const fonts = [];
216
+ const fontFaceMatches = content.matchAll(/@font-face\s*\{([^}]+)\}/g);
217
+ for (const m of fontFaceMatches) {
218
+ const familyMatch = m[1].match(/font-family\s*:\s*["']?([^"';]+)["']?/);
219
+ if (familyMatch)
220
+ fonts.push(familyMatch[1].trim());
221
+ }
222
+ const importMatches = content.matchAll(/@import\s+url\(\s*['"]?(fonts\.googleapis\.com[^'")\s]+)['"]?\s*\)/g);
223
+ for (const m of importMatches) {
224
+ const familyParam = m[1].match(/family=([^&"')\s]+)/);
225
+ if (familyParam) {
226
+ fonts.push(decodeURIComponent(familyParam[1]).replace(/\+/g, " "));
227
+ }
228
+ }
229
+ return {
230
+ cssCustomProperties: Object.keys(cssCustomProperties).length > 0
231
+ ? cssCustomProperties
232
+ : undefined,
233
+ fonts: fonts.length > 0 ? [...new Set(fonts)] : undefined,
234
+ };
235
+ }
236
+ // ---------------------------------------------------------------------------
237
+ // Styling framework detection
238
+ // ---------------------------------------------------------------------------
239
+ /** Detect the styling framework from a package.json string. */
240
+ export function detectStylingFramework(content) {
241
+ try {
242
+ const pkg = JSON.parse(content);
243
+ const all = {
244
+ ...pkg.dependencies,
245
+ ...pkg.devDependencies,
246
+ };
247
+ if (all["tailwindcss"] || all["@tailwindcss/cli"])
248
+ return "tailwindcss";
249
+ if (all["styled-components"])
250
+ return "styled-components";
251
+ if (all["@emotion/react"] || all["@emotion/styled"])
252
+ return "emotion";
253
+ if (all["sass"] || all["node-sass"])
254
+ return "sass";
255
+ if (all["less"])
256
+ return "less";
257
+ if (all["@vanilla-extract/css"])
258
+ return "vanilla-extract";
259
+ if (all["windicss"])
260
+ return "windicss";
261
+ if (all["unocss"])
262
+ return "unocss";
263
+ return undefined;
264
+ }
265
+ catch {
266
+ return undefined;
267
+ }
268
+ }
269
+ // ---------------------------------------------------------------------------
270
+ // Code file analysis helpers (import-code)
271
+ // ---------------------------------------------------------------------------
272
+ /** Create a fresh state object for code file analysis. */
273
+ export function createCodeAnalysisState() {
274
+ return {
275
+ colors: {},
276
+ cssCustomProperties: {},
277
+ fonts: [],
278
+ spacing: {},
279
+ borderRadius: {},
280
+ stylingFramework: null,
281
+ rawExtracts: [],
282
+ seenFonts: new Set(),
283
+ };
284
+ }
285
+ /** De-duplicate and add a font to the analysis state. */
286
+ export function addFont(state, family, source) {
287
+ const normalized = family.trim().replace(/["']/g, "");
288
+ if (!normalized || state.seenFonts.has(normalized.toLowerCase()))
289
+ return;
290
+ state.seenFonts.add(normalized.toLowerCase());
291
+ state.fonts.push({ family: normalized, source });
292
+ }
293
+ /** Extract CSS custom properties, classifying them by name into colors/spacing/radius. */
294
+ export function extractCssVars(state, content) {
295
+ const pattern = /--([\w-]+)\s*:\s*([^;}\n]+)/g;
296
+ let match;
297
+ while ((match = pattern.exec(content)) !== null) {
298
+ const name = `--${match[1]}`;
299
+ const value = match[2].trim();
300
+ state.cssCustomProperties[name] = value;
301
+ if (/color|bg|background|text|border|accent|primary|secondary|surface|muted|foreground/i.test(match[1])) {
302
+ state.colors[name] = value;
303
+ }
304
+ else if (/spacing|gap|padding|margin|space/i.test(match[1])) {
305
+ state.spacing[name] = value;
306
+ }
307
+ else if (/radius|rounded/i.test(match[1])) {
308
+ state.borderRadius[name] = value;
309
+ }
310
+ }
311
+ }
312
+ /** Extract literal color values (hex, rgb, hsl, oklch) from content. */
313
+ export function extractCodeColors(state, content) {
314
+ const hexPattern = /#[0-9a-fA-F]{3,8}\b/g;
315
+ let m;
316
+ while ((m = hexPattern.exec(content)) !== null) {
317
+ state.colors[m[0]] = m[0];
318
+ }
319
+ const rgbPattern = /rgba?\(\s*\d+\s*,\s*\d+\s*,\s*\d+(?:\s*,\s*[\d.]+)?\s*\)/g;
320
+ while ((m = rgbPattern.exec(content)) !== null) {
321
+ state.colors[m[0]] = m[0];
322
+ }
323
+ const hslPattern = /hsla?\(\s*\d+\s*,\s*[\d.]+%\s*,\s*[\d.]+%(?:\s*,\s*[\d.]+)?\s*\)/g;
324
+ while ((m = hslPattern.exec(content)) !== null) {
325
+ state.colors[m[0]] = m[0];
326
+ }
327
+ const oklchPattern = /oklch\(\s*[\d.]+%?\s+[\d.]+\s+[\d.]+(?:\s*\/\s*[\d.]+)?\s*\)/g;
328
+ while ((m = oklchPattern.exec(content)) !== null) {
329
+ state.colors[m[0]] = m[0];
330
+ }
331
+ }
332
+ /** Extract font-family declarations and @font-face blocks from CSS-like content. */
333
+ export function extractCodeFonts(state, content, filename) {
334
+ const fontFamilyPattern = /font-family\s*:\s*["']?([^"';}\n]+)/g;
335
+ let m;
336
+ while ((m = fontFamilyPattern.exec(content)) !== null) {
337
+ const families = m[1].split(",");
338
+ for (const fam of families) {
339
+ const trimmed = fam.trim().replace(/["']/g, "");
340
+ if (trimmed &&
341
+ !/^(sans-serif|serif|monospace|cursive|fantasy|system-ui|inherit|initial)$/i.test(trimmed)) {
342
+ addFont(state, trimmed, filename);
343
+ }
344
+ }
345
+ }
346
+ const fontFacePattern = /@font-face\s*\{([^}]+)\}/g;
347
+ while ((m = fontFacePattern.exec(content)) !== null) {
348
+ const block = m[1];
349
+ const familyMatch = block.match(/font-family\s*:\s*["']?([^"';]+)["']?/);
350
+ if (familyMatch) {
351
+ addFont(state, familyMatch[1], filename);
352
+ }
353
+ }
354
+ }
355
+ /** Analyze a CSS/SCSS/LESS file, extracting vars, colors, and fonts. */
356
+ export function analyzeCssFile(state, content, filename) {
357
+ extractCssVars(state, content);
358
+ extractCodeColors(state, content);
359
+ extractCodeFonts(state, content, filename);
360
+ state.rawExtracts.push({ filename, type: "css", data: { parsed: true } });
361
+ }
362
+ /** Analyze a Tailwind config file for tokens. */
363
+ export function analyzeTailwindConfig(state, content, filename) {
364
+ state.stylingFramework = "tailwind";
365
+ const colorsBlockMatch = content.match(/colors\s*:\s*\{([\s\S]*?)\}/);
366
+ if (colorsBlockMatch) {
367
+ const pairPattern = /["']?([\w-]+)["']?\s*:\s*["']([^"']+)["']/g;
368
+ let m;
369
+ while ((m = pairPattern.exec(colorsBlockMatch[1])) !== null) {
370
+ state.colors[m[1]] = m[2];
371
+ }
372
+ }
373
+ const fontFamilyBlockMatch = content.match(/fontFamily\s*:\s*\{([\s\S]*?)\}/);
374
+ if (fontFamilyBlockMatch) {
375
+ const fontPairPattern = /["']?([\w-]+)["']?\s*:\s*\[?\s*["']([^"']+)["']/g;
376
+ let m;
377
+ while ((m = fontPairPattern.exec(fontFamilyBlockMatch[1])) !== null) {
378
+ addFont(state, m[2], filename);
379
+ }
380
+ }
381
+ const spacingBlockMatch = content.match(/spacing\s*:\s*\{([\s\S]*?)\}/);
382
+ if (spacingBlockMatch) {
383
+ const pairPattern = /["']?([\w.-]+)["']?\s*:\s*["']([^"']+)["']/g;
384
+ let m;
385
+ while ((m = pairPattern.exec(spacingBlockMatch[1])) !== null) {
386
+ state.spacing[m[1]] = m[2];
387
+ }
388
+ }
389
+ const radiusBlockMatch = content.match(/borderRadius\s*:\s*\{([\s\S]*?)\}/);
390
+ if (radiusBlockMatch) {
391
+ const pairPattern = /["']?([\w-]+)["']?\s*:\s*["']([^"']+)["']/g;
392
+ let m;
393
+ while ((m = pairPattern.exec(radiusBlockMatch[1])) !== null) {
394
+ state.borderRadius[m[1]] = m[2];
395
+ }
396
+ }
397
+ extractCodeColors(state, content);
398
+ state.rawExtracts.push({
399
+ filename,
400
+ type: "tailwind-config",
401
+ data: {
402
+ hasColors: !!colorsBlockMatch,
403
+ hasFontFamily: !!fontFamilyBlockMatch,
404
+ hasSpacing: !!spacingBlockMatch,
405
+ hasBorderRadius: !!radiusBlockMatch,
406
+ },
407
+ });
408
+ }
409
+ /** Walk a parsed JSON theme object, extracting tokens into state. */
410
+ export function analyzeJsonTheme(state, content, filename) {
411
+ try {
412
+ const json = JSON.parse(content);
413
+ const walk = (obj, prefix) => {
414
+ for (const [key, value] of Object.entries(obj)) {
415
+ const path = prefix ? `${prefix}.${key}` : key;
416
+ if (typeof value === "string") {
417
+ const lower = key.toLowerCase();
418
+ if (/color|bg|background|text|border|accent|primary|secondary|surface/i.test(lower) ||
419
+ /^#[0-9a-fA-F]{3,8}$/.test(value)) {
420
+ state.colors[path] = value;
421
+ }
422
+ else if (/font|family|typeface/i.test(lower)) {
423
+ addFont(state, value, filename);
424
+ }
425
+ else if (/spacing|gap|padding|margin|space/i.test(lower)) {
426
+ state.spacing[path] = value;
427
+ }
428
+ else if (/radius|rounded/i.test(lower)) {
429
+ state.borderRadius[path] = value;
430
+ }
431
+ }
432
+ else if (value &&
433
+ typeof value === "object" &&
434
+ !Array.isArray(value)) {
435
+ walk(value, path);
436
+ }
437
+ }
438
+ };
439
+ walk(json, "");
440
+ state.rawExtracts.push({
441
+ filename,
442
+ type: "json-theme",
443
+ data: { keys: Object.keys(json) },
444
+ });
445
+ }
446
+ catch {
447
+ state.rawExtracts.push({
448
+ filename,
449
+ type: "json-theme",
450
+ data: { parseError: true },
451
+ });
452
+ }
453
+ }
454
+ /** Analyze package.json for styling framework deps. */
455
+ export function analyzePackageJson(state, content, filename) {
456
+ try {
457
+ const json = JSON.parse(content);
458
+ const allDeps = {
459
+ ...json.dependencies,
460
+ ...json.devDependencies,
461
+ };
462
+ const detected = [];
463
+ for (const fw of FRAMEWORK_DETECTORS) {
464
+ if (allDeps && fw.name in allDeps) {
465
+ detected.push(fw.label);
466
+ if (!state.stylingFramework) {
467
+ state.stylingFramework = fw.label;
468
+ }
469
+ }
470
+ }
471
+ state.rawExtracts.push({
472
+ filename,
473
+ type: "package-json",
474
+ data: { stylingDeps: detected },
475
+ });
476
+ }
477
+ catch {
478
+ state.rawExtracts.push({
479
+ filename,
480
+ type: "package-json",
481
+ data: { parseError: true },
482
+ });
483
+ }
484
+ }
485
+ /** Analyze a theme source file (theme.ts, tokens.ts) for design tokens. */
486
+ export function analyzeThemeSourceFile(state, content, filename) {
487
+ const namedHexPattern = /(?:const|let|var|export)\s+(\w+)\s*=\s*["']?(#[0-9a-fA-F]{3,8})\b/g;
488
+ let m;
489
+ while ((m = namedHexPattern.exec(content)) !== null) {
490
+ state.colors[m[1]] = m[2];
491
+ }
492
+ const kvHexPattern = /["']?([\w-]+)["']?\s*:\s*["'](#[0-9a-fA-F]{3,8})["']/g;
493
+ while ((m = kvHexPattern.exec(content)) !== null) {
494
+ state.colors[m[1]] = m[2];
495
+ }
496
+ const fontStringPattern = /(?:font|family|typeface)\w*\s*[:=]\s*["']([^"']+)["']/gi;
497
+ while ((m = fontStringPattern.exec(content)) !== null) {
498
+ addFont(state, m[1], filename);
499
+ }
500
+ const spacingPattern = /(?:spacing|gap|padding|margin)\w*\s*[:=]\s*["']([^"']+)["']/gi;
501
+ while ((m = spacingPattern.exec(content)) !== null) {
502
+ state.spacing[m[0].split(/[:=]/)[0].trim()] = m[1];
503
+ }
504
+ extractCodeColors(state, content);
505
+ state.rawExtracts.push({
506
+ filename,
507
+ type: "theme-source",
508
+ data: { parsed: true },
509
+ });
510
+ }
511
+ /** Route a file to the correct analyzer based on filename. */
512
+ export function analyzeCodeFile(state, filename, content) {
513
+ const name = filename.toLowerCase();
514
+ const basename = name.split("/").pop() ?? name;
515
+ if (basename.startsWith("tailwind.config")) {
516
+ analyzeTailwindConfig(state, content, filename);
517
+ }
518
+ else if (basename === "package.json") {
519
+ analyzePackageJson(state, content, filename);
520
+ }
521
+ else if (basename === "theme.json" ||
522
+ basename === "tokens.json" ||
523
+ basename.endsWith(".tokens.json")) {
524
+ analyzeJsonTheme(state, content, filename);
525
+ }
526
+ else if (name.endsWith(".css")) {
527
+ analyzeCssFile(state, content, filename);
528
+ }
529
+ else if (/^theme\.(ts|js)$/.test(basename) ||
530
+ /^tokens\.(ts|js)$/.test(basename)) {
531
+ analyzeThemeSourceFile(state, content, filename);
532
+ }
533
+ else if (name.endsWith(".ts") ||
534
+ name.endsWith(".tsx") ||
535
+ name.endsWith(".js") ||
536
+ name.endsWith(".jsx")) {
537
+ extractCodeColors(state, content);
538
+ extractCodeFonts(state, content, filename);
539
+ extractCssVars(state, content);
540
+ state.rawExtracts.push({
541
+ filename,
542
+ type: "source",
543
+ data: { lightPass: true },
544
+ });
545
+ }
546
+ else if (name.endsWith(".json")) {
547
+ analyzeJsonTheme(state, content, filename);
548
+ }
549
+ else if (name.endsWith(".scss") ||
550
+ name.endsWith(".sass") ||
551
+ name.endsWith(".less")) {
552
+ analyzeCssFile(state, content, filename);
553
+ if (!state.stylingFramework) {
554
+ state.stylingFramework = name.endsWith(".less") ? "less" : "sass";
555
+ }
556
+ }
557
+ }
558
+ // ---------------------------------------------------------------------------
559
+ // Document analysis helpers (import-document)
560
+ // ---------------------------------------------------------------------------
561
+ /** Deduplicate and trim an array of strings. */
562
+ export function unique(arr) {
563
+ return [...new Set(arr.map((s) => s.trim()))];
564
+ }
565
+ /** Extract hex and named colors from plain text. */
566
+ export function extractDocumentColors(text) {
567
+ const hex = text.match(HEX_COLOR_RE) ?? [];
568
+ const named = text.match(NAMED_COLOR_RE) ?? [];
569
+ return unique([...hex, ...named.map((n) => n.toLowerCase())]);
570
+ }
571
+ /** Extract known font family names from plain text. */
572
+ export function extractDocumentFonts(text) {
573
+ const matches = text.match(FONT_NAME_RE) ?? [];
574
+ return unique(matches);
575
+ }
576
+ /** Classify a file type string into a content category. */
577
+ export function classifyFile(fileType) {
578
+ const ft = fileType.toLowerCase();
579
+ if (ft.includes("pptx") ||
580
+ ft.includes("ppt") ||
581
+ ft.includes("presentation") ||
582
+ ft.includes("keynote"))
583
+ return "presentation";
584
+ if (ft.includes("docx") ||
585
+ ft.includes("doc") ||
586
+ ft.includes("document") ||
587
+ ft.includes("rtf"))
588
+ return "document";
589
+ if (ft.includes("xlsx") ||
590
+ ft.includes("xls") ||
591
+ ft.includes("spreadsheet") ||
592
+ ft.includes("csv"))
593
+ return "spreadsheet";
594
+ if (ft.includes("pdf"))
595
+ return "pdf";
596
+ return "other";
597
+ }
598
+ /** Return per-type suggestions for how to use a document for design extraction. */
599
+ export function suggestionsForType(contentType, hasText) {
600
+ const base = [];
601
+ switch (contentType) {
602
+ case "presentation":
603
+ base.push("Look for slide master/theme colors — these define the brand palette", "Check heading fonts on title slides for the brand typeface", "Note any accent colors used for callouts or highlights", "Slide backgrounds may reveal primary and secondary brand colors", "Chart/graph colors often match the brand accent palette");
604
+ break;
605
+ case "document":
606
+ base.push("Heading styles reveal the typographic hierarchy and heading font", "Body text font is likely the primary readable typeface", "Look for colored headings or accent text for brand colors", "Document margins and spacing suggest preferred density", "Header/footer formatting may include brand colors or logos");
607
+ break;
608
+ case "spreadsheet":
609
+ base.push("Header row colors often reflect the brand palette", "Conditional formatting colors may indicate status/accent colors", "Chart and graph colors are strong brand palette signals", "Cell background highlighting colors suggest accent palette");
610
+ break;
611
+ case "pdf":
612
+ base.push("PDF may contain embedded brand guidelines or style specs", "Look for consistent heading colors and font choices", "Background colors and accent bars reveal brand palette");
613
+ break;
614
+ case "other":
615
+ base.push("Examine any visual elements for recurring color patterns", "Note any typography that appears intentionally branded");
616
+ break;
617
+ }
618
+ if (!hasText) {
619
+ base.push("No text content was extracted — ask the user to paste key sections or send the file as a chat attachment for visual analysis");
620
+ }
621
+ return base;
622
+ }
623
+ // ---------------------------------------------------------------------------
624
+ // URL scraping helpers (import-from-url)
625
+ // ---------------------------------------------------------------------------
626
+ /** Fetch and extract design tokens from a URL's HTML. */
627
+ export async function extractDesignTokensFromUrl(rawUrl) {
628
+ const url = rawUrl.startsWith("http") ? rawUrl : `https://${rawUrl}`;
629
+ validateUrl(url);
630
+ const response = await fetch(url, {
631
+ headers: {
632
+ "User-Agent": "Mozilla/5.0 (compatible; AgentNative/1.0; +https://agent-native.com)",
633
+ },
634
+ signal: AbortSignal.timeout(10000),
635
+ });
636
+ const html = await response.text();
637
+ const result = { url };
638
+ // Title
639
+ const titleMatch = html.match(/<title[^>]*>([^<]+)<\/title>/i);
640
+ if (titleMatch) {
641
+ result.pageTitle = titleMatch[1].trim();
642
+ }
643
+ // Meta description
644
+ const descMatch = html.match(/<meta[^>]*name=["']description["'][^>]*content=["']([^"']+)["']/i);
645
+ if (descMatch) {
646
+ result.metaDescription = descMatch[1];
647
+ }
648
+ // Meta theme-color
649
+ const themeColorMatch = html.match(/<meta[^>]*name=["']theme-color["'][^>]*content=["']([^"']+)["']/i);
650
+ if (themeColorMatch) {
651
+ result.themeColor = themeColorMatch[1];
652
+ }
653
+ // CSS custom properties
654
+ const cssVarMatches = html.matchAll(/--([\w-]+)\s*:\s*([^;}\n]+)/g);
655
+ const cssVars = {};
656
+ for (const match of cssVarMatches) {
657
+ cssVars[`--${match[1]}`] = match[2].trim();
658
+ }
659
+ if (Object.keys(cssVars).length > 0) {
660
+ const entries = Object.entries(cssVars).slice(0, 50);
661
+ result.cssCustomProperties = Object.fromEntries(entries);
662
+ }
663
+ // Inline colors (hex, rgb)
664
+ const colorMatches = new Set();
665
+ const hexPattern = /#[0-9a-fA-F]{3,8}\b/g;
666
+ let hexMatch;
667
+ while ((hexMatch = hexPattern.exec(html)) !== null) {
668
+ colorMatches.add(hexMatch[0]);
669
+ }
670
+ const rgbPattern = /rgba?\(\s*\d+\s*,\s*\d+\s*,\s*\d+(?:\s*,\s*[\d.]+)?\s*\)/g;
671
+ let rgbMatch;
672
+ while ((rgbMatch = rgbPattern.exec(html)) !== null) {
673
+ colorMatches.add(rgbMatch[0]);
674
+ }
675
+ if (colorMatches.size > 0) {
676
+ result.colors = [...colorMatches].slice(0, 30);
677
+ }
678
+ // @font-face
679
+ const fontFaceMatches = html.matchAll(/@font-face\s*\{([^}]+)\}/g);
680
+ const fonts = [];
681
+ for (const match of fontFaceMatches) {
682
+ const block = match[1];
683
+ const familyMatch = block.match(/font-family\s*:\s*["']?([^"';]+)["']?/);
684
+ const srcMatch = block.match(/src\s*:\s*([^;]+)/);
685
+ fonts.push({
686
+ family: familyMatch?.[1]?.trim(),
687
+ src: srcMatch?.[1]?.trim()?.slice(0, 200),
688
+ });
689
+ }
690
+ if (fonts.length > 0) {
691
+ result.fontFaces = fonts.slice(0, 20);
692
+ }
693
+ // Google Fonts
694
+ const googleFontMatches = html.matchAll(/fonts\.googleapis\.com\/css2?\?[^"'>\s]+/g);
695
+ const googleFonts = [];
696
+ for (const match of googleFontMatches) {
697
+ googleFonts.push(match[0]);
698
+ }
699
+ if (googleFonts.length > 0) {
700
+ result.googleFonts = googleFonts;
701
+ }
702
+ // OG image
703
+ const ogImageMatch = html.match(/<meta[^>]*property=["']og:image["'][^>]*content=["']([^"']+)["']/i);
704
+ if (ogImageMatch) {
705
+ result.ogImage = ogImageMatch[1];
706
+ }
707
+ // Favicon
708
+ const faviconMatch = html.match(/<link[^>]*rel=["'](?:icon|shortcut icon)["'][^>]*href=["']([^"']+)["']/i);
709
+ if (faviconMatch) {
710
+ result.favicon = faviconMatch[1];
711
+ }
712
+ return result;
713
+ }
714
+ //# sourceMappingURL=design-token-utils.js.map