@agent-native/core 0.118.0 → 0.119.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/corpus/README.md +2 -2
- package/corpus/core/CHANGELOG.md +32 -0
- package/corpus/core/docs/content/a2a-protocol.mdx +15 -0
- package/corpus/core/docs/content/template-chat.mdx +1 -1
- package/corpus/core/docs/content/template-plan.mdx +3 -3
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/a2a/activity.ts +371 -0
- package/corpus/core/src/a2a/client.ts +35 -11
- package/corpus/core/src/a2a/index.ts +21 -0
- package/corpus/core/src/a2a/types.ts +8 -0
- package/corpus/core/src/agent/model-config.ts +19 -23
- package/corpus/core/src/agent/production-agent.ts +167 -100
- package/corpus/core/src/agent/types.ts +16 -1
- package/corpus/core/src/cli/index.ts +18 -10
- package/corpus/core/src/cli/multi-frontier-runs.ts +5 -3
- package/corpus/core/src/cli/templates-meta.ts +0 -12
- package/corpus/core/src/cli/workspace-dev.ts +1 -1
- package/corpus/core/src/client/AgentPanel.tsx +9 -1
- package/corpus/core/src/client/RunStuckBanner.tsx +39 -47
- package/corpus/core/src/client/chat/action-chat-ui-surface.tsx +32 -0
- package/corpus/core/src/client/chat/message-components.tsx +53 -8
- package/corpus/core/src/client/chat/tool-call-display.tsx +214 -44
- package/corpus/core/src/client/chat/widgets/InlineExtensionWidget.tsx +0 -1
- package/corpus/core/src/client/chat/widgets/builtin-tool-renderers.tsx +7 -3
- package/corpus/core/src/client/chat-model-groups.ts +67 -27
- package/corpus/core/src/client/conversation/AgentConversation.tsx +12 -1
- package/corpus/core/src/client/error-capture.ts +2 -6
- package/corpus/core/src/client/resources/McpConnectionSuggestion.tsx +20 -14
- package/corpus/core/src/client/resources/ResourcesPanel.tsx +5 -1
- package/corpus/core/src/client/resources/mcp-integration-catalog.ts +7 -17
- package/corpus/core/src/client/resources/mcp-integration-logos.ts +2 -2
- package/corpus/core/src/client/route-chunk-recovery.ts +5 -3
- package/corpus/core/src/client/session-replay.ts +3 -3
- package/corpus/core/src/client/settings/SettingsPanel.tsx +15 -6
- package/corpus/core/src/client/sharing/ShareButton.tsx +1 -27
- package/corpus/core/src/client/sharing/ShareDialog.tsx +0 -16
- package/corpus/core/src/client/sharing/useShareButtonController.ts +0 -7
- package/corpus/core/src/client/sharing/useShareDialogController.ts +0 -2
- package/corpus/core/src/client/sse-event-processor.ts +85 -1
- package/corpus/core/src/client/transcription/use-live-transcription.ts +64 -45
- package/corpus/core/src/deploy/build.ts +2 -1
- package/corpus/core/src/guards/db-tool-scoping.ts +1 -1
- package/corpus/core/src/integrations/adapters/slack.ts +84 -5
- package/corpus/core/src/integrations/index.ts +5 -1
- package/corpus/core/src/localization/default-messages.ts +7 -1
- package/corpus/core/src/mcp-client/oauth-routes.ts +45 -12
- package/corpus/core/src/scripts/agent-engines/list-agent-engines.ts +1 -18
- package/corpus/core/src/scripts/call-agent.ts +49 -6
- package/corpus/core/src/server/agent-chat-plugin.ts +50 -10
- package/corpus/core/src/server/realtime-voice.ts +4 -1
- package/corpus/core/src/templates/workspace-core/.agents/skills/a2a-protocol/SKILL.md +16 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/voice-transcription/SKILL.md +7 -5
- package/corpus/core/src/terminal/cli-registry.ts +1 -1
- package/corpus/core/src/vite/client.ts +166 -1
- package/corpus/templates/analytics/app/hooks/use-dashboard-views.ts +13 -1
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/ViewsMenu.tsx +10 -0
- package/corpus/templates/analytics/changelog/2026-07-22-show-a-useful-error-when-saving-a-dashboard-view-fails.md +6 -0
- package/corpus/templates/brain/app/routes/sources.tsx +181 -114
- package/corpus/templates/clips/AGENTS.md +8 -6
- package/corpus/templates/clips/actions/request-transcript.ts +90 -420
- package/corpus/templates/clips/actions/save-browser-transcript.ts +11 -28
- package/corpus/templates/clips/app/components/capture-install-options.tsx +5 -3
- package/corpus/templates/clips/app/components/player/transcript-panel.tsx +3 -136
- package/corpus/templates/clips/app/lib/capture-install-options.ts +15 -4
- package/corpus/templates/clips/app/routes/download.tsx +3 -2
- package/corpus/templates/clips/changelog/2026-07-22-fixed-an-intermittent-hydration-error-on-the-download-page.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-22-fixed-transcript-generation-when-native-speech-capture-retur.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-22-transcript-generation-now-retries-with-backup-speech-recogni.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-23-fixed-recordings-failing-to-save-with-a-cancelled-or-cleanup.md +6 -0
- package/corpus/templates/clips/server/lib/public-agent-context.ts +2 -2
- package/corpus/templates/clips/server/plugins/db.ts +9 -1
- package/corpus/templates/clips/server/register-secrets.ts +7 -6
- package/corpus/templates/content/app/components/editor/SlashCommandMenu.tsx +16 -84
- package/corpus/templates/content/app/components/editor/VisualEditor.tsx +13 -7
- package/corpus/templates/content/app/components/editor/extensions/ImageBlock.tsx +2 -2
- package/corpus/templates/content/app/i18n-data.ts +10 -0
- package/corpus/templates/design/server/lib/fig-file-decoder.ts +1 -0
- package/corpus/templates/plan/app/entry.client.tsx +3 -0
- package/corpus/templates/plan/changelog/2026-07-22-recover-stale-pages-after-a-deployment-refresh-automatically.md +6 -0
- package/corpus/templates/slides/app/hooks/use-agent-generating.ts +10 -3
- package/corpus/templates/slides/app/pages/Index.tsx +1 -0
- package/corpus/templates/slides/changelog/2026-07-22-new-deck-prompts-now-open-in-their-own-visible-chat-thread.md +6 -0
- package/corpus/toolkit/CHANGELOG.md +9 -0
- package/corpus/toolkit/package.json +1 -1
- package/corpus/toolkit/src/composer/PromptComposer.tsx +5 -1
- package/corpus/toolkit/src/composer/RealtimeVoiceMode.tsx +119 -31
- package/corpus/toolkit/src/composer/useRealtimeVoiceMode.tsx +30 -0
- package/corpus/toolkit/src/conformance/runner.tsx +153 -1
- package/corpus/toolkit/src/editor/SharedRichEditor.tsx +13 -2
- package/corpus/toolkit/src/editor/SlashCommandMenu.tsx +20 -0
- package/corpus/toolkit/src/editor/index.ts +2 -0
- package/corpus/toolkit/src/styles.css +52 -23
- package/dist/a2a/activity.d.ts +50 -0
- package/dist/a2a/activity.d.ts.map +1 -0
- package/dist/a2a/activity.js +236 -0
- package/dist/a2a/activity.js.map +1 -0
- package/dist/a2a/client.d.ts +5 -1
- package/dist/a2a/client.d.ts.map +1 -1
- package/dist/a2a/client.js +18 -13
- package/dist/a2a/client.js.map +1 -1
- package/dist/a2a/index.d.ts +2 -1
- package/dist/a2a/index.d.ts.map +1 -1
- package/dist/a2a/index.js +1 -0
- package/dist/a2a/index.js.map +1 -1
- package/dist/a2a/types.d.ts +1 -0
- package/dist/a2a/types.d.ts.map +1 -1
- package/dist/a2a/types.js.map +1 -1
- package/dist/agent/engine/anthropic-engine.d.ts +1 -1
- package/dist/agent/engine/builder-engine.d.ts +2 -2
- package/dist/agent/engine/builder-engine.d.ts.map +1 -1
- package/dist/agent/model-config.d.ts +16 -16
- package/dist/agent/model-config.d.ts.map +1 -1
- package/dist/agent/model-config.js +19 -23
- package/dist/agent/model-config.js.map +1 -1
- package/dist/agent/production-agent.d.ts +26 -0
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +137 -80
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/agent/types.d.ts +10 -0
- package/dist/agent/types.d.ts.map +1 -1
- package/dist/agent/types.js.map +1 -1
- package/dist/cli/index.js +18 -8
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/multi-frontier-runs.js +3 -3
- package/dist/cli/multi-frontier-runs.js.map +1 -1
- package/dist/cli/templates-meta.d.ts.map +1 -1
- package/dist/cli/templates-meta.js +0 -12
- package/dist/cli/templates-meta.js.map +1 -1
- package/dist/cli/workspace-dev.js +1 -1
- package/dist/cli/workspace-dev.js.map +1 -1
- package/dist/client/AgentPanel.d.ts.map +1 -1
- package/dist/client/AgentPanel.js +4 -1
- package/dist/client/AgentPanel.js.map +1 -1
- package/dist/client/RunStuckBanner.d.ts +3 -5
- package/dist/client/RunStuckBanner.d.ts.map +1 -1
- package/dist/client/RunStuckBanner.js +17 -18
- package/dist/client/RunStuckBanner.js.map +1 -1
- package/dist/client/chat/action-chat-ui-surface.d.ts +8 -0
- package/dist/client/chat/action-chat-ui-surface.d.ts.map +1 -0
- package/dist/client/chat/action-chat-ui-surface.js +10 -0
- package/dist/client/chat/action-chat-ui-surface.js.map +1 -0
- package/dist/client/chat/message-components.d.ts +3 -0
- package/dist/client/chat/message-components.d.ts.map +1 -1
- package/dist/client/chat/message-components.js +40 -7
- package/dist/client/chat/message-components.js.map +1 -1
- package/dist/client/chat/tool-call-display.d.ts +3 -1
- package/dist/client/chat/tool-call-display.d.ts.map +1 -1
- package/dist/client/chat/tool-call-display.js +76 -23
- package/dist/client/chat/tool-call-display.js.map +1 -1
- package/dist/client/chat/widgets/InlineExtensionWidget.d.ts.map +1 -1
- package/dist/client/chat/widgets/InlineExtensionWidget.js +1 -1
- package/dist/client/chat/widgets/InlineExtensionWidget.js.map +1 -1
- package/dist/client/chat/widgets/builtin-tool-renderers.d.ts.map +1 -1
- package/dist/client/chat/widgets/builtin-tool-renderers.js +5 -3
- package/dist/client/chat/widgets/builtin-tool-renderers.js.map +1 -1
- package/dist/client/chat-model-groups.d.ts.map +1 -1
- package/dist/client/chat-model-groups.js +44 -21
- package/dist/client/chat-model-groups.js.map +1 -1
- package/dist/client/conversation/AgentConversation.d.ts.map +1 -1
- package/dist/client/conversation/AgentConversation.js +3 -2
- package/dist/client/conversation/AgentConversation.js.map +1 -1
- package/dist/client/error-capture.d.ts.map +1 -1
- package/dist/client/error-capture.js +2 -2
- package/dist/client/error-capture.js.map +1 -1
- package/dist/client/resources/McpConnectionSuggestion.d.ts +1 -0
- package/dist/client/resources/McpConnectionSuggestion.d.ts.map +1 -1
- package/dist/client/resources/McpConnectionSuggestion.js +9 -8
- package/dist/client/resources/McpConnectionSuggestion.js.map +1 -1
- package/dist/client/resources/ResourcesPanel.d.ts.map +1 -1
- package/dist/client/resources/ResourcesPanel.js +3 -1
- package/dist/client/resources/ResourcesPanel.js.map +1 -1
- package/dist/client/resources/mcp-integration-catalog.d.ts +1 -0
- package/dist/client/resources/mcp-integration-catalog.d.ts.map +1 -1
- package/dist/client/resources/mcp-integration-catalog.js +4 -17
- package/dist/client/resources/mcp-integration-catalog.js.map +1 -1
- package/dist/client/resources/mcp-integration-logos.js +2 -2
- package/dist/client/resources/mcp-integration-logos.js.map +1 -1
- package/dist/client/route-chunk-recovery.d.ts.map +1 -1
- package/dist/client/route-chunk-recovery.js +5 -3
- package/dist/client/route-chunk-recovery.js.map +1 -1
- package/dist/client/session-replay.js +3 -3
- package/dist/client/session-replay.js.map +1 -1
- package/dist/client/settings/SettingsPanel.d.ts.map +1 -1
- package/dist/client/settings/SettingsPanel.js +2 -2
- package/dist/client/settings/SettingsPanel.js.map +1 -1
- package/dist/client/sharing/ShareButton.d.ts +1 -1
- package/dist/client/sharing/ShareButton.d.ts.map +1 -1
- package/dist/client/sharing/ShareButton.js +3 -4
- package/dist/client/sharing/ShareButton.js.map +1 -1
- package/dist/client/sharing/ShareDialog.d.ts.map +1 -1
- package/dist/client/sharing/ShareDialog.js +1 -2
- package/dist/client/sharing/ShareDialog.js.map +1 -1
- package/dist/client/sharing/useShareButtonController.d.ts +0 -1
- package/dist/client/sharing/useShareButtonController.d.ts.map +1 -1
- package/dist/client/sharing/useShareButtonController.js +0 -6
- package/dist/client/sharing/useShareButtonController.js.map +1 -1
- package/dist/client/sharing/useShareDialogController.d.ts +0 -1
- package/dist/client/sharing/useShareDialogController.d.ts.map +1 -1
- package/dist/client/sharing/useShareDialogController.js +0 -1
- package/dist/client/sharing/useShareDialogController.js.map +1 -1
- package/dist/client/sse-event-processor.d.ts +12 -0
- package/dist/client/sse-event-processor.d.ts.map +1 -1
- package/dist/client/sse-event-processor.js +63 -1
- package/dist/client/sse-event-processor.js.map +1 -1
- package/dist/client/transcription/use-live-transcription.d.ts +3 -3
- package/dist/client/transcription/use-live-transcription.d.ts.map +1 -1
- package/dist/client/transcription/use-live-transcription.js +22 -11
- package/dist/client/transcription/use-live-transcription.js.map +1 -1
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/awareness.d.ts.map +1 -1
- package/dist/deploy/build.d.ts.map +1 -1
- package/dist/deploy/build.js +1 -1
- package/dist/deploy/build.js.map +1 -1
- package/dist/guards/db-tool-scoping.js +1 -1
- package/dist/guards/db-tool-scoping.js.map +1 -1
- package/dist/integrations/adapters/slack.d.ts +1 -0
- package/dist/integrations/adapters/slack.d.ts.map +1 -1
- package/dist/integrations/adapters/slack.js +61 -5
- package/dist/integrations/adapters/slack.js.map +1 -1
- package/dist/integrations/index.d.ts +1 -1
- package/dist/integrations/index.d.ts.map +1 -1
- package/dist/integrations/index.js +1 -1
- package/dist/integrations/index.js.map +1 -1
- package/dist/localization/default-messages.d.ts +6 -0
- package/dist/localization/default-messages.d.ts.map +1 -1
- package/dist/localization/default-messages.js +7 -1
- package/dist/localization/default-messages.js.map +1 -1
- package/dist/mcp-client/oauth-routes.d.ts +3 -0
- package/dist/mcp-client/oauth-routes.d.ts.map +1 -1
- package/dist/mcp-client/oauth-routes.js +41 -12
- package/dist/mcp-client/oauth-routes.js.map +1 -1
- package/dist/observability/routes.d.ts +3 -3
- package/dist/provider-api/actions/custom-provider-registration.d.ts +8 -8
- package/dist/provider-api/actions/provider-api.d.ts +11 -11
- package/dist/scripts/agent-engines/list-agent-engines.d.ts.map +1 -1
- package/dist/scripts/agent-engines/list-agent-engines.js +1 -18
- package/dist/scripts/agent-engines/list-agent-engines.js.map +1 -1
- package/dist/scripts/call-agent.d.ts.map +1 -1
- package/dist/scripts/call-agent.js +49 -6
- package/dist/scripts/call-agent.js.map +1 -1
- package/dist/secrets/routes.d.ts +6 -6
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +38 -10
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/realtime-voice.d.ts.map +1 -1
- package/dist/server/realtime-voice.js +1 -1
- package/dist/server/realtime-voice.js.map +1 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/dist/templates/workspace-core/.agents/skills/a2a-protocol/SKILL.md +16 -0
- package/dist/templates/workspace-core/.agents/skills/voice-transcription/SKILL.md +7 -5
- package/dist/terminal/cli-registry.js +1 -1
- package/dist/terminal/cli-registry.js.map +1 -1
- package/dist/vite/client.d.ts +8 -1
- package/dist/vite/client.d.ts.map +1 -1
- package/dist/vite/client.js +113 -2
- package/dist/vite/client.js.map +1 -1
- package/docs/content/a2a-protocol.mdx +15 -0
- package/docs/content/template-chat.mdx +1 -1
- package/docs/content/template-plan.mdx +3 -3
- package/package.json +2 -2
- package/src/a2a/activity.ts +371 -0
- package/src/a2a/client.ts +35 -11
- package/src/a2a/index.ts +21 -0
- package/src/a2a/types.ts +8 -0
- package/src/agent/model-config.ts +19 -23
- package/src/agent/production-agent.ts +167 -100
- package/src/agent/types.ts +16 -1
- package/src/cli/index.ts +18 -10
- package/src/cli/multi-frontier-runs.ts +5 -3
- package/src/cli/templates-meta.ts +0 -12
- package/src/cli/workspace-dev.ts +1 -1
- package/src/client/AgentPanel.tsx +9 -1
- package/src/client/RunStuckBanner.tsx +39 -47
- package/src/client/chat/action-chat-ui-surface.tsx +32 -0
- package/src/client/chat/message-components.tsx +53 -8
- package/src/client/chat/tool-call-display.tsx +214 -44
- package/src/client/chat/widgets/InlineExtensionWidget.tsx +0 -1
- package/src/client/chat/widgets/builtin-tool-renderers.tsx +7 -3
- package/src/client/chat-model-groups.ts +67 -27
- package/src/client/conversation/AgentConversation.tsx +12 -1
- package/src/client/error-capture.ts +2 -6
- package/src/client/resources/McpConnectionSuggestion.tsx +20 -14
- package/src/client/resources/ResourcesPanel.tsx +5 -1
- package/src/client/resources/mcp-integration-catalog.ts +7 -17
- package/src/client/resources/mcp-integration-logos.ts +2 -2
- package/src/client/route-chunk-recovery.ts +5 -3
- package/src/client/session-replay.ts +3 -3
- package/src/client/settings/SettingsPanel.tsx +15 -6
- package/src/client/sharing/ShareButton.tsx +1 -27
- package/src/client/sharing/ShareDialog.tsx +0 -16
- package/src/client/sharing/useShareButtonController.ts +0 -7
- package/src/client/sharing/useShareDialogController.ts +0 -2
- package/src/client/sse-event-processor.ts +85 -1
- package/src/client/transcription/use-live-transcription.ts +64 -45
- package/src/deploy/build.ts +2 -1
- package/src/guards/db-tool-scoping.ts +1 -1
- package/src/integrations/adapters/slack.ts +84 -5
- package/src/integrations/index.ts +5 -1
- package/src/localization/default-messages.ts +7 -1
- package/src/mcp-client/oauth-routes.ts +45 -12
- package/src/scripts/agent-engines/list-agent-engines.ts +1 -18
- package/src/scripts/call-agent.ts +49 -6
- package/src/server/agent-chat-plugin.ts +50 -10
- package/src/server/realtime-voice.ts +4 -1
- package/src/templates/workspace-core/.agents/skills/a2a-protocol/SKILL.md +16 -0
- package/src/templates/workspace-core/.agents/skills/voice-transcription/SKILL.md +7 -5
- package/src/terminal/cli-registry.ts +1 -1
- package/src/vite/client.ts +166 -1
- package/corpus/core/src/observability/hosted-model-experiment.ts +0 -118
- package/corpus/templates/crm/.agents/skills/agent-native-docs/SKILL.md +0 -115
- package/corpus/templates/crm/.agents/skills/agent-native-toolkit/SKILL.md +0 -177
- package/corpus/templates/crm/.agents/skills/crm/SKILL.md +0 -128
- package/corpus/templates/crm/.agents/skills/customizing-agent-native/SKILL.md +0 -220
- package/corpus/templates/crm/.agents/skills/feature-flags/SKILL.md +0 -169
- package/corpus/templates/crm/.agents/skills/upgrade-agent-native/SKILL.md +0 -100
- package/corpus/templates/crm/.env.example +0 -5
- package/corpus/templates/crm/AGENTS.md +0 -120
- package/corpus/templates/crm/CHANGELOG.md +0 -1
- package/corpus/templates/crm/DEVELOPING.md +0 -66
- package/corpus/templates/crm/README.md +0 -106
- package/corpus/templates/crm/_gitignore +0 -12
- package/corpus/templates/crm/actions/_crm-action-utils.ts +0 -87
- package/corpus/templates/crm/actions/_crm-dashboard.ts +0 -69
- package/corpus/templates/crm/actions/_crm-data-program-actions.ts +0 -15
- package/corpus/templates/crm/actions/_crm-signal-utils.ts +0 -79
- package/corpus/templates/crm/actions/apply-crm-proposals.ts +0 -203
- package/corpus/templates/crm/actions/attach-call-evidence.ts +0 -170
- package/corpus/templates/crm/actions/configure-crm-connection.ts +0 -126
- package/corpus/templates/crm/actions/configure-native-crm.ts +0 -44
- package/corpus/templates/crm/actions/create-crm-record.ts +0 -148
- package/corpus/templates/crm/actions/create-crm-signal-tracker.ts +0 -58
- package/corpus/templates/crm/actions/delete-staged-dataset.ts +0 -14
- package/corpus/templates/crm/actions/get-crm-automation-recipe.ts +0 -36
- package/corpus/templates/crm/actions/get-crm-dashboard-panel.ts +0 -35
- package/corpus/templates/crm/actions/get-crm-dashboard.ts +0 -14
- package/corpus/templates/crm/actions/get-crm-overview.ts +0 -13
- package/corpus/templates/crm/actions/get-crm-pipeline-data.ts +0 -61
- package/corpus/templates/crm/actions/get-crm-record.ts +0 -75
- package/corpus/templates/crm/actions/install-crm-pipeline-dashboard.ts +0 -81
- package/corpus/templates/crm/actions/list-crm-dashboard-revisions.ts +0 -15
- package/corpus/templates/crm/actions/list-crm-dashboards.ts +0 -15
- package/corpus/templates/crm/actions/list-crm-proposals.ts +0 -31
- package/corpus/templates/crm/actions/list-crm-records.ts +0 -79
- package/corpus/templates/crm/actions/list-crm-saved-views.ts +0 -15
- package/corpus/templates/crm/actions/list-crm-signal-hits.ts +0 -43
- package/corpus/templates/crm/actions/list-crm-signal-trackers.ts +0 -32
- package/corpus/templates/crm/actions/list-crm-tasks.ts +0 -22
- package/corpus/templates/crm/actions/list-staged-datasets.ts +0 -14
- package/corpus/templates/crm/actions/list-workspace-connections.ts +0 -47
- package/corpus/templates/crm/actions/manage-crm-signal-tracker.ts +0 -87
- package/corpus/templates/crm/actions/manage-crm-task.ts +0 -132
- package/corpus/templates/crm/actions/navigate.ts +0 -63
- package/corpus/templates/crm/actions/provider-api-catalog.ts +0 -22
- package/corpus/templates/crm/actions/provider-api-docs.ts +0 -54
- package/corpus/templates/crm/actions/provider-api-request.ts +0 -92
- package/corpus/templates/crm/actions/query-staged-dataset.ts +0 -44
- package/corpus/templates/crm/actions/record-crm-call-insight.ts +0 -160
- package/corpus/templates/crm/actions/record-crm-smart-signal.ts +0 -150
- package/corpus/templates/crm/actions/restore-crm-dashboard-revision.ts +0 -23
- package/corpus/templates/crm/actions/review-crm-signal.ts +0 -31
- package/corpus/templates/crm/actions/run-crm-saved-view-program.ts +0 -103
- package/corpus/templates/crm/actions/run-crm-signal-trackers.ts +0 -275
- package/corpus/templates/crm/actions/run.ts +0 -7
- package/corpus/templates/crm/actions/save-crm-dashboard.ts +0 -51
- package/corpus/templates/crm/actions/save-crm-saved-view.ts +0 -119
- package/corpus/templates/crm/actions/sync-crm.ts +0 -146
- package/corpus/templates/crm/actions/update-crm-record.ts +0 -510
- package/corpus/templates/crm/actions/view-screen.ts +0 -218
- package/corpus/templates/crm/agent-native.app-skill.json +0 -58
- package/corpus/templates/crm/app/components/crm/CreateCrmRecordDialog.tsx +0 -158
- package/corpus/templates/crm/app/components/crm/CrmDashboardPanel.tsx +0 -78
- package/corpus/templates/crm/app/components/crm/CrmSignalsPanel.tsx +0 -226
- package/corpus/templates/crm/app/components/crm/IntelligenceSettings.tsx +0 -414
- package/corpus/templates/crm/app/components/crm/RecordActions.tsx +0 -510
- package/corpus/templates/crm/app/components/crm/RecordGrid.tsx +0 -134
- package/corpus/templates/crm/app/components/crm/RecordWorkspace.tsx +0 -362
- package/corpus/templates/crm/app/components/crm/SavedViewDataProgram.tsx +0 -93
- package/corpus/templates/crm/app/components/crm/Surface.tsx +0 -97
- package/corpus/templates/crm/app/components/crm/WorkOverview.tsx +0 -180
- package/corpus/templates/crm/app/components/layout/CrmLayout.tsx +0 -112
- package/corpus/templates/crm/app/components/layout/CrmSidebar.tsx +0 -84
- package/corpus/templates/crm/app/components/ui/alert-dialog.tsx +0 -1
- package/corpus/templates/crm/app/components/ui/badge.tsx +0 -1
- package/corpus/templates/crm/app/components/ui/button.tsx +0 -1
- package/corpus/templates/crm/app/components/ui/card.tsx +0 -1
- package/corpus/templates/crm/app/components/ui/dialog.tsx +0 -1
- package/corpus/templates/crm/app/components/ui/input.tsx +0 -1
- package/corpus/templates/crm/app/components/ui/label.tsx +0 -1
- package/corpus/templates/crm/app/components/ui/select.tsx +0 -1
- package/corpus/templates/crm/app/components/ui/sheet.tsx +0 -1
- package/corpus/templates/crm/app/components/ui/skeleton.tsx +0 -1
- package/corpus/templates/crm/app/components/ui/switch.tsx +0 -1
- package/corpus/templates/crm/app/components/ui/table.tsx +0 -1
- package/corpus/templates/crm/app/components/ui/tabs.tsx +0 -1
- package/corpus/templates/crm/app/components/ui/textarea.tsx +0 -1
- package/corpus/templates/crm/app/components/ui/toolkit-provider.tsx +0 -17
- package/corpus/templates/crm/app/design-system.ts +0 -3
- package/corpus/templates/crm/app/entry.client.tsx +0 -16
- package/corpus/templates/crm/app/entry.server.tsx +0 -10
- package/corpus/templates/crm/app/global.css +0 -167
- package/corpus/templates/crm/app/hooks/use-navigation-state.ts +0 -60
- package/corpus/templates/crm/app/i18n/en-US.ts +0 -89
- package/corpus/templates/crm/app/i18n/index.ts +0 -34
- package/corpus/templates/crm/app/lib/dashboard.ts +0 -13
- package/corpus/templates/crm/app/lib/navigation.ts +0 -54
- package/corpus/templates/crm/app/lib/tab-id.ts +0 -1
- package/corpus/templates/crm/app/lib/types.ts +0 -172
- package/corpus/templates/crm/app/lib/utils.ts +0 -1
- package/corpus/templates/crm/app/root.tsx +0 -91
- package/corpus/templates/crm/app/routes/_index.tsx +0 -26
- package/corpus/templates/crm/app/routes/accounts.tsx +0 -41
- package/corpus/templates/crm/app/routes/agent.tsx +0 -5
- package/corpus/templates/crm/app/routes/ask.tsx +0 -53
- package/corpus/templates/crm/app/routes/dashboard.tsx +0 -118
- package/corpus/templates/crm/app/routes/opportunities.tsx +0 -41
- package/corpus/templates/crm/app/routes/people.tsx +0 -41
- package/corpus/templates/crm/app/routes/proposals.tsx +0 -266
- package/corpus/templates/crm/app/routes/records.$recordId.tsx +0 -35
- package/corpus/templates/crm/app/routes/settings.tsx +0 -63
- package/corpus/templates/crm/app/routes/setup.tsx +0 -308
- package/corpus/templates/crm/app/routes/tasks.tsx +0 -252
- package/corpus/templates/crm/app/routes/views.tsx +0 -333
- package/corpus/templates/crm/app/routes.ts +0 -17
- package/corpus/templates/crm/app/vite-env.d.ts +0 -6
- package/corpus/templates/crm/changelog/2026-07-21-agent-native-crm.md +0 -6
- package/corpus/templates/crm/changelog/2026-07-21-clips-call-evidence-review-recipe.md +0 -6
- package/corpus/templates/crm/changelog/2026-07-21-crm-can-now-find-and-review-evidence-grounded-call-signals-w.md +0 -6
- package/corpus/templates/crm/changelog/2026-07-21-crm-can-now-manage-keyword-and-smart-call-signal-trackers-fr.md +0 -6
- package/corpus/templates/crm/changelog/2026-07-21-delegated-local-crm-automation.md +0 -6
- package/corpus/templates/crm/changelog/2026-07-21-native-sql.md +0 -6
- package/corpus/templates/crm/changelog/2026-07-21-pipeline-dashboard.md +0 -6
- package/corpus/templates/crm/changelog/2026-07-21-pipeline-dashboards-now-install-correctly-from-the-crm-actio.md +0 -6
- package/corpus/templates/crm/changelog/2026-07-21-salesforce-connection.md +0 -6
- package/corpus/templates/crm/changelog/2026-07-22-crm-field-validation-now-explains-which-fields-cannot-be-edi.md +0 -6
- package/corpus/templates/crm/changelog/2026-07-22-fixed-hubspot-contact-syncs-missing-records-updated-after-th.md +0 -6
- package/corpus/templates/crm/changelog/2026-07-22-fixed-pipeline-dashboard-panels-so-their-opportunity-data-lo.md +0 -6
- package/corpus/templates/crm/changelog/2026-07-22-full-page-chat-keeps-the-active-conversation-when-moving-to-.md +0 -6
- package/corpus/templates/crm/components.json +0 -20
- package/corpus/templates/crm/docs/architecture/crm-contract.md +0 -180
- package/corpus/templates/crm/learnings.defaults.md +0 -5
- package/corpus/templates/crm/package.json +0 -59
- package/corpus/templates/crm/public/favicon.svg +0 -1
- package/corpus/templates/crm/public/icon-180.svg +0 -1
- package/corpus/templates/crm/public/manifest.json +0 -11
- package/corpus/templates/crm/react-router.config.ts +0 -7
- package/corpus/templates/crm/server/crm/adapter.ts +0 -32
- package/corpus/templates/crm/server/crm/crm-field-firewall.ts +0 -64
- package/corpus/templates/crm/server/crm/crm-mirror.ts +0 -711
- package/corpus/templates/crm/server/crm/hubspot-adapter.ts +0 -1146
- package/corpus/templates/crm/server/crm/native-adapter.ts +0 -1715
- package/corpus/templates/crm/server/crm/read-through.ts +0 -207
- package/corpus/templates/crm/server/crm/salesforce-adapter.ts +0 -1255
- package/corpus/templates/crm/server/db/crm-store.ts +0 -1170
- package/corpus/templates/crm/server/db/index.ts +0 -169
- package/corpus/templates/crm/server/db/schema.ts +0 -441
- package/corpus/templates/crm/server/lib/intelligence/default-detectors.ts +0 -65
- package/corpus/templates/crm/server/lib/intelligence/evidence.ts +0 -105
- package/corpus/templates/crm/server/lib/intelligence/keyword-detector.ts +0 -100
- package/corpus/templates/crm/server/lib/intelligence/smart-detector.ts +0 -144
- package/corpus/templates/crm/server/lib/intelligence/summary.ts +0 -141
- package/corpus/templates/crm/server/lib/provider-api.ts +0 -64
- package/corpus/templates/crm/server/middleware/auth.ts +0 -4
- package/corpus/templates/crm/server/plugins/agent-chat.ts +0 -68
- package/corpus/templates/crm/server/plugins/auth.ts +0 -14
- package/corpus/templates/crm/server/plugins/core-routes.ts +0 -17
- package/corpus/templates/crm/server/plugins/db.ts +0 -454
- package/corpus/templates/crm/server/routes/[...page].get.ts +0 -5
- package/corpus/templates/crm/shared/crm-automation-recipes.ts +0 -132
- package/corpus/templates/crm/shared/crm-contract.ts +0 -254
- package/corpus/templates/crm/shared/crm-sales-config.ts +0 -63
- package/corpus/templates/crm/ssr-entry.ts +0 -11
- package/corpus/templates/crm/tsconfig.json +0 -24
- package/corpus/templates/crm/vite.config.ts +0 -15
- package/corpus/templates/crm/vitest.config.ts +0 -5
- package/dist/observability/hosted-model-experiment.d.ts +0 -39
- package/dist/observability/hosted-model-experiment.d.ts.map +0 -1
- package/dist/observability/hosted-model-experiment.js +0 -90
- package/dist/observability/hosted-model-experiment.js.map +0 -1
- package/src/observability/hosted-model-experiment.ts +0 -118
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
import { isSafeCrmEvidenceExcerpt } from "../../crm/crm-field-firewall.js";
|
|
2
|
-
|
|
3
|
-
export const MAX_EVIDENCE_EXCERPTS = 100;
|
|
4
|
-
export const MAX_EVIDENCE_QUOTE_LENGTH = 1_200;
|
|
5
|
-
|
|
6
|
-
export interface CallEvidenceExcerpt {
|
|
7
|
-
evidenceRef: string;
|
|
8
|
-
quote: string;
|
|
9
|
-
speaker?: string;
|
|
10
|
-
startSeconds: number;
|
|
11
|
-
endSeconds?: number;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
const FORBIDDEN_PAYLOAD_KEYS =
|
|
15
|
-
/(?:audio|base64|binary|blob|body|file|image|media|payload|recording|transcript|video)/i;
|
|
16
|
-
|
|
17
|
-
function isBoundedTime(value: unknown): value is number {
|
|
18
|
-
return (
|
|
19
|
-
typeof value === "number" &&
|
|
20
|
-
Number.isFinite(value) &&
|
|
21
|
-
value >= 0 &&
|
|
22
|
-
value <= 86_400
|
|
23
|
-
);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
function isOpaqueEvidenceRef(value: unknown): value is string {
|
|
27
|
-
return (
|
|
28
|
-
typeof value === "string" &&
|
|
29
|
-
value.trim().length > 0 &&
|
|
30
|
-
value.length <= 256 &&
|
|
31
|
-
!value.trimStart().startsWith("data:") &&
|
|
32
|
-
!/\b(?:base64|binary|blob|media)\b/i.test(value)
|
|
33
|
-
);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Narrows a Clips evidence artifact to the small, SQL-safe shape signals may use.
|
|
38
|
-
* Unknown payload-like keys fail closed so callers cannot accidentally pass a transcript.
|
|
39
|
-
*/
|
|
40
|
-
export function parseCallEvidenceExcerpt(
|
|
41
|
-
value: unknown,
|
|
42
|
-
): CallEvidenceExcerpt | null {
|
|
43
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
44
|
-
const raw = value as Record<string, unknown>;
|
|
45
|
-
if (Object.keys(raw).some((key) => FORBIDDEN_PAYLOAD_KEYS.test(key))) {
|
|
46
|
-
return null;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
const evidenceRef = raw.evidenceRef;
|
|
50
|
-
const quote = raw.quote;
|
|
51
|
-
const speaker = raw.speaker;
|
|
52
|
-
const startSeconds = raw.startSeconds;
|
|
53
|
-
const endSeconds = raw.endSeconds;
|
|
54
|
-
if (
|
|
55
|
-
!isOpaqueEvidenceRef(evidenceRef) ||
|
|
56
|
-
typeof quote !== "string" ||
|
|
57
|
-
quote.trim().length === 0 ||
|
|
58
|
-
quote.length > MAX_EVIDENCE_QUOTE_LENGTH ||
|
|
59
|
-
!isSafeCrmEvidenceExcerpt(quote) ||
|
|
60
|
-
!isBoundedTime(startSeconds) ||
|
|
61
|
-
(endSeconds !== undefined && !isBoundedTime(endSeconds)) ||
|
|
62
|
-
(typeof endSeconds === "number" && endSeconds < startSeconds) ||
|
|
63
|
-
(speaker !== undefined &&
|
|
64
|
-
(typeof speaker !== "string" ||
|
|
65
|
-
speaker.length > 240 ||
|
|
66
|
-
!isSafeCrmEvidenceExcerpt(speaker)))
|
|
67
|
-
) {
|
|
68
|
-
return null;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
return {
|
|
72
|
-
evidenceRef: evidenceRef.trim(),
|
|
73
|
-
quote: quote.trim(),
|
|
74
|
-
...(typeof speaker === "string" && speaker.trim()
|
|
75
|
-
? { speaker: speaker.trim() }
|
|
76
|
-
: {}),
|
|
77
|
-
startSeconds,
|
|
78
|
-
...(typeof endSeconds === "number" ? { endSeconds } : {}),
|
|
79
|
-
};
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
export function parseCallEvidenceExcerpts(
|
|
83
|
-
values: unknown,
|
|
84
|
-
maxItems = MAX_EVIDENCE_EXCERPTS,
|
|
85
|
-
): CallEvidenceExcerpt[] | null {
|
|
86
|
-
if (!Array.isArray(values) || values.length > maxItems || maxItems < 1) {
|
|
87
|
-
return null;
|
|
88
|
-
}
|
|
89
|
-
const excerpts: CallEvidenceExcerpt[] = [];
|
|
90
|
-
for (const value of values) {
|
|
91
|
-
const excerpt = parseCallEvidenceExcerpt(value);
|
|
92
|
-
if (!excerpt) return null;
|
|
93
|
-
excerpts.push(excerpt);
|
|
94
|
-
}
|
|
95
|
-
return excerpts;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
export function formatEvidenceTimestamp(seconds: number): string {
|
|
99
|
-
const rounded = Math.max(0, Math.round(seconds));
|
|
100
|
-
const minutes = Math.floor(rounded / 60);
|
|
101
|
-
const remainder = rounded % 60;
|
|
102
|
-
return `${minutes.toString().padStart(2, "0")}:${remainder
|
|
103
|
-
.toString()
|
|
104
|
-
.padStart(2, "0")}`;
|
|
105
|
-
}
|
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
type CallEvidenceExcerpt,
|
|
3
|
-
parseCallEvidenceExcerpts,
|
|
4
|
-
} from "./evidence.js";
|
|
5
|
-
|
|
6
|
-
export interface KeywordDetectorDefinition {
|
|
7
|
-
id: string;
|
|
8
|
-
name: string;
|
|
9
|
-
kind: "keyword";
|
|
10
|
-
keywords: string[];
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export interface CrmSignalCandidate {
|
|
14
|
-
detectorId: string;
|
|
15
|
-
detectorName: string;
|
|
16
|
-
kind: "keyword" | "smart";
|
|
17
|
-
evidenceRef: string;
|
|
18
|
-
quote: string;
|
|
19
|
-
speaker?: string;
|
|
20
|
-
startSeconds: number;
|
|
21
|
-
endSeconds?: number;
|
|
22
|
-
confidence: number;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
function escapeRegex(value: string): string {
|
|
26
|
-
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
function keywordPattern(keyword: string): RegExp | null {
|
|
30
|
-
const terms = keyword.trim().split(/\s+/).map(escapeRegex).filter(Boolean);
|
|
31
|
-
if (!terms.length) return null;
|
|
32
|
-
return new RegExp(`\\b${terms.join("\\s+")}\\b`, "gi");
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
function boundedQuote(text: string, start: number, end: number): string {
|
|
36
|
-
const radius = 120;
|
|
37
|
-
const quoteStart = Math.max(0, start - radius);
|
|
38
|
-
const quoteEnd = Math.min(text.length, end + radius);
|
|
39
|
-
return `${quoteStart > 0 ? "…" : ""}${text.slice(quoteStart, quoteEnd)}${
|
|
40
|
-
quoteEnd < text.length ? "…" : ""
|
|
41
|
-
}`.trim();
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/** Runs deterministic detector matching on already-bounded Clips evidence excerpts. */
|
|
45
|
-
export function runKeywordDetector(
|
|
46
|
-
detector: KeywordDetectorDefinition,
|
|
47
|
-
values: unknown,
|
|
48
|
-
): CrmSignalCandidate[] {
|
|
49
|
-
const excerpts = parseCallEvidenceExcerpts(values);
|
|
50
|
-
if (!excerpts || !detector.id.trim() || !detector.name.trim()) return [];
|
|
51
|
-
|
|
52
|
-
const patterns = detector.keywords
|
|
53
|
-
.filter((keyword) => typeof keyword === "string" && keyword.trim())
|
|
54
|
-
.slice(0, 40)
|
|
55
|
-
.map(keywordPattern)
|
|
56
|
-
.filter((pattern): pattern is RegExp => pattern !== null);
|
|
57
|
-
const hits: CrmSignalCandidate[] = [];
|
|
58
|
-
const seen = new Set<string>();
|
|
59
|
-
|
|
60
|
-
for (const excerpt of excerpts) {
|
|
61
|
-
for (const pattern of patterns) {
|
|
62
|
-
pattern.lastIndex = 0;
|
|
63
|
-
let match: RegExpExecArray | null;
|
|
64
|
-
while ((match = pattern.exec(excerpt.quote)) !== null) {
|
|
65
|
-
const quote = boundedQuote(
|
|
66
|
-
excerpt.quote,
|
|
67
|
-
match.index,
|
|
68
|
-
match.index + match[0].length,
|
|
69
|
-
);
|
|
70
|
-
const key = `${excerpt.evidenceRef}:${excerpt.startSeconds}:${quote}`;
|
|
71
|
-
if (!seen.has(key)) {
|
|
72
|
-
seen.add(key);
|
|
73
|
-
hits.push({
|
|
74
|
-
detectorId: detector.id,
|
|
75
|
-
detectorName: detector.name,
|
|
76
|
-
kind: "keyword",
|
|
77
|
-
evidenceRef: excerpt.evidenceRef,
|
|
78
|
-
quote,
|
|
79
|
-
...(excerpt.speaker ? { speaker: excerpt.speaker } : {}),
|
|
80
|
-
startSeconds: excerpt.startSeconds,
|
|
81
|
-
...(excerpt.endSeconds !== undefined
|
|
82
|
-
? { endSeconds: excerpt.endSeconds }
|
|
83
|
-
: {}),
|
|
84
|
-
confidence: 100,
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
|
-
if (match[0].length === 0) pattern.lastIndex += 1;
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
return hits;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
export function evidenceRefsForSignals(
|
|
95
|
-
signals: CrmSignalCandidate[],
|
|
96
|
-
): string[] {
|
|
97
|
-
return [...new Set(signals.map((signal) => signal.evidenceRef))];
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
export type { CallEvidenceExcerpt };
|
|
@@ -1,144 +0,0 @@
|
|
|
1
|
-
import { isSafeCrmEvidenceExcerpt } from "../../crm/crm-field-firewall.js";
|
|
2
|
-
import {
|
|
3
|
-
formatEvidenceTimestamp,
|
|
4
|
-
parseCallEvidenceExcerpts,
|
|
5
|
-
} from "./evidence.js";
|
|
6
|
-
import type { CrmSignalCandidate } from "./keyword-detector.js";
|
|
7
|
-
|
|
8
|
-
export interface SmartDetectorDefinition {
|
|
9
|
-
id: string;
|
|
10
|
-
name: string;
|
|
11
|
-
description?: string;
|
|
12
|
-
classifierPrompt: string;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
interface RawSmartSignal {
|
|
16
|
-
evidenceRef?: unknown;
|
|
17
|
-
quote?: unknown;
|
|
18
|
-
confidence?: unknown;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
function clampConfidence(value: unknown): number {
|
|
22
|
-
const parsed = typeof value === "number" ? value : Number(value);
|
|
23
|
-
if (!Number.isFinite(parsed)) return 80;
|
|
24
|
-
return Math.max(
|
|
25
|
-
0,
|
|
26
|
-
Math.min(100, Math.round(parsed <= 1 ? parsed * 100 : parsed)),
|
|
27
|
-
);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
function stripJsonFences(raw: string): string {
|
|
31
|
-
return raw
|
|
32
|
-
.trim()
|
|
33
|
-
.replace(/^```(?:json)?\s*/i, "")
|
|
34
|
-
.replace(/\s*```$/, "")
|
|
35
|
-
.trim();
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
function exactExcerptQuote(
|
|
39
|
-
quote: string,
|
|
40
|
-
evidenceQuote: string,
|
|
41
|
-
): string | null {
|
|
42
|
-
const normalized = quote.trim();
|
|
43
|
-
if (
|
|
44
|
-
!normalized ||
|
|
45
|
-
normalized.length > 1_200 ||
|
|
46
|
-
!isSafeCrmEvidenceExcerpt(normalized) ||
|
|
47
|
-
!evidenceQuote.includes(normalized)
|
|
48
|
-
) {
|
|
49
|
-
return null;
|
|
50
|
-
}
|
|
51
|
-
return normalized;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Builds delegated-agent context only. The CRM never invokes a model directly;
|
|
56
|
-
* callers send this bounded prompt through the agent chat delegation path.
|
|
57
|
-
*/
|
|
58
|
-
export function buildSmartDetectorPrompt(
|
|
59
|
-
detector: SmartDetectorDefinition,
|
|
60
|
-
values: unknown,
|
|
61
|
-
): string | null {
|
|
62
|
-
const excerpts = parseCallEvidenceExcerpts(values, 40);
|
|
63
|
-
if (
|
|
64
|
-
!excerpts ||
|
|
65
|
-
!detector.id.trim() ||
|
|
66
|
-
!detector.name.trim() ||
|
|
67
|
-
!detector.classifierPrompt.trim()
|
|
68
|
-
) {
|
|
69
|
-
return null;
|
|
70
|
-
}
|
|
71
|
-
const evidenceBlock = excerpts
|
|
72
|
-
.map(
|
|
73
|
-
(excerpt) =>
|
|
74
|
-
`[${excerpt.evidenceRef} ${formatEvidenceTimestamp(excerpt.startSeconds)}${
|
|
75
|
-
excerpt.speaker ? ` ${excerpt.speaker}` : ""
|
|
76
|
-
}] ${excerpt.quote}`,
|
|
77
|
-
)
|
|
78
|
-
.join("\n");
|
|
79
|
-
return `Classify bounded CRM call-evidence excerpts for detector "${detector.name}".\n\nCriterion:\n${detector.classifierPrompt.trim()}\n\nEvidence excerpts:\n${evidenceBlock}\n\nReturn only JSON: [{"evidenceRef":"exact evidence reference","quote":"exact verbatim substring from that evidence","confidence":0-100}]. Include only matches. Do not infer facts or create quotes. Never return a transcript.`;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
/** Validates delegated-agent output against the exact bounded evidence supplied. */
|
|
83
|
-
export function parseSmartDetectorOutput(
|
|
84
|
-
detector: SmartDetectorDefinition,
|
|
85
|
-
raw: string,
|
|
86
|
-
values: unknown,
|
|
87
|
-
): CrmSignalCandidate[] {
|
|
88
|
-
const excerpts = parseCallEvidenceExcerpts(values, 40);
|
|
89
|
-
if (!excerpts || typeof raw !== "string" || raw.length > 100_000) return [];
|
|
90
|
-
let parsed: unknown;
|
|
91
|
-
try {
|
|
92
|
-
parsed = JSON.parse(stripJsonFences(raw));
|
|
93
|
-
} catch {
|
|
94
|
-
return [];
|
|
95
|
-
}
|
|
96
|
-
if (!Array.isArray(parsed) || parsed.length > 100) return [];
|
|
97
|
-
const byRef = new Map<string, typeof excerpts>();
|
|
98
|
-
for (const excerpt of excerpts) {
|
|
99
|
-
const matches = byRef.get(excerpt.evidenceRef) ?? [];
|
|
100
|
-
matches.push(excerpt);
|
|
101
|
-
byRef.set(excerpt.evidenceRef, matches);
|
|
102
|
-
}
|
|
103
|
-
const seen = new Set<string>();
|
|
104
|
-
const results: CrmSignalCandidate[] = [];
|
|
105
|
-
for (const item of parsed as RawSmartSignal[]) {
|
|
106
|
-
if (
|
|
107
|
-
!item ||
|
|
108
|
-
typeof item !== "object" ||
|
|
109
|
-
typeof item.evidenceRef !== "string"
|
|
110
|
-
) {
|
|
111
|
-
continue;
|
|
112
|
-
}
|
|
113
|
-
const evidence =
|
|
114
|
-
typeof item.quote === "string"
|
|
115
|
-
? byRef
|
|
116
|
-
.get(item.evidenceRef)
|
|
117
|
-
?.find((candidate) =>
|
|
118
|
-
exactExcerptQuote(item.quote as string, candidate.quote),
|
|
119
|
-
)
|
|
120
|
-
: undefined;
|
|
121
|
-
const quote =
|
|
122
|
-
evidence && typeof item.quote === "string"
|
|
123
|
-
? exactExcerptQuote(item.quote, evidence.quote)
|
|
124
|
-
: null;
|
|
125
|
-
if (!evidence || !quote) continue;
|
|
126
|
-
const key = `${evidence.evidenceRef}:${quote}`;
|
|
127
|
-
if (seen.has(key)) continue;
|
|
128
|
-
seen.add(key);
|
|
129
|
-
results.push({
|
|
130
|
-
detectorId: detector.id,
|
|
131
|
-
detectorName: detector.name,
|
|
132
|
-
kind: "smart",
|
|
133
|
-
evidenceRef: evidence.evidenceRef,
|
|
134
|
-
quote,
|
|
135
|
-
...(evidence.speaker ? { speaker: evidence.speaker } : {}),
|
|
136
|
-
startSeconds: evidence.startSeconds,
|
|
137
|
-
...(evidence.endSeconds !== undefined
|
|
138
|
-
? { endSeconds: evidence.endSeconds }
|
|
139
|
-
: {}),
|
|
140
|
-
confidence: clampConfidence(item.confidence),
|
|
141
|
-
});
|
|
142
|
-
}
|
|
143
|
-
return results;
|
|
144
|
-
}
|
|
@@ -1,141 +0,0 @@
|
|
|
1
|
-
import { isSafeCrmEvidenceExcerpt } from "../../crm/crm-field-firewall.js";
|
|
2
|
-
import {
|
|
3
|
-
formatEvidenceTimestamp,
|
|
4
|
-
parseCallEvidenceExcerpts,
|
|
5
|
-
} from "./evidence.js";
|
|
6
|
-
|
|
7
|
-
export interface CallEvidenceSummary {
|
|
8
|
-
recap: string;
|
|
9
|
-
keyPoints: Array<{ text: string; evidenceRef: string; quoteSeconds: number }>;
|
|
10
|
-
nextSteps: Array<{
|
|
11
|
-
text: string;
|
|
12
|
-
evidenceRef: string;
|
|
13
|
-
quoteSeconds: number;
|
|
14
|
-
owner?: string;
|
|
15
|
-
}>;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
function stripJsonFences(raw: string): string {
|
|
19
|
-
return raw
|
|
20
|
-
.trim()
|
|
21
|
-
.replace(/^```(?:json)?\s*/i, "")
|
|
22
|
-
.replace(/\s*```$/, "")
|
|
23
|
-
.trim();
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
function boundedText(value: unknown, maxLength: number): string | null {
|
|
27
|
-
if (
|
|
28
|
-
typeof value !== "string" ||
|
|
29
|
-
!value.trim() ||
|
|
30
|
-
value.length > maxLength ||
|
|
31
|
-
!isSafeCrmEvidenceExcerpt(value)
|
|
32
|
-
) {
|
|
33
|
-
return null;
|
|
34
|
-
}
|
|
35
|
-
return value.trim();
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
function evidenceMoment(
|
|
39
|
-
item: Record<string, unknown>,
|
|
40
|
-
evidenceByRef: Map<
|
|
41
|
-
string,
|
|
42
|
-
Array<{ startSeconds: number; endSeconds?: number }>
|
|
43
|
-
>,
|
|
44
|
-
): { evidenceRef: string; quoteSeconds: number } | null {
|
|
45
|
-
const quoteSeconds = item.quoteSeconds;
|
|
46
|
-
if (
|
|
47
|
-
typeof item.evidenceRef !== "string" ||
|
|
48
|
-
typeof quoteSeconds !== "number"
|
|
49
|
-
) {
|
|
50
|
-
return null;
|
|
51
|
-
}
|
|
52
|
-
const evidence = evidenceByRef
|
|
53
|
-
.get(item.evidenceRef)
|
|
54
|
-
?.find(
|
|
55
|
-
(candidate) =>
|
|
56
|
-
quoteSeconds >= candidate.startSeconds &&
|
|
57
|
-
(candidate.endSeconds === undefined ||
|
|
58
|
-
quoteSeconds <= candidate.endSeconds),
|
|
59
|
-
);
|
|
60
|
-
if (
|
|
61
|
-
!evidence ||
|
|
62
|
-
!Number.isFinite(quoteSeconds) ||
|
|
63
|
-
quoteSeconds < evidence.startSeconds ||
|
|
64
|
-
(evidence.endSeconds !== undefined && quoteSeconds > evidence.endSeconds)
|
|
65
|
-
) {
|
|
66
|
-
return null;
|
|
67
|
-
}
|
|
68
|
-
return { evidenceRef: item.evidenceRef, quoteSeconds };
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
export function buildCallEvidenceSummaryPrompt(
|
|
72
|
-
callTitle: string,
|
|
73
|
-
values: unknown,
|
|
74
|
-
): string | null {
|
|
75
|
-
const excerpts = parseCallEvidenceExcerpts(values, 40);
|
|
76
|
-
if (!excerpts || !callTitle.trim() || callTitle.length > 240) return null;
|
|
77
|
-
const evidence = excerpts
|
|
78
|
-
.map(
|
|
79
|
-
(excerpt) =>
|
|
80
|
-
`[${excerpt.evidenceRef} ${formatEvidenceTimestamp(excerpt.startSeconds)}] ${excerpt.quote}`,
|
|
81
|
-
)
|
|
82
|
-
.join("\n");
|
|
83
|
-
return `Summarize only the bounded Clips call evidence below for "${callTitle.trim()}". Do not infer facts not present in evidence.\n\nEvidence:\n${evidence}\n\nReturn only JSON: {"recap":"<=120 words","keyPoints":[{"text":"<=240 chars","evidenceRef":"exact ref","quoteSeconds":0}],"nextSteps":[{"text":"<=240 chars","evidenceRef":"exact ref","quoteSeconds":0,"owner":"optional <=120 chars"}]}. Every key point and next step must cite one supplied evidence reference and timestamp. Never return a transcript.`;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
export function parseCallEvidenceSummary(
|
|
87
|
-
raw: string,
|
|
88
|
-
values: unknown,
|
|
89
|
-
): CallEvidenceSummary | null {
|
|
90
|
-
const excerpts = parseCallEvidenceExcerpts(values, 40);
|
|
91
|
-
if (!excerpts || typeof raw !== "string" || raw.length > 100_000) return null;
|
|
92
|
-
let parsed: unknown;
|
|
93
|
-
try {
|
|
94
|
-
parsed = JSON.parse(stripJsonFences(raw));
|
|
95
|
-
} catch {
|
|
96
|
-
return null;
|
|
97
|
-
}
|
|
98
|
-
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
|
|
99
|
-
return null;
|
|
100
|
-
const result = parsed as Record<string, unknown>;
|
|
101
|
-
const recap = boundedText(result.recap, 1_200);
|
|
102
|
-
if (!recap) return null;
|
|
103
|
-
const evidenceByRef = new Map<
|
|
104
|
-
string,
|
|
105
|
-
Array<{ startSeconds: number; endSeconds?: number }>
|
|
106
|
-
>();
|
|
107
|
-
for (const excerpt of excerpts) {
|
|
108
|
-
const moments = evidenceByRef.get(excerpt.evidenceRef) ?? [];
|
|
109
|
-
moments.push({
|
|
110
|
-
startSeconds: excerpt.startSeconds,
|
|
111
|
-
...(excerpt.endSeconds !== undefined
|
|
112
|
-
? { endSeconds: excerpt.endSeconds }
|
|
113
|
-
: {}),
|
|
114
|
-
});
|
|
115
|
-
evidenceByRef.set(excerpt.evidenceRef, moments);
|
|
116
|
-
}
|
|
117
|
-
const parseItems = (rawItems: unknown, includeOwner: boolean) =>
|
|
118
|
-
Array.isArray(rawItems)
|
|
119
|
-
? rawItems.slice(0, 20).flatMap((item) => {
|
|
120
|
-
if (!item || typeof item !== "object" || Array.isArray(item))
|
|
121
|
-
return [];
|
|
122
|
-
const record = item as Record<string, unknown>;
|
|
123
|
-
const text = boundedText(record.text, 240);
|
|
124
|
-
const moment = evidenceMoment(record, evidenceByRef);
|
|
125
|
-
if (!text || !moment) return [];
|
|
126
|
-
const owner = includeOwner ? boundedText(record.owner, 120) : null;
|
|
127
|
-
return [
|
|
128
|
-
{
|
|
129
|
-
text,
|
|
130
|
-
...moment,
|
|
131
|
-
...(owner ? { owner } : {}),
|
|
132
|
-
},
|
|
133
|
-
];
|
|
134
|
-
})
|
|
135
|
-
: [];
|
|
136
|
-
return {
|
|
137
|
-
recap,
|
|
138
|
-
keyPoints: parseItems(result.keyPoints, false),
|
|
139
|
-
nextSteps: parseItems(result.nextSteps, true),
|
|
140
|
-
};
|
|
141
|
-
}
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
createProviderApiRuntime,
|
|
3
|
-
type ProviderApiCredentialResolver,
|
|
4
|
-
type ProviderApiId,
|
|
5
|
-
} from "@agent-native/core/provider-api";
|
|
6
|
-
import { getCredentialContext } from "@agent-native/core/server";
|
|
7
|
-
import { resolveWorkspaceConnectionCredentialForApp } from "@agent-native/core/workspace-connections";
|
|
8
|
-
|
|
9
|
-
export const CRM_APP_ID = "crm";
|
|
10
|
-
export const CRM_PROVIDER_API_IDS = ["hubspot", "salesforce"] as [
|
|
11
|
-
ProviderApiId,
|
|
12
|
-
ProviderApiId,
|
|
13
|
-
];
|
|
14
|
-
|
|
15
|
-
const resolveCrmProviderCredential: ProviderApiCredentialResolver = async ({
|
|
16
|
-
provider,
|
|
17
|
-
key,
|
|
18
|
-
ctx,
|
|
19
|
-
workspaceProvider,
|
|
20
|
-
connectionId,
|
|
21
|
-
}) => {
|
|
22
|
-
const resolvedProvider = workspaceProvider ?? provider;
|
|
23
|
-
const credential = await resolveWorkspaceConnectionCredentialForApp({
|
|
24
|
-
appId: CRM_APP_ID,
|
|
25
|
-
provider: resolvedProvider,
|
|
26
|
-
key,
|
|
27
|
-
...(connectionId ? { connectionId } : {}),
|
|
28
|
-
userEmail: ctx.userEmail,
|
|
29
|
-
orgId: ctx.orgId ?? null,
|
|
30
|
-
});
|
|
31
|
-
if (!credential.available || !credential.value || !credential.provenance) {
|
|
32
|
-
return null;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
return {
|
|
36
|
-
key: credential.provenance.resolvedKey,
|
|
37
|
-
value: credential.value,
|
|
38
|
-
source: "workspace_connection",
|
|
39
|
-
provider: resolvedProvider,
|
|
40
|
-
connectionId: credential.provenance.connectionId,
|
|
41
|
-
connectionLabel: credential.provenance.connectionLabel,
|
|
42
|
-
scope: credential.provenance.secretScope,
|
|
43
|
-
};
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
const runtime = createProviderApiRuntime({
|
|
47
|
-
appId: CRM_APP_ID,
|
|
48
|
-
providerIds: CRM_PROVIDER_API_IDS,
|
|
49
|
-
localCredentialSource: "crm_workspace_connection",
|
|
50
|
-
getCredentialContext: () => {
|
|
51
|
-
const context = getCredentialContext();
|
|
52
|
-
if (!context) {
|
|
53
|
-
throw new Error(
|
|
54
|
-
"CRM provider API requests require an authenticated request context.",
|
|
55
|
-
);
|
|
56
|
-
}
|
|
57
|
-
return context;
|
|
58
|
-
},
|
|
59
|
-
resolveCredential: resolveCrmProviderCredential,
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
export function getCrmProviderApiRuntime() {
|
|
63
|
-
return runtime;
|
|
64
|
-
}
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import { getOrgContext } from "@agent-native/core/org";
|
|
2
|
-
import {
|
|
3
|
-
createAgentChatPlugin,
|
|
4
|
-
loadActionsFromStaticRegistry,
|
|
5
|
-
} from "@agent-native/core/server";
|
|
6
|
-
|
|
7
|
-
import actionsRegistry from "../../.generated/actions-registry.js";
|
|
8
|
-
|
|
9
|
-
const INITIAL_TOOL_NAMES = [
|
|
10
|
-
"configure-native-crm",
|
|
11
|
-
"configure-crm-connection",
|
|
12
|
-
"list-workspace-connections",
|
|
13
|
-
"get-crm-overview",
|
|
14
|
-
"list-crm-records",
|
|
15
|
-
"get-crm-record",
|
|
16
|
-
"sync-crm",
|
|
17
|
-
"list-crm-saved-views",
|
|
18
|
-
"save-crm-saved-view",
|
|
19
|
-
"install-crm-pipeline-dashboard",
|
|
20
|
-
"list-crm-dashboards",
|
|
21
|
-
"get-crm-dashboard",
|
|
22
|
-
"save-crm-dashboard",
|
|
23
|
-
"list-crm-tasks",
|
|
24
|
-
"manage-crm-task",
|
|
25
|
-
"create-crm-record",
|
|
26
|
-
"update-crm-record",
|
|
27
|
-
"list-crm-proposals",
|
|
28
|
-
"apply-crm-proposals",
|
|
29
|
-
"attach-call-evidence",
|
|
30
|
-
"get-crm-automation-recipe",
|
|
31
|
-
"create-crm-signal-tracker",
|
|
32
|
-
"manage-crm-signal-tracker",
|
|
33
|
-
"list-crm-signal-trackers",
|
|
34
|
-
"run-crm-signal-trackers",
|
|
35
|
-
"list-crm-signal-hits",
|
|
36
|
-
"record-crm-smart-signal",
|
|
37
|
-
"record-crm-call-insight",
|
|
38
|
-
"review-crm-signal",
|
|
39
|
-
"navigate",
|
|
40
|
-
"view-screen",
|
|
41
|
-
"provider-api-catalog",
|
|
42
|
-
"provider-api-docs",
|
|
43
|
-
"provider-api-request",
|
|
44
|
-
"list-staged-datasets",
|
|
45
|
-
"query-staged-dataset",
|
|
46
|
-
"delete-staged-dataset",
|
|
47
|
-
];
|
|
48
|
-
|
|
49
|
-
export default createAgentChatPlugin({
|
|
50
|
-
appId: "crm",
|
|
51
|
-
actions: loadActionsFromStaticRegistry(actionsRegistry),
|
|
52
|
-
initialToolNames: INITIAL_TOOL_NAMES,
|
|
53
|
-
resolveOrgId: async (event) => (await getOrgContext(event)).orgId,
|
|
54
|
-
codeExecution: { production: "sandboxed" },
|
|
55
|
-
systemPrompt: `You are the CRM for a workspace using Native SQL, HubSpot, Salesforce, or a combination of those modes.
|
|
56
|
-
|
|
57
|
-
Use CRM actions as the source of truth. Call view-screen when a request refers to the visible record, selection, or saved view. Use list-crm-records and get-crm-record for normal CRM work; sync-crm refreshes only its declared scoped cohort.
|
|
58
|
-
|
|
59
|
-
Native SQL is a first-class local-authoritative CRM and requires no external connection. Use configure-native-crm to initialize it and create-crm-record for accounts, people, and opportunities. Native writes use the local target, remain access-checked and audited, and never invent an upstream revision or sync result.
|
|
60
|
-
|
|
61
|
-
HubSpot and Salesforce are the initial connected providers. Workspace connections own credentials: never request, store, log, or expose provider tokens. Use sync-crm only for declared connected-provider cohorts; Native SQL has no upstream sync.
|
|
62
|
-
|
|
63
|
-
The local CRM mirror is deliberately thin. Respect each field's storage policy: mirrored values may be read locally, remote-only values must be fetched ephemerally, and redacted values must not be fetched or exposed. Never persist raw provider payloads, media, screenshots, audio, video, or transcripts in CRM SQL. Call evidence is only a URL/id with a bounded quote and metadata. CRM signals are first-class, reviewable records grounded to those evidence references. Run keyword detectors locally; smart detectors and summaries must be delegated through agent chat, then recorded only with record-crm-smart-signal or record-crm-call-insight after exact evidence validation.
|
|
64
|
-
|
|
65
|
-
Provider changes are access-checked, revision-aware, audited proposals. This release is proposal-first for upstream writes: review the proposal, direct the user to complete it in the source CRM, and never claim the upstream change succeeded. Ownership, amount, stage, bulk scope, deletion, and external side effects always require an exact preview and approval.
|
|
66
|
-
|
|
67
|
-
First-class CRM actions are convenience workflows, not a provider API ceiling. For an exact HubSpot or Salesforce read endpoint, filter, pagination mode, or object schema that they cannot express, use provider-api-catalog and provider-api-docs, then the read-only provider-api-request. Before broad provider work, declare a cohort, selected fields, and a bounded page/row budget. Stage only that result and use query-staged-dataset or a data program; report scope, filters, page/row counts, truncation, and gaps.`,
|
|
68
|
-
});
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { createAuthPlugin } from "@agent-native/core/server";
|
|
2
|
-
|
|
3
|
-
export default createAuthPlugin({
|
|
4
|
-
marketing: {
|
|
5
|
-
appName: "CRM",
|
|
6
|
-
tagline:
|
|
7
|
-
"A complete Native SQL CRM or a connected companion grounded in its source system.",
|
|
8
|
-
features: [
|
|
9
|
-
"Run accounts, people, opportunities, tasks, and cadence on Native SQL",
|
|
10
|
-
"Connect scoped HubSpot or Salesforce records without copying credentials",
|
|
11
|
-
"Work with the same safe actions from the UI or your CRM agent",
|
|
12
|
-
],
|
|
13
|
-
},
|
|
14
|
-
});
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { createCoreRoutesPlugin } from "@agent-native/core/server";
|
|
2
|
-
|
|
3
|
-
const VIEW_PATHS: Record<string, string> = {
|
|
4
|
-
overview: "/",
|
|
5
|
-
records: "/records",
|
|
6
|
-
record: "/records",
|
|
7
|
-
tasks: "/tasks",
|
|
8
|
-
proposals: "/proposals",
|
|
9
|
-
settings: "/settings",
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
export default createCoreRoutesPlugin({
|
|
13
|
-
resolveOpenPath: ({ view, params }) => {
|
|
14
|
-
if (params.recordId) return `/records/${params.recordId}`;
|
|
15
|
-
return view ? (VIEW_PATHS[view] ?? null) : null;
|
|
16
|
-
},
|
|
17
|
-
});
|