@agent-native/core 0.114.16 → 0.115.3
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 +41 -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 +122 -3
- package/corpus/core/src/cli/skills-content/visual-plan-skill.ts +19 -2
- 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/blocks/library/wireframe.tsx +3 -1
- 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/plan/.agents/skills/visual-plan/SKILL.md +19 -2
- package/corpus/templates/plan/AGENTS.md +10 -0
- package/corpus/templates/plan/actions/create-prototype-plan.ts +27 -3
- package/corpus/templates/plan/actions/get-plan-blocks.ts +1 -1
- package/corpus/templates/plan/actions/update-visual-plan.ts +3 -2
- package/corpus/templates/plan/app/components/plan/PlanContentRenderer.tsx +18 -4
- package/corpus/templates/plan/app/components/plan/PlanVisualSurface.tsx +10 -3
- package/corpus/templates/plan/app/components/plan/wireframe/Wireframe.tsx +3 -1
- package/corpus/templates/plan/app/i18n/en-US.ts +6 -0
- package/corpus/templates/plan/app/lib/create-plan-routing.ts +39 -0
- package/corpus/templates/plan/app/pages/PlansPage.tsx +31 -107
- package/corpus/templates/plan/changelog/2026-07-22-high-fidelity-mockup-requests-now-preserve-branded-css-use-d.md +6 -0
- package/corpus/templates/plan/shared/plan-content.ts +110 -2
- 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 +97 -3
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/cli/skills-content/visual-plan-skill.d.ts +1 -1
- package/dist/cli/skills-content/visual-plan-skill.d.ts.map +1 -1
- package/dist/cli/skills-content/visual-plan-skill.js +19 -2
- package/dist/cli/skills-content/visual-plan-skill.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/blocks/library/wireframe.d.ts.map +1 -1
- package/dist/client/blocks/library/wireframe.js +3 -2
- package/dist/client/blocks/library/wireframe.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/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/progress/routes.d.ts +1 -1
- 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/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/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 +7 -3
- package/src/action.ts +22 -1
- package/src/agent/production-agent.ts +122 -3
- package/src/cli/skills-content/visual-plan-skill.ts +19 -2
- 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/blocks/library/wireframe.tsx +3 -1
- 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/deploy/build.ts
CHANGED
|
@@ -2345,6 +2345,83 @@ export function isDurableBackgroundDeployEnabled(): boolean {
|
|
|
2345
2345
|
return v === "1" || v === "true" || v === "yes" || v === "on";
|
|
2346
2346
|
}
|
|
2347
2347
|
|
|
2348
|
+
const NETLIFY_KEEP_WARM_FUNCTION_NAME = "agent-native-keep-warm";
|
|
2349
|
+
|
|
2350
|
+
/**
|
|
2351
|
+
* Emit a site-local Netlify Scheduled Function that wakes the public server
|
|
2352
|
+
* function and its database every minute. GitHub Actions schedules can be
|
|
2353
|
+
* delayed by tens of minutes, which is longer than a scale-to-zero database's
|
|
2354
|
+
* autosuspend window and leaves the next visitor to pay the cold-start cost.
|
|
2355
|
+
*/
|
|
2356
|
+
export function emitSingleTemplateNetlifyKeepWarmFunction(
|
|
2357
|
+
projectCwd: string,
|
|
2358
|
+
): void {
|
|
2359
|
+
const internalDir = path.join(projectCwd, ".netlify", "functions-internal");
|
|
2360
|
+
const serverBundle = path.join(internalDir, "server", "main.mjs");
|
|
2361
|
+
if (!fs.existsSync(serverBundle)) {
|
|
2362
|
+
console.warn(
|
|
2363
|
+
"[build] Keep-warm emit skipped: expected Nitro Netlify function at " +
|
|
2364
|
+
".netlify/functions-internal/server/main.mjs was not found.",
|
|
2365
|
+
);
|
|
2366
|
+
return;
|
|
2367
|
+
}
|
|
2368
|
+
|
|
2369
|
+
const dest = path.join(internalDir, NETLIFY_KEEP_WARM_FUNCTION_NAME);
|
|
2370
|
+
fs.rmSync(dest, { recursive: true, force: true });
|
|
2371
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
2372
|
+
|
|
2373
|
+
const entry = `const HEALTH_PATH = "/_agent-native/health";
|
|
2374
|
+
const REQUEST_TIMEOUT_MS = 25_000;
|
|
2375
|
+
|
|
2376
|
+
function siteOrigin(request) {
|
|
2377
|
+
const configured = process.env.URL || process.env.DEPLOY_URL;
|
|
2378
|
+
if (configured) return configured;
|
|
2379
|
+
return new URL(request.url).origin;
|
|
2380
|
+
}
|
|
2381
|
+
|
|
2382
|
+
export default async function handler(request) {
|
|
2383
|
+
const url = new URL(HEALTH_PATH, siteOrigin(request));
|
|
2384
|
+
let response;
|
|
2385
|
+
try {
|
|
2386
|
+
response = await fetch(url, {
|
|
2387
|
+
headers: { "user-agent": "agent-native-netlify-keep-warm" },
|
|
2388
|
+
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
|
|
2389
|
+
});
|
|
2390
|
+
} catch (error) {
|
|
2391
|
+
console.error("[agent-native-keep-warm] Health request failed:", url.toString(), error);
|
|
2392
|
+
throw error;
|
|
2393
|
+
}
|
|
2394
|
+
|
|
2395
|
+
if (!response.ok) {
|
|
2396
|
+
const body = await response.text().catch(() => "");
|
|
2397
|
+
throw new Error(
|
|
2398
|
+
"[agent-native-keep-warm] Health request failed with " +
|
|
2399
|
+
response.status +
|
|
2400
|
+
": " +
|
|
2401
|
+
body.slice(0, 500),
|
|
2402
|
+
);
|
|
2403
|
+
}
|
|
2404
|
+
|
|
2405
|
+
console.log("[agent-native-keep-warm] Warmed", url.toString());
|
|
2406
|
+
return new Response(null, { status: 204 });
|
|
2407
|
+
}
|
|
2408
|
+
|
|
2409
|
+
export const config = {
|
|
2410
|
+
name: "agent-native server keep warm",
|
|
2411
|
+
generator: "agent-native build",
|
|
2412
|
+
schedule: "* * * * *",
|
|
2413
|
+
};
|
|
2414
|
+
`;
|
|
2415
|
+
|
|
2416
|
+
fs.writeFileSync(
|
|
2417
|
+
path.join(dest, `${NETLIFY_KEEP_WARM_FUNCTION_NAME}.mjs`),
|
|
2418
|
+
entry,
|
|
2419
|
+
);
|
|
2420
|
+
console.log(
|
|
2421
|
+
`[build] Emitted Netlify scheduled keep-warm function "${NETLIFY_KEEP_WARM_FUNCTION_NAME}".`,
|
|
2422
|
+
);
|
|
2423
|
+
}
|
|
2424
|
+
|
|
2348
2425
|
/**
|
|
2349
2426
|
* Single-template Netlify build: emit an async (background) function INSIDE the
|
|
2350
2427
|
* scanned functions dir so the chat `_process-run` worker runs on Netlify's
|
|
@@ -3528,24 +3605,26 @@ export default bundle;
|
|
|
3528
3605
|
bundleYjsRuntimeForServerlessOutput(nitro.options.output.serverDir, cwd);
|
|
3529
3606
|
}
|
|
3530
3607
|
|
|
3531
|
-
|
|
3532
|
-
|
|
3533
|
-
|
|
3534
|
-
|
|
3535
|
-
|
|
3536
|
-
|
|
3537
|
-
|
|
3538
|
-
|
|
3539
|
-
|
|
3540
|
-
|
|
3541
|
-
|
|
3542
|
-
|
|
3543
|
-
|
|
3544
|
-
|
|
3608
|
+
if (preset === "netlify") {
|
|
3609
|
+
emitSingleTemplateNetlifyKeepWarmFunction(cwd);
|
|
3610
|
+
|
|
3611
|
+
// Durable background agent runs (default-OFF / opt-in; enable with a truthy
|
|
3612
|
+
// AGENT_CHAT_DURABLE_BACKGROUND). Additive ONLY: emits a SECOND Netlify
|
|
3613
|
+
// function whose name ends in `-background` re-exporting the same handler
|
|
3614
|
+
// bundle, so the chat `_process-run` POST lands on Netlify's async (15-min)
|
|
3615
|
+
// function. When not opted in this is a no-op and the single-function
|
|
3616
|
+
// deploy is byte-for-byte unchanged.
|
|
3617
|
+
if (isDurableBackgroundDeployEnabled()) {
|
|
3618
|
+
try {
|
|
3619
|
+
emitSingleTemplateNetlifyBackgroundFunction(cwd);
|
|
3620
|
+
} catch (err) {
|
|
3621
|
+
console.warn(
|
|
3622
|
+
"[build] Failed to emit durable-background Netlify function (non-fatal):",
|
|
3623
|
+
err instanceof Error ? err.message : err,
|
|
3624
|
+
);
|
|
3625
|
+
}
|
|
3545
3626
|
}
|
|
3546
|
-
}
|
|
3547
3627
|
|
|
3548
|
-
if (preset === "netlify") {
|
|
3549
3628
|
writeSingleTemplateNetlifyRedirects(cwd);
|
|
3550
3629
|
assertSingleTemplateNetlifyBuildOutput(cwd);
|
|
3551
3630
|
}
|
|
@@ -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
|
}
|
package/src/jobs/scheduler.ts
CHANGED
|
@@ -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.
|