@graph8/sdk 0.303.0 → 0.357.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (664) hide show
  1. package/README.md +81 -0
  2. package/blocks/README.md +32 -0
  3. package/blocks/_foundation/README.md +78 -0
  4. package/blocks/_foundation/block.json +79 -0
  5. package/blocks/_foundation/components/api-error.tsx +62 -0
  6. package/blocks/_foundation/components/confirm-spend-dialog.tsx +142 -0
  7. package/blocks/_foundation/components/empty-state.tsx +24 -0
  8. package/blocks/_foundation/hooks/use-g8-mutation.ts +88 -0
  9. package/blocks/_foundation/hooks/use-g8-query.ts +87 -0
  10. package/blocks/_foundation/hooks/use-job-poll.ts +130 -0
  11. package/blocks/_foundation/hooks/use-paginated.ts +105 -0
  12. package/blocks/_foundation/lib/g8-client.ts +128 -0
  13. package/blocks/_foundation/recipes/verify-proxy-key.ts +18 -0
  14. package/blocks/_foundation/server/proxy.ts +233 -0
  15. package/blocks/_foundation/server/route.ts +30 -0
  16. package/blocks/agents/README.md +133 -0
  17. package/blocks/agents/block.json +223 -0
  18. package/blocks/agents/components/agent-builder.tsx +199 -0
  19. package/blocks/agents/components/agent-knowledge-panel.tsx +144 -0
  20. package/blocks/agents/components/agent-runs.tsx +175 -0
  21. package/blocks/agents/components/agent-skills-panel.tsx +126 -0
  22. package/blocks/agents/components/agent-test-console.tsx +175 -0
  23. package/blocks/agents/lib/agent-types.ts +114 -0
  24. package/blocks/agents/recipes/create-agent-and-attach-skill.ts +50 -0
  25. package/blocks/agents/recipes/run-and-follow-agent-run.ts +46 -0
  26. package/blocks/agents/recipes/test-agent-before-activating.ts +36 -0
  27. package/blocks/analytics/README.md +73 -0
  28. package/blocks/analytics/block.json +178 -0
  29. package/blocks/analytics/components/funnel-chart.tsx +79 -0
  30. package/blocks/analytics/components/kpi-tiles.tsx +74 -0
  31. package/blocks/analytics/components/leaderboard.tsx +86 -0
  32. package/blocks/analytics/components/report-builder.tsx +200 -0
  33. package/blocks/analytics/hooks/use-report.ts +26 -0
  34. package/blocks/analytics/lib/analytics-types.ts +108 -0
  35. package/blocks/analytics/lib/use-debounced.ts +16 -0
  36. package/blocks/analytics/recipes/01-weekly-outbound-report.ts +32 -0
  37. package/blocks/analytics/recipes/02-revenue-snapshot.ts +22 -0
  38. package/blocks/analytics/recipes/03-saved-report.ts +30 -0
  39. package/blocks/appointments/README.md +80 -0
  40. package/blocks/appointments/block.json +218 -0
  41. package/blocks/appointments/components/availability-editor.tsx +192 -0
  42. package/blocks/appointments/components/booking-page.tsx +154 -0
  43. package/blocks/appointments/components/event-type-editor.tsx +214 -0
  44. package/blocks/appointments/components/meeting-detail.tsx +147 -0
  45. package/blocks/appointments/components/meeting-list.tsx +148 -0
  46. package/blocks/appointments/hooks/use-available-slots.ts +29 -0
  47. package/blocks/appointments/hooks/use-schedules.ts +18 -0
  48. package/blocks/appointments/lib/appointments-types.ts +159 -0
  49. package/blocks/appointments/lib/idempotency.ts +30 -0
  50. package/blocks/appointments/recipes/01-create-event-type-and-hours.ts +27 -0
  51. package/blocks/appointments/recipes/02-find-slots-and-book.ts +34 -0
  52. package/blocks/appointments/recipes/03-bookings-digest.ts +22 -0
  53. package/blocks/appointments/recipes/04-calendar-invite.ts +21 -0
  54. package/blocks/block.schema.json +130 -0
  55. package/blocks/block.types.ts +109 -0
  56. package/blocks/campaigns/README.md +118 -0
  57. package/blocks/campaigns/block.json +361 -0
  58. package/blocks/campaigns/components/campaign-assets.tsx +180 -0
  59. package/blocks/campaigns/components/campaign-audience-step.tsx +91 -0
  60. package/blocks/campaigns/components/campaign-launch-step.tsx +147 -0
  61. package/blocks/campaigns/components/campaign-list.tsx +120 -0
  62. package/blocks/campaigns/components/campaign-metrics.tsx +93 -0
  63. package/blocks/campaigns/components/campaign-select.tsx +52 -0
  64. package/blocks/campaigns/components/campaign-sequence-step.tsx +158 -0
  65. package/blocks/campaigns/components/campaign-wizard.tsx +238 -0
  66. package/blocks/campaigns/components/form-field.tsx +29 -0
  67. package/blocks/campaigns/components/icp-editor.tsx +230 -0
  68. package/blocks/campaigns/components/persona-editor.tsx +210 -0
  69. package/blocks/campaigns/hooks/use-company-profile.ts +34 -0
  70. package/blocks/campaigns/lib/campaigns-utils.ts +155 -0
  71. package/blocks/campaigns/recipes/attach-audience-and-launch.ts +33 -0
  72. package/blocks/campaigns/recipes/campaign-report.ts +22 -0
  73. package/blocks/campaigns/recipes/generate-ideas-and-create-campaign.ts +51 -0
  74. package/blocks/campaigns/recipes/set-up-icp-and-personas.ts +37 -0
  75. package/blocks/coach/README.md +93 -0
  76. package/blocks/coach/block.json +125 -0
  77. package/blocks/coach/components/call-scorecard.tsx +126 -0
  78. package/blocks/coach/components/coaching-feed.tsx +140 -0
  79. package/blocks/coach/lib/coach-types.ts +116 -0
  80. package/blocks/coach/recipes/read-a-scorecard.ts +27 -0
  81. package/blocks/coach/recipes/weekly-coaching-digest.ts +53 -0
  82. package/blocks/copilot/README.md +99 -0
  83. package/blocks/copilot/block.json +151 -0
  84. package/blocks/copilot/components/copilot-memory.tsx +87 -0
  85. package/blocks/copilot/components/copilot-panel.tsx +189 -0
  86. package/blocks/copilot/components/copilot-team-chat.tsx +111 -0
  87. package/blocks/copilot/lib/copilot-types.ts +111 -0
  88. package/blocks/copilot/recipes/ask-the-copilot.ts +35 -0
  89. package/blocks/copilot/recipes/post-in-a-work-channel.ts +33 -0
  90. package/blocks/copilot/recipes/remember-and-recall.ts +19 -0
  91. package/blocks/crm/README.md +122 -0
  92. package/blocks/crm/block.json +378 -0
  93. package/blocks/crm/components/activity-timeline.tsx +99 -0
  94. package/blocks/crm/components/company-detail.tsx +118 -0
  95. package/blocks/crm/components/company-table.tsx +173 -0
  96. package/blocks/crm/components/contact-detail.tsx +135 -0
  97. package/blocks/crm/components/contact-table.tsx +217 -0
  98. package/blocks/crm/components/dedupe-review.tsx +164 -0
  99. package/blocks/crm/components/import-wizard.tsx +193 -0
  100. package/blocks/crm/components/notes-panel.tsx +112 -0
  101. package/blocks/crm/components/record-form.tsx +191 -0
  102. package/blocks/crm/components/task-list.tsx +107 -0
  103. package/blocks/crm/hooks/use-custom-fields.ts +18 -0
  104. package/blocks/crm/hooks/use-debounced.ts +13 -0
  105. package/blocks/crm/hooks/use-page-query.ts +52 -0
  106. package/blocks/crm/lib/crm-types.ts +136 -0
  107. package/blocks/crm/recipes/custom-fields-and-values.ts +28 -0
  108. package/blocks/crm/recipes/dedupe-and-merge.ts +30 -0
  109. package/blocks/crm/recipes/notes-tasks-and-activity.ts +23 -0
  110. package/blocks/crm/recipes/upsert-contact-with-company.ts +33 -0
  111. package/blocks/deals/README.md +78 -0
  112. package/blocks/deals/block.json +198 -0
  113. package/blocks/deals/components/deal-detail.tsx +134 -0
  114. package/blocks/deals/components/forecast-view.tsx +112 -0
  115. package/blocks/deals/components/pipeline-board.tsx +142 -0
  116. package/blocks/deals/components/stage-editor.tsx +96 -0
  117. package/blocks/deals/hooks/use-pipeline-deals.ts +67 -0
  118. package/blocks/deals/hooks/use-pipelines.ts +19 -0
  119. package/blocks/deals/lib/deals-types.ts +128 -0
  120. package/blocks/deals/recipes/01-create-deal-and-advance.ts +32 -0
  121. package/blocks/deals/recipes/02-pipeline-report.ts +35 -0
  122. package/blocks/deals/recipes/03-stale-deals-sweep.ts +20 -0
  123. package/blocks/dialer/README.md +114 -0
  124. package/blocks/dialer/block.json +260 -0
  125. package/blocks/dialer/components/call-log.tsx +78 -0
  126. package/blocks/dialer/components/call-queue.tsx +188 -0
  127. package/blocks/dialer/components/dialer-workspace.tsx +47 -0
  128. package/blocks/dialer/components/disposition-panel.tsx +75 -0
  129. package/blocks/dialer/components/live-calls-table.tsx +107 -0
  130. package/blocks/dialer/components/session-start-form.tsx +111 -0
  131. package/blocks/dialer/components/softphone.tsx +122 -0
  132. package/blocks/dialer/components/transcript-viewer.tsx +82 -0
  133. package/blocks/dialer/hooks/use-dialer-numbers.ts +19 -0
  134. package/blocks/dialer/hooks/use-dialer-session.ts +68 -0
  135. package/blocks/dialer/hooks/use-dispositions.ts +29 -0
  136. package/blocks/dialer/lib/dialer-types.ts +158 -0
  137. package/blocks/dialer/lib/softphone-transport.ts +67 -0
  138. package/blocks/dialer/lib/twilio-transport.ts +74 -0
  139. package/blocks/dialer/recipes/01-create-session-and-dial.ts +39 -0
  140. package/blocks/dialer/recipes/02-disposition-calls.ts +26 -0
  141. package/blocks/dialer/recipes/03-review-a-call.ts +23 -0
  142. package/blocks/enrichment/README.md +105 -0
  143. package/blocks/enrichment/block.json +204 -0
  144. package/blocks/enrichment/components/bulk-enrich-panel.tsx +205 -0
  145. package/blocks/enrichment/components/email-verify-badge.tsx +82 -0
  146. package/blocks/enrichment/components/enrich-button.tsx +136 -0
  147. package/blocks/enrichment/components/waterfall-config.tsx +127 -0
  148. package/blocks/enrichment/hooks/use-providers.ts +18 -0
  149. package/blocks/enrichment/lib/enrichment-types.ts +104 -0
  150. package/blocks/enrichment/recipes/bulk-enrich-and-poll.ts +41 -0
  151. package/blocks/enrichment/recipes/lookup-and-verify.ts +25 -0
  152. package/blocks/enrichment/recipes/waterfall-pipeline.ts +26 -0
  153. package/blocks/forms/README.md +112 -0
  154. package/blocks/forms/block.json +200 -0
  155. package/blocks/forms/components/form-builder.tsx +150 -0
  156. package/blocks/forms/components/form-embed.tsx +103 -0
  157. package/blocks/forms/components/form-mapping-editor.tsx +125 -0
  158. package/blocks/forms/components/site-audit-panel.tsx +73 -0
  159. package/blocks/forms/components/submissions-table.tsx +158 -0
  160. package/blocks/forms/lib/form-types.ts +127 -0
  161. package/blocks/forms/recipes/install-snippet-and-form.ts +21 -0
  162. package/blocks/forms/recipes/retry-failed-deliveries.ts +26 -0
  163. package/blocks/forms/recipes/route-form-to-list.ts +44 -0
  164. package/blocks/inbox/README.md +72 -0
  165. package/blocks/inbox/block.json +194 -0
  166. package/blocks/inbox/components/inbox-list.tsx +156 -0
  167. package/blocks/inbox/components/inbox-screen.tsx +49 -0
  168. package/blocks/inbox/components/reply-composer.tsx +183 -0
  169. package/blocks/inbox/components/tag-and-assign.tsx +189 -0
  170. package/blocks/inbox/components/thread-badge.tsx +17 -0
  171. package/blocks/inbox/components/thread-view.tsx +108 -0
  172. package/blocks/inbox/hooks/use-inbox-thread.ts +24 -0
  173. package/blocks/inbox/hooks/use-inbox-threads.ts +40 -0
  174. package/blocks/inbox/lib/idempotency.ts +30 -0
  175. package/blocks/inbox/lib/inbox-types.ts +100 -0
  176. package/blocks/inbox/recipes/01-triage-and-reply.ts +43 -0
  177. package/blocks/inbox/recipes/02-tag-and-assign.ts +31 -0
  178. package/blocks/inbox/recipes/03-hot-contacts-digest.ts +16 -0
  179. package/blocks/integrations/README.md +75 -0
  180. package/blocks/integrations/block.json +172 -0
  181. package/blocks/integrations/components/integration-list.tsx +165 -0
  182. package/blocks/integrations/components/sync-status.tsx +223 -0
  183. package/blocks/integrations/components/webhook-manager.tsx +300 -0
  184. package/blocks/integrations/lib/integrations-utils.ts +62 -0
  185. package/blocks/integrations/recipes/crm-sync-health.ts +19 -0
  186. package/blocks/integrations/recipes/push-contacts-to-crm.ts +20 -0
  187. package/blocks/integrations/recipes/register-webhook.ts +18 -0
  188. package/blocks/integrations/recipes/verify-webhook-route.ts +33 -0
  189. package/blocks/intent/README.md +57 -0
  190. package/blocks/intent/block.json +138 -0
  191. package/blocks/intent/components/account-intent-score.tsx +91 -0
  192. package/blocks/intent/components/intent-feed.tsx +215 -0
  193. package/blocks/intent/components/intent-keyword-manager.tsx +331 -0
  194. package/blocks/intent/hooks/use-account-intent.ts +46 -0
  195. package/blocks/intent/lib/intent-utils.ts +95 -0
  196. package/blocks/intent/recipes/rank-intent-accounts.ts +36 -0
  197. package/blocks/intent/recipes/track-competitor-domain.ts +23 -0
  198. package/blocks/intent/recipes/who-visited-url.ts +18 -0
  199. package/blocks/lifecycle/README.md +79 -0
  200. package/blocks/lifecycle/block.json +198 -0
  201. package/blocks/lifecycle/components/churn-list.tsx +92 -0
  202. package/blocks/lifecycle/components/customer-table.tsx +119 -0
  203. package/blocks/lifecycle/components/lead-queue.tsx +127 -0
  204. package/blocks/lifecycle/components/lifecycle-board.tsx +102 -0
  205. package/blocks/lifecycle/components/stage-move-dialog.tsx +75 -0
  206. package/blocks/lifecycle/hooks/use-debounced.ts +13 -0
  207. package/blocks/lifecycle/hooks/use-lifecycle-stages.ts +27 -0
  208. package/blocks/lifecycle/lib/lifecycle.ts +99 -0
  209. package/blocks/lifecycle/recipes/customer-brief.ts +23 -0
  210. package/blocks/lifecycle/recipes/move-company-stage.ts +17 -0
  211. package/blocks/lifecycle/recipes/read-lifecycle-board.ts +21 -0
  212. package/blocks/lifecycle/recipes/unlock-stage-contacts.ts +25 -0
  213. package/blocks/lists/README.md +96 -0
  214. package/blocks/lists/block.json +166 -0
  215. package/blocks/lists/components/add-to-list-button.tsx +111 -0
  216. package/blocks/lists/components/list-picker.tsx +94 -0
  217. package/blocks/lists/components/list-table.tsx +160 -0
  218. package/blocks/lists/components/suppression-manager.tsx +153 -0
  219. package/blocks/lists/recipes/create-list-and-add-contacts.ts +35 -0
  220. package/blocks/lists/recipes/refresh-and-check-lists.ts +21 -0
  221. package/blocks/lists/recipes/suppress-and-reinstate.ts +30 -0
  222. package/blocks/mailboxes/README.md +71 -0
  223. package/blocks/mailboxes/block.json +187 -0
  224. package/blocks/mailboxes/components/connect-mailbox.tsx +284 -0
  225. package/blocks/mailboxes/components/domain-purchase.tsx +271 -0
  226. package/blocks/mailboxes/components/mailbox-list.tsx +185 -0
  227. package/blocks/mailboxes/components/warmup-health.tsx +232 -0
  228. package/blocks/mailboxes/lib/mailboxes-utils.ts +69 -0
  229. package/blocks/mailboxes/recipes/buy-domain-and-mailboxes.ts +64 -0
  230. package/blocks/mailboxes/recipes/connect-imap-mailbox.ts +38 -0
  231. package/blocks/mailboxes/recipes/is-it-safe-to-send.ts +17 -0
  232. package/blocks/mailboxes/recipes/warmup-report.ts +31 -0
  233. package/blocks/newsletter/README.md +122 -0
  234. package/blocks/newsletter/block.json +224 -0
  235. package/blocks/newsletter/components/issue-form.tsx +124 -0
  236. package/blocks/newsletter/components/issue-scheduler.tsx +152 -0
  237. package/blocks/newsletter/components/newsletter-editor.tsx +131 -0
  238. package/blocks/newsletter/components/newsletter-stats.tsx +93 -0
  239. package/blocks/newsletter/components/subscriber-table.tsx +173 -0
  240. package/blocks/newsletter/lib/newsletter-types.ts +97 -0
  241. package/blocks/newsletter/recipes/create-newsletter-and-draft-issue.ts +27 -0
  242. package/blocks/newsletter/recipes/import-audience-and-send.ts +43 -0
  243. package/blocks/newsletter/recipes/issue-performance-report.ts +26 -0
  244. package/blocks/nurture/README.md +110 -0
  245. package/blocks/nurture/block.json +191 -0
  246. package/blocks/nurture/components/nurture-builder.tsx +114 -0
  247. package/blocks/nurture/components/nurture-enroll.tsx +107 -0
  248. package/blocks/nurture/components/nurture-form.tsx +120 -0
  249. package/blocks/nurture/components/nurture-stats.tsx +81 -0
  250. package/blocks/nurture/lib/nurture-types.ts +109 -0
  251. package/blocks/nurture/recipes/create-a-nurture.ts +34 -0
  252. package/blocks/nurture/recipes/enroll-contacts-and-launch.ts +24 -0
  253. package/blocks/nurture/recipes/nurture-health-check.ts +28 -0
  254. package/blocks/objects/README.md +120 -0
  255. package/blocks/objects/block.json +243 -0
  256. package/blocks/objects/components/attribute-field-input.tsx +82 -0
  257. package/blocks/objects/components/attribute-form-dialog.tsx +159 -0
  258. package/blocks/objects/components/object-not-found.tsx +34 -0
  259. package/blocks/objects/components/object-record-detail.tsx +143 -0
  260. package/blocks/objects/components/object-schema-editor.tsx +197 -0
  261. package/blocks/objects/components/object-table.tsx +130 -0
  262. package/blocks/objects/components/record-form-dialog.tsx +112 -0
  263. package/blocks/objects/components/record-roles-panel.tsx +106 -0
  264. package/blocks/objects/hooks/use-object-schema.ts +36 -0
  265. package/blocks/objects/lib/object-types.ts +214 -0
  266. package/blocks/objects/recipes/define-object-and-add-records.ts +24 -0
  267. package/blocks/objects/recipes/update-audit-and-archive-records.ts +39 -0
  268. package/blocks/objects/recipes/upsert-records-from-your-system.ts +30 -0
  269. package/blocks/pages/README.md +104 -0
  270. package/blocks/pages/block.json +223 -0
  271. package/blocks/pages/components/brand-kit-editor.tsx +152 -0
  272. package/blocks/pages/components/content-library.tsx +163 -0
  273. package/blocks/pages/components/page-editor.tsx +253 -0
  274. package/blocks/pages/components/page-list.tsx +159 -0
  275. package/blocks/pages/components/seo-report.tsx +159 -0
  276. package/blocks/pages/lib/studio.ts +77 -0
  277. package/blocks/pages/recipes/audit-site-seo.ts +28 -0
  278. package/blocks/pages/recipes/create-and-publish-page.ts +26 -0
  279. package/blocks/pages/recipes/edit-page-section.ts +25 -0
  280. package/blocks/pages/recipes/refresh-brand-kit.ts +22 -0
  281. package/blocks/quotes/README.md +79 -0
  282. package/blocks/quotes/block.json +183 -0
  283. package/blocks/quotes/components/product-picker.tsx +80 -0
  284. package/blocks/quotes/components/quote-builder.tsx +195 -0
  285. package/blocks/quotes/components/quote-list.tsx +79 -0
  286. package/blocks/quotes/components/quote-viewer.tsx +135 -0
  287. package/blocks/quotes/components/signature-status.tsx +77 -0
  288. package/blocks/quotes/hooks/use-debounced.ts +13 -0
  289. package/blocks/quotes/lib/quotes.ts +142 -0
  290. package/blocks/quotes/recipes/create-and-send-quote.ts +44 -0
  291. package/blocks/quotes/recipes/revise-sent-quote.ts +18 -0
  292. package/blocks/quotes/recipes/track-quote-signature.ts +22 -0
  293. package/blocks/radar/README.md +106 -0
  294. package/blocks/radar/block.json +189 -0
  295. package/blocks/radar/components/competitor-battle-card.tsx +53 -0
  296. package/blocks/radar/components/competitor-tracker.tsx +158 -0
  297. package/blocks/radar/components/radar-overview.tsx +67 -0
  298. package/blocks/radar/components/radar-report.tsx +86 -0
  299. package/blocks/radar/hooks/use-competitors.ts +23 -0
  300. package/blocks/radar/lib/radar-types.ts +124 -0
  301. package/blocks/radar/recipes/battle-card.ts +28 -0
  302. package/blocks/radar/recipes/deep-dive-report.ts +32 -0
  303. package/blocks/radar/recipes/marketing-snapshot.ts +18 -0
  304. package/blocks/radar/recipes/track-and-scan.ts +39 -0
  305. package/blocks/search/README.md +129 -0
  306. package/blocks/search/block.json +185 -0
  307. package/blocks/search/components/filter-builder.tsx +149 -0
  308. package/blocks/search/components/prospect-results.tsx +175 -0
  309. package/blocks/search/components/save-to-list-dialog.tsx +135 -0
  310. package/blocks/search/components/saved-searches.tsx +95 -0
  311. package/blocks/search/hooks/use-filter-options.ts +41 -0
  312. package/blocks/search/lib/search-types.ts +149 -0
  313. package/blocks/search/recipes/explore-filter-values.ts +27 -0
  314. package/blocks/search/recipes/saved-searches.ts +34 -0
  315. package/blocks/search/recipes/search-and-save-to-list.ts +37 -0
  316. package/blocks/sequencer/README.md +87 -0
  317. package/blocks/sequencer/block.json +214 -0
  318. package/blocks/sequencer/components/enroll-dialog.tsx +93 -0
  319. package/blocks/sequencer/components/sequence-builder.tsx +306 -0
  320. package/blocks/sequencer/components/sequence-list.tsx +200 -0
  321. package/blocks/sequencer/components/sequence-stats.tsx +256 -0
  322. package/blocks/sequencer/components/step-editor.tsx +213 -0
  323. package/blocks/sequencer/lib/sequencer-utils.ts +168 -0
  324. package/blocks/sequencer/recipes/create-multichannel-sequence.ts +51 -0
  325. package/blocks/sequencer/recipes/launch-and-enroll.ts +44 -0
  326. package/blocks/sequencer/recipes/pause-when-unsafe.ts +30 -0
  327. package/blocks/sequencer/recipes/sequence-report.ts +22 -0
  328. package/blocks/social-ads/README.md +128 -0
  329. package/blocks/social-ads/block.json +256 -0
  330. package/blocks/social-ads/components/ad-campaign-list.tsx +136 -0
  331. package/blocks/social-ads/components/audience-sync.tsx +150 -0
  332. package/blocks/social-ads/components/creative-gallery.tsx +121 -0
  333. package/blocks/social-ads/components/post-composer.tsx +122 -0
  334. package/blocks/social-ads/components/social-post-list.tsx +116 -0
  335. package/blocks/social-ads/hooks/use-social-accounts.ts +16 -0
  336. package/blocks/social-ads/lib/social-ads-types.ts +167 -0
  337. package/blocks/social-ads/recipes/creative-to-gallery.ts +41 -0
  338. package/blocks/social-ads/recipes/schedule-post.ts +51 -0
  339. package/blocks/social-ads/recipes/sync-audience-and-launch.ts +41 -0
  340. package/blocks/visitors/README.md +56 -0
  341. package/blocks/visitors/block.json +139 -0
  342. package/blocks/visitors/components/snippet-install.tsx +169 -0
  343. package/blocks/visitors/components/traffic-chart.tsx +156 -0
  344. package/blocks/visitors/components/visitor-company-card.tsx +92 -0
  345. package/blocks/visitors/components/visitor-feed.tsx +157 -0
  346. package/blocks/visitors/lib/visitors-utils.ts +78 -0
  347. package/blocks/visitors/recipes/check-snippet-installed.ts +24 -0
  348. package/blocks/visitors/recipes/recent-company-visits.ts +27 -0
  349. package/blocks/visitors/recipes/traffic-summary.ts +24 -0
  350. package/blocks/webchat/README.md +87 -0
  351. package/blocks/webchat/block.json +134 -0
  352. package/blocks/webchat/components/chat-widget-config.tsx +160 -0
  353. package/blocks/webchat/components/conversation-list.tsx +74 -0
  354. package/blocks/webchat/lib/webchat-types.ts +83 -0
  355. package/blocks/webchat/recipes/create-bot-and-style-widget.ts +24 -0
  356. package/blocks/webchat/recipes/list-chat-visitors.ts +24 -0
  357. package/blocks/workbench/README.md +135 -0
  358. package/blocks/workbench/block.json +259 -0
  359. package/blocks/workbench/components/column-recipe-editor.tsx +183 -0
  360. package/blocks/workbench/components/run-progress.tsx +132 -0
  361. package/blocks/workbench/components/workbench-add-rows.tsx +100 -0
  362. package/blocks/workbench/components/workbench-grid.tsx +159 -0
  363. package/blocks/workbench/components/workbench-row-actions.tsx +102 -0
  364. package/blocks/workbench/components/workbench-table-list.tsx +105 -0
  365. package/blocks/workbench/hooks/use-workbench-table.ts +30 -0
  366. package/blocks/workbench/lib/waterfall-presets.ts +119 -0
  367. package/blocks/workbench/lib/workbench-types.ts +191 -0
  368. package/blocks/workbench/recipes/build-enriched-table.ts +65 -0
  369. package/blocks/workbench/recipes/import-from-search.ts +42 -0
  370. package/blocks/workbench/recipes/scrape-into-table.ts +36 -0
  371. package/blocks/workbench/recipes/waterfall-column.ts +55 -0
  372. package/blocks/workflows/README.md +100 -0
  373. package/blocks/workflows/block.json +188 -0
  374. package/blocks/workflows/components/run-history.tsx +136 -0
  375. package/blocks/workflows/components/trigger-config.tsx +134 -0
  376. package/blocks/workflows/components/workflow-editor.tsx +142 -0
  377. package/blocks/workflows/components/workflow-list.tsx +153 -0
  378. package/blocks/workflows/hooks/use-workflow.ts +51 -0
  379. package/blocks/workflows/lib/graph.ts +187 -0
  380. package/blocks/workflows/recipes/create-workflow.ts +35 -0
  381. package/blocks/workflows/recipes/find-failed-runs.ts +15 -0
  382. package/blocks/workflows/recipes/run-workflow-and-wait.ts +32 -0
  383. package/blocks/workflows/recipes/set-trigger.ts +22 -0
  384. package/dist/cli.js +5330 -29
  385. package/dist/index.browser.js +7740 -0
  386. package/dist/index.browser.js.map +1 -0
  387. package/dist/index.browser.mjs +7717 -0
  388. package/dist/index.browser.mjs.map +1 -0
  389. package/dist/index.d.mts +2220 -23
  390. package/dist/index.d.ts +2220 -23
  391. package/dist/index.js +64 -3
  392. package/dist/index.js.map +1 -1
  393. package/dist/index.mjs +64 -3
  394. package/dist/index.mjs.map +1 -1
  395. package/dist/react.browser.js +7598 -0
  396. package/dist/react.browser.js.map +1 -0
  397. package/dist/react.browser.mjs +7568 -0
  398. package/dist/react.browser.mjs.map +1 -0
  399. package/dist/react.d.mts +2082 -20
  400. package/dist/react.d.ts +2082 -20
  401. package/dist/react.js +63 -2
  402. package/dist/react.js.map +1 -1
  403. package/dist/react.mjs +63 -2
  404. package/dist/react.mjs.map +1 -1
  405. package/dist/types/agentSetup.d.ts +6 -6
  406. package/dist/types/blocks/add.d.ts +53 -0
  407. package/dist/types/blocks/create.d.ts +46 -0
  408. package/dist/types/blocks/doctor.d.ts +26 -0
  409. package/dist/types/blocks/registry.d.ts +134 -0
  410. package/dist/types/cli.d.ts +16 -0
  411. package/dist/types/core.d.ts +1 -1
  412. package/dist/types/crypto-browser.d.ts +2 -0
  413. package/dist/types/crypto-node.d.ts +6 -0
  414. package/dist/types/react.d.ts +1 -1
  415. package/dist/types/version.d.ts +2 -2
  416. package/dist/types/webhooks.d.ts +2 -2
  417. package/dist/ui/index.d.mts +54 -0
  418. package/dist/ui/index.d.ts +54 -0
  419. package/dist/ui/index.js +105 -0
  420. package/dist/ui/index.js.map +1 -0
  421. package/dist/ui/index.mjs +44 -0
  422. package/dist/ui/index.mjs.map +1 -0
  423. package/dist/ui/lib/compose-refs.d.mts +19 -0
  424. package/dist/ui/lib/compose-refs.d.ts +19 -0
  425. package/dist/ui/lib/compose-refs.js +76 -0
  426. package/dist/ui/lib/compose-refs.js.map +1 -0
  427. package/dist/ui/lib/compose-refs.mjs +41 -0
  428. package/dist/ui/lib/compose-refs.mjs.map +1 -0
  429. package/dist/ui/lib/use-mobile.d.mts +4 -0
  430. package/dist/ui/lib/use-mobile.d.ts +4 -0
  431. package/dist/ui/lib/use-mobile.js +57 -0
  432. package/dist/ui/lib/use-mobile.js.map +1 -0
  433. package/dist/ui/lib/use-mobile.mjs +22 -0
  434. package/dist/ui/lib/use-mobile.mjs.map +1 -0
  435. package/dist/ui/lib/utils.d.mts +10 -0
  436. package/dist/ui/lib/utils.d.ts +10 -0
  437. package/dist/ui/lib/utils.js +33 -0
  438. package/dist/ui/lib/utils.js.map +1 -0
  439. package/dist/ui/lib/utils.mjs +9 -0
  440. package/dist/ui/lib/utils.mjs.map +1 -0
  441. package/dist/ui/primitives/alert-dialog.d.mts +22 -0
  442. package/dist/ui/primitives/alert-dialog.d.ts +22 -0
  443. package/dist/ui/primitives/alert-dialog.js +163 -0
  444. package/dist/ui/primitives/alert-dialog.js.map +1 -0
  445. package/dist/ui/primitives/alert-dialog.mjs +119 -0
  446. package/dist/ui/primitives/alert-dialog.mjs.map +1 -0
  447. package/dist/ui/primitives/avatar.d.mts +8 -0
  448. package/dist/ui/primitives/avatar.d.ts +8 -0
  449. package/dist/ui/primitives/avatar.js +91 -0
  450. package/dist/ui/primitives/avatar.js.map +1 -0
  451. package/dist/ui/primitives/avatar.mjs +55 -0
  452. package/dist/ui/primitives/avatar.mjs.map +1 -0
  453. package/dist/ui/primitives/breadcrumb.d.mts +13 -0
  454. package/dist/ui/primitives/breadcrumb.d.ts +13 -0
  455. package/dist/ui/primitives/breadcrumb.js +127 -0
  456. package/dist/ui/primitives/breadcrumb.js.map +1 -0
  457. package/dist/ui/primitives/breadcrumb.mjs +97 -0
  458. package/dist/ui/primitives/breadcrumb.mjs.map +1 -0
  459. package/dist/ui/primitives/button.d.mts +15 -0
  460. package/dist/ui/primitives/button.d.ts +15 -0
  461. package/dist/ui/primitives/button.js +91 -0
  462. package/dist/ui/primitives/button.js.map +1 -0
  463. package/dist/ui/primitives/button.mjs +56 -0
  464. package/dist/ui/primitives/button.mjs.map +1 -0
  465. package/dist/ui/primitives/card.d.mts +10 -0
  466. package/dist/ui/primitives/card.d.ts +10 -0
  467. package/dist/ui/primitives/card.js +101 -0
  468. package/dist/ui/primitives/card.js.map +1 -0
  469. package/dist/ui/primitives/card.mjs +62 -0
  470. package/dist/ui/primitives/card.mjs.map +1 -0
  471. package/dist/ui/primitives/carousel.d.mts +45 -0
  472. package/dist/ui/primitives/carousel.d.ts +45 -0
  473. package/dist/ui/primitives/carousel.js +300 -0
  474. package/dist/ui/primitives/carousel.js.map +1 -0
  475. package/dist/ui/primitives/carousel.mjs +261 -0
  476. package/dist/ui/primitives/carousel.mjs.map +1 -0
  477. package/dist/ui/primitives/chart.d.mts +68 -0
  478. package/dist/ui/primitives/chart.d.ts +68 -0
  479. package/dist/ui/primitives/chart.js +280 -0
  480. package/dist/ui/primitives/chart.js.map +1 -0
  481. package/dist/ui/primitives/chart.mjs +241 -0
  482. package/dist/ui/primitives/chart.mjs.map +1 -0
  483. package/dist/ui/primitives/collapsible.d.mts +8 -0
  484. package/dist/ui/primitives/collapsible.d.ts +8 -0
  485. package/dist/ui/primitives/collapsible.js +72 -0
  486. package/dist/ui/primitives/collapsible.js.map +1 -0
  487. package/dist/ui/primitives/collapsible.mjs +36 -0
  488. package/dist/ui/primitives/collapsible.mjs.map +1 -0
  489. package/dist/ui/primitives/context-menu.d.mts +29 -0
  490. package/dist/ui/primitives/context-menu.d.ts +29 -0
  491. package/dist/ui/primitives/context-menu.js +203 -0
  492. package/dist/ui/primitives/context-menu.js.map +1 -0
  493. package/dist/ui/primitives/context-menu.mjs +155 -0
  494. package/dist/ui/primitives/context-menu.mjs.map +1 -0
  495. package/dist/ui/primitives/dialog.d.mts +26 -0
  496. package/dist/ui/primitives/dialog.d.ts +26 -0
  497. package/dist/ui/primitives/dialog.js +192 -0
  498. package/dist/ui/primitives/dialog.js.map +1 -0
  499. package/dist/ui/primitives/dialog.mjs +148 -0
  500. package/dist/ui/primitives/dialog.mjs.map +1 -0
  501. package/dist/ui/primitives/drawer.d.mts +26 -0
  502. package/dist/ui/primitives/drawer.d.ts +26 -0
  503. package/dist/ui/primitives/drawer.js +146 -0
  504. package/dist/ui/primitives/drawer.js.map +1 -0
  505. package/dist/ui/primitives/drawer.mjs +103 -0
  506. package/dist/ui/primitives/drawer.mjs.map +1 -0
  507. package/dist/ui/primitives/input.d.mts +5 -0
  508. package/dist/ui/primitives/input.d.ts +5 -0
  509. package/dist/ui/primitives/input.js +46 -0
  510. package/dist/ui/primitives/input.js.map +1 -0
  511. package/dist/ui/primitives/input.mjs +22 -0
  512. package/dist/ui/primitives/input.mjs.map +1 -0
  513. package/dist/ui/primitives/item.d.mts +27 -0
  514. package/dist/ui/primitives/item.d.ts +27 -0
  515. package/dist/ui/primitives/item.js +221 -0
  516. package/dist/ui/primitives/item.js.map +1 -0
  517. package/dist/ui/primitives/item.mjs +188 -0
  518. package/dist/ui/primitives/item.mjs.map +1 -0
  519. package/dist/ui/primitives/kbd.d.mts +15 -0
  520. package/dist/ui/primitives/kbd.d.ts +15 -0
  521. package/dist/ui/primitives/kbd.js +45 -0
  522. package/dist/ui/primitives/kbd.js.map +1 -0
  523. package/dist/ui/primitives/kbd.mjs +21 -0
  524. package/dist/ui/primitives/kbd.mjs.map +1 -0
  525. package/dist/ui/primitives/label.d.mts +6 -0
  526. package/dist/ui/primitives/label.d.ts +6 -0
  527. package/dist/ui/primitives/label.js +55 -0
  528. package/dist/ui/primitives/label.js.map +1 -0
  529. package/dist/ui/primitives/label.mjs +21 -0
  530. package/dist/ui/primitives/label.mjs.map +1 -0
  531. package/dist/ui/primitives/resizable.d.mts +10 -0
  532. package/dist/ui/primitives/resizable.d.ts +10 -0
  533. package/dist/ui/primitives/resizable.js +68 -0
  534. package/dist/ui/primitives/resizable.js.map +1 -0
  535. package/dist/ui/primitives/resizable.mjs +42 -0
  536. package/dist/ui/primitives/resizable.mjs.map +1 -0
  537. package/dist/ui/primitives/save-status.d.mts +31 -0
  538. package/dist/ui/primitives/save-status.d.ts +31 -0
  539. package/dist/ui/primitives/save-status.js +150 -0
  540. package/dist/ui/primitives/save-status.js.map +1 -0
  541. package/dist/ui/primitives/save-status.mjs +126 -0
  542. package/dist/ui/primitives/save-status.mjs.map +1 -0
  543. package/dist/ui/primitives/separator.d.mts +6 -0
  544. package/dist/ui/primitives/separator.d.ts +6 -0
  545. package/dist/ui/primitives/separator.js +62 -0
  546. package/dist/ui/primitives/separator.js.map +1 -0
  547. package/dist/ui/primitives/separator.mjs +28 -0
  548. package/dist/ui/primitives/separator.mjs.map +1 -0
  549. package/dist/ui/primitives/sheet.d.mts +16 -0
  550. package/dist/ui/primitives/sheet.d.ts +16 -0
  551. package/dist/ui/primitives/sheet.js +170 -0
  552. package/dist/ui/primitives/sheet.js.map +1 -0
  553. package/dist/ui/primitives/sheet.mjs +129 -0
  554. package/dist/ui/primitives/sheet.mjs.map +1 -0
  555. package/dist/ui/primitives/sidebar.d.mts +74 -0
  556. package/dist/ui/primitives/sidebar.d.ts +74 -0
  557. package/dist/ui/primitives/sidebar.js +697 -0
  558. package/dist/ui/primitives/sidebar.js.map +1 -0
  559. package/dist/ui/primitives/sidebar.mjs +651 -0
  560. package/dist/ui/primitives/sidebar.mjs.map +1 -0
  561. package/dist/ui/primitives/skeleton.d.mts +5 -0
  562. package/dist/ui/primitives/skeleton.d.ts +5 -0
  563. package/dist/ui/primitives/skeleton.js +40 -0
  564. package/dist/ui/primitives/skeleton.js.map +1 -0
  565. package/dist/ui/primitives/skeleton.mjs +16 -0
  566. package/dist/ui/primitives/skeleton.mjs.map +1 -0
  567. package/dist/ui/primitives/slider.d.mts +20 -0
  568. package/dist/ui/primitives/slider.d.ts +20 -0
  569. package/dist/ui/primitives/slider.js +112 -0
  570. package/dist/ui/primitives/slider.js.map +1 -0
  571. package/dist/ui/primitives/slider.mjs +78 -0
  572. package/dist/ui/primitives/slider.mjs.map +1 -0
  573. package/dist/ui/primitives/sortable.d.mts +50 -0
  574. package/dist/ui/primitives/sortable.d.ts +50 -0
  575. package/dist/ui/primitives/sortable.js +456 -0
  576. package/dist/ui/primitives/sortable.js.map +1 -0
  577. package/dist/ui/primitives/sortable.mjs +435 -0
  578. package/dist/ui/primitives/sortable.mjs.map +1 -0
  579. package/dist/ui/primitives/switch.d.mts +6 -0
  580. package/dist/ui/primitives/switch.d.ts +6 -0
  581. package/dist/ui/primitives/switch.js +67 -0
  582. package/dist/ui/primitives/switch.js.map +1 -0
  583. package/dist/ui/primitives/switch.mjs +33 -0
  584. package/dist/ui/primitives/switch.mjs.map +1 -0
  585. package/dist/ui/primitives/table.d.mts +12 -0
  586. package/dist/ui/primitives/table.d.ts +12 -0
  587. package/dist/ui/primitives/table.js +130 -0
  588. package/dist/ui/primitives/table.js.map +1 -0
  589. package/dist/ui/primitives/table.mjs +89 -0
  590. package/dist/ui/primitives/table.mjs.map +1 -0
  591. package/dist/ui/primitives/tabs.d.mts +9 -0
  592. package/dist/ui/primitives/tabs.d.ts +9 -0
  593. package/dist/ui/primitives/tabs.js +86 -0
  594. package/dist/ui/primitives/tabs.js.map +1 -0
  595. package/dist/ui/primitives/tabs.mjs +49 -0
  596. package/dist/ui/primitives/tabs.mjs.map +1 -0
  597. package/dist/ui/primitives/textarea.d.mts +5 -0
  598. package/dist/ui/primitives/textarea.d.ts +5 -0
  599. package/dist/ui/primitives/textarea.js +43 -0
  600. package/dist/ui/primitives/textarea.js.map +1 -0
  601. package/dist/ui/primitives/textarea.mjs +19 -0
  602. package/dist/ui/primitives/textarea.mjs.map +1 -0
  603. package/dist/ui/primitives/tooltip.d.mts +9 -0
  604. package/dist/ui/primitives/tooltip.d.ts +9 -0
  605. package/dist/ui/primitives/tooltip.js +94 -0
  606. package/dist/ui/primitives/tooltip.js.map +1 -0
  607. package/dist/ui/primitives/tooltip.mjs +57 -0
  608. package/dist/ui/primitives/tooltip.mjs.map +1 -0
  609. package/docs/agents.md +72 -29
  610. package/docs/api/README.md +7 -3
  611. package/docs/api/appObjects.d.ts +3 -1
  612. package/docs/api/appObjects.md +2 -1
  613. package/docs/api/by-path.md +51 -0
  614. package/docs/api/dataPipelines.d.ts +149 -0
  615. package/docs/api/dataPipelines.md +232 -0
  616. package/docs/api/forms.d.ts +16 -0
  617. package/docs/api/forms.md +8 -0
  618. package/docs/api/objects.d.ts +705 -5
  619. package/docs/api/objects.md +1099 -14
  620. package/docs/api/ops.d.ts +1 -1
  621. package/docs/api/ops.md +1 -1
  622. package/docs/api/processLists.d.ts +247 -0
  623. package/docs/api/processLists.md +409 -0
  624. package/docs/api/quotes.d.ts +3 -1
  625. package/docs/api/quotes.md +7 -2
  626. package/docs/api/radar.d.ts +4 -0
  627. package/docs/api/radar.md +1 -0
  628. package/docs/api/reports.d.ts +476 -0
  629. package/docs/api/reports.md +539 -0
  630. package/docs/api/scheduleBuy.d.ts +12 -8
  631. package/docs/api/scheduleBuy.md +13 -10
  632. package/docs/api/seo.d.ts +406 -3
  633. package/docs/api/seo.md +505 -1
  634. package/docs/api/workspaceBackup.d.ts +324 -0
  635. package/docs/api/workspaceBackup.md +427 -0
  636. package/package.json +174 -5
  637. package/stacks/6sense.json +46 -0
  638. package/stacks/README.md +20 -0
  639. package/stacks/apollo.json +128 -0
  640. package/stacks/clay.json +59 -0
  641. package/stacks/gong.json +72 -0
  642. package/stacks/hubspot.json +162 -0
  643. package/stacks/intercom.json +53 -0
  644. package/stacks/mailchimp.json +71 -0
  645. package/stacks/outreach.json +86 -0
  646. package/stacks/salesforce.json +94 -0
  647. package/stacks/stack.schema.json +32 -0
  648. package/stacks/starter.json +22 -0
  649. package/styles/styles.css +2 -0
  650. package/styles/theme.css +181 -0
  651. package/styles/tokens.css +284 -0
  652. package/templates/next-app/README.md.tmpl +35 -0
  653. package/templates/next-app/_pages/redirect-page.tsx.tmpl +5 -0
  654. package/templates/next-app/_pages/route-page.tsx.tmpl +9 -0
  655. package/templates/next-app/app/globals.css.tmpl +8 -0
  656. package/templates/next-app/app/layout.tsx.tmpl +19 -0
  657. package/templates/next-app/components/app-shell.tsx.tmpl +34 -0
  658. package/templates/next-app/dot-env.local.example.tmpl +6 -0
  659. package/templates/next-app/dot-gitignore.tmpl +7 -0
  660. package/templates/next-app/lib/nav.ts.tmpl +2 -0
  661. package/templates/next-app/next.config.mjs.tmpl +4 -0
  662. package/templates/next-app/package.json.tmpl +25 -0
  663. package/templates/next-app/postcss.config.mjs.tmpl +4 -0
  664. package/templates/next-app/tsconfig.json.tmpl +21 -0
@@ -0,0 +1,168 @@
1
+ "use client";
2
+
3
+ /**
4
+ * Types and pure helpers for the sequencer components: the step kinds, how a draft step becomes an API step,
5
+ * what makes a step invalid BEFORE it is sent (the API accepts some broken steps and only fails at send
6
+ * time), and sequence status helpers.
7
+ */
8
+
9
+ export type StepKind = "email" | "linkedin" | "call" | "task";
10
+
11
+ /** UI step kind -> the API `step_type`. `linkedin` is HeyReach; `task` is a manual dialer task. */
12
+ export const STEP_TYPE: Record<StepKind, string> = { email: "EMAIL", linkedin: "HEYREACH", call: "PHONE", task: "MANUAL_DIALER" };
13
+ export const KIND_LABEL: Record<StepKind, string> = { email: "Email", linkedin: "LinkedIn", call: "Call", task: "Call task" };
14
+ export const KINDS = Object.keys(STEP_TYPE) as StepKind[];
15
+
16
+ export const LINKEDIN_ACTIONS = ["CONNECTION_REQUEST", "MESSAGE", "INMAIL", "FOLLOW", "VIEW_PROFILE", "LIKE_POST"] as const;
17
+ export type LinkedinAction = (typeof LINKEDIN_ACTIONS)[number];
18
+ export type InputType = "MANUAL_TEMPLATE" | "AI_GENERATED_TEMPLATE" | "ON_DEMAND";
19
+
20
+ export interface DraftStep {
21
+ /** Local key for React lists. */
22
+ key: string;
23
+ /** The API step id once the step is saved. */
24
+ id?: string;
25
+ kind: StepKind;
26
+ input_type: InputType;
27
+ /** Wait before this step, in days (the API wants seconds). */
28
+ wait_days: number;
29
+ step_data: Record<string, unknown>;
30
+ /** True once changed since it was loaded or saved. */
31
+ dirty?: boolean;
32
+ }
33
+
34
+ export interface SequenceRow {
35
+ id: string;
36
+ name?: string | null;
37
+ status?: string | null;
38
+ step_count?: number | null;
39
+ contact_count?: number | null;
40
+ sequence_kind?: string | null;
41
+ associated_list_id?: number | null;
42
+ updated_at?: string | null;
43
+ }
44
+
45
+ export interface ApiStep {
46
+ id?: string;
47
+ step_order: number;
48
+ step_type: string;
49
+ input_type?: string;
50
+ time_interval?: number | null;
51
+ step_data?: Record<string, unknown> | null;
52
+ }
53
+
54
+ let counter = 0;
55
+ export const newKey = (): string => `step-${Date.now().toString(36)}-${counter++}`;
56
+
57
+ export function newStep(kind: StepKind): DraftStep {
58
+ const data: Record<string, unknown> =
59
+ kind === "email"
60
+ ? { subject: "", body: "" }
61
+ : kind === "linkedin"
62
+ ? { linkedin_action_type: "CONNECTION_REQUEST", linkedin_connection_message: "" }
63
+ : { dial_dnc: false, phone_options: ["mobile", "direct"] };
64
+ return { key: newKey(), kind, input_type: "MANUAL_TEMPLATE", wait_days: 2, step_data: data };
65
+ }
66
+
67
+ export function kindOf(stepType: string | undefined): StepKind {
68
+ const t = (stepType ?? "").toUpperCase();
69
+ if (t === "HEYREACH" || t === "NETRION" || t === "UNIPILE" || t === "ARLINK" || t.includes("LINKEDIN")) return "linkedin";
70
+ if (t === "PHONE") return "call";
71
+ if (t === "MANUAL_DIALER") return "task";
72
+ return "email";
73
+ }
74
+
75
+ export function fromApiStep(s: ApiStep): DraftStep {
76
+ return {
77
+ key: s.id ?? newKey(),
78
+ id: s.id,
79
+ kind: kindOf(s.step_type),
80
+ input_type: (s.input_type as InputType) ?? "MANUAL_TEMPLATE",
81
+ wait_days: (s.time_interval ?? 0) / 86400,
82
+ step_data: { ...(s.step_data ?? {}) },
83
+ };
84
+ }
85
+
86
+ /** The request shape for create and add-steps. `order` is 1-based. */
87
+ export function toApiStep(step: DraftStep, order: number) {
88
+ return {
89
+ step_order: order,
90
+ step_type: STEP_TYPE[step.kind],
91
+ input_type: step.input_type,
92
+ time_interval: Math.max(0, Math.round(step.wait_days * 86400)),
93
+ step_data: step.step_data,
94
+ };
95
+ }
96
+
97
+ const text = (v: unknown): string => (typeof v === "string" ? v.trim() : "");
98
+
99
+ /** Problems that would make the API accept the step but fail or send nothing later. Empty means fine. */
100
+ export function stepIssues(step: DraftStep): string[] {
101
+ const d = step.step_data;
102
+ if (step.kind === "email") {
103
+ if (step.input_type === "ON_DEMAND") return text(d.instructions) ? [] : ["Tell the AI what to write in the instructions."];
104
+ if (step.input_type === "AI_GENERATED_TEMPLATE") return text(d.instructions) ? [] : ["Add instructions for the AI template."];
105
+ return [!text(d.subject) && "Add a subject.", !text(d.body) && "Add a body."].filter(Boolean) as string[];
106
+ }
107
+ if (step.kind === "linkedin") {
108
+ const action = text(d.linkedin_action_type);
109
+ if (!action) return ["Choose a LinkedIn action."];
110
+ const need: Partial<Record<string, string>> = {
111
+ CONNECTION_REQUEST: "linkedin_connection_message",
112
+ MESSAGE: "linkedin_message_text",
113
+ INMAIL: "linkedin_inmail_body",
114
+ };
115
+ const key = need[action];
116
+ return key && !text(d[key]) ? ["Add the message for this LinkedIn action."] : [];
117
+ }
118
+ return [];
119
+ }
120
+
121
+ /** A `{{token}}` that is opened but not closed, or the reverse: the sender silently deletes these. */
122
+ export function hasBrokenTokens(value: string): boolean {
123
+ return (value.match(/\{\{/g) ?? []).length !== (value.match(/\}\}/g) ?? []).length;
124
+ }
125
+
126
+ export function statusGroup(status: string | null | undefined): "draft" | "live" | "paused" | "ended" | "busy" {
127
+ const s = (status ?? "").toLowerCase();
128
+ if (["live", "waiting", "running", "active"].includes(s)) return "live";
129
+ if (s === "paused") return "paused";
130
+ if (["terminated", "completed", "archived", "finished"].includes(s)) return "ended";
131
+ if (["scheduling", "pausing", "resuming", "terminating"].includes(s)) return "busy";
132
+ return "draft";
133
+ }
134
+
135
+ export const STATUS_CLASS: Record<ReturnType<typeof statusGroup>, string> = {
136
+ draft: "bg-gray-100 text-gray-700",
137
+ live: "bg-green-100 text-green-800",
138
+ paused: "bg-amber-100 text-amber-800",
139
+ ended: "bg-slate-100 text-slate-600",
140
+ busy: "bg-blue-100 text-blue-800",
141
+ };
142
+
143
+ export function listOf<T>(envelope: unknown): T[] {
144
+ const data = (envelope as { data?: unknown } | null)?.data;
145
+ if (Array.isArray(data)) return data as T[];
146
+ const obj = data as Record<string, unknown> | null | undefined;
147
+ for (const key of ["items", "steps", "rows"]) if (Array.isArray(obj?.[key])) return obj![key] as T[];
148
+ return [];
149
+ }
150
+
151
+ export function objectOf(envelope: unknown): Record<string, unknown> {
152
+ const data = (envelope as { data?: unknown } | null)?.data;
153
+ return data && typeof data === "object" && !Array.isArray(data) ? (data as Record<string, unknown>) : {};
154
+ }
155
+
156
+ /** Map a mailbox's provider to the sequence channel type the API takes. */
157
+ export function channelTypeFor(provider: string | null | undefined): "GMAIL" | "INBOXKIT" | "SMTP" {
158
+ const p = (provider ?? "").toLowerCase();
159
+ if (p.includes("gmail") || p.includes("google")) return "GMAIL";
160
+ if (p.includes("inboxkit") || p.includes("managed")) return "INBOXKIT";
161
+ return "SMTP";
162
+ }
163
+
164
+ export function newIdempotencyKey(): string {
165
+ return typeof crypto !== "undefined" && "randomUUID" in crypto
166
+ ? crypto.randomUUID()
167
+ : `g8-${Date.now()}-${Math.random().toString(36).slice(2)}`;
168
+ }
@@ -0,0 +1,51 @@
1
+ /**
2
+ * @title Create a draft sequence with email, LinkedIn and a call
3
+ * @when Building outreach. Creating the draft is tier `external` in the contract but contacts nobody; the
4
+ * LAUNCH is what reaches people (see launch-and-enroll.ts). Three rules the API only enforces at send time:
5
+ * 1) an EMAIL step needs `input_type: "MANUAL_TEMPLATE"` or its subject/body are ignored; 2) a LinkedIn
6
+ * (HEYREACH) step needs `linkedin_action_type` and the action's own copy key, never `body`; 3) `time_interval`
7
+ * is in SECONDS. Attach the sender mailbox as a channel; LinkedIn steps also need a LinkedIn sender (app).
8
+ */
9
+ import { g8 } from "@graph8/sdk";
10
+
11
+ g8.init({ apiKey: process.env.G8_API_KEY! });
12
+
13
+ const DAY = 86400;
14
+
15
+ export async function createDraftSequence(name: string, listId: number, mailbox: { id: number; email: string }) {
16
+ const created = await g8.api.sequenceLifecycle.createSequence({
17
+ body: {
18
+ name,
19
+ associated_list_id: listId,
20
+ finish_on_reply: true,
21
+ steps: [
22
+ {
23
+ step_order: 1,
24
+ step_type: "EMAIL",
25
+ input_type: "MANUAL_TEMPLATE",
26
+ time_interval: 0,
27
+ step_data: {
28
+ subject: "{{Quick question|One idea}} for {{company}}",
29
+ body: "Hi {{first_name}},\n\nI noticed {{company}} is growing. Worth a chat?",
30
+ },
31
+ },
32
+ {
33
+ step_order: 2,
34
+ step_type: "HEYREACH",
35
+ input_type: "MANUAL_TEMPLATE",
36
+ time_interval: 2 * DAY,
37
+ step_data: { linkedin_action_type: "CONNECTION_REQUEST", linkedin_connection_message: "Hi {{first_name}}, I'd love to connect." },
38
+ },
39
+ {
40
+ step_order: 3,
41
+ step_type: "PHONE",
42
+ input_type: "MANUAL_TEMPLATE",
43
+ time_interval: 3 * DAY,
44
+ step_data: { dial_dnc: false, phone_options: ["mobile", "direct"] },
45
+ },
46
+ ],
47
+ channels: [{ channel_id: mailbox.id, channel_value: mailbox.email, channel_type: "SMTP" }],
48
+ },
49
+ });
50
+ return created.data?.id;
51
+ }
@@ -0,0 +1,44 @@
1
+ /**
2
+ * @title Check a draft, launch it, and enroll contacts
3
+ * @when Starting outreach. Both `runSequence` and `addContactsToSequence` are tier `external`: they reach real
4
+ * people, so a human must approve the recipient count first. `previewSequence` is free and tells you whether the
5
+ * copy will send as shown. Re-running after a failure is safe: the launch is skipped unless the sequence is still a draft, and enrollment uses a key
6
+ * derived from the sequence and contact ids and is idempotent anyway (already-enrolled contacts are skipped) and needs BOTH
7
+ * `contact_ids` and the `list_id` they came from. Contacts must be in a list already: search results are masked
8
+ * until saved.
9
+ */
10
+ import { createHash } from "node:crypto";
11
+ import { g8 } from "@graph8/sdk";
12
+
13
+ g8.init({ apiKey: process.env.G8_API_KEY! });
14
+
15
+ export async function launchAndEnroll(sequenceId: string, listId: number, contactIds: number[], humanApproved: boolean) {
16
+ if (!humanApproved) throw new Error(`Refusing to contact ${contactIds.length} people without approval`);
17
+
18
+ const verdict = await g8.api.deliverability.getSafeToSend();
19
+ if ((verdict.data as { safe_to_send?: boolean } | undefined)?.safe_to_send === false)
20
+ throw new Error("Deliverability says not safe to send right now");
21
+
22
+ const preview = await g8.api.sequenceLifecycle.previewSequence({ path: { sequence_id: sequenceId } });
23
+ const issues = (preview.data as { content_issues?: unknown[]; will_send_as_shown?: boolean } | undefined)?.content_issues ?? [];
24
+ if (issues.length) throw new Error(`Fix the copy first: ${JSON.stringify(issues)}`);
25
+
26
+ const current = await g8.api.sequences.getSequence({ path: { sequence_id: sequenceId } });
27
+ const status = (current.data as { status?: string } | undefined)?.status;
28
+ // Launch ONLY a draft. "live" has several spellings (live, waiting, running, active) and there are transitional
29
+ // states (scheduling, resuming): anything that is not a draft must not be launched again.
30
+ const isDraft = ["drafted", "draft"].includes((status ?? "").toLowerCase());
31
+ const launched = isDraft
32
+ ? await g8.api.sequences.runSequence({ path: { sequence_id: sequenceId } })
33
+ : { data: { status, skipped: "not a draft, so it was not launched again" } };
34
+ const enrolled = await g8.api.sequences.addContactsToSequence(
35
+ { path: { sequence_id: sequenceId }, body: { contact_ids: contactIds, list_id: listId } },
36
+ {
37
+ idempotencyKey: createHash("sha256")
38
+ .update(`${sequenceId}|${listId}|${[...contactIds].sort((a, b) => a - b).join(",")}`)
39
+ .digest("hex")
40
+ .slice(0, 40),
41
+ },
42
+ );
43
+ return { launched: launched.data, enrolled: enrolled.data };
44
+ }
@@ -0,0 +1,30 @@
1
+ /**
2
+ * @title Pause live sequences when deliverability turns bad
3
+ * @when A scheduled guard. `pauseSequence` is tier `external` (it changes who is being contacted): run it
4
+ * only under a standing instruction from the human. Pausing keeps every contact's place; `resumeSequence`
5
+ * continues. Skips sequences that are already paused or still in a transitional status.
6
+ */
7
+ import { g8 } from "@graph8/sdk";
8
+
9
+ g8.init({ apiKey: process.env.G8_API_KEY! });
10
+
11
+ export async function pauseIfUnsafe() {
12
+ const verdict = await g8.api.deliverability.getSafeToSend();
13
+ if ((verdict.data as { safe_to_send?: boolean } | undefined)?.safe_to_send !== false) return [];
14
+
15
+ const paused: string[] = [];
16
+ const seen = new Set<string>();
17
+ // Pausing takes a sequence out of the "live" filter, so page 1 keeps showing the rest. Stop when a page
18
+ // brings nothing new (pauses still settling) so this cannot loop forever.
19
+ for (;;) {
20
+ const live = await g8.api.sequences.listSequences({ query: { status: "live", limit: 100, page: 1 } });
21
+ const fresh = (live.data ?? []).filter((seq) => !seen.has(seq.id));
22
+ if (fresh.length === 0) break;
23
+ for (const seq of fresh) {
24
+ seen.add(seq.id);
25
+ await g8.api.sequences.pauseSequence({ path: { sequence_id: seq.id } });
26
+ paused.push(seq.id);
27
+ }
28
+ }
29
+ return paused;
30
+ }
@@ -0,0 +1,22 @@
1
+ /**
2
+ * @title Report how a sequence is doing
3
+ * @when A daily digest or an agent deciding whether to pause. Reads only. `step_stats` gives per-step counts by
4
+ * state; `skip_reason_breakdown` is counted once per contact, so do NOT expect it to equal the sum of the
5
+ * per-step skipped counts.
6
+ */
7
+ import { g8 } from "@graph8/sdk";
8
+
9
+ g8.init({ apiKey: process.env.G8_API_KEY! });
10
+
11
+ export async function sequenceReport(sequenceId: string) {
12
+ const [stats, analytics] = await Promise.all([
13
+ g8.api.sequences.getSequenceStats({ path: { sequence_id: sequenceId } }),
14
+ g8.api.sequenceLifecycle.getSequenceAnalytics({ path: { sequence_id: sequenceId } }),
15
+ ]);
16
+ return {
17
+ contacts: stats.data?.total_contacts ?? 0,
18
+ steps: stats.data?.step_stats ?? [],
19
+ skipped: stats.data?.skip_reason_breakdown ?? {},
20
+ overview: analytics.data?.overview ?? {},
21
+ };
22
+ }
@@ -0,0 +1,128 @@
1
+ # social-ads
2
+
3
+ Publish to social, watch your ads, make ad creatives and feed ad platforms with your lists. Builds on `lists`
4
+ (the list picker for audience syncs).
5
+
6
+ Install: `npx @graph8/sdk add social-ads` (installs `foundation`, `crm` and `lists` first).
7
+
8
+ ## What you get
9
+
10
+ | Component | Use it for | Props |
11
+ |---|---|---|
12
+ | `PostComposer` | Write a post, draft with AI, save, schedule or publish | `onSaved(post, action)` |
13
+ | `SocialPostList` | Posts by status; publish, cancel a scheduled post, delete | `refreshKey`, `pageSize` |
14
+ | `AdCampaignList` | Campaigns with budget, dates, results; refresh status, retry launch, delete | `refreshKey` |
15
+ | `CreativeGallery` | Generate, follow, edit and organize AI ad creatives | `status` |
16
+ | `AudienceSync` | Send a list to Meta / LinkedIn / Google / X, push, pause, launch a campaign | `onLaunched` |
17
+
18
+ Hook `useSocialAccounts()`; helpers in `lib/social-ads-types.ts` (time helpers `localInputToIso`, `formatInstant`, `formatDateOnly`).
19
+
20
+ ## Everything that publishes or launches is confirmed
21
+
22
+ Publishing and launching are the `external` tier: they reach real people or spend on an ad account, and cannot be recalled from here.
23
+
24
+ | Action | Tier | What the confirmation says |
25
+ |---|---|---|
26
+ | AI post drafts, ad creative generation, new creative image | billable | credits are used; **no advance price and no balance read** |
27
+ | Schedule a post | external | the account and the exact instant, with the time zone name |
28
+ | Publish now | external | the account; goes live immediately |
29
+ | Create an audience sync | external | the platform and the list size (people sent) |
30
+ | Push now / pause / resume a sync | external | which platform and what it does (the size is not known for an existing sync) |
31
+ | Launch a campaign | external | the platform and the daily budget; the spend is billed by the ad platform, not graph8 credits |
32
+ | Refresh or retry a campaign | external | which platform is asked |
33
+ | Cancel a scheduled post, delete a post, creative or sync | destructive | what is removed; a 404 on delete counts as done |
34
+ | Delete an ad campaign | destructive | **stops the live campaign on the platform first**, then removes it; a 502 means the platform refused and the campaign is still live and spending |
35
+
36
+ ## Time
37
+
38
+ A scheduled post is an instant. `PostComposer` takes a wall-clock time in the viewer's zone (`datetime-local`), sends the UTC instant
39
+ (`new Date(local).toISOString()`), and every screen shows instants in the viewer's zone with its name ("9:00 AM PDT"). Campaign start and end
40
+ are **date-only**: send `YYYY-MM-DD` as typed, show them with `formatDateOnly` (UTC) so a date never slides a day.
41
+
42
+ ## The flow, with the ids that pass between steps
43
+
44
+ 1. `GET /social/accounts` -> an account `id` = `account_ref`. Empty means a person must connect LinkedIn in graph8 first (browser sign-in, no API).
45
+ 2. `POST /social/posts/generate { instructions, variants }` (billable, saves nothing) -> `variants[].body`.
46
+ 3. `POST /social/posts { body, account_ref, idempotency_key }` -> a DRAFT with `id`. The composer keeps that id: a retry after step 4 failed PATCHes it, never creates a second.
47
+ 4. `POST /social/posts/{id}/schedule { scheduled_at }` or `/publish` (external). Poll `GET /social/posts/{id}` until `live` or `failed`; the list shows it.
48
+ 5. Ads: connect ad accounts in graph8 (app only). `POST /audience-syncs { audience_id, platform }` -> sync `id` (409 if that pair exists) -> `POST /audience-syncs/{id}/launch { name, daily_budget, destination_url, ... }`
49
+ -> a campaign in `GET /ad-campaigns` whose `platform_campaign_id` joins the rows of `GET /ad-campaigns/metrics` (one sync can have several campaigns; `sync_config_id` alone would sum them all).
50
+ **A refused launch is HTTP 200 with `status: "error"` and a `message` in the body**, never a success: `launchOutcome` reads it. Retry behaves the same.
51
+ 6. Creatives: `GET /ad-creatives/specs` -> `POST /ad-creatives { platform, ad_format, prompt }` (201, `generating`) -> the list re-reads while any card generates -> `POST .../move-to-gallery`.
52
+
53
+ ```tsx
54
+ "use client";
55
+ import { useState } from "react";
56
+ import { PostComposer } from "@/components/g8/social-ads/post-composer";
57
+ import { SocialPostList } from "@/components/g8/social-ads/social-post-list";
58
+
59
+ export function Social() {
60
+ const [tick, setTick] = useState(0);
61
+ return (<div className="grid gap-6 md:grid-cols-2"><PostComposer onSaved={() => setTick(tick + 1)} /><SocialPostList refreshKey={tick} /></div>);
62
+ }
63
+ ```
64
+
65
+ (`add` flattens `components/` into `components/g8/social-ads/`; adjust the alias to your app.)
66
+
67
+ ## Prerequisites (a human must do these)
68
+
69
+ - `lists-installed` (app); `proxy-allowlist` (app): `social`, `ad-campaigns`, `ad-creatives`, `audience-syncs`, `lists`.
70
+ - `social-account` (api): a LinkedIn account connected in graph8 (Settings, Channels).
71
+ - `ad-accounts` (api): each ad platform connected in graph8 through its sign-in.
72
+ - `credits` (api): for AI drafts and creatives.
73
+
74
+ ## Defaults the agent can use without asking
75
+
76
+ | Decision | Default |
77
+ |---|---|
78
+ | Account a post uses | the first connected account |
79
+ | AI drafts per request | 3 |
80
+ | Sync mode and cadence | mirror, every 24 hours |
81
+
82
+ Ask the person: campaign daily budget, dates and destination URL (always typed by them), and who may publish, sync or launch (the proxy's `authorize`).
83
+ `listSyncRuns` is a plain read that the contract grades `billable`; it is used by recipes only, not by a component.
84
+
85
+ ## Recipes
86
+
87
+ | File | Does |
88
+ |---|---|
89
+ | `recipes/schedule-post.ts` | Accounts, AI drafts, create a draft, schedule or publish, wait until live |
90
+ | `recipes/creative-to-gallery.ts` | Specs, create a creative, poll, edit copy, move to the gallery |
91
+ | `recipes/sync-audience-and-launch.ts` | Sync a list, push, launch a campaign, read results by campaign |
92
+
93
+ ## Operations
94
+
95
+ | Operation | Method and path | Tier | Used by |
96
+ |---|---|---|---|
97
+ | cancelSocialPost | POST /social/posts/{post_id}/cancel | destructive | SocialPostList |
98
+ | createAdCreative | POST /ad-creatives | billable | CreativeGallery |
99
+ | createAudienceSync | POST /audience-syncs | external | AudienceSync |
100
+ | createSocialPost | POST /social/posts | write | PostComposer |
101
+ | deleteAdCampaign | DELETE /ad-campaigns/{campaign_id} | destructive | AdCampaignList |
102
+ | deleteAdCreative | DELETE /ad-creatives/{creative_id} | destructive | CreativeGallery |
103
+ | deleteAudienceSync | DELETE /audience-syncs/{config_id} | destructive | AudienceSync |
104
+ | deleteSocialPost | DELETE /social/posts/{post_id} | destructive | SocialPostList |
105
+ | generateSocialPost | POST /social/posts/generate | billable | PostComposer |
106
+ | getAdCreativeSpecs | GET /ad-creatives/specs | read | CreativeGallery |
107
+ | getAdCreativeStatus | GET /ad-creatives/{creative_id}/status | read | recipes |
108
+ | getPerCampaignMetrics | GET /ad-campaigns/metrics | read | AdCampaignList |
109
+ | getSocialPost | GET /social/posts/{post_id} | read | recipes |
110
+ | launchAdCampaign | POST /audience-syncs/{config_id}/launch | external | AudienceSync |
111
+ | listAdCampaigns | GET /ad-campaigns | read | AdCampaignList |
112
+ | listAdCreatives | GET /ad-creatives | read | CreativeGallery |
113
+ | listAudienceSyncs | GET /audience-syncs | read | AudienceSync |
114
+ | listSocialAccounts | GET /social/accounts | read | PostComposer, useSocialAccounts |
115
+ | listSocialPosts | GET /social/posts | read | SocialPostList |
116
+ | listSyncErrors | GET /audience-syncs/{config_id}/errors | read | AudienceSync |
117
+ | listSyncRuns | GET /audience-syncs/{config_id}/runs | billable | recipes |
118
+ | moveAdCreativeToGallery | POST /ad-creatives/{creative_id}/move-to-gallery | write | CreativeGallery |
119
+ | publishSocialPost | POST /social/posts/{post_id}/publish | external | PostComposer, SocialPostList |
120
+ | refreshAllCampaignStatuses | POST /ad-campaigns/status-refresh | external | AdCampaignList |
121
+ | refreshCampaignStatus | POST /ad-campaigns/{campaign_id}/status-refresh | external | AdCampaignList |
122
+ | regenerateAdCreativeImage | POST /ad-creatives/{creative_id}/regenerate-image | billable | CreativeGallery |
123
+ | retryCampaignLaunch | POST /ad-campaigns/{campaign_id}/retry | external | AdCampaignList |
124
+ | scheduleSocialPost | POST /social/posts/{post_id}/schedule | external | PostComposer |
125
+ | triggerAudienceSync | POST /audience-syncs/{config_id}/trigger | external | AudienceSync |
126
+ | updateAdCreative | PATCH /ad-creatives/{creative_id} | write | CreativeGallery |
127
+ | updateAudienceSync | PATCH /audience-syncs/{config_id} | external | AudienceSync |
128
+ | updateSocialPost | PATCH /social/posts/{post_id} | write | PostComposer |