@graph8/sdk 0.370.0 → 0.374.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 (646) hide show
  1. package/README.md +22 -3
  2. package/blocks/_foundation/README.md +61 -0
  3. package/blocks/_foundation/block.json +57 -0
  4. package/blocks/_foundation/components/auth-gate.tsx +363 -0
  5. package/blocks/_foundation/components/confirm-spend-dialog.tsx +15 -8
  6. package/blocks/_foundation/components/empty-state.tsx +5 -2
  7. package/blocks/_foundation/components/list-select.tsx +112 -0
  8. package/blocks/_foundation/components/paging-notices.tsx +55 -0
  9. package/blocks/_foundation/components/screen/detail-panel.tsx +2 -1
  10. package/blocks/_foundation/components/screen/filter-controls.tsx +92 -0
  11. package/blocks/_foundation/components/screen/index.ts +1 -0
  12. package/blocks/_foundation/components/screen/split-view.tsx +1 -1
  13. package/blocks/_foundation/hooks/use-all-pages.ts +54 -0
  14. package/blocks/_foundation/hooks/use-load-more-list.ts +61 -0
  15. package/blocks/_foundation/hooks/use-url-filters.ts +93 -0
  16. package/blocks/_foundation/lib/paging.ts +57 -0
  17. package/blocks/_foundation/lib/use-debounced-value.ts +13 -0
  18. package/blocks/_foundation/server/auth.ts +815 -0
  19. package/blocks/agents/README.md +81 -4
  20. package/blocks/agents/block.json +311 -2
  21. package/blocks/agents/components/agent-activity.tsx +112 -0
  22. package/blocks/agents/components/agent-approvals.tsx +135 -0
  23. package/blocks/agents/components/agent-builder.tsx +17 -3
  24. package/blocks/agents/components/agent-conversations.tsx +143 -0
  25. package/blocks/agents/components/agent-knowledge-panel.tsx +2 -2
  26. package/blocks/agents/components/agent-operators.tsx +164 -0
  27. package/blocks/agents/components/agent-run-detail.tsx +20 -3
  28. package/blocks/agents/components/agent-runs.tsx +3 -3
  29. package/blocks/agents/components/agent-skills-panel.tsx +7 -7
  30. package/blocks/agents/components/agent-test-history.tsx +121 -0
  31. package/blocks/agents/components/agents-screen.tsx +53 -11
  32. package/blocks/agents/components/assistant-sessions.tsx +150 -0
  33. package/blocks/agents/components/duplicate-agent-button.tsx +42 -0
  34. package/blocks/agents/components/from-template-button.tsx +65 -0
  35. package/blocks/agents/components/knowledge-browser.tsx +107 -0
  36. package/blocks/agents/components/knowledge-detail.tsx +156 -0
  37. package/blocks/agents/components/knowledge-form.tsx +69 -0
  38. package/blocks/agents/components/name-dialog.tsx +32 -0
  39. package/blocks/agents/components/receptionist-button.tsx +46 -0
  40. package/blocks/agents/components/save-as-template-button.tsx +32 -0
  41. package/blocks/agents/components/skill-editor.tsx +147 -0
  42. package/blocks/agents/components/skill-library.tsx +111 -0
  43. package/blocks/agents/lib/agent-types.ts +7 -1
  44. package/blocks/agents/lib/facts.tsx +13 -0
  45. package/blocks/agents/lib/knowledge-utils.ts +49 -0
  46. package/blocks/agents/lib/load-more.tsx +141 -0
  47. package/blocks/agents/lib/skill-utils.ts +91 -0
  48. package/blocks/agents/recipes/create-agent-and-attach-skill.ts +1 -1
  49. package/blocks/analytics/components/analytics-screen.tsx +16 -3
  50. package/blocks/analytics/components/kpi-tiles.tsx +1 -1
  51. package/blocks/analytics/components/report-builder.tsx +15 -2
  52. package/blocks/appointments/README.md +6 -0
  53. package/blocks/appointments/block.json +27 -0
  54. package/blocks/appointments/components/booking-page.tsx +2 -2
  55. package/blocks/appointments/components/meeting-contact-links.tsx +49 -0
  56. package/blocks/appointments/components/meeting-detail.tsx +2 -2
  57. package/blocks/appointments/components/meeting-list.tsx +29 -13
  58. package/blocks/appointments/components/record-meetings-tab.tsx +92 -0
  59. package/blocks/campaigns/README.md +1 -1
  60. package/blocks/campaigns/block.json +34 -1
  61. package/blocks/campaigns/components/campaign-assets.tsx +1 -1
  62. package/blocks/campaigns/components/campaign-launch-step.tsx +16 -11
  63. package/blocks/campaigns/components/campaign-links.tsx +180 -0
  64. package/blocks/campaigns/components/campaign-metrics.tsx +1 -1
  65. package/blocks/campaigns/components/campaign-wizard.tsx +10 -5
  66. package/blocks/campaigns/components/icp-detail.tsx +11 -2
  67. package/blocks/campaigns/components/icp-editor.tsx +8 -3
  68. package/blocks/campaigns/components/persona-detail.tsx +11 -2
  69. package/blocks/campaigns/components/persona-editor.tsx +6 -1
  70. package/blocks/campaigns/lib/campaigns-utils.ts +4 -4
  71. package/blocks/coach/components/call-scorecard.tsx +7 -7
  72. package/blocks/company-intelligence/README.md +132 -0
  73. package/blocks/company-intelligence/block.json +318 -0
  74. package/blocks/company-intelligence/components/company-intelligence-screen.tsx +114 -0
  75. package/blocks/company-intelligence/components/company-intelligence-tab.tsx +88 -0
  76. package/blocks/company-intelligence/components/company-profile.tsx +68 -0
  77. package/blocks/company-intelligence/components/intelligence-sources.tsx +63 -0
  78. package/blocks/company-intelligence/components/report-detail.tsx +189 -0
  79. package/blocks/company-intelligence/components/research-reports.tsx +136 -0
  80. package/blocks/company-intelligence/components/research-run.tsx +165 -0
  81. package/blocks/company-intelligence/components/source-detail.tsx +117 -0
  82. package/blocks/company-intelligence/components/source-view.tsx +274 -0
  83. package/blocks/company-intelligence/components/wiki-document-detail.tsx +116 -0
  84. package/blocks/company-intelligence/components/wiki-documents.tsx +66 -0
  85. package/blocks/company-intelligence/hooks/use-intelligence.ts +173 -0
  86. package/blocks/company-intelligence/lib/intelligence-types.ts +230 -0
  87. package/blocks/company-intelligence/lib/safe-markdown.tsx +150 -0
  88. package/blocks/company-intelligence/recipes/read-competitors-and-news.ts +33 -0
  89. package/blocks/company-intelligence/recipes/research-your-website.ts +43 -0
  90. package/blocks/company-intelligence/recipes/write-the-research-reports.ts +54 -0
  91. package/blocks/copilot/components/copilot-memory.tsx +6 -2
  92. package/blocks/copilot/components/copilot-panel.tsx +1 -1
  93. package/blocks/copilot/components/copilot-team-chat.tsx +6 -1
  94. package/blocks/crm/README.md +25 -0
  95. package/blocks/crm/block.json +257 -9
  96. package/blocks/crm/components/bulk-update.tsx +119 -0
  97. package/blocks/crm/components/companies-screen.tsx +23 -9
  98. package/blocks/crm/components/company-detail.tsx +2 -2
  99. package/blocks/crm/components/contact-detail.tsx +4 -4
  100. package/blocks/crm/components/contact-documents-tab.tsx +144 -0
  101. package/blocks/crm/components/contact-insights-tab.tsx +118 -0
  102. package/blocks/crm/components/contact-lookup-link.tsx +85 -0
  103. package/blocks/crm/components/contact-row-actions.tsx +43 -0
  104. package/blocks/crm/components/contact-tag-chips.tsx +113 -0
  105. package/blocks/crm/components/contacts-screen.tsx +77 -18
  106. package/blocks/crm/components/dedupe-review.tsx +6 -1
  107. package/blocks/crm/components/import-wizard.tsx +3 -7
  108. package/blocks/crm/components/list-select.tsx +20 -0
  109. package/blocks/crm/components/owner-assign.tsx +132 -0
  110. package/blocks/crm/components/record-engagement-tab.tsx +103 -0
  111. package/blocks/crm/components/record-form.tsx +1 -1
  112. package/blocks/crm/components/record-open-links.tsx +79 -0
  113. package/blocks/crm/components/tag-assign.tsx +112 -0
  114. package/blocks/crm/components/tag-manager.tsx +178 -0
  115. package/blocks/crm/components/tasks-screen.tsx +35 -15
  116. package/blocks/crm/components/unlock-info-button.tsx +82 -0
  117. package/blocks/crm/components/verify-email-button.tsx +93 -0
  118. package/blocks/crm/hooks/use-all-lists.ts +18 -0
  119. package/blocks/crm/hooks/use-contact-tags.ts +29 -0
  120. package/blocks/crm/hooks/use-page-query.ts +3 -1
  121. package/blocks/crm/lib/crm-types.ts +14 -0
  122. package/blocks/crm/lib/read-lists.ts +16 -0
  123. package/blocks/crm/lib/record-actions.ts +102 -0
  124. package/blocks/deals/README.md +25 -6
  125. package/blocks/deals/block.json +168 -2
  126. package/blocks/deals/components/close-deal-dialog.tsx +169 -0
  127. package/blocks/deals/components/create-deal-button.tsx +109 -0
  128. package/blocks/deals/components/deal-contacts-editor.tsx +134 -0
  129. package/blocks/deals/components/deal-detail.tsx +7 -5
  130. package/blocks/deals/components/deal-filters.tsx +65 -0
  131. package/blocks/deals/components/deal-line-items.tsx +120 -0
  132. package/blocks/deals/components/deal-notes-tab.tsx +97 -0
  133. package/blocks/deals/components/deal-related.tsx +30 -9
  134. package/blocks/deals/components/deal-tasks-tab.tsx +88 -0
  135. package/blocks/deals/components/deals-screen.tsx +57 -22
  136. package/blocks/deals/components/forecast-view.tsx +4 -4
  137. package/blocks/deals/components/pipeline-board.tsx +8 -6
  138. package/blocks/deals/components/pipeline-editor.tsx +132 -0
  139. package/blocks/deals/components/record-deals-tab.tsx +62 -0
  140. package/blocks/deals/components/stage-editor.tsx +1 -1
  141. package/blocks/deals/hooks/use-pipeline-deals.ts +17 -4
  142. package/blocks/deals/lib/deal-extras.ts +156 -0
  143. package/blocks/dialer/README.md +14 -5
  144. package/blocks/dialer/block.json +17 -2
  145. package/blocks/dialer/components/call-contact-button.tsx +26 -9
  146. package/blocks/dialer/components/call-log-screen.tsx +10 -2
  147. package/blocks/dialer/components/call-log.tsx +16 -4
  148. package/blocks/dialer/components/call-queue.tsx +3 -3
  149. package/blocks/dialer/components/dialer-screen.tsx +69 -27
  150. package/blocks/dialer/components/disposition-panel.tsx +1 -1
  151. package/blocks/dialer/components/record-calls-tab.tsx +101 -0
  152. package/blocks/dialer/components/session-start-form.tsx +58 -11
  153. package/blocks/dialer/components/softphone.tsx +1 -1
  154. package/blocks/documents/README.md +86 -0
  155. package/blocks/documents/block.json +378 -0
  156. package/blocks/documents/components/account-bar.tsx +48 -0
  157. package/blocks/documents/components/correspondence-form.tsx +95 -0
  158. package/blocks/documents/components/correspondence-import.tsx +106 -0
  159. package/blocks/documents/components/correspondence-panel.tsx +191 -0
  160. package/blocks/documents/components/documents-screen.tsx +76 -0
  161. package/blocks/documents/components/library-document-detail.tsx +175 -0
  162. package/blocks/documents/components/library-document-form.tsx +105 -0
  163. package/blocks/documents/components/library-folder-form.tsx +74 -0
  164. package/blocks/documents/components/library-panel.tsx +235 -0
  165. package/blocks/documents/components/library-upload.tsx +160 -0
  166. package/blocks/documents/components/question-row.tsx +130 -0
  167. package/blocks/documents/components/questionnaire-detail.tsx +197 -0
  168. package/blocks/documents/components/questionnaires-panel.tsx +173 -0
  169. package/blocks/documents/components/record-documents-tab.tsx +109 -0
  170. package/blocks/documents/lib/documents-types.ts +252 -0
  171. package/blocks/documents/lib/download.ts +64 -0
  172. package/blocks/documents/recipes/follow-a-questionnaire.ts +26 -0
  173. package/blocks/documents/recipes/log-account-correspondence.ts +27 -0
  174. package/blocks/documents/recipes/organize-the-library.ts +25 -0
  175. package/blocks/email-signatures/README.md +123 -0
  176. package/blocks/email-signatures/block.json +341 -0
  177. package/blocks/email-signatures/components/email-signatures-screen.tsx +166 -0
  178. package/blocks/email-signatures/components/signature-assign-template.tsx +119 -0
  179. package/blocks/email-signatures/components/signature-block-editor.tsx +87 -0
  180. package/blocks/email-signatures/components/signature-campaign-form.tsx +165 -0
  181. package/blocks/email-signatures/components/signature-campaigns.tsx +75 -0
  182. package/blocks/email-signatures/components/signature-identity-form.tsx +131 -0
  183. package/blocks/email-signatures/components/signature-mailboxes.tsx +195 -0
  184. package/blocks/email-signatures/components/signature-policy.tsx +130 -0
  185. package/blocks/email-signatures/components/signature-preview.tsx +119 -0
  186. package/blocks/email-signatures/components/signature-report.tsx +77 -0
  187. package/blocks/email-signatures/components/signature-template-details.tsx +112 -0
  188. package/blocks/email-signatures/components/signature-template-form.tsx +109 -0
  189. package/blocks/email-signatures/hooks/use-signatures-data.ts +93 -0
  190. package/blocks/email-signatures/lib/signatures-types.ts +392 -0
  191. package/blocks/email-signatures/recipes/assign-a-signature-to-a-new-hire.ts +32 -0
  192. package/blocks/email-signatures/recipes/create-a-template-and-make-it-default.ts +35 -0
  193. package/blocks/email-signatures/recipes/signature-engagement-report.ts +16 -0
  194. package/blocks/enrichment/README.md +38 -10
  195. package/blocks/enrichment/block.json +164 -12
  196. package/blocks/enrichment/components/auto-enrichment-configs.tsx +134 -0
  197. package/blocks/enrichment/components/auto-enrichment-settings.tsx +82 -0
  198. package/blocks/enrichment/components/bulk-enrich-panel.tsx +79 -30
  199. package/blocks/enrichment/components/email-verify-badge.tsx +3 -3
  200. package/blocks/enrichment/components/enrich-button.tsx +1 -1
  201. package/blocks/enrichment/components/enrichment-activity.tsx +93 -0
  202. package/blocks/enrichment/components/enrichment-job-detail.tsx +18 -0
  203. package/blocks/enrichment/components/enrichment-screen.tsx +103 -19
  204. package/blocks/enrichment/components/list-pipelines.tsx +97 -0
  205. package/blocks/enrichment/components/pipeline-detail.tsx +214 -0
  206. package/blocks/enrichment/components/pipeline-editor.tsx +144 -0
  207. package/blocks/enrichment/components/pipeline-templates.tsx +90 -0
  208. package/blocks/enrichment/components/waterfall-config.tsx +27 -7
  209. package/blocks/enrichment/lib/enrichment-types.ts +51 -0
  210. package/blocks/enrichment/lib/pipeline-types.ts +234 -0
  211. package/blocks/enrichment/recipes/bulk-enrich-and-poll.ts +15 -4
  212. package/blocks/forms/README.md +10 -0
  213. package/blocks/forms/block.json +107 -0
  214. package/blocks/forms/components/form-activity.tsx +71 -0
  215. package/blocks/forms/components/form-backfill.tsx +108 -0
  216. package/blocks/forms/components/form-builder.tsx +1 -1
  217. package/blocks/forms/components/form-embed.tsx +1 -1
  218. package/blocks/forms/components/form-groups.tsx +151 -0
  219. package/blocks/forms/components/form-mapping-editor.tsx +6 -9
  220. package/blocks/forms/components/form-route-history.tsx +72 -0
  221. package/blocks/forms/components/form-saved-views.tsx +81 -0
  222. package/blocks/forms/components/forms-screen.tsx +57 -20
  223. package/blocks/forms/components/more-rows.tsx +30 -0
  224. package/blocks/forms/components/submissions-export.tsx +67 -0
  225. package/blocks/forms/components/submissions-table.tsx +15 -6
  226. package/blocks/forms/lib/forms-extra.ts +67 -0
  227. package/blocks/inbox/README.md +45 -4
  228. package/blocks/inbox/block.json +145 -8
  229. package/blocks/inbox/components/blocked-senders.tsx +103 -0
  230. package/blocks/inbox/components/compose-message.tsx +193 -0
  231. package/blocks/inbox/components/inbox-screen.tsx +54 -6
  232. package/blocks/inbox/components/inbox-search.tsx +106 -0
  233. package/blocks/inbox/components/record-conversations-tab.tsx +154 -0
  234. package/blocks/inbox/components/tag-manager.tsx +136 -0
  235. package/blocks/inbox/components/thread-actions.tsx +133 -0
  236. package/blocks/inbox/components/thread-badge.tsx +2 -2
  237. package/blocks/inbox/components/thread-view.tsx +3 -1
  238. package/blocks/inbox/hooks/use-inbox-mailboxes.ts +31 -0
  239. package/blocks/inbox/lib/inbox-manage.ts +227 -0
  240. package/blocks/integrations/README.md +54 -1
  241. package/blocks/integrations/block.json +189 -15
  242. package/blocks/integrations/components/ad-accounts.tsx +82 -0
  243. package/blocks/integrations/components/connection-health.tsx +59 -0
  244. package/blocks/integrations/components/crm-detail.tsx +20 -1
  245. package/blocks/integrations/components/crm-records.tsx +103 -0
  246. package/blocks/integrations/components/field-mappings.tsx +61 -0
  247. package/blocks/integrations/components/integration-list.tsx +4 -4
  248. package/blocks/integrations/components/integrations-screen.tsx +20 -3
  249. package/blocks/integrations/components/migration-panel.tsx +133 -0
  250. package/blocks/integrations/components/sugarcrm-connect.tsx +95 -0
  251. package/blocks/integrations/components/sync-status.tsx +6 -6
  252. package/blocks/integrations/components/sync-triggers.tsx +134 -0
  253. package/blocks/integrations/components/webhook-detail.tsx +26 -7
  254. package/blocks/integrations/components/webhook-manager.tsx +30 -17
  255. package/blocks/integrations/components/workspace-tools.tsx +127 -0
  256. package/blocks/integrations/lib/crm-utils.ts +39 -0
  257. package/blocks/integrations/lib/facts.tsx +13 -0
  258. package/blocks/integrations/lib/integrations-utils.ts +5 -0
  259. package/blocks/integrations/lib/load-more.tsx +141 -0
  260. package/blocks/intent/components/account-intent-score.tsx +5 -5
  261. package/blocks/intent/components/intent-feed.tsx +8 -8
  262. package/blocks/intent/components/intent-keyword-manager.tsx +8 -8
  263. package/blocks/intent/lib/intent-utils.ts +4 -4
  264. package/blocks/lifecycle/components/account-related.tsx +8 -1
  265. package/blocks/lifecycle/components/churn-list.tsx +5 -2
  266. package/blocks/lifecycle/components/customer-table.tsx +1 -1
  267. package/blocks/lists/README.md +7 -1
  268. package/blocks/lists/block.json +31 -3
  269. package/blocks/lists/components/add-company-people-to-list-button.tsx +73 -0
  270. package/blocks/lists/components/add-to-list-button.tsx +17 -7
  271. package/blocks/lists/components/list-picker.tsx +13 -3
  272. package/blocks/lists/components/list-table.tsx +1 -1
  273. package/blocks/lists/components/lists-screen.tsx +4 -2
  274. package/blocks/lists/components/record-lists-tab.tsx +99 -0
  275. package/blocks/lists/components/suppression-manager.tsx +27 -6
  276. package/blocks/lists/components/suppressions-screen.tsx +21 -12
  277. package/blocks/mailboxes/block.json +4 -0
  278. package/blocks/mailboxes/components/connect-mailbox.tsx +9 -8
  279. package/blocks/mailboxes/components/domain-detail.tsx +10 -4
  280. package/blocks/mailboxes/components/domain-purchase.tsx +14 -11
  281. package/blocks/mailboxes/components/mailbox-detail.tsx +3 -2
  282. package/blocks/mailboxes/components/mailbox-list.tsx +8 -3
  283. package/blocks/mailboxes/components/mailboxes-screen.tsx +8 -3
  284. package/blocks/mailboxes/components/warmup-health.tsx +20 -20
  285. package/blocks/mailboxes/lib/mailboxes-utils.ts +4 -4
  286. package/blocks/mailboxes/lib/use-provider-domains.ts +23 -0
  287. package/blocks/newsletter/README.md +12 -0
  288. package/blocks/newsletter/block.json +117 -0
  289. package/blocks/newsletter/components/issue-scheduler.tsx +2 -2
  290. package/blocks/newsletter/components/issue-versions.tsx +93 -0
  291. package/blocks/newsletter/components/more-rows.tsx +30 -0
  292. package/blocks/newsletter/components/newsletter-editor.tsx +1 -1
  293. package/blocks/newsletter/components/newsletter-list-syncs.tsx +121 -0
  294. package/blocks/newsletter/components/newsletter-screen.tsx +38 -13
  295. package/blocks/newsletter/components/newsletter-settings.tsx +211 -0
  296. package/blocks/newsletter/components/newsletter-stats.tsx +2 -2
  297. package/blocks/newsletter/components/newsletter-templates.tsx +133 -0
  298. package/blocks/newsletter/components/subscriber-table.tsx +5 -7
  299. package/blocks/newsletter/components/subscriber-timeline.tsx +65 -0
  300. package/blocks/newsletter/lib/newsletter-extra.ts +60 -0
  301. package/blocks/nurture/components/nurture-builder.tsx +10 -2
  302. package/blocks/nurture/components/nurture-enroll.tsx +6 -7
  303. package/blocks/nurture/components/nurture-form.tsx +5 -8
  304. package/blocks/nurture/components/nurture-screen.tsx +16 -5
  305. package/blocks/nurture/components/nurture-stats.tsx +5 -4
  306. package/blocks/objects/README.md +1 -1
  307. package/blocks/objects/block.json +13 -5
  308. package/blocks/objects/components/attribute-field-input.tsx +14 -1
  309. package/blocks/objects/components/object-record-detail.tsx +8 -1
  310. package/blocks/objects/components/object-schema-editor.tsx +1 -1
  311. package/blocks/objects/components/record-roles-panel.tsx +15 -5
  312. package/blocks/pages/README.md +14 -0
  313. package/blocks/pages/block.json +123 -2
  314. package/blocks/pages/components/more-rows.tsx +30 -0
  315. package/blocks/pages/components/page-ai-tools.tsx +196 -0
  316. package/blocks/pages/components/page-analytics.tsx +176 -0
  317. package/blocks/pages/components/page-clone.tsx +99 -0
  318. package/blocks/pages/components/page-domains.tsx +167 -0
  319. package/blocks/pages/components/page-editor.tsx +1 -1
  320. package/blocks/pages/components/page-generation-status.tsx +48 -0
  321. package/blocks/pages/components/page-tracking.tsx +137 -0
  322. package/blocks/pages/components/pages-screen.tsx +57 -16
  323. package/blocks/pages/components/seo-report.tsx +6 -1
  324. package/blocks/pages/hooks/use-landing-page-paths.ts +60 -0
  325. package/blocks/pages/lib/studio.ts +7 -0
  326. package/blocks/phone-numbers/README.md +74 -0
  327. package/blocks/phone-numbers/block.json +262 -0
  328. package/blocks/phone-numbers/components/a2p-registration.tsx +230 -0
  329. package/blocks/phone-numbers/components/assign-number.tsx +104 -0
  330. package/blocks/phone-numbers/components/number-search.tsx +239 -0
  331. package/blocks/phone-numbers/components/number-settings.tsx +134 -0
  332. package/blocks/phone-numbers/components/number-usage.tsx +97 -0
  333. package/blocks/phone-numbers/components/phone-number-detail.tsx +84 -0
  334. package/blocks/phone-numbers/components/phone-number-list.tsx +110 -0
  335. package/blocks/phone-numbers/components/phone-numbers-screen.tsx +201 -0
  336. package/blocks/phone-numbers/components/register-owned-number.tsx +98 -0
  337. package/blocks/phone-numbers/components/release-number.tsx +126 -0
  338. package/blocks/phone-numbers/hooks/use-phone-numbers.ts +58 -0
  339. package/blocks/phone-numbers/lib/phone-numbers-utils.ts +202 -0
  340. package/blocks/phone-numbers/recipes/01-search-and-buy-number.ts +49 -0
  341. package/blocks/phone-numbers/recipes/02-assign-number-to-rep.ts +25 -0
  342. package/blocks/phone-numbers/recipes/03-audit-numbers.ts +36 -0
  343. package/blocks/phone-numbers/recipes/04-register-text-messaging.ts +39 -0
  344. package/blocks/pickers/README.md +23 -0
  345. package/blocks/pickers/block.json +103 -0
  346. package/blocks/pickers/components/company-picker.tsx +90 -0
  347. package/blocks/pickers/components/contact-picker.tsx +131 -0
  348. package/blocks/pickers/components/member-picker.tsx +99 -0
  349. package/blocks/pickers/components/search-picker.tsx +98 -0
  350. package/blocks/pickers/hooks/use-current-member.ts +104 -0
  351. package/blocks/pickers/hooks/use-picker-pages.ts +73 -0
  352. package/blocks/pickers/lib/use-debounced.ts +13 -0
  353. package/blocks/programmatic-pages/README.md +82 -0
  354. package/blocks/programmatic-pages/block.json +292 -0
  355. package/blocks/programmatic-pages/components/programmatic-campaign-form.tsx +136 -0
  356. package/blocks/programmatic-pages/components/programmatic-generate.tsx +112 -0
  357. package/blocks/programmatic-pages/components/programmatic-generated-pages.tsx +210 -0
  358. package/blocks/programmatic-pages/components/programmatic-overview.tsx +84 -0
  359. package/blocks/programmatic-pages/components/programmatic-pages-screen.tsx +221 -0
  360. package/blocks/programmatic-pages/components/programmatic-preview.tsx +66 -0
  361. package/blocks/programmatic-pages/components/programmatic-publish.tsx +102 -0
  362. package/blocks/programmatic-pages/components/programmatic-settings.tsx +96 -0
  363. package/blocks/programmatic-pages/components/programmatic-source-fields.tsx +75 -0
  364. package/blocks/programmatic-pages/components/programmatic-source.tsx +106 -0
  365. package/blocks/programmatic-pages/components/programmatic-variables.tsx +84 -0
  366. package/blocks/programmatic-pages/hooks/use-programmatic-workspace.ts +19 -0
  367. package/blocks/programmatic-pages/lib/programmatic-types.ts +330 -0
  368. package/blocks/programmatic-pages/recipes/create-a-programmatic-campaign.ts +23 -0
  369. package/blocks/programmatic-pages/recipes/render-and-follow.ts +21 -0
  370. package/blocks/programmatic-pages/recipes/review-then-publish.ts +17 -0
  371. package/blocks/quotes/README.md +38 -1
  372. package/blocks/quotes/block.json +170 -6
  373. package/blocks/quotes/components/create-quote-from-deal.tsx +48 -0
  374. package/blocks/quotes/components/manual-products.tsx +144 -0
  375. package/blocks/quotes/components/quote-batch-actions.tsx +86 -0
  376. package/blocks/quotes/components/quote-builder.tsx +1 -1
  377. package/blocks/quotes/components/quote-documents.tsx +94 -0
  378. package/blocks/quotes/components/quote-evidence.tsx +95 -0
  379. package/blocks/quotes/components/quote-lifecycle-actions.tsx +146 -0
  380. package/blocks/quotes/components/quote-list.tsx +28 -8
  381. package/blocks/quotes/components/quote-related.tsx +3 -2
  382. package/blocks/quotes/components/quote-settings.tsx +184 -0
  383. package/blocks/quotes/components/quote-templates.tsx +189 -0
  384. package/blocks/quotes/components/quote-viewer.tsx +23 -5
  385. package/blocks/quotes/components/quotes-screen.tsx +15 -5
  386. package/blocks/quotes/components/record-quotes-tab.tsx +90 -0
  387. package/blocks/quotes/lib/quote-admin.ts +264 -0
  388. package/blocks/radar/components/competitor-battle-card.tsx +1 -1
  389. package/blocks/radar/components/radar-overview.tsx +4 -4
  390. package/blocks/radar/components/radar-screen.tsx +2 -2
  391. package/blocks/sequencer/README.md +61 -0
  392. package/blocks/sequencer/block.json +200 -6
  393. package/blocks/sequencer/components/add-to-sequence-button.tsx +82 -0
  394. package/blocks/sequencer/components/enroll-dialog.tsx +2 -2
  395. package/blocks/sequencer/components/enrollment-withdraw.tsx +71 -0
  396. package/blocks/sequencer/components/record-sequences-tab.tsx +126 -0
  397. package/blocks/sequencer/components/sequence-builder.tsx +32 -23
  398. package/blocks/sequencer/components/sequence-campaign-link.tsx +78 -0
  399. package/blocks/sequencer/components/sequence-detail.tsx +10 -2
  400. package/blocks/sequencer/components/sequence-edit-form.tsx +111 -0
  401. package/blocks/sequencer/components/sequence-enrollments.tsx +5 -2
  402. package/blocks/sequencer/components/sequence-list.tsx +1 -1
  403. package/blocks/sequencer/components/sequence-manage-actions.tsx +119 -0
  404. package/blocks/sequencer/components/sequence-senders-panel.tsx +84 -0
  405. package/blocks/sequencer/components/sequence-stats.tsx +8 -8
  406. package/blocks/sequencer/components/sequence-templates.tsx +160 -0
  407. package/blocks/sequencer/components/sequences-screen.tsx +39 -6
  408. package/blocks/sequencer/components/step-ai-assist.tsx +196 -0
  409. package/blocks/sequencer/components/step-editor.tsx +21 -12
  410. package/blocks/sequencer/components/step-templates.tsx +224 -0
  411. package/blocks/sequencer/lib/sequencer-manage.ts +235 -0
  412. package/blocks/sequencer/lib/sequencer-utils.ts +9 -5
  413. package/blocks/signals/README.md +39 -0
  414. package/blocks/signals/block.json +287 -0
  415. package/blocks/signals/components/auto-seed-panel.tsx +111 -0
  416. package/blocks/signals/components/listener-form.tsx +184 -0
  417. package/blocks/signals/components/matched-posts.tsx +195 -0
  418. package/blocks/signals/components/post-engagements.tsx +114 -0
  419. package/blocks/signals/components/record-social-tab.tsx +49 -0
  420. package/blocks/signals/components/social-listeners-screen.tsx +250 -0
  421. package/blocks/signals/components/social-settings.tsx +128 -0
  422. package/blocks/signals/components/source-lists.tsx +83 -0
  423. package/blocks/signals/components/top-engagers.tsx +68 -0
  424. package/blocks/signals/components/x-integration.tsx +129 -0
  425. package/blocks/signals/lib/signals-types.ts +228 -0
  426. package/blocks/signals/recipes/preview-and-create-a-listener.ts +16 -0
  427. package/blocks/signals/recipes/spend-against-caps.ts +14 -0
  428. package/blocks/signals/recipes/triage-matched-posts.ts +18 -0
  429. package/blocks/social-ads/README.md +8 -0
  430. package/blocks/social-ads/block.json +137 -4
  431. package/blocks/social-ads/components/audience-sync-detail.tsx +9 -3
  432. package/blocks/social-ads/components/audience-sync.tsx +6 -2
  433. package/blocks/social-ads/components/campaign-ads.tsx +166 -0
  434. package/blocks/social-ads/components/campaign-detail.tsx +6 -1
  435. package/blocks/social-ads/components/campaign-editor.tsx +134 -0
  436. package/blocks/social-ads/components/creative-concepts.tsx +74 -0
  437. package/blocks/social-ads/components/creative-detail.tsx +6 -1
  438. package/blocks/social-ads/components/creative-gallery.tsx +20 -2
  439. package/blocks/social-ads/components/creative-revisions.tsx +57 -0
  440. package/blocks/social-ads/components/creative-tools.tsx +176 -0
  441. package/blocks/social-ads/components/post-composer.tsx +4 -2
  442. package/blocks/social-ads/components/post-detail.tsx +3 -0
  443. package/blocks/social-ads/components/social-ideas.tsx +64 -0
  444. package/blocks/social-ads/components/social-performance.tsx +80 -0
  445. package/blocks/social-ads/components/social-screen.tsx +33 -6
  446. package/blocks/social-ads/lib/ads-extra.ts +67 -0
  447. package/blocks/surveys/README.md +91 -0
  448. package/blocks/surveys/block.json +299 -0
  449. package/blocks/surveys/components/account-nps.tsx +69 -0
  450. package/blocks/surveys/components/contact-survey-history.tsx +52 -0
  451. package/blocks/surveys/components/org-summary.tsx +82 -0
  452. package/blocks/surveys/components/sending-domains.tsx +113 -0
  453. package/blocks/surveys/components/survey-form.tsx +126 -0
  454. package/blocks/surveys/components/survey-responses.tsx +145 -0
  455. package/blocks/surveys/components/survey-results.tsx +72 -0
  456. package/blocks/surveys/components/survey-send-history.tsx +58 -0
  457. package/blocks/surveys/components/survey-send.tsx +162 -0
  458. package/blocks/surveys/components/survey-triggers.tsx +166 -0
  459. package/blocks/surveys/components/surveys-screen.tsx +234 -0
  460. package/blocks/surveys/lib/surveys-types.ts +228 -0
  461. package/blocks/surveys/recipes/create-an-nps-survey.ts +22 -0
  462. package/blocks/surveys/recipes/send-a-survey-and-follow-it.ts +27 -0
  463. package/blocks/surveys/recipes/survey-score-report.ts +27 -0
  464. package/blocks/visitors/components/snippet-install.tsx +18 -9
  465. package/blocks/visitors/components/traffic-chart.tsx +7 -6
  466. package/blocks/visitors/components/visitor-company-card.tsx +24 -14
  467. package/blocks/visitors/components/visitor-feed.tsx +5 -5
  468. package/blocks/web-analytics/README.md +102 -0
  469. package/blocks/web-analytics/block.json +292 -0
  470. package/blocks/web-analytics/components/acquisition-tab.tsx +154 -0
  471. package/blocks/web-analytics/components/analytics-filters.tsx +161 -0
  472. package/blocks/web-analytics/components/audience-tab.tsx +135 -0
  473. package/blocks/web-analytics/components/conversions-tab.tsx +128 -0
  474. package/blocks/web-analytics/components/engagement-tab.tsx +123 -0
  475. package/blocks/web-analytics/components/overview-tab.tsx +102 -0
  476. package/blocks/web-analytics/components/pages-tab.tsx +148 -0
  477. package/blocks/web-analytics/components/ranked-table.tsx +103 -0
  478. package/blocks/web-analytics/components/realtime-tab.tsx +103 -0
  479. package/blocks/web-analytics/components/report-card.tsx +71 -0
  480. package/blocks/web-analytics/components/web-analytics-screen.tsx +90 -0
  481. package/blocks/web-analytics/hooks/use-report.ts +48 -0
  482. package/blocks/web-analytics/lib/analytics-scope.ts +155 -0
  483. package/blocks/web-analytics/lib/page-path.ts +14 -0
  484. package/blocks/web-analytics/lib/web-analytics-types.ts +187 -0
  485. package/blocks/web-analytics/recipes/best-landing-pages.ts +26 -0
  486. package/blocks/web-analytics/recipes/form-conversion-check.ts +19 -0
  487. package/blocks/web-analytics/recipes/weekly-traffic-report.ts +37 -0
  488. package/blocks/webchat/components/chat-widget-config.tsx +1 -1
  489. package/blocks/webchat/components/conversation-list.tsx +1 -1
  490. package/blocks/workbench/README.md +54 -2
  491. package/blocks/workbench/block.json +234 -5
  492. package/blocks/workbench/components/column-recipe-editor.tsx +1 -1
  493. package/blocks/workbench/components/run-progress.tsx +1 -1
  494. package/blocks/workbench/components/workbench-auto-enrich.tsx +88 -0
  495. package/blocks/workbench/components/workbench-automation.tsx +36 -0
  496. package/blocks/workbench/components/workbench-connections.tsx +136 -0
  497. package/blocks/workbench/components/workbench-crm-import.tsx +91 -0
  498. package/blocks/workbench/components/workbench-datafile-import.tsx +154 -0
  499. package/blocks/workbench/components/workbench-grid.tsx +71 -8
  500. package/blocks/workbench/components/workbench-pipelines.tsx +173 -0
  501. package/blocks/workbench/components/workbench-row-actions.tsx +8 -1
  502. package/blocks/workbench/components/workbench-schedule.tsx +191 -0
  503. package/blocks/workbench/components/workbench-screen.tsx +65 -22
  504. package/blocks/workbench/components/workbench-send-to-sequence.tsx +116 -0
  505. package/blocks/workbench/components/workbench-table-list.tsx +14 -2
  506. package/blocks/workbench/components/workbench-table-settings.tsx +53 -0
  507. package/blocks/workbench/components/workbench-triggers.tsx +178 -0
  508. package/blocks/workbench/hooks/use-connected-crms.ts +29 -0
  509. package/blocks/workbench/lib/api-status.ts +8 -0
  510. package/blocks/workbench/lib/automation-types.ts +257 -0
  511. package/blocks/workflows/components/workflow-editor.tsx +1 -1
  512. package/dist/cli.js +744 -394
  513. package/dist/index.browser.js +1 -1
  514. package/dist/index.browser.js.map +1 -1
  515. package/dist/index.browser.mjs +1 -1
  516. package/dist/index.browser.mjs.map +1 -1
  517. package/dist/index.d.mts +2 -2
  518. package/dist/index.d.ts +2 -2
  519. package/dist/index.js +1 -1
  520. package/dist/index.js.map +1 -1
  521. package/dist/index.mjs +1 -1
  522. package/dist/index.mjs.map +1 -1
  523. package/dist/react.browser.js +1 -1
  524. package/dist/react.browser.js.map +1 -1
  525. package/dist/react.browser.mjs +1 -1
  526. package/dist/react.browser.mjs.map +1 -1
  527. package/dist/react.d.mts +2 -2
  528. package/dist/react.d.ts +2 -2
  529. package/dist/react.js +1 -1
  530. package/dist/react.js.map +1 -1
  531. package/dist/react.mjs +1 -1
  532. package/dist/react.mjs.map +1 -1
  533. package/dist/types/blocks/auth.d.ts +45 -0
  534. package/dist/types/blocks/brand.d.ts +11 -2
  535. package/dist/types/blocks/create.d.ts +11 -4
  536. package/dist/types/blocks/doctor.d.ts +1 -0
  537. package/dist/types/blocks/flows.d.ts +7 -1
  538. package/dist/types/blocks/orgBrand.d.ts +34 -0
  539. package/dist/types/cli.d.ts +3 -0
  540. package/dist/types/version.d.ts +2 -2
  541. package/docs/api/desk.d.ts +2 -2
  542. package/docs/api/desk.md +3 -3
  543. package/docs/api/forms.md +1 -1
  544. package/package.json +1 -1
  545. package/stacks/6sense/pages/companies.tsx.tmpl +21 -0
  546. package/stacks/6sense/pages/contacts.tsx.tmpl +21 -0
  547. package/stacks/6sense/pages/tasks.tsx.tmpl +19 -0
  548. package/stacks/6sense.json +37 -4
  549. package/stacks/apollo/pages/calls.tsx.tmpl +23 -0
  550. package/stacks/apollo/pages/campaigns.tsx.tmpl +27 -0
  551. package/stacks/apollo/pages/companies.tsx.tmpl +19 -36
  552. package/stacks/apollo/pages/contacts.tsx.tmpl +35 -95
  553. package/stacks/apollo/pages/deals.tsx.tmpl +17 -0
  554. package/stacks/apollo/pages/inbox-contact.tsx.tmpl +13 -0
  555. package/stacks/apollo/pages/lists.tsx.tmpl +24 -0
  556. package/stacks/apollo/pages/meetings.tsx.tmpl +13 -0
  557. package/stacks/apollo/pages/sequences.tsx.tmpl +18 -0
  558. package/stacks/apollo/pages/tasks.tsx.tmpl +20 -0
  559. package/stacks/apollo.json +68 -9
  560. package/stacks/calendly/pages/companies.tsx.tmpl +19 -0
  561. package/stacks/calendly/pages/contacts.tsx.tmpl +21 -0
  562. package/stacks/calendly/pages/meetings.tsx.tmpl +13 -0
  563. package/stacks/calendly/pages/tasks.tsx.tmpl +19 -0
  564. package/stacks/calendly.json +8 -4
  565. package/stacks/clay/pages/companies.tsx.tmpl +17 -1
  566. package/stacks/clay/pages/contacts.tsx.tmpl +14 -0
  567. package/stacks/clay/pages/lists.tsx.tmpl +24 -0
  568. package/stacks/clay/pages/tasks.tsx.tmpl +19 -0
  569. package/stacks/clay.json +16 -3
  570. package/stacks/gong/pages/calls.tsx.tmpl +23 -0
  571. package/stacks/gong/pages/companies.tsx.tmpl +22 -0
  572. package/stacks/gong/pages/contacts.tsx.tmpl +34 -0
  573. package/stacks/gong/pages/lists.tsx.tmpl +12 -0
  574. package/stacks/gong/pages/meetings.tsx.tmpl +13 -0
  575. package/stacks/gong/pages/tasks.tsx.tmpl +19 -0
  576. package/stacks/gong.json +23 -6
  577. package/stacks/hootsuite/pages/companies.tsx.tmpl +22 -0
  578. package/stacks/hootsuite/pages/contacts.tsx.tmpl +30 -0
  579. package/stacks/hootsuite/pages/lists.tsx.tmpl +12 -0
  580. package/stacks/hootsuite/pages/tasks.tsx.tmpl +19 -0
  581. package/stacks/hootsuite.json +19 -4
  582. package/stacks/hubspot/pages/campaigns.tsx.tmpl +30 -0
  583. package/stacks/hubspot/pages/companies.tsx.tmpl +16 -35
  584. package/stacks/hubspot/pages/contacts.tsx.tmpl +35 -95
  585. package/stacks/hubspot/pages/deals.tsx.tmpl +14 -1
  586. package/stacks/hubspot/pages/forms.tsx.tmpl +36 -0
  587. package/stacks/hubspot/pages/inbox.tsx.tmpl +12 -1
  588. package/stacks/hubspot/pages/lifecycle.tsx.tmpl +23 -0
  589. package/stacks/hubspot/pages/lists.tsx.tmpl +12 -0
  590. package/stacks/hubspot/pages/meetings.tsx.tmpl +13 -0
  591. package/stacks/hubspot/pages/sequences.tsx.tmpl +18 -0
  592. package/stacks/hubspot/pages/tasks.tsx.tmpl +20 -0
  593. package/stacks/hubspot/pages/web-analytics.tsx.tmpl +14 -0
  594. package/stacks/hubspot.json +66 -7
  595. package/stacks/intercom/pages/companies.tsx.tmpl +19 -0
  596. package/stacks/intercom/pages/contacts.tsx.tmpl +21 -0
  597. package/stacks/intercom/pages/inbox-contact.tsx.tmpl +13 -0
  598. package/stacks/intercom/pages/tasks.tsx.tmpl +19 -0
  599. package/stacks/intercom.json +18 -4
  600. package/stacks/mailchimp/pages/companies.tsx.tmpl +22 -0
  601. package/stacks/mailchimp/pages/contacts.tsx.tmpl +30 -0
  602. package/stacks/mailchimp/pages/forms.tsx.tmpl +36 -0
  603. package/stacks/mailchimp/pages/lists.tsx.tmpl +12 -0
  604. package/stacks/mailchimp/pages/tasks.tsx.tmpl +19 -0
  605. package/stacks/mailchimp.json +22 -6
  606. package/stacks/outreach/pages/calls.tsx.tmpl +23 -0
  607. package/stacks/outreach/pages/campaigns.tsx.tmpl +27 -0
  608. package/stacks/outreach/pages/companies.tsx.tmpl +22 -0
  609. package/stacks/outreach/pages/contacts.tsx.tmpl +29 -66
  610. package/stacks/outreach/pages/inbox-contact.tsx.tmpl +13 -0
  611. package/stacks/outreach/pages/lists.tsx.tmpl +12 -0
  612. package/stacks/outreach/pages/meetings.tsx.tmpl +13 -0
  613. package/stacks/outreach/pages/sequences.tsx.tmpl +18 -0
  614. package/stacks/outreach/pages/tasks.tsx.tmpl +19 -0
  615. package/stacks/outreach.json +38 -9
  616. package/stacks/pipedrive/pages/companies.tsx.tmpl +11 -35
  617. package/stacks/pipedrive/pages/contacts.tsx.tmpl +17 -35
  618. package/stacks/pipedrive/pages/deals.tsx.tmpl +10 -1
  619. package/stacks/pipedrive/pages/inbox.tsx.tmpl +12 -1
  620. package/stacks/pipedrive/pages/meetings.tsx.tmpl +13 -0
  621. package/stacks/pipedrive/pages/tasks.tsx.tmpl +20 -0
  622. package/stacks/pipedrive.json +14 -2
  623. package/stacks/salesforce/pages/companies.tsx.tmpl +16 -35
  624. package/stacks/salesforce/pages/contacts.tsx.tmpl +26 -35
  625. package/stacks/salesforce/pages/deals.tsx.tmpl +14 -1
  626. package/stacks/salesforce/pages/lifecycle.tsx.tmpl +23 -0
  627. package/stacks/salesforce/pages/lists.tsx.tmpl +12 -0
  628. package/stacks/salesforce/pages/tasks.tsx.tmpl +20 -0
  629. package/stacks/salesforce.json +17 -3
  630. package/stacks/zoominfo/pages/companies.tsx.tmpl +17 -1
  631. package/stacks/zoominfo/pages/contacts.tsx.tmpl +16 -0
  632. package/stacks/zoominfo/pages/lists.tsx.tmpl +24 -0
  633. package/stacks/zoominfo/pages/tasks.tsx.tmpl +19 -0
  634. package/stacks/zoominfo.json +36 -3
  635. package/styles/styles.css +1 -1
  636. package/templates/auth/auth-route.ts.tmpl +16 -0
  637. package/templates/auth/g8.auth.anonymous.ts.tmpl +15 -0
  638. package/templates/auth/g8.auth.basic.ts.tmpl +17 -0
  639. package/templates/auth/g8.auth.jwt.ts.tmpl +23 -0
  640. package/templates/auth/g8.auth.password.ts.tmpl +18 -0
  641. package/templates/auth/g8.auth.session.ts.tmpl +23 -0
  642. package/templates/auth/middleware.ts.tmpl +14 -0
  643. package/templates/next-app/README.md.tmpl +5 -0
  644. package/templates/next-app/app/globals.css.tmpl +349 -64
  645. package/templates/next-app/components/app-shell.tsx.tmpl +6 -0
  646. package/templates/next-app/components/shell/quick-jump.tsx.tmpl +4 -0
@@ -9,7 +9,13 @@
9
9
  "column recipes: AI prompt with {{column}} placeholders, enrichment waterfall presets, formulas, plain columns, target-field mapping",
10
10
  "runs are quoted for free, confirmed with the exact credits, started with the quote as the cap and followed to a final receipt",
11
11
  "unlock locked rows (1 credit each), send rows to a list, delete rows",
12
- "finished WorkbenchScreen page"
12
+ "finished WorkbenchScreen page",
13
+ "tabs on an opened table: Data, Automation, Import, Connections",
14
+ "automation: auto-enrich with its passes listed, a schedule (hourly, daily, weekly or cron), event triggers (run AI, recompute formulas, send to a list, call a webhook) and pipelines of recipe columns; anything that arms spend is confirmed and never shows an invented price",
15
+ "import a datafile with an AI-suggested column mapping, or pull records from a connected CRM",
16
+ "connections that copy new rows into another workbench, synced on demand",
17
+ "enroll selected rows in a running sequence (locked rows skipped, the confirm counts exactly who is emailed)",
18
+ "filter and sort rows, delete a column, rename the workbench, locked-row count"
13
19
  ],
14
20
  "dependsOn": [
15
21
  "enrichment",
@@ -19,25 +25,48 @@
19
25
  "add_workbench_column_workbench_tables__table_id__columns_post",
20
26
  "add_workbench_row_workbench_tables__table_id__rows_post",
21
27
  "bulk_delete_workbench_rows_workbench_tables__table_id__rows_bulk_delete_post",
28
+ "create_list_lists_post",
29
+ "create_workbench_connection_workbench_tables__table_id__connections_post",
22
30
  "create_workbench_formula_columns_workbench_tables__table_id__formula_columns_post",
31
+ "create_workbench_pipeline_workbench_tables__table_id__pipelines_post",
23
32
  "create_workbench_table_workbench_tables_post",
33
+ "create_workbench_trigger_workbench_tables__table_id__triggers_post",
34
+ "delete_workbench_column_workbench_tables__table_id__columns__column_id__delete",
35
+ "delete_workbench_connection_workbench_tables__table_id__connections__connection_id__delete",
36
+ "delete_workbench_pipeline_workbench_tables__table_id__pipelines__pipeline_id__delete",
37
+ "delete_workbench_schedule_workbench_tables__table_id__schedule_delete",
24
38
  "delete_workbench_table_workbench_tables__table_id__delete",
39
+ "delete_workbench_trigger_workbench_tables__table_id__triggers__trigger_id__delete",
25
40
  "estimate_workbench_scraper_credits_workbench_scraper_credit_estimate_get",
26
41
  "export_workbench_table_workbench_tables__table_id__export_post",
27
42
  "get_workbench_analytics_workbench_tables__table_id__analytics_get",
28
43
  "get_workbench_history_workbench_tables__table_id__history_get",
44
+ "get_workbench_locked_row_count_workbench_tables__table_id__locked_row_count_get",
45
+ "get_workbench_mapping_suggestion_workbench_tables__table_id__suggest_mappings__job_id__get",
46
+ "get_workbench_pipeline_workbench_tables__table_id__pipelines__pipeline_id__get",
29
47
  "get_workbench_row_workbench_tables__table_id__rows__row_id__get",
48
+ "get_workbench_schedule_workbench_tables__table_id__schedule_get",
30
49
  "get_workbench_scraper_run_workbench_tables__table_id__scraper_runs__run_id__get",
31
50
  "get_workbench_table_workbench_tables__table_id__get",
51
+ "import_workbench_datafile_workbench_tables__table_id__import_datafile_post",
52
+ "import_workbench_from_crm_workbench_tables__table_id__import_crm_post",
32
53
  "import_workbench_from_search_workbench_tables__table_id__import_search_post",
54
+ "list_crm_syncs_crm_syncs_get",
33
55
  "list_enrichment_providers_enrichment_providers_get",
56
+ "list_lists_lists_get",
57
+ "list_sequences_sequences_get",
34
58
  "list_workbench_columns_workbench_tables__table_id__columns_get",
59
+ "list_workbench_connections_workbench_tables__table_id__connections_get",
60
+ "list_workbench_enrichment_configs_workbench_tables__table_id__enrichment_configs_get",
61
+ "list_workbench_pipelines_workbench_tables__table_id__pipelines_get",
35
62
  "list_workbench_rows_workbench_tables__table_id__rows_get",
36
63
  "list_workbench_tables_workbench_tables_get",
37
64
  "list_workbench_target_fields_workbench_target_fields_get",
65
+ "list_workbench_triggers_workbench_tables__table_id__triggers_get",
38
66
  "map_workbench_column_workbench_tables__table_id__columns__column_id__mapping_put",
39
67
  "paste_import_workbench_rows_workbench_tables__table_id__import_paste_post",
40
68
  "preview_workbench_search_import_workbench_tables__table_id__import_search_preview_post",
69
+ "query_workbench_rows_workbench_tables__table_id__rows_query_post",
41
70
  "quote_workbench_ai_run_workbench_tables__table_id__ai_validate_credits_post",
42
71
  "quote_workbench_unlock_workbench_tables__table_id__unlock_quote_post",
43
72
  "quote_workbench_waterfall_run_workbench_tables__table_id__waterfall_configs__column_id__validate_credits_post",
@@ -47,8 +76,16 @@
47
76
  "run_workbench_waterfall_workbench_tables__table_id__waterfall_configs__column_id__run_post",
48
77
  "save_workbench_column_ai_config_workbench_tables__table_id__columns__col_id__ai_config_put",
49
78
  "save_workbench_waterfall_workbench_tables__table_id__waterfall_configs_post",
79
+ "send_workbench_rows_to_sequence_workbench_tables__table_id__send_to_sequence_post",
80
+ "set_workbench_auto_enrich_workbench_tables__table_id__auto_enrich_put",
81
+ "set_workbench_schedule_workbench_tables__table_id__schedule_put",
82
+ "suggest_workbench_mappings_workbench_tables__table_id__suggest_mappings_post",
83
+ "sync_workbench_connection_workbench_tables__table_id__connections__connection_id__sync_post",
50
84
  "unlock_workbench_rows_workbench_tables__table_id__unlock_rows_post",
51
- "update_workbench_row_workbench_tables__table_id__rows__row_id__patch"
85
+ "update_workbench_pipeline_workbench_tables__table_id__pipelines__pipeline_id__put",
86
+ "update_workbench_row_workbench_tables__table_id__rows__row_id__patch",
87
+ "update_workbench_table_workbench_tables__table_id__put",
88
+ "update_workbench_trigger_workbench_tables__table_id__triggers__trigger_id__put"
52
89
  ],
53
90
  "components": [
54
91
  {
@@ -71,14 +108,17 @@
71
108
  "file": "components/workbench-grid.tsx",
72
109
  "purpose": "The table itself: rows by columns, selection, double-click cell edit, run buttons on recipe columns, and the panels for adding rows, columns and acting on the selection.",
73
110
  "operations": [
111
+ "delete_workbench_column_workbench_tables__table_id__columns__column_id__delete",
74
112
  "get_workbench_table_workbench_tables__table_id__get",
75
113
  "list_workbench_columns_workbench_tables__table_id__columns_get",
76
114
  "list_workbench_rows_workbench_tables__table_id__rows_get",
115
+ "query_workbench_rows_workbench_tables__table_id__rows_query_post",
77
116
  "update_workbench_row_workbench_tables__table_id__rows__row_id__patch"
78
117
  ],
79
118
  "tiers": [
80
119
  "read",
81
- "write"
120
+ "write",
121
+ "destructive"
82
122
  ]
83
123
  },
84
124
  {
@@ -153,6 +193,7 @@
153
193
  "operations": [
154
194
  "create_workbench_table_workbench_tables_post",
155
195
  "delete_workbench_table_workbench_tables__table_id__delete",
196
+ "get_workbench_locked_row_count_workbench_tables__table_id__locked_row_count_get",
156
197
  "list_workbench_tables_workbench_tables_get"
157
198
  ],
158
199
  "tiers": [
@@ -189,6 +230,151 @@
189
230
  "read",
190
231
  "write"
191
232
  ]
233
+ },
234
+ {
235
+ "name": "WorkbenchTriggers",
236
+ "file": "components/workbench-triggers.tsx",
237
+ "purpose": "Event triggers: when a row arrives, an AI column finishes or a status changes, run the AI columns, recompute formulas, send the row to a list or call a webhook. Switch, create (arming an AI trigger is confirmed with no invented price) and delete (confirmed).",
238
+ "operations": [
239
+ "list_workbench_triggers_workbench_tables__table_id__triggers_get",
240
+ "create_workbench_trigger_workbench_tables__table_id__triggers_post",
241
+ "update_workbench_trigger_workbench_tables__table_id__triggers__trigger_id__put",
242
+ "delete_workbench_trigger_workbench_tables__table_id__triggers__trigger_id__delete",
243
+ "list_lists_lists_get",
244
+ "create_list_lists_post"
245
+ ],
246
+ "tiers": [
247
+ "read",
248
+ "write",
249
+ "billable",
250
+ "destructive"
251
+ ]
252
+ },
253
+ {
254
+ "name": "WorkbenchSchedule",
255
+ "file": "components/workbench-schedule.tsx",
256
+ "purpose": "Re-run the workbench on a timer (hourly, daily, weekly or a cron whose minute is a plain number) in UTC: the live schedule with its scheduler state and next and last run, set or edit it (saved stopped; keeps its action_config; formula scope, CRM and limit are collected; starting an AI schedule is priced from the API's run-all quote and sends the quoted cap) and remove it (confirmed).",
257
+ "operations": [
258
+ "delete_workbench_schedule_workbench_tables__table_id__schedule_delete",
259
+ "get_workbench_schedule_workbench_tables__table_id__schedule_get",
260
+ "list_crm_syncs_crm_syncs_get",
261
+ "quote_workbench_ai_run_workbench_tables__table_id__ai_validate_credits_post",
262
+ "set_workbench_schedule_workbench_tables__table_id__schedule_put"
263
+ ],
264
+ "tiers": [
265
+ "read",
266
+ "billable",
267
+ "destructive"
268
+ ]
269
+ },
270
+ {
271
+ "name": "WorkbenchPipelines",
272
+ "file": "components/workbench-pipelines.tsx",
273
+ "purpose": "Ordered runs of the table's AI, waterfall and formula columns that start on an event: list with a switch each, read a pipeline's steps, create one (saved switched off), enable (confirmed when it has AI or provider steps) and delete (confirmed).",
274
+ "operations": [
275
+ "list_workbench_pipelines_workbench_tables__table_id__pipelines_get",
276
+ "get_workbench_pipeline_workbench_tables__table_id__pipelines__pipeline_id__get",
277
+ "create_workbench_pipeline_workbench_tables__table_id__pipelines_post",
278
+ "update_workbench_pipeline_workbench_tables__table_id__pipelines__pipeline_id__put",
279
+ "delete_workbench_pipeline_workbench_tables__table_id__pipelines__pipeline_id__delete"
280
+ ],
281
+ "tiers": [
282
+ "read",
283
+ "billable",
284
+ "destructive"
285
+ ]
286
+ },
287
+ {
288
+ "name": "WorkbenchAutoEnrich",
289
+ "file": "components/workbench-auto-enrich.tsx",
290
+ "purpose": "The auto-enrich switch with the enrichment passes it would run listed first; switching on confirms the exact pass count, switching off is immediate.",
291
+ "operations": [
292
+ "list_workbench_enrichment_configs_workbench_tables__table_id__enrichment_configs_get",
293
+ "set_workbench_auto_enrich_workbench_tables__table_id__auto_enrich_put"
294
+ ],
295
+ "tiers": [
296
+ "read",
297
+ "billable"
298
+ ]
299
+ },
300
+ {
301
+ "name": "WorkbenchAutomation",
302
+ "file": "components/workbench-automation.tsx",
303
+ "purpose": "Auto-enrich, schedule, triggers and pipelines for one workbench, stacked. A composer.",
304
+ "operations": [],
305
+ "tiers": []
306
+ },
307
+ {
308
+ "name": "WorkbenchSendToSequence",
309
+ "file": "components/workbench-send-to-sequence.tsx",
310
+ "purpose": "Enroll selected rows in a running sequence: pick the sequence by name and the list to save to, confirm the exact recipient count (locked rows skipped, never an omitted row list).",
311
+ "operations": [
312
+ "list_sequences_sequences_get",
313
+ "send_workbench_rows_to_sequence_workbench_tables__table_id__send_to_sequence_post",
314
+ "list_lists_lists_get",
315
+ "create_list_lists_post"
316
+ ],
317
+ "tiers": [
318
+ "read",
319
+ "write",
320
+ "external"
321
+ ]
322
+ },
323
+ {
324
+ "name": "WorkbenchConnections",
325
+ "file": "components/workbench-connections.tsx",
326
+ "purpose": "Copy new rows into another workbench: connections in both directions by workbench name, create (optionally some columns only), sync an outgoing one, delete (confirmed).",
327
+ "operations": [
328
+ "list_workbench_connections_workbench_tables__table_id__connections_get",
329
+ "list_workbench_tables_workbench_tables_get",
330
+ "create_workbench_connection_workbench_tables__table_id__connections_post",
331
+ "sync_workbench_connection_workbench_tables__table_id__connections__connection_id__sync_post",
332
+ "delete_workbench_connection_workbench_tables__table_id__connections__connection_id__delete"
333
+ ],
334
+ "tiers": [
335
+ "read",
336
+ "write",
337
+ "destructive"
338
+ ]
339
+ },
340
+ {
341
+ "name": "WorkbenchDatafileImport",
342
+ "file": "components/workbench-datafile-import.tsx",
343
+ "purpose": "Import the rows of an already-uploaded datafile, with an AI-suggested header-to-column mapping (one confirmed AI call, polled to the end) that the person can edit.",
344
+ "operations": [
345
+ "suggest_workbench_mappings_workbench_tables__table_id__suggest_mappings_post",
346
+ "get_workbench_mapping_suggestion_workbench_tables__table_id__suggest_mappings__job_id__get",
347
+ "import_workbench_datafile_workbench_tables__table_id__import_datafile_post"
348
+ ],
349
+ "tiers": [
350
+ "read",
351
+ "write",
352
+ "billable"
353
+ ]
354
+ },
355
+ {
356
+ "name": "WorkbenchCrmImport",
357
+ "file": "components/workbench-crm-import.tsx",
358
+ "purpose": "Pull contacts or companies from a connected CRM into the workbench: only connected CRMs offered, a 1 to 10,000 limit, a confirm that says nobody is contacted; a link-out when none is connected.",
359
+ "operations": [
360
+ "list_crm_syncs_crm_syncs_get",
361
+ "import_workbench_from_crm_workbench_tables__table_id__import_crm_post"
362
+ ],
363
+ "tiers": [
364
+ "read",
365
+ "external"
366
+ ]
367
+ },
368
+ {
369
+ "name": "WorkbenchTableSettings",
370
+ "file": "components/workbench-table-settings.tsx",
371
+ "purpose": "Rename a workbench or change its description in a side sheet; sends only what changed.",
372
+ "operations": [
373
+ "update_workbench_table_workbench_tables__table_id__put"
374
+ ],
375
+ "tiers": [
376
+ "write"
377
+ ]
192
378
  }
193
379
  ],
194
380
  "hooks": [
@@ -200,6 +386,14 @@
200
386
  "get_workbench_table_workbench_tables__table_id__get",
201
387
  "list_workbench_columns_workbench_tables__table_id__columns_get"
202
388
  ]
389
+ },
390
+ {
391
+ "name": "useConnectedCrms",
392
+ "file": "hooks/use-connected-crms.ts",
393
+ "purpose": "The connected CRMs (GET /crm-syncs rows that carry a connection id) and crmLabel, shared by the CRM import and the CRM schedule.",
394
+ "operations": [
395
+ "list_crm_syncs_crm_syncs_get"
396
+ ]
203
397
  }
204
398
  ],
205
399
  "lib": [
@@ -210,6 +404,14 @@
210
404
  {
211
405
  "file": "lib/waterfall-presets.ts",
212
406
  "purpose": "Waterfall presets (work email, mobile phone, LinkedIn URL, company phone) copied from graph8's own templates, and buildWaterfallConfig for the save body."
407
+ },
408
+ {
409
+ "file": "lib/automation-types.ts",
410
+ "purpose": "Trigger, schedule, pipeline, connection and mapping shapes plus the rules copied from the handlers (webhook and export config checks, cron validity, which actions spend, which sequences accept people)."
411
+ },
412
+ {
413
+ "file": "lib/api-status.ts",
414
+ "purpose": "isNotFound: a 404 is 'none yet' on a read and 'already gone' on a delete."
213
415
  }
214
416
  ],
215
417
  "recipes": [
@@ -244,7 +446,7 @@
244
446
  {
245
447
  "id": "proxy-allowlist",
246
448
  "where": "app",
247
- "description": "allowedPrefixes in the /api/g8 route includes `workbench`, `enrichment` and `lists`.",
449
+ "description": "allowedPrefixes in the /api/g8 route includes `workbench`, `enrichment`, `lists`, `sequences` (the sequence picker) and `crm-syncs` (the CRM import list).",
248
450
  "verify": "GET /api/g8/workbench/tables returns 200 when signed in."
249
451
  },
250
452
  {
@@ -262,10 +464,12 @@
262
464
  ],
263
465
  "scopes": [
264
466
  "enrichment:read",
467
+ "integrations:read",
265
468
  "lists:delete",
266
469
  "lists:read",
267
470
  "lists:run",
268
- "lists:write"
471
+ "lists:write",
472
+ "sequences:read"
269
473
  ],
270
474
  "defaults": [
271
475
  {
@@ -297,6 +501,31 @@
297
501
  "decision": "Where finished rows go",
298
502
  "default": "A list picked or created in the row actions panel",
299
503
  "askHuman": false
504
+ },
505
+ {
506
+ "decision": "New pipeline and new schedule",
507
+ "default": "Saved switched OFF; starting one is a separate step, and a confirm when it would charge credits",
508
+ "askHuman": false
509
+ },
510
+ {
511
+ "decision": "Trigger that runs AI columns",
512
+ "default": "Created ON like any trigger, but only after a confirm that names no price (none is published); every other trigger action needs no confirm",
513
+ "askHuman": true
514
+ },
515
+ {
516
+ "decision": "Rows sent to a sequence",
517
+ "default": "Only the selected, unlocked rows; the confirm counts exactly those people; never an omitted row list (that would send every row)",
518
+ "askHuman": false
519
+ },
520
+ {
521
+ "decision": "CRM import size",
522
+ "default": "100 records at most (the API allows 1 to 10,000)",
523
+ "askHuman": false
524
+ },
525
+ {
526
+ "decision": "Datafile upload",
527
+ "default": "Not in the developer API: the person pastes the id of a file uploaded in the platform app",
528
+ "askHuman": false
300
529
  }
301
530
  ],
302
531
  "peerDependencies": {
@@ -139,7 +139,7 @@ export function ColumnRecipeEditor({ tableId, columns, entityType = "contact", o
139
139
  );
140
140
  })}
141
141
  </fieldset>
142
- {unmapped.length ? <p role="alert" className="text-sm text-amber-700">Not mapped yet: {unmapped.join(", ")}. Use the Map columns tab, or the steps that need them find nothing.</p> : null}
142
+ {unmapped.length ? <p role="alert" className="text-sm text-warning-foreground">Not mapped yet: {unmapped.join(", ")}. Use the Map columns tab, or the steps that need them find nothing.</p> : null}
143
143
  {addWaterfall.error ? <ApiError error={addWaterfall.error} title="Could not save the enrichment column" /> : null}
144
144
  <div><Button size="sm" loading={addWaterfall.loading} disabled={steps.length === 0} onClick={() => void addWaterfall.mutate(undefined)}>Save enrichment column</Button></div>
145
145
  </div>
@@ -94,7 +94,7 @@ export function RunProgress({ tableId, target, rowIds, label = "this column", on
94
94
  if (job) {
95
95
  return (
96
96
  <div className={`flex flex-col gap-2 rounded-md border p-3 ${className ?? ""}`} role="status">
97
- <h3 className="text-sm font-semibold">{poll.done ? `Run ${receipt?.status ?? "finished"}` : "Running..."}</h3>
97
+ <h3 className="text-sm font-medium">{poll.done ? `Run ${receipt?.status ?? "finished"}` : "Running..."}</h3>
98
98
  <p className="text-sm text-muted-foreground">
99
99
  {receipt ? `${receipt.credits_charged ?? 0} credits charged so far.` : "Queued. The first update can take a few seconds."}
100
100
  {Object.entries(distribution).length ? ` Rows: ${Object.entries(distribution).map(([k, v]) => `${v} ${k}`).join(", ")}.` : ""}
@@ -0,0 +1,88 @@
1
+ "use client";
2
+
3
+ /**
4
+ * WorkbenchAutoEnrich: the switch that enriches every row as it arrives, with the list of enrichment passes it would run
5
+ * so nobody switches it on blind. Switching ON confirms the exact number of passes (read from the table) and says graph8
6
+ * publishes no total up front; switching OFF is immediate. It will not switch on when there is nothing configured.
7
+ *
8
+ * SDK operations, in order:
9
+ * 1. listWorkbenchEnrichmentConfigs GET /workbench/tables/{table_id}/enrichment-configs (read; the passes auto-enrich would run)
10
+ * 2. setWorkbenchAutoEnrich PUT /workbench/tables/{table_id}/auto-enrich { enabled, batch_size }
11
+ * (billable tier: ON removes the human from the loop, every arriving row then costs credits; ConfirmSpendDialog)
12
+ */
13
+
14
+ import { useState } from "react";
15
+ import { Sparkles } from "lucide-react";
16
+ import { Input, Label, Skeleton, Switch } from "@graph8/sdk/ui";
17
+ import { ApiError } from "@/g8/components/api-error";
18
+ import { ConfirmSpendDialog } from "@/g8/components/confirm-spend-dialog";
19
+ import { EmptyState } from "@/g8/components/empty-state";
20
+ import { SectionCard } from "@/g8/components/screen/section-card";
21
+ import { StatusPill } from "@/g8/components/screen/status-pill";
22
+ import { useG8Mutation } from "@/g8/hooks/use-g8-mutation";
23
+ import { useG8Query } from "@/g8/hooks/use-g8-query";
24
+ import { g8Get, g8Put } from "@/g8/lib/g8-client";
25
+ import { configName, rowsOf } from "../lib/automation-types";
26
+ import type { EnrichmentConfig } from "../lib/automation-types";
27
+
28
+ export interface WorkbenchAutoEnrichProps {
29
+ tableId: string;
30
+ /** The table's current setting (`auto_enrich` from getWorkbenchTable). */
31
+ autoEnrich?: boolean | null;
32
+ /** Called after the switch was saved so the caller can re-read the table. */
33
+ onChanged?: () => void;
34
+ className?: string;
35
+ }
36
+
37
+ const MIN_BATCH = 1;
38
+ const MAX_BATCH = 1000;
39
+ const clampBatch = (n: number) => (Number.isFinite(n) ? Math.min(MAX_BATCH, Math.max(MIN_BATCH, Math.round(n))) : 10);
40
+
41
+ export function WorkbenchAutoEnrich({ tableId, autoEnrich, onChanged, className }: WorkbenchAutoEnrichProps) {
42
+ const configs = useG8Query(async (signal) => rowsOf<EnrichmentConfig>((await g8Get(`/workbench/tables/${tableId}/enrichment-configs`, undefined, { signal })).data), [tableId]);
43
+ const [on, setOn] = useState<boolean | null>(null);
44
+ const [batch, setBatch] = useState(10);
45
+ const [confirming, setConfirming] = useState(false);
46
+ const enabled = on ?? autoEnrich === true;
47
+ const save = useG8Mutation(async (v: { enabled: boolean }) => (await g8Put(`/workbench/tables/${tableId}/auto-enrich`, { enabled: v.enabled, batch_size: clampBatch(batch) })).data, {
48
+ onSuccess: (_r, v) => { setOn(v.enabled); setConfirming(false); onChanged?.(); },
49
+ onError: () => setConfirming(false),
50
+ });
51
+ const items = configs.data ?? [];
52
+ const loaded = configs.data !== undefined;
53
+
54
+ return (
55
+ <SectionCard className={className} title="Auto-enrich" icon={<Sparkles aria-hidden />}
56
+ description="Enrich every row the moment it arrives, from an import, a webhook, a scraper or a routing rule."
57
+ actions={<StatusPill tone={enabled ? "warning" : "neutral"} dot>{enabled ? "On" : "Off"}</StatusPill>}>
58
+ {configs.error ? <ApiError error={configs.error} title="Could not load the enrichment passes" onRetry={() => void configs.refetch()} /> : null}
59
+ {save.error ? <ApiError error={save.error} title="Could not change auto-enrich" /> : null}
60
+ {configs.loading && !loaded ? <Skeleton className="h-12 w-full" aria-label="Loading enrichment passes" /> : null}
61
+ {loaded && items.length === 0 ? (
62
+ <EmptyState compact icon={<Sparkles strokeWidth={1.5} />} title="Nothing to run yet" description="Auto-enrich needs at least one AI or waterfall column. Add one to this workbench first." />
63
+ ) : null}
64
+ {items.length ? (
65
+ <ul className="mb-3 flex flex-col gap-1">
66
+ {items.map((c, i) => (
67
+ <li key={String(c.id ?? i)} className="flex items-center gap-2 text-sm"><span className="truncate">{configName(c)}</span>{c.type ? <span className="text-xs text-text-color-muted">{c.type.replace(/_/g, " ")}</span> : null}</li>
68
+ ))}
69
+ </ul>
70
+ ) : null}
71
+ <div className="flex flex-wrap items-end gap-4">
72
+ <div className="flex items-center gap-2">
73
+ <Switch id={`wb-auto-${tableId}`} aria-label="Enrich new rows automatically" checked={enabled} disabled={save.loading || (!enabled && (!loaded || items.length === 0))}
74
+ onCheckedChange={(next) => { if (next) setConfirming(true); else void save.mutate({ enabled: false }); }} />
75
+ <Label htmlFor={`wb-auto-${tableId}`}>Enrich new rows automatically</Label>
76
+ </div>
77
+ <div className="flex flex-col gap-1">
78
+ <Label htmlFor={`wb-batch-${tableId}`}>Rows per batch</Label>
79
+ <Input id={`wb-batch-${tableId}`} className="w-28" type="number" min={MIN_BATCH} max={MAX_BATCH} value={batch} disabled={enabled} onChange={(e) => setBatch(clampBatch(Number(e.target.value)))} />
80
+ {enabled ? <p className="text-xs text-text-color-muted">Turn it off to change the batch size.</p> : null}
81
+ </div>
82
+ </div>
83
+ <ConfirmSpendDialog open={confirming} tier="billable" title="Turn on auto-enrich"
84
+ description={`${items.length} enrichment ${items.length === 1 ? "pass" : "passes"} will run on every row that arrives, in batches of ${clampBatch(batch)}, with nobody in the loop. Each row costs credits. No total is published up front, so none is shown.`}
85
+ confirmLabel="Turn on auto-enrich" confirming={save.loading} onConfirm={() => void save.mutate({ enabled: true })} onCancel={() => setConfirming(false)} />
86
+ </SectionCard>
87
+ );
88
+ }
@@ -0,0 +1,36 @@
1
+ "use client";
2
+
3
+ /**
4
+ * WorkbenchAutomation: everything that keeps a workbench running by itself, stacked in one place: auto-enrich, the
5
+ * schedule, event triggers and pipelines. A composer; each part declares and confirms its own operations.
6
+ *
7
+ * Composes: WorkbenchAutoEnrich, WorkbenchSchedule, WorkbenchTriggers, WorkbenchPipelines (see each file for its operations).
8
+ */
9
+
10
+ import { WorkbenchAutoEnrich } from "./workbench-auto-enrich";
11
+ import { WorkbenchPipelines } from "./workbench-pipelines";
12
+ import { WorkbenchSchedule } from "./workbench-schedule";
13
+ import { WorkbenchTriggers } from "./workbench-triggers";
14
+ import type { WorkbenchColumn } from "../lib/workbench-types";
15
+
16
+ export interface WorkbenchAutomationProps {
17
+ tableId: string;
18
+ columns?: WorkbenchColumn[];
19
+ entityType?: "contact" | "company";
20
+ /** The table's `auto_enrich` flag. */
21
+ autoEnrich?: boolean | null;
22
+ /** Called after auto-enrich was switched so the caller can re-read the table. */
23
+ onChanged?: () => void;
24
+ className?: string;
25
+ }
26
+
27
+ export function WorkbenchAutomation({ tableId, columns = [], entityType = "contact", autoEnrich, onChanged, className }: WorkbenchAutomationProps) {
28
+ return (
29
+ <div className={`flex flex-col gap-4 ${className ?? ""}`}>
30
+ <WorkbenchAutoEnrich tableId={tableId} autoEnrich={autoEnrich} onChanged={onChanged} />
31
+ <WorkbenchSchedule tableId={tableId} columns={columns} />
32
+ <WorkbenchTriggers tableId={tableId} columns={columns} entityType={entityType} />
33
+ <WorkbenchPipelines tableId={tableId} columns={columns} />
34
+ </div>
35
+ );
36
+ }
@@ -0,0 +1,136 @@
1
+ "use client";
2
+
3
+ /**
4
+ * WorkbenchConnections: copy the new rows of this workbench into another workbench, automatically-ish. A connection is an
5
+ * append-only link from a source workbench to a destination (optionally copying only some columns). Lists the connections in
6
+ * both directions by workbench NAME, creates one in a side sheet, syncs an outgoing one on demand, and deletes with a confirm.
7
+ *
8
+ * SDK operations, in order:
9
+ * 1. listWorkbenchConnections GET /workbench/tables/{table_id}/connections (read; connections where this table is source OR destination)
10
+ * 2. listWorkbenchTables GET /workbench/tables?limit=100 (read; turns ids into names and fills the destination picker)
11
+ * 3. createWorkbenchConnection POST /workbench/tables/{table_id}/connections { destination_table_id, sync_mode: "append", field_mapping? } (write)
12
+ * 4. syncWorkbenchConnection POST /workbench/tables/{table_id}/connections/{connection_id}/sync (write; only from the SOURCE table; copies rows added since the last sync and stops at the first locked row)
13
+ * 5. deleteWorkbenchConnection DELETE /workbench/tables/{table_id}/connections/{connection_id} (destructive, ConfirmSpendDialog; rows already copied stay; a 404 means already gone)
14
+ *
15
+ * Nothing is sent outside the organisation: rows are copied between its own workbenches, so only the delete needs a confirm.
16
+ */
17
+
18
+ import { useState } from "react";
19
+ import { ArrowRightLeft } from "lucide-react";
20
+ import { Button, Label, Skeleton } from "@graph8/sdk/ui";
21
+ import { ApiError } from "@/g8/components/api-error";
22
+ import { ConfirmSpendDialog } from "@/g8/components/confirm-spend-dialog";
23
+ import { EmptyState } from "@/g8/components/empty-state";
24
+ import { FormSheet } from "@/g8/components/screen/form-sheet";
25
+ import { SectionCard } from "@/g8/components/screen/section-card";
26
+ import { StatusPill } from "@/g8/components/screen/status-pill";
27
+ import { useG8Mutation } from "@/g8/hooks/use-g8-mutation";
28
+ import { useG8Query } from "@/g8/hooks/use-g8-query";
29
+ import { g8Delete, g8Get, g8Post } from "@/g8/lib/g8-client";
30
+ import { isNotFound } from "../lib/api-status";
31
+ import { rowsOf } from "../lib/automation-types";
32
+ import type { WorkbenchConnection } from "../lib/automation-types";
33
+ import { pageItems, pageTotal } from "../lib/workbench-types";
34
+ import type { WorkbenchColumn, WorkbenchTable } from "../lib/workbench-types";
35
+
36
+ export interface WorkbenchConnectionsProps {
37
+ tableId: string;
38
+ /** This table's columns, for copying only some of them. */
39
+ columns?: WorkbenchColumn[];
40
+ className?: string;
41
+ }
42
+
43
+ const TABLE_LIMIT = 100;
44
+ const FALLBACK_NAME = "Another workbench";
45
+
46
+ export function WorkbenchConnections({ tableId, columns = [], className }: WorkbenchConnectionsProps) {
47
+ const path = `/workbench/tables/${tableId}/connections`;
48
+ const list = useG8Query(async (signal) => rowsOf<WorkbenchConnection>((await g8Get(path, undefined, { signal })).data), [tableId]);
49
+ const tables = useG8Query(async (signal) => {
50
+ const data = (await g8Get("/workbench/tables", { limit: TABLE_LIMIT }, { signal })).data;
51
+ const rows = pageItems<WorkbenchTable>(data);
52
+ return { rows, total: pageTotal(data, rows.length) };
53
+ }, [tableId]);
54
+ const [open, setOpen] = useState(false);
55
+ const [dest, setDest] = useState("");
56
+ const [only, setOnly] = useState<string[]>([]);
57
+ const [deleting, setDeleting] = useState<{ c: WorkbenchConnection; name: string } | null>(null);
58
+ const [syncingId, setSyncingId] = useState<number | null>(null);
59
+ const [notice, setNotice] = useState<string | null>(null);
60
+
61
+ const names = new Map((tables.data?.rows ?? []).map((t) => [t.id, t.name]));
62
+ const nameOf = (id?: string) => (id ? names.get(id) : undefined) ?? FALLBACK_NAME;
63
+ const destinations = (tables.data?.rows ?? []).filter((t) => t.id !== tableId);
64
+
65
+ const create = useG8Mutation(
66
+ async () => (await g8Post(path, { destination_table_id: dest, sync_mode: "append", ...(only.length ? { field_mapping: Object.fromEntries(only.map((n) => [n, n])) } : {}) })).data,
67
+ { onSuccess: () => { setOpen(false); setDest(""); setOnly([]); void list.refetch(); } },
68
+ );
69
+ const sync = useG8Mutation(async (v: { c: WorkbenchConnection; name: string }) => {
70
+ setSyncingId(v.c.id);
71
+ return { name: v.name, result: (await g8Post<{ synced_rows?: number }>(`${path}/${v.c.id}/sync`)).data };
72
+ }, {
73
+ onSuccess: ({ name, result }) => { setSyncingId(null); const n = result.synced_rows ?? 0; setNotice(`Copied ${n.toLocaleString()} new ${n === 1 ? "row" : "rows"} to ${name}.`); void list.refetch(); },
74
+ onError: () => setSyncingId(null),
75
+ });
76
+ const remove = useG8Mutation(async (c: WorkbenchConnection) => { try { await g8Delete(`${path}/${c.id}`); } catch (e) { if (!isNotFound(e)) throw e; } }, {
77
+ onSuccess: () => { setDeleting(null); void list.refetch(); },
78
+ });
79
+ const items = list.data ?? [];
80
+
81
+ return (
82
+ <SectionCard className={className} title="Connections" icon={<ArrowRightLeft aria-hidden />}
83
+ description="Copy new rows into another workbench. A sync copies what was added since the last one and stops at the first locked row."
84
+ actions={<Button size="sm" onClick={() => { create.reset(); setOpen(true); }}>New connection</Button>}>
85
+ {list.error ? <ApiError error={list.error} title="Could not load connections" onRetry={() => void list.refetch()} /> : null}
86
+ {sync.error ? <ApiError error={sync.error} title="Could not sync the connection" /> : null}
87
+ {remove.error ? <ApiError error={remove.error} title="Could not delete the connection" /> : null}
88
+ {list.loading && !list.data ? <Skeleton className="h-16 w-full" aria-label="Loading connections" /> : null}
89
+ {!list.loading && !list.error && items.length === 0 ? (
90
+ <EmptyState compact icon={<ArrowRightLeft strokeWidth={1.5} />} title="No connections yet" description="Connect this workbench to another one to copy new rows across, for example from a raw table to a cleaned one." />
91
+ ) : null}
92
+ {notice ? <p role="status" className="mb-2 text-sm text-text-color-muted">{notice}</p> : null}
93
+ <ul className="flex flex-col divide-y divide-border">
94
+ {items.map((c) => {
95
+ const outgoing = c.source_table_id === tableId;
96
+ const other = nameOf(outgoing ? c.destination_table_id : c.source_table_id);
97
+ return (
98
+ <li key={c.id} className="flex flex-wrap items-center gap-3 py-3">
99
+ <div className="min-w-0 flex-1">
100
+ <p className="flex flex-wrap items-center gap-1.5 text-sm"><span className="text-text-color-muted">{outgoing ? "Copies new rows to" : "Receives rows from"}</span><span className="truncate font-medium">{other}</span>
101
+ {c.enabled === false ? <StatusPill tone="neutral">Paused</StatusPill> : null}</p>
102
+ <p className="text-xs text-text-color-muted">{c.field_mapping && Object.keys(c.field_mapping).length ? `${Object.keys(c.field_mapping).length} chosen columns` : "All columns"}, add-only</p>
103
+ </div>
104
+ {outgoing ? <Button size="sm" variant="outline" aria-label={`Sync ${other}`} loading={syncingId === c.id} onClick={() => void sync.mutate({ c, name: other })}>Sync now</Button> : null}
105
+ <Button size="sm" variant="ghost" aria-label={`Delete connection to ${other}`} onClick={() => setDeleting({ c, name: other })}>Delete</Button>
106
+ </li>
107
+ );
108
+ })}
109
+ </ul>
110
+
111
+ <FormSheet open={open} onOpenChange={setOpen} title="New connection" description="New rows added here are copied to the workbench you pick. Nothing already in it is changed."
112
+ footer={(<><Button variant="ghost" onClick={() => setOpen(false)}>Cancel</Button><Button loading={create.loading} disabled={!dest} onClick={() => void create.mutate(undefined)}>Create connection</Button></>)}>
113
+ <div className="flex flex-col gap-3">
114
+ {tables.error ? <ApiError error={tables.error} title="Could not load workbenches" onRetry={() => void tables.refetch()} /> : null}
115
+ <div className="flex flex-col gap-1"><Label htmlFor="wbc-dest">Copy new rows to</Label>
116
+ <select id="wbc-dest" className="h-9 w-full rounded-md border border-border bg-background px-2 text-sm" value={dest} onChange={(e) => setDest(e.target.value)}>
117
+ <option value="">Choose a workbench</option>{destinations.map((t) => <option key={t.id} value={t.id}>{t.name}</option>)}</select>
118
+ {tables.data && tables.data.total > tables.data.rows.length ? <p className="text-xs text-text-color-muted">Showing the first {tables.data.rows.length} workbenches.</p> : null}</div>
119
+ {columns.length ? (
120
+ <fieldset className="flex flex-col gap-2 rounded-md border border-border p-3">
121
+ <legend className="px-1 text-xs text-text-color-muted">Copy only these columns (optional)</legend>
122
+ <p className="text-xs text-text-color-muted">Leave all unticked to copy every column.</p>
123
+ {columns.map((c) => (
124
+ <label key={c.id} className="flex items-center gap-2 text-sm"><input type="checkbox" aria-label={c.display_name || c.name} checked={only.includes(c.name)} onChange={(e) => setOnly(e.target.checked ? [...only, c.name] : only.filter((n) => n !== c.name))} /><span>{c.display_name || c.name}</span></label>
125
+ ))}
126
+ </fieldset>
127
+ ) : null}
128
+ {create.error ? <ApiError error={create.error} title="Could not create the connection" /> : null}
129
+ </div>
130
+ </FormSheet>
131
+
132
+ <ConfirmSpendDialog open={deleting != null} tier="destructive" title={`Delete the connection to "${deleting?.name ?? ""}"`} description="New rows stop being copied. Rows already copied stay where they are."
133
+ confirmLabel="Delete connection" confirming={remove.loading} onConfirm={() => deleting && void remove.mutate(deleting.c)} onCancel={() => setDeleting(null)} />
134
+ </SectionCard>
135
+ );
136
+ }