@agent-native/core 0.145.5 → 0.145.7
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 +1 -1
- package/corpus/templates/analytics/.agents/skills/actions/SKILL.md +18 -0
- package/corpus/templates/analytics/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
- package/corpus/templates/analytics/.agents/skills/dashboard-management/SKILL.md +17 -1
- package/corpus/templates/analytics/.agents/skills/delegate-to-agent/SKILL.md +45 -47
- package/corpus/templates/analytics/.agents/skills/frontend-design/SKILL.md +1 -0
- package/corpus/templates/analytics/.agents/skills/gong/SKILL.md +22 -3
- package/corpus/templates/analytics/.agents/skills/turn-into-app/SKILL.md +76 -23
- package/corpus/templates/analytics/.agents/skills/turn-into-app/agents/openai.yaml +2 -2
- package/corpus/templates/analytics/.agents/skills/turn-into-app/references/fresh-project.md +64 -0
- package/corpus/templates/analytics/AGENTS.md +2 -1
- package/corpus/templates/analytics/actions/account-deep-dive.ts +83 -47
- package/corpus/templates/analytics/actions/create-dashboard-folder.ts +27 -0
- package/corpus/templates/analytics/actions/gong-calls.ts +3 -3
- package/corpus/templates/analytics/actions/list-dashboard-folders.ts +26 -0
- package/corpus/templates/analytics/actions/list-sql-dashboards.ts +1 -0
- package/corpus/templates/analytics/actions/set-dashboard-folder.ts +26 -0
- package/corpus/templates/analytics/app/components/ProviderCorpusJobNotifier.tsx +18 -3
- package/corpus/templates/analytics/app/components/layout/CommandPalette.tsx +6 -4
- package/corpus/templates/analytics/app/components/layout/Header.tsx +1 -0
- package/corpus/templates/analytics/app/components/layout/NewDashboardDialog.tsx +12 -2
- package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +35 -20
- package/corpus/templates/analytics/app/global.css +17 -0
- package/corpus/templates/analytics/app/hooks/use-dashboard-revisions.ts +29 -15
- package/corpus/templates/analytics/app/hooks/use-dashboard-views.ts +15 -3
- package/corpus/templates/analytics/app/i18n-data.ts +296 -0
- package/corpus/templates/analytics/app/lib/prefetch-keys.ts +23 -2
- package/corpus/templates/analytics/app/pages/DashboardOverview.tsx +642 -0
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +66 -31
- package/corpus/templates/analytics/app/root.tsx +4 -0
- package/corpus/templates/analytics/app/routes/dashboards._index.tsx +5 -1
- package/corpus/templates/analytics/changelog/2026-08-07-added-a-dashboards-overview-with-personal-and-shared-folders.md +6 -0
- package/corpus/templates/analytics/changelog/2026-08-07-analytics-no-longer-stalls-under-bursts-of-event-ingest-key-.md +6 -0
- package/corpus/templates/analytics/changelog/2026-08-07-analytics-tracking-and-chat-startup-no-longer-emit-avoidable.md +6 -0
- package/corpus/templates/analytics/changelog/2026-08-07-dashboard-panels-now-load-custom-api-data-programs-reliably.md +6 -0
- package/corpus/templates/analytics/changelog/2026-08-07-gong-searches-conserve-api-quota-and-report-incomplete-coverage.md +6 -0
- package/corpus/templates/analytics/changelog/2026-08-07-searchable-dashboards-make-personal-and-shared-folders-easie.md +6 -0
- package/corpus/templates/analytics/netlify.toml +3 -0
- package/corpus/templates/analytics/scripts/emit-netlify-dashboard-report-cron.ts +112 -0
- package/corpus/templates/analytics/server/db/index.ts +12 -0
- package/corpus/templates/analytics/server/db/schema.ts +14 -0
- package/corpus/templates/analytics/server/jobs/analytics-rollup-backfill.ts +4 -0
- package/corpus/templates/analytics/server/lib/agent-chat-plan-mode.ts +1 -0
- package/corpus/templates/analytics/server/lib/analytics-query-catalog.ts +85 -15
- package/corpus/templates/analytics/server/lib/dashboard-folders-store.ts +168 -0
- package/corpus/templates/analytics/server/lib/dashboard-panel-query.ts +9 -4
- package/corpus/templates/analytics/server/lib/dashboards-store.ts +116 -1
- package/corpus/templates/analytics/server/lib/first-party-analytics-rollups.ts +4 -8
- package/corpus/templates/analytics/server/lib/first-party-analytics.ts +65 -10
- package/corpus/templates/analytics/server/lib/gong.ts +139 -78
- package/corpus/templates/analytics/server/lib/session-replay.ts +5 -5
- package/corpus/templates/analytics/server/plugins/db.ts +55 -15
- package/corpus/templates/analytics/server/plugins/session-replay-retention-jobs.ts +6 -2
- package/corpus/templates/analytics/server/routes/api/session-replay/retention.post.ts +65 -0
- package/corpus/templates/assets/.agents/skills/actions/SKILL.md +18 -0
- package/corpus/templates/assets/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
- package/corpus/templates/assets/.agents/skills/delegate-to-agent/SKILL.md +45 -47
- package/corpus/templates/assets/.agents/skills/frontend-design/SKILL.md +1 -0
- package/corpus/templates/assets/.agents/skills/turn-into-app/SKILL.md +76 -23
- package/corpus/templates/assets/.agents/skills/turn-into-app/agents/openai.yaml +2 -2
- package/corpus/templates/assets/.agents/skills/turn-into-app/references/fresh-project.md +64 -0
- package/corpus/templates/brain/.agents/skills/actions/SKILL.md +18 -0
- package/corpus/templates/brain/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
- package/corpus/templates/brain/.agents/skills/delegate-to-agent/SKILL.md +45 -47
- package/corpus/templates/brain/.agents/skills/frontend-design/SKILL.md +1 -0
- package/corpus/templates/brain/.agents/skills/turn-into-app/SKILL.md +76 -23
- package/corpus/templates/brain/.agents/skills/turn-into-app/agents/openai.yaml +2 -2
- package/corpus/templates/brain/.agents/skills/turn-into-app/references/fresh-project.md +64 -0
- package/corpus/templates/calendar/.agents/skills/actions/SKILL.md +18 -0
- package/corpus/templates/calendar/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
- package/corpus/templates/calendar/.agents/skills/delegate-to-agent/SKILL.md +45 -47
- package/corpus/templates/calendar/.agents/skills/frontend-design/SKILL.md +1 -0
- package/corpus/templates/calendar/.agents/skills/turn-into-app/SKILL.md +76 -23
- package/corpus/templates/calendar/.agents/skills/turn-into-app/agents/openai.yaml +2 -2
- package/corpus/templates/calendar/.agents/skills/turn-into-app/references/fresh-project.md +64 -0
- package/corpus/templates/chat/.agents/skills/actions/SKILL.md +18 -0
- package/corpus/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
- package/corpus/templates/chat/.agents/skills/delegate-to-agent/SKILL.md +45 -47
- package/corpus/templates/chat/.agents/skills/frontend-design/SKILL.md +1 -0
- package/corpus/templates/chat/.agents/skills/turn-into-app/SKILL.md +76 -23
- package/corpus/templates/chat/.agents/skills/turn-into-app/agents/openai.yaml +2 -2
- package/corpus/templates/chat/.agents/skills/turn-into-app/references/fresh-project.md +64 -0
- package/corpus/templates/chat/.env.example +3 -0
- package/corpus/templates/chat/AGENTS.md +4 -0
- package/corpus/templates/clips/.agents/skills/actions/SKILL.md +18 -0
- package/corpus/templates/clips/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
- package/corpus/templates/clips/.agents/skills/delegate-to-agent/SKILL.md +45 -47
- package/corpus/templates/clips/.agents/skills/frontend-design/SKILL.md +1 -0
- package/corpus/templates/clips/.agents/skills/turn-into-app/SKILL.md +76 -23
- package/corpus/templates/clips/.agents/skills/turn-into-app/agents/openai.yaml +2 -2
- package/corpus/templates/clips/.agents/skills/turn-into-app/references/fresh-project.md +64 -0
- package/corpus/templates/clips/actions/lib/audio-only-transcription.ts +4 -0
- package/corpus/templates/clips/actions/request-transcript.ts +52 -3
- package/corpus/templates/clips/app/components/recorder/recorder-engine.ts +3 -10
- package/corpus/templates/clips/app/routes/r.$recordingId.tsx +1 -0
- package/corpus/templates/clips/changelog/2026-08-07-screen-recordings-now-capture-tab-and-system-audio-even-when.md +6 -0
- package/corpus/templates/clips/changelog/2026-08-07-transcription-now-retries-transient-cloud-failures-automatic.md +6 -0
- package/corpus/templates/clips/server/db/schema.ts +7 -0
- package/corpus/templates/clips/server/plugins/db.ts +8 -0
- package/corpus/templates/clips/shared/recording-capture.ts +38 -0
- package/corpus/templates/clips/shared/transcript-failure.ts +89 -0
- package/corpus/templates/content/.agents/skills/actions/SKILL.md +18 -0
- package/corpus/templates/content/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
- package/corpus/templates/content/.agents/skills/delegate-to-agent/SKILL.md +45 -47
- package/corpus/templates/content/.agents/skills/frontend-design/SKILL.md +1 -0
- package/corpus/templates/content/.agents/skills/turn-into-app/SKILL.md +76 -23
- package/corpus/templates/content/.agents/skills/turn-into-app/agents/openai.yaml +2 -2
- package/corpus/templates/content/.agents/skills/turn-into-app/references/fresh-project.md +64 -0
- package/corpus/templates/content/.env.example +9 -3
- package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +1 -0
- package/corpus/templates/content/changelog/2026-08-07-collapsed-sidebar-utility-buttons-stay-anchored-at-the-botto.md +6 -0
- package/corpus/templates/crm/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
- package/corpus/templates/crm/.agents/skills/turn-into-app/SKILL.md +76 -23
- package/corpus/templates/crm/.agents/skills/turn-into-app/agents/openai.yaml +2 -2
- package/corpus/templates/crm/.agents/skills/turn-into-app/references/fresh-project.md +64 -0
- package/corpus/templates/design/.agents/skills/actions/SKILL.md +18 -0
- package/corpus/templates/design/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
- package/corpus/templates/design/.agents/skills/delegate-to-agent/SKILL.md +45 -47
- package/corpus/templates/design/.agents/skills/frontend-design/SKILL.md +1 -0
- package/corpus/templates/design/.agents/skills/turn-into-app/SKILL.md +76 -23
- package/corpus/templates/design/.agents/skills/turn-into-app/agents/openai.yaml +2 -2
- package/corpus/templates/design/.agents/skills/turn-into-app/references/fresh-project.md +64 -0
- package/corpus/templates/dispatch/.agents/skills/actions/SKILL.md +18 -0
- package/corpus/templates/dispatch/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
- package/corpus/templates/dispatch/.agents/skills/delegate-to-agent/SKILL.md +45 -47
- package/corpus/templates/dispatch/.agents/skills/frontend-design/SKILL.md +1 -0
- package/corpus/templates/dispatch/.agents/skills/turn-into-app/SKILL.md +76 -23
- package/corpus/templates/dispatch/.agents/skills/turn-into-app/agents/openai.yaml +2 -2
- package/corpus/templates/dispatch/.agents/skills/turn-into-app/references/fresh-project.md +64 -0
- package/corpus/templates/factory/.agents/skills/actions/SKILL.md +18 -0
- package/corpus/templates/factory/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
- package/corpus/templates/factory/.agents/skills/delegate-to-agent/SKILL.md +45 -47
- package/corpus/templates/factory/.agents/skills/frontend-design/SKILL.md +1 -0
- package/corpus/templates/factory/.agents/skills/turn-into-app/SKILL.md +76 -23
- package/corpus/templates/factory/.agents/skills/turn-into-app/agents/openai.yaml +2 -2
- package/corpus/templates/factory/.agents/skills/turn-into-app/references/fresh-project.md +64 -0
- package/corpus/templates/factory/actions/babysit-agent-native-pull-request.ts +279 -0
- package/corpus/templates/factory/actions/get-factory-automation-health.ts +23 -4
- package/corpus/templates/factory/app/components/factory/FactoryCanvas.tsx +1 -1
- package/corpus/templates/factory/app/routes/factory.tsx +21 -3
- package/corpus/templates/factory/changelog/2026-08-07-factory-can-keep-builder-bot-pull-requests-moving-by-request.md +6 -0
- package/corpus/templates/factory/server/lib/require-factory-automation.ts +1 -0
- package/corpus/templates/factory/server/plugins/agent-chat.ts +4 -1
- package/corpus/templates/factory/server/plugins/factory-scheduler-job.ts +81 -12
- package/corpus/templates/factory/server/triage/github-client.ts +31 -0
- package/corpus/templates/factory/server/triage/pr-babysit.ts +75 -1
- package/corpus/templates/forms/.agents/skills/actions/SKILL.md +18 -0
- package/corpus/templates/forms/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
- package/corpus/templates/forms/.agents/skills/delegate-to-agent/SKILL.md +45 -47
- package/corpus/templates/forms/.agents/skills/frontend-design/SKILL.md +1 -0
- package/corpus/templates/forms/.agents/skills/turn-into-app/SKILL.md +76 -23
- package/corpus/templates/forms/.agents/skills/turn-into-app/agents/openai.yaml +2 -2
- package/corpus/templates/forms/.agents/skills/turn-into-app/references/fresh-project.md +64 -0
- package/corpus/templates/macros/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
- package/corpus/templates/macros/.agents/skills/frontend-design/SKILL.md +1 -0
- package/corpus/templates/macros/.agents/skills/turn-into-app/SKILL.md +76 -23
- package/corpus/templates/macros/.agents/skills/turn-into-app/agents/openai.yaml +2 -2
- package/corpus/templates/macros/.agents/skills/turn-into-app/references/fresh-project.md +64 -0
- package/corpus/templates/mail/.agents/skills/actions/SKILL.md +18 -0
- package/corpus/templates/mail/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
- package/corpus/templates/mail/.agents/skills/delegate-to-agent/SKILL.md +45 -47
- package/corpus/templates/mail/.agents/skills/frontend-design/SKILL.md +1 -0
- package/corpus/templates/mail/.agents/skills/turn-into-app/SKILL.md +76 -23
- package/corpus/templates/mail/.agents/skills/turn-into-app/agents/openai.yaml +2 -2
- package/corpus/templates/mail/.agents/skills/turn-into-app/references/fresh-project.md +64 -0
- package/corpus/templates/plan/.agents/skills/actions/SKILL.md +18 -0
- package/corpus/templates/plan/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
- package/corpus/templates/plan/.agents/skills/delegate-to-agent/SKILL.md +45 -47
- package/corpus/templates/plan/.agents/skills/frontend-design/SKILL.md +1 -0
- package/corpus/templates/plan/.agents/skills/turn-into-app/SKILL.md +76 -23
- package/corpus/templates/plan/.agents/skills/turn-into-app/agents/openai.yaml +2 -2
- package/corpus/templates/plan/.agents/skills/turn-into-app/references/fresh-project.md +64 -0
- package/corpus/templates/plan/app/pages/PlansPage.tsx +2 -1
- package/corpus/templates/plan/changelog/2026-08-07-inline-help-icons-now-stay-visually-balanced-with-nearby-tex.md +6 -0
- package/corpus/templates/slides/.agents/skills/actions/SKILL.md +18 -0
- package/corpus/templates/slides/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
- package/corpus/templates/slides/.agents/skills/delegate-to-agent/SKILL.md +45 -47
- package/corpus/templates/slides/.agents/skills/frontend-design/SKILL.md +1 -0
- package/corpus/templates/slides/.agents/skills/turn-into-app/SKILL.md +76 -23
- package/corpus/templates/slides/.agents/skills/turn-into-app/agents/openai.yaml +2 -2
- package/corpus/templates/slides/.agents/skills/turn-into-app/references/fresh-project.md +64 -0
- package/corpus/templates/slides/.env.example +5 -0
- package/corpus/templates/slides/changelog/2026-08-07-fixed-generated-slides-briefly-disappearing-while-they-are-b.md +6 -0
- package/corpus/templates/slides/server/plugins/collab.ts +20 -8
- package/corpus/templates/tasks/.agents/skills/actions/SKILL.md +18 -0
- package/corpus/templates/tasks/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
- package/corpus/templates/tasks/.agents/skills/delegate-to-agent/SKILL.md +45 -47
- package/corpus/templates/tasks/.agents/skills/frontend-design/SKILL.md +1 -0
- package/corpus/templates/tasks/.agents/skills/turn-into-app/SKILL.md +76 -23
- package/corpus/templates/tasks/.agents/skills/turn-into-app/agents/openai.yaml +2 -2
- package/corpus/templates/tasks/.agents/skills/turn-into-app/references/fresh-project.md +64 -0
- package/corpus/templates/tasks/.env.example +3 -0
- package/dist/agent/production-agent.js +24 -3
- package/dist/client/AgentPanel.d.ts +6 -0
- package/dist/client/AgentPanel.js +176 -30
- package/dist/client/AssistantChat.d.ts +2 -0
- package/dist/client/AssistantChat.js +4 -1
- package/dist/client/ConnectBuilderCard.js +6 -11
- package/dist/client/MultiTabAssistantChat.js +1 -1
- package/dist/client/RuntimeConfigNotice.d.ts +1 -0
- package/dist/client/RuntimeConfigNotice.js +94 -0
- package/dist/client/agent-chat/index.d.ts +1 -1
- package/dist/client/agent-chat/index.js +1 -1
- package/dist/client/agent-chat-adapter.js +85 -4
- package/dist/client/agent-page/AgentTabsPage.js +1 -1
- package/dist/client/agent-sidebar-state.d.ts +6 -0
- package/dist/client/agent-sidebar-state.js +25 -0
- package/dist/client/app-providers.js +2 -1
- package/dist/client/assistant-ui-recovery.js +1 -1
- package/dist/client/chat/index.d.ts +1 -1
- package/dist/client/chat/index.js +1 -1
- package/dist/client/chat/markdown-renderer.d.ts +2 -1
- package/dist/client/chat/markdown-renderer.js +48 -2
- package/dist/client/chat/message-components.d.ts +6 -0
- package/dist/client/chat/message-components.js +182 -53
- package/dist/client/chat/tool-call-display.d.ts +16 -4
- package/dist/client/chat/tool-call-display.js +225 -18
- package/dist/client/extensions/ExtensionsSidebarSection.js +1 -1
- package/dist/client/frame-protocol.d.ts +4 -0
- package/dist/client/i18n.js +9 -0
- package/dist/client/integrations/IntegrationsPanel.js +2 -5
- package/dist/client/onboarding/FirstRunOnboarding.js +2 -3
- package/dist/client/org/TeamPage.js +49 -6
- package/dist/client/org/hooks.d.ts +7 -2
- package/dist/client/org/hooks.js +11 -4
- package/dist/client/resources/McpConnectionSuggestion.js +2 -3
- package/dist/client/resources/McpIntegrationDialog.js +2 -16
- package/dist/client/resources/McpIntegrationLogo.d.ts +11 -0
- package/dist/client/resources/McpIntegrationLogo.js +14 -0
- package/dist/client/resources/ResourceTree.js +1 -1
- package/dist/client/resources/mcp-integration-logos.d.ts +1 -0
- package/dist/client/resources/mcp-integration-logos.js +47 -18
- package/dist/client/settings/useBuilderStatus.js +6 -0
- package/dist/client/ui/index.d.ts +1 -0
- package/dist/client/ui/index.js +1 -0
- package/dist/client/use-db-sync.js +4 -0
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/config.d.ts +26 -3
- package/dist/config.js +106 -14
- package/dist/db/ddl-guard.d.ts +15 -2
- package/dist/db/ddl-guard.js +53 -5
- package/dist/file-upload/actions/upload-image.d.ts +1 -1
- package/dist/jobs/scheduler.js +7 -0
- package/dist/localization/default-messages.d.ts +17 -0
- package/dist/localization/default-messages.js +17 -0
- package/dist/mcp/oauth-client-metadata.js +5 -1
- package/dist/mcp/oauth-route.d.ts +5 -4
- package/dist/mcp/oauth-route.js +25 -9
- package/dist/mcp/screen-memory-stdio.d.ts +7 -7
- package/dist/mcp/server.d.ts +1 -1
- package/dist/mcp/server.js +9 -10
- package/dist/notifications/routes.d.ts +2 -2
- package/dist/observability/routes.d.ts +3 -3
- package/dist/org/handlers.d.ts +1 -0
- package/dist/org/handlers.js +17 -2
- package/dist/provider-api/actions/custom-provider-registration.d.ts +5 -5
- package/dist/provider-api/actions/provider-api.d.ts +7 -7
- package/dist/provider-api/corpus-jobs.d.ts +12 -2
- package/dist/provider-api/corpus-jobs.js +31 -1
- package/dist/provider-api/index.d.ts +2 -0
- package/dist/provider-api/index.js +7 -1
- package/dist/secrets/routes.d.ts +3 -3
- package/dist/server/agent-chat/recurring-jobs-runtime.d.ts +1 -1
- package/dist/server/agent-chat/recurring-jobs-runtime.js +14 -2
- package/dist/server/agent-chat/script-entries.js +12 -1
- package/dist/server/agent-chat-plugin.js +2 -2
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/auth.d.ts +1 -0
- package/dist/server/auth.js +85 -1
- package/dist/server/better-auth-instance.d.ts +9 -0
- package/dist/server/better-auth-instance.js +25 -11
- package/dist/server/core-routes-plugin.d.ts +7 -0
- package/dist/server/core-routes-plugin.js +51 -5
- package/dist/server/create-server.js +23 -2
- package/dist/server/db-pressure.d.ts +38 -0
- package/dist/server/db-pressure.js +147 -0
- package/dist/server/index.d.ts +1 -0
- package/dist/server/index.js +1 -0
- package/dist/server/legacy-auth-migration.d.ts +10 -0
- package/dist/server/legacy-auth-migration.js +37 -0
- package/dist/server/onboarding-html.js +206 -2
- package/dist/server/poll.d.ts +26 -0
- package/dist/server/poll.js +108 -13
- package/dist/server/ssr-handler.js +4 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/dist/shared/index.d.ts +1 -0
- package/dist/shared/index.js +1 -0
- package/dist/shared/runtime-config.d.ts +44 -0
- package/dist/shared/runtime-config.js +284 -0
- package/dist/styles/agent-native.css +48 -1
- package/dist/templates/chat/.agents/skills/actions/SKILL.md +18 -0
- package/dist/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
- package/dist/templates/chat/.agents/skills/delegate-to-agent/SKILL.md +45 -47
- package/dist/templates/chat/.agents/skills/frontend-design/SKILL.md +1 -0
- package/dist/templates/chat/.agents/skills/turn-into-app/SKILL.md +76 -23
- package/dist/templates/chat/.agents/skills/turn-into-app/agents/openai.yaml +2 -2
- package/dist/templates/chat/.agents/skills/turn-into-app/references/fresh-project.md +64 -0
- package/dist/templates/chat/.env.example +3 -0
- package/dist/templates/chat/AGENTS.md +4 -0
- package/dist/templates/default/.agents/skills/actions/SKILL.md +18 -0
- package/dist/templates/default/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
- package/dist/templates/default/.agents/skills/delegate-to-agent/SKILL.md +45 -47
- package/dist/templates/default/.agents/skills/frontend-design/SKILL.md +1 -0
- package/dist/templates/default/.agents/skills/turn-into-app/SKILL.md +76 -23
- package/dist/templates/default/.agents/skills/turn-into-app/agents/openai.yaml +2 -2
- package/dist/templates/default/.agents/skills/turn-into-app/references/fresh-project.md +64 -0
- package/dist/templates/default/AGENTS.md +6 -1
- package/dist/templates/default/app/i18n/ar-SA.ts +6 -0
- package/dist/templates/default/app/i18n/de-DE.ts +6 -0
- package/dist/templates/default/app/i18n/en-US.ts +6 -0
- package/dist/templates/default/app/i18n/es-ES.ts +6 -0
- package/dist/templates/default/app/i18n/fr-FR.ts +6 -0
- package/dist/templates/default/app/i18n/hi-IN.ts +6 -0
- package/dist/templates/default/app/i18n/ja-JP.ts +6 -0
- package/dist/templates/default/app/i18n/ko-KR.ts +6 -0
- package/dist/templates/default/app/i18n/pt-BR.ts +6 -0
- package/dist/templates/default/app/i18n/zh-CN.ts +6 -0
- package/dist/templates/default/app/i18n/zh-TW.ts +6 -0
- package/dist/templates/headless/.agents/skills/actions/SKILL.md +18 -0
- package/dist/templates/headless/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
- package/dist/templates/headless/.agents/skills/turn-into-app/SKILL.md +76 -23
- package/dist/templates/headless/.agents/skills/turn-into-app/agents/openai.yaml +2 -2
- package/dist/templates/headless/.agents/skills/turn-into-app/references/fresh-project.md +64 -0
- package/dist/templates/workspace-core/.agents/skills/actions/SKILL.md +18 -0
- package/dist/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
- package/dist/templates/workspace-core/.agents/skills/delegate-to-agent/SKILL.md +45 -47
- package/dist/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +1 -0
- package/dist/templates/workspace-core/.agents/skills/turn-into-app/SKILL.md +76 -23
- package/dist/templates/workspace-core/.agents/skills/turn-into-app/agents/openai.yaml +2 -2
- package/dist/templates/workspace-core/.agents/skills/turn-into-app/references/fresh-project.md +64 -0
- package/dist/templates/workspace-core/.agents/skills/workspace-conventions/SKILL.md +4 -0
- package/dist/templates/workspace-core/.agents/skills/writing-agent-instructions/SKILL.md +8 -0
- package/dist/templates/workspace-core/AGENTS.md +7 -2
- package/dist/templates/workspace-root/AGENTS.md +5 -0
- package/dist/vite/client.d.ts +3 -3
- package/dist/vite/client.js +47 -1
- package/dist/vite/index.d.ts +1 -1
- package/docs/content/agent-native-config.mdx +240 -139
- package/docs/content/authentication.mdx +17 -0
- package/docs/content/deployment.mdx +19 -14
- package/docs/content/drop-in-agent.mdx +19 -2
- package/docs/content/environment-variables.mdx +63 -38
- package/docs/content/getting-started-actions.mdx +15 -6
- package/docs/content/getting-started-database.mdx +14 -10
- package/docs/content/getting-started-pages.mdx +32 -35
- package/docs/content/getting-started.mdx +7 -6
- package/package.json +1 -1
- package/src/templates/chat/.agents/skills/actions/SKILL.md +18 -0
- package/src/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
- package/src/templates/chat/.agents/skills/delegate-to-agent/SKILL.md +45 -47
- package/src/templates/chat/.agents/skills/frontend-design/SKILL.md +1 -0
- package/src/templates/chat/.agents/skills/turn-into-app/SKILL.md +76 -23
- package/src/templates/chat/.agents/skills/turn-into-app/agents/openai.yaml +2 -2
- package/src/templates/chat/.agents/skills/turn-into-app/references/fresh-project.md +64 -0
- package/src/templates/chat/.env.example +3 -0
- package/src/templates/chat/AGENTS.md +4 -0
- package/src/templates/default/.agents/skills/actions/SKILL.md +18 -0
- package/src/templates/default/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
- package/src/templates/default/.agents/skills/delegate-to-agent/SKILL.md +45 -47
- package/src/templates/default/.agents/skills/frontend-design/SKILL.md +1 -0
- package/src/templates/default/.agents/skills/turn-into-app/SKILL.md +76 -23
- package/src/templates/default/.agents/skills/turn-into-app/agents/openai.yaml +2 -2
- package/src/templates/default/.agents/skills/turn-into-app/references/fresh-project.md +64 -0
- package/src/templates/default/AGENTS.md +6 -1
- package/src/templates/default/app/i18n/ar-SA.ts +6 -0
- package/src/templates/default/app/i18n/de-DE.ts +6 -0
- package/src/templates/default/app/i18n/en-US.ts +6 -0
- package/src/templates/default/app/i18n/es-ES.ts +6 -0
- package/src/templates/default/app/i18n/fr-FR.ts +6 -0
- package/src/templates/default/app/i18n/hi-IN.ts +6 -0
- package/src/templates/default/app/i18n/ja-JP.ts +6 -0
- package/src/templates/default/app/i18n/ko-KR.ts +6 -0
- package/src/templates/default/app/i18n/pt-BR.ts +6 -0
- package/src/templates/default/app/i18n/zh-CN.ts +6 -0
- package/src/templates/default/app/i18n/zh-TW.ts +6 -0
- package/src/templates/headless/.agents/skills/actions/SKILL.md +18 -0
- package/src/templates/headless/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
- package/src/templates/headless/.agents/skills/turn-into-app/SKILL.md +76 -23
- package/src/templates/headless/.agents/skills/turn-into-app/agents/openai.yaml +2 -2
- package/src/templates/headless/.agents/skills/turn-into-app/references/fresh-project.md +64 -0
- package/src/templates/workspace-core/.agents/skills/actions/SKILL.md +18 -0
- package/src/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
- package/src/templates/workspace-core/.agents/skills/delegate-to-agent/SKILL.md +45 -47
- package/src/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +1 -0
- package/src/templates/workspace-core/.agents/skills/turn-into-app/SKILL.md +76 -23
- package/src/templates/workspace-core/.agents/skills/turn-into-app/agents/openai.yaml +2 -2
- package/src/templates/workspace-core/.agents/skills/turn-into-app/references/fresh-project.md +64 -0
- package/src/templates/workspace-core/.agents/skills/workspace-conventions/SKILL.md +4 -0
- package/src/templates/workspace-core/.agents/skills/writing-agent-instructions/SKILL.md +8 -0
- package/src/templates/workspace-core/AGENTS.md +7 -2
- package/src/templates/workspace-root/AGENTS.md +5 -0
- package/corpus/templates/dispatch/app/routes/admin.apps.$appId.tsx +0 -1
- package/corpus/templates/dispatch/app/routes/admin.apps.tsx +0 -1
|
@@ -1,19 +1,14 @@
|
|
|
1
1
|
// Gong sales call intelligence API helper
|
|
2
2
|
// Fetches calls, transcripts, and users
|
|
3
3
|
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
requireRequestCredentialContext,
|
|
7
|
-
scopedCredentialCacheKey,
|
|
8
|
-
} from "./credentials-context";
|
|
4
|
+
import { scopedCredentialCacheKey } from "./credentials-context";
|
|
9
5
|
import {
|
|
10
6
|
DEFAULT_GONG_CALL_LIMIT,
|
|
11
7
|
limitGongCalls,
|
|
12
8
|
normalizeGongCallLimit,
|
|
13
9
|
} from "./gong-limits";
|
|
14
|
-
import {
|
|
10
|
+
import { executeProviderApiRequest } from "./provider-api";
|
|
15
11
|
|
|
16
|
-
const DEFAULT_API_BASE = "https://api.gong.io/v2";
|
|
17
12
|
const MAX_GONG_SEARCH_PAGES = 50;
|
|
18
13
|
const MAX_GONG_CALL_LIST_PAGES = 50;
|
|
19
14
|
const MAX_GONG_EXHAUSTIVE_RECORDS = 500;
|
|
@@ -24,38 +19,101 @@ const cache = new Map<string, { data: unknown; ts: number }>();
|
|
|
24
19
|
const CACHE_TTL_MS = 10 * 60 * 1000;
|
|
25
20
|
const MAX_CACHE = 120;
|
|
26
21
|
|
|
27
|
-
async function getAuthHeader(): Promise<string> {
|
|
28
|
-
const ctx = requireRequestCredentialContext("GONG_ACCESS_KEY");
|
|
29
|
-
const credentials = await resolveAnalyticsGongCredentials({ ctx });
|
|
30
|
-
if (!credentials)
|
|
31
|
-
throw new Error("GONG_ACCESS_KEY and GONG_ACCESS_SECRET not configured");
|
|
32
|
-
return `Basic ${Buffer.from(
|
|
33
|
-
`${credentials.accessKey}:${credentials.accessSecret}`,
|
|
34
|
-
).toString("base64")}`;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
async function getApiBase(): Promise<string> {
|
|
38
|
-
const ctx = requireRequestCredentialContext("GONG_ACCESS_KEY");
|
|
39
|
-
const configured = await resolveCredential("GONG_API_BASE", ctx);
|
|
40
|
-
return (configured || DEFAULT_API_BASE).replace(/\/+$/, "");
|
|
41
|
-
}
|
|
42
|
-
|
|
43
22
|
export interface GongRequestOptions {
|
|
44
23
|
signal?: AbortSignal;
|
|
45
24
|
deadlineAt?: number;
|
|
46
25
|
}
|
|
47
26
|
|
|
48
|
-
function
|
|
49
|
-
|
|
27
|
+
function requestTimeoutMs(options?: GongRequestOptions): number {
|
|
28
|
+
return options?.deadlineAt
|
|
50
29
|
? Math.max(
|
|
51
30
|
1,
|
|
52
31
|
Math.min(GONG_API_REQUEST_TIMEOUT_MS, options.deadlineAt - Date.now()),
|
|
53
32
|
)
|
|
54
33
|
: GONG_API_REQUEST_TIMEOUT_MS;
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
interface GongProviderResponse {
|
|
37
|
+
response: {
|
|
38
|
+
ok: boolean;
|
|
39
|
+
status: number;
|
|
40
|
+
headers?: Record<string, string>;
|
|
41
|
+
json?: unknown;
|
|
42
|
+
text?: string;
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function splitGongPath(path: string): {
|
|
47
|
+
path: string;
|
|
48
|
+
query?: Record<string, string>;
|
|
49
|
+
} {
|
|
50
|
+
const separator = path.indexOf("?");
|
|
51
|
+
if (separator < 0) return { path };
|
|
52
|
+
const query = Object.fromEntries(
|
|
53
|
+
new URLSearchParams(path.slice(separator + 1)).entries(),
|
|
54
|
+
);
|
|
55
|
+
return {
|
|
56
|
+
path: path.slice(0, separator),
|
|
57
|
+
...(Object.keys(query).length > 0 ? { query } : {}),
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function responseHeader(
|
|
62
|
+
headers: Record<string, string> | undefined,
|
|
63
|
+
name: string,
|
|
64
|
+
): string | undefined {
|
|
65
|
+
const lowerName = name.toLowerCase();
|
|
66
|
+
return Object.entries(headers ?? {}).find(
|
|
67
|
+
([key]) => key.toLowerCase() === lowerName,
|
|
68
|
+
)?.[1];
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function responseDetail(response: GongProviderResponse["response"]): string {
|
|
72
|
+
if (typeof response.text === "string" && response.text.trim()) {
|
|
73
|
+
return response.text.replace(/\s+/g, " ").trim().slice(0, 2_000);
|
|
74
|
+
}
|
|
75
|
+
if (response.json !== undefined) {
|
|
76
|
+
return JSON.stringify(response.json).slice(0, 2_000);
|
|
77
|
+
}
|
|
78
|
+
return "";
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function gongApiError(response: GongProviderResponse["response"]): Error {
|
|
82
|
+
const requestId =
|
|
83
|
+
responseHeader(response.headers, "x-request-id") ??
|
|
84
|
+
responseHeader(response.headers, "request-id");
|
|
85
|
+
const retryAfter = responseHeader(response.headers, "retry-after");
|
|
86
|
+
const metadata = [
|
|
87
|
+
requestId ? `requestId ${requestId}` : "",
|
|
88
|
+
response.status === 429 && retryAfter ? `retry-after ${retryAfter}` : "",
|
|
89
|
+
]
|
|
90
|
+
.filter(Boolean)
|
|
91
|
+
.join(", ");
|
|
92
|
+
const detail = responseDetail(response);
|
|
93
|
+
return new Error(
|
|
94
|
+
`Gong API error ${response.status}${metadata ? ` (${metadata})` : ""}${detail ? `: ${detail}` : ""}`,
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
async function executeGongRequest<T>(options: {
|
|
99
|
+
method: "GET" | "POST";
|
|
100
|
+
path: string;
|
|
101
|
+
body?: unknown;
|
|
102
|
+
requestOptions?: GongRequestOptions;
|
|
103
|
+
}): Promise<T> {
|
|
104
|
+
const request = splitGongPath(options.path);
|
|
105
|
+
const result = (await executeProviderApiRequest({
|
|
106
|
+
provider: "gong",
|
|
107
|
+
method: options.method,
|
|
108
|
+
path: request.path,
|
|
109
|
+
...(request.query ? { query: request.query } : {}),
|
|
110
|
+
...(options.body !== undefined ? { body: options.body } : {}),
|
|
111
|
+
timeoutMs: requestTimeoutMs(options.requestOptions),
|
|
112
|
+
signal: options.requestOptions?.signal,
|
|
113
|
+
})) as GongProviderResponse;
|
|
114
|
+
|
|
115
|
+
if (!result.response.ok) throw gongApiError(result.response);
|
|
116
|
+
return result.response.json as T;
|
|
59
117
|
}
|
|
60
118
|
|
|
61
119
|
async function apiGet<T>(
|
|
@@ -69,21 +127,12 @@ async function apiGet<T>(
|
|
|
69
127
|
return cached.data as T;
|
|
70
128
|
}
|
|
71
129
|
|
|
72
|
-
const
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
},
|
|
77
|
-
signal: requestSignal(options),
|
|
130
|
+
const data = await executeGongRequest<T>({
|
|
131
|
+
method: "GET",
|
|
132
|
+
path,
|
|
133
|
+
requestOptions: options,
|
|
78
134
|
});
|
|
79
135
|
|
|
80
|
-
if (!res.ok) {
|
|
81
|
-
const text = await res.text();
|
|
82
|
-
throw new Error(`Gong API error ${res.status}: ${text}`);
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
const data = await res.json();
|
|
86
|
-
|
|
87
136
|
if (cache.size >= MAX_CACHE) {
|
|
88
137
|
const oldest = cache.keys().next().value;
|
|
89
138
|
if (oldest) cache.delete(oldest);
|
|
@@ -108,23 +157,13 @@ async function apiPost<T>(
|
|
|
108
157
|
return cached.data as T;
|
|
109
158
|
}
|
|
110
159
|
|
|
111
|
-
const
|
|
160
|
+
const data = await executeGongRequest<T>({
|
|
112
161
|
method: "POST",
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
},
|
|
117
|
-
body: JSON.stringify(body),
|
|
118
|
-
signal: requestSignal(options),
|
|
162
|
+
path,
|
|
163
|
+
body,
|
|
164
|
+
requestOptions: options,
|
|
119
165
|
});
|
|
120
166
|
|
|
121
|
-
if (!res.ok) {
|
|
122
|
-
const text = await res.text();
|
|
123
|
-
throw new Error(`Gong API error ${res.status}: ${text}`);
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
const data = await res.json();
|
|
127
|
-
|
|
128
167
|
if (cache.size >= MAX_CACHE) {
|
|
129
168
|
const oldest = cache.keys().next().value;
|
|
130
169
|
if (oldest) cache.delete(oldest);
|
|
@@ -298,29 +337,9 @@ export async function getCall(
|
|
|
298
337
|
return data.calls?.[0] ?? null;
|
|
299
338
|
}
|
|
300
339
|
|
|
301
|
-
|
|
302
|
-
callId: string,
|
|
303
|
-
options?: GongRequestOptions,
|
|
304
|
-
): Promise<GongCallDetail | null> {
|
|
305
|
-
const body = {
|
|
306
|
-
filter: { callIds: [callId] },
|
|
307
|
-
contentSelector: {
|
|
308
|
-
exposedFields: {
|
|
309
|
-
parties: true,
|
|
310
|
-
content: { brief: true, keyPoints: true, outline: true },
|
|
311
|
-
},
|
|
312
|
-
},
|
|
313
|
-
};
|
|
314
|
-
const data = await apiPost<{ calls?: any[] }>(
|
|
315
|
-
"/calls/extensive",
|
|
316
|
-
body,
|
|
317
|
-
`detail:${callId}`,
|
|
318
|
-
options,
|
|
319
|
-
);
|
|
320
|
-
const call = data.calls?.[0];
|
|
321
|
-
if (!call) return null;
|
|
340
|
+
function normalizeCallDetail(call: any, fallbackId: string): GongCallDetail {
|
|
322
341
|
return {
|
|
323
|
-
id: call.metaData?.id ??
|
|
342
|
+
id: call.metaData?.id ?? fallbackId,
|
|
324
343
|
title: call.metaData?.title || "Untitled",
|
|
325
344
|
url: call.metaData?.url || "",
|
|
326
345
|
started: call.metaData?.started || "",
|
|
@@ -340,6 +359,48 @@ export async function getCallDetail(
|
|
|
340
359
|
};
|
|
341
360
|
}
|
|
342
361
|
|
|
362
|
+
export async function getCallDetails(
|
|
363
|
+
callIds: string[],
|
|
364
|
+
options?: GongRequestOptions,
|
|
365
|
+
): Promise<GongCallDetail[]> {
|
|
366
|
+
const ids = Array.from(
|
|
367
|
+
new Set(
|
|
368
|
+
callIds
|
|
369
|
+
.map((id) => (typeof id === "string" ? id.trim() : ""))
|
|
370
|
+
.filter(Boolean),
|
|
371
|
+
),
|
|
372
|
+
);
|
|
373
|
+
if (!ids.length) return [];
|
|
374
|
+
|
|
375
|
+
const body = {
|
|
376
|
+
filter: { callIds: ids },
|
|
377
|
+
contentSelector: {
|
|
378
|
+
exposedFields: {
|
|
379
|
+
parties: true,
|
|
380
|
+
content: { brief: true, keyPoints: true, outline: true },
|
|
381
|
+
},
|
|
382
|
+
},
|
|
383
|
+
};
|
|
384
|
+
const data = await apiPost<{ calls?: any[] }>(
|
|
385
|
+
"/calls/extensive",
|
|
386
|
+
body,
|
|
387
|
+
`details:${ids.join(",")}`,
|
|
388
|
+
options,
|
|
389
|
+
);
|
|
390
|
+
return (data.calls ?? []).map((call, index) =>
|
|
391
|
+
normalizeCallDetail(call, ids[index] ?? ""),
|
|
392
|
+
);
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
export async function getCallDetail(
|
|
396
|
+
callId: string,
|
|
397
|
+
options?: GongRequestOptions,
|
|
398
|
+
): Promise<GongCallDetail | null> {
|
|
399
|
+
const details = await getCallDetails([callId], options);
|
|
400
|
+
const detail = details[0];
|
|
401
|
+
return detail === undefined ? null : detail;
|
|
402
|
+
}
|
|
403
|
+
|
|
343
404
|
export async function getCallTranscripts(
|
|
344
405
|
callIds: string[],
|
|
345
406
|
options?: GongRequestOptions,
|
|
@@ -39,7 +39,10 @@ import {
|
|
|
39
39
|
SESSION_REPLAY_NETWORK_EVENT_TAG,
|
|
40
40
|
} from "../../shared/session-replay-diagnostics.js";
|
|
41
41
|
import { getDb, schema } from "../db/index.js";
|
|
42
|
-
import {
|
|
42
|
+
import {
|
|
43
|
+
resolveAnalyticsEventDimensions,
|
|
44
|
+
touchPublicKeyLastUsedAt,
|
|
45
|
+
} from "./first-party-analytics.js";
|
|
43
46
|
|
|
44
47
|
export type ReplayRange = "24h" | "7d" | "30d" | "90d" | "all";
|
|
45
48
|
|
|
@@ -1654,10 +1657,7 @@ export async function recordSessionReplayChunks(
|
|
|
1654
1657
|
})
|
|
1655
1658
|
.where(eq(schema.sessionRecordings.id, recording.id));
|
|
1656
1659
|
|
|
1657
|
-
await
|
|
1658
|
-
.update(schema.analyticsPublicKeys)
|
|
1659
|
-
.set({ lastUsedAt: ingestedAt })
|
|
1660
|
-
.where(eq(schema.analyticsPublicKeys.id, key.id));
|
|
1660
|
+
await touchPublicKeyLastUsedAt(key.id, ingestedAt);
|
|
1661
1661
|
|
|
1662
1662
|
recordChange({
|
|
1663
1663
|
source: "session-recordings",
|
|
@@ -1439,6 +1439,58 @@ const runAnalyticsMigrations = runMigrations(
|
|
|
1439
1439
|
)`,
|
|
1440
1440
|
},
|
|
1441
1441
|
},
|
|
1442
|
+
{
|
|
1443
|
+
version: 138,
|
|
1444
|
+
name: "analytics-dashboard-folders",
|
|
1445
|
+
sql: {
|
|
1446
|
+
postgres: `CREATE TABLE IF NOT EXISTS dashboard_folders (
|
|
1447
|
+
id TEXT PRIMARY KEY,
|
|
1448
|
+
name TEXT NOT NULL,
|
|
1449
|
+
scope TEXT NOT NULL,
|
|
1450
|
+
created_at TEXT NOT NULL DEFAULT (now()::text),
|
|
1451
|
+
updated_at TEXT NOT NULL DEFAULT (now()::text),
|
|
1452
|
+
owner_email TEXT NOT NULL DEFAULT 'local@localhost',
|
|
1453
|
+
org_id TEXT,
|
|
1454
|
+
visibility TEXT NOT NULL DEFAULT 'private'
|
|
1455
|
+
);
|
|
1456
|
+
CREATE TABLE IF NOT EXISTS dashboard_folder_shares (
|
|
1457
|
+
id TEXT PRIMARY KEY,
|
|
1458
|
+
resource_id TEXT NOT NULL,
|
|
1459
|
+
principal_type TEXT NOT NULL,
|
|
1460
|
+
principal_id TEXT NOT NULL,
|
|
1461
|
+
role TEXT NOT NULL DEFAULT 'viewer',
|
|
1462
|
+
created_by TEXT NOT NULL,
|
|
1463
|
+
created_at TEXT NOT NULL DEFAULT (now()::text)
|
|
1464
|
+
);
|
|
1465
|
+
ALTER TABLE dashboards ADD COLUMN IF NOT EXISTS folder_id TEXT;
|
|
1466
|
+
CREATE INDEX IF NOT EXISTS dashboard_folders_owner_org_idx ON dashboard_folders (owner_email, org_id);
|
|
1467
|
+
CREATE INDEX IF NOT EXISTS dashboard_folder_shares_resource_idx ON dashboard_folder_shares (resource_id);
|
|
1468
|
+
CREATE INDEX IF NOT EXISTS dashboards_folder_idx ON dashboards (folder_id)`,
|
|
1469
|
+
sqlite: `CREATE TABLE IF NOT EXISTS dashboard_folders (
|
|
1470
|
+
id TEXT PRIMARY KEY,
|
|
1471
|
+
name TEXT NOT NULL,
|
|
1472
|
+
scope TEXT NOT NULL,
|
|
1473
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
1474
|
+
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
1475
|
+
owner_email TEXT NOT NULL DEFAULT 'local@localhost',
|
|
1476
|
+
org_id TEXT,
|
|
1477
|
+
visibility TEXT NOT NULL DEFAULT 'private'
|
|
1478
|
+
);
|
|
1479
|
+
CREATE TABLE IF NOT EXISTS dashboard_folder_shares (
|
|
1480
|
+
id TEXT PRIMARY KEY,
|
|
1481
|
+
resource_id TEXT NOT NULL,
|
|
1482
|
+
principal_type TEXT NOT NULL,
|
|
1483
|
+
principal_id TEXT NOT NULL,
|
|
1484
|
+
role TEXT NOT NULL DEFAULT 'viewer',
|
|
1485
|
+
created_by TEXT NOT NULL,
|
|
1486
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
1487
|
+
);
|
|
1488
|
+
ALTER TABLE dashboards ADD COLUMN IF NOT EXISTS folder_id TEXT;
|
|
1489
|
+
CREATE INDEX IF NOT EXISTS dashboard_folders_owner_org_idx ON dashboard_folders (owner_email, org_id);
|
|
1490
|
+
CREATE INDEX IF NOT EXISTS dashboard_folder_shares_resource_idx ON dashboard_folder_shares (resource_id);
|
|
1491
|
+
CREATE INDEX IF NOT EXISTS dashboards_folder_idx ON dashboards (folder_id)`,
|
|
1492
|
+
},
|
|
1493
|
+
},
|
|
1442
1494
|
],
|
|
1443
1495
|
{ table: "analytics_migrations" },
|
|
1444
1496
|
);
|
|
@@ -1476,29 +1528,17 @@ export default async (nitroApp: any): Promise<void> => {
|
|
|
1476
1528
|
Boolean(process.env.NETLIFY_FUNCTION_NAME) ||
|
|
1477
1529
|
Boolean(process.env.AWS_LAMBDA_FUNCTION_NAME) ||
|
|
1478
1530
|
Boolean(process.env.LAMBDA_TASK_ROOT);
|
|
1479
|
-
if (
|
|
1480
|
-
isNetlifyServerlessRuntime &&
|
|
1481
|
-
process.env.ANALYTICS_SKIP_BOOT_MIGRATIONS === "1"
|
|
1482
|
-
) {
|
|
1531
|
+
if (isNetlifyServerlessRuntime && !isScheduledRollupRuntime) {
|
|
1483
1532
|
console.info(
|
|
1484
|
-
"[db] Skipping Analytics migrations in production serverless runtime
|
|
1533
|
+
"[db] Skipping Analytics migrations in production serverless runtime",
|
|
1485
1534
|
);
|
|
1486
1535
|
return;
|
|
1487
1536
|
}
|
|
1488
1537
|
// The schema must exist before the first query. Measured cost on this
|
|
1489
1538
|
// database (180 tables): ~5.5s for the version check alone, which is why the
|
|
1490
|
-
// serverless runtime
|
|
1491
|
-
// above rather than paying it on every cold start.
|
|
1539
|
+
// serverless runtime never runs it on cold starts.
|
|
1492
1540
|
// guard:allow-boot-data-work — schema must exist before the first query
|
|
1493
1541
|
await runAnalyticsMigrations(nitroApp);
|
|
1494
|
-
if (isNetlifyServerlessRuntime) {
|
|
1495
|
-
// The migration list is authoritative; repeating repair and schema
|
|
1496
|
-
// introspection on every function cold start only adds pool pressure.
|
|
1497
|
-
console.info(
|
|
1498
|
-
"[db] Skipping post-migration schema convergence in production serverless runtime",
|
|
1499
|
-
);
|
|
1500
|
-
return;
|
|
1501
|
-
}
|
|
1502
1542
|
try {
|
|
1503
1543
|
const summary = await ensureAdditiveColumns({
|
|
1504
1544
|
db: getDbExec(),
|
|
@@ -1,19 +1,23 @@
|
|
|
1
1
|
import { runSessionReplayRetentionOnce } from "../jobs/session-replay-retention";
|
|
2
|
+
import { isProductionServerlessRuntime } from "../lib/production-serverless-runtime";
|
|
2
3
|
|
|
3
4
|
const ONE_DAY_MS = 24 * 60 * 60 * 1000;
|
|
4
5
|
let skippingLogged = false;
|
|
5
6
|
|
|
6
7
|
export default function registerSessionReplayRetentionJobs(): void {
|
|
7
8
|
const isProd = process.env.NODE_ENV === "production";
|
|
9
|
+
const isServerless = isProductionServerlessRuntime();
|
|
8
10
|
const flag =
|
|
9
11
|
process.env.ANALYTICS_SESSION_REPLAY_RETENTION_JOBS ??
|
|
10
12
|
process.env.RUN_BACKGROUND_JOBS;
|
|
11
|
-
const enabled = flag === "1" || (isProd && flag !== "0");
|
|
13
|
+
const enabled = !isServerless && (flag === "1" || (isProd && flag !== "0"));
|
|
12
14
|
|
|
13
15
|
if (!enabled) {
|
|
14
16
|
if (!skippingLogged) {
|
|
15
17
|
console.log(
|
|
16
|
-
|
|
18
|
+
isServerless
|
|
19
|
+
? "[session-replay] Skipping in-process retention job because production serverless runtimes rely on scheduled/background sweeps."
|
|
20
|
+
: "[session-replay] Skipping retention job (set ANALYTICS_SESSION_REPLAY_RETENTION_JOBS=1 or RUN_BACKGROUND_JOBS=1 to enable in dev; on by default in production)",
|
|
17
21
|
);
|
|
18
22
|
skippingLogged = true;
|
|
19
23
|
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { timingSafeEqual } from "node:crypto";
|
|
2
|
+
|
|
3
|
+
import { createError, defineEventHandler, getHeader } from "h3";
|
|
4
|
+
|
|
5
|
+
// guard:allow-action-twin — external scheduler endpoint authenticates before invoking retention job logic.
|
|
6
|
+
import { runSessionReplayRetentionOnce } from "../../../jobs/session-replay-retention";
|
|
7
|
+
|
|
8
|
+
declare global {
|
|
9
|
+
var __AGENT_NATIVE_SESSION_REPLAY_RETENTION_SCHEDULED_RUNTIME__:
|
|
10
|
+
| boolean
|
|
11
|
+
| undefined;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function productionLike(): boolean {
|
|
15
|
+
return (
|
|
16
|
+
process.env.NODE_ENV === "production" ||
|
|
17
|
+
process.env.NETLIFY === "true" ||
|
|
18
|
+
process.env.VERCEL === "1" ||
|
|
19
|
+
Boolean(process.env.AWS_LAMBDA_FUNCTION_NAME)
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function scheduledFunctionRuntime(): boolean {
|
|
24
|
+
return (
|
|
25
|
+
globalThis.__AGENT_NATIVE_SESSION_REPLAY_RETENTION_SCHEDULED_RUNTIME__ ===
|
|
26
|
+
true
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function cronSecret(): string | null {
|
|
31
|
+
const secret = process.env.SESSION_REPLAY_RETENTION_CRON_SECRET?.trim();
|
|
32
|
+
return secret ? secret : null;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function headerMatchesSecret(
|
|
36
|
+
header: string | undefined,
|
|
37
|
+
secret: string,
|
|
38
|
+
): boolean {
|
|
39
|
+
const expected = `Bearer ${secret}`;
|
|
40
|
+
const value = header?.trim() ?? "";
|
|
41
|
+
if (value.length !== expected.length) return false;
|
|
42
|
+
return timingSafeEqual(Buffer.from(value), Buffer.from(expected));
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export default defineEventHandler(async (event) => {
|
|
46
|
+
const secret = cronSecret();
|
|
47
|
+
const scheduledRuntime = scheduledFunctionRuntime();
|
|
48
|
+
if (!secret && productionLike() && !scheduledRuntime) {
|
|
49
|
+
throw createError({
|
|
50
|
+
statusCode: 503,
|
|
51
|
+
statusMessage: "SESSION_REPLAY_RETENTION_CRON_SECRET is required",
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (
|
|
56
|
+
secret &&
|
|
57
|
+
!scheduledRuntime &&
|
|
58
|
+
!headerMatchesSecret(getHeader(event, "authorization"), secret)
|
|
59
|
+
) {
|
|
60
|
+
throw createError({ statusCode: 401, statusMessage: "Unauthorized" });
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const result = await runSessionReplayRetentionOnce();
|
|
64
|
+
return { ok: true, ...result };
|
|
65
|
+
});
|
|
@@ -20,6 +20,24 @@ Before creating any custom REST/API route for app data, inspect `actions/` and t
|
|
|
20
20
|
|
|
21
21
|
**Stop trigger:** the moment you are about to create a file under `server/routes/api/` — or add server middleware to guard one — stop and check it against the exception list in *When You Still Need Custom `/api/` Routes* below. If it is not on that list, write a `defineAction` instead. This applies even when you already started the route; abandoning a half-written action to hand-roll routes is the exact failure this rule exists to prevent.
|
|
22
22
|
|
|
23
|
+
## Keep actions deterministic and composable
|
|
24
|
+
|
|
25
|
+
An action may call a provider API, validate or normalize data, and persist
|
|
26
|
+
records without being an AI feature. Keep those operations deterministic,
|
|
27
|
+
focused, and independently useful to the agent. Do not put LLM calls or a
|
|
28
|
+
second model runtime in ordinary actions. The only narrow exception is the
|
|
29
|
+
`completeText()` text-in/text-out escape hatch described in
|
|
30
|
+
`delegate-to-agent`; it must not own tools, chat history, run state, side
|
|
31
|
+
effects, or user steering.
|
|
32
|
+
|
|
33
|
+
When a workflow is framed as research, analysis, generation, recommendation,
|
|
34
|
+
or synthesis, or spans several provider calls and writes, route the user into
|
|
35
|
+
the AgentSidebar and let the agent orchestrate focused actions. Do not hide an
|
|
36
|
+
AI-shaped workflow behind one opaque `generate-*` or `create-*` action just
|
|
37
|
+
because its implementation is deterministic. A visible user-initiated run
|
|
38
|
+
should use `sendToAgentChat({ openSidebar: true })`, and its follow-ups should
|
|
39
|
+
continue in the same thread rather than a separate freeform input.
|
|
40
|
+
|
|
23
41
|
## Why
|
|
24
42
|
|
|
25
43
|
Actions give the agent callable tools with structured input/output, AND they give the frontend a typed client contract through hooks. One implementation serves both the agent and the UI. They keep the agent's chat context clean, they're reusable, and they can be tested independently.
|
|
@@ -56,6 +56,11 @@ The repeated app shell has two distinct navigation surfaces:
|
|
|
56
56
|
labeled as local, preview, or analyze. For original/generated review, stack
|
|
57
57
|
the source above the result by default and use side-by-side only for short,
|
|
58
58
|
highly scannable content.
|
|
59
|
+
- Deterministic implementation does not make an AI-shaped experience
|
|
60
|
+
deterministic. If the user expects research, analysis, generation,
|
|
61
|
+
recommendation, synthesis, visible progress, or steering, route the button
|
|
62
|
+
to the AgentSidebar and let the agent call focused actions. Keep revisions in
|
|
63
|
+
the same thread instead of adding a second freeform prompt box.
|
|
59
64
|
- Standalone apps with `AgentSidebar` must resolve one assistant-ui runtime
|
|
60
65
|
context. Match direct assistant-ui pins to the installed core/toolkit peer
|
|
61
66
|
graph, use Vite dedupe/aliases when linked dependencies can split contexts,
|
|
@@ -14,11 +14,21 @@ metadata:
|
|
|
14
14
|
|
|
15
15
|
## Rule
|
|
16
16
|
|
|
17
|
-
The
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
17
|
+
The app's default AI surface is the agent chat. Any user-facing work that asks
|
|
18
|
+
the model to research, analyze, generate, recommend, synthesize, or reason over
|
|
19
|
+
multiple steps must start or continue in the AgentSidebar so users can see,
|
|
20
|
+
steer, and audit the work. UI buttons use `sendToAgentChat()` with
|
|
21
|
+
`openSidebar: true`, and follow-up or revision text belongs in that same thread
|
|
22
|
+
instead of a second app-local textbox.
|
|
23
|
+
|
|
24
|
+
Actions are tools, not alternate AI runtimes. Keep them deterministic and
|
|
25
|
+
focused: provider reads, validation, deterministic transforms, CRUD, and
|
|
26
|
+
persistence are good action work. Let the agent orchestrate several such tools
|
|
27
|
+
when the workflow is AI-shaped or user-steerable. Server-side one-shot model
|
|
28
|
+
calls are a rare escape hatch for narrow text transforms only; use
|
|
29
|
+
`completeText()` from `@agent-native/core/server` only when the work
|
|
30
|
+
intentionally does not need tools, chat history, run state, side effects, or
|
|
31
|
+
user steering.
|
|
22
32
|
|
|
23
33
|
## Why
|
|
24
34
|
|
|
@@ -35,6 +45,7 @@ sendToAgentChat({
|
|
|
35
45
|
message: "Generate a summary of this document",
|
|
36
46
|
context: documentContent, // optional hidden context (not shown in chat UI)
|
|
37
47
|
submit: true, // auto-submit to the agent
|
|
48
|
+
openSidebar: true,
|
|
38
49
|
});
|
|
39
50
|
```
|
|
40
51
|
|
|
@@ -56,6 +67,10 @@ sendToAgentChat({
|
|
|
56
67
|
This is still a full agent run: tools, actions, thread state, and run tracking
|
|
57
68
|
all remain active. It simply does not focus or open the sidebar.
|
|
58
69
|
|
|
70
|
+
Use this silent form only for explicitly background or system-initiated work.
|
|
71
|
+
It is not the default for a user clicking an AI-labeled button; visible work
|
|
72
|
+
should open the sidebar so the user can follow and redirect the run.
|
|
73
|
+
|
|
59
74
|
**From scripts (Node):**
|
|
60
75
|
|
|
61
76
|
```ts
|
|
@@ -77,8 +92,9 @@ const result = await completeText({
|
|
|
77
92
|
});
|
|
78
93
|
```
|
|
79
94
|
|
|
80
|
-
|
|
81
|
-
|
|
95
|
+
If the narrow exception is exposed to the UI, wrap it in an action so the UI
|
|
96
|
+
and agent share the same operation. Keep it clearly non-conversational and do
|
|
97
|
+
not call provider SDKs directly.
|
|
82
98
|
|
|
83
99
|
**From the UI, detecting when agent is done:**
|
|
84
100
|
|
|
@@ -97,9 +113,9 @@ The `submit` option controls whether the message is sent automatically or placed
|
|
|
97
113
|
|
|
98
114
|
| `submit` value | Behavior | Use when |
|
|
99
115
|
| -------------- | --------------------------------------- | ----------------------------------------------------------------------------------- |
|
|
100
|
-
| `true` | Auto-submits to the agent immediately | Routine operations
|
|
101
|
-
| `false` | Prefills the
|
|
102
|
-
| omitted | Uses the project's default setting | General-purpose delegation
|
|
116
|
+
| `true` | Auto-submits to the agent immediately | Routine operations with clear intent; keep `openSidebar: true` for visible work |
|
|
117
|
+
| `false` | Prefills the AgentSidebar composer | Review, edit, or add detail before the run; use the existing sidebar thread |
|
|
118
|
+
| omitted | Uses the project's default setting | General-purpose delegation |
|
|
103
119
|
|
|
104
120
|
```ts
|
|
105
121
|
// Auto-submit: routine operation
|
|
@@ -109,61 +125,43 @@ sendToAgentChat({ message: "Update the project summary", submit: true });
|
|
|
109
125
|
sendToAgentChat({
|
|
110
126
|
message: "Delete all projects older than 30 days",
|
|
111
127
|
submit: false,
|
|
128
|
+
openSidebar: true,
|
|
112
129
|
});
|
|
113
130
|
```
|
|
114
131
|
|
|
115
|
-
## Capture user input
|
|
116
|
-
|
|
117
|
-
Buttons that produce new content ("New Design", "Create Dashboard", "Make Deck", "Generate Form") need the user's prompt as input. **Never hardcode a generic message** — the result will be a generic generation the user didn't actually ask for.
|
|
132
|
+
## Capture user input in the sidebar
|
|
118
133
|
|
|
119
|
-
|
|
134
|
+
The AgentSidebar composer is the default prompt surface. When a button needs
|
|
135
|
+
the user to describe what to create, prefill that same composer and let the
|
|
136
|
+
user edit or complete it:
|
|
120
137
|
|
|
121
138
|
```tsx
|
|
122
139
|
<Button
|
|
123
140
|
onClick={() =>
|
|
124
|
-
sendToAgentChat({
|
|
141
|
+
sendToAgentChat({
|
|
142
|
+
message: "Help me create a research report from this brief:",
|
|
143
|
+
context: researchBrief,
|
|
144
|
+
submit: false,
|
|
145
|
+
openSidebar: true,
|
|
146
|
+
})
|
|
125
147
|
}
|
|
126
148
|
>
|
|
127
|
-
|
|
149
|
+
Start in agent
|
|
128
150
|
</Button>
|
|
129
151
|
```
|
|
130
152
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
<Popover open={open} onOpenChange={setOpen}>
|
|
135
|
-
<PopoverTrigger asChild>
|
|
136
|
-
<Button>New Design</Button>
|
|
137
|
-
</PopoverTrigger>
|
|
138
|
-
<PopoverContent className="w-96">
|
|
139
|
-
<Textarea
|
|
140
|
-
autoFocus
|
|
141
|
-
value={prompt}
|
|
142
|
-
onChange={(e) => setPrompt(e.target.value)}
|
|
143
|
-
placeholder="What do you want to design?"
|
|
144
|
-
/>
|
|
145
|
-
<Button
|
|
146
|
-
onClick={() => {
|
|
147
|
-
sendToAgentChat({ message: prompt, submit: true });
|
|
148
|
-
setOpen(false);
|
|
149
|
-
setPrompt("");
|
|
150
|
-
}}
|
|
151
|
-
>
|
|
152
|
-
Create
|
|
153
|
-
</Button>
|
|
154
|
-
</PopoverContent>
|
|
155
|
-
</Popover>
|
|
156
|
-
```
|
|
157
|
-
|
|
158
|
-
**Always ask for input first when** the output depends on a prompt the user must provide — "design what?", "deck about what?", "dashboard for which metric?", "form for which use case?".
|
|
159
|
-
|
|
160
|
-
**Auto-submit without input is fine when intent is unambiguous:**
|
|
153
|
+
Never auto-submit a generic creative prompt when the user has not said what
|
|
154
|
+
they want. Auto-submit without additional input is fine when intent is
|
|
155
|
+
unambiguous:
|
|
161
156
|
|
|
162
157
|
- "Try to fix" on a tool error — submits the error details with a clear fix instruction
|
|
163
158
|
- "Retry the last operation" after a transient failure
|
|
164
159
|
- Single-purpose buttons where there is nothing meaningful for the user to add
|
|
165
160
|
|
|
166
|
-
|
|
161
|
+
Use a Popover only for compact, structured parameters the UI must validate,
|
|
162
|
+
such as a date range, target, or approval choice. Do not add a second freeform
|
|
163
|
+
prompt or follow-up textbox for an AI workflow; keep the conversation and
|
|
164
|
+
revisions in the AgentSidebar thread.
|
|
167
165
|
|
|
168
166
|
## Delegating to a Sub-Agent (Agent Teams)
|
|
169
167
|
|