@agent-native/core 0.114.16 → 0.115.1
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/agent-native.eject.json +2 -0
- package/corpus/README.md +3 -3
- package/corpus/core/CHANGELOG.md +29 -0
- package/corpus/core/agent-native.eject.json +2 -0
- package/corpus/core/docs/content/agent-native-toolkit.mdx +16 -0
- package/corpus/core/docs/content/recurring-jobs.mdx +35 -6
- package/corpus/core/export-snapshot.json +4 -0
- package/corpus/core/package.json +5 -1
- package/corpus/core/src/action.ts +22 -1
- package/corpus/core/src/agent/production-agent.ts +105 -3
- package/corpus/core/src/cli/templates-meta.ts +12 -0
- package/corpus/core/src/client/AssistantChat.tsx +53 -26
- package/corpus/core/src/client/agent-page/AgentJobsTab.tsx +19 -0
- package/corpus/core/src/client/agent-page/use-jobs.ts +1 -0
- package/corpus/core/src/client/chat/message-components.tsx +35 -1
- package/corpus/core/src/client/chat/tool-call-display.tsx +38 -3
- package/corpus/core/src/connections/catalog.ts +20 -1
- package/corpus/core/src/connections/reader.ts +65 -0
- package/corpus/core/src/dashboard-storage/index.ts +27 -0
- package/corpus/core/src/dashboard-storage/panel-source.ts +168 -0
- package/corpus/core/src/dashboard-storage/schema.ts +62 -0
- package/corpus/core/src/dashboard-storage/store.ts +333 -0
- package/corpus/core/src/deploy/build.ts +95 -16
- package/corpus/core/src/eject/provider-api-definitions.ts +1 -0
- package/corpus/core/src/eject/workspace-connections.ts +1 -0
- package/corpus/core/src/extensions/actions.ts +199 -73
- package/corpus/core/src/jobs/actions/list-recurring-jobs.ts +2 -0
- package/corpus/core/src/jobs/scheduler.ts +71 -4
- package/corpus/core/src/jobs/tools.ts +31 -1
- package/corpus/core/src/localization/default-messages.ts +1 -0
- package/corpus/core/src/mcp-client/index.ts +6 -0
- package/corpus/core/src/provider-api/actions/provider-api.ts +1 -1
- package/corpus/core/src/provider-api/index.ts +190 -5
- package/corpus/core/src/secrets/register-framework-secrets.ts +8 -0
- package/corpus/core/src/server/agent-chat/context-tools.ts +9 -0
- package/corpus/core/src/server/agent-chat/framework-prompts.ts +2 -2
- package/corpus/core/src/server/agent-chat-plugin.ts +22 -2
- package/corpus/core/src/server/core-routes-plugin.ts +1 -0
- package/corpus/core/src/server/credential-provider.ts +9 -3
- package/corpus/core/src/server/workspace-provider-oauth.ts +181 -4
- package/corpus/core/src/styles/agent-native.css +45 -2
- package/corpus/core/src/templates/default/.agents/skills/agent-native-docs/SKILL.md +27 -0
- package/corpus/core/src/templates/default/.agents/skills/app-branding/SKILL.md +159 -0
- package/corpus/core/src/templates/default/.agents/skills/app-permissions/SKILL.md +155 -0
- package/corpus/core/src/templates/headless/.agents/skills/agent-native-docs/SKILL.md +27 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/agent-native-docs/SKILL.md +27 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +31 -18
- package/corpus/core/src/templates/workspace-core/.agents/skills/recurring-jobs/SKILL.md +15 -0
- package/corpus/core/src/triggers/actions.ts +11 -2
- package/corpus/core/src/triggers/dispatcher.ts +20 -1
- package/corpus/core/src/triggers/types.ts +5 -0
- package/corpus/core/src/vite/action-types-plugin.ts +9 -1
- package/corpus/templates/analytics/.agents/skills/agent-native-docs/SKILL.md +115 -0
- package/corpus/templates/analytics/AGENTS.md +11 -11
- package/corpus/templates/analytics/_gitignore +39 -0
- package/corpus/templates/analytics/actions/query-dashboard-panel.ts +30 -0
- package/corpus/templates/analytics/actions/update-dashboard.ts +2 -1
- package/corpus/templates/analytics/app/lib/sql-query.ts +11 -25
- package/corpus/templates/analytics/changelog/2026-07-21-fixed-extension-updates-failing-before-changes-could-be-appl.md +6 -0
- package/corpus/templates/analytics/server/lib/dashboard-panel-query.ts +1 -0
- package/corpus/templates/analytics/server/lib/dashboard-panel-source-resolver.ts +51 -0
- package/corpus/templates/analytics/server/lib/prometheus.ts +1 -1
- package/corpus/templates/analytics/server/plugins/agent-chat.ts +1 -1
- package/corpus/templates/assets/.agents/skills/agent-native-docs/SKILL.md +115 -0
- package/corpus/templates/brain/.agents/skills/agent-native-docs/SKILL.md +115 -0
- package/corpus/templates/calendar/.agents/skills/agent-native-docs/SKILL.md +115 -0
- package/corpus/templates/calendar/_gitignore +39 -0
- package/corpus/templates/chat/.agents/skills/agent-native-docs/SKILL.md +27 -0
- package/corpus/templates/chat/AGENTS.md +1 -1
- package/corpus/templates/clips/.agents/skills/agent-native-docs/SKILL.md +115 -0
- package/corpus/templates/clips/AGENTS.md +7 -0
- package/corpus/templates/clips/actions/prepare-crm-call-evidence.ts +58 -0
- package/corpus/templates/clips/app/components/recorder/recorder-engine.ts +88 -11
- package/corpus/templates/clips/changelog/2026-07-21-crm-call-evidence-handoff.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-21-recording-retries-and-restarts-keep-their-upload-session-so-.md +6 -0
- package/corpus/templates/clips/chrome-extension/src/background.ts +20 -5
- package/corpus/templates/clips/chrome-extension/src/native-recording-state.ts +19 -0
- package/corpus/templates/clips/chrome-extension/src/offscreen.ts +8 -0
- package/corpus/templates/clips/desktop/src/overlays/recording-pill.tsx +9 -0
- package/corpus/templates/clips/desktop/src-tauri/src/recording_indicator.rs +54 -28
- package/corpus/templates/clips/server/plugins/agent-chat.ts +1 -0
- package/corpus/templates/content/.agents/skills/agent-native-docs/SKILL.md +115 -0
- package/corpus/templates/content/_gitignore +39 -0
- package/corpus/templates/content/learnings.defaults.md +5 -0
- package/corpus/templates/crm/.agents/skills/agent-native-docs/SKILL.md +115 -0
- package/corpus/templates/crm/.agents/skills/agent-native-toolkit/SKILL.md +133 -0
- package/corpus/templates/crm/.agents/skills/crm/SKILL.md +128 -0
- package/corpus/templates/crm/.agents/skills/customizing-agent-native/SKILL.md +145 -0
- package/corpus/templates/crm/.agents/skills/feature-flags/SKILL.md +169 -0
- package/corpus/templates/crm/.agents/skills/upgrade-agent-native/SKILL.md +100 -0
- package/corpus/templates/crm/.env.example +5 -0
- package/corpus/templates/crm/AGENTS.md +120 -0
- package/corpus/templates/crm/CHANGELOG.md +1 -0
- package/corpus/templates/crm/DEVELOPING.md +66 -0
- package/corpus/templates/crm/README.md +106 -0
- package/corpus/templates/crm/_gitignore +12 -0
- package/corpus/templates/crm/actions/_crm-action-utils.ts +87 -0
- package/corpus/templates/crm/actions/_crm-dashboard.ts +69 -0
- package/corpus/templates/crm/actions/_crm-signal-utils.ts +79 -0
- package/corpus/templates/crm/actions/apply-crm-proposals.ts +203 -0
- package/corpus/templates/crm/actions/attach-call-evidence.ts +170 -0
- package/corpus/templates/crm/actions/configure-crm-connection.ts +126 -0
- package/corpus/templates/crm/actions/configure-native-crm.ts +44 -0
- package/corpus/templates/crm/actions/create-crm-record.ts +148 -0
- package/corpus/templates/crm/actions/create-crm-signal-tracker.ts +58 -0
- package/corpus/templates/crm/actions/delete-staged-dataset.ts +14 -0
- package/corpus/templates/crm/actions/get-crm-automation-recipe.ts +36 -0
- package/corpus/templates/crm/actions/get-crm-dashboard-panel.ts +33 -0
- package/corpus/templates/crm/actions/get-crm-dashboard.ts +14 -0
- package/corpus/templates/crm/actions/get-crm-overview.ts +13 -0
- package/corpus/templates/crm/actions/get-crm-pipeline-data.ts +61 -0
- package/corpus/templates/crm/actions/get-crm-record.ts +75 -0
- package/corpus/templates/crm/actions/install-crm-pipeline-dashboard.ts +81 -0
- package/corpus/templates/crm/actions/list-crm-dashboard-revisions.ts +15 -0
- package/corpus/templates/crm/actions/list-crm-dashboards.ts +15 -0
- package/corpus/templates/crm/actions/list-crm-proposals.ts +31 -0
- package/corpus/templates/crm/actions/list-crm-records.ts +79 -0
- package/corpus/templates/crm/actions/list-crm-saved-views.ts +15 -0
- package/corpus/templates/crm/actions/list-crm-signal-hits.ts +43 -0
- package/corpus/templates/crm/actions/list-crm-signal-trackers.ts +32 -0
- package/corpus/templates/crm/actions/list-crm-tasks.ts +22 -0
- package/corpus/templates/crm/actions/list-staged-datasets.ts +14 -0
- package/corpus/templates/crm/actions/list-workspace-connections.ts +47 -0
- package/corpus/templates/crm/actions/manage-crm-signal-tracker.ts +87 -0
- package/corpus/templates/crm/actions/manage-crm-task.ts +132 -0
- package/corpus/templates/crm/actions/navigate.ts +63 -0
- package/corpus/templates/crm/actions/provider-api-catalog.ts +22 -0
- package/corpus/templates/crm/actions/provider-api-docs.ts +54 -0
- package/corpus/templates/crm/actions/provider-api-request.ts +92 -0
- package/corpus/templates/crm/actions/query-staged-dataset.ts +44 -0
- package/corpus/templates/crm/actions/record-crm-call-insight.ts +160 -0
- package/corpus/templates/crm/actions/record-crm-smart-signal.ts +150 -0
- package/corpus/templates/crm/actions/restore-crm-dashboard-revision.ts +23 -0
- package/corpus/templates/crm/actions/review-crm-signal.ts +31 -0
- package/corpus/templates/crm/actions/run-crm-saved-view-program.ts +103 -0
- package/corpus/templates/crm/actions/run-crm-signal-trackers.ts +275 -0
- package/corpus/templates/crm/actions/run.ts +11 -0
- package/corpus/templates/crm/actions/save-crm-dashboard.ts +51 -0
- package/corpus/templates/crm/actions/save-crm-saved-view.ts +119 -0
- package/corpus/templates/crm/actions/sync-crm.ts +146 -0
- package/corpus/templates/crm/actions/update-crm-record.ts +508 -0
- package/corpus/templates/crm/actions/view-screen.ts +218 -0
- package/corpus/templates/crm/agent-native.app-skill.json +58 -0
- package/corpus/templates/crm/app/components/crm/CreateCrmRecordDialog.tsx +158 -0
- package/corpus/templates/crm/app/components/crm/CrmDashboardPanel.tsx +83 -0
- package/corpus/templates/crm/app/components/crm/CrmSignalsPanel.tsx +225 -0
- package/corpus/templates/crm/app/components/crm/IntelligenceSettings.tsx +413 -0
- package/corpus/templates/crm/app/components/crm/RecordActions.tsx +510 -0
- package/corpus/templates/crm/app/components/crm/RecordGrid.tsx +134 -0
- package/corpus/templates/crm/app/components/crm/RecordWorkspace.tsx +367 -0
- package/corpus/templates/crm/app/components/crm/SavedViewDataProgram.tsx +92 -0
- package/corpus/templates/crm/app/components/crm/Surface.tsx +96 -0
- package/corpus/templates/crm/app/components/crm/WorkOverview.tsx +180 -0
- package/corpus/templates/crm/app/components/layout/CrmLayout.tsx +106 -0
- package/corpus/templates/crm/app/components/layout/CrmSidebar.tsx +84 -0
- package/corpus/templates/crm/app/entry.client.tsx +16 -0
- package/corpus/templates/crm/app/entry.server.tsx +10 -0
- package/corpus/templates/crm/app/global.css +167 -0
- package/corpus/templates/crm/app/hooks/use-navigation-state.ts +60 -0
- package/corpus/templates/crm/app/i18n/en-US.ts +89 -0
- package/corpus/templates/crm/app/i18n/index.ts +34 -0
- package/corpus/templates/crm/app/lib/dashboard.ts +13 -0
- package/corpus/templates/crm/app/lib/navigation.ts +54 -0
- package/corpus/templates/crm/app/lib/tab-id.ts +1 -0
- package/corpus/templates/crm/app/lib/types.ts +172 -0
- package/corpus/templates/crm/app/lib/utils.ts +1 -0
- package/corpus/templates/crm/app/root.tsx +88 -0
- package/corpus/templates/crm/app/routes/_index.tsx +26 -0
- package/corpus/templates/crm/app/routes/accounts.tsx +41 -0
- package/corpus/templates/crm/app/routes/agent.tsx +5 -0
- package/corpus/templates/crm/app/routes/ask.tsx +53 -0
- package/corpus/templates/crm/app/routes/dashboard.tsx +118 -0
- package/corpus/templates/crm/app/routes/opportunities.tsx +41 -0
- package/corpus/templates/crm/app/routes/people.tsx +41 -0
- package/corpus/templates/crm/app/routes/proposals.tsx +266 -0
- package/corpus/templates/crm/app/routes/records.$recordId.tsx +35 -0
- package/corpus/templates/crm/app/routes/settings.tsx +63 -0
- package/corpus/templates/crm/app/routes/setup.tsx +308 -0
- package/corpus/templates/crm/app/routes/tasks.tsx +252 -0
- package/corpus/templates/crm/app/routes/views.tsx +333 -0
- package/corpus/templates/crm/app/routes.ts +17 -0
- package/corpus/templates/crm/app/vite-env.d.ts +6 -0
- package/corpus/templates/crm/changelog/2026-07-21-agent-native-crm.md +6 -0
- package/corpus/templates/crm/changelog/2026-07-21-clips-call-evidence-review-recipe.md +6 -0
- package/corpus/templates/crm/changelog/2026-07-21-crm-can-now-find-and-review-evidence-grounded-call-signals-w.md +6 -0
- package/corpus/templates/crm/changelog/2026-07-21-crm-can-now-manage-keyword-and-smart-call-signal-trackers-fr.md +6 -0
- package/corpus/templates/crm/changelog/2026-07-21-delegated-local-crm-automation.md +6 -0
- package/corpus/templates/crm/changelog/2026-07-21-native-sql.md +6 -0
- package/corpus/templates/crm/changelog/2026-07-21-pipeline-dashboard.md +6 -0
- package/corpus/templates/crm/changelog/2026-07-21-pipeline-dashboards-now-install-correctly-from-the-crm-actio.md +6 -0
- package/corpus/templates/crm/changelog/2026-07-21-salesforce-connection.md +6 -0
- package/corpus/templates/crm/components.json +20 -0
- package/corpus/templates/crm/docs/architecture/crm-contract.md +180 -0
- package/corpus/templates/crm/learnings.defaults.md +5 -0
- package/corpus/templates/crm/package.json +59 -0
- package/corpus/templates/crm/public/favicon.svg +1 -0
- package/corpus/templates/crm/public/icon-180.svg +1 -0
- package/corpus/templates/crm/public/manifest.json +11 -0
- package/corpus/templates/crm/react-router.config.ts +7 -0
- package/corpus/templates/crm/server/crm/adapter.ts +32 -0
- package/corpus/templates/crm/server/crm/crm-field-firewall.ts +64 -0
- package/corpus/templates/crm/server/crm/crm-mirror.ts +711 -0
- package/corpus/templates/crm/server/crm/hubspot-adapter.ts +1143 -0
- package/corpus/templates/crm/server/crm/native-adapter.ts +1715 -0
- package/corpus/templates/crm/server/crm/read-through.ts +207 -0
- package/corpus/templates/crm/server/crm/salesforce-adapter.ts +1255 -0
- package/corpus/templates/crm/server/db/crm-store.ts +1170 -0
- package/corpus/templates/crm/server/db/index.ts +169 -0
- package/corpus/templates/crm/server/db/schema.ts +441 -0
- package/corpus/templates/crm/server/lib/intelligence/default-detectors.ts +65 -0
- package/corpus/templates/crm/server/lib/intelligence/evidence.ts +105 -0
- package/corpus/templates/crm/server/lib/intelligence/keyword-detector.ts +100 -0
- package/corpus/templates/crm/server/lib/intelligence/smart-detector.ts +144 -0
- package/corpus/templates/crm/server/lib/intelligence/summary.ts +141 -0
- package/corpus/templates/crm/server/lib/provider-api.ts +64 -0
- package/corpus/templates/crm/server/middleware/auth.ts +4 -0
- package/corpus/templates/crm/server/plugins/agent-chat.ts +68 -0
- package/corpus/templates/crm/server/plugins/auth.ts +14 -0
- package/corpus/templates/crm/server/plugins/core-routes.ts +17 -0
- package/corpus/templates/crm/server/plugins/db.ts +454 -0
- package/corpus/templates/crm/server/routes/[...page].get.ts +5 -0
- package/corpus/templates/crm/shared/crm-automation-recipes.ts +132 -0
- package/corpus/templates/crm/shared/crm-contract.ts +254 -0
- package/corpus/templates/crm/shared/crm-sales-config.ts +63 -0
- package/corpus/templates/crm/ssr-entry.ts +11 -0
- package/corpus/templates/crm/tsconfig.json +24 -0
- package/corpus/templates/crm/vite.config.ts +15 -0
- package/corpus/templates/crm/vitest.config.ts +5 -0
- package/corpus/templates/design/.agents/skills/agent-native-docs/SKILL.md +115 -0
- package/corpus/templates/dispatch/.agents/skills/agent-native-docs/SKILL.md +115 -0
- package/corpus/templates/forms/.agents/skills/agent-native-docs/SKILL.md +115 -0
- package/corpus/templates/forms/_gitignore +39 -0
- package/corpus/templates/forms/learnings.defaults.md +5 -0
- package/corpus/templates/macros/.agents/skills/agent-native-docs/SKILL.md +115 -0
- package/corpus/templates/macros/_gitignore +39 -0
- package/corpus/templates/macros/learnings.defaults.md +5 -0
- package/corpus/templates/mail/.agents/skills/agent-native-docs/SKILL.md +115 -0
- package/corpus/templates/mail/_gitignore +39 -0
- package/corpus/templates/plan/.agents/skills/agent-native-docs/SKILL.md +115 -0
- package/corpus/templates/slides/.agents/skills/agent-native-docs/SKILL.md +115 -0
- package/corpus/templates/slides/_gitignore +39 -0
- package/corpus/templates/tasks/.agents/skills/agent-native-docs/SKILL.md +27 -0
- package/corpus/templates/tasks/_gitignore +39 -0
- package/corpus/toolkit/CHANGELOG.md +12 -0
- package/corpus/toolkit/README.md +30 -0
- package/corpus/toolkit/agent-native.eject.json +33 -0
- package/corpus/toolkit/package.json +15 -1
- package/corpus/toolkit/src/dashboard/DataTable.tsx +273 -0
- package/corpus/toolkit/src/dashboard/DateRangePicker.tsx +57 -0
- package/corpus/toolkit/src/dashboard/GenericChartPanel.tsx +461 -0
- package/corpus/toolkit/src/dashboard/MetricCard.tsx +54 -0
- package/corpus/toolkit/src/dashboard/StatsCard.tsx +49 -0
- package/corpus/toolkit/src/dashboard/dashboard-layout.ts +329 -0
- package/corpus/toolkit/src/dashboard/index.ts +6 -0
- package/corpus/toolkit/src/index.ts +1 -0
- package/corpus/toolkit/src/ui/calendar.tsx +8 -8
- package/corpus/toolkit/src/ui/date-picker.tsx +4 -1
- package/dist/action.d.ts +14 -1
- package/dist/action.d.ts.map +1 -1
- package/dist/action.js.map +1 -1
- package/dist/agent/production-agent.d.ts +3 -1
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +83 -3
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/cli/templates-meta.d.ts.map +1 -1
- package/dist/cli/templates-meta.js +12 -0
- package/dist/cli/templates-meta.js.map +1 -1
- package/dist/client/AssistantChat.d.ts +4 -0
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +30 -17
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/agent-page/AgentJobsTab.d.ts.map +1 -1
- package/dist/client/agent-page/AgentJobsTab.js +3 -1
- package/dist/client/agent-page/AgentJobsTab.js.map +1 -1
- package/dist/client/agent-page/use-jobs.d.ts +1 -0
- package/dist/client/agent-page/use-jobs.d.ts.map +1 -1
- package/dist/client/agent-page/use-jobs.js.map +1 -1
- package/dist/client/chat/message-components.d.ts +5 -0
- package/dist/client/chat/message-components.d.ts.map +1 -1
- package/dist/client/chat/message-components.js +17 -1
- 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 +17 -7
- package/dist/client/chat/tool-call-display.js.map +1 -1
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/awareness.d.ts.map +1 -1
- package/dist/collab/routes.d.ts +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/connections/catalog.d.ts +17 -3
- package/dist/connections/catalog.d.ts.map +1 -1
- package/dist/connections/catalog.js +16 -1
- package/dist/connections/catalog.js.map +1 -1
- package/dist/connections/reader.d.ts +18 -0
- package/dist/connections/reader.d.ts.map +1 -1
- package/dist/connections/reader.js +41 -0
- package/dist/connections/reader.js.map +1 -1
- package/dist/dashboard-storage/index.d.ts +4 -0
- package/dist/dashboard-storage/index.d.ts.map +1 -0
- package/dist/dashboard-storage/index.js +4 -0
- package/dist/dashboard-storage/index.js.map +1 -0
- package/dist/dashboard-storage/panel-source.d.ts +68 -0
- package/dist/dashboard-storage/panel-source.d.ts.map +1 -0
- package/dist/dashboard-storage/panel-source.js +76 -0
- package/dist/dashboard-storage/panel-source.js.map +1 -0
- package/dist/dashboard-storage/schema.d.ts +562 -0
- package/dist/dashboard-storage/schema.d.ts.map +1 -0
- package/dist/dashboard-storage/schema.js +32 -0
- package/dist/dashboard-storage/schema.js.map +1 -0
- package/dist/dashboard-storage/store.d.ts +62 -0
- package/dist/dashboard-storage/store.d.ts.map +1 -0
- package/dist/dashboard-storage/store.js +227 -0
- package/dist/dashboard-storage/store.js.map +1 -0
- package/dist/deploy/build.d.ts +7 -0
- package/dist/deploy/build.d.ts.map +1 -1
- package/dist/deploy/build.js +78 -14
- package/dist/deploy/build.js.map +1 -1
- package/dist/eject/provider-api-definitions.d.ts +2 -1
- package/dist/eject/provider-api-definitions.d.ts.map +1 -1
- package/dist/eject/provider-api-definitions.js +1 -0
- package/dist/eject/provider-api-definitions.js.map +1 -1
- package/dist/eject/workspace-connections.d.ts.map +1 -1
- package/dist/eject/workspace-connections.js +1 -0
- package/dist/eject/workspace-connections.js.map +1 -1
- package/dist/extensions/actions.d.ts.map +1 -1
- package/dist/extensions/actions.js +165 -67
- package/dist/extensions/actions.js.map +1 -1
- package/dist/file-upload/actions/upload-image.d.ts +1 -1
- package/dist/jobs/actions/list-recurring-jobs.d.ts +1 -0
- package/dist/jobs/actions/list-recurring-jobs.d.ts.map +1 -1
- package/dist/jobs/actions/list-recurring-jobs.js +1 -0
- package/dist/jobs/actions/list-recurring-jobs.js.map +1 -1
- package/dist/jobs/scheduler.d.ts +17 -2
- package/dist/jobs/scheduler.d.ts.map +1 -1
- package/dist/jobs/scheduler.js +51 -2
- package/dist/jobs/scheduler.js.map +1 -1
- package/dist/jobs/tools.d.ts.map +1 -1
- package/dist/jobs/tools.js +32 -2
- package/dist/jobs/tools.js.map +1 -1
- package/dist/localization/default-messages.d.ts +1 -0
- package/dist/localization/default-messages.d.ts.map +1 -1
- package/dist/localization/default-messages.js +1 -0
- package/dist/localization/default-messages.js.map +1 -1
- package/dist/mcp-client/index.d.ts +2 -0
- package/dist/mcp-client/index.d.ts.map +1 -1
- package/dist/mcp-client/index.js +5 -0
- package/dist/mcp-client/index.js.map +1 -1
- package/dist/notifications/routes.d.ts +3 -3
- package/dist/observability/routes.d.ts +5 -5
- package/dist/provider-api/actions/custom-provider-registration.d.ts +8 -8
- package/dist/provider-api/actions/provider-api.d.ts +8 -6
- package/dist/provider-api/actions/provider-api.d.ts.map +1 -1
- package/dist/provider-api/actions/provider-api.js +1 -1
- package/dist/provider-api/actions/provider-api.js.map +1 -1
- package/dist/provider-api/index.d.ts +11 -7
- package/dist/provider-api/index.d.ts.map +1 -1
- package/dist/provider-api/index.js +143 -5
- package/dist/provider-api/index.js.map +1 -1
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/secrets/register-framework-secrets.d.ts.map +1 -1
- package/dist/secrets/register-framework-secrets.js +7 -0
- package/dist/secrets/register-framework-secrets.js.map +1 -1
- package/dist/secrets/routes.d.ts +9 -9
- package/dist/server/agent-chat/context-tools.d.ts.map +1 -1
- package/dist/server/agent-chat/context-tools.js +9 -0
- package/dist/server/agent-chat/context-tools.js.map +1 -1
- package/dist/server/agent-chat/framework-prompts.js +2 -2
- package/dist/server/agent-chat/framework-prompts.js.map +1 -1
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +18 -2
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/core-routes-plugin.d.ts.map +1 -1
- package/dist/server/core-routes-plugin.js +1 -0
- package/dist/server/core-routes-plugin.js.map +1 -1
- package/dist/server/credential-provider.d.ts +4 -3
- package/dist/server/credential-provider.d.ts.map +1 -1
- package/dist/server/credential-provider.js +9 -3
- package/dist/server/credential-provider.js.map +1 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/dist/server/workspace-provider-oauth.d.ts +6 -1
- package/dist/server/workspace-provider-oauth.d.ts.map +1 -1
- package/dist/server/workspace-provider-oauth.js +141 -4
- package/dist/server/workspace-provider-oauth.js.map +1 -1
- package/dist/styles/agent-native.css +45 -2
- package/dist/templates/chat/.agents/skills/agent-native-docs/SKILL.md +27 -0
- package/dist/templates/chat/AGENTS.md +1 -1
- package/dist/templates/default/.agents/skills/agent-native-docs/SKILL.md +27 -0
- package/dist/templates/default/.agents/skills/app-branding/SKILL.md +159 -0
- package/dist/templates/default/.agents/skills/app-permissions/SKILL.md +155 -0
- package/dist/templates/headless/.agents/skills/agent-native-docs/SKILL.md +27 -0
- package/dist/templates/workspace-core/.agents/skills/agent-native-docs/SKILL.md +27 -0
- package/dist/templates/workspace-core/.agents/skills/extensions/SKILL.md +31 -18
- package/dist/templates/workspace-core/.agents/skills/recurring-jobs/SKILL.md +15 -0
- package/dist/triggers/actions.d.ts.map +1 -1
- package/dist/triggers/actions.js +10 -2
- package/dist/triggers/actions.js.map +1 -1
- package/dist/triggers/dispatcher.d.ts.map +1 -1
- package/dist/triggers/dispatcher.js +15 -0
- package/dist/triggers/dispatcher.js.map +1 -1
- package/dist/triggers/types.d.ts +5 -0
- package/dist/triggers/types.d.ts.map +1 -1
- package/dist/triggers/types.js.map +1 -1
- package/dist/vite/action-types-plugin.d.ts.map +1 -1
- package/dist/vite/action-types-plugin.js +4 -1
- package/dist/vite/action-types-plugin.js.map +1 -1
- package/docs/content/agent-native-toolkit.mdx +16 -0
- package/docs/content/recurring-jobs.mdx +35 -6
- package/package.json +6 -2
- package/src/action.ts +22 -1
- package/src/agent/production-agent.ts +105 -3
- package/src/cli/templates-meta.ts +12 -0
- package/src/client/AssistantChat.tsx +53 -26
- package/src/client/agent-page/AgentJobsTab.tsx +19 -0
- package/src/client/agent-page/use-jobs.ts +1 -0
- package/src/client/chat/message-components.tsx +35 -1
- package/src/client/chat/tool-call-display.tsx +38 -3
- package/src/connections/catalog.ts +20 -1
- package/src/connections/reader.ts +65 -0
- package/src/dashboard-storage/index.ts +27 -0
- package/src/dashboard-storage/panel-source.ts +168 -0
- package/src/dashboard-storage/schema.ts +62 -0
- package/src/dashboard-storage/store.ts +333 -0
- package/src/deploy/build.ts +95 -16
- package/src/eject/provider-api-definitions.ts +1 -0
- package/src/eject/workspace-connections.ts +1 -0
- package/src/extensions/actions.ts +199 -73
- package/src/jobs/actions/list-recurring-jobs.ts +2 -0
- package/src/jobs/scheduler.ts +71 -4
- package/src/jobs/tools.ts +31 -1
- package/src/localization/default-messages.ts +1 -0
- package/src/mcp-client/index.ts +6 -0
- package/src/provider-api/actions/provider-api.ts +1 -1
- package/src/provider-api/index.ts +190 -5
- package/src/secrets/register-framework-secrets.ts +8 -0
- package/src/server/agent-chat/context-tools.ts +9 -0
- package/src/server/agent-chat/framework-prompts.ts +2 -2
- package/src/server/agent-chat-plugin.ts +22 -2
- package/src/server/core-routes-plugin.ts +1 -0
- package/src/server/credential-provider.ts +9 -3
- package/src/server/workspace-provider-oauth.ts +181 -4
- package/src/styles/agent-native.css +45 -2
- package/src/templates/chat/.agents/skills/agent-native-docs/SKILL.md +27 -0
- package/src/templates/chat/AGENTS.md +1 -1
- package/src/templates/default/.agents/skills/agent-native-docs/SKILL.md +27 -0
- package/src/templates/default/.agents/skills/app-branding/SKILL.md +159 -0
- package/src/templates/default/.agents/skills/app-permissions/SKILL.md +155 -0
- package/src/templates/headless/.agents/skills/agent-native-docs/SKILL.md +27 -0
- package/src/templates/workspace-core/.agents/skills/agent-native-docs/SKILL.md +27 -0
- package/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +31 -18
- package/src/templates/workspace-core/.agents/skills/recurring-jobs/SKILL.md +15 -0
- package/src/triggers/actions.ts +11 -2
- package/src/triggers/dispatcher.ts +20 -1
- package/src/triggers/types.ts +5 -0
- package/src/vite/action-types-plugin.ts +9 -1
- package/corpus/templates/analytics/server/handlers/sql-query.ts +0 -36
- package/corpus/templates/analytics/server/routes/api/sql-query.post.ts +0 -1
package/src/jobs/tools.ts
CHANGED
|
@@ -18,6 +18,7 @@ import { isValidCron, nextOccurrence, describeCron } from "./cron.js";
|
|
|
18
18
|
import {
|
|
19
19
|
parseJobFrontmatter,
|
|
20
20
|
buildJobContent,
|
|
21
|
+
normalizeJobMcpTools,
|
|
21
22
|
type JobFrontmatter,
|
|
22
23
|
} from "./scheduler.js";
|
|
23
24
|
|
|
@@ -106,6 +107,13 @@ async function runCreate(args: Record<string, any>): Promise<string> {
|
|
|
106
107
|
});
|
|
107
108
|
}
|
|
108
109
|
|
|
110
|
+
let mcpTools: string[] | undefined;
|
|
111
|
+
try {
|
|
112
|
+
mcpTools = normalizeJobMcpTools(args.mcpTools);
|
|
113
|
+
} catch (err) {
|
|
114
|
+
return JSON.stringify({ error: (err as Error).message });
|
|
115
|
+
}
|
|
116
|
+
|
|
109
117
|
const owner = scope === "personal" ? getOwner() : getSharedOwner();
|
|
110
118
|
const path = `jobs/${name}.md`;
|
|
111
119
|
const now = new Date();
|
|
@@ -135,6 +143,7 @@ async function runCreate(args: Record<string, any>): Promise<string> {
|
|
|
135
143
|
...(typeof model === "string" && model.trim()
|
|
136
144
|
? { model: model.trim() }
|
|
137
145
|
: {}),
|
|
146
|
+
...(mcpTools?.length ? { mcpTools } : {}),
|
|
138
147
|
};
|
|
139
148
|
|
|
140
149
|
const content = buildJobContent(meta, instructions);
|
|
@@ -148,6 +157,7 @@ async function runCreate(args: Record<string, any>): Promise<string> {
|
|
|
148
157
|
scheduleDescription: describeCron(schedule),
|
|
149
158
|
nextRun: next.toISOString(),
|
|
150
159
|
scope: scope || "shared",
|
|
160
|
+
...(mcpTools?.length ? { mcpTools } : {}),
|
|
151
161
|
});
|
|
152
162
|
}
|
|
153
163
|
|
|
@@ -184,6 +194,7 @@ async function runList(args: Record<string, any>): Promise<string> {
|
|
|
184
194
|
deliveryPlatform: meta.deliveryPlatform || null,
|
|
185
195
|
deliveryDestination: meta.deliveryDestination || null,
|
|
186
196
|
model: meta.model || null,
|
|
197
|
+
mcpTools: meta.mcpTools || [],
|
|
187
198
|
};
|
|
188
199
|
}),
|
|
189
200
|
);
|
|
@@ -243,6 +254,16 @@ async function runUpdate(args: Record<string, any>): Promise<string> {
|
|
|
243
254
|
}
|
|
244
255
|
if (typeof model === "string" && model.trim()) meta.model = model.trim();
|
|
245
256
|
|
|
257
|
+
if (args.mcpTools !== undefined) {
|
|
258
|
+
try {
|
|
259
|
+
const mcpTools = normalizeJobMcpTools(args.mcpTools) ?? [];
|
|
260
|
+
if (mcpTools.length) meta.mcpTools = mcpTools;
|
|
261
|
+
else delete meta.mcpTools;
|
|
262
|
+
} catch (err) {
|
|
263
|
+
return JSON.stringify({ error: (err as Error).message });
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
246
267
|
const newBody = instructions || body;
|
|
247
268
|
const content = buildJobContent(meta, newBody);
|
|
248
269
|
await resourcePut(resource.owner, resource.path, content);
|
|
@@ -254,6 +275,7 @@ async function runUpdate(args: Record<string, any>): Promise<string> {
|
|
|
254
275
|
scheduleDescription: describeCron(meta.schedule),
|
|
255
276
|
enabled: meta.enabled,
|
|
256
277
|
nextRun: meta.nextRun,
|
|
278
|
+
mcpTools: meta.mcpTools || [],
|
|
257
279
|
});
|
|
258
280
|
}
|
|
259
281
|
|
|
@@ -295,7 +317,9 @@ Actions:
|
|
|
295
317
|
- "update": Update a job's schedule, instructions, or enabled state. Requires name.
|
|
296
318
|
- "delete": Delete a recurring job. Requires name. Always confirm with the user first.
|
|
297
319
|
|
|
298
|
-
Cron format is 5 fields: minute hour day-of-month month day-of-week. Common patterns: '0 9 * * *' (daily 9am), '0 9 * * 1-5' (weekdays 9am), '0 * * * *' (every hour), '0 9 * * 1' (Mondays 9am), '*/30 * * * *' (every 30 min)
|
|
320
|
+
Cron format is 5 fields: minute hour day-of-month month day-of-week. Common patterns: '0 9 * * *' (daily 9am), '0 9 * * 1-5' (weekdays 9am), '0 * * * *' (every hour), '0 9 * * 1' (Mondays 9am), '*/30 * * * *' (every 30 min).
|
|
321
|
+
|
|
322
|
+
For jobs that use a connected MCP, pass the exact tool names in mcpTools. This binds only those tools to the background run; OAuth credentials remain in the connector and are resolved for the job's user/org context.`,
|
|
299
323
|
parameters: {
|
|
300
324
|
type: "object",
|
|
301
325
|
properties: {
|
|
@@ -342,6 +366,12 @@ Cron format is 5 fields: minute hour day-of-month month day-of-week. Common patt
|
|
|
342
366
|
description:
|
|
343
367
|
"Optional model id for this routine. The channel/app/engine default is used when omitted.",
|
|
344
368
|
},
|
|
369
|
+
mcpTools: {
|
|
370
|
+
type: "array",
|
|
371
|
+
items: { type: "string" },
|
|
372
|
+
description:
|
|
373
|
+
'Optional explicit MCP capabilities for this job. Use the connected tool names exactly as advertised, for example ["mcp__meeting-notes__list_meetings", "mcp__meeting-notes__get_transcript"]. The job runs only with these tools; credentials remain in the connector.',
|
|
374
|
+
},
|
|
345
375
|
},
|
|
346
376
|
required: ["action"],
|
|
347
377
|
},
|
|
@@ -453,6 +453,7 @@ const messages = {
|
|
|
453
453
|
cancel: "Cancel",
|
|
454
454
|
recurringDetails: "Recurring job details",
|
|
455
455
|
instructions: "Instructions",
|
|
456
|
+
mcpTools: "Connected MCP tools",
|
|
456
457
|
automationsLoadError: "Could not load automations.",
|
|
457
458
|
automationsEmpty: "No automations yet.",
|
|
458
459
|
automationEventTrigger: "On {{event}}",
|
package/src/mcp-client/index.ts
CHANGED
|
@@ -166,6 +166,8 @@ import {
|
|
|
166
166
|
|
|
167
167
|
export interface McpActionEntryOptions {
|
|
168
168
|
invocationPolicy?: McpToolInvocationPolicy;
|
|
169
|
+
/** Restrict the generated entries to an explicit background capability set. */
|
|
170
|
+
toolNames?: readonly string[];
|
|
169
171
|
}
|
|
170
172
|
|
|
171
173
|
export function mcpToolsToActionEntries(
|
|
@@ -173,7 +175,11 @@ export function mcpToolsToActionEntries(
|
|
|
173
175
|
options: McpActionEntryOptions = {},
|
|
174
176
|
): Record<string, ActionEntry> {
|
|
175
177
|
const entries: Record<string, ActionEntry> = {};
|
|
178
|
+
const selectedToolNames = options.toolNames
|
|
179
|
+
? new Set(options.toolNames)
|
|
180
|
+
: undefined;
|
|
176
181
|
for (const tool of manager.getTools().filter(isVisibleToModel)) {
|
|
182
|
+
if (selectedToolNames && !selectedToolNames.has(tool.name)) continue;
|
|
177
183
|
entries[tool.name] = mcpToolToActionEntry(manager, tool, options);
|
|
178
184
|
}
|
|
179
185
|
return entries;
|
|
@@ -177,7 +177,7 @@ export function createProviderApiRequestSchema(
|
|
|
177
177
|
.string()
|
|
178
178
|
.optional()
|
|
179
179
|
.describe(
|
|
180
|
-
"
|
|
180
|
+
"Shared workspace connection id to use when the provider has multiple granted connections. Required when provider-api-catalog marks requiresConnectionId.",
|
|
181
181
|
),
|
|
182
182
|
accountId: z
|
|
183
183
|
.string()
|
|
@@ -73,6 +73,7 @@ export const PROVIDER_API_IDS = [
|
|
|
73
73
|
"granola",
|
|
74
74
|
"grafana",
|
|
75
75
|
"hubspot",
|
|
76
|
+
"salesforce",
|
|
76
77
|
"jira",
|
|
77
78
|
"mixpanel",
|
|
78
79
|
"notion",
|
|
@@ -384,6 +385,7 @@ export interface ProviderApiConfig {
|
|
|
384
385
|
id: ProviderApiId;
|
|
385
386
|
label: string;
|
|
386
387
|
defaultBaseUrl: string;
|
|
388
|
+
requiresConnectionId?: boolean;
|
|
387
389
|
baseUrlCredentialKey?: string;
|
|
388
390
|
auth: ProviderApiAuthKind;
|
|
389
391
|
credentialKeys: readonly string[];
|
|
@@ -1212,6 +1214,43 @@ const PROVIDER_CONFIGS: Record<ProviderApiId, ProviderApiConfig> = {
|
|
|
1212
1214
|
},
|
|
1213
1215
|
],
|
|
1214
1216
|
},
|
|
1217
|
+
salesforce: {
|
|
1218
|
+
id: "salesforce",
|
|
1219
|
+
label: "Salesforce",
|
|
1220
|
+
defaultBaseUrl: "https://login.salesforce.com",
|
|
1221
|
+
requiresConnectionId: true,
|
|
1222
|
+
auth: {
|
|
1223
|
+
type: "oauth-bearer",
|
|
1224
|
+
oauthProvider: "salesforce",
|
|
1225
|
+
tokenLabel: "Salesforce OAuth token",
|
|
1226
|
+
workspaceProvider: "salesforce",
|
|
1227
|
+
},
|
|
1228
|
+
credentialKeys: ["SALESFORCE_OAUTH_ACCOUNT"],
|
|
1229
|
+
docsUrls: [
|
|
1230
|
+
"https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/",
|
|
1231
|
+
],
|
|
1232
|
+
allowedHostSuffixes: [],
|
|
1233
|
+
templateUses: ["analytics", "brain", "crm", "dispatch"],
|
|
1234
|
+
examples: [
|
|
1235
|
+
{
|
|
1236
|
+
label: "List recent Accounts",
|
|
1237
|
+
method: "GET",
|
|
1238
|
+
path: "/services/data/v60.0/sobjects/Account",
|
|
1239
|
+
},
|
|
1240
|
+
{
|
|
1241
|
+
label: "Query Opportunity records with SOQL",
|
|
1242
|
+
method: "GET",
|
|
1243
|
+
path: "/services/data/v60.0/query",
|
|
1244
|
+
query: {
|
|
1245
|
+
q: "SELECT Id, Name, StageName, Amount, CloseDate FROM Opportunity LIMIT 100",
|
|
1246
|
+
},
|
|
1247
|
+
},
|
|
1248
|
+
],
|
|
1249
|
+
notes: [
|
|
1250
|
+
"Workspace OAuth stores the Salesforce instance URL on the connection. Requests with a connectionId use that instance instead of the login host.",
|
|
1251
|
+
"CRM templates own object allow-lists, field projections, and API-version selection.",
|
|
1252
|
+
],
|
|
1253
|
+
},
|
|
1215
1254
|
jira: {
|
|
1216
1255
|
id: "jira",
|
|
1217
1256
|
label: "Jira Cloud",
|
|
@@ -1574,6 +1613,7 @@ export function listProviderApiCatalog(
|
|
|
1574
1613
|
id: config.id,
|
|
1575
1614
|
label: config.label,
|
|
1576
1615
|
defaultBaseUrl: config.defaultBaseUrl,
|
|
1616
|
+
requiresConnectionId: config.requiresConnectionId ?? false,
|
|
1577
1617
|
baseUrlCredentialKey: config.baseUrlCredentialKey ?? null,
|
|
1578
1618
|
auth: describeAuth(config.auth),
|
|
1579
1619
|
credentialKeys: config.credentialKeys,
|
|
@@ -1749,6 +1789,11 @@ export async function executeProviderApiRequest(
|
|
|
1749
1789
|
|
|
1750
1790
|
// --- built-in provider path (original code) ---
|
|
1751
1791
|
const config = builtIn!;
|
|
1792
|
+
if (config.requiresConnectionId && !args.connectionId?.trim()) {
|
|
1793
|
+
throw new Error(
|
|
1794
|
+
`${config.label} Provider API requests require a workspace connectionId.`,
|
|
1795
|
+
);
|
|
1796
|
+
}
|
|
1752
1797
|
const ctx = requireRuntimeCredentialContext(
|
|
1753
1798
|
runtime,
|
|
1754
1799
|
config.credentialKeys[0] ?? config.id,
|
|
@@ -1951,9 +1996,9 @@ export async function executeProviderApiRequest(
|
|
|
1951
1996
|
}
|
|
1952
1997
|
|
|
1953
1998
|
/**
|
|
1954
|
-
* Resolve a provider OAuth token for a trusted server-side
|
|
1955
|
-
* Google Picker. Callers must keep the result out of
|
|
1956
|
-
* persistence, and extension/tool surfaces.
|
|
1999
|
+
* Resolve a provider OAuth token for a trusted server-side integration bridge
|
|
2000
|
+
* such as a CRM adapter or Google Picker. Callers must keep the result out of
|
|
2001
|
+
* agent, MCP, A2A, logs, persistence, and extension/tool surfaces.
|
|
1957
2002
|
*/
|
|
1958
2003
|
export async function resolveProviderApiOAuthAccessToken(
|
|
1959
2004
|
args: {
|
|
@@ -3304,7 +3349,9 @@ async function resolveWorkspaceOAuthBaseUrl(
|
|
|
3304
3349
|
auth.type === "oauth-bearer-or-basic"
|
|
3305
3350
|
? auth.workspaceProvider
|
|
3306
3351
|
: undefined;
|
|
3307
|
-
if (workspaceProvider !== "jira")
|
|
3352
|
+
if (workspaceProvider !== "jira" && workspaceProvider !== "salesforce") {
|
|
3353
|
+
return null;
|
|
3354
|
+
}
|
|
3308
3355
|
let resolved: Awaited<ReturnType<typeof resolveWorkspaceConnectionForApp>>;
|
|
3309
3356
|
try {
|
|
3310
3357
|
resolved = await resolveWorkspaceConnectionForApp({
|
|
@@ -3325,11 +3372,33 @@ async function resolveWorkspaceOAuthBaseUrl(
|
|
|
3325
3372
|
if (!resolved.available || !resolved.connection) return null;
|
|
3326
3373
|
const connectionConfig = resolved.connection.config;
|
|
3327
3374
|
if (connectionConfig.credentialMode !== "oauth") return null;
|
|
3328
|
-
const baseUrl =
|
|
3375
|
+
const baseUrl =
|
|
3376
|
+
workspaceProvider === "salesforce"
|
|
3377
|
+
? connectionConfig.salesforceInstanceUrl
|
|
3378
|
+
: connectionConfig.atlassianApiBaseUrl;
|
|
3329
3379
|
if (typeof baseUrl !== "string" || !baseUrl.trim()) return null;
|
|
3380
|
+
if (workspaceProvider === "salesforce" && !isSalesforceInstanceUrl(baseUrl)) {
|
|
3381
|
+
return null;
|
|
3382
|
+
}
|
|
3330
3383
|
return baseUrl.replace(/\/+$/, "");
|
|
3331
3384
|
}
|
|
3332
3385
|
|
|
3386
|
+
function isSalesforceInstanceUrl(value: string): boolean {
|
|
3387
|
+
try {
|
|
3388
|
+
const url = new URL(value);
|
|
3389
|
+
const host = url.hostname.toLowerCase();
|
|
3390
|
+
return (
|
|
3391
|
+
url.protocol === "https:" &&
|
|
3392
|
+
!url.username &&
|
|
3393
|
+
!url.password &&
|
|
3394
|
+
!url.port &&
|
|
3395
|
+
(host === "salesforce.com" || host.endsWith(".salesforce.com"))
|
|
3396
|
+
);
|
|
3397
|
+
} catch {
|
|
3398
|
+
return false;
|
|
3399
|
+
}
|
|
3400
|
+
}
|
|
3401
|
+
|
|
3333
3402
|
async function resolvePlaceholders(
|
|
3334
3403
|
config: ProviderApiConfig,
|
|
3335
3404
|
runtime: ProviderApiRuntimeOptions,
|
|
@@ -4024,6 +4093,7 @@ async function resolveOAuthBearerToken(options: {
|
|
|
4024
4093
|
ctx: CredentialContext;
|
|
4025
4094
|
accountId?: string | null;
|
|
4026
4095
|
ownerEmail?: string | null;
|
|
4096
|
+
salesforceLoginUrl?: string | null;
|
|
4027
4097
|
}): Promise<ProviderApiResolvedCredential> {
|
|
4028
4098
|
const ownerEmail = options.ownerEmail?.trim() || options.ctx.userEmail;
|
|
4029
4099
|
const accounts = await listOAuthAccountsByOwner(
|
|
@@ -4050,6 +4120,7 @@ async function resolveOAuthBearerToken(options: {
|
|
|
4050
4120
|
accountId: account.accountId,
|
|
4051
4121
|
ownerEmail,
|
|
4052
4122
|
tokens,
|
|
4123
|
+
salesforceLoginUrl: options.salesforceLoginUrl,
|
|
4053
4124
|
});
|
|
4054
4125
|
return {
|
|
4055
4126
|
key: `${options.auth.oauthProvider.toUpperCase()}_OAUTH_TOKEN`,
|
|
@@ -4126,6 +4197,11 @@ async function resolveOptionalConnectionBoundOAuthBearerToken(options: {
|
|
|
4126
4197
|
ctx: options.ctx,
|
|
4127
4198
|
accountId: connectionAccountId,
|
|
4128
4199
|
ownerEmail: resolved.connection.ownerEmail,
|
|
4200
|
+
salesforceLoginUrl:
|
|
4201
|
+
options.auth.oauthProvider === "salesforce" &&
|
|
4202
|
+
typeof resolved.connection.config?.salesforceLoginUrl === "string"
|
|
4203
|
+
? resolved.connection.config.salesforceLoginUrl
|
|
4204
|
+
: null,
|
|
4129
4205
|
});
|
|
4130
4206
|
return {
|
|
4131
4207
|
...credential,
|
|
@@ -4139,6 +4215,7 @@ async function getValidOAuthAccessToken(options: {
|
|
|
4139
4215
|
accountId: string;
|
|
4140
4216
|
ownerEmail: string;
|
|
4141
4217
|
tokens: OAuthTokens;
|
|
4218
|
+
salesforceLoginUrl?: string | null;
|
|
4142
4219
|
}): Promise<string> {
|
|
4143
4220
|
const accessToken =
|
|
4144
4221
|
options.tokens.access_token ?? options.tokens.accessToken ?? "";
|
|
@@ -4177,6 +4254,9 @@ async function getValidOAuthAccessToken(options: {
|
|
|
4177
4254
|
if (options.oauthProvider === "hubspot") {
|
|
4178
4255
|
return refreshHubSpotOAuthToken(options, refreshToken);
|
|
4179
4256
|
}
|
|
4257
|
+
if (options.oauthProvider === "salesforce") {
|
|
4258
|
+
return refreshSalesforceOAuthToken(options, refreshToken);
|
|
4259
|
+
}
|
|
4180
4260
|
if (options.oauthProvider === "jira") {
|
|
4181
4261
|
return refreshJiraOAuthToken(options, refreshToken);
|
|
4182
4262
|
}
|
|
@@ -4484,6 +4564,102 @@ async function refreshHubSpotOAuthToken(
|
|
|
4484
4564
|
return data.access_token;
|
|
4485
4565
|
}
|
|
4486
4566
|
|
|
4567
|
+
async function refreshSalesforceOAuthToken(
|
|
4568
|
+
options: {
|
|
4569
|
+
oauthProvider: string;
|
|
4570
|
+
accountId: string;
|
|
4571
|
+
ownerEmail: string;
|
|
4572
|
+
tokens: OAuthTokens;
|
|
4573
|
+
salesforceLoginUrl?: string | null;
|
|
4574
|
+
},
|
|
4575
|
+
refreshToken: string,
|
|
4576
|
+
): Promise<string> {
|
|
4577
|
+
const credentials =
|
|
4578
|
+
await resolveOAuthClientCredentialCandidates("SALESFORCE");
|
|
4579
|
+
if (!credentials.length) {
|
|
4580
|
+
throw new Error(
|
|
4581
|
+
"SALESFORCE_CLIENT_ID/SECRET not set for Salesforce OAuth refresh.",
|
|
4582
|
+
);
|
|
4583
|
+
}
|
|
4584
|
+
|
|
4585
|
+
let response: Response | null = null;
|
|
4586
|
+
let data: {
|
|
4587
|
+
access_token?: string;
|
|
4588
|
+
refresh_token?: string;
|
|
4589
|
+
expires_in?: number;
|
|
4590
|
+
token_type?: string;
|
|
4591
|
+
} = {};
|
|
4592
|
+
for (const credential of credentials) {
|
|
4593
|
+
const result = await fetchBoundedOAuthRefreshJson<{
|
|
4594
|
+
access_token?: string;
|
|
4595
|
+
refresh_token?: string;
|
|
4596
|
+
expires_in?: number;
|
|
4597
|
+
token_type?: string;
|
|
4598
|
+
}>(
|
|
4599
|
+
salesforceOAuthRefreshUrl(options.salesforceLoginUrl),
|
|
4600
|
+
{
|
|
4601
|
+
method: "POST",
|
|
4602
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
4603
|
+
body: new URLSearchParams({
|
|
4604
|
+
grant_type: "refresh_token",
|
|
4605
|
+
client_id: credential.clientId,
|
|
4606
|
+
client_secret: credential.clientSecret,
|
|
4607
|
+
refresh_token: refreshToken,
|
|
4608
|
+
}),
|
|
4609
|
+
},
|
|
4610
|
+
"Salesforce",
|
|
4611
|
+
);
|
|
4612
|
+
response = result.response;
|
|
4613
|
+
data = result.data;
|
|
4614
|
+
if (response.ok && data.access_token) break;
|
|
4615
|
+
}
|
|
4616
|
+
|
|
4617
|
+
if (!response?.ok || !data.access_token) {
|
|
4618
|
+
throw new Error(
|
|
4619
|
+
`Salesforce OAuth refresh failed (${response?.status ?? 0}).`,
|
|
4620
|
+
);
|
|
4621
|
+
}
|
|
4622
|
+
const updated = {
|
|
4623
|
+
...options.tokens,
|
|
4624
|
+
access_token: data.access_token,
|
|
4625
|
+
refresh_token: data.refresh_token ?? refreshToken,
|
|
4626
|
+
token_type: data.token_type ?? options.tokens.token_type,
|
|
4627
|
+
...(Number.isFinite(data.expires_in) && (data.expires_in ?? 0) > 0
|
|
4628
|
+
? { expiry_date: Date.now() + (data.expires_in as number) * 1_000 }
|
|
4629
|
+
: {}),
|
|
4630
|
+
};
|
|
4631
|
+
await saveOAuthTokens(
|
|
4632
|
+
options.oauthProvider,
|
|
4633
|
+
options.accountId,
|
|
4634
|
+
updated as unknown as Record<string, unknown>,
|
|
4635
|
+
options.ownerEmail,
|
|
4636
|
+
);
|
|
4637
|
+
return data.access_token;
|
|
4638
|
+
}
|
|
4639
|
+
|
|
4640
|
+
function salesforceOAuthRefreshUrl(value: string | null | undefined): string {
|
|
4641
|
+
const loginUrl = value?.trim() || "https://login.salesforce.com";
|
|
4642
|
+
try {
|
|
4643
|
+
const url = new URL(loginUrl);
|
|
4644
|
+
if (
|
|
4645
|
+
url.protocol !== "https:" ||
|
|
4646
|
+
url.username ||
|
|
4647
|
+
url.password ||
|
|
4648
|
+
url.port ||
|
|
4649
|
+
url.pathname !== "/" ||
|
|
4650
|
+
url.search ||
|
|
4651
|
+
url.hash ||
|
|
4652
|
+
(url.hostname !== "login.salesforce.com" &&
|
|
4653
|
+
url.hostname !== "test.salesforce.com")
|
|
4654
|
+
) {
|
|
4655
|
+
throw new Error("Invalid Salesforce OAuth login URL.");
|
|
4656
|
+
}
|
|
4657
|
+
return `${url.origin}/services/oauth2/token`;
|
|
4658
|
+
} catch {
|
|
4659
|
+
throw new Error("Invalid Salesforce OAuth login URL.");
|
|
4660
|
+
}
|
|
4661
|
+
}
|
|
4662
|
+
|
|
4487
4663
|
async function refreshJiraOAuthToken(
|
|
4488
4664
|
options: {
|
|
4489
4665
|
oauthProvider: string;
|
|
@@ -4796,6 +4972,15 @@ async function resolveOAuthClientCredentialCandidates(
|
|
|
4796
4972
|
].filter((value): value is { clientId: string; clientSecret: string } =>
|
|
4797
4973
|
Boolean(value),
|
|
4798
4974
|
);
|
|
4975
|
+
if (provider === "SALESFORCE") {
|
|
4976
|
+
const [consumerKey, consumerSecret] = await Promise.all([
|
|
4977
|
+
resolveSecret("SALESFORCE_CONSUMER_KEY"),
|
|
4978
|
+
resolveSecret("SALESFORCE_CONSUMER_SECRET"),
|
|
4979
|
+
]);
|
|
4980
|
+
if (consumerKey && consumerSecret) {
|
|
4981
|
+
candidates.push({ clientId: consumerKey, clientSecret: consumerSecret });
|
|
4982
|
+
}
|
|
4983
|
+
}
|
|
4799
4984
|
const seen = new Set<string>();
|
|
4800
4985
|
return candidates.filter((candidate) => {
|
|
4801
4986
|
if (seen.has(candidate.clientId)) return false;
|
|
@@ -48,6 +48,14 @@ export function registerFrameworkSecrets(): void {
|
|
|
48
48
|
docsUrl:
|
|
49
49
|
"https://developers.hubspot.com/docs/apps/developer-platform/build-apps/authentication/oauth/oauth-quickstart-guide",
|
|
50
50
|
},
|
|
51
|
+
{
|
|
52
|
+
id: "salesforce",
|
|
53
|
+
credentialPrefix: "SALESFORCE",
|
|
54
|
+
oauthProvider: "salesforce",
|
|
55
|
+
label: "Salesforce",
|
|
56
|
+
docsUrl:
|
|
57
|
+
"https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/intro_understanding_web_server_oauth_flow.htm",
|
|
58
|
+
},
|
|
51
59
|
{
|
|
52
60
|
id: "jira",
|
|
53
61
|
credentialPrefix: "JIRA",
|
|
@@ -97,6 +97,15 @@ Convert natural language to 5-field cron format:
|
|
|
97
97
|
- "every hour" → \`0 * * * *\`
|
|
98
98
|
- "every monday at 9am" → \`0 9 * * 1\`
|
|
99
99
|
|
|
100
|
+
When a recurring job needs a connected MCP, discover the exact MCP tool names
|
|
101
|
+
available in the current user/org context and pass them in the create call's
|
|
102
|
+
\`mcpTools\` array. Bind only the tools the job needs; do not put an MCP URL,
|
|
103
|
+
OAuth token, or arbitrary endpoint in the instructions. The scheduler resolves
|
|
104
|
+
the selected tools with the job owner's existing connector grant and fails
|
|
105
|
+
clearly if a connector is revoked or a selected tool disappears. For imports,
|
|
106
|
+
normalize the provider response and call the app's bounded idempotent import
|
|
107
|
+
action once with the full batch rather than issuing one write per item.
|
|
108
|
+
|
|
100
109
|
#### Suggesting "Save as automation"
|
|
101
110
|
|
|
102
111
|
When you finish a task that has obvious recurring value — daily inbox triage, weekly metrics summaries, archive sweeps, status digests, anything the user would plausibly want re-run on a fresh cadence — close the response with ONE short line offering to save it. Examples:
|
|
@@ -74,7 +74,7 @@ Keep \`create-extension\` payloads compact enough to finish quickly. For complex
|
|
|
74
74
|
|
|
75
75
|
Generated UI content can use appAction(), appFetch(), dbQuery(), extensionFetch(), extensionData, agentNative.ui.output(value, opts?), and agentNative.chat.send(...)/sendToAgentChat(...). Use appAction() for app data writes, and dbQuery() only for read-only inspection of known app SQL tables. It can receive chat inputs through slotContext/window.onSlotContext. Use agentNative.ui.output for passive current values from knobs, sliders, selections, and controls; it writes application state at \`inline-ui:<extensionId>:output\` scoped to the inline extension id returned by \`render-inline-extension\` or \`show-extension-inline\`. When the user later says "use that value", "apply the current setting", or similar, read it with \`readAppState("inline-ui:<id>:output")\` instead of asking them to send it again. Use agentNative.chat.send for visible submit/apply actions that should put a message into chat. Transient extensionData is browser-local and not agent-readable, synced, promoted, or garbage-collected; use application_state/appFetch, appAction, ui.output, or chat.send for anything the agent or app must observe. Use semantic Tailwind classes like bg-background, text-foreground, bg-primary, border-border, and text-muted-foreground so the UI inherits the parent app theme.
|
|
76
76
|
|
|
77
|
-
If the user asks to change, edit, fix, style, rename, or add behavior to an existing extension/widget/dashboard/calculator/mini-app, use the current extension id from \`<current-screen>\` or \`<current-url>\` when present. Call \`get-extension\` only if you need to inspect its content, then \`update-extension\` with
|
|
77
|
+
If the user asks to change, edit, fix, style, rename, or add behavior to an existing extension/widget/dashboard/calculator/mini-app, use the current extension id from \`<current-screen>\` or \`<current-url>\` when present. Call \`get-extension\` only if you need to inspect its content, then call \`update-extension\` with exactly \`id\`, \`operation\`, and \`payloadJson\`; encode the operation payload as a JSON string and never send empty placeholder fields. After one content read, keep the body in working memory and use \`operation="edit"\` with focused \`edits\`/\`patches\` inside \`payloadJson\`; do not loop on repeated \`get-extension\` + \`run-code\` string scans before writing. For a data-only repair, preserve the existing layout, CSS, copy, and interactions. Use \`operation="replace"\` only when the user explicitly requests a broad visual rewrite or supplies a complete replacement body. Use \`operation="metadata"\` for name/description/icon, and use \`set-resource-visibility\` for sharing changes. If a focused patch fails, read the current body and change the target rather than retrying identical arguments. Use \`list-extensions\` only when no current id/name is available. Existing extension edits are SQL data updates, not source-code changes, even when the request says "change the UI" or "fix this". Do **NOT** call \`connect-builder\` for existing extension edits.
|
|
78
78
|
|
|
79
79
|
In Act mode, when in doubt — if the request asks for a new small interactive utility and does not need reuse, choose \`render-inline-extension\`; if it mentions saving/reuse or asks for an extension/widget/dashboard/calculator/mini-app, choose \`create-extension\`. If it references an existing one or the current extension page, choose \`update-extension\`. Do **not** preface the call with planning text like "let me build the dashboard…" — just call the right extension action directly.
|
|
80
80
|
|
|
@@ -115,7 +115,7 @@ Keep the first \`create-extension\` call compact and working. If the request is
|
|
|
115
115
|
|
|
116
116
|
Generated UI can read chat inputs from slotContext/window.onSlotContext, see/update app state through appFetch/appAction, use extensionData, record passive current values through agentNative.ui.output(value, opts?), and send visible results through agentNative.chat.send(...) or sendToAgentChat(...). ui.output writes \`inline-ui:<extensionId>:output\` in application state; when the user asks to use the current slider/selection/value, read \`readAppState("inline-ui:<id>:output")\`. Transient extensionData is browser-local only, so do not rely on it for values the agent or app must observe. Use semantic Tailwind theme classes.
|
|
117
117
|
|
|
118
|
-
If the user asks to change, edit, fix, style, rename, or add behavior to an existing extension/widget/dashboard/calculator/mini-app, use the current extension id from \`<current-screen>\` or \`<current-url>\` when present. Call \`get-extension\` only if you need to inspect its content, then \`update-extension\` with
|
|
118
|
+
If the user asks to change, edit, fix, style, rename, or add behavior to an existing extension/widget/dashboard/calculator/mini-app, use the current extension id from \`<current-screen>\` or \`<current-url>\` when present. Call \`get-extension\` only if you need to inspect its content, then call \`update-extension\` with exactly \`id\`, \`operation\`, and \`payloadJson\`; encode the operation payload as a JSON string and never send empty placeholder fields. After one content read, use \`operation="edit"\` with focused \`edits\`/\`patches\` inside \`payloadJson\`; do not repeatedly re-read and scan the same HTML with \`run-code\` before writing. For a data-only repair, preserve the existing layout, CSS, copy, and interactions. Use \`operation="replace"\` only when the user explicitly requests a broad visual rewrite or supplies a complete replacement body. Use \`operation="metadata"\` for name/description/icon, and use \`set-resource-visibility\` for sharing changes. If a focused patch fails, read the current body and change the target rather than retrying identical arguments. Use \`list-extensions\` only when no current id/name is available. Existing extension edits are SQL data updates, not source-code changes. Do NOT call \`connect-builder\` for them.
|
|
119
119
|
|
|
120
120
|
For existing extensions, use \`get-extension\` or \`update-extension\` directly when \`<current-screen>\` or \`<current-url>\` provides an \`extensionId\`. Use \`list-extensions\` only to browse or resolve an unknown name. Use \`hide-extension\` when the user wants a shared extension removed only from their own view. Do not query the legacy \`tools\` table directly.
|
|
121
121
|
|
|
@@ -124,6 +124,7 @@ import {
|
|
|
124
124
|
verifyInternalToken,
|
|
125
125
|
extractBearerToken,
|
|
126
126
|
} from "../integrations/internal-token.js";
|
|
127
|
+
import type { RecurringJobContext } from "../jobs/scheduler.js";
|
|
127
128
|
import {
|
|
128
129
|
McpClientManager,
|
|
129
130
|
loadMcpConfig,
|
|
@@ -575,6 +576,22 @@ export function createAgentChatPlugin(
|
|
|
575
576
|
}
|
|
576
577
|
setGlobalMcpManager(mcpManager);
|
|
577
578
|
const mcpActionEntries = mcpToolsToActionEntries(mcpManager);
|
|
579
|
+
const getJobMcpActionEntries = (
|
|
580
|
+
job?: RecurringJobContext,
|
|
581
|
+
): Record<string, ActionEntry> => {
|
|
582
|
+
const requested = job?.meta.mcpTools ?? [];
|
|
583
|
+
if (requested.length === 0) return {};
|
|
584
|
+
const entries = mcpToolsToActionEntries(mcpManager, {
|
|
585
|
+
toolNames: requested,
|
|
586
|
+
});
|
|
587
|
+
const missing = requested.filter((toolName) => !entries[toolName]);
|
|
588
|
+
if (missing.length > 0) {
|
|
589
|
+
throw new Error(
|
|
590
|
+
`Configured MCP tools are unavailable in this run: ${missing.join(", ")}. Reconnect the MCP server or update the job's capability list.`,
|
|
591
|
+
);
|
|
592
|
+
}
|
|
593
|
+
return entries;
|
|
594
|
+
};
|
|
578
595
|
|
|
579
596
|
// Mount status + management routes so the settings UI can list / add /
|
|
580
597
|
// remove remote MCP servers and hot-reload the running manager.
|
|
@@ -2632,6 +2649,7 @@ export function createAgentChatPlugin(
|
|
|
2632
2649
|
// through the settings UI). getEngineTools() in production-agent re-reads
|
|
2633
2650
|
// the registry per request, so updates here propagate without restart.
|
|
2634
2651
|
mcpManager.onChange(() => {
|
|
2652
|
+
syncMcpActionEntries(mcpManager, mcpActionEntries);
|
|
2635
2653
|
syncMcpActionEntries(mcpManager, prodActions);
|
|
2636
2654
|
});
|
|
2637
2655
|
|
|
@@ -5524,7 +5542,7 @@ Non-code requests are still fine on this surface: read data, navigate the UI, su
|
|
|
5524
5542
|
const { processRecurringJobs } = await import("../jobs/scheduler.js");
|
|
5525
5543
|
|
|
5526
5544
|
const schedulerDeps = {
|
|
5527
|
-
getActions: () => ({
|
|
5545
|
+
getActions: (job?: RecurringJobContext) => ({
|
|
5528
5546
|
...templateScripts,
|
|
5529
5547
|
...resourceScripts,
|
|
5530
5548
|
...docsScripts,
|
|
@@ -5537,6 +5555,7 @@ Non-code requests are still fine on this surface: read data, navigate the UI, su
|
|
|
5537
5555
|
...fetchTool,
|
|
5538
5556
|
...webSearchTool,
|
|
5539
5557
|
...toolActions,
|
|
5558
|
+
...getJobMcpActionEntries(job),
|
|
5540
5559
|
}),
|
|
5541
5560
|
getSystemPrompt: async (owner: string) => {
|
|
5542
5561
|
const resources = await loadResourcesForPrompt(
|
|
@@ -5557,10 +5576,11 @@ Non-code requests are still fine on this surface: read data, navigate the UI, su
|
|
|
5557
5576
|
// first request on the same compact surface as interactive chat
|
|
5558
5577
|
// instead of the full jobTools/automationTools/notificationTools/
|
|
5559
5578
|
// fetchTool/webSearchTool/toolActions catalog every tick.
|
|
5560
|
-
getInitialToolNames: () => [
|
|
5579
|
+
getInitialToolNames: (job?: RecurringJobContext) => [
|
|
5561
5580
|
...effectiveInitialToolNames,
|
|
5562
5581
|
"manage-jobs",
|
|
5563
5582
|
"manage-progress",
|
|
5583
|
+
...(job?.meta.mcpTools ?? []),
|
|
5564
5584
|
],
|
|
5565
5585
|
apiKey: options?.apiKey,
|
|
5566
5586
|
model: options?.model,
|
|
@@ -75,6 +75,9 @@ export function readDeployCredentialEnv(key: string): string | undefined {
|
|
|
75
75
|
|
|
76
76
|
const APP_PROVIDED_DEPLOY_CREDENTIAL_KEYS = new Set([
|
|
77
77
|
"ANTHROPIC_API_KEY",
|
|
78
|
+
"EMAIL_FROM",
|
|
79
|
+
"EMAIL_INBOUND_WEBHOOK_SECRET",
|
|
80
|
+
"EMAIL_AGENT_ADDRESS",
|
|
78
81
|
"OPENAI_API_KEY",
|
|
79
82
|
"OPENAI_BASE_URL",
|
|
80
83
|
"OPENROUTER_API_KEY",
|
|
@@ -84,6 +87,8 @@ const APP_PROVIDED_DEPLOY_CREDENTIAL_KEYS = new Set([
|
|
|
84
87
|
"GROQ_API_KEY",
|
|
85
88
|
"MISTRAL_API_KEY",
|
|
86
89
|
"COHERE_API_KEY",
|
|
90
|
+
"RESEND_API_KEY",
|
|
91
|
+
"SENDGRID_API_KEY",
|
|
87
92
|
]);
|
|
88
93
|
|
|
89
94
|
function isAppProvidedDeployCredentialKey(key: string | undefined): boolean {
|
|
@@ -97,9 +102,10 @@ function isAppProvidedDeployCredentialKey(key: string | undefined): boolean {
|
|
|
97
102
|
* identity-bearing provider keys so one deploy key does not silently
|
|
98
103
|
* impersonate another tenant. App-provided service credentials are different:
|
|
99
104
|
* they configure the deployed app itself rather than identifying a user. This
|
|
100
|
-
* includes LLM keys that let the app developer pay for model usage
|
|
101
|
-
*
|
|
102
|
-
*
|
|
105
|
+
* includes LLM keys that let the app developer pay for model usage, email
|
|
106
|
+
* transport configuration owned by the deployment, and OAuth client
|
|
107
|
+
* credentials whose per-user identity remains in scoped OAuth tokens. Key-aware
|
|
108
|
+
* callers may use those env vars.
|
|
103
109
|
*
|
|
104
110
|
* @deprecated Use `canUseDeployCredentialFallbackForRequest()` for generic
|
|
105
111
|
* provider secrets. This stricter helper remains for legacy call sites with
|