@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
@@ -0,0 +1,318 @@
1
+ {
2
+ "$schema": "../block.schema.json",
3
+ "id": "company-intelligence",
4
+ "title": "Company intelligence",
5
+ "summary": "Research your own website, then read what it found (profile, competitors, news, keywords), the wiki documents written from it and the six market research reports. Billable steps are confirmed.",
6
+ "features": [
7
+ "website research run with step-by-step progress; billable, confirmed, locked to the workspace's own website",
8
+ "company profile, competitors, brand news, products, keywords, audience questions and brand assets, each readable and re-collectable",
9
+ "wiki documents written from the research, read as safe formatted text and rewritten one at a time",
10
+ "six research reports: write one or all, retry, resume, stop, reset; read, edit, approve into the knowledge base, see the model's reasoning, delete",
11
+ "optional tab for a CRM company page (CompanyIntelligenceTab)",
12
+ "markdown and web content from the API is always drawn as text, never as HTML"
13
+ ],
14
+ "dependsOn": [
15
+ "foundation"
16
+ ],
17
+ "operations": [
18
+ "analyze_website_intelligence_analyze_post",
19
+ "approve_research_report_research_reports__report_id__approve_post",
20
+ "delete_research_report_research_reports__report_id__delete",
21
+ "generate_all_research_reports_research_reports_generate_all_post",
22
+ "generate_global_context_document_global_context_generate__doc_type__post",
23
+ "generate_research_report_research_reports_generate_post",
24
+ "get_all_intelligence_data_intelligence_all__website_url__get",
25
+ "get_global_context_tree_flat_global_context_tree_flat_get",
26
+ "get_global_context_tree_global_context_tree_get",
27
+ "get_intelligence_data_intelligence_data__data_type__get",
28
+ "get_intelligence_org_domain_intelligence_org_domain_get",
29
+ "get_intelligence_primary_website_intelligence_primary_website_get",
30
+ "get_intelligence_status_intelligence_status__task_id__get",
31
+ "get_latest_intelligence_task_intelligence_latest_task_get",
32
+ "get_research_report_research_reports__report_id__get",
33
+ "get_research_report_thinking_research_reports__report_id__thinking_get",
34
+ "get_research_workflow_status_research_reports_workflow_get",
35
+ "list_intelligence_documents_intelligence_documents_get",
36
+ "reset_intelligence_intelligence_delete",
37
+ "reset_research_workflow_research_reports_workflow_reset_post",
38
+ "resume_research_workflow_research_reports_workflow_resume_post",
39
+ "retry_intelligence_source_intelligence_retry_post",
40
+ "retry_research_report_research_reports_retry_post",
41
+ "stop_all_research_research_reports_stop_all_post",
42
+ "unapprove_research_report_research_reports__report_id__unapprove_post",
43
+ "update_research_report_research_reports__report_id__patch"
44
+ ],
45
+ "components": [
46
+ {
47
+ "name": "ResearchRun",
48
+ "file": "components/research-run.tsx",
49
+ "purpose": "Start the website research (billable, confirmed), follow it step by step, and reset it (destructive, confirmed with the real record count).",
50
+ "operations": [
51
+ "analyze_website_intelligence_analyze_post",
52
+ "get_intelligence_org_domain_intelligence_org_domain_get",
53
+ "get_intelligence_primary_website_intelligence_primary_website_get",
54
+ "get_intelligence_status_intelligence_status__task_id__get",
55
+ "get_latest_intelligence_task_intelligence_latest_task_get",
56
+ "list_intelligence_documents_intelligence_documents_get",
57
+ "reset_intelligence_intelligence_delete"
58
+ ],
59
+ "tiers": [
60
+ "read",
61
+ "billable",
62
+ "destructive"
63
+ ]
64
+ },
65
+ {
66
+ "name": "CompanyProfileCard",
67
+ "file": "components/company-profile.tsx",
68
+ "purpose": "The company profile the research collected (industry, size, funding, links) with counts of what else was found. Mount alone on any page.",
69
+ "operations": [
70
+ "get_all_intelligence_data_intelligence_all__website_url__get",
71
+ "get_intelligence_primary_website_intelligence_primary_website_get"
72
+ ],
73
+ "tiers": [
74
+ "read"
75
+ ]
76
+ },
77
+ {
78
+ "name": "IntelligenceSources",
79
+ "file": "components/intelligence-sources.tsx",
80
+ "purpose": "List of the collected data sources plus the ones of the last run that failed or have not finished.",
81
+ "operations": [
82
+ "get_intelligence_status_intelligence_status__task_id__get",
83
+ "get_latest_intelligence_task_intelligence_latest_task_get",
84
+ "list_intelligence_documents_intelligence_documents_get"
85
+ ],
86
+ "tiers": [
87
+ "read"
88
+ ]
89
+ },
90
+ {
91
+ "name": "SourceDetail",
92
+ "file": "components/source-detail.tsx",
93
+ "purpose": "Complete screen for one source: what it collected, when, edits, and re-collect it (billable, confirmed).",
94
+ "operations": [
95
+ "get_intelligence_data_intelligence_data__data_type__get",
96
+ "get_intelligence_primary_website_intelligence_primary_website_get",
97
+ "retry_intelligence_source_intelligence_retry_post"
98
+ ],
99
+ "tiers": [
100
+ "read",
101
+ "billable"
102
+ ]
103
+ },
104
+ {
105
+ "name": "SourceView",
106
+ "file": "components/source-view.tsx",
107
+ "purpose": "Read-only renderer for one source's data: profile, competitors, news, products, keywords, questions, trends, pages, brand assets; unknown shapes fall back to a readable tree.",
108
+ "operations": [],
109
+ "tiers": []
110
+ },
111
+ {
112
+ "name": "WikiDocuments",
113
+ "file": "components/wiki-documents.tsx",
114
+ "purpose": "The wiki documents written from the research, with search and a folder filter.",
115
+ "operations": [
116
+ "get_global_context_tree_flat_global_context_tree_flat_get"
117
+ ],
118
+ "tiers": [
119
+ "read"
120
+ ]
121
+ },
122
+ {
123
+ "name": "WikiDocumentDetail",
124
+ "file": "components/wiki-document-detail.tsx",
125
+ "purpose": "Complete screen for one wiki document: safe formatted content, state, version, and rewrite it from the research (billable, confirmed).",
126
+ "operations": [
127
+ "generate_global_context_document_global_context_generate__doc_type__post",
128
+ "get_global_context_tree_flat_global_context_tree_flat_get",
129
+ "get_intelligence_primary_website_intelligence_primary_website_get"
130
+ ],
131
+ "tiers": [
132
+ "read",
133
+ "billable"
134
+ ]
135
+ },
136
+ {
137
+ "name": "ResearchReports",
138
+ "file": "components/research-reports.tsx",
139
+ "purpose": "The six research reports and their workflow: write one or all, retry, resume, stop, reset; every cost confirmed with the number of reports.",
140
+ "operations": [
141
+ "generate_all_research_reports_research_reports_generate_all_post",
142
+ "generate_research_report_research_reports_generate_post",
143
+ "get_intelligence_primary_website_intelligence_primary_website_get",
144
+ "get_research_workflow_status_research_reports_workflow_get",
145
+ "reset_research_workflow_research_reports_workflow_reset_post",
146
+ "resume_research_workflow_research_reports_workflow_resume_post",
147
+ "retry_research_report_research_reports_retry_post",
148
+ "stop_all_research_research_reports_stop_all_post"
149
+ ],
150
+ "tiers": [
151
+ "read",
152
+ "write",
153
+ "billable",
154
+ "destructive"
155
+ ]
156
+ },
157
+ {
158
+ "name": "ReportDetail",
159
+ "file": "components/report-detail.tsx",
160
+ "purpose": "Complete screen for one research report: safe formatted text, edit (changed text only), approve into the knowledge base, recorded reasoning, write again, delete.",
161
+ "operations": [
162
+ "approve_research_report_research_reports__report_id__approve_post",
163
+ "delete_research_report_research_reports__report_id__delete",
164
+ "generate_research_report_research_reports_generate_post",
165
+ "get_intelligence_primary_website_intelligence_primary_website_get",
166
+ "get_research_report_research_reports__report_id__get",
167
+ "get_research_report_thinking_research_reports__report_id__thinking_get",
168
+ "unapprove_research_report_research_reports__report_id__unapprove_post",
169
+ "update_research_report_research_reports__report_id__patch"
170
+ ],
171
+ "tiers": [
172
+ "read",
173
+ "write",
174
+ "billable",
175
+ "destructive"
176
+ ]
177
+ },
178
+ {
179
+ "name": "CompanyIntelligenceTab",
180
+ "file": "components/company-intelligence-tab.tsx",
181
+ "purpose": "Optional tab for a CRM company detail page (mount through extraDetailTabs): the profile when the company is your own website, the competitor entry when it is a competitor your research found, otherwise an honest empty state.",
182
+ "operations": [
183
+ "get_all_intelligence_data_intelligence_all__website_url__get",
184
+ "get_intelligence_data_intelligence_data__data_type__get",
185
+ "get_intelligence_primary_website_intelligence_primary_website_get"
186
+ ],
187
+ "tiers": [
188
+ "read"
189
+ ]
190
+ },
191
+ {
192
+ "name": "CompanyIntelligenceScreen",
193
+ "file": "components/company-intelligence-screen.tsx",
194
+ "purpose": "Finished company-intelligence page: Overview (research run + profile), Sources, Documents and Reports tabs, each with a detail panel and deep links.",
195
+ "operations": [
196
+ "get_global_context_tree_global_context_tree_get",
197
+ "get_intelligence_primary_website_intelligence_primary_website_get",
198
+ "get_latest_intelligence_task_intelligence_latest_task_get",
199
+ "get_research_workflow_status_research_reports_workflow_get",
200
+ "list_intelligence_documents_intelligence_documents_get"
201
+ ],
202
+ "tiers": [
203
+ "read"
204
+ ]
205
+ }
206
+ ],
207
+ "hooks": [
208
+ {
209
+ "name": "useResearchTarget",
210
+ "file": "hooks/use-intelligence.ts",
211
+ "purpose": "Cached reads shared by the components: useResearchTarget (primary website + a suggestion), useLatestRun, useRunStatus, useSourceDocuments, useSourceEntry, useAllIntelligence, useWikiDocuments, useWikiStats, useWorkflow, and refreshIntelligence() to refresh them all after a write.",
212
+ "operations": [
213
+ "get_all_intelligence_data_intelligence_all__website_url__get",
214
+ "get_global_context_tree_flat_global_context_tree_flat_get",
215
+ "get_global_context_tree_global_context_tree_get",
216
+ "get_intelligence_data_intelligence_data__data_type__get",
217
+ "get_intelligence_org_domain_intelligence_org_domain_get",
218
+ "get_intelligence_primary_website_intelligence_primary_website_get",
219
+ "get_intelligence_status_intelligence_status__task_id__get",
220
+ "get_latest_intelligence_task_intelligence_latest_task_get",
221
+ "get_research_workflow_status_research_reports_workflow_get",
222
+ "list_intelligence_documents_intelligence_documents_get"
223
+ ]
224
+ }
225
+ ],
226
+ "lib": [
227
+ {
228
+ "file": "lib/intelligence-types.ts",
229
+ "purpose": "Open-payload types, defensive readers (text, num, rowsOf), canonicalDomain, safeHttpUrl, run/step helpers, the six report types, workflow slot helpers, and the changed-text-only report edit."
230
+ },
231
+ {
232
+ "file": "lib/safe-markdown.tsx",
233
+ "purpose": "SafeMarkdown: renders API markdown as React text nodes (headings, lists, tables, code, links to http(s) only). Never produces HTML; no dangerouslySetInnerHTML."
234
+ }
235
+ ],
236
+ "recipes": [
237
+ {
238
+ "file": "recipes/research-your-website.ts",
239
+ "title": "Research your own website and read the company profile",
240
+ "when": "Setting up company intelligence: primary website, billable run, poll, read the profile."
241
+ },
242
+ {
243
+ "file": "recipes/read-competitors-and-news.ts",
244
+ "title": "Read the competitors and the news the research found",
245
+ "when": "Feeding a briefing or digest from the collected competitors and brand news."
246
+ },
247
+ {
248
+ "file": "recipes/write-the-research-reports.ts",
249
+ "title": "Write the six research reports, follow them and approve one",
250
+ "when": "Building market research: count the missing reports, get a yes, write, poll, read, approve."
251
+ }
252
+ ],
253
+ "prerequisites": [
254
+ {
255
+ "id": "intelligence-scopes",
256
+ "description": "The graph8 key needs knowledge:read, knowledge:run and knowledge:delete (research and documents) and campaigns:read, campaigns:write, campaigns:run, campaigns:delete (research reports).",
257
+ "where": "api",
258
+ "verify": "g8.api.me.describeCurrentKey() lists those scopes."
259
+ },
260
+ {
261
+ "id": "credits",
262
+ "description": "Research runs, document rewrites and report writing use credits. The API quotes no price in advance, so a person confirms each one.",
263
+ "where": "api",
264
+ "verify": "The workspace owner knows the plan's credit balance (the API has no balance read)."
265
+ },
266
+ {
267
+ "id": "own-website",
268
+ "description": "The research is about the workspace's own website and is locked to the first one researched. A person decides which website that is.",
269
+ "where": "app",
270
+ "verify": "GET /api/v1/intelligence/primary-website returns has_website true after the first run."
271
+ }
272
+ ],
273
+ "scopes": [
274
+ "campaigns:delete",
275
+ "campaigns:read",
276
+ "campaigns:run",
277
+ "campaigns:write",
278
+ "knowledge:delete",
279
+ "knowledge:read",
280
+ "knowledge:run"
281
+ ],
282
+ "defaults": [
283
+ {
284
+ "decision": "Which website is researched",
285
+ "default": "The workspace's primary website once set; before that the company domain from the workspace settings is only suggested, a person confirms it",
286
+ "askHuman": true
287
+ },
288
+ {
289
+ "decision": "Run again when a run finished less than an hour ago",
290
+ "default": "No: the API returns that run and does no new work",
291
+ "askHuman": false
292
+ },
293
+ {
294
+ "decision": "Writing a research report",
295
+ "default": "Never automatic: a person confirms the number of reports first",
296
+ "askHuman": false
297
+ },
298
+ {
299
+ "decision": "Approving a report into the knowledge base",
300
+ "default": "Only when a person asks; approved reports are read by campaigns and the copilot",
301
+ "askHuman": true
302
+ },
303
+ {
304
+ "decision": "Editing a report",
305
+ "default": "Send only the changed text; a cleared text is sent as an empty string",
306
+ "askHuman": false
307
+ },
308
+ {
309
+ "decision": "Missing data",
310
+ "default": "Shown as unknown (a dash), never as zero and never guessed",
311
+ "askHuman": false
312
+ }
313
+ ],
314
+ "peerDependencies": {
315
+ "react": ">=18",
316
+ "lucide-react": ">=0.400"
317
+ }
318
+ }
@@ -0,0 +1,114 @@
1
+ "use client";
2
+
3
+ /**
4
+ * CompanyIntelligenceScreen: the finished company-intelligence page. Four tabs (`?tab=`):
5
+ * Overview start, follow and reset the website research (ResearchRun) and read the company profile it collected.
6
+ * Sources everything the research collected, and the sources that failed; open one (`?id=<type>`) to read it and re-collect it.
7
+ * Documents the wiki documents written from the research; open one (`?id=`) to read it or write it again.
8
+ * Reports the six research reports and their workflow: write, retry, resume, stop, reset; open one (`?id=`) to read,
9
+ * edit, approve into the knowledge base, see the reasoning, write again or delete.
10
+ * Every detail also opens as a full page with `?view=full`. Every write refreshes the shared read cache, so the stat strip and
11
+ * the lists update without a reload.
12
+ *
13
+ * Reality of the API: this is the research of YOUR OWN workspace website (locked to one website); it has no lookup for other
14
+ * companies and no technographics, org chart or briefing endpoints. The screen says so instead of inventing data. To show a
15
+ * company's intelligence on a CRM company page, mount `CompanyIntelligenceTab` in the CRM block's `extraDetailTabs`.
16
+ *
17
+ * SDK operations: none of its own; the stat strip reads listIntelligenceDocuments, getGlobalContextTree,
18
+ * getResearchWorkflowStatus and getLatestIntelligenceTask (all free reads). Everything billable or destructive is inside the parts
19
+ * it composes (ResearchRun, SourceDetail, WikiDocumentDetail, ResearchReports, ReportDetail), each behind ConfirmSpendDialog.
20
+ * Prerequisites: `intelligence`, `global-context` and `research-reports` in the proxy allowlist; credits for research.
21
+ */
22
+ import type { ReactNode } from "react";
23
+ import { Telescope } from "lucide-react";
24
+ import { Button } from "@graph8/sdk/ui";
25
+ import { useUrlState } from "@/g8/hooks/use-url-state";
26
+ import { ScreenLayout } from "@/g8/components/screen/screen-layout";
27
+ import type { StatItem } from "@/g8/components/screen/stat-strip";
28
+ import { SplitView } from "@/g8/components/screen/split-view";
29
+ import { EmptyValue } from "@/g8/components/screen/key-value-list";
30
+ import { plural } from "@/g8/lib/plural";
31
+ import { useLatestRun, useResearchTarget, useSourceDocuments, useWikiStats, useWorkflow } from "../hooks/use-intelligence";
32
+ import { humanize, isReportDone, slotsOf, whenDate } from "../lib/intelligence-types";
33
+ import { CompanyProfileCard } from "./company-profile";
34
+ import { IntelligenceSources } from "./intelligence-sources";
35
+ import { ReportDetail } from "./report-detail";
36
+ import { ResearchReports } from "./research-reports";
37
+ import { ResearchRun } from "./research-run";
38
+ import { SourceDetail } from "./source-detail";
39
+ import { WikiDocumentDetail } from "./wiki-document-detail";
40
+ import { WikiDocuments } from "./wiki-documents";
41
+
42
+ /** The record open in the detail panel, passed to the slot props. */
43
+ export type IntelligenceRecord = { kind: "source" | "document" | "report"; id: string };
44
+
45
+ export interface CompanyIntelligenceScreenProps {
46
+ toolbarActions?: ReactNode;
47
+ /** Buttons added to the open record's header. */
48
+ renderDetailActions?: (record: IntelligenceRecord) => ReactNode;
49
+ /** Tabs added after the built-in ones on the open record. */
50
+ extraDetailTabs?: { id: string; label: string; render: (record: IntelligenceRecord) => ReactNode }[];
51
+ className?: string;
52
+ }
53
+
54
+ type Tab = "overview" | "sources" | "documents" | "reports";
55
+ const TABS = ["overview", "sources", "documents", "reports"] as const;
56
+
57
+ export function CompanyIntelligenceScreen(props: CompanyIntelligenceScreenProps) {
58
+ const [tabValue, setTab] = useUrlState("tab", "overview");
59
+ const tab: Tab = (TABS as readonly string[]).includes(tabValue) ? (tabValue as Tab) : "overview";
60
+ const [id, setId] = useUrlState("id", "");
61
+ const [view, setView] = useUrlState("view", "");
62
+ const expanded = view === "full" && Boolean(id);
63
+ const target = useResearchTarget();
64
+ const docs = useSourceDocuments();
65
+ const wiki = useWikiStats();
66
+ const flow = useWorkflow(target.primary);
67
+ const latest = useLatestRun();
68
+
69
+ const close = () => { setId(""); setView(""); };
70
+ const panel = { onClose: close, onExpand: expanded ? undefined : () => setView("full"), onCollapse: expanded ? () => setView("") : undefined };
71
+ const slots = (record: IntelligenceRecord) => ({
72
+ extraActions: props.renderDetailActions?.(record),
73
+ extraTabs: (props.extraDetailTabs ?? []).map((t) => ({ id: t.id, label: t.label, content: t.render(record) })),
74
+ });
75
+ const split = (list: ReactNode, detail: ReactNode) => (
76
+ <SplitView detailOpen={Boolean(id)} onCloseDetail={close} expanded={expanded} onExpandedChange={(next) => setView(next ? "full" : "")} detailWidth="lg" list={list} detail={id ? detail : null} />
77
+ );
78
+
79
+ const reportSlots = slotsOf(flow.workflow ?? undefined);
80
+ const stats: StatItem[] = [
81
+ { label: "Sources collected", value: docs.docs ? docs.docs.length.toLocaleString() : <EmptyValue /> },
82
+ { label: "Wiki documents", value: wiki.stats ? `${wiki.stats.completed.toLocaleString()} of ${wiki.stats.total.toLocaleString()}` : <EmptyValue />, hint: wiki.stats ? "finished" : undefined },
83
+ { label: "Research reports", value: flow.workflow ? `${reportSlots.filter((s) => isReportDone(s.status)).length} of ${reportSlots.length || 6}` : <EmptyValue />, hint: flow.workflow ? "finished" : undefined },
84
+ { label: "Last research", value: latest.run?.status ? humanize(latest.run.status) : <EmptyValue />, hint: latest.run?.completed_at ? whenDate(latest.run.completed_at) ?? undefined : latest.run ? undefined : "none yet", tone: latest.run?.status === "failed" ? "negative" : "neutral" },
85
+ ];
86
+
87
+ return (
88
+ <ScreenLayout
89
+ title="Company intelligence"
90
+ description="What the research of your website found, and the documents and reports written from it."
91
+ icon={<Telescope className="size-5" />}
92
+ actions={<>{props.toolbarActions}{tab === "overview" ? null : <Button onClick={() => { setTab("overview"); close(); }}>Research website</Button>}</>}
93
+ tabs={[{ id: "overview", label: "Overview" }, { id: "sources", label: "Sources" }, { id: "documents", label: "Documents" }, { id: "reports", label: "Reports" }]}
94
+ activeTab={tab}
95
+ onTabChange={(next) => { setTab(next); close(); }}
96
+ stats={stats}
97
+ className={props.className}
98
+ >
99
+ {tab === "overview" ? (
100
+ <div className="space-y-4">
101
+ <ResearchRun />
102
+ <CompanyProfileCard onOpenSource={(type) => { setTab("sources"); setId(type); }} />
103
+ <p className="text-xs text-muted-foreground">{plural(docs.docs?.length ?? 0, "source")} collected. This is the research of your own website: there is no lookup for other companies.</p>
104
+ </div>
105
+ ) : tab === "sources" ? (
106
+ split(<IntelligenceSources idParam="id" selectedType={id} onSelect={(s) => setId(s.dataType)} />, <SourceDetail key={id} dataType={id} {...panel} {...slots({ kind: "source", id })} />)
107
+ ) : tab === "documents" ? (
108
+ split(<WikiDocuments idParam="id" selectedId={id} onSelect={(d) => setId(d.id)} />, <WikiDocumentDetail key={id} docId={id} {...panel} {...slots({ kind: "document", id })} />)
109
+ ) : (
110
+ split(<ResearchReports idParam="id" selectedId={id} onSelect={(s) => s.id && setId(s.id)} />, <ReportDetail key={id} reportId={id} {...panel} {...slots({ kind: "report", id })} />)
111
+ )}
112
+ </ScreenLayout>
113
+ );
114
+ }
@@ -0,0 +1,88 @@
1
+ "use client";
2
+
3
+ /**
4
+ * CompanyIntelligenceTab: an optional tab for a company's detail page. Mount it from the CRM block's `extraDetailTabs`:
5
+ *
6
+ * <CompaniesScreen extraDetailTabs={[{ id: "intelligence", label: "Intelligence", render: (c) => <CompanyIntelligenceTab company={c} /> }]} />
7
+ *
8
+ * What it can honestly show: the company intelligence API researches YOUR OWN workspace website (it is locked to one
9
+ * website) and has no lookup for other companies. So the tab shows
10
+ * - the full company profile when the company on screen IS your workspace's website,
11
+ * - the competitor entry your research holds for it when the company is one of the competitors your research found,
12
+ * - otherwise a clear note that there is nothing to show (it never invents firmographics, news or technology data).
13
+ *
14
+ * SDK operations, in order:
15
+ * 1. getIntelligencePrimaryWebsite GET /intelligence/primary-website (read, through useResearchTarget)
16
+ * 2. getAllIntelligenceData GET /intelligence/all/{website_url} (read, through CompanyProfileCard) own-company case
17
+ * 3. getIntelligenceData GET /intelligence/data/competitor_discovery (read, through useSourceEntry) competitor case
18
+ */
19
+ import { Skeleton } from "@graph8/sdk/ui";
20
+ import { Telescope } from "lucide-react";
21
+ import { ApiError } from "@/g8/components/api-error";
22
+ import { EmptyState } from "@/g8/components/empty-state";
23
+ import { SectionCard } from "@/g8/components/screen/section-card";
24
+ import { StatusPill } from "@/g8/components/screen/status-pill";
25
+ import { useBrand } from "@/g8/hooks/use-brand";
26
+ import { entryData, useResearchTarget, useSourceEntry } from "../hooks/use-intelligence";
27
+ import { asArray, canonicalDomain, humanize, isRec, text } from "../lib/intelligence-types";
28
+ import { CompanyProfileCard } from "./company-profile";
29
+
30
+ /** The few company fields the tab reads; the CRM block's CompanyRecord satisfies it. */
31
+ export interface TabCompany { name?: string | null; domain?: string | null; website?: string | null }
32
+
33
+ export interface CompanyIntelligenceTabProps {
34
+ company: TabCompany;
35
+ /** Called when a person asks for the full intelligence screen. Omit it to hide the button. */
36
+ onOpenIntelligence?: () => void;
37
+ className?: string;
38
+ }
39
+
40
+ export function CompanyIntelligenceTab({ company, onOpenIntelligence, className }: CompanyIntelligenceTabProps) {
41
+ const brand = useBrand();
42
+ const host = canonicalDomain(company.domain ?? company.website) || null;
43
+ const target = useResearchTarget();
44
+ const own = Boolean(host && target.primaryDomain && host === target.primaryDomain);
45
+ const competitors = useSourceEntry("competitor_discovery", target.primary, Boolean(target.primary) && !own);
46
+ if (target.loading) return <Skeleton className="h-32 w-full" />;
47
+ if (target.error) return <ApiError error={target.error} title="Could not load company intelligence" onRetry={() => void target.refetch()} />;
48
+ if (!host) return <EmptyState title="No website on record" description="Add this company's website to see what your research knows about it." compact icon={<Telescope />} />;
49
+ if (own) {
50
+ return (
51
+ <div className={className}>
52
+ <CompanyProfileCard website={host} />
53
+ {onOpenIntelligence ? <button type="button" className="mt-3 text-sm underline underline-offset-2" onClick={onOpenIntelligence}>Open company intelligence</button> : null}
54
+ </div>
55
+ );
56
+ }
57
+ if (competitors.error && (competitors.error as { status?: number }).status !== 404) return <ApiError error={competitors.error} title="Could not load the competitors" onRetry={() => void competitors.refetch()} />;
58
+ const list = asArray(entryData(competitors.data ?? null)?.competitors).filter(isRec);
59
+ const match = list.find((c) => canonicalDomain(text(c.domain)) === host);
60
+ if (match) {
61
+ const pills = [text(match.competitive_type), text(match.similarity) ? `${text(match.similarity)} similarity` : null, text(match.confidence) ? `${text(match.confidence)} confidence` : null].filter(Boolean) as string[];
62
+ return (
63
+ <div className={className}>
64
+ <SectionCard title={text(match.name) ?? host} description="A competitor your company research found">
65
+ <div className="space-y-2 text-sm">
66
+ <div className="flex flex-wrap gap-1.5">{pills.map((p) => <StatusPill key={p} tone="info" quiet>{humanize(p)}</StatusPill>)}</div>
67
+ {text(match.description) ? <p>{text(match.description)}</p> : null}
68
+ {text(match.reasoning) ? <p className="text-muted-foreground">{text(match.reasoning)}</p> : null}
69
+ </div>
70
+ </SectionCard>
71
+ {onOpenIntelligence ? <button type="button" className="mt-3 text-sm underline underline-offset-2" onClick={onOpenIntelligence}>Open company intelligence</button> : null}
72
+ </div>
73
+ );
74
+ }
75
+ if (competitors.loading && !competitors.data && target.primary) return <Skeleton className="h-32 w-full" />;
76
+ return (
77
+ <EmptyState
78
+ className={className}
79
+ compact
80
+ icon={<Telescope />}
81
+ title="No intelligence for this company"
82
+ description={target.primary
83
+ ? `${brand.linkLabel} researches your own website (${target.primary}). It has no profile, news or technology data for other companies, and this one is not among the competitors your research found.`
84
+ : `${brand.linkLabel} researches your own website, and that research has not run yet. It has no profile, news or technology data for other companies.`}
85
+ action={onOpenIntelligence ? <button type="button" className="text-sm underline underline-offset-2" onClick={onOpenIntelligence}>Open company intelligence</button> : undefined}
86
+ />
87
+ );
88
+ }
@@ -0,0 +1,68 @@
1
+ "use client";
2
+
3
+ /**
4
+ * CompanyProfileCard: the company profile the research collected (industry, size, funding, links) with a one-line count of
5
+ * what else was found (products, keywords, competitors, articles). Mount it alone on any page.
6
+ *
7
+ * SDK operations, in order:
8
+ * 1. getIntelligencePrimaryWebsite GET /intelligence/primary-website (read, through useResearchTarget) used when no `website` prop is given
9
+ * 2. getAllIntelligenceData GET /intelligence/all/{website_url} (read) every source collected for the website
10
+ * Nothing here is billable. A source that was not collected is said to be missing, never shown as zero.
11
+ */
12
+ import { Building2 } from "lucide-react";
13
+ import { Skeleton } from "@graph8/sdk/ui";
14
+ import { ApiError } from "@/g8/components/api-error";
15
+ import { EmptyState } from "@/g8/components/empty-state";
16
+ import { SectionCard } from "@/g8/components/screen/section-card";
17
+ import { EntityAvatar } from "@/g8/components/screen/entity-avatar";
18
+ import { plural } from "@/g8/lib/plural";
19
+ import { entryData, useAllIntelligence, useResearchTarget } from "../hooks/use-intelligence";
20
+ import { asArray, canonicalDomain, safeHttpUrl, text, whenDate } from "../lib/intelligence-types";
21
+ import { CompanyProfileFields } from "./source-view";
22
+
23
+ export interface CompanyProfileCardProps {
24
+ /** A website or host. Default: the workspace's research website. */
25
+ website?: string | null;
26
+ /** Called with a source type when a person asks for the full source. */
27
+ onOpenSource?: (dataType: string) => void;
28
+ className?: string;
29
+ }
30
+
31
+ const FOUND: Array<[string, string, string, string]> = [
32
+ ["product_inventory", "products", "product", "Products"],
33
+ ["company_keywords", "keywords", "keyword", "Keywords"],
34
+ ["competitor_discovery", "competitors", "competitor", "Competitors"],
35
+ ["brand_news", "articles", "article", "News"],
36
+ ["audience_questions", "questions", "audience question", "Audience questions"],
37
+ ];
38
+
39
+ export function CompanyProfileCard({ website, onOpenSource, className }: CompanyProfileCardProps) {
40
+ const target = useResearchTarget();
41
+ const host = canonicalDomain(website ?? target.primary) || null;
42
+ const all = useAllIntelligence(host);
43
+ if (target.loading && !website) return <Skeleton className="h-40 w-full" />;
44
+ if (!host) return <EmptyState title="No research website yet" description="Start the website research to build the company profile." compact icon={<Building2 />} />;
45
+ if (all.error) return <ApiError error={all.error} title="Could not load the company profile" onRetry={() => void all.refetch()} />;
46
+ if (all.loading || !all.entries) return <Skeleton className="h-40 w-full" />;
47
+ const profile = entryData(all.entries.company_enrichment);
48
+ const logo = safeHttpUrl(entryData(all.entries.visual_assets)?.logo_url);
49
+ const name = text(profile?.company_name) ?? host;
50
+ const collected = whenDate(all.entries.company_enrichment?.collected_at);
51
+ return (
52
+ <SectionCard className={className} title={name} description={host + (collected ? `, collected ${collected}` : "")} icon={<EntityAvatar name={name} imageUrl={logo ?? undefined} kind="company" size="sm" />}>
53
+ {profile ? <CompanyProfileFields data={profile} /> : <p className="text-sm text-muted-foreground">The company profile was not collected for this website.</p>}
54
+ <ul className="mt-3 flex flex-wrap gap-x-4 gap-y-1 border-t border-border pt-3 text-xs text-muted-foreground">
55
+ {FOUND.map(([type, key, noun, label]) => {
56
+ const data = entryData(all.entries?.[type]);
57
+ if (!data) return <li key={type}>{label}: not collected</li>;
58
+ const n = asArray(data[key]).length;
59
+ return (
60
+ <li key={type}>
61
+ {onOpenSource && n ? <button type="button" className="underline underline-offset-2" onClick={() => onOpenSource(type)}>{plural(n, noun)}</button> : plural(n, noun)}
62
+ </li>
63
+ );
64
+ })}
65
+ </ul>
66
+ </SectionCard>
67
+ );
68
+ }
@@ -0,0 +1,63 @@
1
+ "use client";
2
+
3
+ /**
4
+ * IntelligenceSources: the list of data sources the research collected (company profile, products, keywords, competitors,
5
+ * news, audience questions, brand assets ...), plus the sources of the last run that failed or have not finished, so a
6
+ * missing source is visible and can be re-collected. Click a row to open it.
7
+ *
8
+ * SDK operations, in order:
9
+ * 1. listIntelligenceDocuments GET /intelligence/documents (read) the collected sources
10
+ * 2. getLatestIntelligenceTask GET /intelligence/latest-task (read) the last run
11
+ * 3. getIntelligenceStatus GET /intelligence/status/{task_id} (read) which steps of that run did not complete
12
+ * The API does not page this list (at most one row per source type); the header says how many there are.
13
+ */
14
+ import { Database } from "lucide-react";
15
+ import { Skeleton } from "@graph8/sdk/ui";
16
+ import { ApiError } from "@/g8/components/api-error";
17
+ import { EmptyState } from "@/g8/components/empty-state";
18
+ import { RecordLink } from "@/g8/components/screen/record-link";
19
+ import { StatusPill } from "@/g8/components/screen/status-pill";
20
+ import { plural } from "@/g8/lib/plural";
21
+ import { useLatestRun, useRunStatus, useSourceDocuments } from "../hooks/use-intelligence";
22
+ import { humanize, runSteps, stepTone, text, titleize, whenDate } from "../lib/intelligence-types";
23
+
24
+ export interface SourceRow { dataType: string; label: string; folder: string | null; collectedAt: string | null; state: string }
25
+
26
+ export interface IntelligenceSourcesProps {
27
+ /** Called when a person opens a source. */
28
+ onSelect?: (source: SourceRow) => void;
29
+ /** The open source's type, to mark its row. */
30
+ selectedType?: string;
31
+ /** The URL param the owning screen reads for the open source, so Cmd-click opens it in a new tab. */
32
+ idParam?: string;
33
+ className?: string;
34
+ }
35
+
36
+ export function IntelligenceSources({ onSelect, selectedType, idParam, className }: IntelligenceSourcesProps) {
37
+ const { docs, error, refetch } = useSourceDocuments();
38
+ const { run } = useLatestRun();
39
+ const { status } = useRunStatus(run?.task_id);
40
+ if (error) return <ApiError error={error} title="Could not load the sources" onRetry={() => void refetch()} />;
41
+ if (!docs) return <Skeleton className="h-40 w-full" />;
42
+ const collected: SourceRow[] = docs.map((d) => ({ dataType: d.data_type, label: text(d.display_name) ?? humanize(d.data_type), folder: text(d.folder), collectedAt: d.collected_at ?? null, state: "completed" }));
43
+ const have = new Set(collected.map((r) => r.dataType));
44
+ const missing: SourceRow[] = runSteps(status ?? undefined).filter((s) => !have.has(s.key) && s.state !== "completed").map((s) => ({ dataType: s.key, label: titleize(s.key), folder: null, collectedAt: null, state: s.state }));
45
+ const rows = [...collected, ...missing];
46
+ if (rows.length === 0) return <EmptyState title="No sources yet" description="Start the website research and the sources it collects will appear here." icon={<Database />} />;
47
+ return (
48
+ <div className={className}>
49
+ <p className="mb-2 text-xs text-muted-foreground" role="status">All {plural(rows.length, "source")}{missing.length ? `, ${plural(missing.length, "source")} not collected` : ""}</p>
50
+ <ul className="divide-y divide-border rounded-md border border-border">
51
+ {rows.map((r) => (
52
+ <li key={r.dataType} aria-current={r.dataType === selectedType ? "true" : undefined} className="flex items-center justify-between gap-3 px-3 py-2 text-sm aria-[current=true]:bg-muted">
53
+ <div className="min-w-0">
54
+ <RecordLink id={r.dataType} param={idParam} onOpen={() => onSelect?.(r)}>{r.label}</RecordLink>
55
+ <div className="text-xs text-muted-foreground">{[r.folder, r.collectedAt ? `Collected ${whenDate(r.collectedAt)}` : null].filter(Boolean).join(", ") || "Not collected"}</div>
56
+ </div>
57
+ <StatusPill tone={stepTone(r.state)} quiet>{r.state === "completed" ? "Collected" : humanize(r.state)}</StatusPill>
58
+ </li>
59
+ ))}
60
+ </ul>
61
+ </div>
62
+ );
63
+ }