@graph8/sdk 0.308.1 → 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 (654) 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 +1440 -21
  390. package/dist/index.d.ts +1440 -21
  391. package/dist/index.js +42 -3
  392. package/dist/index.js.map +1 -1
  393. package/dist/index.mjs +42 -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 +1340 -18
  400. package/dist/react.d.ts +1340 -18
  401. package/dist/react.js +41 -2
  402. package/dist/react.js.map +1 -1
  403. package/dist/react.mjs +41 -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 +6 -3
  611. package/docs/api/appObjects.d.ts +1 -1
  612. package/docs/api/appObjects.md +1 -1
  613. package/docs/api/by-path.md +29 -0
  614. package/docs/api/objects.d.ts +72 -5
  615. package/docs/api/objects.md +84 -7
  616. package/docs/api/processLists.d.ts +247 -0
  617. package/docs/api/processLists.md +409 -0
  618. package/docs/api/reports.d.ts +476 -0
  619. package/docs/api/reports.md +539 -0
  620. package/docs/api/scheduleBuy.d.ts +12 -8
  621. package/docs/api/scheduleBuy.md +13 -10
  622. package/docs/api/seo.d.ts +406 -3
  623. package/docs/api/seo.md +505 -1
  624. package/docs/api/workspaceBackup.d.ts +324 -0
  625. package/docs/api/workspaceBackup.md +427 -0
  626. package/package.json +174 -5
  627. package/stacks/6sense.json +46 -0
  628. package/stacks/README.md +20 -0
  629. package/stacks/apollo.json +128 -0
  630. package/stacks/clay.json +59 -0
  631. package/stacks/gong.json +72 -0
  632. package/stacks/hubspot.json +162 -0
  633. package/stacks/intercom.json +53 -0
  634. package/stacks/mailchimp.json +71 -0
  635. package/stacks/outreach.json +86 -0
  636. package/stacks/salesforce.json +94 -0
  637. package/stacks/stack.schema.json +32 -0
  638. package/stacks/starter.json +22 -0
  639. package/styles/styles.css +2 -0
  640. package/styles/theme.css +181 -0
  641. package/styles/tokens.css +284 -0
  642. package/templates/next-app/README.md.tmpl +35 -0
  643. package/templates/next-app/_pages/redirect-page.tsx.tmpl +5 -0
  644. package/templates/next-app/_pages/route-page.tsx.tmpl +9 -0
  645. package/templates/next-app/app/globals.css.tmpl +8 -0
  646. package/templates/next-app/app/layout.tsx.tmpl +19 -0
  647. package/templates/next-app/components/app-shell.tsx.tmpl +34 -0
  648. package/templates/next-app/dot-env.local.example.tmpl +6 -0
  649. package/templates/next-app/dot-gitignore.tmpl +7 -0
  650. package/templates/next-app/lib/nav.ts.tmpl +2 -0
  651. package/templates/next-app/next.config.mjs.tmpl +4 -0
  652. package/templates/next-app/package.json.tmpl +25 -0
  653. package/templates/next-app/postcss.config.mjs.tmpl +4 -0
  654. package/templates/next-app/tsconfig.json.tmpl +21 -0
@@ -0,0 +1,194 @@
1
+ {
2
+ "$schema": "../block.schema.json",
3
+ "id": "inbox",
4
+ "title": "AI inbox",
5
+ "summary": "Unified reply inbox for email, SMS and LinkedIn: thread list, conversation view, AI-drafted replies, tagging and assignment.",
6
+ "features": [
7
+ "one queue across email, SMS and LinkedIn with channel and status filters",
8
+ "conversation view with unsent drafts flagged",
9
+ "AI draft (confirmed, billable) and send (confirmed, external) in one composer",
10
+ "tag and assign teammates",
11
+ "drop-in two-pane InboxScreen"
12
+ ],
13
+ "dependsOn": [
14
+ "crm",
15
+ "mailboxes"
16
+ ],
17
+ "operations": [
18
+ "assign_reply_inbox__reply_id__assign_post",
19
+ "create_inbox_tag_inbox_tags_post",
20
+ "generate_inbox_draft_inbox_drafts_generate_post",
21
+ "get_reply_inbox__reply_id__get",
22
+ "list_inbox_inbox_get",
23
+ "list_inbox_users_inbox_users_get",
24
+ "send_reply_inbox__reply_id__send_post",
25
+ "tag_reply_inbox__reply_id__tag_post"
26
+ ],
27
+ "components": [
28
+ {
29
+ "name": "InboxList",
30
+ "file": "components/inbox-list.tsx",
31
+ "purpose": "Paged table of conversations across email, SMS and LinkedIn with channel and status filters.",
32
+ "operations": [
33
+ "list_inbox_inbox_get"
34
+ ],
35
+ "tiers": [
36
+ "read"
37
+ ]
38
+ },
39
+ {
40
+ "name": "ThreadView",
41
+ "file": "components/thread-view.tsx",
42
+ "purpose": "One conversation with contact, tags, assignees and unsent drafts; renders your controls under the messages.",
43
+ "operations": [
44
+ "get_reply_inbox__reply_id__get"
45
+ ],
46
+ "tiers": [
47
+ "read"
48
+ ]
49
+ },
50
+ {
51
+ "name": "ReplyComposer",
52
+ "file": "components/reply-composer.tsx",
53
+ "purpose": "Write a reply, draft or reshape it with AI (confirm, billable) and send it on the thread's channel (confirm, external).",
54
+ "operations": [
55
+ "generate_inbox_draft_inbox_drafts_generate_post",
56
+ "send_reply_inbox__reply_id__send_post"
57
+ ],
58
+ "tiers": [
59
+ "billable",
60
+ "external"
61
+ ]
62
+ },
63
+ {
64
+ "name": "TagAndAssign",
65
+ "file": "components/tag-and-assign.tsx",
66
+ "purpose": "Create and apply tags and assign a teammate, each behind a confirm dialog.",
67
+ "operations": [
68
+ "assign_reply_inbox__reply_id__assign_post",
69
+ "create_inbox_tag_inbox_tags_post",
70
+ "list_inbox_users_inbox_users_get",
71
+ "tag_reply_inbox__reply_id__tag_post"
72
+ ],
73
+ "tiers": [
74
+ "read",
75
+ "write",
76
+ "external"
77
+ ]
78
+ },
79
+ {
80
+ "name": "InboxScreen",
81
+ "file": "components/inbox-screen.tsx",
82
+ "purpose": "Finished two-pane inbox composing the list, thread view, composer and tag/assign panel.",
83
+ "operations": [],
84
+ "tiers": []
85
+ },
86
+ {
87
+ "name": "ThreadBadge",
88
+ "file": "components/thread-badge.tsx",
89
+ "purpose": "Small status pill shared by the thread view and tag panel.",
90
+ "operations": [],
91
+ "tiers": []
92
+ }
93
+ ],
94
+ "hooks": [
95
+ {
96
+ "name": "useInboxThreads",
97
+ "file": "hooks/use-inbox-threads.ts",
98
+ "purpose": "One page of the unified inbox, refetched when a filter or the page changes.",
99
+ "operations": [
100
+ "list_inbox_inbox_get"
101
+ ]
102
+ },
103
+ {
104
+ "name": "useInboxThread",
105
+ "file": "hooks/use-inbox-thread.ts",
106
+ "purpose": "One conversation with its messages, drafts included.",
107
+ "operations": [
108
+ "get_reply_inbox__reply_id__get"
109
+ ]
110
+ }
111
+ ],
112
+ "lib": [
113
+ {
114
+ "file": "lib/inbox-types.ts",
115
+ "purpose": "Thread, message, tag and assignee types plus HTML-to-text, label and date helpers."
116
+ },
117
+ {
118
+ "file": "lib/idempotency.ts",
119
+ "purpose": "useIdempotencyKey: one Idempotency-Key per distinct payload, rotated when the body changes so an edited retry never hits a 409."
120
+ }
121
+ ],
122
+ "recipes": [
123
+ {
124
+ "file": "recipes/01-triage-and-reply.ts",
125
+ "title": "Triage the inbox and answer a reply",
126
+ "when": "A job or agent that reads new replies, drafts with AI (billable) and sends (external) after a human approves."
127
+ },
128
+ {
129
+ "file": "recipes/02-tag-and-assign.ts",
130
+ "title": "Tag a conversation and assign it",
131
+ "when": "Routing replies to the right teammate with a tag; both calls are external and need approval."
132
+ },
133
+ {
134
+ "file": "recipes/03-hot-contacts-digest.ts",
135
+ "title": "Digest of engaging contacts and unowned threads",
136
+ "when": "A read-only morning summary of who to answer first."
137
+ }
138
+ ],
139
+ "prerequisites": [
140
+ {
141
+ "id": "connected-mailbox",
142
+ "description": "At least one connected sending mailbox (Google or Microsoft OAuth) so email threads exist and email replies can be sent. The OAuth connect flow is only in the graph8 app.",
143
+ "where": "app",
144
+ "verify": "Open app.graph8.com, Settings, Mailboxes: the mailbox shows Connected. Then GET /inbox returns email threads."
145
+ },
146
+ {
147
+ "id": "inbox-scopes",
148
+ "description": "The proxy's API key needs inbox:read and inbox:write for the screens, inbox:run for AI drafts and sending.",
149
+ "where": "api",
150
+ "verify": "`g8.api.me.describeCurrentKey()` lists inbox:read, inbox:write and inbox:run."
151
+ },
152
+ {
153
+ "id": "credits",
154
+ "description": "AI drafts charge credits (HTTP 402 when the org has none). There is no balance read, so the dialog shows no estimate.",
155
+ "where": "api",
156
+ "verify": "POST /inbox/drafts/generate returns 200, not 402."
157
+ }
158
+ ],
159
+ "scopes": [
160
+ "inbox:read",
161
+ "inbox:run",
162
+ "inbox:write"
163
+ ],
164
+ "defaults": [
165
+ {
166
+ "decision": "Which AI operation the Draft button uses",
167
+ "default": "generate_from_scratch grounded in the thread; shorten, expand and fix grammar act on the text in the box",
168
+ "askHuman": false
169
+ },
170
+ {
171
+ "decision": "Whether the person sees every AI draft before it is sent",
172
+ "default": "Always: a draft is only written into the reply box; sending is a separate confirmed click",
173
+ "askHuman": false
174
+ },
175
+ {
176
+ "decision": "Default tone and goal of AI drafts",
177
+ "default": "professional / follow_up",
178
+ "askHuman": false
179
+ },
180
+ {
181
+ "decision": "Where to get the list of tags the picker offers (no list-tags operation exists)",
182
+ "default": "Pass availableTags from your own state; tags created in the panel are added for the session",
183
+ "askHuman": true
184
+ },
185
+ {
186
+ "decision": "Filter by assignee",
187
+ "default": "Not offered: the API cannot filter by an arbitrary assignee email (an org key owns no threads). Filter thread.assignees client-side",
188
+ "askHuman": false
189
+ }
190
+ ],
191
+ "peerDependencies": {
192
+ "react": ">=18"
193
+ }
194
+ }
@@ -0,0 +1,156 @@
1
+ "use client";
2
+
3
+ /**
4
+ * InboxList: the unified reply queue (email, SMS and LinkedIn) with channel and status filters and paging.
5
+ *
6
+ * SDK operations, in order:
7
+ * 1. GET /inbox?channel=&status=&tag=&page=&page_size= (inbox.listInbox) read
8
+ * Nothing here sends, spends or deletes, so there is no ConfirmSpendDialog.
9
+ *
10
+ * Wire it to a detail pane with `onSelect`; the row gives you `thread.id` and `thread.channel`, which are
11
+ * the two things ThreadView needs.
12
+ */
13
+ import { useState } from "react";
14
+ import { Button, Skeleton, Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@graph8/sdk/ui";
15
+ import { ApiError } from "@/g8/components/api-error";
16
+ import { EmptyState } from "@/g8/components/empty-state";
17
+ import { useInboxThreads, type InboxFilters } from "../hooks/use-inbox-threads";
18
+ import {
19
+ INBOX_CHANNELS,
20
+ INBOX_STATUSES,
21
+ contactLabel,
22
+ formatWhen,
23
+ latestMessage,
24
+ previewText,
25
+ type InboxChannel,
26
+ type InboxThread,
27
+ } from "../lib/inbox-types";
28
+
29
+ export interface InboxListProps {
30
+ onSelect?: (thread: InboxThread) => void;
31
+ selectedId?: string | null;
32
+ /** Start with these filters (for example a tag id from the URL). */
33
+ initialFilters?: InboxFilters;
34
+ pageSize?: number;
35
+ /** Fires when a filter changes. The selection no longer matches the list, so clear it (InboxScreen does). */
36
+ onFiltersChange?: (filters: InboxFilters) => void;
37
+ className?: string;
38
+ }
39
+
40
+ function ChannelFilter({ value, onChange }: { value?: InboxChannel; onChange: (next?: InboxChannel) => void }) {
41
+ return (
42
+ <div role="group" aria-label="Channel" className="flex gap-1">
43
+ <Button size="sm" variant={value ? "outline" : "default"} onClick={() => onChange(undefined)}>
44
+ All
45
+ </Button>
46
+ {INBOX_CHANNELS.map((c) => (
47
+ <Button key={c.value} size="sm" variant={value === c.value ? "default" : "outline"} onClick={() => onChange(c.value)}>
48
+ {c.label}
49
+ </Button>
50
+ ))}
51
+ </div>
52
+ );
53
+ }
54
+
55
+ function LoadingRows() {
56
+ return (
57
+ <div className="space-y-2 p-3" aria-busy="true" aria-label="Loading threads">
58
+ {Array.from({ length: 6 }, (_, i) => (
59
+ <Skeleton key={i} className="h-10 w-full" />
60
+ ))}
61
+ </div>
62
+ );
63
+ }
64
+
65
+ export function InboxList({ onSelect, selectedId, initialFilters, pageSize = 25, onFiltersChange, className }: InboxListProps) {
66
+ const [filters, setFilters] = useState<InboxFilters>(initialFilters ?? {});
67
+ const [page, setPage] = useState(1);
68
+ const { threads, loading, error, hasNext, total, refetch } = useInboxThreads(filters, page, pageSize);
69
+
70
+ const update = (patch: Partial<InboxFilters>) => {
71
+ const next = { ...filters, ...patch };
72
+ setFilters(next);
73
+ setPage(1);
74
+ onFiltersChange?.(next);
75
+ };
76
+
77
+ return (
78
+ <div className={`flex flex-col gap-3 ${className ?? ""}`}>
79
+ <div className="flex flex-wrap items-center justify-between gap-2">
80
+ <ChannelFilter value={filters.channel} onChange={(channel) => update({ channel })} />
81
+ <div className="flex items-center gap-2">
82
+ <select
83
+ aria-label="Status"
84
+ className="h-8 rounded-md border bg-background px-2 text-sm"
85
+ value={filters.status ?? ""}
86
+ onChange={(e) => update({ status: e.target.value || undefined })}
87
+ >
88
+ <option value="">Any status</option>
89
+ {INBOX_STATUSES.map((s) => (
90
+ <option key={s} value={s}>
91
+ {s.replace("_", " ").toLowerCase()}
92
+ </option>
93
+ ))}
94
+ </select>
95
+ <Button size="sm" variant="ghost" onClick={() => void refetch()}>
96
+ Refresh
97
+ </Button>
98
+ </div>
99
+ </div>
100
+
101
+ {error ? (
102
+ <ApiError error={error} title="Could not load the inbox" onRetry={() => void refetch()} />
103
+ ) : loading && threads.length === 0 ? (
104
+ <LoadingRows />
105
+ ) : threads.length === 0 ? (
106
+ <EmptyState
107
+ title="No conversations match"
108
+ description="Replies from sequences, SMS and LinkedIn land here. Clear the filters, or enroll contacts in a sequence to get replies."
109
+ />
110
+ ) : (
111
+ <Table>
112
+ <TableHeader>
113
+ <TableRow>
114
+ <TableHead>Contact</TableHead>
115
+ <TableHead>Latest message</TableHead>
116
+ <TableHead>Channel</TableHead>
117
+ <TableHead>Updated</TableHead>
118
+ </TableRow>
119
+ </TableHeader>
120
+ <TableBody>
121
+ {threads.map((thread) => (
122
+ <TableRow
123
+ key={`${thread.channel}:${thread.id}`}
124
+ data-state={selectedId === thread.id ? "selected" : undefined}
125
+ className="cursor-pointer"
126
+ onClick={() => onSelect?.(thread)}
127
+ >
128
+ <TableCell className="max-w-48 truncate font-medium">{contactLabel(thread)}</TableCell>
129
+ <TableCell className="max-w-80 truncate text-muted-foreground">
130
+ {thread.subject ? <span className="text-foreground">{thread.subject} </span> : null}
131
+ {previewText(thread)}
132
+ </TableCell>
133
+ <TableCell className="capitalize">{thread.channel}</TableCell>
134
+ <TableCell className="whitespace-nowrap text-muted-foreground">
135
+ {formatWhen(thread.updated_at ?? latestMessage(thread)?.date)}
136
+ </TableCell>
137
+ </TableRow>
138
+ ))}
139
+ </TableBody>
140
+ </Table>
141
+ )}
142
+
143
+ <div className="flex items-center justify-between text-sm text-muted-foreground">
144
+ <span>{total != null ? `${total.toLocaleString()} conversations` : `Page ${page}`}</span>
145
+ <div className="flex gap-2">
146
+ <Button size="sm" variant="outline" disabled={page <= 1 || loading} onClick={() => setPage((p) => p - 1)}>
147
+ Previous
148
+ </Button>
149
+ <Button size="sm" variant="outline" disabled={!hasNext || loading} onClick={() => setPage((p) => p + 1)}>
150
+ Next
151
+ </Button>
152
+ </div>
153
+ </div>
154
+ </div>
155
+ );
156
+ }
@@ -0,0 +1,49 @@
1
+ "use client";
2
+
3
+ /**
4
+ * InboxScreen: the finished two-pane inbox. List on the left; on the right the open conversation with its
5
+ * reply composer and tag/assign panel. Copy it as the page, or take the four parts it composes.
6
+ *
7
+ * SDK operations: none of its own. It composes InboxList (read), ThreadView (read), ReplyComposer
8
+ * (billable draft, external send) and TagAndAssign (external). The dialogs live in those parts.
9
+ */
10
+ import { useMemo, useState } from "react";
11
+ import { EmptyState } from "@/g8/components/empty-state";
12
+ import type { InboxFilters } from "../hooks/use-inbox-threads";
13
+ import type { InboxTag, InboxThread } from "../lib/inbox-types";
14
+ import { InboxList } from "./inbox-list";
15
+ import { ReplyComposer } from "./reply-composer";
16
+ import { TagAndAssign } from "./tag-and-assign";
17
+ import { ThreadView } from "./thread-view";
18
+
19
+ export interface InboxScreenProps {
20
+ initialFilters?: InboxFilters;
21
+ /** Tags the person can apply. There is no list-tags operation; keep this list in your app. */
22
+ availableTags?: InboxTag[];
23
+ className?: string;
24
+ }
25
+
26
+ export function InboxScreen({ initialFilters, availableTags, className }: InboxScreenProps) {
27
+ const [open, setOpen] = useState<InboxThread | null>(null);
28
+ const tags = useMemo(() => availableTags ?? [], [availableTags]);
29
+
30
+ return (
31
+ <div className={`grid gap-4 lg:grid-cols-[minmax(0,2fr)_minmax(0,3fr)] ${className ?? ""}`}>
32
+ <InboxList onFiltersChange={() => setOpen(null)} initialFilters={initialFilters} selectedId={open?.id} onSelect={setOpen} />
33
+ <div className="min-w-0">
34
+ {open ? (
35
+ <ThreadView key={`${open.channel}:${open.id}`} thread={open}>
36
+ {(thread, reload) => (
37
+ <div className="space-y-3">
38
+ <ReplyComposer thread={thread} onSent={reload} />
39
+ <TagAndAssign thread={thread} availableTags={tags} onChanged={reload} />
40
+ </div>
41
+ )}
42
+ </ThreadView>
43
+ ) : (
44
+ <EmptyState title="Select a conversation" description="Pick a reply on the left to read it and respond." />
45
+ )}
46
+ </div>
47
+ </div>
48
+ );
49
+ }
@@ -0,0 +1,183 @@
1
+ "use client";
2
+
3
+ /**
4
+ * ReplyComposer: write a reply, optionally with AI, and send it on the thread's own channel.
5
+ *
6
+ * SDK operations, in order:
7
+ * 1. POST /inbox/drafts/generate (aiInbox.generateInboxDraft) BILLABLE -> ConfirmSpendDialog first
8
+ * generate_from_scratch grounded in the thread, or shorten / expand / fix_grammar_spelling on your text.
9
+ * Returns { content (HTML), plain_content }; it delivers NOTHING.
10
+ * 2. POST /inbox/{reply_id}/send (inbox.sendReply) EXTERNAL -> ConfirmSpendDialog first
11
+ * Reaches a real person and cannot be recalled. A fixed Idempotency-Key per compose makes a double
12
+ * click or a retry safe.
13
+ *
14
+ * Both calls are gated by tier: nothing is billed or sent until the person clicks the dialog's button.
15
+ */
16
+ import { useEffect, useRef, useState } from "react";
17
+ import { useIdempotencyKey } from "../lib/idempotency";
18
+ import { Button, Input, Textarea } from "@graph8/sdk/ui";
19
+ import { ApiError } from "@/g8/components/api-error";
20
+ import { ConfirmSpendDialog } from "@/g8/components/confirm-spend-dialog";
21
+ import { g8Post } from "@/g8/lib/g8-client";
22
+ import { useG8Mutation } from "@/g8/hooks/use-g8-mutation";
23
+ import { replyRecipient, stripHtml, type InboxThread } from "../lib/inbox-types";
24
+
25
+ type DraftOperation = "generate_from_scratch" | "shorten" | "expand" | "fix_grammar_spelling";
26
+ type Pending = { kind: "draft"; operation: DraftOperation } | { kind: "send" } | null;
27
+
28
+ export interface ReplyComposerProps {
29
+ thread: InboxThread;
30
+ /** Called after the send succeeds; reload the thread here. */
31
+ onSent?: (result: { message_id?: string | null; status: string }) => void;
32
+ className?: string;
33
+ }
34
+
35
+ const TONES = ["professional", "friendly", "casual", "assertive", "empathetic"] as const;
36
+ const OBJECTIVES = ["follow_up", "book_meeting", "handle_objection", "provide_value", "close_deal"] as const;
37
+ const DRAFT_LABEL: Record<DraftOperation, string> = {
38
+ generate_from_scratch: "Draft with AI",
39
+ shorten: "Shorten",
40
+ expand: "Expand",
41
+ fix_grammar_spelling: "Fix grammar",
42
+ };
43
+
44
+ /** The API only drafts for these two channel types; LinkedIn drafts use the account-based flow. */
45
+ function draftChannel(channel: string): "email" | "sms" | undefined {
46
+ return channel === "email" || channel === "sms" ? channel : undefined;
47
+ }
48
+
49
+ export function ReplyComposer({ thread, onSent, className }: ReplyComposerProps) {
50
+ const channel = String(thread.channel);
51
+ const [body, setBody] = useState("");
52
+ const [subject, setSubject] = useState(thread.subject ? (/^re:/i.test(thread.subject) ? thread.subject : `Re: ${thread.subject}`) : "");
53
+ const [to, setTo] = useState(replyRecipient(thread));
54
+ const [tone, setTone] = useState<(typeof TONES)[number]>("professional");
55
+ const [objective, setObjective] = useState<(typeof OBJECTIVES)[number]>("follow_up");
56
+ const [pending, setPending] = useState<Pending>(null);
57
+ const idempotency = useIdempotencyKey(JSON.stringify([thread.channel, thread.id, body, to, channel === "email" ? subject : null]));
58
+ const threadKey = `${thread.channel}:${thread.id}`;
59
+ const currentThread = useRef(threadKey);
60
+ currentThread.current = threadKey;
61
+
62
+ // Stale context: a different conversation starts with a clean composer and a fresh idempotency key.
63
+ useEffect(() => {
64
+ setBody("");
65
+ setSubject(thread.subject ? (/^re:/i.test(thread.subject) ? thread.subject : `Re: ${thread.subject}`) : "");
66
+ setTo(replyRecipient(thread));
67
+ setPending(null);
68
+ draft.reset();
69
+ send.reset();
70
+ // eslint-disable-next-line react-hooks/exhaustive-deps
71
+ }, [thread.id, thread.channel]);
72
+
73
+ const draft = useG8Mutation(async (operation: DraftOperation) => {
74
+ const env = await g8Post<{ content?: string; plain_content?: string }>("/inbox/drafts/generate", {
75
+ operation,
76
+ conversation_id: thread.id,
77
+ channel_type: draftChannel(channel),
78
+ message_html: operation === "generate_from_scratch" ? "" : body,
79
+ tone,
80
+ objective: operation === "generate_from_scratch" ? objective : undefined,
81
+ });
82
+ return env.data;
83
+ });
84
+
85
+ const send = useG8Mutation(async () => {
86
+ const env = await g8Post<{ message_id?: string | null; status: string }>(
87
+ `/inbox/${encodeURIComponent(thread.id)}/send`,
88
+ { body, channel, subject: channel === "email" ? subject : undefined, to: to || undefined },
89
+ { idempotencyKey: idempotency.get() },
90
+ );
91
+ return env.data;
92
+ });
93
+
94
+ const confirm = async () => {
95
+ const current = pending;
96
+ if (!current) return;
97
+ const startedFor = threadKey; // a result that arrives after the person switched conversation is dropped
98
+ try {
99
+ if (current.kind === "draft") {
100
+ const result = await draft.mutateAsync(current.operation);
101
+ if (currentThread.current === startedFor) setBody(result.plain_content ?? stripHtml(result.content));
102
+ } else {
103
+ const result = await send.mutateAsync(undefined);
104
+ idempotency.rotate();
105
+ if (currentThread.current === startedFor) setBody("");
106
+ onSent?.(result);
107
+ }
108
+ if (currentThread.current === startedFor) setPending(null);
109
+ } catch {
110
+ if (currentThread.current === startedFor) setPending(null); // the error renders below; the person can retry
111
+ }
112
+ };
113
+
114
+ const busy = draft.loading || send.loading;
115
+ const canSend = body.trim().length > 0 && (channel === "linkedin" || to.trim().length > 0) && !busy;
116
+ const canTransform = body.trim().length > 0 && !busy;
117
+ const canDraft = Boolean(draftChannel(channel));
118
+
119
+ return (
120
+ <div className={`space-y-2 rounded-lg border p-3 ${className ?? ""}`}>
121
+ {channel === "email" ? (
122
+ <Input aria-label="Subject" placeholder="Subject" value={subject} onChange={(e) => setSubject(e.target.value)} />
123
+ ) : null}
124
+ <Input aria-label="To" placeholder={channel === "sms" ? "Phone number" : "Recipient"} value={to} onChange={(e) => setTo(e.target.value)} />
125
+ <Textarea aria-label="Reply" rows={6} placeholder="Write your reply" value={body} onChange={(e) => setBody(e.target.value)} />
126
+
127
+ {canDraft ? (
128
+ <div className="flex flex-wrap items-center gap-2 text-sm">
129
+ <select aria-label="Tone" className="h-8 rounded-md border bg-background px-2" value={tone} onChange={(e) => setTone(e.target.value as (typeof TONES)[number])}>
130
+ {TONES.map((t) => (
131
+ <option key={t}>{t}</option>
132
+ ))}
133
+ </select>
134
+ <select aria-label="Goal" className="h-8 rounded-md border bg-background px-2" value={objective} onChange={(e) => setObjective(e.target.value as (typeof OBJECTIVES)[number])}>
135
+ {OBJECTIVES.map((o) => (
136
+ <option key={o} value={o}>
137
+ {o.replace("_", " ")}
138
+ </option>
139
+ ))}
140
+ </select>
141
+ <Button size="sm" variant="outline" disabled={busy} onClick={() => setPending({ kind: "draft", operation: "generate_from_scratch" })}>
142
+ {DRAFT_LABEL.generate_from_scratch}
143
+ </Button>
144
+ {(["shorten", "expand", "fix_grammar_spelling"] as const).map((op) => (
145
+ <Button key={op} size="sm" variant="ghost" disabled={!canTransform} onClick={() => setPending({ kind: "draft", operation: op })}>
146
+ {DRAFT_LABEL[op]}
147
+ </Button>
148
+ ))}
149
+ </div>
150
+ ) : null}
151
+
152
+ {draft.error ? <ApiError error={draft.error} title="Could not write the draft" /> : null}
153
+ {send.error ? <ApiError error={send.error} title="Could not send the reply" onRetry={() => setPending({ kind: "send" })} /> : null}
154
+
155
+ <div className="flex justify-end">
156
+ <Button disabled={!canSend} onClick={() => setPending({ kind: "send" })}>
157
+ Send reply
158
+ </Button>
159
+ </div>
160
+
161
+ <ConfirmSpendDialog
162
+ open={pending?.kind === "draft"}
163
+ tier="billable"
164
+ title={pending?.kind === "draft" ? `${DRAFT_LABEL[pending.operation]} (AI)` : ""}
165
+ description="The draft is written into the box above. Nothing is sent. Each AI draft charges credits; you will not be charged for editing it."
166
+ confirmLabel="Write draft"
167
+ confirming={draft.loading}
168
+ onConfirm={() => void confirm()}
169
+ onCancel={() => setPending(null)}
170
+ />
171
+ <ConfirmSpendDialog
172
+ open={pending?.kind === "send"}
173
+ tier="external"
174
+ title={`Send this ${channel} reply?`}
175
+ description={`It goes to ${to || "the contact"} from your connected ${channel === "email" ? "mailbox" : channel} account.`}
176
+ recipients={1}
177
+ confirming={send.loading}
178
+ onConfirm={() => void confirm()}
179
+ onCancel={() => setPending(null)}
180
+ />
181
+ </div>
182
+ );
183
+ }