@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,29 @@
1
+ "use client";
2
+
3
+ /**
4
+ * useDispositions: the call outcomes this org accepts (system set plus its own custom ones).
5
+ *
6
+ * SDK operations: GET /voice/dispositions (voice.listVoiceDispositions), read tier.
7
+ *
8
+ * `disposition` on a call is an open string, so always offer the list from here rather than a hard-coded enum.
9
+ */
10
+ import { g8Get } from "@/g8/lib/g8-client";
11
+ import { useG8Query } from "@/g8/hooks/use-g8-query";
12
+ import { dataOf, type DispositionOption } from "../lib/dialer-types";
13
+
14
+ interface DispositionsResponse {
15
+ system?: Array<{ key: string; is_connected: boolean }>;
16
+ custom?: Array<{ key: string; name: string; color?: string; is_connected: boolean }>;
17
+ }
18
+
19
+ const titleCase = (key: string) => key.replace(/_/g, " ").replace(/^./, (c) => c.toUpperCase());
20
+
21
+ export function useDispositions() {
22
+ const q = useG8Query(async (signal) => {
23
+ const data = dataOf<DispositionsResponse>(await g8Get("/voice/dispositions", undefined, { signal }));
24
+ const system = (data.system ?? []).map((d): DispositionOption => ({ key: d.key, label: titleCase(d.key), is_connected: d.is_connected, custom: false }));
25
+ const custom = (data.custom ?? []).map((d): DispositionOption => ({ key: d.key, label: d.name, is_connected: d.is_connected, color: d.color, custom: true }));
26
+ return [...system, ...custom];
27
+ }, []);
28
+ return { ...q, options: q.data ?? [] };
29
+ }
@@ -0,0 +1,158 @@
1
+ "use client";
2
+
3
+ /**
4
+ * Shapes and helpers for the dialer components.
5
+ *
6
+ * The dialer runs in a separate voice service behind the API. Several responses are the voice service's own
7
+ * JSON, so read them through `dataOf()` and treat every field as optional; the types below list what the
8
+ * block relies on, not everything the service sends.
9
+ *
10
+ * There is NO live event stream in the API (no WebSocket or SSE for sessions or transcripts). State is read by
11
+ * polling: `GET /dialer/sessions/{id}/queue-stats` is the cheap 5-second poll the graph8 app itself uses as its
12
+ * fallback, and `GET /dialer/sessions/{id}` carries the live call list.
13
+ */
14
+
15
+ export type DialerMode = "power" | "parallel";
16
+
17
+ /** `batch_status` on queue-stats. */
18
+ export type BatchStatus = "in_flight" | "complete_awaiting_disposition" | "complete_auto_advance_eligible";
19
+
20
+ export interface QueueStats {
21
+ session_id: string;
22
+ /** DRAFT, ACTIVE, PAUSED, COMPLETED (upper or lower case, depending on the route). */
23
+ status: string;
24
+ batch_status?: BatchStatus | null;
25
+ current_batch_id?: string | null;
26
+ queue_remaining: number;
27
+ retry_pending?: number;
28
+ last_terminal_at?: string | null;
29
+ prewarm_ready?: boolean;
30
+ }
31
+
32
+ /** One call in the session's live state. `room_name` equals `call_id` and is what dispositions and transcripts key on. */
33
+ export interface LiveCall {
34
+ call_id: string;
35
+ room_name?: string;
36
+ contact_id: string;
37
+ to_phone?: string;
38
+ /** dialing, ringing, active, hangup, failed (plus busy / no-answer after a terminal webhook). */
39
+ status: string;
40
+ started_at?: string;
41
+ first_name?: string | null;
42
+ last_name?: string | null;
43
+ email?: string | null;
44
+ title?: string | null;
45
+ is_voicemail?: boolean;
46
+ disposition?: string | null;
47
+ }
48
+
49
+ export interface SessionDetail {
50
+ session_id: string;
51
+ status: string;
52
+ name?: string | null;
53
+ from_phone?: string | null;
54
+ dialing_mode?: DialerMode | null;
55
+ parallel_count?: number | null;
56
+ list_id?: string | null;
57
+ list_title?: string | null;
58
+ current_batch_id?: string | null;
59
+ counts?: { total: number; total_dialed: number; total_undialed: number; queue_remaining: number } | null;
60
+ live_state?: { calls?: LiveCall[]; active_calls?: number; completed_calls?: number; voicemail_calls?: number } | null;
61
+ }
62
+
63
+ export interface QueueRow {
64
+ contact_id: string;
65
+ first_name?: string | null;
66
+ last_name?: string | null;
67
+ email?: string | null;
68
+ company?: string | null;
69
+ title?: string | null;
70
+ all_phones?: Array<{ field?: string; phone?: string }>;
71
+ is_next_to_dial?: boolean;
72
+ blocked_reason?: string | null;
73
+ callresult?: { disposition?: string | null } | null;
74
+ }
75
+
76
+ export interface NextBatchResult {
77
+ session_id: string;
78
+ current_batch_id: string;
79
+ conference_name: string;
80
+ twilio_token?: string;
81
+ queue_remaining: number;
82
+ queue_exhausted?: boolean;
83
+ all_dials_failed?: boolean;
84
+ error_message?: string | null;
85
+ batch?: LiveCall[];
86
+ }
87
+
88
+ export interface DispositionOption {
89
+ key: string;
90
+ label: string;
91
+ is_connected: boolean;
92
+ color?: string;
93
+ custom: boolean;
94
+ }
95
+
96
+ export interface CallSummary {
97
+ room_name: string;
98
+ contact_id?: string | null;
99
+ disposition?: string | null;
100
+ call_duration?: number | null;
101
+ created_at?: string | null;
102
+ from_?: string | null;
103
+ to?: string | null;
104
+ has_transcript?: boolean;
105
+ recording_url?: string | null;
106
+ summary?: string | null;
107
+ }
108
+
109
+ export interface TranscriptSegment {
110
+ speaker?: string | null;
111
+ content?: string | null;
112
+ timestamp?: string | null;
113
+ }
114
+
115
+ export interface DialerNumber {
116
+ phone_number?: string;
117
+ number?: string;
118
+ friendly_name?: string | null;
119
+ calls_today?: number;
120
+ daily_limit?: number | null;
121
+ }
122
+
123
+ /** The `data` member of an envelope, or the object itself when the endpoint returns it bare. */
124
+ export function dataOf<T>(env: unknown): T {
125
+ const e = env as { data?: unknown } | null;
126
+ return (e && typeof e === "object" && "data" in e && e.data != null ? e.data : env) as T;
127
+ }
128
+
129
+ export function contactName(c: { first_name?: string | null; last_name?: string | null; email?: string | null; to_phone?: string }): string {
130
+ return [c.first_name, c.last_name].filter(Boolean).join(" ") || c.email || c.to_phone || "Unknown contact";
131
+ }
132
+
133
+ export function normalizeStatus(status: string | null | undefined): string {
134
+ return String(status ?? "").toLowerCase();
135
+ }
136
+
137
+ /** A call that is still ringing or connected (a hang-up makes sense). */
138
+ export function isLiveCall(call: Pick<LiveCall, "status">): boolean {
139
+ return ["dialing", "ringing", "active", "in-progress", "answered"].includes(normalizeStatus(call.status));
140
+ }
141
+
142
+ /** A call that finished and has no outcome recorded yet. */
143
+ export function needsDisposition(call: LiveCall): boolean {
144
+ return ["hangup", "completed"].includes(normalizeStatus(call.status)) && !call.disposition && !call.is_voicemail;
145
+ }
146
+
147
+ export function isSessionOver(status: string | null | undefined): boolean {
148
+ return ["completed", "stopped", "cancelled"].includes(normalizeStatus(status));
149
+ }
150
+
151
+ export function formatDuration(seconds: number | null | undefined): string {
152
+ if (!seconds || seconds < 0) return "0:00";
153
+ return `${Math.floor(seconds / 60)}:${String(Math.floor(seconds % 60)).padStart(2, "0")}`;
154
+ }
155
+
156
+ export function firstPhone(row: QueueRow): string {
157
+ return row.all_phones?.find((p) => p.phone)?.phone ?? "";
158
+ }
@@ -0,0 +1,67 @@
1
+ "use client";
2
+
3
+ /**
4
+ * The seam between the Softphone component and a browser voice client.
5
+ *
6
+ * graph8's dialer places calls from the server (the voice service dials your prospects into a conference);
7
+ * the rep's browser only has to JOIN that conference with audio. The API gives you a short-lived softphone
8
+ * credential (`GET /dialer/sessions/token`) and the conference name (`POST /dialer/sessions/{id}/next-batch`),
9
+ * but it has no live event stream and ships no audio client. So the audio client is yours to choose, behind
10
+ * this interface. `twilio-transport.ts` implements it with `@twilio/voice-sdk` (an optional peer: install it
11
+ * only if you use that adapter). Write your own adapter for another vendor and pass it as `transport`.
12
+ */
13
+
14
+ export interface SoftphoneCredentials {
15
+ token: string;
16
+ /** The identity the credential was minted for. */
17
+ identity?: string;
18
+ }
19
+
20
+ export type SoftphoneEvent =
21
+ | { type: "registered" }
22
+ | { type: "unregistered" }
23
+ | { type: "incoming" }
24
+ | { type: "connected" }
25
+ | { type: "disconnected" }
26
+ | { type: "muted"; muted: boolean }
27
+ | { type: "token-expiring" }
28
+ | { type: "error"; message: string };
29
+
30
+ export interface SoftphoneTransport {
31
+ /** Create the client and register it with the credential. Resolves once the rep can receive audio. */
32
+ connect(credentials: SoftphoneCredentials): Promise<void>;
33
+ /** Join a dialer conference (the `conference_name` from next-batch). Optional: a transport may auto-answer instead. */
34
+ joinConference?(conferenceName: string, options?: { callId?: string; muted?: boolean }): Promise<void>;
35
+ /** Answer an incoming leg. */
36
+ accept?(): void;
37
+ mute(muted: boolean): void;
38
+ /** Leave the current call but keep the client registered. */
39
+ hangup(): void;
40
+ /** Tear everything down. */
41
+ disconnect(): Promise<void> | void;
42
+ /** Swap in a fresh credential before the old one expires. */
43
+ updateToken?(token: string): void;
44
+ /** Listen to client events. Returns an unsubscribe function. */
45
+ subscribe(listener: (event: SoftphoneEvent) => void): () => void;
46
+ }
47
+
48
+ /** A transport that does nothing; useful for a read-only preview and in tests. */
49
+ export function createNoopTransport(): SoftphoneTransport {
50
+ const listeners = new Set<(event: SoftphoneEvent) => void>();
51
+ const emit = (event: SoftphoneEvent) => listeners.forEach((l) => l(event));
52
+ return {
53
+ async connect() {
54
+ emit({ type: "registered" });
55
+ },
56
+ async joinConference() {
57
+ emit({ type: "connected" });
58
+ },
59
+ mute: (muted) => emit({ type: "muted", muted }),
60
+ hangup: () => emit({ type: "disconnected" }),
61
+ disconnect: () => emit({ type: "unregistered" }),
62
+ subscribe(listener) {
63
+ listeners.add(listener);
64
+ return () => listeners.delete(listener);
65
+ },
66
+ };
67
+ }
@@ -0,0 +1,74 @@
1
+ "use client";
2
+
3
+ /**
4
+ * Twilio adapter for the Softphone: implements SoftphoneTransport with `@twilio/voice-sdk`.
5
+ *
6
+ * Needs the optional peer `npm i @twilio/voice-sdk`. graph8's dialer runs on Twilio conferences: the voice
7
+ * service dials prospects into a conference and the rep's browser joins it through `device.connect` with the
8
+ * parameters below. The Device is created once and reused for every batch.
9
+ *
10
+ * Usage: `<Softphone transport={createTwilioTransport()} ... />` (create it once, outside render, or in useMemo).
11
+ */
12
+ import { Call, Device } from "@twilio/voice-sdk";
13
+ import type { SoftphoneCredentials, SoftphoneEvent, SoftphoneTransport } from "./softphone-transport";
14
+
15
+ export function createTwilioTransport(): SoftphoneTransport {
16
+ let device: Device | null = null;
17
+ let call: Call | null = null;
18
+ const listeners = new Set<(event: SoftphoneEvent) => void>();
19
+ const emit = (event: SoftphoneEvent) => listeners.forEach((l) => l(event));
20
+
21
+ const watch = (c: Call) => {
22
+ call = c;
23
+ c.on("accept", () => emit({ type: "connected" }));
24
+ c.on("disconnect", () => {
25
+ call = null;
26
+ emit({ type: "disconnected" });
27
+ });
28
+ c.on("cancel", () => {
29
+ call = null;
30
+ emit({ type: "disconnected" });
31
+ });
32
+ c.on("mute", (muted: boolean) => emit({ type: "muted", muted }));
33
+ c.on("error", (e: { message?: string }) => emit({ type: "error", message: e?.message ?? "Call error" }));
34
+ };
35
+
36
+ return {
37
+ async connect({ token }: SoftphoneCredentials) {
38
+ await device?.destroy();
39
+ const next = new Device(token, { codecPreferences: [Call.Codec.Opus, Call.Codec.PCMU] });
40
+ device = next;
41
+ next.on("registered", () => emit({ type: "registered" }));
42
+ next.on("unregistered", () => emit({ type: "unregistered" }));
43
+ next.on("tokenWillExpire", () => emit({ type: "token-expiring" }));
44
+ next.on("error", (e: { message?: string }) => emit({ type: "error", message: e?.message ?? "Device error" }));
45
+ next.on("incoming", (incoming: Call) => {
46
+ emit({ type: "incoming" });
47
+ watch(incoming);
48
+ incoming.accept();
49
+ });
50
+ await next.register();
51
+ },
52
+ async joinConference(conferenceName, options) {
53
+ if (!device) throw new Error("Softphone is not connected");
54
+ const joined = await device.connect({
55
+ params: { conference_name: conferenceName, call_id: options?.callId ?? "", muted: options?.muted ? "true" : "false" },
56
+ });
57
+ watch(joined);
58
+ },
59
+ accept: () => call?.accept(),
60
+ mute: (muted) => call?.mute(muted),
61
+ hangup: () => call?.disconnect(),
62
+ async disconnect() {
63
+ call?.disconnect();
64
+ await device?.destroy();
65
+ device = null;
66
+ call = null;
67
+ },
68
+ updateToken: (token) => device?.updateToken(token),
69
+ subscribe(listener) {
70
+ listeners.add(listener);
71
+ return () => listeners.delete(listener);
72
+ },
73
+ };
74
+ }
@@ -0,0 +1,39 @@
1
+ /**
2
+ * @title Create a dialing session, dial one batch, and poll it
3
+ * @when An agent running a calling block for a rep. Creating the DRAFT is safe (dials nobody). `next-batch` CALLS
4
+ * REAL PEOPLE and reserves credits: have a human approve before step 2. The API has no event stream, so progress
5
+ * is read by polling queue-stats (every 5 seconds is what the graph8 app does).
6
+ */
7
+ import { g8 } from "@graph8/sdk";
8
+
9
+ g8.init({ apiKey: process.env.G8_API_KEY! });
10
+
11
+ const listId = process.argv[2];
12
+ const repUserId = process.argv[3]; // an organisation key has no user of its own: name the rep these calls belong to
13
+ if (!listId || !repUserId) throw new Error("usage: tsx 01-create-session-and-dial.ts <list id> <rep user id>");
14
+
15
+ // 1. WRITE, dials nobody. Voice reuses a live session for the same list rather than making a second one.
16
+ const draft = (await g8.api.dialer.createSessionDraft({
17
+ body: { user_id: repUserId, list_id: listId, dialing_mode: "power", parallel_count: 1, name: "Outbound calls" },
18
+ })) as { data?: { session_id?: string } };
19
+ const sessionId = draft.data?.session_id;
20
+ if (!sessionId) throw new Error("graph8 returned no session id");
21
+
22
+ // 2. EXTERNAL: dials the next contact(s). `previous_batch_id` is null for the first batch, then the
23
+ // `current_batch_id` from queue-stats (it makes a retried request idempotent).
24
+ const batch = (await g8.api.dialer.dialNextBatch({
25
+ path: { session_id: sessionId },
26
+ body: { previous_batch_id: null, dialing_mode: "power", parallel_count: 1 },
27
+ })) as { data?: { conference_name?: string; queue_remaining?: number; all_dials_failed?: boolean; error_message?: string } };
28
+ if (batch.data?.all_dials_failed) throw new Error(batch.data.error_message ?? "Every call failed; the session was paused");
29
+ console.log("conference", batch.data?.conference_name, "left in queue", batch.data?.queue_remaining);
30
+
31
+ // 3. Poll until the batch finishes. batch_status: in_flight | complete_awaiting_disposition | complete_auto_advance_eligible.
32
+ for (let i = 0; i < 60; i++) {
33
+ const stats = (await g8.api.dialer.readQueueStats({ path: { session_id: sessionId } })) as {
34
+ data?: { status?: string; batch_status?: string | null };
35
+ };
36
+ console.log(stats.data?.status, stats.data?.batch_status);
37
+ if (stats.data?.batch_status !== "in_flight") break;
38
+ await new Promise((r) => setTimeout(r, 5000));
39
+ }
@@ -0,0 +1,26 @@
1
+ /**
2
+ * @title Record outcomes for a session's finished calls
3
+ * @when After a batch completes (batch_status "complete_awaiting_disposition"). Dispositions are an open string:
4
+ * read the org's accepted list first (system set plus custom). Tier `write`: it contacts nobody.
5
+ */
6
+ import { g8 } from "@graph8/sdk";
7
+
8
+ g8.init({ apiKey: process.env.G8_API_KEY! });
9
+
10
+ const sessionId = process.argv[2];
11
+ if (!sessionId) throw new Error("usage: tsx 02-disposition-calls.ts <session id>");
12
+
13
+ const accepted = await g8.api.voice.listVoiceDispositions();
14
+ const keys = new Set([...(accepted.data.system ?? []), ...(accepted.data.custom ?? [])].map((d) => d.key));
15
+ console.log("accepted dispositions:", [...keys].join(", "));
16
+
17
+ const calls = await g8.api.voice.listCallsForContact({ query: { parallel_session_id: sessionId, limit: 100 } });
18
+ for (const call of calls.data.calls ?? []) {
19
+ if (call.disposition) continue;
20
+ // Decide from the facts you have; here a very short call is treated as no answer. Never invent an outcome for a
21
+ // call you cannot judge: leave it for the rep.
22
+ const guess = (call.call_duration ?? 0) < 8 && keys.has("no_answer") ? "no_answer" : null;
23
+ if (!guess) continue;
24
+ await g8.api.dialer.setCallDisposition({ path: { livekit_room_name: call.room_name }, body: { disposition: guess } });
25
+ console.log(call.room_name, "->", guess);
26
+ }
@@ -0,0 +1,23 @@
1
+ /**
2
+ * @title Pull a call's transcript, AI grade, and the rep's recent performance
3
+ * @when Coaching or QA. All read-only. `room_name` is the call id. Grading returns "pending" until computed and
4
+ * the transcript has status "empty" until it is flushed; retry later instead of treating either as an error.
5
+ */
6
+ import { g8 } from "@graph8/sdk";
7
+
8
+ g8.init({ apiKey: process.env.G8_API_KEY! });
9
+
10
+ const roomName = process.argv[2];
11
+ const repEmail = process.argv[3];
12
+ if (!roomName) throw new Error("usage: tsx 03-review-a-call.ts <room name> [rep email]");
13
+
14
+ const transcript = await g8.api.voice.getCallTranscript({ path: { room_name: roomName } });
15
+ console.log(transcript.data.status, transcript.data.summary);
16
+ for (const s of transcript.data.transcript ?? []) console.log(`${s.speaker}: ${s.content}`);
17
+
18
+ const grading = await g8.api.voice.getCallGrading({ path: { room_name: roomName } });
19
+ console.log("grading", JSON.stringify(grading.data));
20
+
21
+ // Team or personal numbers for the period (defaults to today); a manager passes sdr_email.
22
+ const performance = await g8.api.dialerAnalytics.getDialerPerformance({ query: repEmail ? { sdr_email: repEmail } : {} });
23
+ console.log("performance", JSON.stringify(performance.data));
@@ -0,0 +1,105 @@
1
+ # enrichment
2
+
3
+ Fill in what you do not know about your contacts: look up one person or company, verify an email, enrich many
4
+ contacts of a list in one job, and manage the provider pipelines behind it. Builds on `crm`.
5
+
6
+ Install: `npx @graph8/sdk add enrichment` (installs `foundation`, `crm` and `lists` first).
7
+
8
+ ## What you get
9
+
10
+ | Component | Use it for | Props |
11
+ |---|---|---|
12
+ | `EnrichButton` | Look up one person/company; optionally apply the found fields to the record | `kind`, `lookup`, `record`, `onResult`, `onApplied` |
13
+ | `EmailVerifyBadge` | Status chip (Unverified / Valid / Risky / Invalid) with a Verify action | `email`, `initialStatus`, `onVerified`, `readOnly` |
14
+ | `BulkEnrichPanel` | Fill work email / phones for many contacts of a list: preflight, estimate, job, progress | `listId`, `contactIds`, `defaultProviders`, `onDone` |
15
+ | `WaterfallConfig` | Saved pipelines of a list and a form to create one | `listId`, `onChanged` |
16
+
17
+ `BulkEnrichPanel` with no props is a complete page (choose a list, tick contacts, enrich), so it can be mounted as a
18
+ route as is; give it `listId` and `contactIds` to embed it. For that reason this block depends on `lists`.
19
+
20
+ Hook `useProviders()`; helpers in `lib/enrichment-types.ts` (`estimateCredits`, `isJobTerminal`, the price constants).
21
+
22
+ ## Cost, in plain numbers (all billable steps are confirmed)
23
+
24
+ | Action | Cost | Confirmed with |
25
+ |---|---|---|
26
+ | Person or company lookup | 2 credits, **only if a match is found** (a miss is free) | `ConfirmSpendDialog` (billable) showing 2 credits |
27
+ | Email verification | 1 credit | `ConfirmSpendDialog` (billable) |
28
+ | Bulk enrichment | quoted by the preflight (`max_total_credits`, the most it can charge); flat 2 credits per record when the preflight cannot price it. Providers on your own key cost 0 | `ConfirmSpendDialog` (billable) with that estimate |
29
+ | Create a waterfall pipeline | creating does not run it; running spends per the providers used | `ConfirmSpendDialog` |
30
+
31
+ There is **no balance read** in the API. Every number shown is an estimate of what a run can cost, never a check that
32
+ you can afford it; an under-funded run fails with 402.
33
+
34
+ ## The flow, with the ids that pass between steps
35
+
36
+ 1. Contacts must be on a list: `list_id` (from the `lists` block) and `contact_ids` (from a `ContactTable` selection).
37
+ Masked search results have no ids and cannot be enriched: save them to a list first (`search` block).
38
+ 2. `POST /enrichment/preflight { list_id, contact_ids, mode: "waterfall", providers, target_field }` (free) ->
39
+ `contact_count`, `not_in_list`, `missing_credentials`, `warnings`, `credits_per_record`, `max_total_credits`.
40
+ 3. The person confirms the estimate. `POST /enrichment/enrich { contact_ids, list_id, fields_config: { work_email: [providers] } }`
41
+ -> 202 `{ job_id }`.
42
+ 4. Poll `GET /enrichment/jobs/{job_id}` (`useJobPoll`, backoff; there is no stream and no completion webhook) until
43
+ `status` is `completed`, `failed` or `cancelled`. It reports `completed/total`, `successful_enrichments`, `failed_enrichments`,
44
+ `total_credits_used`. If nothing was enriched, `?include_provider_errors=true` explains why (usually a missing provider key).
45
+ 5. `POST /enrichment/jobs/{job_id}/cancel` stops a running job; records already done keep their data and charge.
46
+
47
+ ```tsx
48
+ "use client";
49
+ import { BulkEnrichPanel } from "@/components/g8/enrichment/bulk-enrich-panel";
50
+ import { ContactTable } from "@/components/g8/crm/contact-table";
51
+
52
+ export function EnrichList({ listId }: { listId: number }) {
53
+ return (
54
+ <ContactTable listId={listId} selectable
55
+ renderBulkActions={({ ids }) => <span className="w-[28rem]"><BulkEnrichPanel listId={listId} contactIds={ids} /></span>} />
56
+ );
57
+ }
58
+ ```
59
+
60
+ (`add` flattens `components/` into `components/g8/enrichment/`; adjust the alias to your app.)
61
+
62
+ Single record: `<EnrichButton kind="person" lookup={{ email: contact.work_email }} record={contact} />` inside
63
+ `ContactDetail renderActions`. A locked (`"***"`) email is never sent to the API.
64
+
65
+ ## Prerequisites (a human must do these)
66
+
67
+ - `provider-keys` (api): providers that graph8 does not fund need the workspace's own key, saved in graph8 settings
68
+ (no API for it). The preflight reports `missing_credentials`; those steps are skipped.
69
+ - `credits` (api): the workspace needs credits for graph8-funded providers.
70
+ - `proxy-allowlist` (app): `allowedPrefixes` includes `enrichment` (and `contacts`, `companies` for Apply).
71
+ - `crm-installed` (app).
72
+
73
+ ## Defaults the agent can use without asking
74
+
75
+ | Decision | Default |
76
+ |---|---|
77
+ | Providers a bulk run tries | `prospeo`, `dropcontact` (the API default), kept to those in the catalog |
78
+ | Field to fill | work email |
79
+ | Apply a lookup to the record | never automatically; the person ticks fields |
80
+
81
+ Ask the person: who may spend credits (decide it in the proxy's `authorize`).
82
+
83
+ ## Recipes
84
+
85
+ | File | Does |
86
+ |---|---|
87
+ | `recipes/lookup-and-verify.ts` | One person/company lookup and an email check |
88
+ | `recipes/bulk-enrich-and-poll.ts` | Preflight quote, start, poll with backoff, read provider errors |
89
+ | `recipes/waterfall-pipeline.ts` | Provider readiness, create and list pipelines |
90
+
91
+ ## Operations
92
+
93
+ | Operation | Method and path | Tier | Used by |
94
+ |---|---|---|---|
95
+ | lookupPerson / lookupCompany | POST /enrichment/lookup/person, /company | billable | EnrichButton |
96
+ | verifyEmail | POST /enrichment/verify-email | billable | EmailVerifyBadge |
97
+ | preflightEnrichment | POST /enrichment/preflight | read | BulkEnrichPanel |
98
+ | startEnrichment | POST /enrichment/enrich | billable | BulkEnrichPanel |
99
+ | getEnrichmentJob | GET /enrichment/jobs/{job_id} | read | BulkEnrichPanel |
100
+ | cancelEnrichmentJob | POST /enrichment/jobs/{job_id}/cancel | write | BulkEnrichPanel |
101
+ | listEnrichmentProviders | GET /enrichment/providers | read | BulkEnrichPanel, WaterfallConfig |
102
+ | listWaterfallConfigs | GET /enrichment/waterfall/configs | read | WaterfallConfig |
103
+ | createDefaultWaterfallConfig | POST /enrichment/waterfall/configs | billable | WaterfallConfig |
104
+ | deleteWaterfallConfig | DELETE /enrichment/waterfall/configs/{column_id} | destructive | WaterfallConfig |
105
+ | updateContact / updateCompany | PATCH /contacts/{id}, /companies/{id} | write | EnrichButton (Apply) |