@graph8/sdk 0.308.1 → 0.357.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +81 -0
- package/blocks/README.md +32 -0
- package/blocks/_foundation/README.md +78 -0
- package/blocks/_foundation/block.json +79 -0
- package/blocks/_foundation/components/api-error.tsx +62 -0
- package/blocks/_foundation/components/confirm-spend-dialog.tsx +142 -0
- package/blocks/_foundation/components/empty-state.tsx +24 -0
- package/blocks/_foundation/hooks/use-g8-mutation.ts +88 -0
- package/blocks/_foundation/hooks/use-g8-query.ts +87 -0
- package/blocks/_foundation/hooks/use-job-poll.ts +130 -0
- package/blocks/_foundation/hooks/use-paginated.ts +105 -0
- package/blocks/_foundation/lib/g8-client.ts +128 -0
- package/blocks/_foundation/recipes/verify-proxy-key.ts +18 -0
- package/blocks/_foundation/server/proxy.ts +233 -0
- package/blocks/_foundation/server/route.ts +30 -0
- package/blocks/agents/README.md +133 -0
- package/blocks/agents/block.json +223 -0
- package/blocks/agents/components/agent-builder.tsx +199 -0
- package/blocks/agents/components/agent-knowledge-panel.tsx +144 -0
- package/blocks/agents/components/agent-runs.tsx +175 -0
- package/blocks/agents/components/agent-skills-panel.tsx +126 -0
- package/blocks/agents/components/agent-test-console.tsx +175 -0
- package/blocks/agents/lib/agent-types.ts +114 -0
- package/blocks/agents/recipes/create-agent-and-attach-skill.ts +50 -0
- package/blocks/agents/recipes/run-and-follow-agent-run.ts +46 -0
- package/blocks/agents/recipes/test-agent-before-activating.ts +36 -0
- package/blocks/analytics/README.md +73 -0
- package/blocks/analytics/block.json +178 -0
- package/blocks/analytics/components/funnel-chart.tsx +79 -0
- package/blocks/analytics/components/kpi-tiles.tsx +74 -0
- package/blocks/analytics/components/leaderboard.tsx +86 -0
- package/blocks/analytics/components/report-builder.tsx +200 -0
- package/blocks/analytics/hooks/use-report.ts +26 -0
- package/blocks/analytics/lib/analytics-types.ts +108 -0
- package/blocks/analytics/lib/use-debounced.ts +16 -0
- package/blocks/analytics/recipes/01-weekly-outbound-report.ts +32 -0
- package/blocks/analytics/recipes/02-revenue-snapshot.ts +22 -0
- package/blocks/analytics/recipes/03-saved-report.ts +30 -0
- package/blocks/appointments/README.md +80 -0
- package/blocks/appointments/block.json +218 -0
- package/blocks/appointments/components/availability-editor.tsx +192 -0
- package/blocks/appointments/components/booking-page.tsx +154 -0
- package/blocks/appointments/components/event-type-editor.tsx +214 -0
- package/blocks/appointments/components/meeting-detail.tsx +147 -0
- package/blocks/appointments/components/meeting-list.tsx +148 -0
- package/blocks/appointments/hooks/use-available-slots.ts +29 -0
- package/blocks/appointments/hooks/use-schedules.ts +18 -0
- package/blocks/appointments/lib/appointments-types.ts +159 -0
- package/blocks/appointments/lib/idempotency.ts +30 -0
- package/blocks/appointments/recipes/01-create-event-type-and-hours.ts +27 -0
- package/blocks/appointments/recipes/02-find-slots-and-book.ts +34 -0
- package/blocks/appointments/recipes/03-bookings-digest.ts +22 -0
- package/blocks/appointments/recipes/04-calendar-invite.ts +21 -0
- package/blocks/block.schema.json +130 -0
- package/blocks/block.types.ts +109 -0
- package/blocks/campaigns/README.md +118 -0
- package/blocks/campaigns/block.json +361 -0
- package/blocks/campaigns/components/campaign-assets.tsx +180 -0
- package/blocks/campaigns/components/campaign-audience-step.tsx +91 -0
- package/blocks/campaigns/components/campaign-launch-step.tsx +147 -0
- package/blocks/campaigns/components/campaign-list.tsx +120 -0
- package/blocks/campaigns/components/campaign-metrics.tsx +93 -0
- package/blocks/campaigns/components/campaign-select.tsx +52 -0
- package/blocks/campaigns/components/campaign-sequence-step.tsx +158 -0
- package/blocks/campaigns/components/campaign-wizard.tsx +238 -0
- package/blocks/campaigns/components/form-field.tsx +29 -0
- package/blocks/campaigns/components/icp-editor.tsx +230 -0
- package/blocks/campaigns/components/persona-editor.tsx +210 -0
- package/blocks/campaigns/hooks/use-company-profile.ts +34 -0
- package/blocks/campaigns/lib/campaigns-utils.ts +155 -0
- package/blocks/campaigns/recipes/attach-audience-and-launch.ts +33 -0
- package/blocks/campaigns/recipes/campaign-report.ts +22 -0
- package/blocks/campaigns/recipes/generate-ideas-and-create-campaign.ts +51 -0
- package/blocks/campaigns/recipes/set-up-icp-and-personas.ts +37 -0
- package/blocks/coach/README.md +93 -0
- package/blocks/coach/block.json +125 -0
- package/blocks/coach/components/call-scorecard.tsx +126 -0
- package/blocks/coach/components/coaching-feed.tsx +140 -0
- package/blocks/coach/lib/coach-types.ts +116 -0
- package/blocks/coach/recipes/read-a-scorecard.ts +27 -0
- package/blocks/coach/recipes/weekly-coaching-digest.ts +53 -0
- package/blocks/copilot/README.md +99 -0
- package/blocks/copilot/block.json +151 -0
- package/blocks/copilot/components/copilot-memory.tsx +87 -0
- package/blocks/copilot/components/copilot-panel.tsx +189 -0
- package/blocks/copilot/components/copilot-team-chat.tsx +111 -0
- package/blocks/copilot/lib/copilot-types.ts +111 -0
- package/blocks/copilot/recipes/ask-the-copilot.ts +35 -0
- package/blocks/copilot/recipes/post-in-a-work-channel.ts +33 -0
- package/blocks/copilot/recipes/remember-and-recall.ts +19 -0
- package/blocks/crm/README.md +122 -0
- package/blocks/crm/block.json +378 -0
- package/blocks/crm/components/activity-timeline.tsx +99 -0
- package/blocks/crm/components/company-detail.tsx +118 -0
- package/blocks/crm/components/company-table.tsx +173 -0
- package/blocks/crm/components/contact-detail.tsx +135 -0
- package/blocks/crm/components/contact-table.tsx +217 -0
- package/blocks/crm/components/dedupe-review.tsx +164 -0
- package/blocks/crm/components/import-wizard.tsx +193 -0
- package/blocks/crm/components/notes-panel.tsx +112 -0
- package/blocks/crm/components/record-form.tsx +191 -0
- package/blocks/crm/components/task-list.tsx +107 -0
- package/blocks/crm/hooks/use-custom-fields.ts +18 -0
- package/blocks/crm/hooks/use-debounced.ts +13 -0
- package/blocks/crm/hooks/use-page-query.ts +52 -0
- package/blocks/crm/lib/crm-types.ts +136 -0
- package/blocks/crm/recipes/custom-fields-and-values.ts +28 -0
- package/blocks/crm/recipes/dedupe-and-merge.ts +30 -0
- package/blocks/crm/recipes/notes-tasks-and-activity.ts +23 -0
- package/blocks/crm/recipes/upsert-contact-with-company.ts +33 -0
- package/blocks/deals/README.md +78 -0
- package/blocks/deals/block.json +198 -0
- package/blocks/deals/components/deal-detail.tsx +134 -0
- package/blocks/deals/components/forecast-view.tsx +112 -0
- package/blocks/deals/components/pipeline-board.tsx +142 -0
- package/blocks/deals/components/stage-editor.tsx +96 -0
- package/blocks/deals/hooks/use-pipeline-deals.ts +67 -0
- package/blocks/deals/hooks/use-pipelines.ts +19 -0
- package/blocks/deals/lib/deals-types.ts +128 -0
- package/blocks/deals/recipes/01-create-deal-and-advance.ts +32 -0
- package/blocks/deals/recipes/02-pipeline-report.ts +35 -0
- package/blocks/deals/recipes/03-stale-deals-sweep.ts +20 -0
- package/blocks/dialer/README.md +114 -0
- package/blocks/dialer/block.json +260 -0
- package/blocks/dialer/components/call-log.tsx +78 -0
- package/blocks/dialer/components/call-queue.tsx +188 -0
- package/blocks/dialer/components/dialer-workspace.tsx +47 -0
- package/blocks/dialer/components/disposition-panel.tsx +75 -0
- package/blocks/dialer/components/live-calls-table.tsx +107 -0
- package/blocks/dialer/components/session-start-form.tsx +111 -0
- package/blocks/dialer/components/softphone.tsx +122 -0
- package/blocks/dialer/components/transcript-viewer.tsx +82 -0
- package/blocks/dialer/hooks/use-dialer-numbers.ts +19 -0
- package/blocks/dialer/hooks/use-dialer-session.ts +68 -0
- package/blocks/dialer/hooks/use-dispositions.ts +29 -0
- package/blocks/dialer/lib/dialer-types.ts +158 -0
- package/blocks/dialer/lib/softphone-transport.ts +67 -0
- package/blocks/dialer/lib/twilio-transport.ts +74 -0
- package/blocks/dialer/recipes/01-create-session-and-dial.ts +39 -0
- package/blocks/dialer/recipes/02-disposition-calls.ts +26 -0
- package/blocks/dialer/recipes/03-review-a-call.ts +23 -0
- package/blocks/enrichment/README.md +105 -0
- package/blocks/enrichment/block.json +204 -0
- package/blocks/enrichment/components/bulk-enrich-panel.tsx +205 -0
- package/blocks/enrichment/components/email-verify-badge.tsx +82 -0
- package/blocks/enrichment/components/enrich-button.tsx +136 -0
- package/blocks/enrichment/components/waterfall-config.tsx +127 -0
- package/blocks/enrichment/hooks/use-providers.ts +18 -0
- package/blocks/enrichment/lib/enrichment-types.ts +104 -0
- package/blocks/enrichment/recipes/bulk-enrich-and-poll.ts +41 -0
- package/blocks/enrichment/recipes/lookup-and-verify.ts +25 -0
- package/blocks/enrichment/recipes/waterfall-pipeline.ts +26 -0
- package/blocks/forms/README.md +112 -0
- package/blocks/forms/block.json +200 -0
- package/blocks/forms/components/form-builder.tsx +150 -0
- package/blocks/forms/components/form-embed.tsx +103 -0
- package/blocks/forms/components/form-mapping-editor.tsx +125 -0
- package/blocks/forms/components/site-audit-panel.tsx +73 -0
- package/blocks/forms/components/submissions-table.tsx +158 -0
- package/blocks/forms/lib/form-types.ts +127 -0
- package/blocks/forms/recipes/install-snippet-and-form.ts +21 -0
- package/blocks/forms/recipes/retry-failed-deliveries.ts +26 -0
- package/blocks/forms/recipes/route-form-to-list.ts +44 -0
- package/blocks/inbox/README.md +72 -0
- package/blocks/inbox/block.json +194 -0
- package/blocks/inbox/components/inbox-list.tsx +156 -0
- package/blocks/inbox/components/inbox-screen.tsx +49 -0
- package/blocks/inbox/components/reply-composer.tsx +183 -0
- package/blocks/inbox/components/tag-and-assign.tsx +189 -0
- package/blocks/inbox/components/thread-badge.tsx +17 -0
- package/blocks/inbox/components/thread-view.tsx +108 -0
- package/blocks/inbox/hooks/use-inbox-thread.ts +24 -0
- package/blocks/inbox/hooks/use-inbox-threads.ts +40 -0
- package/blocks/inbox/lib/idempotency.ts +30 -0
- package/blocks/inbox/lib/inbox-types.ts +100 -0
- package/blocks/inbox/recipes/01-triage-and-reply.ts +43 -0
- package/blocks/inbox/recipes/02-tag-and-assign.ts +31 -0
- package/blocks/inbox/recipes/03-hot-contacts-digest.ts +16 -0
- package/blocks/integrations/README.md +75 -0
- package/blocks/integrations/block.json +172 -0
- package/blocks/integrations/components/integration-list.tsx +165 -0
- package/blocks/integrations/components/sync-status.tsx +223 -0
- package/blocks/integrations/components/webhook-manager.tsx +300 -0
- package/blocks/integrations/lib/integrations-utils.ts +62 -0
- package/blocks/integrations/recipes/crm-sync-health.ts +19 -0
- package/blocks/integrations/recipes/push-contacts-to-crm.ts +20 -0
- package/blocks/integrations/recipes/register-webhook.ts +18 -0
- package/blocks/integrations/recipes/verify-webhook-route.ts +33 -0
- package/blocks/intent/README.md +57 -0
- package/blocks/intent/block.json +138 -0
- package/blocks/intent/components/account-intent-score.tsx +91 -0
- package/blocks/intent/components/intent-feed.tsx +215 -0
- package/blocks/intent/components/intent-keyword-manager.tsx +331 -0
- package/blocks/intent/hooks/use-account-intent.ts +46 -0
- package/blocks/intent/lib/intent-utils.ts +95 -0
- package/blocks/intent/recipes/rank-intent-accounts.ts +36 -0
- package/blocks/intent/recipes/track-competitor-domain.ts +23 -0
- package/blocks/intent/recipes/who-visited-url.ts +18 -0
- package/blocks/lifecycle/README.md +79 -0
- package/blocks/lifecycle/block.json +198 -0
- package/blocks/lifecycle/components/churn-list.tsx +92 -0
- package/blocks/lifecycle/components/customer-table.tsx +119 -0
- package/blocks/lifecycle/components/lead-queue.tsx +127 -0
- package/blocks/lifecycle/components/lifecycle-board.tsx +102 -0
- package/blocks/lifecycle/components/stage-move-dialog.tsx +75 -0
- package/blocks/lifecycle/hooks/use-debounced.ts +13 -0
- package/blocks/lifecycle/hooks/use-lifecycle-stages.ts +27 -0
- package/blocks/lifecycle/lib/lifecycle.ts +99 -0
- package/blocks/lifecycle/recipes/customer-brief.ts +23 -0
- package/blocks/lifecycle/recipes/move-company-stage.ts +17 -0
- package/blocks/lifecycle/recipes/read-lifecycle-board.ts +21 -0
- package/blocks/lifecycle/recipes/unlock-stage-contacts.ts +25 -0
- package/blocks/lists/README.md +96 -0
- package/blocks/lists/block.json +166 -0
- package/blocks/lists/components/add-to-list-button.tsx +111 -0
- package/blocks/lists/components/list-picker.tsx +94 -0
- package/blocks/lists/components/list-table.tsx +160 -0
- package/blocks/lists/components/suppression-manager.tsx +153 -0
- package/blocks/lists/recipes/create-list-and-add-contacts.ts +35 -0
- package/blocks/lists/recipes/refresh-and-check-lists.ts +21 -0
- package/blocks/lists/recipes/suppress-and-reinstate.ts +30 -0
- package/blocks/mailboxes/README.md +71 -0
- package/blocks/mailboxes/block.json +187 -0
- package/blocks/mailboxes/components/connect-mailbox.tsx +284 -0
- package/blocks/mailboxes/components/domain-purchase.tsx +271 -0
- package/blocks/mailboxes/components/mailbox-list.tsx +185 -0
- package/blocks/mailboxes/components/warmup-health.tsx +232 -0
- package/blocks/mailboxes/lib/mailboxes-utils.ts +69 -0
- package/blocks/mailboxes/recipes/buy-domain-and-mailboxes.ts +64 -0
- package/blocks/mailboxes/recipes/connect-imap-mailbox.ts +38 -0
- package/blocks/mailboxes/recipes/is-it-safe-to-send.ts +17 -0
- package/blocks/mailboxes/recipes/warmup-report.ts +31 -0
- package/blocks/newsletter/README.md +122 -0
- package/blocks/newsletter/block.json +224 -0
- package/blocks/newsletter/components/issue-form.tsx +124 -0
- package/blocks/newsletter/components/issue-scheduler.tsx +152 -0
- package/blocks/newsletter/components/newsletter-editor.tsx +131 -0
- package/blocks/newsletter/components/newsletter-stats.tsx +93 -0
- package/blocks/newsletter/components/subscriber-table.tsx +173 -0
- package/blocks/newsletter/lib/newsletter-types.ts +97 -0
- package/blocks/newsletter/recipes/create-newsletter-and-draft-issue.ts +27 -0
- package/blocks/newsletter/recipes/import-audience-and-send.ts +43 -0
- package/blocks/newsletter/recipes/issue-performance-report.ts +26 -0
- package/blocks/nurture/README.md +110 -0
- package/blocks/nurture/block.json +191 -0
- package/blocks/nurture/components/nurture-builder.tsx +114 -0
- package/blocks/nurture/components/nurture-enroll.tsx +107 -0
- package/blocks/nurture/components/nurture-form.tsx +120 -0
- package/blocks/nurture/components/nurture-stats.tsx +81 -0
- package/blocks/nurture/lib/nurture-types.ts +109 -0
- package/blocks/nurture/recipes/create-a-nurture.ts +34 -0
- package/blocks/nurture/recipes/enroll-contacts-and-launch.ts +24 -0
- package/blocks/nurture/recipes/nurture-health-check.ts +28 -0
- package/blocks/objects/README.md +120 -0
- package/blocks/objects/block.json +243 -0
- package/blocks/objects/components/attribute-field-input.tsx +82 -0
- package/blocks/objects/components/attribute-form-dialog.tsx +159 -0
- package/blocks/objects/components/object-not-found.tsx +34 -0
- package/blocks/objects/components/object-record-detail.tsx +143 -0
- package/blocks/objects/components/object-schema-editor.tsx +197 -0
- package/blocks/objects/components/object-table.tsx +130 -0
- package/blocks/objects/components/record-form-dialog.tsx +112 -0
- package/blocks/objects/components/record-roles-panel.tsx +106 -0
- package/blocks/objects/hooks/use-object-schema.ts +36 -0
- package/blocks/objects/lib/object-types.ts +214 -0
- package/blocks/objects/recipes/define-object-and-add-records.ts +24 -0
- package/blocks/objects/recipes/update-audit-and-archive-records.ts +39 -0
- package/blocks/objects/recipes/upsert-records-from-your-system.ts +30 -0
- package/blocks/pages/README.md +104 -0
- package/blocks/pages/block.json +223 -0
- package/blocks/pages/components/brand-kit-editor.tsx +152 -0
- package/blocks/pages/components/content-library.tsx +163 -0
- package/blocks/pages/components/page-editor.tsx +253 -0
- package/blocks/pages/components/page-list.tsx +159 -0
- package/blocks/pages/components/seo-report.tsx +159 -0
- package/blocks/pages/lib/studio.ts +77 -0
- package/blocks/pages/recipes/audit-site-seo.ts +28 -0
- package/blocks/pages/recipes/create-and-publish-page.ts +26 -0
- package/blocks/pages/recipes/edit-page-section.ts +25 -0
- package/blocks/pages/recipes/refresh-brand-kit.ts +22 -0
- package/blocks/quotes/README.md +79 -0
- package/blocks/quotes/block.json +183 -0
- package/blocks/quotes/components/product-picker.tsx +80 -0
- package/blocks/quotes/components/quote-builder.tsx +195 -0
- package/blocks/quotes/components/quote-list.tsx +79 -0
- package/blocks/quotes/components/quote-viewer.tsx +135 -0
- package/blocks/quotes/components/signature-status.tsx +77 -0
- package/blocks/quotes/hooks/use-debounced.ts +13 -0
- package/blocks/quotes/lib/quotes.ts +142 -0
- package/blocks/quotes/recipes/create-and-send-quote.ts +44 -0
- package/blocks/quotes/recipes/revise-sent-quote.ts +18 -0
- package/blocks/quotes/recipes/track-quote-signature.ts +22 -0
- package/blocks/radar/README.md +106 -0
- package/blocks/radar/block.json +189 -0
- package/blocks/radar/components/competitor-battle-card.tsx +53 -0
- package/blocks/radar/components/competitor-tracker.tsx +158 -0
- package/blocks/radar/components/radar-overview.tsx +67 -0
- package/blocks/radar/components/radar-report.tsx +86 -0
- package/blocks/radar/hooks/use-competitors.ts +23 -0
- package/blocks/radar/lib/radar-types.ts +124 -0
- package/blocks/radar/recipes/battle-card.ts +28 -0
- package/blocks/radar/recipes/deep-dive-report.ts +32 -0
- package/blocks/radar/recipes/marketing-snapshot.ts +18 -0
- package/blocks/radar/recipes/track-and-scan.ts +39 -0
- package/blocks/search/README.md +129 -0
- package/blocks/search/block.json +185 -0
- package/blocks/search/components/filter-builder.tsx +149 -0
- package/blocks/search/components/prospect-results.tsx +175 -0
- package/blocks/search/components/save-to-list-dialog.tsx +135 -0
- package/blocks/search/components/saved-searches.tsx +95 -0
- package/blocks/search/hooks/use-filter-options.ts +41 -0
- package/blocks/search/lib/search-types.ts +149 -0
- package/blocks/search/recipes/explore-filter-values.ts +27 -0
- package/blocks/search/recipes/saved-searches.ts +34 -0
- package/blocks/search/recipes/search-and-save-to-list.ts +37 -0
- package/blocks/sequencer/README.md +87 -0
- package/blocks/sequencer/block.json +214 -0
- package/blocks/sequencer/components/enroll-dialog.tsx +93 -0
- package/blocks/sequencer/components/sequence-builder.tsx +306 -0
- package/blocks/sequencer/components/sequence-list.tsx +200 -0
- package/blocks/sequencer/components/sequence-stats.tsx +256 -0
- package/blocks/sequencer/components/step-editor.tsx +213 -0
- package/blocks/sequencer/lib/sequencer-utils.ts +168 -0
- package/blocks/sequencer/recipes/create-multichannel-sequence.ts +51 -0
- package/blocks/sequencer/recipes/launch-and-enroll.ts +44 -0
- package/blocks/sequencer/recipes/pause-when-unsafe.ts +30 -0
- package/blocks/sequencer/recipes/sequence-report.ts +22 -0
- package/blocks/social-ads/README.md +128 -0
- package/blocks/social-ads/block.json +256 -0
- package/blocks/social-ads/components/ad-campaign-list.tsx +136 -0
- package/blocks/social-ads/components/audience-sync.tsx +150 -0
- package/blocks/social-ads/components/creative-gallery.tsx +121 -0
- package/blocks/social-ads/components/post-composer.tsx +122 -0
- package/blocks/social-ads/components/social-post-list.tsx +116 -0
- package/blocks/social-ads/hooks/use-social-accounts.ts +16 -0
- package/blocks/social-ads/lib/social-ads-types.ts +167 -0
- package/blocks/social-ads/recipes/creative-to-gallery.ts +41 -0
- package/blocks/social-ads/recipes/schedule-post.ts +51 -0
- package/blocks/social-ads/recipes/sync-audience-and-launch.ts +41 -0
- package/blocks/visitors/README.md +56 -0
- package/blocks/visitors/block.json +139 -0
- package/blocks/visitors/components/snippet-install.tsx +169 -0
- package/blocks/visitors/components/traffic-chart.tsx +156 -0
- package/blocks/visitors/components/visitor-company-card.tsx +92 -0
- package/blocks/visitors/components/visitor-feed.tsx +157 -0
- package/blocks/visitors/lib/visitors-utils.ts +78 -0
- package/blocks/visitors/recipes/check-snippet-installed.ts +24 -0
- package/blocks/visitors/recipes/recent-company-visits.ts +27 -0
- package/blocks/visitors/recipes/traffic-summary.ts +24 -0
- package/blocks/webchat/README.md +87 -0
- package/blocks/webchat/block.json +134 -0
- package/blocks/webchat/components/chat-widget-config.tsx +160 -0
- package/blocks/webchat/components/conversation-list.tsx +74 -0
- package/blocks/webchat/lib/webchat-types.ts +83 -0
- package/blocks/webchat/recipes/create-bot-and-style-widget.ts +24 -0
- package/blocks/webchat/recipes/list-chat-visitors.ts +24 -0
- package/blocks/workbench/README.md +135 -0
- package/blocks/workbench/block.json +259 -0
- package/blocks/workbench/components/column-recipe-editor.tsx +183 -0
- package/blocks/workbench/components/run-progress.tsx +132 -0
- package/blocks/workbench/components/workbench-add-rows.tsx +100 -0
- package/blocks/workbench/components/workbench-grid.tsx +159 -0
- package/blocks/workbench/components/workbench-row-actions.tsx +102 -0
- package/blocks/workbench/components/workbench-table-list.tsx +105 -0
- package/blocks/workbench/hooks/use-workbench-table.ts +30 -0
- package/blocks/workbench/lib/waterfall-presets.ts +119 -0
- package/blocks/workbench/lib/workbench-types.ts +191 -0
- package/blocks/workbench/recipes/build-enriched-table.ts +65 -0
- package/blocks/workbench/recipes/import-from-search.ts +42 -0
- package/blocks/workbench/recipes/scrape-into-table.ts +36 -0
- package/blocks/workbench/recipes/waterfall-column.ts +55 -0
- package/blocks/workflows/README.md +100 -0
- package/blocks/workflows/block.json +188 -0
- package/blocks/workflows/components/run-history.tsx +136 -0
- package/blocks/workflows/components/trigger-config.tsx +134 -0
- package/blocks/workflows/components/workflow-editor.tsx +142 -0
- package/blocks/workflows/components/workflow-list.tsx +153 -0
- package/blocks/workflows/hooks/use-workflow.ts +51 -0
- package/blocks/workflows/lib/graph.ts +187 -0
- package/blocks/workflows/recipes/create-workflow.ts +35 -0
- package/blocks/workflows/recipes/find-failed-runs.ts +15 -0
- package/blocks/workflows/recipes/run-workflow-and-wait.ts +32 -0
- package/blocks/workflows/recipes/set-trigger.ts +22 -0
- package/dist/cli.js +5330 -29
- package/dist/index.browser.js +7740 -0
- package/dist/index.browser.js.map +1 -0
- package/dist/index.browser.mjs +7717 -0
- package/dist/index.browser.mjs.map +1 -0
- package/dist/index.d.mts +1440 -21
- package/dist/index.d.ts +1440 -21
- package/dist/index.js +42 -3
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +42 -3
- package/dist/index.mjs.map +1 -1
- package/dist/react.browser.js +7598 -0
- package/dist/react.browser.js.map +1 -0
- package/dist/react.browser.mjs +7568 -0
- package/dist/react.browser.mjs.map +1 -0
- package/dist/react.d.mts +1340 -18
- package/dist/react.d.ts +1340 -18
- package/dist/react.js +41 -2
- package/dist/react.js.map +1 -1
- package/dist/react.mjs +41 -2
- package/dist/react.mjs.map +1 -1
- package/dist/types/agentSetup.d.ts +6 -6
- package/dist/types/blocks/add.d.ts +53 -0
- package/dist/types/blocks/create.d.ts +46 -0
- package/dist/types/blocks/doctor.d.ts +26 -0
- package/dist/types/blocks/registry.d.ts +134 -0
- package/dist/types/cli.d.ts +16 -0
- package/dist/types/core.d.ts +1 -1
- package/dist/types/crypto-browser.d.ts +2 -0
- package/dist/types/crypto-node.d.ts +6 -0
- package/dist/types/react.d.ts +1 -1
- package/dist/types/version.d.ts +2 -2
- package/dist/types/webhooks.d.ts +2 -2
- package/dist/ui/index.d.mts +54 -0
- package/dist/ui/index.d.ts +54 -0
- package/dist/ui/index.js +105 -0
- package/dist/ui/index.js.map +1 -0
- package/dist/ui/index.mjs +44 -0
- package/dist/ui/index.mjs.map +1 -0
- package/dist/ui/lib/compose-refs.d.mts +19 -0
- package/dist/ui/lib/compose-refs.d.ts +19 -0
- package/dist/ui/lib/compose-refs.js +76 -0
- package/dist/ui/lib/compose-refs.js.map +1 -0
- package/dist/ui/lib/compose-refs.mjs +41 -0
- package/dist/ui/lib/compose-refs.mjs.map +1 -0
- package/dist/ui/lib/use-mobile.d.mts +4 -0
- package/dist/ui/lib/use-mobile.d.ts +4 -0
- package/dist/ui/lib/use-mobile.js +57 -0
- package/dist/ui/lib/use-mobile.js.map +1 -0
- package/dist/ui/lib/use-mobile.mjs +22 -0
- package/dist/ui/lib/use-mobile.mjs.map +1 -0
- package/dist/ui/lib/utils.d.mts +10 -0
- package/dist/ui/lib/utils.d.ts +10 -0
- package/dist/ui/lib/utils.js +33 -0
- package/dist/ui/lib/utils.js.map +1 -0
- package/dist/ui/lib/utils.mjs +9 -0
- package/dist/ui/lib/utils.mjs.map +1 -0
- package/dist/ui/primitives/alert-dialog.d.mts +22 -0
- package/dist/ui/primitives/alert-dialog.d.ts +22 -0
- package/dist/ui/primitives/alert-dialog.js +163 -0
- package/dist/ui/primitives/alert-dialog.js.map +1 -0
- package/dist/ui/primitives/alert-dialog.mjs +119 -0
- package/dist/ui/primitives/alert-dialog.mjs.map +1 -0
- package/dist/ui/primitives/avatar.d.mts +8 -0
- package/dist/ui/primitives/avatar.d.ts +8 -0
- package/dist/ui/primitives/avatar.js +91 -0
- package/dist/ui/primitives/avatar.js.map +1 -0
- package/dist/ui/primitives/avatar.mjs +55 -0
- package/dist/ui/primitives/avatar.mjs.map +1 -0
- package/dist/ui/primitives/breadcrumb.d.mts +13 -0
- package/dist/ui/primitives/breadcrumb.d.ts +13 -0
- package/dist/ui/primitives/breadcrumb.js +127 -0
- package/dist/ui/primitives/breadcrumb.js.map +1 -0
- package/dist/ui/primitives/breadcrumb.mjs +97 -0
- package/dist/ui/primitives/breadcrumb.mjs.map +1 -0
- package/dist/ui/primitives/button.d.mts +15 -0
- package/dist/ui/primitives/button.d.ts +15 -0
- package/dist/ui/primitives/button.js +91 -0
- package/dist/ui/primitives/button.js.map +1 -0
- package/dist/ui/primitives/button.mjs +56 -0
- package/dist/ui/primitives/button.mjs.map +1 -0
- package/dist/ui/primitives/card.d.mts +10 -0
- package/dist/ui/primitives/card.d.ts +10 -0
- package/dist/ui/primitives/card.js +101 -0
- package/dist/ui/primitives/card.js.map +1 -0
- package/dist/ui/primitives/card.mjs +62 -0
- package/dist/ui/primitives/card.mjs.map +1 -0
- package/dist/ui/primitives/carousel.d.mts +45 -0
- package/dist/ui/primitives/carousel.d.ts +45 -0
- package/dist/ui/primitives/carousel.js +300 -0
- package/dist/ui/primitives/carousel.js.map +1 -0
- package/dist/ui/primitives/carousel.mjs +261 -0
- package/dist/ui/primitives/carousel.mjs.map +1 -0
- package/dist/ui/primitives/chart.d.mts +68 -0
- package/dist/ui/primitives/chart.d.ts +68 -0
- package/dist/ui/primitives/chart.js +280 -0
- package/dist/ui/primitives/chart.js.map +1 -0
- package/dist/ui/primitives/chart.mjs +241 -0
- package/dist/ui/primitives/chart.mjs.map +1 -0
- package/dist/ui/primitives/collapsible.d.mts +8 -0
- package/dist/ui/primitives/collapsible.d.ts +8 -0
- package/dist/ui/primitives/collapsible.js +72 -0
- package/dist/ui/primitives/collapsible.js.map +1 -0
- package/dist/ui/primitives/collapsible.mjs +36 -0
- package/dist/ui/primitives/collapsible.mjs.map +1 -0
- package/dist/ui/primitives/context-menu.d.mts +29 -0
- package/dist/ui/primitives/context-menu.d.ts +29 -0
- package/dist/ui/primitives/context-menu.js +203 -0
- package/dist/ui/primitives/context-menu.js.map +1 -0
- package/dist/ui/primitives/context-menu.mjs +155 -0
- package/dist/ui/primitives/context-menu.mjs.map +1 -0
- package/dist/ui/primitives/dialog.d.mts +26 -0
- package/dist/ui/primitives/dialog.d.ts +26 -0
- package/dist/ui/primitives/dialog.js +192 -0
- package/dist/ui/primitives/dialog.js.map +1 -0
- package/dist/ui/primitives/dialog.mjs +148 -0
- package/dist/ui/primitives/dialog.mjs.map +1 -0
- package/dist/ui/primitives/drawer.d.mts +26 -0
- package/dist/ui/primitives/drawer.d.ts +26 -0
- package/dist/ui/primitives/drawer.js +146 -0
- package/dist/ui/primitives/drawer.js.map +1 -0
- package/dist/ui/primitives/drawer.mjs +103 -0
- package/dist/ui/primitives/drawer.mjs.map +1 -0
- package/dist/ui/primitives/input.d.mts +5 -0
- package/dist/ui/primitives/input.d.ts +5 -0
- package/dist/ui/primitives/input.js +46 -0
- package/dist/ui/primitives/input.js.map +1 -0
- package/dist/ui/primitives/input.mjs +22 -0
- package/dist/ui/primitives/input.mjs.map +1 -0
- package/dist/ui/primitives/item.d.mts +27 -0
- package/dist/ui/primitives/item.d.ts +27 -0
- package/dist/ui/primitives/item.js +221 -0
- package/dist/ui/primitives/item.js.map +1 -0
- package/dist/ui/primitives/item.mjs +188 -0
- package/dist/ui/primitives/item.mjs.map +1 -0
- package/dist/ui/primitives/kbd.d.mts +15 -0
- package/dist/ui/primitives/kbd.d.ts +15 -0
- package/dist/ui/primitives/kbd.js +45 -0
- package/dist/ui/primitives/kbd.js.map +1 -0
- package/dist/ui/primitives/kbd.mjs +21 -0
- package/dist/ui/primitives/kbd.mjs.map +1 -0
- package/dist/ui/primitives/label.d.mts +6 -0
- package/dist/ui/primitives/label.d.ts +6 -0
- package/dist/ui/primitives/label.js +55 -0
- package/dist/ui/primitives/label.js.map +1 -0
- package/dist/ui/primitives/label.mjs +21 -0
- package/dist/ui/primitives/label.mjs.map +1 -0
- package/dist/ui/primitives/resizable.d.mts +10 -0
- package/dist/ui/primitives/resizable.d.ts +10 -0
- package/dist/ui/primitives/resizable.js +68 -0
- package/dist/ui/primitives/resizable.js.map +1 -0
- package/dist/ui/primitives/resizable.mjs +42 -0
- package/dist/ui/primitives/resizable.mjs.map +1 -0
- package/dist/ui/primitives/save-status.d.mts +31 -0
- package/dist/ui/primitives/save-status.d.ts +31 -0
- package/dist/ui/primitives/save-status.js +150 -0
- package/dist/ui/primitives/save-status.js.map +1 -0
- package/dist/ui/primitives/save-status.mjs +126 -0
- package/dist/ui/primitives/save-status.mjs.map +1 -0
- package/dist/ui/primitives/separator.d.mts +6 -0
- package/dist/ui/primitives/separator.d.ts +6 -0
- package/dist/ui/primitives/separator.js +62 -0
- package/dist/ui/primitives/separator.js.map +1 -0
- package/dist/ui/primitives/separator.mjs +28 -0
- package/dist/ui/primitives/separator.mjs.map +1 -0
- package/dist/ui/primitives/sheet.d.mts +16 -0
- package/dist/ui/primitives/sheet.d.ts +16 -0
- package/dist/ui/primitives/sheet.js +170 -0
- package/dist/ui/primitives/sheet.js.map +1 -0
- package/dist/ui/primitives/sheet.mjs +129 -0
- package/dist/ui/primitives/sheet.mjs.map +1 -0
- package/dist/ui/primitives/sidebar.d.mts +74 -0
- package/dist/ui/primitives/sidebar.d.ts +74 -0
- package/dist/ui/primitives/sidebar.js +697 -0
- package/dist/ui/primitives/sidebar.js.map +1 -0
- package/dist/ui/primitives/sidebar.mjs +651 -0
- package/dist/ui/primitives/sidebar.mjs.map +1 -0
- package/dist/ui/primitives/skeleton.d.mts +5 -0
- package/dist/ui/primitives/skeleton.d.ts +5 -0
- package/dist/ui/primitives/skeleton.js +40 -0
- package/dist/ui/primitives/skeleton.js.map +1 -0
- package/dist/ui/primitives/skeleton.mjs +16 -0
- package/dist/ui/primitives/skeleton.mjs.map +1 -0
- package/dist/ui/primitives/slider.d.mts +20 -0
- package/dist/ui/primitives/slider.d.ts +20 -0
- package/dist/ui/primitives/slider.js +112 -0
- package/dist/ui/primitives/slider.js.map +1 -0
- package/dist/ui/primitives/slider.mjs +78 -0
- package/dist/ui/primitives/slider.mjs.map +1 -0
- package/dist/ui/primitives/sortable.d.mts +50 -0
- package/dist/ui/primitives/sortable.d.ts +50 -0
- package/dist/ui/primitives/sortable.js +456 -0
- package/dist/ui/primitives/sortable.js.map +1 -0
- package/dist/ui/primitives/sortable.mjs +435 -0
- package/dist/ui/primitives/sortable.mjs.map +1 -0
- package/dist/ui/primitives/switch.d.mts +6 -0
- package/dist/ui/primitives/switch.d.ts +6 -0
- package/dist/ui/primitives/switch.js +67 -0
- package/dist/ui/primitives/switch.js.map +1 -0
- package/dist/ui/primitives/switch.mjs +33 -0
- package/dist/ui/primitives/switch.mjs.map +1 -0
- package/dist/ui/primitives/table.d.mts +12 -0
- package/dist/ui/primitives/table.d.ts +12 -0
- package/dist/ui/primitives/table.js +130 -0
- package/dist/ui/primitives/table.js.map +1 -0
- package/dist/ui/primitives/table.mjs +89 -0
- package/dist/ui/primitives/table.mjs.map +1 -0
- package/dist/ui/primitives/tabs.d.mts +9 -0
- package/dist/ui/primitives/tabs.d.ts +9 -0
- package/dist/ui/primitives/tabs.js +86 -0
- package/dist/ui/primitives/tabs.js.map +1 -0
- package/dist/ui/primitives/tabs.mjs +49 -0
- package/dist/ui/primitives/tabs.mjs.map +1 -0
- package/dist/ui/primitives/textarea.d.mts +5 -0
- package/dist/ui/primitives/textarea.d.ts +5 -0
- package/dist/ui/primitives/textarea.js +43 -0
- package/dist/ui/primitives/textarea.js.map +1 -0
- package/dist/ui/primitives/textarea.mjs +19 -0
- package/dist/ui/primitives/textarea.mjs.map +1 -0
- package/dist/ui/primitives/tooltip.d.mts +9 -0
- package/dist/ui/primitives/tooltip.d.ts +9 -0
- package/dist/ui/primitives/tooltip.js +94 -0
- package/dist/ui/primitives/tooltip.js.map +1 -0
- package/dist/ui/primitives/tooltip.mjs +57 -0
- package/dist/ui/primitives/tooltip.mjs.map +1 -0
- package/docs/agents.md +72 -29
- package/docs/api/README.md +6 -3
- package/docs/api/appObjects.d.ts +1 -1
- package/docs/api/appObjects.md +1 -1
- package/docs/api/by-path.md +29 -0
- package/docs/api/objects.d.ts +72 -5
- package/docs/api/objects.md +84 -7
- package/docs/api/processLists.d.ts +247 -0
- package/docs/api/processLists.md +409 -0
- package/docs/api/reports.d.ts +476 -0
- package/docs/api/reports.md +539 -0
- package/docs/api/scheduleBuy.d.ts +12 -8
- package/docs/api/scheduleBuy.md +13 -10
- package/docs/api/seo.d.ts +406 -3
- package/docs/api/seo.md +505 -1
- package/docs/api/workspaceBackup.d.ts +324 -0
- package/docs/api/workspaceBackup.md +427 -0
- package/package.json +174 -5
- package/stacks/6sense.json +46 -0
- package/stacks/README.md +20 -0
- package/stacks/apollo.json +128 -0
- package/stacks/clay.json +59 -0
- package/stacks/gong.json +72 -0
- package/stacks/hubspot.json +162 -0
- package/stacks/intercom.json +53 -0
- package/stacks/mailchimp.json +71 -0
- package/stacks/outreach.json +86 -0
- package/stacks/salesforce.json +94 -0
- package/stacks/stack.schema.json +32 -0
- package/stacks/starter.json +22 -0
- package/styles/styles.css +2 -0
- package/styles/theme.css +181 -0
- package/styles/tokens.css +284 -0
- package/templates/next-app/README.md.tmpl +35 -0
- package/templates/next-app/_pages/redirect-page.tsx.tmpl +5 -0
- package/templates/next-app/_pages/route-page.tsx.tmpl +9 -0
- package/templates/next-app/app/globals.css.tmpl +8 -0
- package/templates/next-app/app/layout.tsx.tmpl +19 -0
- package/templates/next-app/components/app-shell.tsx.tmpl +34 -0
- package/templates/next-app/dot-env.local.example.tmpl +6 -0
- package/templates/next-app/dot-gitignore.tmpl +7 -0
- package/templates/next-app/lib/nav.ts.tmpl +2 -0
- package/templates/next-app/next.config.mjs.tmpl +4 -0
- package/templates/next-app/package.json.tmpl +25 -0
- package/templates/next-app/postcss.config.mjs.tmpl +4 -0
- package/templates/next-app/tsconfig.json.tmpl +21 -0
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server-side proxy that lets the browser call graph8 without ever seeing the
|
|
3
|
+
* API key. Used by `app/api/g8/[...path]/route.ts` (see ./route.ts).
|
|
4
|
+
*
|
|
5
|
+
* browser -> /api/g8/contacts?limit=10 -> THIS -> https://be.graph8.com/api/v1/contacts?limit=10
|
|
6
|
+
* Authorization: Bearer $G8_API_KEY
|
|
7
|
+
*
|
|
8
|
+
* Plain Web `Request`/`Response`, no framework imports, so it runs on the Node
|
|
9
|
+
* and Edge runtimes and is unit-testable. The key is read from the environment
|
|
10
|
+
* on every request and is never logged, echoed or put in a response.
|
|
11
|
+
*
|
|
12
|
+
* SECURITY: this route is exactly as powerful as the key. It therefore REFUSES
|
|
13
|
+
* every request (500) until you set BOTH `authorize` (check your own session)
|
|
14
|
+
* and `allowedPrefixes` (only the areas the UI needs). The opt-outs
|
|
15
|
+
* `dangerouslyAllowUnauthenticated` and `dangerouslyAllowAllPaths` exist for
|
|
16
|
+
* local prototypes only.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
export interface G8ProxyConfig {
|
|
20
|
+
/**
|
|
21
|
+
* Path prefixes (relative to /api/v1, no leading slash) the browser may call,
|
|
22
|
+
* for example `["contacts", "companies", "lists"]`. `/contacts` and
|
|
23
|
+
* `/contacts/42` match "contacts"; "contactsX" does not. Omit to allow every
|
|
24
|
+
* path (fine for prototypes, not for production).
|
|
25
|
+
*/
|
|
26
|
+
allowedPrefixes?: readonly string[];
|
|
27
|
+
/**
|
|
28
|
+
* Your own gate, run before anything is forwarded. Return a `Response`
|
|
29
|
+
* (usually 401/403) to refuse, or nothing to continue. REQUIRED unless
|
|
30
|
+
* `dangerouslyAllowUnauthenticated` is true.
|
|
31
|
+
*/
|
|
32
|
+
authorize?: (request: Request) => Response | void | Promise<Response | void>;
|
|
33
|
+
/**
|
|
34
|
+
* Agency keys: decide the client org ON THE SERVER, from your session, for
|
|
35
|
+
* example `(req) => orgForUser(req)`. Sent as `X-Target-Org-Id`; whatever the
|
|
36
|
+
* browser sends is ignored. Return undefined to act on the key's own org.
|
|
37
|
+
*/
|
|
38
|
+
targetOrgId?: (request: Request) => string | undefined | Promise<string | undefined>;
|
|
39
|
+
/**
|
|
40
|
+
* Forward the BROWSER's own `X-Target-Org-Id`. Default false: a signed-in user
|
|
41
|
+
* of your app must not be able to switch to another client org. Ignored when
|
|
42
|
+
* `targetOrgId` is set.
|
|
43
|
+
*/
|
|
44
|
+
allowTargetOrgHeader?: boolean;
|
|
45
|
+
/** Prototype opt-out: run without `authorize`. Anyone who can reach the route can use your key. */
|
|
46
|
+
dangerouslyAllowUnauthenticated?: boolean;
|
|
47
|
+
/** Prototype opt-out: run without `allowedPrefixes` (every /api/v1 path is reachable). */
|
|
48
|
+
dangerouslyAllowAllPaths?: boolean;
|
|
49
|
+
/** Largest request body forwarded, in bytes. Default 5 MiB. */
|
|
50
|
+
maxBodyBytes?: number;
|
|
51
|
+
/** Replace `fetch` (tests). */
|
|
52
|
+
fetch?: typeof fetch;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export const DEFAULT_API_URL = "https://be.graph8.com";
|
|
56
|
+
const DEFAULT_MAX_BODY = 5 * 1024 * 1024;
|
|
57
|
+
|
|
58
|
+
/** Hop-by-hop headers (RFC 9110 7.6.1) plus the ones fetch re-computes. Never copied either way. */
|
|
59
|
+
const HOP_BY_HOP = new Set([
|
|
60
|
+
"connection",
|
|
61
|
+
"keep-alive",
|
|
62
|
+
"proxy-authenticate",
|
|
63
|
+
"proxy-authorization",
|
|
64
|
+
"proxy-connection",
|
|
65
|
+
"te",
|
|
66
|
+
"trailer",
|
|
67
|
+
"transfer-encoding",
|
|
68
|
+
"upgrade",
|
|
69
|
+
"host",
|
|
70
|
+
"content-length",
|
|
71
|
+
"content-encoding",
|
|
72
|
+
]);
|
|
73
|
+
|
|
74
|
+
/** Request headers the browser may influence. Everything else is dropped. */
|
|
75
|
+
const FORWARDED_REQUEST_HEADERS = ["content-type", "accept", "accept-language", "idempotency-key"];
|
|
76
|
+
|
|
77
|
+
function json(status: number, body: Record<string, unknown>): Response {
|
|
78
|
+
return new Response(JSON.stringify(body), { status, headers: { "content-type": "application/json" } });
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function cleanPrefix(prefix: string): string {
|
|
82
|
+
return prefix.replace(/^\/+|\/+$/g, "");
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/** The validated, re-encoded path under /api/v1, or null when a segment is unsafe. */
|
|
86
|
+
export function normalizePath(segments: readonly string[] | undefined): string | null {
|
|
87
|
+
if (!segments || segments.length === 0) return null;
|
|
88
|
+
const out: string[] = [];
|
|
89
|
+
for (const raw of segments) {
|
|
90
|
+
let seg: string;
|
|
91
|
+
try {
|
|
92
|
+
seg = decodeURIComponent(raw);
|
|
93
|
+
} catch {
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
if (seg === "" || seg === "." || seg === ".." || /[\\/\0]/.test(seg)) return null;
|
|
97
|
+
out.push(encodeURIComponent(seg));
|
|
98
|
+
}
|
|
99
|
+
return out.join("/");
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export function isAllowed(path: string, prefixes: readonly string[] | undefined): boolean {
|
|
103
|
+
if (!prefixes) return true;
|
|
104
|
+
const decoded = decodeURIComponent(path);
|
|
105
|
+
return prefixes.map(cleanPrefix).some((p) => p !== "" && (decoded === p || decoded.startsWith(`${p}/`)));
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function buildUpstreamHeaders(request: Request, apiKey: string, org: string | undefined): Headers {
|
|
109
|
+
const headers = new Headers();
|
|
110
|
+
for (const name of FORWARDED_REQUEST_HEADERS) {
|
|
111
|
+
const value = request.headers.get(name);
|
|
112
|
+
if (value) headers.set(name, value);
|
|
113
|
+
}
|
|
114
|
+
if (org) headers.set("X-Target-Org-Id", org);
|
|
115
|
+
headers.set("Authorization", `Bearer ${apiKey}`);
|
|
116
|
+
headers.set("X-G8-Client", "g8-blocks-proxy");
|
|
117
|
+
return headers;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function buildResponseHeaders(upstream: Response): Headers {
|
|
121
|
+
const headers = new Headers();
|
|
122
|
+
upstream.headers.forEach((value, name) => {
|
|
123
|
+
const lower = name.toLowerCase();
|
|
124
|
+
if (HOP_BY_HOP.has(lower) || lower === "set-cookie" || lower === "location") return;
|
|
125
|
+
headers.set(name, value);
|
|
126
|
+
});
|
|
127
|
+
return headers;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Read the body with a running byte count and stop as soon as it passes `max`,
|
|
132
|
+
* so an oversized upload never sits whole in memory. Null means "too large".
|
|
133
|
+
*/
|
|
134
|
+
async function readBodyCapped(request: Request, max: number): Promise<ArrayBuffer | null> {
|
|
135
|
+
const declared = Number(request.headers.get("content-length"));
|
|
136
|
+
if (Number.isFinite(declared) && declared > max) return null;
|
|
137
|
+
if (!request.body) return new ArrayBuffer(0);
|
|
138
|
+
const reader = request.body.getReader();
|
|
139
|
+
const chunks: Uint8Array[] = [];
|
|
140
|
+
let total = 0;
|
|
141
|
+
for (;;) {
|
|
142
|
+
const { done, value } = await reader.read();
|
|
143
|
+
if (done) break;
|
|
144
|
+
total += value.byteLength;
|
|
145
|
+
if (total > max) {
|
|
146
|
+
await reader.cancel().catch(() => undefined);
|
|
147
|
+
return null;
|
|
148
|
+
}
|
|
149
|
+
chunks.push(value);
|
|
150
|
+
}
|
|
151
|
+
const out = new ArrayBuffer(total);
|
|
152
|
+
const view = new Uint8Array(out);
|
|
153
|
+
let at = 0;
|
|
154
|
+
for (const c of chunks) {
|
|
155
|
+
view.set(c, at);
|
|
156
|
+
at += c.byteLength;
|
|
157
|
+
}
|
|
158
|
+
return out;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/** The first reason this config is unsafe to serve, or null. Checked on every request. */
|
|
162
|
+
function configProblem(config: G8ProxyConfig): string | null {
|
|
163
|
+
if (!config.authorize && !config.dangerouslyAllowUnauthenticated) {
|
|
164
|
+
return "Set `authorize` (check your app's session) in app/api/g8/[...path]/route.ts. The proxy refuses to run without it.";
|
|
165
|
+
}
|
|
166
|
+
if (!config.allowedPrefixes && !config.dangerouslyAllowAllPaths) {
|
|
167
|
+
return "Set `allowedPrefixes` (the API areas the UI needs) in app/api/g8/[...path]/route.ts. The proxy refuses to run without it.";
|
|
168
|
+
}
|
|
169
|
+
return null;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/** Next.js 15 requires exactly this shape; Next 14 passes a plain object, which `await` below also accepts. */
|
|
173
|
+
type RouteContext = { params: Promise<{ path: string[] }> };
|
|
174
|
+
|
|
175
|
+
/** Build the five App Router handlers. */
|
|
176
|
+
export function createG8Proxy(config: G8ProxyConfig = {}) {
|
|
177
|
+
async function handle(request: Request, context: RouteContext): Promise<Response> {
|
|
178
|
+
const problem = configProblem(config);
|
|
179
|
+
if (problem) return json(500, { error: "g8_proxy_misconfigured", message: problem });
|
|
180
|
+
const denied = await config.authorize?.(request);
|
|
181
|
+
if (denied) return denied;
|
|
182
|
+
|
|
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." });
|
|
185
|
+
|
|
186
|
+
const params = await (context.params as Promise<{ path?: string[] }> | { path?: string[] });
|
|
187
|
+
const path = normalizePath(params?.path);
|
|
188
|
+
if (!path) return json(400, { error: "bad_path", message: "Invalid API path." });
|
|
189
|
+
if (!isAllowed(path, config.allowedPrefixes)) {
|
|
190
|
+
return json(403, { error: "path_not_allowed", message: "This path is not available from the browser." });
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
const method = request.method.toUpperCase();
|
|
194
|
+
let body: ArrayBuffer | undefined;
|
|
195
|
+
if (method !== "GET" && method !== "HEAD") {
|
|
196
|
+
const read = await readBodyCapped(request, config.maxBodyBytes ?? DEFAULT_MAX_BODY);
|
|
197
|
+
if (!read) return json(413, { error: "body_too_large", message: "Request body is too large." });
|
|
198
|
+
body = read;
|
|
199
|
+
}
|
|
200
|
+
const org = config.targetOrgId
|
|
201
|
+
? await config.targetOrgId(request)
|
|
202
|
+
: config.allowTargetOrgHeader
|
|
203
|
+
? (request.headers.get("x-target-org-id") ?? undefined)
|
|
204
|
+
: undefined;
|
|
205
|
+
|
|
206
|
+
const base = (process.env.G8_API_URL ?? DEFAULT_API_URL).replace(/\/+$/, "");
|
|
207
|
+
const url = `${base}/api/v1/${path}${new URL(request.url).search}`;
|
|
208
|
+
const doFetch = config.fetch ?? globalThis.fetch;
|
|
209
|
+
let upstream: Response;
|
|
210
|
+
try {
|
|
211
|
+
upstream = await doFetch(url, {
|
|
212
|
+
method,
|
|
213
|
+
headers: buildUpstreamHeaders(request, apiKey, org),
|
|
214
|
+
body: body && body.byteLength > 0 ? body : undefined,
|
|
215
|
+
redirect: "manual",
|
|
216
|
+
cache: "no-store",
|
|
217
|
+
});
|
|
218
|
+
} catch {
|
|
219
|
+
return json(502, { error: "upstream_unreachable", message: "Could not reach the graph8 API." });
|
|
220
|
+
}
|
|
221
|
+
// redirect: "manual" hands back the 3xx itself; its Location would expose backend URLs.
|
|
222
|
+
if (upstream.status >= 300 && upstream.status < 400) {
|
|
223
|
+
return json(502, { error: "upstream_redirect", message: "The graph8 API answered with a redirect." });
|
|
224
|
+
}
|
|
225
|
+
return new Response(upstream.body, {
|
|
226
|
+
status: upstream.status,
|
|
227
|
+
statusText: upstream.statusText,
|
|
228
|
+
headers: buildResponseHeaders(upstream),
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
return { GET: handle, POST: handle, PUT: handle, PATCH: handle, DELETE: handle };
|
|
233
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Install as `app/api/g8/[...path]/route.ts` (the CLI copies it there and
|
|
3
|
+
* copies ./proxy.ts to `g8/server/proxy.ts`, matching the `@/g8/*` import).
|
|
4
|
+
*
|
|
5
|
+
* Next.js only allows HTTP-method names and a few config exports from a route
|
|
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.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { createG8Proxy } from "@/g8/server/proxy";
|
|
12
|
+
|
|
13
|
+
// 1. Only the API areas this app's UI needs, relative to /api/v1. REQUIRED.
|
|
14
|
+
const allowedPrefixes: string[] | undefined = undefined; // e.g. ["contacts", "companies", "lists"]
|
|
15
|
+
|
|
16
|
+
export const { GET, POST, PUT, PATCH, DELETE } = createG8Proxy({
|
|
17
|
+
allowedPrefixes,
|
|
18
|
+
// 2. Check YOUR session and return a Response (401/403) to refuse. REQUIRED:
|
|
19
|
+
// authorize: async (request) => { if (!(await getSession(request))) return new Response("Unauthorized", { status: 401 }); },
|
|
20
|
+
//
|
|
21
|
+
// Agency keys only: pick the client org from the session, never from the browser:
|
|
22
|
+
// targetOrgId: async (request) => (await getSession(request))?.g8OrgId,
|
|
23
|
+
//
|
|
24
|
+
// Local prototypes ONLY (anyone who can reach the route can use your key):
|
|
25
|
+
// dangerouslyAllowUnauthenticated: true,
|
|
26
|
+
// dangerouslyAllowAllPaths: true,
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
// Never cache proxied API responses.
|
|
30
|
+
export const dynamic = "force-dynamic";
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
# agents: build, test and run AI agents
|
|
2
|
+
|
|
3
|
+
An agent is a persona (how it talks), a voice, knowledge (documents and company knowledge) and skills
|
|
4
|
+
(single-purpose actions). This block gives you the screens to build one, prove it works before anyone talks
|
|
5
|
+
to it, and follow the runs agents do for you.
|
|
6
|
+
|
|
7
|
+
Install: `npx @graph8/sdk add agents` (installs `foundation` first).
|
|
8
|
+
|
|
9
|
+
## What you get
|
|
10
|
+
|
|
11
|
+
| Component | Use it for | Embed props |
|
|
12
|
+
|---|---|---|
|
|
13
|
+
| `AgentBuilder` | Agent list plus editor: persona dials, voice, inbound / outbound / voicemail instructions, active toggle, delete. Tabs for knowledge and skills | `agentId`, `onSelect`, `onChanged` |
|
|
14
|
+
| `AgentKnowledgePanel` | The agent's own documents (billable upload, remove) and company knowledge search | `agentId`, `useCompanyKnowledge`, `onToggleCompanyKnowledge`, `creditsPerFile` |
|
|
15
|
+
| `AgentSkillsPanel` | Attach / detach skills, write a new LLM skill | `agentId`, `onChanged` |
|
|
16
|
+
| `AgentTestConsole` | Free dry runs, saved cases, regression sweep, the activation gate; run an attached skill live | `agentId` |
|
|
17
|
+
| `AgentRuns` | Start a run, follow it (polled), cancel it, decide its approvals | `agentId`, `pageSize`, `pollMs` |
|
|
18
|
+
|
|
19
|
+
## The flow, with the ids that pass between steps
|
|
20
|
+
|
|
21
|
+
1. **Create**: `POST /voice/agents { role, persona, identity }` returns `agent.agent_id`. Create it
|
|
22
|
+
`agent_status: "inactive"`. `persona` needs `agent_name`, `persona`, `description` and the three dials
|
|
23
|
+
(0 to 1). `persona`, `identity` and `knowledge` are replaced whole on `PUT /voice/agents/{agent_id}`.
|
|
24
|
+
2. **Voice**: `GET /voice/voice-library/presets` lists voices; put the chosen id in `identity.voice`.
|
|
25
|
+
3. **Knowledge**: `POST /voice/agents/{agent_id}/documents/upload` (multipart field `files`, 5 MiB total per upload through the proxy,
|
|
26
|
+
billable) and `GET .../documents`. `use_company_knowledge` is a plain field on the agent; company
|
|
27
|
+
knowledge itself is read with `GET /knowledge/search?query=`.
|
|
28
|
+
4. **Skills**: `POST /skills { name, runtime_type: "llm", llm_config: { prompt, model } }` returns an
|
|
29
|
+
`action_id`; `POST /voice/agents/{agent_id}/skills { action_ids }` attaches it. Models come from
|
|
30
|
+
`GET /skills/models`.
|
|
31
|
+
5. **Test**: `POST /voice/agents/{agent_id}/test { input_message | test_case_id, channel, assertion_type,
|
|
32
|
+
expected_output }` is a dry run: no model call, no message sent. Save good ones with
|
|
33
|
+
`POST .../test-cases`, sweep with `POST .../test/run-all`, read the gate with `GET .../test-suite-status`.
|
|
34
|
+
6. **Activate**: `PUT /voice/agents/{agent_id} { agent_status: "active" }` once the gate is satisfied.
|
|
35
|
+
7. **Runs**: `GET /agent/specialists` gives the `agent_id` a run accepts; `POST /agent/runs { agent_id,
|
|
36
|
+
title, goal }` returns `work_item_id`; poll `GET /agent/runs/{run_id}` until `status` is terminal.
|
|
37
|
+
Approvals a run stops on: `GET /agent/approvals`, then `POST /agent/approvals/{approval_id}/decide
|
|
38
|
+
{ decision: "approve" | "reject" }`.
|
|
39
|
+
|
|
40
|
+
```tsx
|
|
41
|
+
"use client";
|
|
42
|
+
import { useState } from "react";
|
|
43
|
+
import { AgentBuilder } from "@/components/g8/agents/components/agent-builder";
|
|
44
|
+
import { AgentTestConsole } from "@/components/g8/agents/components/agent-test-console";
|
|
45
|
+
|
|
46
|
+
export function AgentStudio() {
|
|
47
|
+
const [id, setId] = useState<string | null>(null);
|
|
48
|
+
return (
|
|
49
|
+
<>
|
|
50
|
+
<AgentBuilder agentId={id} onSelect={setId} />
|
|
51
|
+
{id ? <AgentTestConsole agentId={id} /> : null}
|
|
52
|
+
</>
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
(`add` installs under `components/g8/agents/`, or `src/components/g8/agents/`; adjust the alias.)
|
|
58
|
+
|
|
59
|
+
## Tiers and confirmations
|
|
60
|
+
|
|
61
|
+
- Create, edit, attach, dry runs and saved cases are writes (free); they run directly.
|
|
62
|
+
- Deleting an agent, removing a document, detaching a skill and cancelling a run are `destructive` and go
|
|
63
|
+
through `ConfirmSpendDialog`.
|
|
64
|
+
- Uploading documents is `billable` (they are embedded with a paid model): the dialog shows the file count
|
|
65
|
+
and an estimate (`creditsPerFile`, default 5; there is no balance or price read, so it is an estimate).
|
|
66
|
+
- Running a skill live is `external` (it may call an API or message someone). Starting a run is a write that
|
|
67
|
+
spends credits as it works, so it is confirmed as `billable`. Approving an action is confirmed as `external`.
|
|
68
|
+
|
|
69
|
+
## Prerequisites
|
|
70
|
+
|
|
71
|
+
- `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`.
|
|
73
|
+
- Agents that place calls need a phone number and a dialer session: see the `dialer` block. Nothing here
|
|
74
|
+
places a call.
|
|
75
|
+
|
|
76
|
+
## Defaults the agent can use without asking
|
|
77
|
+
|
|
78
|
+
| Decision | Default |
|
|
79
|
+
|---|---|
|
|
80
|
+
| Status of a new agent | `inactive` until a dry run passes |
|
|
81
|
+
| Persona dials | 0.5 each |
|
|
82
|
+
| Use company knowledge | on |
|
|
83
|
+
|
|
84
|
+
Ask the person: who may approve agent actions and run skills live (decide it in the proxy's `authorize`).
|
|
85
|
+
|
|
86
|
+
## Known limits
|
|
87
|
+
|
|
88
|
+
- Runs and approvals that gate a Work coordination action cannot be decided with an API key
|
|
89
|
+
(`COORDINATION_APPROVAL_NOT_DECIDABLE_BY_KEY`): the screen shows the error; decide those in the graph8 app.
|
|
90
|
+
- No streaming: `AgentRuns` polls every `pollMs` (backoff up to 4x).
|
|
91
|
+
- A dry run never calls a model, so `llm_judge` assertions are saved but skipped.
|
|
92
|
+
|
|
93
|
+
## Recipes
|
|
94
|
+
|
|
95
|
+
| File | Does |
|
|
96
|
+
|---|---|
|
|
97
|
+
| `recipes/create-agent-and-attach-skill.ts` | Create an agent, create and attach a skill, list its documents |
|
|
98
|
+
| `recipes/test-agent-before-activating.ts` | Save a case, run the sweep, read the activation gate, one ad-hoc dry run |
|
|
99
|
+
| `recipes/run-and-follow-agent-run.ts` | Pick a specialist, start a run, poll to the end, list and decide approvals, cancel |
|
|
100
|
+
|
|
101
|
+
## Operations
|
|
102
|
+
|
|
103
|
+
| Operation | Method and path | Tier | Used by |
|
|
104
|
+
|---|---|---|---|
|
|
105
|
+
| listAgentApprovals | GET /agent/approvals | read | AgentRuns |
|
|
106
|
+
| decideAgentApproval | POST /agent/approvals/{approval_id}/decide | write | AgentRuns |
|
|
107
|
+
| listAgentRuns | GET /agent/runs | read | AgentRuns |
|
|
108
|
+
| createAgentRun | POST /agent/runs | write | AgentRuns |
|
|
109
|
+
| getAgentRun | GET /agent/runs/{run_id} | read | AgentRuns |
|
|
110
|
+
| cancelAgentRun | POST /agent/runs/{run_id}/cancel | destructive | AgentRuns |
|
|
111
|
+
| listAgentSpecialists | GET /agent/specialists | read | AgentRuns |
|
|
112
|
+
| searchKnowledge | GET /knowledge/search | read | AgentKnowledgePanel |
|
|
113
|
+
| listSkills | GET /skills | read | AgentSkillsPanel |
|
|
114
|
+
| createSkill | POST /skills | write | AgentSkillsPanel |
|
|
115
|
+
| listModels | GET /skills/models | read | AgentSkillsPanel |
|
|
116
|
+
| executeSkill | POST /skills/{action_id}/execute | external | AgentTestConsole |
|
|
117
|
+
| deleteAgentDocument | DELETE /voice/agent-documents/{document_id} | destructive | AgentKnowledgePanel |
|
|
118
|
+
| listVoiceAgents | GET /voice/agents | read | AgentBuilder |
|
|
119
|
+
| createVoiceAgent | POST /voice/agents | write | AgentBuilder |
|
|
120
|
+
| getVoiceAgent | GET /voice/agents/{agent_id} | read | AgentBuilder |
|
|
121
|
+
| updateVoiceAgent | PUT /voice/agents/{agent_id} | write | AgentBuilder, AgentKnowledgePanel |
|
|
122
|
+
| deleteVoiceAgent | DELETE /voice/agents/{agent_id} | destructive | AgentBuilder |
|
|
123
|
+
| listAgentDocuments | GET /voice/agents/{agent_id}/documents | read | AgentKnowledgePanel |
|
|
124
|
+
| uploadAgentDocuments | POST /voice/agents/{agent_id}/documents/upload | billable | AgentKnowledgePanel |
|
|
125
|
+
| listAgentSkills | GET /voice/agents/{agent_id}/skills | read | AgentSkillsPanel, AgentTestConsole |
|
|
126
|
+
| attachSkillsToAgent | POST /voice/agents/{agent_id}/skills | write | AgentSkillsPanel |
|
|
127
|
+
| detachSkillFromAgent | DELETE /voice/agents/{agent_id}/skills/{action_id} | destructive | AgentSkillsPanel |
|
|
128
|
+
| runAgentTest | POST /voice/agents/{agent_id}/test | write | AgentTestConsole |
|
|
129
|
+
| listAgentTestCases | GET /voice/agents/{agent_id}/test-cases | read | AgentTestConsole |
|
|
130
|
+
| createAgentTestCase | POST /voice/agents/{agent_id}/test-cases | write | AgentTestConsole |
|
|
131
|
+
| getAgentTestSuiteStatus | GET /voice/agents/{agent_id}/test-suite-status | read | AgentTestConsole |
|
|
132
|
+
| runAllAgentTests | POST /voice/agents/{agent_id}/test/run-all | write | AgentTestConsole |
|
|
133
|
+
| listPresetVoices | GET /voice/voice-library/presets | read | AgentBuilder |
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "../block.schema.json",
|
|
3
|
+
"id": "agents",
|
|
4
|
+
"title": "AI agents",
|
|
5
|
+
"summary": "Build and test AI agents (voice and chat): persona, voice, knowledge, skills, dry-run test console and live agent runs with approvals.",
|
|
6
|
+
"features": [
|
|
7
|
+
"agent list with create, edit, activate and delete",
|
|
8
|
+
"persona dials, voice choice and per-call-type instructions",
|
|
9
|
+
"agent documents (billable upload) and company knowledge search",
|
|
10
|
+
"attach, detach and write skills",
|
|
11
|
+
"dry-run test console with saved cases and an activation gate",
|
|
12
|
+
"run a skill live behind a confirmation",
|
|
13
|
+
"agent runs with polling, cancel and approvals"
|
|
14
|
+
],
|
|
15
|
+
"dependsOn": [
|
|
16
|
+
"foundation"
|
|
17
|
+
],
|
|
18
|
+
"operations": [
|
|
19
|
+
"attach_skills_to_agent_voice_agents__agent_id__skills_post",
|
|
20
|
+
"cancel_agent_run_agent_runs__run_id__cancel_post",
|
|
21
|
+
"create_agent_run_agent_runs_post",
|
|
22
|
+
"create_agent_test_case_voice_agents__agent_id__test_cases_post",
|
|
23
|
+
"create_skill_skills_post",
|
|
24
|
+
"create_voice_agent_voice_agents_post",
|
|
25
|
+
"decide_agent_approval_agent_approvals__approval_id__decide_post",
|
|
26
|
+
"delete_agent_document_voice_agent_documents__document_id__delete",
|
|
27
|
+
"delete_voice_agent_voice_agents__agent_id__delete",
|
|
28
|
+
"detach_skill_from_agent_voice_agents__agent_id__skills__action_id__delete",
|
|
29
|
+
"execute_skill_skills__action_id__execute_post",
|
|
30
|
+
"get_agent_run_agent_runs__run_id__get",
|
|
31
|
+
"get_agent_test_suite_status_voice_agents__agent_id__test_suite_status_get",
|
|
32
|
+
"get_voice_agent_voice_agents__agent_id__get",
|
|
33
|
+
"list_agent_approvals_agent_approvals_get",
|
|
34
|
+
"list_agent_documents_voice_agents__agent_id__documents_get",
|
|
35
|
+
"list_agent_runs_agent_runs_get",
|
|
36
|
+
"list_agent_skills_voice_agents__agent_id__skills_get",
|
|
37
|
+
"list_agent_specialists_agent_specialists_get",
|
|
38
|
+
"list_agent_test_cases_voice_agents__agent_id__test_cases_get",
|
|
39
|
+
"list_models_skills_models_get",
|
|
40
|
+
"list_preset_voices_voice_voice_library_presets_get",
|
|
41
|
+
"list_skills_skills_get",
|
|
42
|
+
"list_voice_agents_voice_agents_get",
|
|
43
|
+
"run_agent_test_voice_agents__agent_id__test_post",
|
|
44
|
+
"run_all_agent_tests_voice_agents__agent_id__test_run_all_post",
|
|
45
|
+
"search_knowledge_knowledge_search_get",
|
|
46
|
+
"update_voice_agent_voice_agents__agent_id__put",
|
|
47
|
+
"upload_agent_documents_voice_agents__agent_id__documents_upload_post"
|
|
48
|
+
],
|
|
49
|
+
"components": [
|
|
50
|
+
{
|
|
51
|
+
"name": "AgentBuilder",
|
|
52
|
+
"file": "components/agent-builder.tsx",
|
|
53
|
+
"purpose": "List, create, edit and delete agents: persona, voice, instructions, active toggle, with the knowledge and skills panels as tabs.",
|
|
54
|
+
"operations": [
|
|
55
|
+
"list_voice_agents_voice_agents_get",
|
|
56
|
+
"get_voice_agent_voice_agents__agent_id__get",
|
|
57
|
+
"create_voice_agent_voice_agents_post",
|
|
58
|
+
"update_voice_agent_voice_agents__agent_id__put",
|
|
59
|
+
"delete_voice_agent_voice_agents__agent_id__delete",
|
|
60
|
+
"list_preset_voices_voice_voice_library_presets_get"
|
|
61
|
+
],
|
|
62
|
+
"tiers": [
|
|
63
|
+
"read",
|
|
64
|
+
"write",
|
|
65
|
+
"destructive"
|
|
66
|
+
]
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
"name": "AgentKnowledgePanel",
|
|
70
|
+
"file": "components/agent-knowledge-panel.tsx",
|
|
71
|
+
"purpose": "An agent's own documents (billable upload, delete) plus company knowledge search and the use-company-knowledge switch.",
|
|
72
|
+
"operations": [
|
|
73
|
+
"update_voice_agent_voice_agents__agent_id__put",
|
|
74
|
+
"list_agent_documents_voice_agents__agent_id__documents_get",
|
|
75
|
+
"upload_agent_documents_voice_agents__agent_id__documents_upload_post",
|
|
76
|
+
"delete_agent_document_voice_agent_documents__document_id__delete",
|
|
77
|
+
"search_knowledge_knowledge_search_get"
|
|
78
|
+
],
|
|
79
|
+
"tiers": [
|
|
80
|
+
"read",
|
|
81
|
+
"write",
|
|
82
|
+
"billable",
|
|
83
|
+
"destructive"
|
|
84
|
+
]
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
"name": "AgentSkillsPanel",
|
|
88
|
+
"file": "components/agent-skills-panel.tsx",
|
|
89
|
+
"purpose": "Attach and detach skills for an agent, or write a new LLM skill in place.",
|
|
90
|
+
"operations": [
|
|
91
|
+
"list_agent_skills_voice_agents__agent_id__skills_get",
|
|
92
|
+
"list_skills_skills_get",
|
|
93
|
+
"attach_skills_to_agent_voice_agents__agent_id__skills_post",
|
|
94
|
+
"detach_skill_from_agent_voice_agents__agent_id__skills__action_id__delete",
|
|
95
|
+
"list_models_skills_models_get",
|
|
96
|
+
"create_skill_skills_post"
|
|
97
|
+
],
|
|
98
|
+
"tiers": [
|
|
99
|
+
"read",
|
|
100
|
+
"write",
|
|
101
|
+
"destructive"
|
|
102
|
+
]
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
"name": "AgentTestConsole",
|
|
106
|
+
"file": "components/agent-test-console.tsx",
|
|
107
|
+
"purpose": "Free dry runs (ad-hoc or saved cases), regression sweep and activation gate; run an attached skill live behind an external confirmation.",
|
|
108
|
+
"operations": [
|
|
109
|
+
"list_agent_test_cases_voice_agents__agent_id__test_cases_get",
|
|
110
|
+
"get_agent_test_suite_status_voice_agents__agent_id__test_suite_status_get",
|
|
111
|
+
"run_agent_test_voice_agents__agent_id__test_post",
|
|
112
|
+
"create_agent_test_case_voice_agents__agent_id__test_cases_post",
|
|
113
|
+
"run_all_agent_tests_voice_agents__agent_id__test_run_all_post",
|
|
114
|
+
"list_agent_skills_voice_agents__agent_id__skills_get",
|
|
115
|
+
"execute_skill_skills__action_id__execute_post"
|
|
116
|
+
],
|
|
117
|
+
"tiers": [
|
|
118
|
+
"read",
|
|
119
|
+
"write",
|
|
120
|
+
"external"
|
|
121
|
+
]
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
"name": "AgentRuns",
|
|
125
|
+
"file": "components/agent-runs.tsx",
|
|
126
|
+
"purpose": "Start, follow (polled), cancel agent runs and approve or reject the actions a run stops on.",
|
|
127
|
+
"operations": [
|
|
128
|
+
"list_agent_runs_agent_runs_get",
|
|
129
|
+
"list_agent_specialists_agent_specialists_get",
|
|
130
|
+
"create_agent_run_agent_runs_post",
|
|
131
|
+
"get_agent_run_agent_runs__run_id__get",
|
|
132
|
+
"cancel_agent_run_agent_runs__run_id__cancel_post",
|
|
133
|
+
"list_agent_approvals_agent_approvals_get",
|
|
134
|
+
"decide_agent_approval_agent_approvals__approval_id__decide_post"
|
|
135
|
+
],
|
|
136
|
+
"tiers": [
|
|
137
|
+
"read",
|
|
138
|
+
"write",
|
|
139
|
+
"destructive"
|
|
140
|
+
]
|
|
141
|
+
}
|
|
142
|
+
],
|
|
143
|
+
"hooks": [],
|
|
144
|
+
"lib": [
|
|
145
|
+
{
|
|
146
|
+
"file": "lib/agent-types.ts",
|
|
147
|
+
"purpose": "Response shapes (agent, persona, skill, run) and small readers for the enveloped and un-enveloped bodies voice and skills return."
|
|
148
|
+
}
|
|
149
|
+
],
|
|
150
|
+
"recipes": [
|
|
151
|
+
{
|
|
152
|
+
"file": "recipes/create-agent-and-attach-skill.ts",
|
|
153
|
+
"title": "Create an agent, give it a skill and knowledge",
|
|
154
|
+
"when": "Building an agent from code or a seed script instead of the AgentBuilder screen."
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
"file": "recipes/test-agent-before-activating.ts",
|
|
158
|
+
"title": "Save test cases, sweep, read the activation gate",
|
|
159
|
+
"when": "Before setting an agent active; dry runs are free."
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
"file": "recipes/run-and-follow-agent-run.ts",
|
|
163
|
+
"title": "Start an agent run, poll it, decide approvals",
|
|
164
|
+
"when": "Handing a goal to an agent and following it to the end."
|
|
165
|
+
}
|
|
166
|
+
],
|
|
167
|
+
"prerequisites": [
|
|
168
|
+
{
|
|
169
|
+
"id": "foundation-installed",
|
|
170
|
+
"description": "The foundation block is installed and the /api/g8 proxy allows the agent, skills, knowledge and voice prefixes.",
|
|
171
|
+
"where": "app",
|
|
172
|
+
"verify": "allowedPrefixes includes \"voice\", \"skills\", \"knowledge\" and \"agent\"."
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
"id": "api-key-scopes",
|
|
176
|
+
"description": "The API key carries the block's scopes (voice, knowledge, workflows).",
|
|
177
|
+
"where": "api",
|
|
178
|
+
"verify": "describeCurrentKey lists voice:read, voice:write, voice:delete, knowledge:read, workflows:read, workflows:write, workflows:run, workflows:delete."
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
"id": "company-knowledge",
|
|
182
|
+
"description": "Company knowledge exists in the workspace if agents should draw on it (optional).",
|
|
183
|
+
"where": "api",
|
|
184
|
+
"verify": "GET /knowledge/status returns concepts."
|
|
185
|
+
}
|
|
186
|
+
],
|
|
187
|
+
"scopes": [
|
|
188
|
+
"knowledge:read",
|
|
189
|
+
"voice:delete",
|
|
190
|
+
"voice:read",
|
|
191
|
+
"voice:run",
|
|
192
|
+
"voice:write",
|
|
193
|
+
"workflows:delete",
|
|
194
|
+
"workflows:read",
|
|
195
|
+
"workflows:run",
|
|
196
|
+
"workflows:write"
|
|
197
|
+
],
|
|
198
|
+
"defaults": [
|
|
199
|
+
{
|
|
200
|
+
"decision": "Status of a new agent",
|
|
201
|
+
"default": "inactive until a dry run passes, then a person turns it active",
|
|
202
|
+
"askHuman": false
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
"decision": "Persona dials (formality, conciseness, assertiveness)",
|
|
206
|
+
"default": "0.5 each",
|
|
207
|
+
"askHuman": false
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
"decision": "Use company knowledge",
|
|
211
|
+
"default": "on",
|
|
212
|
+
"askHuman": false
|
|
213
|
+
},
|
|
214
|
+
{
|
|
215
|
+
"decision": "Who may approve agent actions and run skills live",
|
|
216
|
+
"default": "decided in the proxy's authorize hook; the screens always confirm first",
|
|
217
|
+
"askHuman": true
|
|
218
|
+
}
|
|
219
|
+
],
|
|
220
|
+
"peerDependencies": {
|
|
221
|
+
"react": ">=18"
|
|
222
|
+
}
|
|
223
|
+
}
|