@agent-native/core 0.108.0 → 0.109.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (368) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +25 -0
  3. package/corpus/core/package.json +1 -1
  4. package/corpus/core/src/a2a/client.ts +162 -17
  5. package/corpus/core/src/a2a/correlation.ts +50 -0
  6. package/corpus/core/src/a2a/handlers.ts +200 -14
  7. package/corpus/core/src/a2a/index.ts +7 -1
  8. package/corpus/core/src/a2a/invoke.ts +77 -1
  9. package/corpus/core/src/a2a/server.ts +13 -1
  10. package/corpus/core/src/a2a/task-store.ts +146 -6
  11. package/corpus/core/src/a2a/types.ts +32 -0
  12. package/corpus/core/src/action.ts +5 -2
  13. package/corpus/core/src/agent/production-agent.ts +33 -4
  14. package/corpus/core/src/client/AssistantChat.tsx +648 -603
  15. package/corpus/core/src/client/MultiTabAssistantChat.tsx +31 -4
  16. package/corpus/core/src/client/agent-chat-adapter.ts +23 -37
  17. package/corpus/core/src/client/agent-sidebar-state.ts +4 -0
  18. package/corpus/core/src/client/analytics.ts +84 -0
  19. package/corpus/core/src/client/chat/message-components.tsx +94 -22
  20. package/corpus/core/src/client/chat/tool-call-display.tsx +170 -47
  21. package/corpus/core/src/client/chat/use-agent-chat-lifecycle-tracking.ts +74 -0
  22. package/corpus/core/src/client/chat-thread-url.ts +11 -0
  23. package/corpus/core/src/client/error-capture.ts +12 -0
  24. package/corpus/core/src/client/extensions/ExtensionSlot.tsx +37 -1
  25. package/corpus/core/src/client/index.ts +2 -0
  26. package/corpus/core/src/client/route-chunk-recovery.ts +20 -8
  27. package/corpus/core/src/client/session-replay.ts +31 -0
  28. package/corpus/core/src/client/use-run-stuck-detection.ts +27 -1
  29. package/corpus/core/src/db/client.ts +55 -0
  30. package/corpus/core/src/extensions/actions.ts +2 -14
  31. package/corpus/core/src/extensions/store.ts +1 -1
  32. package/corpus/core/src/localization/default-messages.ts +3 -0
  33. package/corpus/core/src/mcp/build-server.ts +2 -2
  34. package/corpus/core/src/observability/traces.ts +172 -19
  35. package/corpus/core/src/progress/actions.ts +4 -2
  36. package/corpus/core/src/provider-api/index.ts +205 -105
  37. package/corpus/core/src/scripts/call-agent.ts +190 -19
  38. package/corpus/core/src/server/agent-chat/action-filters-a2a.ts +112 -25
  39. package/corpus/core/src/server/agent-chat-plugin.ts +136 -4
  40. package/corpus/core/src/styles/agent-conversation.css +7 -0
  41. package/corpus/core/src/templates/default/app/i18n/ar-SA.ts +20 -0
  42. package/corpus/core/src/templates/default/app/i18n/de-DE.ts +20 -0
  43. package/corpus/core/src/templates/default/app/i18n/en-US.ts +20 -0
  44. package/corpus/core/src/templates/default/app/i18n/es-ES.ts +20 -0
  45. package/corpus/core/src/templates/default/app/i18n/fr-FR.ts +21 -0
  46. package/corpus/core/src/templates/default/app/i18n/hi-IN.ts +19 -0
  47. package/corpus/core/src/templates/default/app/i18n/ja-JP.ts +20 -0
  48. package/corpus/core/src/templates/default/app/i18n/ko-KR.ts +19 -0
  49. package/corpus/core/src/templates/default/app/i18n/pt-BR.ts +20 -0
  50. package/corpus/core/src/templates/default/app/i18n/zh-CN.ts +19 -0
  51. package/corpus/core/src/templates/default/app/i18n/zh-TW.ts +19 -0
  52. package/corpus/core/src/templates/workspace-core/.agents/skills/a2a-protocol/SKILL.md +49 -0
  53. package/corpus/core/src/templates/workspace-core/.agents/skills/composable-mini-apps/SKILL.md +5 -0
  54. package/corpus/core/src/templates/workspace-core/.agents/skills/observability/SKILL.md +7 -1
  55. package/corpus/core/src/templates/workspace-core/.agents/skills/performance/SKILL.md +13 -0
  56. package/corpus/core/src/templates/workspace-core/.agents/skills/tracking/SKILL.md +1 -1
  57. package/corpus/templates/analytics/.agents/skills/dashboard-management/SKILL.md +29 -10
  58. package/corpus/templates/analytics/.agents/skills/gong/SKILL.md +54 -23
  59. package/corpus/templates/analytics/.builder/skills/apollo/SKILL.md +19 -41
  60. package/corpus/templates/analytics/.builder/skills/commonroom/SKILL.md +20 -35
  61. package/corpus/templates/analytics/.builder/skills/github/SKILL.md +23 -67
  62. package/corpus/templates/analytics/.builder/skills/pylon/SKILL.md +25 -43
  63. package/corpus/templates/analytics/AGENTS.md +22 -13
  64. package/corpus/templates/analytics/actions/account-deep-dive.ts +1 -0
  65. package/corpus/templates/analytics/actions/configure-gong-native-insights.ts +29 -0
  66. package/corpus/templates/analytics/actions/content-calendar-schema.ts +8 -4
  67. package/corpus/templates/analytics/actions/content-calendar.ts +12 -4
  68. package/corpus/templates/analytics/actions/dashboard-mutation-api.ts +2 -1
  69. package/corpus/templates/analytics/actions/gong-calls.ts +113 -22
  70. package/corpus/templates/analytics/actions/gong-native-insights.ts +166 -0
  71. package/corpus/templates/analytics/actions/hubspot-deals.ts +190 -46
  72. package/corpus/templates/analytics/actions/pylon-issues.ts +123 -0
  73. package/corpus/templates/analytics/actions/query-agent-native-analytics.ts +1 -1
  74. package/corpus/templates/analytics/actions/slack-messages.ts +179 -27
  75. package/corpus/templates/analytics/app/components/dashboard/SqlChart.tsx +48 -152
  76. package/corpus/templates/analytics/app/components/ui/chart.tsx +1 -1
  77. package/corpus/templates/analytics/app/hooks/use-chart-tooltip-flip.ts +21 -6
  78. package/corpus/templates/analytics/app/i18n/zh-TW.ts +13 -0
  79. package/corpus/templates/analytics/app/i18n-data.ts +134 -0
  80. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/PanelEditorDialog.tsx +181 -30
  81. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/SqlChartCard.tsx +6 -0
  82. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/types.ts +4 -3
  83. package/corpus/templates/analytics/changelog/2026-07-17-analytics-now-includes-a-default-alert-for-spikes-in-stuck-agent-chats.md +6 -0
  84. package/corpus/templates/analytics/changelog/2026-07-17-dashboard-editors-can-add-shared-extensions-or-opt-into-per-.md +6 -0
  85. package/corpus/templates/analytics/changelog/2026-07-17-dashboard-extensions-show-a-loading-skeleton.md +6 -0
  86. package/corpus/templates/analytics/changelog/2026-07-17-errors-now-group-repeat-failures-consistently-and-keep-priva.md +6 -0
  87. package/corpus/templates/analytics/changelog/2026-07-17-gong-transcript-reviews-now-batch-bounded-call-windows-for-f.md +6 -0
  88. package/corpus/templates/analytics/changelog/2026-07-17-hubspot-deal-filters-now-run-in-hubspot-before-paging-result.md +6 -0
  89. package/corpus/templates/analytics/changelog/2026-07-17-notion-content-calendars-now-discover-the-matching-database-.md +6 -0
  90. package/corpus/templates/analytics/changelog/2026-07-17-pylon-dashboard-reads-now-use-the-paginated-issue-search-api.md +6 -0
  91. package/corpus/templates/analytics/changelog/2026-07-17-slack-reads-no-longer-join-channels-and-report-pagination-coverage.md +6 -0
  92. package/corpus/templates/analytics/docs/schemas/first-party-analytics.md +23 -14
  93. package/corpus/templates/analytics/docs/schemas/tracked-events.md +5 -1
  94. package/corpus/templates/analytics/server/handlers/notion.ts +14 -3
  95. package/corpus/templates/analytics/server/handlers/slack.ts +182 -29
  96. package/corpus/templates/analytics/server/jobs/analytics-alerts.ts +3 -3
  97. package/corpus/templates/analytics/server/lib/agent-chat-plan-mode.ts +2 -6
  98. package/corpus/templates/analytics/server/lib/analytics-alerts.ts +209 -87
  99. package/corpus/templates/analytics/server/lib/analytics-connector-catalog.ts +6 -2
  100. package/corpus/templates/analytics/server/lib/error-capture.ts +75 -8
  101. package/corpus/templates/analytics/server/lib/gong-native-policy.ts +72 -0
  102. package/corpus/templates/analytics/server/lib/gong.ts +54 -66
  103. package/corpus/templates/analytics/server/lib/hubspot.ts +40 -3
  104. package/corpus/templates/analytics/server/lib/notion.ts +83 -8
  105. package/corpus/templates/analytics/server/lib/real-data-actions.ts +4 -0
  106. package/corpus/templates/analytics/server/lib/slack.ts +242 -90
  107. package/corpus/templates/analytics/server/plugins/agent-chat.ts +3 -3
  108. package/corpus/templates/analytics/server/routes/api/pylon/accounts.get.ts +42 -1
  109. package/corpus/templates/analytics/server/routes/api/pylon/issues.get.ts +71 -1
  110. package/corpus/templates/analytics/server/routes/api/test-connection.post.ts +44 -4
  111. package/corpus/templates/clips/actions/finalize-recording.ts +541 -62
  112. package/corpus/templates/clips/app/components/library/bulk-action-toolbar.tsx +19 -1
  113. package/corpus/templates/clips/app/components/library/create-folder-dialog.tsx +123 -0
  114. package/corpus/templates/clips/app/components/library/library-grid.tsx +42 -4
  115. package/corpus/templates/clips/app/components/library/recording-card.tsx +30 -0
  116. package/corpus/templates/clips/app/components/player/playback-comment-overlay.tsx +17 -2
  117. package/corpus/templates/clips/app/components/player/video-player.tsx +14 -2
  118. package/corpus/templates/clips/app/components/recorder/recorder-engine.ts +2 -2
  119. package/corpus/templates/clips/app/entry.client.tsx +6 -1
  120. package/corpus/templates/clips/app/i18n/ar-SA.ts +12 -1
  121. package/corpus/templates/clips/app/i18n/de-DE.ts +12 -1
  122. package/corpus/templates/clips/app/i18n/en-US.ts +12 -1
  123. package/corpus/templates/clips/app/i18n/es-ES.ts +11 -1
  124. package/corpus/templates/clips/app/i18n/fr-FR.ts +11 -1
  125. package/corpus/templates/clips/app/i18n/hi-IN.ts +10 -1
  126. package/corpus/templates/clips/app/i18n/ja-JP.ts +12 -1
  127. package/corpus/templates/clips/app/i18n/ko-KR.ts +11 -1
  128. package/corpus/templates/clips/app/i18n/pt-BR.ts +11 -1
  129. package/corpus/templates/clips/app/i18n/zh-CN.ts +11 -1
  130. package/corpus/templates/clips/app/i18n/zh-TW.ts +11 -1
  131. package/corpus/templates/clips/app/routes/_app.settings._index.tsx +72 -1
  132. package/corpus/templates/clips/app/routes/r.$recordingId.tsx +1 -1
  133. package/corpus/templates/clips/app/routes/record.tsx +3 -3
  134. package/corpus/templates/clips/app/routes/share.$shareId.tsx +6 -3
  135. package/corpus/templates/clips/changelog/2026-07-17-choose-which-workspace-receives-new-clips-recordings-and-des.md +6 -0
  136. package/corpus/templates/clips/changelog/2026-07-17-clips-now-retries-storage-verification-in-the-background-ins.md +6 -0
  137. package/corpus/templates/clips/changelog/2026-07-17-create-folders-directly-from-the-move-menu.md +6 -0
  138. package/corpus/templates/clips/changelog/2026-07-17-failed-desktop-uploads-now-offer-a-direct-way-to-reopen-clip.md +6 -0
  139. package/corpus/templates/clips/changelog/2026-07-17-fixed-broken-thumbnail-icons-appearing-over-playable-clip-em.md +6 -0
  140. package/corpus/templates/clips/changelog/2026-07-17-playback-comments-stay-readable-at-faster-playback-speeds.md +6 -0
  141. package/corpus/templates/clips/chrome-extension/src/finalize-recovery.ts +3 -0
  142. package/corpus/templates/clips/chrome-extension/src/offscreen.ts +3 -3
  143. package/corpus/templates/clips/desktop/src/app.tsx +19 -7
  144. package/corpus/templates/clips/desktop/src/lib/recorder.ts +111 -13
  145. package/corpus/templates/clips/desktop/src/lib/upload-verification.ts +16 -7
  146. package/corpus/templates/clips/desktop/src-tauri/src/lib.rs +2 -4
  147. package/corpus/templates/clips/desktop/src-tauri/src/native_screen/live_upload.rs +32 -15
  148. package/corpus/templates/clips/desktop/src-tauri/src/native_screen.rs +45 -18
  149. package/corpus/templates/clips/server/jobs/media-verification.ts +130 -0
  150. package/corpus/templates/clips/server/lib/builder-media-compression.ts +15 -0
  151. package/corpus/templates/clips/server/lib/media-verification-state.ts +38 -0
  152. package/corpus/templates/clips/server/lib/player-thumbnail-url.ts +31 -0
  153. package/corpus/templates/clips/server/lib/post-finalize-dispatch.ts +10 -3
  154. package/corpus/templates/clips/server/plugins/auth.ts +5 -5
  155. package/corpus/templates/clips/server/plugins/calendar-jobs.ts +2 -0
  156. package/corpus/templates/clips/server/routes/api/_agent-native-background/post-finalize-worker.post.ts +12 -2
  157. package/corpus/templates/clips/server/routes/api/public-recording.get.ts +6 -1
  158. package/corpus/templates/clips/server/routes/api/thumbnail/[recordingId].get.ts +340 -0
  159. package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/abort.post.ts +24 -7
  160. package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/chunk.post.ts +91 -7
  161. package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/status.get.ts +14 -0
  162. package/corpus/templates/clips/shared/finalize-recovery.ts +61 -2
  163. package/corpus/templates/clips/shared/share-meta.ts +1 -1
  164. package/corpus/templates/content/app/entry.client.tsx +6 -1
  165. package/corpus/templates/dispatch/AGENTS.md +5 -0
  166. package/corpus/templates/dispatch/changelog/2026-07-17-apps-page-links-to-other-available-apps.md +6 -0
  167. package/corpus/templates/dispatch/changelog/2026-07-17-curated-template-remixes.md +6 -0
  168. package/corpus/templates/mail/app/entry.client.tsx +6 -1
  169. package/corpus/templates/slides/.agents/skills/slide-images/SKILL.md +11 -7
  170. package/corpus/templates/slides/.env.example +0 -1
  171. package/corpus/templates/slides/AGENTS.md +4 -0
  172. package/corpus/templates/slides/DEVELOPING.md +2 -2
  173. package/corpus/templates/slides/actions/index-design-system-with-builder.ts +1 -1
  174. package/corpus/templates/slides/actions/logo-config.ts +6 -7
  175. package/corpus/templates/slides/actions/search-images.ts +11 -39
  176. package/corpus/templates/slides/actions/search-logos.ts +5 -52
  177. package/corpus/templates/slides/app/components/editor/ImageSearchPanel.tsx +1 -1
  178. package/corpus/templates/slides/app/components/editor/LogoSearchPanel.tsx +16 -26
  179. package/corpus/templates/slides/app/entry.client.tsx +6 -1
  180. package/corpus/templates/slides/server/lib/media-search-providers.ts +216 -0
  181. package/corpus/templates/slides/server/register-secrets.ts +30 -0
  182. package/dist/a2a/client.d.ts +47 -1
  183. package/dist/a2a/client.d.ts.map +1 -1
  184. package/dist/a2a/client.js +94 -12
  185. package/dist/a2a/client.js.map +1 -1
  186. package/dist/a2a/correlation.d.ts +10 -0
  187. package/dist/a2a/correlation.d.ts.map +1 -0
  188. package/dist/a2a/correlation.js +40 -0
  189. package/dist/a2a/correlation.js.map +1 -0
  190. package/dist/a2a/handlers.d.ts.map +1 -1
  191. package/dist/a2a/handlers.js +147 -15
  192. package/dist/a2a/handlers.js.map +1 -1
  193. package/dist/a2a/index.d.ts +4 -4
  194. package/dist/a2a/index.d.ts.map +1 -1
  195. package/dist/a2a/index.js +2 -2
  196. package/dist/a2a/index.js.map +1 -1
  197. package/dist/a2a/invoke.d.ts +29 -2
  198. package/dist/a2a/invoke.d.ts.map +1 -1
  199. package/dist/a2a/invoke.js +33 -1
  200. package/dist/a2a/invoke.js.map +1 -1
  201. package/dist/a2a/server.d.ts.map +1 -1
  202. package/dist/a2a/server.js +14 -1
  203. package/dist/a2a/server.js.map +1 -1
  204. package/dist/a2a/task-store.d.ts +12 -1
  205. package/dist/a2a/task-store.d.ts.map +1 -1
  206. package/dist/a2a/task-store.js +96 -6
  207. package/dist/a2a/task-store.js.map +1 -1
  208. package/dist/a2a/types.d.ts +27 -0
  209. package/dist/a2a/types.d.ts.map +1 -1
  210. package/dist/a2a/types.js.map +1 -1
  211. package/dist/action.d.ts +5 -2
  212. package/dist/action.d.ts.map +1 -1
  213. package/dist/action.js.map +1 -1
  214. package/dist/agent/production-agent.d.ts +14 -0
  215. package/dist/agent/production-agent.d.ts.map +1 -1
  216. package/dist/agent/production-agent.js +19 -3
  217. package/dist/agent/production-agent.js.map +1 -1
  218. package/dist/client/AssistantChat.d.ts +14 -1
  219. package/dist/client/AssistantChat.d.ts.map +1 -1
  220. package/dist/client/AssistantChat.js +158 -136
  221. package/dist/client/AssistantChat.js.map +1 -1
  222. package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
  223. package/dist/client/MultiTabAssistantChat.js +27 -4
  224. package/dist/client/MultiTabAssistantChat.js.map +1 -1
  225. package/dist/client/agent-chat-adapter.d.ts.map +1 -1
  226. package/dist/client/agent-chat-adapter.js +21 -39
  227. package/dist/client/agent-chat-adapter.js.map +1 -1
  228. package/dist/client/agent-sidebar-state.d.ts +1 -0
  229. package/dist/client/agent-sidebar-state.d.ts.map +1 -1
  230. package/dist/client/agent-sidebar-state.js +4 -0
  231. package/dist/client/agent-sidebar-state.js.map +1 -1
  232. package/dist/client/analytics.d.ts +14 -0
  233. package/dist/client/analytics.d.ts.map +1 -1
  234. package/dist/client/analytics.js +67 -0
  235. package/dist/client/analytics.js.map +1 -1
  236. package/dist/client/chat/message-components.d.ts +8 -0
  237. package/dist/client/chat/message-components.d.ts.map +1 -1
  238. package/dist/client/chat/message-components.js +62 -19
  239. package/dist/client/chat/message-components.js.map +1 -1
  240. package/dist/client/chat/tool-call-display.d.ts +6 -0
  241. package/dist/client/chat/tool-call-display.d.ts.map +1 -1
  242. package/dist/client/chat/tool-call-display.js +83 -14
  243. package/dist/client/chat/tool-call-display.js.map +1 -1
  244. package/dist/client/chat/use-agent-chat-lifecycle-tracking.d.ts +8 -0
  245. package/dist/client/chat/use-agent-chat-lifecycle-tracking.d.ts.map +1 -0
  246. package/dist/client/chat/use-agent-chat-lifecycle-tracking.js +51 -0
  247. package/dist/client/chat/use-agent-chat-lifecycle-tracking.js.map +1 -0
  248. package/dist/client/chat-thread-url.d.ts +2 -0
  249. package/dist/client/chat-thread-url.d.ts.map +1 -0
  250. package/dist/client/chat-thread-url.js +12 -0
  251. package/dist/client/chat-thread-url.js.map +1 -0
  252. package/dist/client/error-capture.d.ts.map +1 -1
  253. package/dist/client/error-capture.js +7 -0
  254. package/dist/client/error-capture.js.map +1 -1
  255. package/dist/client/extensions/ExtensionSlot.d.ts +3 -1
  256. package/dist/client/extensions/ExtensionSlot.d.ts.map +1 -1
  257. package/dist/client/extensions/ExtensionSlot.js +28 -3
  258. package/dist/client/extensions/ExtensionSlot.js.map +1 -1
  259. package/dist/client/index.d.ts +1 -1
  260. package/dist/client/index.d.ts.map +1 -1
  261. package/dist/client/index.js +1 -1
  262. package/dist/client/index.js.map +1 -1
  263. package/dist/client/route-chunk-recovery.d.ts.map +1 -1
  264. package/dist/client/route-chunk-recovery.js +14 -9
  265. package/dist/client/route-chunk-recovery.js.map +1 -1
  266. package/dist/client/session-replay.d.ts +15 -0
  267. package/dist/client/session-replay.d.ts.map +1 -1
  268. package/dist/client/session-replay.js +20 -0
  269. package/dist/client/session-replay.js.map +1 -1
  270. package/dist/client/use-run-stuck-detection.d.ts.map +1 -1
  271. package/dist/client/use-run-stuck-detection.js +25 -1
  272. package/dist/client/use-run-stuck-detection.js.map +1 -1
  273. package/dist/db/client.d.ts +7 -0
  274. package/dist/db/client.d.ts.map +1 -1
  275. package/dist/db/client.js +33 -0
  276. package/dist/db/client.js.map +1 -1
  277. package/dist/extensions/actions.d.ts.map +1 -1
  278. package/dist/extensions/actions.js +2 -10
  279. package/dist/extensions/actions.js.map +1 -1
  280. package/dist/extensions/store.js +1 -1
  281. package/dist/extensions/store.js.map +1 -1
  282. package/dist/localization/default-messages.d.ts +3 -0
  283. package/dist/localization/default-messages.d.ts.map +1 -1
  284. package/dist/localization/default-messages.js +3 -0
  285. package/dist/localization/default-messages.js.map +1 -1
  286. package/dist/mcp/build-server.d.ts +2 -0
  287. package/dist/mcp/build-server.d.ts.map +1 -1
  288. package/dist/mcp/build-server.js +2 -2
  289. package/dist/mcp/build-server.js.map +1 -1
  290. package/dist/notifications/routes.d.ts +2 -2
  291. package/dist/observability/routes.d.ts +5 -5
  292. package/dist/observability/traces.d.ts +9 -0
  293. package/dist/observability/traces.d.ts.map +1 -1
  294. package/dist/observability/traces.js +137 -19
  295. package/dist/observability/traces.js.map +1 -1
  296. package/dist/progress/actions.d.ts.map +1 -1
  297. package/dist/progress/actions.js +3 -2
  298. package/dist/progress/actions.js.map +1 -1
  299. package/dist/progress/routes.d.ts +1 -1
  300. package/dist/provider-api/corpus-jobs.d.ts +2 -2
  301. package/dist/provider-api/index.d.ts.map +1 -1
  302. package/dist/provider-api/index.js +91 -8
  303. package/dist/provider-api/index.js.map +1 -1
  304. package/dist/scripts/call-agent.d.ts.map +1 -1
  305. package/dist/scripts/call-agent.js +140 -17
  306. package/dist/scripts/call-agent.js.map +1 -1
  307. package/dist/secrets/routes.d.ts +9 -9
  308. package/dist/server/agent-chat/action-filters-a2a.d.ts +24 -2
  309. package/dist/server/agent-chat/action-filters-a2a.d.ts.map +1 -1
  310. package/dist/server/agent-chat/action-filters-a2a.js +62 -7
  311. package/dist/server/agent-chat/action-filters-a2a.js.map +1 -1
  312. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  313. package/dist/server/agent-chat-plugin.js +118 -5
  314. package/dist/server/agent-chat-plugin.js.map +1 -1
  315. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  316. package/dist/server/transcribe-voice.d.ts +1 -1
  317. package/dist/styles/agent-conversation.css +7 -0
  318. package/dist/templates/default/app/i18n/ar-SA.ts +20 -0
  319. package/dist/templates/default/app/i18n/de-DE.ts +20 -0
  320. package/dist/templates/default/app/i18n/en-US.ts +20 -0
  321. package/dist/templates/default/app/i18n/es-ES.ts +20 -0
  322. package/dist/templates/default/app/i18n/fr-FR.ts +21 -0
  323. package/dist/templates/default/app/i18n/hi-IN.ts +19 -0
  324. package/dist/templates/default/app/i18n/ja-JP.ts +20 -0
  325. package/dist/templates/default/app/i18n/ko-KR.ts +19 -0
  326. package/dist/templates/default/app/i18n/pt-BR.ts +20 -0
  327. package/dist/templates/default/app/i18n/zh-CN.ts +19 -0
  328. package/dist/templates/default/app/i18n/zh-TW.ts +19 -0
  329. package/dist/templates/workspace-core/.agents/skills/a2a-protocol/SKILL.md +49 -0
  330. package/dist/templates/workspace-core/.agents/skills/composable-mini-apps/SKILL.md +5 -0
  331. package/dist/templates/workspace-core/.agents/skills/observability/SKILL.md +7 -1
  332. package/dist/templates/workspace-core/.agents/skills/performance/SKILL.md +13 -0
  333. package/dist/templates/workspace-core/.agents/skills/tracking/SKILL.md +1 -1
  334. package/package.json +1 -1
  335. package/src/templates/default/app/i18n/ar-SA.ts +20 -0
  336. package/src/templates/default/app/i18n/de-DE.ts +20 -0
  337. package/src/templates/default/app/i18n/en-US.ts +20 -0
  338. package/src/templates/default/app/i18n/es-ES.ts +20 -0
  339. package/src/templates/default/app/i18n/fr-FR.ts +21 -0
  340. package/src/templates/default/app/i18n/hi-IN.ts +19 -0
  341. package/src/templates/default/app/i18n/ja-JP.ts +20 -0
  342. package/src/templates/default/app/i18n/ko-KR.ts +19 -0
  343. package/src/templates/default/app/i18n/pt-BR.ts +20 -0
  344. package/src/templates/default/app/i18n/zh-CN.ts +19 -0
  345. package/src/templates/default/app/i18n/zh-TW.ts +19 -0
  346. package/src/templates/workspace-core/.agents/skills/a2a-protocol/SKILL.md +49 -0
  347. package/src/templates/workspace-core/.agents/skills/composable-mini-apps/SKILL.md +5 -0
  348. package/src/templates/workspace-core/.agents/skills/observability/SKILL.md +7 -1
  349. package/src/templates/workspace-core/.agents/skills/performance/SKILL.md +13 -0
  350. package/src/templates/workspace-core/.agents/skills/tracking/SKILL.md +1 -1
  351. package/corpus/templates/analytics/server/handlers/github.ts +0 -200
  352. package/corpus/templates/analytics/server/handlers/pylon.ts +0 -43
  353. package/corpus/templates/analytics/server/lib/apollo.ts +0 -167
  354. package/corpus/templates/analytics/server/lib/commonroom.ts +0 -149
  355. package/corpus/templates/analytics/server/lib/github.ts +0 -660
  356. package/corpus/templates/analytics/server/lib/mixpanel.ts +0 -156
  357. package/corpus/templates/analytics/server/lib/posthog.ts +0 -194
  358. package/corpus/templates/analytics/server/lib/pylon.ts +0 -109
  359. package/corpus/templates/analytics/server/routes/api/github/graphql.post.ts +0 -1
  360. package/corpus/templates/analytics/server/routes/api/github/issue.get.ts +0 -1
  361. package/corpus/templates/analytics/server/routes/api/github/org-prs.get.ts +0 -1
  362. package/corpus/templates/analytics/server/routes/api/github/pr.get.ts +0 -1
  363. package/corpus/templates/analytics/server/routes/api/github/prs.get.ts +0 -1
  364. package/corpus/templates/analytics/server/routes/api/github/search.get.ts +0 -1
  365. package/corpus/templates/slides/actions/fetch-logos.ts +0 -90
  366. package/corpus/templates/slides/actions/image-search.ts +0 -64
  367. package/corpus/templates/slides/actions/import-github.ts +0 -182
  368. package/corpus/templates/slides/actions/logo-lookup.ts +0 -113
@@ -1,156 +0,0 @@
1
- // Mixpanel Data Export API helper
2
- // Queries events, top events, and funnels
3
-
4
- import { resolveCredential } from "./credentials";
5
- import {
6
- requireRequestCredentialContext,
7
- scopedCredentialCacheKey,
8
- } from "./credentials-context";
9
-
10
- const API_BASE = "https://data.mixpanel.com/api/2.0";
11
- const QUERY_BASE = "https://mixpanel.com/api/query";
12
-
13
- // In-memory cache
14
- const cache = new Map<string, { data: unknown; ts: number }>();
15
- const CACHE_TTL_MS = 5 * 60 * 1000; // 5 minutes
16
- const MAX_CACHE = 100;
17
-
18
- async function getCredentials(): Promise<{ projectId: string; auth: string }> {
19
- const ctx = requireRequestCredentialContext("MIXPANEL_PROJECT_ID");
20
- const projectId = await resolveCredential("MIXPANEL_PROJECT_ID", ctx);
21
- const serviceAccount = await resolveCredential(
22
- "MIXPANEL_SERVICE_ACCOUNT",
23
- ctx,
24
- );
25
- if (!projectId) throw new Error("MIXPANEL_PROJECT_ID not configured");
26
- if (!serviceAccount)
27
- throw new Error(
28
- "MIXPANEL_SERVICE_ACCOUNT not configured (format: username:secret)",
29
- );
30
- const auth = Buffer.from(serviceAccount).toString("base64");
31
- return { projectId, auth };
32
- }
33
-
34
- function cacheSet(key: string, data: unknown) {
35
- if (cache.size >= MAX_CACHE) {
36
- const oldest = cache.keys().next().value;
37
- if (oldest) cache.delete(oldest);
38
- }
39
- cache.set(key, { data, ts: Date.now() });
40
- }
41
-
42
- async function apiGet<T>(
43
- base: string,
44
- path: string,
45
- cacheKey?: string,
46
- ): Promise<T> {
47
- const key = scopedCredentialCacheKey(cacheKey ?? path, "MIXPANEL_PROJECT_ID");
48
- const cached = cache.get(key);
49
- if (cached && Date.now() - cached.ts < CACHE_TTL_MS) {
50
- return cached.data as T;
51
- }
52
-
53
- const { projectId, auth } = await getCredentials();
54
- const separator = path.includes("?") ? "&" : "?";
55
- const url = `${base}${path}${separator}project_id=${projectId}`;
56
-
57
- const res = await fetch(url, {
58
- headers: { Authorization: `Basic ${auth}` },
59
- });
60
-
61
- if (!res.ok) {
62
- const text = await res.text();
63
- throw new Error(`Mixpanel API error ${res.status}: ${text}`);
64
- }
65
-
66
- const data = await res.json();
67
- cacheSet(key, data);
68
- return data as T;
69
- }
70
-
71
- // -- Types --
72
-
73
- export interface MixpanelEvent {
74
- event: string;
75
- properties: Record<string, unknown>;
76
- }
77
-
78
- export interface MixpanelTopEvent {
79
- amount: number;
80
- percent_change: number;
81
- }
82
-
83
- export interface MixpanelFunnel {
84
- meta: { dates: string[] };
85
- data: Record<
86
- string,
87
- Record<string, { count: number; step_conv_ratio: number }>
88
- >;
89
- }
90
-
91
- // -- API functions --
92
-
93
- export async function getMixpanelClient() {
94
- const creds = await getCredentials();
95
- return { projectId: creds.projectId, apiGet };
96
- }
97
-
98
- export async function queryEvents(
99
- fromDate: string,
100
- toDate: string,
101
- eventNames?: string[],
102
- ): Promise<MixpanelEvent[]> {
103
- const params = new URLSearchParams({ from_date: fromDate, to_date: toDate });
104
- if (eventNames?.length) {
105
- params.set("event", JSON.stringify(eventNames));
106
- }
107
- return apiGet<MixpanelEvent[]>(
108
- API_BASE,
109
- `/export?${params.toString()}`,
110
- `events-${fromDate}-${toDate}`,
111
- );
112
- }
113
-
114
- export async function getTopEvents(
115
- type: "general" | "average" | "unique" = "general",
116
- limit = 10,
117
- ): Promise<Record<string, MixpanelTopEvent>> {
118
- const params = new URLSearchParams({
119
- type,
120
- limit: String(limit),
121
- });
122
- return apiGet<Record<string, MixpanelTopEvent>>(
123
- QUERY_BASE,
124
- `/events/top?${params.toString()}`,
125
- `top-events-${type}-${limit}`,
126
- );
127
- }
128
-
129
- export async function getFunnels(
130
- funnelId: number,
131
- fromDate: string,
132
- toDate: string,
133
- ): Promise<MixpanelFunnel> {
134
- const params = new URLSearchParams({
135
- funnel_id: String(funnelId),
136
- from_date: fromDate,
137
- to_date: toDate,
138
- });
139
- return apiGet<MixpanelFunnel>(
140
- QUERY_BASE,
141
- `/funnels?${params.toString()}`,
142
- `funnel-${funnelId}-${fromDate}-${toDate}`,
143
- );
144
- }
145
-
146
- export async function testConnection(): Promise<{
147
- ok: boolean;
148
- error?: string;
149
- }> {
150
- try {
151
- await getTopEvents("general", 1);
152
- return { ok: true };
153
- } catch (e) {
154
- return { ok: false, error: (e as Error).message };
155
- }
156
- }
@@ -1,194 +0,0 @@
1
- // PostHog API helper
2
- // Queries events, insights, and trends
3
-
4
- import { resolveCredential } from "./credentials";
5
- import {
6
- requireRequestCredentialContext,
7
- scopedCredentialCacheKey,
8
- } from "./credentials-context";
9
-
10
- const DEFAULT_HOST = "https://app.posthog.com";
11
-
12
- // In-memory cache
13
- const cache = new Map<string, { data: unknown; ts: number }>();
14
- const CACHE_TTL_MS = 5 * 60 * 1000; // 5 minutes
15
- const MAX_CACHE = 100;
16
-
17
- async function getConfig(): Promise<{
18
- apiKey: string;
19
- projectId: string;
20
- host: string;
21
- }> {
22
- const ctx = requireRequestCredentialContext("POSTHOG_API_KEY");
23
- const apiKey = await resolveCredential("POSTHOG_API_KEY", ctx);
24
- const projectId = await resolveCredential("POSTHOG_PROJECT_ID", ctx);
25
- const host = (await resolveCredential("POSTHOG_HOST", ctx)) ?? DEFAULT_HOST;
26
- if (!apiKey) throw new Error("POSTHOG_API_KEY not configured");
27
- if (!projectId) throw new Error("POSTHOG_PROJECT_ID not configured");
28
- return { apiKey, projectId, host: host.replace(/\/$/, "") };
29
- }
30
-
31
- function cacheSet(key: string, data: unknown) {
32
- if (cache.size >= MAX_CACHE) {
33
- const oldest = cache.keys().next().value;
34
- if (oldest) cache.delete(oldest);
35
- }
36
- cache.set(key, { data, ts: Date.now() });
37
- }
38
-
39
- async function apiGet<T>(path: string, cacheKey?: string): Promise<T> {
40
- const key = scopedCredentialCacheKey(cacheKey ?? path, "POSTHOG_API_KEY");
41
- const cached = cache.get(key);
42
- if (cached && Date.now() - cached.ts < CACHE_TTL_MS) {
43
- return cached.data as T;
44
- }
45
-
46
- const { apiKey, host } = await getConfig();
47
- const res = await fetch(`${host}${path}`, {
48
- headers: { Authorization: `Bearer ${apiKey}` },
49
- });
50
-
51
- if (!res.ok) {
52
- const text = await res.text();
53
- throw new Error(`PostHog API error ${res.status}: ${text}`);
54
- }
55
-
56
- const data = await res.json();
57
- cacheSet(key, data);
58
- return data as T;
59
- }
60
-
61
- async function apiPost<T>(
62
- path: string,
63
- body: unknown,
64
- cacheKey?: string,
65
- ): Promise<T> {
66
- const key = cacheKey
67
- ? scopedCredentialCacheKey(cacheKey, "POSTHOG_API_KEY")
68
- : undefined;
69
- if (key) {
70
- const cached = cache.get(key);
71
- if (cached && Date.now() - cached.ts < CACHE_TTL_MS) {
72
- return cached.data as T;
73
- }
74
- }
75
-
76
- const { apiKey, host } = await getConfig();
77
- const res = await fetch(`${host}${path}`, {
78
- method: "POST",
79
- headers: {
80
- Authorization: `Bearer ${apiKey}`,
81
- "Content-Type": "application/json",
82
- },
83
- body: JSON.stringify(body),
84
- });
85
-
86
- if (!res.ok) {
87
- const text = await res.text();
88
- throw new Error(`PostHog API error ${res.status}: ${text}`);
89
- }
90
-
91
- const data = await res.json();
92
- if (key) cacheSet(key, data);
93
- return data as T;
94
- }
95
-
96
- // -- Types --
97
-
98
- export interface PostHogEvent {
99
- id: string;
100
- event: string;
101
- properties: Record<string, unknown>;
102
- timestamp: string;
103
- distinct_id: string;
104
- }
105
-
106
- export interface PostHogEventResponse {
107
- results: PostHogEvent[];
108
- next?: string;
109
- }
110
-
111
- export interface PostHogInsight {
112
- id: number;
113
- name: string;
114
- filters: Record<string, unknown>;
115
- result: unknown;
116
- created_at: string;
117
- }
118
-
119
- export interface PostHogTrendResult {
120
- result: {
121
- action: { id: string; name: string };
122
- label: string;
123
- count: number;
124
- data: number[];
125
- labels: string[];
126
- days: string[];
127
- }[];
128
- }
129
-
130
- // -- API functions --
131
-
132
- export async function getPostHogClient() {
133
- const config = await getConfig();
134
- return { projectId: config.projectId, host: config.host, apiGet, apiPost };
135
- }
136
-
137
- export async function queryEvents(
138
- eventName?: string,
139
- limit = 100,
140
- after?: string,
141
- ): Promise<PostHogEventResponse> {
142
- const { projectId } = await getConfig();
143
- const params = new URLSearchParams({ limit: String(limit) });
144
- if (eventName) params.set("event", eventName);
145
- if (after) params.set("after", after);
146
- return apiGet<PostHogEventResponse>(
147
- `/api/projects/${projectId}/events/?${params.toString()}`,
148
- );
149
- }
150
-
151
- export async function getInsights(
152
- limit = 20,
153
- ): Promise<{ results: PostHogInsight[] }> {
154
- const { projectId } = await getConfig();
155
- return apiGet<{ results: PostHogInsight[] }>(
156
- `/api/projects/${projectId}/insights/?limit=${limit}`,
157
- );
158
- }
159
-
160
- export async function getTrends(
161
- events: { id: string; name?: string }[],
162
- dateFrom?: string,
163
- dateTo?: string,
164
- ): Promise<PostHogTrendResult> {
165
- const { projectId } = await getConfig();
166
- const body = {
167
- insight: "TRENDS",
168
- events: events.map((e) => ({
169
- id: e.id,
170
- name: e.name ?? e.id,
171
- type: "events",
172
- })),
173
- date_from: dateFrom ?? "-7d",
174
- date_to: dateTo,
175
- };
176
- return apiPost<PostHogTrendResult>(
177
- `/api/projects/${projectId}/insights/trend/`,
178
- body,
179
- `trends-${JSON.stringify(events)}-${dateFrom}-${dateTo}`,
180
- );
181
- }
182
-
183
- export async function testConnection(): Promise<{
184
- ok: boolean;
185
- error?: string;
186
- }> {
187
- try {
188
- const { projectId } = await getConfig();
189
- await apiGet(`/api/projects/${projectId}/`);
190
- return { ok: true };
191
- } catch (e) {
192
- return { ok: false, error: (e as Error).message };
193
- }
194
- }
@@ -1,109 +0,0 @@
1
- // Pylon support platform API helper
2
- // Fetches accounts, issues, and contacts
3
-
4
- import { resolveCredential } from "./credentials";
5
- import {
6
- requireRequestCredentialContext,
7
- scopedCredentialCacheKey,
8
- } from "./credentials-context";
9
-
10
- const API_BASE = "https://api.usepylon.com";
11
-
12
- const cache = new Map<string, { data: unknown; ts: number }>();
13
- const CACHE_TTL_MS = 10 * 60 * 1000;
14
- const MAX_CACHE = 120;
15
-
16
- async function getToken(): Promise<string> {
17
- const ctx = requireRequestCredentialContext("PYLON_API_KEY");
18
- const token = await resolveCredential("PYLON_API_KEY", ctx);
19
- if (!token) throw new Error("PYLON_API_KEY not configured");
20
- return token;
21
- }
22
-
23
- async function apiGet<T>(path: string, cacheKey?: string): Promise<T> {
24
- const key = scopedCredentialCacheKey(cacheKey ?? path, "PYLON_API_KEY");
25
- const cached = cache.get(key);
26
- if (cached && Date.now() - cached.ts < CACHE_TTL_MS) {
27
- return cached.data as T;
28
- }
29
-
30
- const res = await fetch(`${API_BASE}${path}`, {
31
- headers: {
32
- Authorization: `Bearer ${await getToken()}`,
33
- "Content-Type": "application/json",
34
- },
35
- });
36
-
37
- if (!res.ok) {
38
- const text = await res.text();
39
- throw new Error(`Pylon API error ${res.status}: ${text}`);
40
- }
41
-
42
- const data = await res.json();
43
-
44
- if (cache.size >= MAX_CACHE) {
45
- const oldest = cache.keys().next().value;
46
- if (oldest) cache.delete(oldest);
47
- }
48
- cache.set(key, { data, ts: Date.now() });
49
-
50
- return data as T;
51
- }
52
-
53
- export interface PylonAccount {
54
- id: string;
55
- name: string;
56
- domain?: string;
57
- [key: string]: unknown;
58
- }
59
-
60
- export interface PylonIssue {
61
- id: string;
62
- title: string;
63
- state: string;
64
- priority?: string;
65
- account_id?: string;
66
- created_at: string;
67
- updated_at: string;
68
- [key: string]: unknown;
69
- }
70
-
71
- export async function getAccounts(query?: string): Promise<PylonAccount[]> {
72
- const path = query
73
- ? `/accounts?query=${encodeURIComponent(query)}`
74
- : "/accounts";
75
- const data = await apiGet<{ data: PylonAccount[] }>(path);
76
- return data.data ?? (data as any);
77
- }
78
-
79
- export async function getAccount(id: string): Promise<PylonAccount> {
80
- return apiGet<PylonAccount>(`/accounts/${id}`);
81
- }
82
-
83
- export async function getIssues(params?: {
84
- account_id?: string;
85
- state?: string;
86
- query?: string;
87
- }): Promise<PylonIssue[]> {
88
- const searchParams = new URLSearchParams();
89
- if (params?.account_id) searchParams.set("account_id", params.account_id);
90
- if (params?.state) searchParams.set("state", params.state);
91
- if (params?.query) searchParams.set("query", params.query);
92
- // Pylon requires start_time and end_time — max 30 days
93
- const now = new Date();
94
- const thirtyDaysAgo = new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000);
95
- searchParams.set("start_time", thirtyDaysAgo.toISOString());
96
- searchParams.set("end_time", now.toISOString());
97
- const qs = searchParams.toString();
98
- const path = `/issues${qs ? `?${qs}` : ""}`;
99
- const data = await apiGet<{ data: PylonIssue[] }>(path);
100
- return data.data ?? (data as any);
101
- }
102
-
103
- export async function getContacts(query?: string): Promise<unknown[]> {
104
- const path = query
105
- ? `/contacts?query=${encodeURIComponent(query)}`
106
- : "/contacts";
107
- const data = await apiGet<{ data: unknown[] }>(path);
108
- return data.data ?? (data as any);
109
- }
@@ -1 +0,0 @@
1
- export { handleGitHubGraphQL as default } from "../../../handlers/github";
@@ -1 +0,0 @@
1
- export { handleGitHubIssue as default } from "../../../handlers/github";
@@ -1 +0,0 @@
1
- export { handleGitHubOrgPRs as default } from "../../../handlers/github";
@@ -1 +0,0 @@
1
- export { handleGitHubPR as default } from "../../../handlers/github";
@@ -1 +0,0 @@
1
- export { handleGitHubPRList as default } from "../../../handlers/github";
@@ -1 +0,0 @@
1
- export { handleGitHubSearch as default } from "../../../handlers/github";
@@ -1,90 +0,0 @@
1
- import { parseArgs } from "@agent-native/core";
2
-
3
- export default async function (args: string[]) {
4
- const { domains: domainsArg } = parseArgs(args);
5
-
6
- const API_KEY = process.env.BRANDFETCH_API_KEY;
7
- if (!API_KEY) {
8
- throw new Error(
9
- "Missing BRANDFETCH_API_KEY env var. Set it in your .env file.",
10
- );
11
- }
12
-
13
- const brands = domainsArg
14
- ? (domainsArg as string).split(",").map((d: string) => d.trim())
15
- : [
16
- "greylock.com",
17
- "microsoft.com",
18
- "zapier.com",
19
- "jcrew.com",
20
- "panasonic.com",
21
- "scale.com",
22
- "ocbc.com",
23
- "pendo.io",
24
- "clickup.com",
25
- "harrys.com",
26
- ];
27
-
28
- const results: Record<
29
- string,
30
- { url: string; format: string; theme: string }
31
- > = {};
32
-
33
- for (const domain of brands) {
34
- try {
35
- const res = await fetch("https://api.brandfetch.io/v2/brands/" + domain, {
36
- headers: { Authorization: "Bearer " + API_KEY },
37
- });
38
-
39
- if (!res.ok) {
40
- console.log(domain, "ERROR:", res.status, res.statusText);
41
- const text = await res.text();
42
- console.log(" Body:", text.substring(0, 200));
43
- continue;
44
- }
45
-
46
- const data = await res.json();
47
- const logos = data.logos || [];
48
-
49
- // Find dark theme logo (for dark backgrounds = white logo)
50
- const darkLogo = logos.find(
51
- (l: any) => l.type === "logo" && l.theme === "dark",
52
- );
53
- const anyLogo = logos.find((l: any) => l.type === "logo");
54
-
55
- const logo = darkLogo || anyLogo;
56
-
57
- if (logo && logo.formats && logo.formats.length > 0) {
58
- // Prefer SVG, then PNG
59
- const svg = logo.formats.find((f: any) => f.format === "svg");
60
- const png = logo.formats.find((f: any) => f.format === "png");
61
- const chosen = svg || png || logo.formats[0];
62
- results[domain] = {
63
- url: chosen.src,
64
- format: chosen.format,
65
- theme: logo.theme,
66
- };
67
- console.log(
68
- domain,
69
- "-> theme:",
70
- logo.theme,
71
- "format:",
72
- chosen.format,
73
- "url:",
74
- chosen.src,
75
- );
76
- } else {
77
- console.log(
78
- domain,
79
- "NO LOGO FOUND. Available types:",
80
- logos.map((l: any) => l.type + "/" + l.theme).join(", "),
81
- );
82
- }
83
- } catch (e: any) {
84
- console.log(domain, "FETCH ERROR:", e.message);
85
- }
86
- }
87
-
88
- console.log("\n--- JSON OUTPUT ---");
89
- console.log(JSON.stringify(results, null, 2));
90
- }
@@ -1,64 +0,0 @@
1
- import { defineAction } from "@agent-native/core";
2
- import { resolveSecret } from "@agent-native/core/server";
3
- import { z } from "zod";
4
-
5
- export default defineAction({
6
- description:
7
- "Search for images using Google Custom Search API (agent CLI tool).",
8
- schema: z.object({
9
- query: z.string().optional().describe("Search query (required)"),
10
- count: z.coerce
11
- .number()
12
- .optional()
13
- .describe("Number of results (default: 10)"),
14
- }),
15
- http: false,
16
- run: async (args) => {
17
- const query = args.query;
18
- if (!query) {
19
- throw new Error("--query is required");
20
- }
21
-
22
- const [apiKey, cx] = await Promise.all([
23
- resolveSecret("GOOGLE_API_KEY"),
24
- resolveSecret("GOOGLE_SEARCH_CX"),
25
- ]);
26
-
27
- if (!apiKey || !cx) {
28
- throw new Error(
29
- "GOOGLE_API_KEY and GOOGLE_SEARCH_CX must be saved in settings.",
30
- );
31
- }
32
-
33
- const count = Math.min(args.count ?? 10, 10);
34
-
35
- const params = new URLSearchParams({
36
- key: apiKey,
37
- cx,
38
- q: query,
39
- searchType: "image",
40
- num: String(count),
41
- safe: "active",
42
- });
43
-
44
- const response = await fetch(
45
- `https://www.googleapis.com/customsearch/v1?${params}`,
46
- );
47
- if (!response.ok) {
48
- const text = await response.text();
49
- throw new Error(`Google API error: ${text}`);
50
- }
51
-
52
- const data = await response.json();
53
- const results = (data.items || []).map((item: any, i: number) => ({
54
- index: i + 1,
55
- url: item.link,
56
- title: item.title,
57
- width: item.image?.width,
58
- height: item.image?.height,
59
- thumbnail: item.image?.thumbnailLink,
60
- }));
61
-
62
- return JSON.stringify(results, null, 2);
63
- },
64
- });