@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
|
@@ -623,7 +623,7 @@ export function createExtensionActionEntries(): Record<string, ActionEntry> {
|
|
|
623
623
|
"update-extension": {
|
|
624
624
|
tool: {
|
|
625
625
|
description:
|
|
626
|
-
'Update an existing sandboxed Alpine.js mini-app extension.
|
|
626
|
+
'Update an existing sandboxed Alpine.js mini-app extension. Pass exactly three fields: `id`, `operation`, and `payloadJson`. `payloadJson` is a JSON object encoded as a string so model gateways cannot fill its optional members with invalid empty placeholders. For operation="edit", pass {"edits":[...]} or {"patches":[...]} and optional format=true. For operation="replace", pass exactly one of content, contentFromAttachment, or contentFromWorkspaceFile; use this operation only for a user-requested broad visual rewrite or complete replacement body. For operation="metadata", pass name, description, or icon. Change sharing through set-resource-visibility instead. If the user is viewing the extension, use the extensionId from <current-screen> or <current-url> directly.',
|
|
627
627
|
parameters: {
|
|
628
628
|
type: "object",
|
|
629
629
|
properties: {
|
|
@@ -632,72 +632,35 @@ export function createExtensionActionEntries(): Record<string, ActionEntry> {
|
|
|
632
632
|
description:
|
|
633
633
|
"Extension id to update. Prefer the extensionId from <current-screen> or <current-url> for the current extension.",
|
|
634
634
|
},
|
|
635
|
-
|
|
636
|
-
type: "string",
|
|
637
|
-
description: "Optional new display name.",
|
|
638
|
-
},
|
|
639
|
-
description: {
|
|
640
|
-
type: "string",
|
|
641
|
-
description: "Optional new description.",
|
|
642
|
-
},
|
|
643
|
-
content: {
|
|
644
|
-
type: "string",
|
|
645
|
-
description:
|
|
646
|
-
"Optional full replacement Alpine.js HTML body snippet.",
|
|
647
|
-
},
|
|
648
|
-
contentFromAttachment: {
|
|
635
|
+
operation: {
|
|
649
636
|
type: "string",
|
|
637
|
+
enum: ["edit", "replace", "metadata"],
|
|
650
638
|
description:
|
|
651
|
-
'
|
|
639
|
+
'The single update mode: "edit" for focused patches/edits, "replace" for an explicitly authorized complete body replacement, or "metadata" for name/description/icon.',
|
|
652
640
|
},
|
|
653
|
-
|
|
641
|
+
payloadJson: {
|
|
654
642
|
type: "string",
|
|
643
|
+
minLength: 2,
|
|
655
644
|
description:
|
|
656
|
-
'
|
|
657
|
-
},
|
|
658
|
-
allowFullReplacement: {
|
|
659
|
-
type: "boolean",
|
|
660
|
-
description:
|
|
661
|
-
"Explicitly allow replacing the entire existing body. Omit or set false for data-only repairs so the existing visual design is protected. Use true only when the user explicitly requested a broad visual rewrite or supplied a complete replacement body.",
|
|
662
|
-
},
|
|
663
|
-
patches: {
|
|
664
|
-
anyOf: [
|
|
665
|
-
{ type: "string" },
|
|
666
|
-
{ type: "array", items: { type: "object" } },
|
|
667
|
-
],
|
|
668
|
-
description:
|
|
669
|
-
'Optional patches as a JSON-encoded string or native array of { "find": "...", "replace": "...", "all"?: true, "expectedMatches"?: 1, "required"?: true } objects. Missing required targets fail instead of silently no-oping.',
|
|
670
|
-
},
|
|
671
|
-
edits: {
|
|
672
|
-
anyOf: [
|
|
673
|
-
{ type: "string" },
|
|
674
|
-
{ type: "array", items: { type: "object" } },
|
|
675
|
-
],
|
|
676
|
-
description:
|
|
677
|
-
'Preferred optional granular edit operations as a JSON-encoded string or native array. Examples: { "op": "insert-after", "marker": "<!-- section:metrics -->", "content": "..." }, { "op": "replace-section", "section": "npm-chart", "content": "..." }, { "op": "wrap-section", "section": "charts", "before": "<div>", "after": "</div>" }, { "op": "regex-replace", "pattern": "...", "replace": "...", "expectedMatches": 1 }.',
|
|
678
|
-
},
|
|
679
|
-
format: {
|
|
680
|
-
type: "boolean",
|
|
681
|
-
description:
|
|
682
|
-
"When true, format the final extension HTML with Prettier after applying content, patches, and edits.",
|
|
683
|
-
},
|
|
684
|
-
icon: {
|
|
685
|
-
type: "string",
|
|
686
|
-
description: "Optional icon name or short label.",
|
|
687
|
-
},
|
|
688
|
-
visibility: {
|
|
689
|
-
type: "string",
|
|
690
|
-
description:
|
|
691
|
-
"Optional sharing visibility. Public extension sharing is not supported; use private or org.",
|
|
692
|
-
enum: ["private", "org"],
|
|
645
|
+
'A non-empty JSON object encoded as a string. edit example: {"edits":[{"op":"replace","find":"old","replace":"new"}],"format":true}. replace example: {"contentFromAttachment":"latest"}. metadata example: {"name":"New name"}.',
|
|
693
646
|
},
|
|
694
647
|
},
|
|
695
|
-
required: ["id"],
|
|
648
|
+
required: ["id", "operation", "payloadJson"],
|
|
649
|
+
additionalProperties: false,
|
|
696
650
|
},
|
|
697
651
|
},
|
|
698
652
|
run: async (args, ctx) => {
|
|
653
|
+
const normalizedUpdate = normalizeUpdateExtensionArgs(args);
|
|
654
|
+
if ("error" in normalizedUpdate) return normalizedUpdate.error;
|
|
655
|
+
args = normalizedUpdate.args;
|
|
699
656
|
const id = String(args?.id ?? "").trim();
|
|
700
657
|
if (!id) return "Error: id is required.";
|
|
658
|
+
if (
|
|
659
|
+
args?.name !== undefined &&
|
|
660
|
+
(typeof args.name !== "string" || args.name.trim().length === 0)
|
|
661
|
+
) {
|
|
662
|
+
return "Error: extension name must be a non-empty string. No changes were applied.";
|
|
663
|
+
}
|
|
701
664
|
const localMessage = await localExtensionEditMessage(id);
|
|
702
665
|
if (localMessage) return localMessage;
|
|
703
666
|
|
|
@@ -722,11 +685,19 @@ export function createExtensionActionEntries(): Record<string, ActionEntry> {
|
|
|
722
685
|
});
|
|
723
686
|
}
|
|
724
687
|
|
|
688
|
+
const attachmentRef =
|
|
689
|
+
typeof args?.contentFromAttachment === "string"
|
|
690
|
+
? args.contentFromAttachment.trim()
|
|
691
|
+
: "";
|
|
692
|
+
const workspaceFileRef =
|
|
693
|
+
typeof args?.contentFromWorkspaceFile === "string"
|
|
694
|
+
? args.contentFromWorkspaceFile.trim()
|
|
695
|
+
: "";
|
|
725
696
|
const fullReplacementRequested =
|
|
726
697
|
(typeof args?.content === "string" &&
|
|
727
698
|
args.content.trim().length > 0) ||
|
|
728
|
-
|
|
729
|
-
|
|
699
|
+
attachmentRef.length > 0 ||
|
|
700
|
+
workspaceFileRef.length > 0;
|
|
730
701
|
if (
|
|
731
702
|
fullReplacementRequested &&
|
|
732
703
|
!coerceBoolean(args?.allowFullReplacement)
|
|
@@ -748,8 +719,7 @@ export function createExtensionActionEntries(): Record<string, ActionEntry> {
|
|
|
748
719
|
: undefined;
|
|
749
720
|
if (
|
|
750
721
|
replacementContent === undefined &&
|
|
751
|
-
(
|
|
752
|
-
args?.contentFromWorkspaceFile !== undefined)
|
|
722
|
+
(attachmentRef.length > 0 || workspaceFileRef.length > 0)
|
|
753
723
|
) {
|
|
754
724
|
const resolved = await resolveExtensionContentAsync(args, ctx);
|
|
755
725
|
if ("error" in resolved) return resolved.error;
|
|
@@ -757,20 +727,20 @@ export function createExtensionActionEntries(): Record<string, ActionEntry> {
|
|
|
757
727
|
}
|
|
758
728
|
|
|
759
729
|
let result = null;
|
|
730
|
+
const patches = parsePatches((args as any).patches);
|
|
731
|
+
if (args?.patches !== undefined && !patches) {
|
|
732
|
+
return "Error: patches must be a JSON array of { find, replace } objects.";
|
|
733
|
+
}
|
|
734
|
+
const edits = parseEdits((args as any).edits);
|
|
735
|
+
if (args?.edits !== undefined && !edits) {
|
|
736
|
+
return "Error: edits must be a JSON array of supported extension edit operations.";
|
|
737
|
+
}
|
|
760
738
|
const hasContentUpdate =
|
|
761
739
|
replacementContent !== undefined ||
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
args?.format
|
|
740
|
+
(patches?.length ?? 0) > 0 ||
|
|
741
|
+
(edits?.length ?? 0) > 0 ||
|
|
742
|
+
coerceBoolean(args?.format);
|
|
765
743
|
if (hasContentUpdate) {
|
|
766
|
-
const patches = parsePatches((args as any).patches);
|
|
767
|
-
if (args?.patches !== undefined && !patches) {
|
|
768
|
-
return "Error: patches must be a JSON array of { find, replace } objects.";
|
|
769
|
-
}
|
|
770
|
-
const edits = parseEdits((args as any).edits);
|
|
771
|
-
if (args?.edits !== undefined && !edits) {
|
|
772
|
-
return "Error: edits must be a JSON array of supported extension edit operations.";
|
|
773
|
-
}
|
|
774
744
|
try {
|
|
775
745
|
result = await updateExtensionContent(id, {
|
|
776
746
|
content: replacementContent,
|
|
@@ -806,13 +776,15 @@ export function createExtensionActionEntries(): Record<string, ActionEntry> {
|
|
|
806
776
|
meta.description = String(args.description).trim();
|
|
807
777
|
}
|
|
808
778
|
if (args?.icon !== undefined) meta.icon = String(args.icon);
|
|
809
|
-
if (args?.visibility !== undefined)
|
|
779
|
+
if (args?.visibility !== undefined)
|
|
810
780
|
meta.visibility = String(args.visibility);
|
|
811
|
-
}
|
|
812
781
|
if (Object.keys(meta).length > 0) {
|
|
813
782
|
result = await updateExtension(id, meta as any);
|
|
814
783
|
}
|
|
815
784
|
|
|
785
|
+
if (!result && !hasContentUpdate && Object.keys(meta).length === 0) {
|
|
786
|
+
return "Error: update-extension received no actual changes. Choose one operation and provide a non-empty payloadJson object; empty placeholder fields are not an update.";
|
|
787
|
+
}
|
|
816
788
|
if (!result) result = await getExtension(id);
|
|
817
789
|
if (!result) return `Error: extension not found: ${id}`;
|
|
818
790
|
const hiddenIds = await getHiddenExtensionIdsForCurrentUser();
|
|
@@ -1444,7 +1416,7 @@ async function summarizeExtensionForAgentRead(
|
|
|
1444
1416
|
reason: "unchanged-content-already-returned-this-run",
|
|
1445
1417
|
contentHash: fingerprint,
|
|
1446
1418
|
contentLength: row.content.length,
|
|
1447
|
-
next:
|
|
1419
|
+
next: 'Use the content already returned earlier in this run and call update-extension with operation="edit" plus focused edits/patches inside payloadJson. Set forceContent=true only if you truly need the full body again.',
|
|
1448
1420
|
},
|
|
1449
1421
|
};
|
|
1450
1422
|
}
|
|
@@ -1746,6 +1718,160 @@ function coerceBoolean(value: unknown): boolean {
|
|
|
1746
1718
|
return value === true || value === "true";
|
|
1747
1719
|
}
|
|
1748
1720
|
|
|
1721
|
+
function normalizeUpdateExtensionArgs(
|
|
1722
|
+
args: any,
|
|
1723
|
+
): { args: Record<string, unknown> } | { error: string } {
|
|
1724
|
+
const hasCompactContract =
|
|
1725
|
+
args?.operation !== undefined || args?.payloadJson !== undefined;
|
|
1726
|
+
if (!hasCompactContract) {
|
|
1727
|
+
const legacyArgs = { ...((args ?? {}) as Record<string, unknown>) };
|
|
1728
|
+
const hasInvalidPlaceholderSignal =
|
|
1729
|
+
(typeof legacyArgs.visibility === "string" &&
|
|
1730
|
+
legacyArgs.visibility.trim().length === 0) ||
|
|
1731
|
+
[legacyArgs.patches, legacyArgs.edits].some(
|
|
1732
|
+
(value) =>
|
|
1733
|
+
value !== null &&
|
|
1734
|
+
typeof value === "object" &&
|
|
1735
|
+
(Array.isArray(value)
|
|
1736
|
+
? value.length > 0 &&
|
|
1737
|
+
value.every(
|
|
1738
|
+
(item) =>
|
|
1739
|
+
item !== null &&
|
|
1740
|
+
typeof item === "object" &&
|
|
1741
|
+
!Array.isArray(item) &&
|
|
1742
|
+
Object.keys(item).length === 0,
|
|
1743
|
+
)
|
|
1744
|
+
: Object.keys(value).length === 0),
|
|
1745
|
+
);
|
|
1746
|
+
if (hasInvalidPlaceholderSignal) {
|
|
1747
|
+
for (const [key, value] of Object.entries(legacyArgs)) {
|
|
1748
|
+
if (key === "id") continue;
|
|
1749
|
+
const empty =
|
|
1750
|
+
value === false ||
|
|
1751
|
+
value === null ||
|
|
1752
|
+
(typeof value === "string" && value.trim().length === 0) ||
|
|
1753
|
+
(Array.isArray(value) &&
|
|
1754
|
+
(value.length === 0 ||
|
|
1755
|
+
value.every(
|
|
1756
|
+
(item) =>
|
|
1757
|
+
item !== null &&
|
|
1758
|
+
typeof item === "object" &&
|
|
1759
|
+
!Array.isArray(item) &&
|
|
1760
|
+
Object.keys(item).length === 0,
|
|
1761
|
+
))) ||
|
|
1762
|
+
(typeof value === "object" &&
|
|
1763
|
+
value !== null &&
|
|
1764
|
+
!Array.isArray(value) &&
|
|
1765
|
+
Object.keys(value).length === 0);
|
|
1766
|
+
if (empty) delete legacyArgs[key];
|
|
1767
|
+
}
|
|
1768
|
+
delete legacyArgs.visibility;
|
|
1769
|
+
}
|
|
1770
|
+
return { args: legacyArgs };
|
|
1771
|
+
}
|
|
1772
|
+
|
|
1773
|
+
const operation = String(args?.operation ?? "").trim();
|
|
1774
|
+
if (!(["edit", "replace", "metadata"] as const).includes(operation as any)) {
|
|
1775
|
+
return {
|
|
1776
|
+
error:
|
|
1777
|
+
'Error: operation must be "edit", "replace", or "metadata". No changes were applied.',
|
|
1778
|
+
};
|
|
1779
|
+
}
|
|
1780
|
+
|
|
1781
|
+
let payload: unknown;
|
|
1782
|
+
try {
|
|
1783
|
+
payload = JSON.parse(String(args?.payloadJson ?? ""));
|
|
1784
|
+
} catch {
|
|
1785
|
+
return {
|
|
1786
|
+
error:
|
|
1787
|
+
"Error: payloadJson must be a valid JSON object encoded as a string. No changes were applied.",
|
|
1788
|
+
};
|
|
1789
|
+
}
|
|
1790
|
+
if (!payload || typeof payload !== "object" || Array.isArray(payload)) {
|
|
1791
|
+
return {
|
|
1792
|
+
error:
|
|
1793
|
+
"Error: payloadJson must decode to a non-empty JSON object. No changes were applied.",
|
|
1794
|
+
};
|
|
1795
|
+
}
|
|
1796
|
+
|
|
1797
|
+
const payloadRecord = payload as Record<string, unknown>;
|
|
1798
|
+
const allowedByOperation: Record<string, Set<string>> = {
|
|
1799
|
+
edit: new Set(["patches", "edits", "format"]),
|
|
1800
|
+
replace: new Set([
|
|
1801
|
+
"content",
|
|
1802
|
+
"contentFromAttachment",
|
|
1803
|
+
"contentFromWorkspaceFile",
|
|
1804
|
+
"format",
|
|
1805
|
+
]),
|
|
1806
|
+
metadata: new Set(["name", "description", "icon"]),
|
|
1807
|
+
};
|
|
1808
|
+
const unexpected = Object.keys(payloadRecord).filter(
|
|
1809
|
+
(key) => !allowedByOperation[operation].has(key),
|
|
1810
|
+
);
|
|
1811
|
+
if (unexpected.length > 0) {
|
|
1812
|
+
return {
|
|
1813
|
+
error: `Error: operation=${operation} does not accept ${unexpected.join(", ")}. No changes were applied.`,
|
|
1814
|
+
};
|
|
1815
|
+
}
|
|
1816
|
+
|
|
1817
|
+
if (operation === "edit") {
|
|
1818
|
+
const patches = parsePatches(payloadRecord.patches);
|
|
1819
|
+
const edits = parseEdits(payloadRecord.edits);
|
|
1820
|
+
const hasEdit =
|
|
1821
|
+
(patches?.length ?? 0) > 0 ||
|
|
1822
|
+
(edits?.length ?? 0) > 0 ||
|
|
1823
|
+
coerceBoolean(payloadRecord.format);
|
|
1824
|
+
if (!hasEdit) {
|
|
1825
|
+
return {
|
|
1826
|
+
error:
|
|
1827
|
+
"Error: operation=edit requires at least one valid patch/edit or format=true. No changes were applied.",
|
|
1828
|
+
};
|
|
1829
|
+
}
|
|
1830
|
+
}
|
|
1831
|
+
|
|
1832
|
+
if (operation === "replace") {
|
|
1833
|
+
const replacementSources = [
|
|
1834
|
+
payloadRecord.content,
|
|
1835
|
+
payloadRecord.contentFromAttachment,
|
|
1836
|
+
payloadRecord.contentFromWorkspaceFile,
|
|
1837
|
+
].filter((value) => typeof value === "string" && value.trim().length > 0);
|
|
1838
|
+
if (replacementSources.length !== 1) {
|
|
1839
|
+
return {
|
|
1840
|
+
error:
|
|
1841
|
+
"Error: operation=replace requires exactly one non-empty content, contentFromAttachment, or contentFromWorkspaceFile value. No changes were applied.",
|
|
1842
|
+
};
|
|
1843
|
+
}
|
|
1844
|
+
}
|
|
1845
|
+
|
|
1846
|
+
if (operation === "metadata") {
|
|
1847
|
+
const keys = Object.keys(payloadRecord);
|
|
1848
|
+
if (keys.length === 0) {
|
|
1849
|
+
return {
|
|
1850
|
+
error:
|
|
1851
|
+
"Error: operation=metadata requires name, description, or icon. No changes were applied.",
|
|
1852
|
+
};
|
|
1853
|
+
}
|
|
1854
|
+
if (
|
|
1855
|
+
payloadRecord.name !== undefined &&
|
|
1856
|
+
(typeof payloadRecord.name !== "string" ||
|
|
1857
|
+
payloadRecord.name.trim().length === 0)
|
|
1858
|
+
) {
|
|
1859
|
+
return {
|
|
1860
|
+
error:
|
|
1861
|
+
"Error: extension name must be a non-empty string. No changes were applied.",
|
|
1862
|
+
};
|
|
1863
|
+
}
|
|
1864
|
+
}
|
|
1865
|
+
|
|
1866
|
+
return {
|
|
1867
|
+
args: {
|
|
1868
|
+
id: String(args?.id ?? "").trim(),
|
|
1869
|
+
...payloadRecord,
|
|
1870
|
+
...(operation === "replace" ? { allowFullReplacement: true } : {}),
|
|
1871
|
+
},
|
|
1872
|
+
};
|
|
1873
|
+
}
|
|
1874
|
+
|
|
1749
1875
|
function parseInlineContext(
|
|
1750
1876
|
value: unknown,
|
|
1751
1877
|
): Record<string, unknown> | undefined {
|
|
@@ -46,6 +46,7 @@ export interface RecurringJobActionItem {
|
|
|
46
46
|
lastError: string | null;
|
|
47
47
|
nextRun: string | null;
|
|
48
48
|
createdBy: string | null;
|
|
49
|
+
mcpTools: string[];
|
|
49
50
|
canUpdate: boolean;
|
|
50
51
|
}
|
|
51
52
|
|
|
@@ -96,6 +97,7 @@ export default defineAction({
|
|
|
96
97
|
lastError: meta.lastError ?? null,
|
|
97
98
|
nextRun: nextRun(meta),
|
|
98
99
|
createdBy: meta.createdBy ?? null,
|
|
100
|
+
mcpTools: meta.mcpTools ?? [],
|
|
99
101
|
canUpdate,
|
|
100
102
|
});
|
|
101
103
|
}
|
|
@@ -42,6 +42,50 @@ export interface JobFrontmatter {
|
|
|
42
42
|
deliveryThreadRef?: string;
|
|
43
43
|
deliveryTenantId?: string;
|
|
44
44
|
model?: string;
|
|
45
|
+
/** Explicit MCP tool capabilities available to this background run. */
|
|
46
|
+
mcpTools?: string[];
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const MAX_JOB_MCP_TOOLS = 64;
|
|
50
|
+
const JOB_MCP_TOOL_NAME_RE = /^mcp__[^\s]+__[^\s]+$/;
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Normalize the non-secret MCP capability references persisted with a job.
|
|
54
|
+
* Tool names are opaque framework identifiers; URLs and credentials never
|
|
55
|
+
* belong in job frontmatter.
|
|
56
|
+
*/
|
|
57
|
+
export function normalizeJobMcpTools(value: unknown): string[] | undefined {
|
|
58
|
+
if (value === undefined || value === null) return undefined;
|
|
59
|
+
const parsed =
|
|
60
|
+
typeof value === "string"
|
|
61
|
+
? (() => {
|
|
62
|
+
try {
|
|
63
|
+
return JSON.parse(value);
|
|
64
|
+
} catch {
|
|
65
|
+
throw new Error("mcpTools must be a JSON array of tool names.");
|
|
66
|
+
}
|
|
67
|
+
})()
|
|
68
|
+
: value;
|
|
69
|
+
if (!Array.isArray(parsed)) {
|
|
70
|
+
throw new Error("mcpTools must be an array of MCP tool names.");
|
|
71
|
+
}
|
|
72
|
+
if (parsed.length > MAX_JOB_MCP_TOOLS) {
|
|
73
|
+
throw new Error(
|
|
74
|
+
`mcpTools may contain at most ${MAX_JOB_MCP_TOOLS} tool names.`,
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
const normalized = [...new Set(parsed)];
|
|
78
|
+
if (
|
|
79
|
+
normalized.some(
|
|
80
|
+
(toolName) =>
|
|
81
|
+
typeof toolName !== "string" || !JOB_MCP_TOOL_NAME_RE.test(toolName),
|
|
82
|
+
)
|
|
83
|
+
) {
|
|
84
|
+
throw new Error(
|
|
85
|
+
"mcpTools must contain only framework MCP tool names such as mcp__server__tool.",
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
return normalized;
|
|
45
89
|
}
|
|
46
90
|
|
|
47
91
|
const FRONTMATTER_RE = /^---\n([\s\S]*?)\n---\n?([\s\S]*)$/;
|
|
@@ -129,6 +173,14 @@ export function parseJobFrontmatter(content: string): {
|
|
|
129
173
|
case "model":
|
|
130
174
|
meta.model = value;
|
|
131
175
|
break;
|
|
176
|
+
case "mcpTools":
|
|
177
|
+
try {
|
|
178
|
+
meta.mcpTools = normalizeJobMcpTools(value);
|
|
179
|
+
} catch {
|
|
180
|
+
// Ignore malformed optional capability metadata and keep the job
|
|
181
|
+
// readable; newly-created jobs are validated before persistence.
|
|
182
|
+
}
|
|
183
|
+
break;
|
|
132
184
|
}
|
|
133
185
|
}
|
|
134
186
|
|
|
@@ -166,6 +218,8 @@ export function buildJobContent(meta: JobFrontmatter, body: string): string {
|
|
|
166
218
|
if (meta.deliveryTenantId)
|
|
167
219
|
lines.push(`deliveryTenantId: ${meta.deliveryTenantId}`);
|
|
168
220
|
if (meta.model) lines.push(`model: ${meta.model}`);
|
|
221
|
+
if (meta.mcpTools?.length)
|
|
222
|
+
lines.push(`mcpTools: ${JSON.stringify(meta.mcpTools)}`);
|
|
169
223
|
lines.push(`---`);
|
|
170
224
|
lines.push("");
|
|
171
225
|
lines.push(body);
|
|
@@ -174,8 +228,15 @@ export function buildJobContent(meta: JobFrontmatter, body: string): string {
|
|
|
174
228
|
|
|
175
229
|
// ─── Job execution ──────────────────────────────────────────────────────────
|
|
176
230
|
|
|
231
|
+
export interface RecurringJobContext {
|
|
232
|
+
name: string;
|
|
233
|
+
meta: JobFrontmatter;
|
|
234
|
+
body: string;
|
|
235
|
+
resource: Resource;
|
|
236
|
+
}
|
|
237
|
+
|
|
177
238
|
export interface SchedulerDeps {
|
|
178
|
-
getActions: () => Record<string, ActionEntry>;
|
|
239
|
+
getActions: (job?: RecurringJobContext) => Record<string, ActionEntry>;
|
|
179
240
|
getSystemPrompt: (owner: string) => Promise<string>;
|
|
180
241
|
/**
|
|
181
242
|
* Tool names to expose on the FIRST engine request for a job run. When
|
|
@@ -188,7 +249,7 @@ export interface SchedulerDeps {
|
|
|
188
249
|
* merged actions are the app's own vs. framework additions, so this must
|
|
189
250
|
* be supplied explicitly rather than inferred here.
|
|
190
251
|
*/
|
|
191
|
-
getInitialToolNames?: () => string[] | undefined;
|
|
252
|
+
getInitialToolNames?: (job?: RecurringJobContext) => string[] | undefined;
|
|
192
253
|
/** Optional engine override. Defaults to the resolved request engine. */
|
|
193
254
|
engine?: AgentEngine;
|
|
194
255
|
apiKey?: string;
|
|
@@ -477,9 +538,15 @@ async function executeJob(
|
|
|
477
538
|
},
|
|
478
539
|
async () => {
|
|
479
540
|
try {
|
|
480
|
-
const
|
|
541
|
+
const jobContext: RecurringJobContext = {
|
|
542
|
+
name: jobName,
|
|
543
|
+
meta,
|
|
544
|
+
body,
|
|
545
|
+
resource,
|
|
546
|
+
};
|
|
547
|
+
const baseActions = deps.getActions(jobContext);
|
|
481
548
|
const systemPrompt = await deps.getSystemPrompt(jobUserEmail);
|
|
482
|
-
const initialToolNames = deps.getInitialToolNames?.();
|
|
549
|
+
const initialToolNames = deps.getInitialToolNames?.(jobContext);
|
|
483
550
|
// Only attach tool-search (and pay its schema cost) when the caller
|
|
484
551
|
// actually supplied an initial subset to filter down to — otherwise
|
|
485
552
|
// this is byte-for-byte the prior unfiltered behavior.
|
|
@@ -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}}",
|
|
@@ -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()
|