@graph8/sdk 0.362.0 → 0.373.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 (615) hide show
  1. package/README.md +33 -10
  2. package/blocks/_foundation/README.md +78 -1
  3. package/blocks/_foundation/block.json +123 -6
  4. package/blocks/_foundation/components/api-error.tsx +9 -7
  5. package/blocks/_foundation/components/brand-provider.tsx +23 -0
  6. package/blocks/_foundation/components/confirm-spend-dialog.tsx +15 -8
  7. package/blocks/_foundation/components/confirmed-action.tsx +90 -0
  8. package/blocks/_foundation/components/connect-graph8.tsx +280 -0
  9. package/blocks/_foundation/components/empty-state.tsx +5 -2
  10. package/blocks/_foundation/components/list-select.tsx +112 -0
  11. package/blocks/_foundation/components/paging-notices.tsx +55 -0
  12. package/blocks/_foundation/components/screen/detail-panel.tsx +2 -1
  13. package/blocks/_foundation/components/screen/filter-controls.tsx +92 -0
  14. package/blocks/_foundation/components/screen/index.ts +2 -0
  15. package/blocks/_foundation/components/screen/record-link.tsx +76 -0
  16. package/blocks/_foundation/components/screen/split-view.tsx +1 -1
  17. package/blocks/_foundation/components/screen/time-series-chart-recharts.tsx +65 -0
  18. package/blocks/_foundation/components/screen/time-series-chart.tsx +15 -97
  19. package/blocks/_foundation/components/screen/time-series-format.ts +57 -0
  20. package/blocks/_foundation/hooks/use-all-pages.ts +54 -0
  21. package/blocks/_foundation/hooks/use-brand.ts +52 -0
  22. package/blocks/_foundation/hooks/use-g8-mutation.ts +23 -0
  23. package/blocks/_foundation/hooks/use-g8-query.ts +127 -1
  24. package/blocks/_foundation/hooks/use-load-more-list.ts +61 -0
  25. package/blocks/_foundation/hooks/use-paginated.ts +120 -0
  26. package/blocks/_foundation/hooks/use-row-activation.ts +57 -0
  27. package/blocks/_foundation/hooks/use-url-filters.ts +93 -0
  28. package/blocks/_foundation/lib/g8-cache.ts +454 -0
  29. package/blocks/_foundation/lib/g8-client.ts +1 -1
  30. package/blocks/_foundation/lib/paging.ts +57 -0
  31. package/blocks/_foundation/lib/plural.ts +23 -0
  32. package/blocks/_foundation/lib/use-debounced-value.ts +13 -0
  33. package/blocks/_foundation/server/connect-route.ts +15 -0
  34. package/blocks/_foundation/server/connect.ts +127 -0
  35. package/blocks/_foundation/server/local-key.ts +70 -0
  36. package/blocks/_foundation/server/proxy.ts +103 -3
  37. package/blocks/_foundation/server/route.ts +16 -4
  38. package/blocks/agents/README.md +93 -2
  39. package/blocks/agents/block.json +343 -2
  40. package/blocks/agents/components/agent-activity.tsx +112 -0
  41. package/blocks/agents/components/agent-approvals.tsx +135 -0
  42. package/blocks/agents/components/agent-builder.tsx +29 -10
  43. package/blocks/agents/components/agent-conversations.tsx +143 -0
  44. package/blocks/agents/components/agent-knowledge-panel.tsx +4 -3
  45. package/blocks/agents/components/agent-operators.tsx +164 -0
  46. package/blocks/agents/components/agent-run-detail.tsx +119 -0
  47. package/blocks/agents/components/agent-runs.tsx +19 -10
  48. package/blocks/agents/components/agent-skills-panel.tsx +7 -7
  49. package/blocks/agents/components/agent-test-history.tsx +121 -0
  50. package/blocks/agents/components/agents-screen.tsx +226 -0
  51. package/blocks/agents/components/assistant-sessions.tsx +150 -0
  52. package/blocks/agents/components/duplicate-agent-button.tsx +42 -0
  53. package/blocks/agents/components/from-template-button.tsx +65 -0
  54. package/blocks/agents/components/knowledge-browser.tsx +107 -0
  55. package/blocks/agents/components/knowledge-detail.tsx +156 -0
  56. package/blocks/agents/components/knowledge-form.tsx +69 -0
  57. package/blocks/agents/components/name-dialog.tsx +32 -0
  58. package/blocks/agents/components/receptionist-button.tsx +46 -0
  59. package/blocks/agents/components/save-as-template-button.tsx +32 -0
  60. package/blocks/agents/components/skill-editor.tsx +147 -0
  61. package/blocks/agents/components/skill-library.tsx +111 -0
  62. package/blocks/agents/lib/agent-types.ts +7 -1
  63. package/blocks/agents/lib/facts.tsx +13 -0
  64. package/blocks/agents/lib/knowledge-utils.ts +49 -0
  65. package/blocks/agents/lib/load-more.tsx +141 -0
  66. package/blocks/agents/lib/skill-utils.ts +91 -0
  67. package/blocks/agents/recipes/create-agent-and-attach-skill.ts +1 -1
  68. package/blocks/analytics/README.md +13 -0
  69. package/blocks/analytics/block.json +45 -1
  70. package/blocks/analytics/components/analytics-screen.tsx +222 -0
  71. package/blocks/analytics/components/kpi-tiles.tsx +1 -1
  72. package/blocks/analytics/components/leaderboard.tsx +14 -7
  73. package/blocks/analytics/components/report-builder.tsx +38 -11
  74. package/blocks/analytics/components/report-detail.tsx +84 -0
  75. package/blocks/analytics/components/trend-chart.tsx +62 -0
  76. package/blocks/appointments/README.md +6 -0
  77. package/blocks/appointments/block.json +33 -2
  78. package/blocks/appointments/components/availability-editor.tsx +17 -5
  79. package/blocks/appointments/components/booking-page.tsx +2 -2
  80. package/blocks/appointments/components/event-type-editor.tsx +2 -1
  81. package/blocks/appointments/components/event-type-related.tsx +4 -2
  82. package/blocks/appointments/components/meeting-contact-links.tsx +49 -0
  83. package/blocks/appointments/components/meeting-detail.tsx +2 -2
  84. package/blocks/appointments/components/meeting-list.tsx +38 -18
  85. package/blocks/appointments/components/meetings-screen.tsx +7 -4
  86. package/blocks/appointments/components/record-meetings-tab.tsx +92 -0
  87. package/blocks/appointments/components/scheduling-screen.tsx +2 -1
  88. package/blocks/block.schema.json +18 -0
  89. package/blocks/block.types.ts +17 -0
  90. package/blocks/campaigns/README.md +41 -11
  91. package/blocks/campaigns/block.json +105 -42
  92. package/blocks/campaigns/components/campaign-assets.tsx +17 -6
  93. package/blocks/campaigns/components/campaign-launch-step.tsx +114 -26
  94. package/blocks/campaigns/components/campaign-list.tsx +7 -3
  95. package/blocks/campaigns/components/campaign-metrics.tsx +1 -1
  96. package/blocks/campaigns/components/campaign-wizard.tsx +52 -14
  97. package/blocks/campaigns/components/campaigns-screen.tsx +267 -0
  98. package/blocks/campaigns/components/icp-detail.tsx +163 -0
  99. package/blocks/campaigns/components/icp-editor.tsx +22 -17
  100. package/blocks/campaigns/components/persona-detail.tsx +181 -0
  101. package/blocks/campaigns/components/persona-editor.tsx +19 -11
  102. package/blocks/campaigns/lib/campaigns-utils.ts +138 -5
  103. package/blocks/campaigns/recipes/attach-audience-and-launch.ts +16 -3
  104. package/blocks/campaigns/recipes/generate-ideas-and-create-campaign.ts +8 -4
  105. package/blocks/coach/README.md +10 -0
  106. package/blocks/coach/block.json +16 -1
  107. package/blocks/coach/components/call-scorecard.tsx +7 -7
  108. package/blocks/coach/components/coach-screen.tsx +222 -0
  109. package/blocks/company-intelligence/README.md +132 -0
  110. package/blocks/company-intelligence/block.json +318 -0
  111. package/blocks/company-intelligence/components/company-intelligence-screen.tsx +114 -0
  112. package/blocks/company-intelligence/components/company-intelligence-tab.tsx +88 -0
  113. package/blocks/company-intelligence/components/company-profile.tsx +68 -0
  114. package/blocks/company-intelligence/components/intelligence-sources.tsx +63 -0
  115. package/blocks/company-intelligence/components/report-detail.tsx +189 -0
  116. package/blocks/company-intelligence/components/research-reports.tsx +136 -0
  117. package/blocks/company-intelligence/components/research-run.tsx +161 -0
  118. package/blocks/company-intelligence/components/source-detail.tsx +117 -0
  119. package/blocks/company-intelligence/components/source-view.tsx +274 -0
  120. package/blocks/company-intelligence/components/wiki-document-detail.tsx +116 -0
  121. package/blocks/company-intelligence/components/wiki-documents.tsx +66 -0
  122. package/blocks/company-intelligence/hooks/use-intelligence.ts +173 -0
  123. package/blocks/company-intelligence/lib/intelligence-types.ts +230 -0
  124. package/blocks/company-intelligence/lib/safe-markdown.tsx +150 -0
  125. package/blocks/company-intelligence/recipes/read-competitors-and-news.ts +33 -0
  126. package/blocks/company-intelligence/recipes/research-your-website.ts +43 -0
  127. package/blocks/company-intelligence/recipes/write-the-research-reports.ts +54 -0
  128. package/blocks/copilot/README.md +13 -0
  129. package/blocks/copilot/block.json +14 -1
  130. package/blocks/copilot/components/copilot-memory.tsx +6 -2
  131. package/blocks/copilot/components/copilot-panel.tsx +14 -5
  132. package/blocks/copilot/components/copilot-screen.tsx +148 -0
  133. package/blocks/copilot/components/copilot-team-chat.tsx +13 -6
  134. package/blocks/crm/README.md +34 -0
  135. package/blocks/crm/block.json +107 -2
  136. package/blocks/crm/components/companies-screen.tsx +359 -0
  137. package/blocks/crm/components/company-detail.tsx +10 -8
  138. package/blocks/crm/components/company-table.tsx +11 -4
  139. package/blocks/crm/components/contact-detail.tsx +10 -7
  140. package/blocks/crm/components/contact-lookup-link.tsx +44 -0
  141. package/blocks/crm/components/contact-table.tsx +10 -3
  142. package/blocks/crm/components/contacts-screen.tsx +377 -0
  143. package/blocks/crm/components/dedupe-review.tsx +13 -6
  144. package/blocks/crm/components/import-wizard.tsx +7 -9
  145. package/blocks/crm/components/list-select.tsx +20 -0
  146. package/blocks/crm/components/notes-panel.tsx +4 -4
  147. package/blocks/crm/components/record-engagement-tab.tsx +103 -0
  148. package/blocks/crm/components/record-form.tsx +6 -4
  149. package/blocks/crm/components/task-list.tsx +4 -4
  150. package/blocks/crm/components/tasks-screen.tsx +399 -0
  151. package/blocks/crm/hooks/use-all-lists.ts +18 -0
  152. package/blocks/crm/hooks/use-custom-fields.ts +6 -1
  153. package/blocks/crm/hooks/use-page-query.ts +9 -1
  154. package/blocks/crm/lib/crm-types.ts +26 -2
  155. package/blocks/crm/lib/read-lists.ts +16 -0
  156. package/blocks/crm/lib/screen-parts.tsx +105 -0
  157. package/blocks/deals/README.md +24 -6
  158. package/blocks/deals/block.json +160 -5
  159. package/blocks/deals/components/close-deal-dialog.tsx +169 -0
  160. package/blocks/deals/components/deal-contacts-editor.tsx +134 -0
  161. package/blocks/deals/components/deal-detail.tsx +25 -13
  162. package/blocks/deals/components/deal-filters.tsx +65 -0
  163. package/blocks/deals/components/deal-line-items.tsx +120 -0
  164. package/blocks/deals/components/deal-notes-tab.tsx +97 -0
  165. package/blocks/deals/components/deal-related.tsx +31 -10
  166. package/blocks/deals/components/deal-tasks-tab.tsx +88 -0
  167. package/blocks/deals/components/deals-screen.tsx +66 -26
  168. package/blocks/deals/components/forecast-view.tsx +4 -4
  169. package/blocks/deals/components/pipeline-board.tsx +8 -6
  170. package/blocks/deals/components/pipeline-editor.tsx +132 -0
  171. package/blocks/deals/components/record-deals-tab.tsx +62 -0
  172. package/blocks/deals/components/stage-editor.tsx +5 -5
  173. package/blocks/deals/hooks/use-pipeline-deals.ts +21 -4
  174. package/blocks/deals/hooks/use-pipelines.ts +1 -1
  175. package/blocks/deals/lib/deal-extras.ts +156 -0
  176. package/blocks/dialer/README.md +45 -4
  177. package/blocks/dialer/block.json +84 -3
  178. package/blocks/dialer/components/call-contact-button.tsx +269 -0
  179. package/blocks/dialer/components/call-log-screen.tsx +208 -0
  180. package/blocks/dialer/components/call-log.tsx +23 -7
  181. package/blocks/dialer/components/call-queue.tsx +4 -4
  182. package/blocks/dialer/components/dialer-screen.tsx +361 -0
  183. package/blocks/dialer/components/dialer-session-detail.tsx +153 -0
  184. package/blocks/dialer/components/disposition-panel.tsx +1 -1
  185. package/blocks/dialer/components/live-calls-table.tsx +7 -3
  186. package/blocks/dialer/components/record-calls-tab.tsx +101 -0
  187. package/blocks/dialer/components/session-start-form.tsx +61 -12
  188. package/blocks/dialer/components/softphone.tsx +4 -2
  189. package/blocks/enrichment/README.md +29 -7
  190. package/blocks/enrichment/block.json +49 -9
  191. package/blocks/enrichment/components/bulk-enrich-panel.tsx +83 -29
  192. package/blocks/enrichment/components/email-verify-badge.tsx +31 -11
  193. package/blocks/enrichment/components/enrich-button.tsx +32 -9
  194. package/blocks/enrichment/components/enrichment-job-detail.tsx +78 -0
  195. package/blocks/enrichment/components/enrichment-screen.tsx +341 -0
  196. package/blocks/enrichment/components/waterfall-config.tsx +66 -17
  197. package/blocks/enrichment/lib/enrichment-types.ts +39 -0
  198. package/blocks/enrichment/recipes/bulk-enrich-and-poll.ts +15 -4
  199. package/blocks/enrichment/recipes/waterfall-pipeline.ts +3 -2
  200. package/blocks/forms/README.md +8 -0
  201. package/blocks/forms/block.json +139 -18
  202. package/blocks/forms/components/form-activity.tsx +71 -0
  203. package/blocks/forms/components/form-backfill.tsx +108 -0
  204. package/blocks/forms/components/form-builder.tsx +4 -2
  205. package/blocks/forms/components/form-embed.tsx +4 -2
  206. package/blocks/forms/components/form-groups.tsx +151 -0
  207. package/blocks/forms/components/form-mapping-editor.tsx +6 -9
  208. package/blocks/forms/components/form-route-history.tsx +72 -0
  209. package/blocks/forms/components/form-saved-views.tsx +81 -0
  210. package/blocks/forms/components/forms-screen.tsx +56 -19
  211. package/blocks/forms/components/more-rows.tsx +30 -0
  212. package/blocks/forms/components/submissions-export.tsx +67 -0
  213. package/blocks/forms/components/submissions-table.tsx +17 -6
  214. package/blocks/forms/lib/forms-extra.ts +67 -0
  215. package/blocks/inbox/README.md +32 -3
  216. package/blocks/inbox/block.json +29 -2
  217. package/blocks/inbox/components/inbox-list.tsx +7 -3
  218. package/blocks/inbox/components/inbox-screen.tsx +294 -27
  219. package/blocks/inbox/components/record-conversations-tab.tsx +154 -0
  220. package/blocks/inbox/components/reply-composer.tsx +65 -9
  221. package/blocks/inbox/components/tag-and-assign.tsx +4 -2
  222. package/blocks/inbox/components/thread-badge.tsx +2 -2
  223. package/blocks/inbox/components/thread-view.tsx +1 -1
  224. package/blocks/inbox/hooks/use-inbox-thread.ts +1 -1
  225. package/blocks/inbox/hooks/use-inbox-threads.ts +1 -0
  226. package/blocks/inbox/lib/inbox-types.ts +47 -1
  227. package/blocks/inbox/recipes/01-triage-and-reply.ts +12 -2
  228. package/blocks/integrations/README.md +63 -1
  229. package/blocks/integrations/block.json +234 -15
  230. package/blocks/integrations/components/ad-accounts.tsx +82 -0
  231. package/blocks/integrations/components/connection-health.tsx +59 -0
  232. package/blocks/integrations/components/crm-detail.tsx +119 -0
  233. package/blocks/integrations/components/crm-records.tsx +103 -0
  234. package/blocks/integrations/components/field-mappings.tsx +61 -0
  235. package/blocks/integrations/components/integration-list.tsx +13 -8
  236. package/blocks/integrations/components/integrations-screen.tsx +152 -0
  237. package/blocks/integrations/components/migration-panel.tsx +133 -0
  238. package/blocks/integrations/components/sugarcrm-connect.tsx +95 -0
  239. package/blocks/integrations/components/sync-status.tsx +11 -9
  240. package/blocks/integrations/components/sync-triggers.tsx +134 -0
  241. package/blocks/integrations/components/webhook-detail.tsx +179 -0
  242. package/blocks/integrations/components/webhook-manager.tsx +43 -25
  243. package/blocks/integrations/components/workspace-tools.tsx +127 -0
  244. package/blocks/integrations/lib/crm-utils.ts +39 -0
  245. package/blocks/integrations/lib/facts.tsx +13 -0
  246. package/blocks/integrations/lib/integrations-utils.ts +11 -1
  247. package/blocks/integrations/lib/load-more.tsx +141 -0
  248. package/blocks/intent/README.md +14 -0
  249. package/blocks/intent/block.json +27 -1
  250. package/blocks/intent/components/account-intent-score.tsx +5 -5
  251. package/blocks/intent/components/intent-feed.tsx +13 -10
  252. package/blocks/intent/components/intent-keyword-manager.tsx +16 -12
  253. package/blocks/intent/components/intent-screen.tsx +265 -0
  254. package/blocks/intent/components/keyword-detail.tsx +124 -0
  255. package/blocks/intent/lib/intent-utils.ts +4 -4
  256. package/blocks/lifecycle/block.json +13 -8
  257. package/blocks/lifecycle/components/account-related.tsx +8 -1
  258. package/blocks/lifecycle/components/churn-list.tsx +5 -2
  259. package/blocks/lifecycle/components/customer-table.tsx +1 -1
  260. package/blocks/lifecycle/components/lifecycle-board.tsx +3 -1
  261. package/blocks/lifecycle/components/lifecycle-screen.tsx +3 -1
  262. package/blocks/lifecycle/lib/lifecycle.ts +1 -1
  263. package/blocks/lists/README.md +20 -1
  264. package/blocks/lists/block.json +69 -3
  265. package/blocks/lists/components/add-company-people-to-list-button.tsx +73 -0
  266. package/blocks/lists/components/add-to-list-button.tsx +20 -9
  267. package/blocks/lists/components/list-picker.tsx +17 -3
  268. package/blocks/lists/components/list-table.tsx +12 -6
  269. package/blocks/lists/components/lists-screen.tsx +346 -0
  270. package/blocks/lists/components/record-lists-tab.tsx +99 -0
  271. package/blocks/lists/components/suppression-manager.tsx +33 -8
  272. package/blocks/lists/components/suppressions-screen.tsx +264 -0
  273. package/blocks/mailboxes/README.md +17 -0
  274. package/blocks/mailboxes/block.json +69 -17
  275. package/blocks/mailboxes/components/connect-mailbox.tsx +32 -21
  276. package/blocks/mailboxes/components/domain-detail.tsx +148 -0
  277. package/blocks/mailboxes/components/domain-purchase.tsx +20 -14
  278. package/blocks/mailboxes/components/mailbox-detail.tsx +157 -0
  279. package/blocks/mailboxes/components/mailbox-list.tsx +8 -3
  280. package/blocks/mailboxes/components/mailboxes-screen.tsx +228 -0
  281. package/blocks/mailboxes/components/warmup-health.tsx +24 -22
  282. package/blocks/mailboxes/lib/mailboxes-utils.ts +26 -5
  283. package/blocks/mailboxes/lib/use-provider-domains.ts +23 -0
  284. package/blocks/newsletter/README.md +12 -0
  285. package/blocks/newsletter/block.json +157 -24
  286. package/blocks/newsletter/components/issue-scheduler.tsx +4 -3
  287. package/blocks/newsletter/components/issue-versions.tsx +93 -0
  288. package/blocks/newsletter/components/more-rows.tsx +30 -0
  289. package/blocks/newsletter/components/newsletter-editor.tsx +1 -1
  290. package/blocks/newsletter/components/newsletter-list-syncs.tsx +121 -0
  291. package/blocks/newsletter/components/newsletter-screen.tsx +39 -14
  292. package/blocks/newsletter/components/newsletter-settings.tsx +211 -0
  293. package/blocks/newsletter/components/newsletter-stats.tsx +2 -2
  294. package/blocks/newsletter/components/newsletter-templates.tsx +133 -0
  295. package/blocks/newsletter/components/subscriber-table.tsx +5 -7
  296. package/blocks/newsletter/components/subscriber-timeline.tsx +65 -0
  297. package/blocks/newsletter/lib/newsletter-extra.ts +60 -0
  298. package/blocks/nurture/block.json +28 -14
  299. package/blocks/nurture/components/nurture-builder.tsx +13 -3
  300. package/blocks/nurture/components/nurture-enroll.tsx +12 -10
  301. package/blocks/nurture/components/nurture-form.tsx +27 -10
  302. package/blocks/nurture/components/nurture-screen.tsx +26 -11
  303. package/blocks/nurture/components/nurture-stats.tsx +5 -4
  304. package/blocks/nurture/lib/nurture-types.ts +1 -1
  305. package/blocks/objects/README.md +18 -1
  306. package/blocks/objects/block.json +42 -21
  307. package/blocks/objects/components/attribute-field-input.tsx +14 -1
  308. package/blocks/objects/components/object-not-found.tsx +3 -1
  309. package/blocks/objects/components/object-record-detail.tsx +10 -2
  310. package/blocks/objects/components/object-schema-editor.tsx +4 -2
  311. package/blocks/objects/components/object-table.tsx +13 -3
  312. package/blocks/objects/components/objects-screen.tsx +147 -0
  313. package/blocks/objects/components/record-roles-panel.tsx +15 -5
  314. package/blocks/objects/lib/object-types.ts +1 -1
  315. package/blocks/pages/README.md +14 -0
  316. package/blocks/pages/block.json +140 -23
  317. package/blocks/pages/components/brand-kit-editor.tsx +5 -2
  318. package/blocks/pages/components/content-library.tsx +9 -4
  319. package/blocks/pages/components/more-rows.tsx +30 -0
  320. package/blocks/pages/components/page-ai-tools.tsx +196 -0
  321. package/blocks/pages/components/page-analytics.tsx +176 -0
  322. package/blocks/pages/components/page-clone.tsx +99 -0
  323. package/blocks/pages/components/page-domains.tsx +167 -0
  324. package/blocks/pages/components/page-editor.tsx +1 -1
  325. package/blocks/pages/components/page-generation-status.tsx +48 -0
  326. package/blocks/pages/components/page-list.tsx +2 -1
  327. package/blocks/pages/components/page-tracking.tsx +137 -0
  328. package/blocks/pages/components/pages-screen.tsx +57 -16
  329. package/blocks/pages/components/seo-report.tsx +6 -1
  330. package/blocks/pages/lib/studio.ts +7 -0
  331. package/blocks/phone-numbers/README.md +74 -0
  332. package/blocks/phone-numbers/block.json +262 -0
  333. package/blocks/phone-numbers/components/a2p-registration.tsx +230 -0
  334. package/blocks/phone-numbers/components/assign-number.tsx +104 -0
  335. package/blocks/phone-numbers/components/number-search.tsx +239 -0
  336. package/blocks/phone-numbers/components/number-settings.tsx +134 -0
  337. package/blocks/phone-numbers/components/number-usage.tsx +97 -0
  338. package/blocks/phone-numbers/components/phone-number-detail.tsx +84 -0
  339. package/blocks/phone-numbers/components/phone-number-list.tsx +110 -0
  340. package/blocks/phone-numbers/components/phone-numbers-screen.tsx +201 -0
  341. package/blocks/phone-numbers/components/register-owned-number.tsx +98 -0
  342. package/blocks/phone-numbers/components/release-number.tsx +126 -0
  343. package/blocks/phone-numbers/hooks/use-phone-numbers.ts +58 -0
  344. package/blocks/phone-numbers/lib/phone-numbers-utils.ts +202 -0
  345. package/blocks/phone-numbers/recipes/01-search-and-buy-number.ts +49 -0
  346. package/blocks/phone-numbers/recipes/02-assign-number-to-rep.ts +25 -0
  347. package/blocks/phone-numbers/recipes/03-audit-numbers.ts +36 -0
  348. package/blocks/phone-numbers/recipes/04-register-text-messaging.ts +39 -0
  349. package/blocks/pickers/README.md +23 -0
  350. package/blocks/pickers/block.json +103 -0
  351. package/blocks/pickers/components/company-picker.tsx +90 -0
  352. package/blocks/pickers/components/contact-picker.tsx +131 -0
  353. package/blocks/pickers/components/member-picker.tsx +99 -0
  354. package/blocks/pickers/components/search-picker.tsx +98 -0
  355. package/blocks/pickers/hooks/use-current-member.ts +104 -0
  356. package/blocks/pickers/hooks/use-picker-pages.ts +73 -0
  357. package/blocks/pickers/lib/use-debounced.ts +13 -0
  358. package/blocks/quotes/README.md +13 -0
  359. package/blocks/quotes/block.json +65 -13
  360. package/blocks/quotes/components/create-quote-from-deal.tsx +48 -0
  361. package/blocks/quotes/components/product-picker.tsx +3 -1
  362. package/blocks/quotes/components/quote-builder.tsx +1 -1
  363. package/blocks/quotes/components/quote-lifecycle-actions.tsx +146 -0
  364. package/blocks/quotes/components/quote-list.tsx +5 -3
  365. package/blocks/quotes/components/quote-related.tsx +8 -4
  366. package/blocks/quotes/components/quote-viewer.tsx +7 -2
  367. package/blocks/quotes/components/record-quotes-tab.tsx +90 -0
  368. package/blocks/radar/README.md +10 -0
  369. package/blocks/radar/block.json +41 -1
  370. package/blocks/radar/components/competitor-battle-card.tsx +1 -1
  371. package/blocks/radar/components/competitor-detail.tsx +117 -0
  372. package/blocks/radar/components/competitor-tracker.tsx +3 -1
  373. package/blocks/radar/components/radar-overview.tsx +4 -4
  374. package/blocks/radar/components/radar-report.tsx +4 -2
  375. package/blocks/radar/components/radar-screen.tsx +214 -0
  376. package/blocks/radar/components/report-detail.tsx +104 -0
  377. package/blocks/search/README.md +10 -0
  378. package/blocks/search/block.json +16 -1
  379. package/blocks/search/components/filter-builder.tsx +3 -3
  380. package/blocks/search/components/prospect-results.tsx +5 -3
  381. package/blocks/search/components/prospect-search-screen.tsx +235 -0
  382. package/blocks/search/components/saved-searches.tsx +4 -1
  383. package/blocks/search/hooks/use-filter-options.ts +20 -6
  384. package/blocks/search/lib/search-types.ts +2 -0
  385. package/blocks/sequencer/README.md +55 -9
  386. package/blocks/sequencer/block.json +126 -19
  387. package/blocks/sequencer/components/add-to-sequence-button.tsx +82 -0
  388. package/blocks/sequencer/components/enroll-dialog.tsx +11 -5
  389. package/blocks/sequencer/components/record-sequences-tab.tsx +126 -0
  390. package/blocks/sequencer/components/sequence-builder.tsx +224 -60
  391. package/blocks/sequencer/components/sequence-detail.tsx +261 -0
  392. package/blocks/sequencer/components/sequence-enrollments.tsx +116 -0
  393. package/blocks/sequencer/components/sequence-list.tsx +34 -9
  394. package/blocks/sequencer/components/sequence-stats.tsx +11 -10
  395. package/blocks/sequencer/components/sequence-steps-panel.tsx +103 -0
  396. package/blocks/sequencer/components/sequences-screen.tsx +162 -0
  397. package/blocks/sequencer/components/step-editor.tsx +14 -12
  398. package/blocks/sequencer/lib/sequencer-utils.ts +133 -10
  399. package/blocks/sequencer/recipes/create-multichannel-sequence.ts +33 -5
  400. package/blocks/sequencer/recipes/launch-and-enroll.ts +19 -2
  401. package/blocks/social-ads/README.md +19 -0
  402. package/blocks/social-ads/block.json +233 -1
  403. package/blocks/social-ads/components/ad-campaign-list.tsx +9 -5
  404. package/blocks/social-ads/components/ads-screen.tsx +152 -0
  405. package/blocks/social-ads/components/audience-sync-detail.tsx +194 -0
  406. package/blocks/social-ads/components/audience-sync.tsx +17 -9
  407. package/blocks/social-ads/components/campaign-ads.tsx +166 -0
  408. package/blocks/social-ads/components/campaign-detail.tsx +138 -0
  409. package/blocks/social-ads/components/campaign-editor.tsx +134 -0
  410. package/blocks/social-ads/components/creative-concepts.tsx +74 -0
  411. package/blocks/social-ads/components/creative-detail.tsx +155 -0
  412. package/blocks/social-ads/components/creative-gallery.tsx +35 -7
  413. package/blocks/social-ads/components/creative-revisions.tsx +57 -0
  414. package/blocks/social-ads/components/creative-tools.tsx +176 -0
  415. package/blocks/social-ads/components/post-composer.tsx +7 -3
  416. package/blocks/social-ads/components/post-detail.tsx +163 -0
  417. package/blocks/social-ads/components/social-ideas.tsx +64 -0
  418. package/blocks/social-ads/components/social-performance.tsx +80 -0
  419. package/blocks/social-ads/components/social-post-list.tsx +11 -3
  420. package/blocks/social-ads/components/social-screen.tsx +187 -0
  421. package/blocks/social-ads/lib/ads-extra.ts +67 -0
  422. package/blocks/surveys/README.md +91 -0
  423. package/blocks/surveys/block.json +299 -0
  424. package/blocks/surveys/components/account-nps.tsx +69 -0
  425. package/blocks/surveys/components/contact-survey-history.tsx +52 -0
  426. package/blocks/surveys/components/org-summary.tsx +82 -0
  427. package/blocks/surveys/components/sending-domains.tsx +113 -0
  428. package/blocks/surveys/components/survey-form.tsx +126 -0
  429. package/blocks/surveys/components/survey-responses.tsx +145 -0
  430. package/blocks/surveys/components/survey-results.tsx +72 -0
  431. package/blocks/surveys/components/survey-send-history.tsx +58 -0
  432. package/blocks/surveys/components/survey-send.tsx +162 -0
  433. package/blocks/surveys/components/survey-triggers.tsx +166 -0
  434. package/blocks/surveys/components/surveys-screen.tsx +234 -0
  435. package/blocks/surveys/lib/surveys-types.ts +228 -0
  436. package/blocks/surveys/recipes/create-an-nps-survey.ts +22 -0
  437. package/blocks/surveys/recipes/send-a-survey-and-follow-it.ts +27 -0
  438. package/blocks/surveys/recipes/survey-score-report.ts +27 -0
  439. package/blocks/visitors/README.md +10 -0
  440. package/blocks/visitors/block.json +25 -1
  441. package/blocks/visitors/components/snippet-install.tsx +21 -10
  442. package/blocks/visitors/components/traffic-chart.tsx +4 -4
  443. package/blocks/visitors/components/visitor-company-card.tsx +26 -16
  444. package/blocks/visitors/components/visitor-detail.tsx +105 -0
  445. package/blocks/visitors/components/visitor-feed.tsx +16 -7
  446. package/blocks/visitors/components/visitors-screen.tsx +166 -0
  447. package/blocks/webchat/README.md +10 -0
  448. package/blocks/webchat/block.json +21 -7
  449. package/blocks/webchat/components/chat-widget-config.tsx +8 -5
  450. package/blocks/webchat/components/conversation-list.tsx +8 -4
  451. package/blocks/webchat/components/webchat-screen.tsx +245 -0
  452. package/blocks/workbench/README.md +11 -0
  453. package/blocks/workbench/block.json +48 -1
  454. package/blocks/workbench/components/column-recipe-editor.tsx +5 -3
  455. package/blocks/workbench/components/run-progress.tsx +1 -1
  456. package/blocks/workbench/components/workbench-grid.tsx +10 -4
  457. package/blocks/workbench/components/workbench-row-detail.tsx +104 -0
  458. package/blocks/workbench/components/workbench-screen.tsx +202 -0
  459. package/blocks/workbench/components/workbench-sources.tsx +194 -0
  460. package/blocks/workbench/components/workbench-table-list.tsx +14 -2
  461. package/blocks/workflows/README.md +13 -0
  462. package/blocks/workflows/block.json +28 -9
  463. package/blocks/workflows/components/run-history.tsx +31 -9
  464. package/blocks/workflows/components/trigger-config.tsx +3 -1
  465. package/blocks/workflows/components/workflow-editor.tsx +4 -2
  466. package/blocks/workflows/components/workflow-list.tsx +13 -6
  467. package/blocks/workflows/components/workflows-screen.tsx +193 -0
  468. package/dist/cli.js +3109 -1977
  469. package/dist/errors.d.mts +34 -0
  470. package/dist/errors.d.ts +34 -0
  471. package/dist/errors.js +46 -0
  472. package/dist/errors.js.map +1 -0
  473. package/dist/errors.mjs +21 -0
  474. package/dist/errors.mjs.map +1 -0
  475. package/dist/index.browser.js +11 -5
  476. package/dist/index.browser.js.map +1 -1
  477. package/dist/index.browser.mjs +11 -5
  478. package/dist/index.browser.mjs.map +1 -1
  479. package/dist/index.d.mts +164 -25
  480. package/dist/index.d.ts +164 -25
  481. package/dist/index.js +11 -5
  482. package/dist/index.js.map +1 -1
  483. package/dist/index.mjs +11 -5
  484. package/dist/index.mjs.map +1 -1
  485. package/dist/react.browser.js +10 -4
  486. package/dist/react.browser.js.map +1 -1
  487. package/dist/react.browser.mjs +10 -4
  488. package/dist/react.browser.mjs.map +1 -1
  489. package/dist/react.d.mts +142 -5
  490. package/dist/react.d.ts +142 -5
  491. package/dist/react.js +10 -4
  492. package/dist/react.js.map +1 -1
  493. package/dist/react.mjs +10 -4
  494. package/dist/react.mjs.map +1 -1
  495. package/dist/types/blocks/add.d.ts +11 -4
  496. package/dist/types/blocks/brand.d.ts +122 -0
  497. package/dist/types/blocks/compose.d.ts +53 -0
  498. package/dist/types/blocks/create.d.ts +27 -20
  499. package/dist/types/blocks/doctor.d.ts +6 -1
  500. package/dist/types/blocks/flows.d.ts +7 -1
  501. package/dist/types/blocks/navfile.d.ts +35 -0
  502. package/dist/types/blocks/orgBrand.d.ts +34 -0
  503. package/dist/types/blocks/paths.d.ts +4 -0
  504. package/dist/types/blocks/prefixes.d.ts +37 -0
  505. package/dist/types/blocks/registry.d.ts +17 -0
  506. package/dist/types/blocks/screens.d.ts +53 -0
  507. package/dist/types/cli.d.ts +5 -0
  508. package/dist/types/errors.d.ts +33 -0
  509. package/dist/types/http.d.ts +2 -18
  510. package/dist/types/version.d.ts +2 -2
  511. package/docs/agents.md +15 -4
  512. package/docs/api/README.md +2 -2
  513. package/docs/api/by-path.md +1 -0
  514. package/docs/api/desk.d.ts +98 -2
  515. package/docs/api/desk.md +123 -1
  516. package/docs/api/inbox.d.ts +10 -2
  517. package/docs/api/inbox.md +10 -2
  518. package/docs/api/seo.d.ts +19 -1
  519. package/docs/api/seo.md +24 -1
  520. package/package.json +16 -2
  521. package/stacks/6sense/pages/companies.tsx.tmpl +21 -0
  522. package/stacks/6sense/pages/contacts.tsx.tmpl +19 -0
  523. package/stacks/6sense/pages/tasks.tsx.tmpl +19 -0
  524. package/stacks/6sense.json +55 -17
  525. package/stacks/apollo/pages/calls.tsx.tmpl +23 -0
  526. package/stacks/apollo/pages/companies.tsx.tmpl +33 -0
  527. package/stacks/apollo/pages/contacts.tsx.tmpl +51 -0
  528. package/stacks/apollo/pages/deals.tsx.tmpl +17 -0
  529. package/stacks/apollo/pages/inbox-contact.tsx.tmpl +13 -0
  530. package/stacks/apollo/pages/lists.tsx.tmpl +12 -0
  531. package/stacks/apollo/pages/meetings.tsx.tmpl +13 -0
  532. package/stacks/apollo/pages/sequences.tsx.tmpl +12 -0
  533. package/stacks/apollo/pages/tasks.tsx.tmpl +20 -0
  534. package/stacks/apollo.json +147 -37
  535. package/stacks/calendly/pages/companies.tsx.tmpl +19 -0
  536. package/stacks/calendly/pages/contacts.tsx.tmpl +21 -0
  537. package/stacks/calendly/pages/meetings.tsx.tmpl +13 -0
  538. package/stacks/calendly/pages/tasks.tsx.tmpl +19 -0
  539. package/stacks/calendly.json +64 -0
  540. package/stacks/clay/pages/companies.tsx.tmpl +31 -0
  541. package/stacks/clay/pages/contacts.tsx.tmpl +31 -0
  542. package/stacks/clay/pages/lists.tsx.tmpl +12 -0
  543. package/stacks/clay/pages/tasks.tsx.tmpl +19 -0
  544. package/stacks/clay.json +73 -27
  545. package/stacks/gong/pages/calls.tsx.tmpl +23 -0
  546. package/stacks/gong/pages/companies.tsx.tmpl +22 -0
  547. package/stacks/gong/pages/contacts.tsx.tmpl +32 -0
  548. package/stacks/gong/pages/lists.tsx.tmpl +12 -0
  549. package/stacks/gong/pages/meetings.tsx.tmpl +13 -0
  550. package/stacks/gong/pages/tasks.tsx.tmpl +19 -0
  551. package/stacks/gong.json +98 -35
  552. package/stacks/hootsuite/pages/companies.tsx.tmpl +22 -0
  553. package/stacks/hootsuite/pages/contacts.tsx.tmpl +28 -0
  554. package/stacks/hootsuite/pages/lists.tsx.tmpl +12 -0
  555. package/stacks/hootsuite/pages/tasks.tsx.tmpl +19 -0
  556. package/stacks/hootsuite.json +104 -0
  557. package/stacks/hubspot/pages/companies.tsx.tmpl +26 -0
  558. package/stacks/hubspot/pages/contacts.tsx.tmpl +45 -0
  559. package/stacks/hubspot/pages/deals.tsx.tmpl +20 -0
  560. package/stacks/hubspot/pages/inbox.tsx.tmpl +103 -0
  561. package/stacks/hubspot/pages/lifecycle.tsx.tmpl +23 -0
  562. package/stacks/hubspot/pages/lists.tsx.tmpl +12 -0
  563. package/stacks/hubspot/pages/meetings.tsx.tmpl +13 -0
  564. package/stacks/hubspot/pages/quotes.tsx.tmpl +11 -0
  565. package/stacks/hubspot/pages/sequences.tsx.tmpl +12 -0
  566. package/stacks/hubspot/pages/tasks.tsx.tmpl +20 -0
  567. package/stacks/hubspot.json +181 -64
  568. package/stacks/intercom/pages/companies.tsx.tmpl +19 -0
  569. package/stacks/intercom/pages/contacts.tsx.tmpl +21 -0
  570. package/stacks/intercom/pages/inbox-contact.tsx.tmpl +13 -0
  571. package/stacks/intercom/pages/tasks.tsx.tmpl +19 -0
  572. package/stacks/intercom.json +52 -20
  573. package/stacks/mailchimp/pages/companies.tsx.tmpl +22 -0
  574. package/stacks/mailchimp/pages/contacts.tsx.tmpl +28 -0
  575. package/stacks/mailchimp/pages/lists.tsx.tmpl +12 -0
  576. package/stacks/mailchimp/pages/tasks.tsx.tmpl +19 -0
  577. package/stacks/mailchimp.json +68 -34
  578. package/stacks/outreach/pages/calls.tsx.tmpl +23 -0
  579. package/stacks/outreach/pages/companies.tsx.tmpl +22 -0
  580. package/stacks/outreach/pages/contacts.tsx.tmpl +46 -0
  581. package/stacks/outreach/pages/inbox-contact.tsx.tmpl +13 -0
  582. package/stacks/outreach/pages/lists.tsx.tmpl +12 -0
  583. package/stacks/outreach/pages/meetings.tsx.tmpl +13 -0
  584. package/stacks/outreach/pages/sequences.tsx.tmpl +12 -0
  585. package/stacks/outreach/pages/tasks.tsx.tmpl +19 -0
  586. package/stacks/outreach.json +106 -25
  587. package/stacks/pipedrive/pages/companies.tsx.tmpl +23 -0
  588. package/stacks/pipedrive/pages/contacts.tsx.tmpl +27 -0
  589. package/stacks/pipedrive/pages/deals.tsx.tmpl +20 -0
  590. package/stacks/pipedrive/pages/inbox.tsx.tmpl +103 -0
  591. package/stacks/pipedrive/pages/meetings.tsx.tmpl +13 -0
  592. package/stacks/pipedrive/pages/quotes.tsx.tmpl +11 -0
  593. package/stacks/pipedrive/pages/tasks.tsx.tmpl +20 -0
  594. package/stacks/pipedrive.json +117 -0
  595. package/stacks/salesforce/pages/companies.tsx.tmpl +26 -0
  596. package/stacks/salesforce/pages/contacts.tsx.tmpl +32 -0
  597. package/stacks/salesforce/pages/deals.tsx.tmpl +20 -0
  598. package/stacks/salesforce/pages/lifecycle.tsx.tmpl +23 -0
  599. package/stacks/salesforce/pages/lists.tsx.tmpl +12 -0
  600. package/stacks/salesforce/pages/quotes.tsx.tmpl +11 -0
  601. package/stacks/salesforce/pages/tasks.tsx.tmpl +20 -0
  602. package/stacks/salesforce.json +85 -31
  603. package/stacks/zoominfo/pages/companies.tsx.tmpl +31 -0
  604. package/stacks/zoominfo/pages/contacts.tsx.tmpl +31 -0
  605. package/stacks/zoominfo/pages/lists.tsx.tmpl +12 -0
  606. package/stacks/zoominfo/pages/tasks.tsx.tmpl +19 -0
  607. package/stacks/zoominfo.json +115 -0
  608. package/styles/styles.css +1 -1
  609. package/templates/next-app/README.md.tmpl +40 -9
  610. package/templates/next-app/app/globals.css.tmpl +349 -64
  611. package/templates/next-app/app/layout.tsx.tmpl +7 -2
  612. package/templates/next-app/components/app-shell.tsx.tmpl +104 -88
  613. package/templates/next-app/components/shell/quick-jump.tsx.tmpl +4 -0
  614. package/templates/next-app/dot-gitignore.tmpl +2 -0
  615. package/templates/next-app/package.json.tmpl +1 -1
@@ -0,0 +1,127 @@
1
+ /**
2
+ * Server side of the Connect graph8 screen (local preview only), mounted at `app/api/g8-connect/route.ts`:
3
+ *
4
+ * GET -> { localPreview: true, connected, source: "env" | "file" | null, keyHint, account }
5
+ * POST { key } -> validates the key with a cheap read (GET /api/v1/me) and stores it in .g8/local-key
6
+ * DELETE -> removes the stored key
7
+ *
8
+ * It answers ONLY `next dev` requests from this machine (same check as the proxy's local preview). In a
9
+ * production build every method is 404, as if the route did not exist. The key is never echoed back: the
10
+ * answer carries only a hint (`...wxyz`) and the key's account (name, workspace, scopes) from /me.
11
+ * When G8_API_KEY is set in the environment it wins, so POST and DELETE refuse (409) and say where to change it.
12
+ */
13
+
14
+ import { DEFAULT_API_URL, isLocalPreviewRequest } from "./proxy";
15
+ import { currentKey, keyHint, removeLocalKey, writeLocalKey, LOCAL_KEY_FILE } from "./local-key";
16
+
17
+ export interface G8ConnectConfig {
18
+ /** Replace `fetch` (tests). */
19
+ fetch?: typeof fetch;
20
+ /** Project root holding `.g8/` (tests). Default: process.cwd(). */
21
+ root?: string;
22
+ }
23
+
24
+ export interface ConnectedAccount {
25
+ name?: string;
26
+ workspace?: string;
27
+ scopes?: string[];
28
+ }
29
+
30
+ function json(status: number, body: Record<string, unknown>): Response {
31
+ return new Response(JSON.stringify(body), { status, headers: { "content-type": "application/json", "cache-control": "no-store" } });
32
+ }
33
+
34
+ const str = (v: unknown): string | undefined => (typeof v === "string" && v ? v : undefined);
35
+
36
+ /** The safe, human facts about a key from GET /me (never the key itself). */
37
+ export function accountFromMe(body: unknown): ConnectedAccount {
38
+ const root = (body ?? {}) as Record<string, unknown>;
39
+ const d = ((root.data as Record<string, unknown> | undefined) ?? root) as Record<string, unknown>;
40
+ const org = d.organization as Record<string, unknown> | undefined;
41
+ const scopes = Array.isArray(d.scopes) ? d.scopes.filter((s): s is string => typeof s === "string") : undefined;
42
+ return { name: str(d.name) ?? str(d.key_name) ?? str(d.label), workspace: str(org?.name) ?? str(d.org_name) ?? str(d.organization_name), scopes };
43
+ }
44
+
45
+ /** A pasted key that is plausibly a key: printable, no spaces, 8 to 512 characters. */
46
+ export function plausibleKey(value: unknown): string | null {
47
+ if (typeof value !== "string") return null;
48
+ const key = value.trim();
49
+ return key.length >= 8 && key.length <= 512 && /^[\x21-\x7e]+$/.test(key) ? key : null;
50
+ }
51
+
52
+ type Checked = { ok: true; account: ConnectedAccount } | { ok: false; status: number; error: string; message: string };
53
+
54
+ /** Ask graph8 who the key is: GET /api/v1/me (free, read-only). */
55
+ export async function checkKey(key: string, doFetch: typeof fetch): Promise<Checked> {
56
+ const base = (process.env.G8_API_URL ?? DEFAULT_API_URL).replace(/\/+$/, "");
57
+ let res: Response;
58
+ try {
59
+ res = await doFetch(`${base}/api/v1/me`, { headers: { authorization: `Bearer ${key}`, accept: "application/json" }, cache: "no-store", redirect: "manual" });
60
+ } catch {
61
+ return { ok: false, status: 502, error: "upstream_unreachable", message: "Could not reach the graph8 API to check the key." };
62
+ }
63
+ const body = await res.json().catch(() => ({}));
64
+ if (res.ok) return { ok: true, account: accountFromMe(body) };
65
+ if (res.status === 401 || res.status === 403) {
66
+ return { ok: false, status: 400, error: "key_rejected", message: "graph8 did not accept this key. Copy it again from graph8 (Settings > Developers > API keys)." };
67
+ }
68
+ return { ok: false, status: 502, error: "upstream_error", message: `graph8 answered HTTP ${res.status} while checking the key. Try again.` };
69
+ }
70
+
71
+ /** Build the GET/POST/DELETE handlers for `app/api/g8-connect/route.ts`. */
72
+ export function createG8ConnectRoute(config: G8ConnectConfig = {}) {
73
+ const doFetch = (): typeof fetch => config.fetch ?? globalThis.fetch;
74
+
75
+ function refuse(request: Request): Response | null {
76
+ if (process.env.NODE_ENV === "production") return json(404, { error: "not_found" });
77
+ if (!isLocalPreviewRequest(request)) {
78
+ return json(403, { error: "local_preview_only", message: "The Connect graph8 screen only works from this machine (http://localhost)." });
79
+ }
80
+ return null;
81
+ }
82
+
83
+ async function status(): Promise<Record<string, unknown>> {
84
+ const current = await currentKey(config.root);
85
+ if (!current) return { localPreview: true, connected: false, source: null, keyFile: LOCAL_KEY_FILE };
86
+ const checked = await checkKey(current.key, doFetch());
87
+ return {
88
+ localPreview: true,
89
+ connected: checked.ok,
90
+ source: current.source,
91
+ keyHint: keyHint(current.key),
92
+ keyFile: LOCAL_KEY_FILE,
93
+ ...(checked.ok ? { account: checked.account } : { problem: checked.message }),
94
+ };
95
+ }
96
+
97
+ async function GET(request: Request): Promise<Response> {
98
+ return refuse(request) ?? json(200, await status());
99
+ }
100
+
101
+ async function POST(request: Request): Promise<Response> {
102
+ const refused = refuse(request);
103
+ if (refused) return refused;
104
+ if ((await currentKey(config.root))?.source === "env") {
105
+ return json(409, { error: "key_in_environment", message: "G8_API_KEY is set in the server environment (.env.local), and it wins. Change it there, then restart `npm run dev`." });
106
+ }
107
+ const body = (await request.json().catch(() => ({}))) as { key?: unknown };
108
+ const key = plausibleKey(body.key);
109
+ if (!key) return json(400, { error: "invalid_key", message: "Paste a graph8 API key: one line, no spaces." });
110
+ const checked = await checkKey(key, doFetch());
111
+ if (!checked.ok) return json(checked.status, { error: checked.error, message: checked.message });
112
+ await writeLocalKey(key, config.root);
113
+ return json(200, { localPreview: true, connected: true, source: "file", keyHint: keyHint(key), keyFile: LOCAL_KEY_FILE, account: checked.account });
114
+ }
115
+
116
+ async function DELETE(request: Request): Promise<Response> {
117
+ const refused = refuse(request);
118
+ if (refused) return refused;
119
+ if ((await currentKey(config.root))?.source === "env") {
120
+ return json(409, { error: "key_in_environment", message: "G8_API_KEY is set in the server environment (.env.local). Remove it there, then restart `npm run dev`." });
121
+ }
122
+ await removeLocalKey(config.root);
123
+ return json(200, { localPreview: true, connected: false, source: null, keyFile: LOCAL_KEY_FILE });
124
+ }
125
+
126
+ return { GET, POST, DELETE };
127
+ }
@@ -0,0 +1,70 @@
1
+ /**
2
+ * The graph8 API key for local preview, kept on the SERVER: the Connect graph8 screen posts a pasted key to
3
+ * `app/api/g8-connect/route.ts`, which validates it and stores it here, in `.g8/local-key` at the project root
4
+ * (file mode 0600, folder 0700, with its own `.gitignore` so it is never committed). The browser never holds it.
5
+ *
6
+ * resolveApiKey(): G8_API_KEY from the environment wins; otherwise, outside production, the stored key.
7
+ *
8
+ * Node only (reads the file system); the Next route that imports it runs on the Node runtime (the default).
9
+ * In a production build the file is never read: set G8_API_KEY in the deployment's environment.
10
+ */
11
+
12
+ import { promises as fs } from "node:fs";
13
+ import path from "node:path";
14
+
15
+ /** Where the key lives, relative to the project root (the directory `next dev` runs in). */
16
+ export const LOCAL_KEY_FILE = path.join(".g8", "local-key");
17
+
18
+ export type KeySource = "env" | "file";
19
+
20
+ const isProduction = (): boolean => process.env.NODE_ENV === "production";
21
+
22
+ function keyPath(root: string = process.cwd()): string {
23
+ return path.join(root, LOCAL_KEY_FILE);
24
+ }
25
+
26
+ /** The stored key, or undefined (none, unreadable, or a production build). */
27
+ export async function readLocalKey(root?: string): Promise<string | undefined> {
28
+ if (isProduction()) return undefined;
29
+ try {
30
+ const key = (await fs.readFile(keyPath(root), "utf8")).trim();
31
+ return key || undefined;
32
+ } catch {
33
+ return undefined;
34
+ }
35
+ }
36
+
37
+ /** The key the proxy uses, and where it came from. The environment always wins. */
38
+ export async function currentKey(root?: string): Promise<{ key: string; source: KeySource } | null> {
39
+ const env = process.env.G8_API_KEY?.trim();
40
+ if (env) return { key: env, source: "env" };
41
+ const stored = await readLocalKey(root);
42
+ return stored ? { key: stored, source: "file" } : null;
43
+ }
44
+
45
+ /** For `createG8Proxy({ apiKey: resolveApiKey })`. */
46
+ export async function resolveApiKey(): Promise<string | undefined> {
47
+ return (await currentKey())?.key;
48
+ }
49
+
50
+ /** Store a key (validated by the caller): 0700 folder, 0600 file, and a `.gitignore` that ignores the folder. */
51
+ export async function writeLocalKey(key: string, root?: string): Promise<void> {
52
+ const file = keyPath(root);
53
+ const dir = path.dirname(file);
54
+ await fs.mkdir(dir, { recursive: true, mode: 0o700 });
55
+ await fs.writeFile(path.join(dir, ".gitignore"), "# Written by the graph8 Connect screen: never commit this folder.\n*\n", { mode: 0o644 });
56
+ const tmp = `${file}.${process.pid}.tmp`;
57
+ await fs.writeFile(tmp, `${key}\n`, { mode: 0o600 });
58
+ await fs.chmod(tmp, 0o600);
59
+ await fs.rename(tmp, file);
60
+ }
61
+
62
+ /** Remove the stored key. Missing is fine. */
63
+ export async function removeLocalKey(root?: string): Promise<void> {
64
+ await fs.rm(keyPath(root), { force: true });
65
+ }
66
+
67
+ /** `...wxyz`: enough for a person to recognise which key is in use, never enough to use it. */
68
+ export function keyHint(key: string): string {
69
+ return key.length > 8 ? `...${key.slice(-4)}` : "...";
70
+ }
@@ -14,6 +14,11 @@
14
14
  * and `allowedPrefixes` (only the areas the UI needs). The opt-outs
15
15
  * `dangerouslyAllowUnauthenticated` and `dangerouslyAllowAllPaths` exist for
16
16
  * local prototypes only.
17
+ *
18
+ * LOCAL PREVIEW (`localPreview: true`, set in apps made by `graph8-sdk create`):
19
+ * until `authorize` is set, the route answers ONLY `next dev` requests made
20
+ * from this machine (see `isLocalPreviewRequest`). A production build refuses
21
+ * every request (500) until `authorize` is set; the setting then does nothing.
17
22
  */
18
23
 
19
24
  export interface G8ProxyConfig {
@@ -42,6 +47,19 @@ export interface G8ProxyConfig {
42
47
  * `targetOrgId` is set.
43
48
  */
44
49
  allowTargetOrgHeader?: boolean;
50
+ /**
51
+ * Local preview, for `npm run dev` before your app has sign-in. Only applies while `authorize` is NOT set:
52
+ * the proxy then answers a request only when NODE_ENV is not "production" AND the request comes from this
53
+ * machine (Host localhost, 127.0.0.1 or [::1], same-origin, no forwarding proxy in between). Anything else
54
+ * gets 403; a production build gets 500 until you set `authorize`. Default false.
55
+ */
56
+ localPreview?: boolean;
57
+ /**
58
+ * Where the server's graph8 API key comes from. Default: `process.env.G8_API_KEY`, read on every request.
59
+ * Created apps pass `resolveApiKey` (g8/server/local-key.ts): the environment first, then, in local
60
+ * preview only, the key pasted in the Connect graph8 screen.
61
+ */
62
+ apiKey?: () => string | undefined | Promise<string | undefined>;
45
63
  /** Prototype opt-out: run without `authorize`. Anyone who can reach the route can use your key. */
46
64
  dangerouslyAllowUnauthenticated?: boolean;
47
65
  /** Prototype opt-out: run without `allowedPrefixes` (every /api/v1 path is reachable). */
@@ -158,9 +176,81 @@ async function readBodyCapped(request: Request, max: number): Promise<ArrayBuffe
158
176
  return out;
159
177
  }
160
178
 
179
+ const LOOPBACK_HOSTS = new Set(["localhost", "127.0.0.1", "[::1]", "::1"]);
180
+ const LOOPBACK_ADDRESSES = /^(127\.\d{1,3}\.\d{1,3}\.\d{1,3}|::1|::ffff:127\.\d{1,3}\.\d{1,3}\.\d{1,3}|localhost)$/i;
181
+
182
+ /** `localhost:3000` -> `localhost`, `[::1]:3000` -> `[::1]`. */
183
+ function hostnameOf(host: string): string {
184
+ const h = host.trim().toLowerCase();
185
+ if (h.startsWith("[")) return h.slice(0, h.indexOf("]") + 1);
186
+ return h.replace(/:\d+$/, "");
187
+ }
188
+
189
+ function isLoopbackOrigin(value: string): boolean {
190
+ try {
191
+ return LOOPBACK_HOSTS.has(new URL(value).hostname.toLowerCase());
192
+ } catch {
193
+ return false;
194
+ }
195
+ }
196
+
197
+ /**
198
+ * True when a request was made on this machine, by this app's own page (or typed in the address bar):
199
+ * - Host (and X-Forwarded-Host, if any) is localhost, 127.0.0.1 or [::1], which also blocks DNS rebinding;
200
+ * - every X-Forwarded-For hop is a loopback address (tunnels such as ngrok add the real client);
201
+ * - the browser's Sec-Fetch-Site is same-origin or none, and Origin (if any) is a loopback origin,
202
+ * so another website open in the same browser cannot drive the proxy (CSRF).
203
+ * Headers can be forged by a client that reaches the dev server directly, so created apps also bind
204
+ * `next dev` to 127.0.0.1 (package.json). Never rely on this check in production: set `authorize`.
205
+ */
206
+ export function isLocalPreviewRequest(request: Request): boolean {
207
+ const host = request.headers.get("host") ?? new URL(request.url).host;
208
+ if (!LOOPBACK_HOSTS.has(hostnameOf(host))) return false;
209
+ const fwdHost = request.headers.get("x-forwarded-host");
210
+ if (fwdHost && !fwdHost.split(",").every((h) => LOOPBACK_HOSTS.has(hostnameOf(h)))) return false;
211
+ const fwdFor = request.headers.get("x-forwarded-for");
212
+ if (fwdFor && !fwdFor.split(",").every((a) => LOOPBACK_ADDRESSES.test(a.trim()))) return false;
213
+ const site = request.headers.get("sec-fetch-site");
214
+ if (site && site !== "same-origin" && site !== "none") return false;
215
+ const origin = request.headers.get("origin");
216
+ if (origin && !isLoopbackOrigin(origin)) return false;
217
+ return true;
218
+ }
219
+
220
+ const isProduction = (): boolean => process.env.NODE_ENV === "production";
221
+
222
+ let previewLogged = false;
223
+
224
+ /**
225
+ * The local-preview verdict for a request when `authorize` is unset: null to continue, or the refusal.
226
+ * Only called when `localPreview` is on and `authorize` is not set.
227
+ */
228
+ function localPreviewGate(request: Request): Response | null {
229
+ if (isProduction()) {
230
+ return json(500, {
231
+ error: "g8_proxy_misconfigured",
232
+ message:
233
+ "Local preview only runs under `next dev`. This is a production build, so set `authorize` (check your app's session) in app/api/g8/[...path]/route.ts before going live. `npx @graph8/sdk doctor --production` lists what is left.",
234
+ });
235
+ }
236
+ if (!isLocalPreviewRequest(request)) {
237
+ return json(403, {
238
+ error: "local_preview_only",
239
+ message: "Local preview only answers requests from this machine (http://localhost). Set `authorize` in app/api/g8/[...path]/route.ts to serve anyone else.",
240
+ });
241
+ }
242
+ if (!previewLogged) {
243
+ previewLogged = true;
244
+ console.warn(
245
+ "[graph8] Local preview: /api/g8 answers requests from this machine only, with no sign-in check. Set `authorize` in app/api/g8/[...path]/route.ts before you deploy.",
246
+ );
247
+ }
248
+ return null;
249
+ }
250
+
161
251
  /** The first reason this config is unsafe to serve, or null. Checked on every request. */
162
252
  function configProblem(config: G8ProxyConfig): string | null {
163
- if (!config.authorize && !config.dangerouslyAllowUnauthenticated) {
253
+ if (!config.authorize && !config.dangerouslyAllowUnauthenticated && !config.localPreview) {
164
254
  return "Set `authorize` (check your app's session) in app/api/g8/[...path]/route.ts. The proxy refuses to run without it.";
165
255
  }
166
256
  if (!config.allowedPrefixes && !config.dangerouslyAllowAllPaths) {
@@ -177,11 +267,21 @@ export function createG8Proxy(config: G8ProxyConfig = {}) {
177
267
  async function handle(request: Request, context: RouteContext): Promise<Response> {
178
268
  const problem = configProblem(config);
179
269
  if (problem) return json(500, { error: "g8_proxy_misconfigured", message: problem });
270
+ const preview = Boolean(config.localPreview && !config.authorize && !config.dangerouslyAllowUnauthenticated);
271
+ if (preview) {
272
+ const refused = localPreviewGate(request);
273
+ if (refused) return refused;
274
+ }
180
275
  const denied = await config.authorize?.(request);
181
276
  if (denied) return denied;
182
277
 
183
- const apiKey = process.env.G8_API_KEY;
184
- if (!apiKey) return json(500, { error: "g8_proxy_misconfigured", message: "G8_API_KEY is not set on the server." });
278
+ const apiKey = config.apiKey ? await config.apiKey() : process.env.G8_API_KEY;
279
+ if (!apiKey) {
280
+ const message = preview
281
+ ? "No graph8 API key yet: open this app in the browser and paste one in the Connect graph8 screen, or set G8_API_KEY in .env.local."
282
+ : "G8_API_KEY is not set on the server.";
283
+ return json(500, { error: "g8_proxy_misconfigured", message });
284
+ }
185
285
 
186
286
  const params = await (context.params as Promise<{ path?: string[] }> | { path?: string[] });
187
287
  const path = normalizePath(params?.path);
@@ -4,18 +4,30 @@
4
4
  *
5
5
  * Next.js only allows HTTP-method names and a few config exports from a route
6
6
  * file, so the proxy configuration is a plain constant here, not an export.
7
- * Edit it. The proxy REFUSES every request (500) until BOTH `authorize` and
8
- * `allowedPrefixes` are set, because this route carries the full-power API key.
7
+ * Edit it. Before you deploy, set `authorize`: a production build refuses every
8
+ * request (500) until it is set, because this route carries the full-power API key.
9
+ * `npx @graph8/sdk doctor --production` checks this file for you.
9
10
  */
10
11
 
11
12
  import { createG8Proxy } from "@/g8/server/proxy";
13
+ import { resolveApiKey } from "@/g8/server/local-key";
12
14
 
13
- // 1. Only the API areas this app's UI needs, relative to /api/v1. REQUIRED.
15
+ // 1. The API areas this app's UI may call, relative to /api/v1. REQUIRED.
16
+ // The lines between the graph8:allowed-prefixes markers are GENERATED from the operations the installed blocks
17
+ // declare, and rewritten by `npx @graph8/sdk add <block>` and `npx @graph8/sdk doctor --fix-prefixes`. To own the
18
+ // list yourself, delete both marker lines; the CLI then never touches it.
19
+ // graph8:allowed-prefixes:start
14
20
  const allowedPrefixes: string[] | undefined = undefined; // e.g. ["contacts", "companies", "lists"]
21
+ // graph8:allowed-prefixes:end
15
22
 
16
23
  export const { GET, POST, PUT, PATCH, DELETE } = createG8Proxy({
17
24
  allowedPrefixes,
18
- // 2. Check YOUR session and return a Response (401/403) to refuse. REQUIRED:
25
+ // 2. Local preview: until `authorize` is set, answer only `npm run dev` requests from this machine
26
+ // (http://localhost). Ignored once `authorize` is set; a production build never runs without `authorize`.
27
+ localPreview: true,
28
+ // The key: G8_API_KEY from the environment, else (local preview only) the one pasted in the Connect graph8 screen.
29
+ apiKey: resolveApiKey,
30
+ // 3. Check YOUR session and return a Response (401/403) to refuse. REQUIRED before you deploy:
19
31
  // authorize: async (request) => { if (!(await getSession(request))) return new Response("Unauthorized", { status: 401 }); },
20
32
  //
21
33
  // Agency keys only: pick the client org from the session, never from the browser:
@@ -4,6 +4,27 @@ An agent is a persona (how it talks), a voice, knowledge (documents and company
4
4
  (single-purpose actions). This block gives you the screens to build one, prove it works before anyone talks
5
5
  to it, and follow the runs agents do for you.
6
6
 
7
+ ## Screens
8
+
9
+ `AgentsScreen` (`components/agents-screen.tsx`) is the finished agents workspace; mount it as the page.
10
+
11
+ - **Agents tab**: stat strip (agents, active, inactive), search, status filter, the list, **New agent** (form sheet; the
12
+ agent starts inactive), activate / deactivate. Opening an agent (deep link `?id=`) shows a detail panel with
13
+ **Configure** (persona, voice, knowledge, skills, delete), **Test** (free dry runs, saved cases, the activation gate,
14
+ run a skill live) and **Runs** (this agent's runs).
15
+ - **Runs tab**: every run as a list; opening one (`?run=`) shows `AgentRunDetail` (status, step, credits, times, its approvals to approve or reject, cancel). Start a run here. `&view=full` opens any record as a full page.
16
+ - **Approvals tab**: everything agents ask permission for: the oversight summary, pending approvals (approve, reject, **request changes** with feedback) and the decided history with each approval's signed receipts.
17
+ - **Skill library tab**: every skill (yours plus graph8's), search, filter by kind and state, open one to edit it (**SkillEditor**: loaded first, only the changed fields are saved, placeholders, template check, enable/disable, delete), write a new LLM or API skill, or start from a template.
18
+ - **Company knowledge tab**: the entries agents draw on. Status strip, meaning-based search or browse by type and lifecycle, open an entry (content, history, sources, related), **New entry**, edit a draft, propose a new version of a published one, verify, deprecate; **Export** downloads everything.
19
+ - **Operators tab**: the autonomous monitors in your workspace: turn each on or off, set the trust dial per skill (off, detect, propose, auto), read findings, activity, health and scorecard.
20
+ - **Assistant tab**: your sessions with the graph8 assistant (list, open, rename, pin, delete, add a note) and **Ask** for one live turn; if the assistant starts a run, open it from here.
21
+ - An open agent also has **Conversations** (its chat history, rename, hand over to a human, delete, and a message box), **Activity** (calls, skill runs, chats, skill performance over 7, 30 or 90 days) and **Test history** (saved cases: edit, delete; every run). Its header has **Duplicate** and **Save as template**; the screen header has **From a template** and **Receptionist**.
22
+ - Lists never stop silently: agents load 100 at a time with "Load more"; conversations, sessions, runs and knowledge say when the API's own maximum is reached.
23
+ - Uploading documents, running a skill, starting or cancelling a run, approving, sending a chat message or an assistant turn, turning an operator or its trust dial up, switching the receptionist, and deleting anything are confirmed
24
+ with `ConfirmSpendDialog` inside the parts. Needs `voice:read|write|delete|run`, `knowledge:read|write`, `workflows:*`.
25
+ - Slots: `renderRowActions`, `renderDetailActions`, `extraDetailTabs`, `toolbarActions`. `AgentBuilder` gained
26
+ `hideList`; `AgentRuns` gained `selectedId`, `onSelectRun`, `hideDetail`, `refreshKey`; new `AgentRunDetail`.
27
+
7
28
  Install: `npx @graph8/sdk add agents` (installs `foundation` first).
8
29
 
9
30
  ## What you get
@@ -15,6 +36,16 @@ Install: `npx @graph8/sdk add agents` (installs `foundation` first).
15
36
  | `AgentSkillsPanel` | Attach / detach skills, write a new LLM skill | `agentId`, `onChanged` |
16
37
  | `AgentTestConsole` | Free dry runs, saved cases, regression sweep, the activation gate; run an attached skill live | `agentId` |
17
38
  | `AgentRuns` | Start a run, follow it (polled), cancel it, decide its approvals | `agentId`, `pageSize`, `pollMs` |
39
+ | `AgentRunDetail` | One run in full, its approvals, cancel, and **steer** it with an instruction while it is live | `runId`, `pollMs`, `onChanged` |
40
+ | `AgentActivity` | An agent's calls, skill runs, workflow runs, chats and skill performance | `agentId` |
41
+ | `AgentConversations` | An agent's chat history: open, rename, hand over to a human, delete, message it (billable) | `agentId`, `contactId` |
42
+ | `AgentTestHistory` | Saved test cases (edit, delete) and every run | `agentId` |
43
+ | `DuplicateAgentButton`, `SaveAsTemplateButton`, `FromTemplateButton`, `ReceptionistButton` | Copy an agent, keep it as a template, start from a template, set up the receptionist | `agent`, `onDuplicated` / `onCreated` |
44
+ | `SkillLibrary`, `SkillEditor` | Every skill in one list, and create / edit / delete one | `target`, `onClose`, `onChanged` |
45
+ | `KnowledgeBrowser`, `KnowledgeDetail`, `KnowledgeForm` | Company knowledge: browse, search, read, author, amend, verify, deprecate | `conceptId`, `mode`, `onChanged` |
46
+ | `AgentApprovals` | The approvals inbox with history and receipts | `onOpenRun` |
47
+ | `AgentOperators` | Autonomous operators: on/off, trust dials, findings, activity, health, scorecard | none |
48
+ | `AssistantSessions` | Sessions with the graph8 assistant | `onOpenRun` |
18
49
 
19
50
  ## The flow, with the ids that pass between steps
20
51
 
@@ -25,7 +56,7 @@ Install: `npx @graph8/sdk add agents` (installs `foundation` first).
25
56
  3. **Knowledge**: `POST /voice/agents/{agent_id}/documents/upload` (multipart field `files`, 5 MiB total per upload through the proxy,
26
57
  billable) and `GET .../documents`. `use_company_knowledge` is a plain field on the agent; company
27
58
  knowledge itself is read with `GET /knowledge/search?query=`.
28
- 4. **Skills**: `POST /skills { name, runtime_type: "llm", llm_config: { prompt, model } }` returns an
59
+ 4. **Skills**: `POST /skills { name, runtime_type: "llm", llm_config: { model, prompt_template } }` (voice requires `prompt_template`) returns an
29
60
  `action_id`; `POST /voice/agents/{agent_id}/skills { action_ids }` attaches it. Models come from
30
61
  `GET /skills/models`.
31
62
  5. **Test**: `POST /voice/agents/{agent_id}/test { input_message | test_case_id, channel, assertion_type,
@@ -63,13 +94,15 @@ export function AgentStudio() {
63
94
  through `ConfirmSpendDialog`.
64
95
  - Uploading documents is `billable` (they are embedded with a paid model): the dialog shows the file count
65
96
  and an estimate (`creditsPerFile`, default 5; there is no balance or price read, so it is an estimate).
97
+ - Sending a chat message to an agent and asking the assistant are `billable` (they run a model and may run skills or start a job). Turning an operator on and raising a trust dial are `billable` (they start work that proceeds on its own).
98
+ - Duplicating, saving a template, renaming, editing a skill or a test case, writing knowledge and verifying are writes (free). Deprecating a knowledge entry, deleting a skill, a conversation, a session or a test case are `destructive`. Switching the receptionist on or off and approving are confirmed as `external`.
66
99
  - Running a skill live is `external` (it may call an API or message someone). Starting a run is a write that
67
100
  spends credits as it works, so it is confirmed as `billable`. Approving an action is confirmed as `external`.
68
101
 
69
102
  ## Prerequisites
70
103
 
71
104
  - `foundation-installed` (app): the proxy `allowedPrefixes` include `voice`, `skills`, `knowledge`, `agent`.
72
- - `api-key-scopes` (api): `voice:read|write|delete`, `knowledge:read`, `workflows:read|write|run|delete`.
105
+ - `api-key-scopes` (api): `voice:read|write|delete|run`, `knowledge:read|write`, `workflows:read|write|run|delete`.
73
106
  - Agents that place calls need a phone number and a dialer session: see the `dialer` block. Nothing here
74
107
  places a call.
75
108
 
@@ -87,6 +120,8 @@ Ask the person: who may approve agent actions and run skills live (decide it in
87
120
 
88
121
  - Runs and approvals that gate a Work coordination action cannot be decided with an API key
89
122
  (`COORDINATION_APPROVAL_NOT_DECIDABLE_BY_KEY`): the screen shows the error; decide those in the graph8 app.
123
+ - Not offered on purpose: live voice sessions (they need a WebSocket), the first-run onboarding discovery wizard, the operating model and operator recipients (organisation policy), agent global settings (an open body with no schema), twins (a multipart upload plus LinkedIn lookups, a product decision), and deciding an operator's proposed fix (it changes your data; do it in graph8).
124
+ - Knowledge entries that graph8 generates from your records are read only; only authored entries can be edited, amended, verified or deprecated.
90
125
  - No streaming: `AgentRuns` polls every `pollMs` (backoff up to 4x).
91
126
  - A dry run never calls a model, so `llm_judge` assertions are saved but skipped.
92
127
 
@@ -131,3 +166,59 @@ Ask the person: who may approve agent actions and run skills live (decide it in
131
166
  | getAgentTestSuiteStatus | GET /voice/agents/{agent_id}/test-suite-status | read | AgentTestConsole |
132
167
  | runAllAgentTests | POST /voice/agents/{agent_id}/test/run-all | write | AgentTestConsole |
133
168
  | listPresetVoices | GET /voice/voice-library/presets | read | AgentBuilder |
169
+ | cloneAgent | POST /voice/agents/clone | write | DuplicateAgentButton, FromTemplateButton |
170
+ | createAgentSession | POST /agent/sessions | write | AssistantSessions |
171
+ | createAuthoredKnowledge | POST /knowledge/authored | write | KnowledgeForm |
172
+ | createAuthoredKnowledgeAmendment | POST /knowledge/authored/{concept_id}/amendments | write | KnowledgeForm |
173
+ | createFromTemplate | POST /skills/from-template | write | SkillLibrary |
174
+ | deleteAgentSession | DELETE /agent/sessions/{session_id} | destructive | AssistantSessions |
175
+ | deleteAgentTestCase | DELETE /voice/agents/{agent_id}/test-cases/{test_case_id} | destructive | AgentTestHistory |
176
+ | deleteChatAgentConversation | DELETE /voice/chat-agent/conversations/{chat_id} | destructive | AgentConversations |
177
+ | deleteSkill | DELETE /skills/{action_id} | destructive | SkillEditor |
178
+ | deprecateAuthoredKnowledge | POST /knowledge/authored/{concept_id}/deprecate | write | KnowledgeDetail |
179
+ | ensureReceptionistAgent | POST /voice/agents/receptionist | write | ReceptionistButton |
180
+ | exportKnowledge | GET /knowledge/export | read | KnowledgeBrowser |
181
+ | extractVariables | GET /skills/{action_id}/variables | read | SkillEditor |
182
+ | getAgentActivity | GET /voice/agents/{agent_id}/activity | read | AgentActivity |
183
+ | getAgentApprovalReceipts | GET /agent/approvals/{approval_id}/receipts | read | AgentApprovals |
184
+ | getAgentOperatorsSummary | GET /agent/operators/summary | read | AgentOperators |
185
+ | getAgentOversight | GET /agent/oversight | read | AgentApprovals |
186
+ | getAgentSessionState | GET /agent/sessions/{session_id}/state | read | AssistantSessions |
187
+ | getAgentSkillStats | GET /voice/agents/{agent_id}/skill-stats | read | AgentActivity |
188
+ | getChatAgentHistory | POST /voice/chat-agent/history | read | AgentConversations |
189
+ | getKnowledge | GET /knowledge/{concept_id} | read | KnowledgeDetail |
190
+ | getKnowledgeHistory | GET /knowledge/{concept_id}/history | read | KnowledgeDetail |
191
+ | getKnowledgeStatus | GET /knowledge/status | read | KnowledgeBrowser |
192
+ | getSkill | GET /skills/{action_id} | read | SkillEditor |
193
+ | knowledgeSources | GET /knowledge/{concept_id}/sources | read | KnowledgeDetail |
194
+ | listAgentApprovalHistory | GET /agent/approvals/history | read | AgentApprovals |
195
+ | listAgentOperatorActivity | GET /agent/operators/{operator}/activity | read | AgentOperators |
196
+ | listAgentOperatorFindings | GET /agent/operators/{operator}/findings | read | AgentOperators |
197
+ | listAgentOperatorSkills | GET /agent/operators/{operator}/skills | read | AgentOperators |
198
+ | listAgentOperators | GET /agent/operators | read | AgentOperators |
199
+ | listAgentSessions | GET /agent/sessions | read | AssistantSessions |
200
+ | listAgentTemplates | GET /voice/agent-templates | read | FromTemplateButton |
201
+ | listAgentTestRuns | GET /voice/agents/{agent_id}/test-runs | read | AgentTestHistory |
202
+ | listChatAgentConversations | POST /voice/chat-agent/conversations | read | AgentConversations |
203
+ | listKnowledge | GET /knowledge | read | KnowledgeBrowser |
204
+ | listTemplates | GET /skills/templates | read | SkillLibrary |
205
+ | markAgentSessionRead | PUT /agent/sessions/{session_id}/read | write | AssistantSessions |
206
+ | pinAgentSession | POST /agent/sessions/{session_id}/pin | write | AssistantSessions |
207
+ | postAgentChat | POST /agent/chat | billable | AssistantSessions |
208
+ | postAgentSessionMessage | POST /agent/sessions/{session_id}/messages | write | AssistantSessions |
209
+ | relatedKnowledge | GET /knowledge/{concept_id}/related | read | KnowledgeDetail |
210
+ | renameAgentSession | POST /agent/sessions/{session_id}/rename | write | AssistantSessions |
211
+ | renameChatAgentConversation | PUT /voice/chat-agent/conversations/{chat_id}/name | write | AgentConversations |
212
+ | requestAgentApprovalChanges | POST /agent/approvals/{approval_id}/request-changes | write | AgentApprovals |
213
+ | saveAgentAsTemplate | POST /voice/agents/{agent_id}/save-as-template | write | SaveAsTemplateButton |
214
+ | sendChatAgentMessage | POST /voice/chat-agent/messages | billable | AgentConversations |
215
+ | setAgentOperatorEnabled | PUT /agent/operators/{operator}/enabled | billable | AgentOperators |
216
+ | setAgentOperatorTrustDial | PUT /agent/operators/{operator}/skills/{skill_key} | billable | AgentOperators |
217
+ | steerAgentWorkItem | POST /agent/work-items/{work_item_id}/steer | write | AgentRunDetail |
218
+ | toggleReceptionistAgent | PATCH /voice/agents/receptionist | write | ReceptionistButton |
219
+ | transferChatAgentConversation | POST /voice/chat-agent/conversations/{chat_id}/transfer-to-human | write | AgentConversations |
220
+ | updateAgentTestCase | PUT /voice/agents/{agent_id}/test-cases/{test_case_id} | write | AgentTestHistory |
221
+ | updateAuthoredKnowledgeDraft | PATCH /knowledge/authored/{concept_id} | write | KnowledgeForm |
222
+ | updateSkill | PUT /skills/{action_id} | write | SkillEditor |
223
+ | validateTemplate | POST /skills/validate | write | SkillEditor |
224
+ | verifyAuthoredKnowledge | POST /knowledge/authored/{concept_id}/verify | write | KnowledgeDetail |