@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
|
@@ -49,8 +49,8 @@ export declare function handleUpdateResource(event: any): Promise<import("./stor
|
|
|
49
49
|
}>;
|
|
50
50
|
/** DELETE /_agent-native/resources/:id — delete a resource */
|
|
51
51
|
export declare function handleDeleteResource(event: any): Promise<{
|
|
52
|
-
ok?: undefined;
|
|
53
52
|
error: string;
|
|
53
|
+
ok?: undefined;
|
|
54
54
|
} | {
|
|
55
55
|
error?: undefined;
|
|
56
56
|
ok: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"register-framework-secrets.d.ts","sourceRoot":"","sources":["../../src/secrets/register-framework-secrets.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,wBAAgB,wBAAwB,IAAI,IAAI,
|
|
1
|
+
{"version":3,"file":"register-framework-secrets.d.ts","sourceRoot":"","sources":["../../src/secrets/register-framework-secrets.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,wBAAgB,wBAAwB,IAAI,IAAI,CAyN/C"}
|
|
@@ -44,6 +44,13 @@ export function registerFrameworkSecrets() {
|
|
|
44
44
|
label: "HubSpot",
|
|
45
45
|
docsUrl: "https://developers.hubspot.com/docs/apps/developer-platform/build-apps/authentication/oauth/oauth-quickstart-guide",
|
|
46
46
|
},
|
|
47
|
+
{
|
|
48
|
+
id: "salesforce",
|
|
49
|
+
credentialPrefix: "SALESFORCE",
|
|
50
|
+
oauthProvider: "salesforce",
|
|
51
|
+
label: "Salesforce",
|
|
52
|
+
docsUrl: "https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/intro_understanding_web_server_oauth_flow.htm",
|
|
53
|
+
},
|
|
47
54
|
{
|
|
48
55
|
id: "jira",
|
|
49
56
|
credentialPrefix: "JIRA",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"register-framework-secrets.js","sourceRoot":"","sources":["../../src/secrets/register-framework-secrets.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Framework-level secret registrations.\n *\n * Side-effect module — imported by the core-routes plugin at boot so the\n * sidebar settings UI and the `/_agent-native/secrets` list route surface the\n * relevant keys in every template.\n *\n * Each call uses a `getRequiredSecret` guard so a template that has already\n * registered the same key (often with stricter settings like `required: true`)\n * wins — the framework registration is a fallback, not an override.\n *\n * OPENAI_API_KEY is optional framework-wide because it enables the shared\n * realtime speech-to-speech agent mode. Templates can pre-register the same\n * key with stricter requirements; the guard below preserves their definition.\n */\n\nimport { getRequiredSecret, registerRequiredSecret } from \"./register.js\";\n\nexport function registerFrameworkSecrets(): void {\n const workspaceOAuthProviders = [\n {\n id: \"figma\",\n credentialPrefix: \"FIGMA\",\n oauthProvider: \"figma\",\n label: \"Figma\",\n docsUrl: \"https://developers.figma.com/docs/rest-api/oauth-apps/\",\n },\n {\n id: \"google_drive\",\n credentialPrefix: \"GOOGLE\",\n oauthProvider: \"google\",\n label: \"Google Drive\",\n docsUrl:\n \"https://developers.google.com/identity/protocols/oauth2/web-server\",\n },\n {\n id: \"github\",\n credentialPrefix: \"GITHUB\",\n oauthProvider: \"github\",\n label: \"GitHub\",\n docsUrl: \"https://docs.github.com/apps/oauth-apps/building-oauth-apps\",\n },\n {\n id: \"hubspot\",\n credentialPrefix: \"HUBSPOT\",\n oauthProvider: \"hubspot\",\n label: \"HubSpot\",\n docsUrl:\n \"https://developers.hubspot.com/docs/apps/developer-platform/build-apps/authentication/oauth/oauth-quickstart-guide\",\n },\n {\n id: \"jira\",\n credentialPrefix: \"JIRA\",\n oauthProvider: \"jira\",\n label: \"Jira Cloud\",\n docsUrl:\n \"https://developer.atlassian.com/cloud/jira/platform/oauth-2-3lo-apps/\",\n },\n {\n id: \"sentry\",\n credentialPrefix: \"SENTRY\",\n oauthProvider: \"sentry\",\n label: \"Sentry\",\n docsUrl: \"https://docs.sentry.io/api/auth/\",\n },\n {\n id: \"notion\",\n credentialPrefix: \"NOTION\",\n oauthProvider: \"notion\",\n label: \"Notion\",\n docsUrl: \"https://developers.notion.com/docs/authorization\",\n },\n ] as const;\n\n for (const provider of workspaceOAuthProviders) {\n const prefix = provider.credentialPrefix;\n for (const credential of [\n { suffix: \"CLIENT_ID\", label: \"OAuth client ID\" },\n { suffix: \"CLIENT_SECRET\", label: \"OAuth client secret\" },\n ] as const) {\n const key = `${prefix}_${credential.suffix}`;\n if (!getRequiredSecret(key)) {\n registerRequiredSecret({\n key,\n label: `${provider.label} ${credential.label}`,\n description: `Workspace-owned ${provider.label} OAuth application credential. Tokens granted by users are stored separately and encrypted.`,\n docsUrl: provider.docsUrl,\n scope: \"workspace\",\n kind: \"api-key\",\n required: false,\n });\n }\n }\n\n const connectionKey = `${prefix}_CONNECTED`;\n if (!getRequiredSecret(connectionKey)) {\n registerRequiredSecret({\n key: connectionKey,\n label: `${provider.label} account`,\n description: `Connect a ${provider.label} account for scoped workspace imports.`,\n docsUrl: provider.docsUrl,\n scope: \"user\",\n kind: \"oauth\",\n required: false,\n oauthProvider: provider.oauthProvider,\n oauthConnectUrl: `/_agent-native/connections/oauth/${provider.id}/start`,\n });\n }\n }\n\n if (!getRequiredSecret(\"OPENAI_API_KEY\")) {\n registerRequiredSecret({\n key: \"OPENAI_API_KEY\",\n label: \"OpenAI API key\",\n description:\n \"Optional fallback for realtime voice when Builder is not connected, and for OpenAI transcription.\",\n docsUrl: \"https://platform.openai.com/api-keys\",\n scope: \"user\",\n kind: \"api-key\",\n required: false,\n validator: async (value) => {\n const response = await fetch(\"https://api.openai.com/v1/models\", {\n headers: { Authorization: `Bearer ${value}` },\n });\n return response.ok\n ? { ok: true }\n : {\n ok: false,\n error: `OpenAI rejected the key (HTTP ${response.status}).`,\n };\n },\n });\n }\n\n // Web-search tool backends — optional; the tool selects the first\n // configured manual key at call time, then falls back to Builder Connect.\n const webSearchKeys: Array<{\n key: string;\n label: string;\n description: string;\n docsUrl: string;\n }> = [\n {\n key: \"BRAVE_SEARCH_API_KEY\",\n label: \"Brave Search API Key\",\n description:\n \"Enables the web-search agent tool via Brave Search. Optional when Builder.io is connected for managed web search.\",\n docsUrl: \"https://brave.com/search/api/\",\n },\n {\n key: \"TAVILY_API_KEY\",\n label: \"Tavily API Key\",\n description:\n \"Enables the web-search agent tool via Tavily. Used as fallback when BRAVE_SEARCH_API_KEY is not set and before Builder-managed search.\",\n docsUrl: \"https://tavily.com/\",\n },\n {\n key: \"EXA_API_KEY\",\n label: \"Exa API Key\",\n description:\n \"Enables the web-search agent tool via Exa. Used as fallback when Brave and Tavily are not set and before Builder-managed search.\",\n docsUrl: \"https://exa.ai/\",\n },\n {\n key: \"FIRECRAWL_API_KEY\",\n label: \"Firecrawl API Key\",\n description:\n \"Enables the web-search agent tool via Firecrawl. Used as fallback when Brave, Tavily, and Exa are not set and before Builder-managed search.\",\n docsUrl: \"https://firecrawl.dev/\",\n },\n ];\n\n for (const entry of webSearchKeys) {\n if (!getRequiredSecret(entry.key)) {\n registerRequiredSecret({\n key: entry.key,\n label: entry.label,\n description: entry.description,\n docsUrl: entry.docsUrl,\n scope: \"workspace\",\n kind: \"api-key\",\n required: false,\n });\n }\n }\n\n if (!getRequiredSecret(\"GITHUB_TOKEN\")) {\n registerRequiredSecret({\n key: \"GITHUB_TOKEN\",\n label: \"GitHub token\",\n description:\n \"Enables connector-scoped repository file reads and writes for headless/cloud agent runs.\",\n docsUrl:\n \"https://docs.github.com/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens\",\n scope: \"workspace\",\n kind: \"api-key\",\n required: false,\n });\n }\n\n if (!getRequiredSecret(\"FIGMA_ACCESS_TOKEN\")) {\n registerRequiredSecret({\n key: \"FIGMA_ACCESS_TOKEN\",\n label: \"Figma access token\",\n description:\n \"Optional fallback for reading Figma file and node context when the hosted Figma MCP server is unavailable. Generate a personal access token with current_user:read and file_content:read.\",\n docsUrl:\n \"https://developers.figma.com/docs/rest-api/personal-access-tokens/\",\n scope: \"user\",\n kind: \"api-key\",\n required: false,\n validator: async (value) => {\n const response = await fetch(\"https://api.figma.com/v1/me\", {\n headers: {\n \"X-Figma-Token\": value,\n \"User-Agent\": \"AgentNative/1.0\",\n },\n });\n return response.ok\n ? { ok: true }\n : {\n ok: false,\n error: `Figma rejected the token (HTTP ${response.status}).`,\n };\n },\n });\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"register-framework-secrets.js","sourceRoot":"","sources":["../../src/secrets/register-framework-secrets.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Framework-level secret registrations.\n *\n * Side-effect module — imported by the core-routes plugin at boot so the\n * sidebar settings UI and the `/_agent-native/secrets` list route surface the\n * relevant keys in every template.\n *\n * Each call uses a `getRequiredSecret` guard so a template that has already\n * registered the same key (often with stricter settings like `required: true`)\n * wins — the framework registration is a fallback, not an override.\n *\n * OPENAI_API_KEY is optional framework-wide because it enables the shared\n * realtime speech-to-speech agent mode. Templates can pre-register the same\n * key with stricter requirements; the guard below preserves their definition.\n */\n\nimport { getRequiredSecret, registerRequiredSecret } from \"./register.js\";\n\nexport function registerFrameworkSecrets(): void {\n const workspaceOAuthProviders = [\n {\n id: \"figma\",\n credentialPrefix: \"FIGMA\",\n oauthProvider: \"figma\",\n label: \"Figma\",\n docsUrl: \"https://developers.figma.com/docs/rest-api/oauth-apps/\",\n },\n {\n id: \"google_drive\",\n credentialPrefix: \"GOOGLE\",\n oauthProvider: \"google\",\n label: \"Google Drive\",\n docsUrl:\n \"https://developers.google.com/identity/protocols/oauth2/web-server\",\n },\n {\n id: \"github\",\n credentialPrefix: \"GITHUB\",\n oauthProvider: \"github\",\n label: \"GitHub\",\n docsUrl: \"https://docs.github.com/apps/oauth-apps/building-oauth-apps\",\n },\n {\n id: \"hubspot\",\n credentialPrefix: \"HUBSPOT\",\n oauthProvider: \"hubspot\",\n label: \"HubSpot\",\n docsUrl:\n \"https://developers.hubspot.com/docs/apps/developer-platform/build-apps/authentication/oauth/oauth-quickstart-guide\",\n },\n {\n id: \"salesforce\",\n credentialPrefix: \"SALESFORCE\",\n oauthProvider: \"salesforce\",\n label: \"Salesforce\",\n docsUrl:\n \"https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/intro_understanding_web_server_oauth_flow.htm\",\n },\n {\n id: \"jira\",\n credentialPrefix: \"JIRA\",\n oauthProvider: \"jira\",\n label: \"Jira Cloud\",\n docsUrl:\n \"https://developer.atlassian.com/cloud/jira/platform/oauth-2-3lo-apps/\",\n },\n {\n id: \"sentry\",\n credentialPrefix: \"SENTRY\",\n oauthProvider: \"sentry\",\n label: \"Sentry\",\n docsUrl: \"https://docs.sentry.io/api/auth/\",\n },\n {\n id: \"notion\",\n credentialPrefix: \"NOTION\",\n oauthProvider: \"notion\",\n label: \"Notion\",\n docsUrl: \"https://developers.notion.com/docs/authorization\",\n },\n ] as const;\n\n for (const provider of workspaceOAuthProviders) {\n const prefix = provider.credentialPrefix;\n for (const credential of [\n { suffix: \"CLIENT_ID\", label: \"OAuth client ID\" },\n { suffix: \"CLIENT_SECRET\", label: \"OAuth client secret\" },\n ] as const) {\n const key = `${prefix}_${credential.suffix}`;\n if (!getRequiredSecret(key)) {\n registerRequiredSecret({\n key,\n label: `${provider.label} ${credential.label}`,\n description: `Workspace-owned ${provider.label} OAuth application credential. Tokens granted by users are stored separately and encrypted.`,\n docsUrl: provider.docsUrl,\n scope: \"workspace\",\n kind: \"api-key\",\n required: false,\n });\n }\n }\n\n const connectionKey = `${prefix}_CONNECTED`;\n if (!getRequiredSecret(connectionKey)) {\n registerRequiredSecret({\n key: connectionKey,\n label: `${provider.label} account`,\n description: `Connect a ${provider.label} account for scoped workspace imports.`,\n docsUrl: provider.docsUrl,\n scope: \"user\",\n kind: \"oauth\",\n required: false,\n oauthProvider: provider.oauthProvider,\n oauthConnectUrl: `/_agent-native/connections/oauth/${provider.id}/start`,\n });\n }\n }\n\n if (!getRequiredSecret(\"OPENAI_API_KEY\")) {\n registerRequiredSecret({\n key: \"OPENAI_API_KEY\",\n label: \"OpenAI API key\",\n description:\n \"Optional fallback for realtime voice when Builder is not connected, and for OpenAI transcription.\",\n docsUrl: \"https://platform.openai.com/api-keys\",\n scope: \"user\",\n kind: \"api-key\",\n required: false,\n validator: async (value) => {\n const response = await fetch(\"https://api.openai.com/v1/models\", {\n headers: { Authorization: `Bearer ${value}` },\n });\n return response.ok\n ? { ok: true }\n : {\n ok: false,\n error: `OpenAI rejected the key (HTTP ${response.status}).`,\n };\n },\n });\n }\n\n // Web-search tool backends — optional; the tool selects the first\n // configured manual key at call time, then falls back to Builder Connect.\n const webSearchKeys: Array<{\n key: string;\n label: string;\n description: string;\n docsUrl: string;\n }> = [\n {\n key: \"BRAVE_SEARCH_API_KEY\",\n label: \"Brave Search API Key\",\n description:\n \"Enables the web-search agent tool via Brave Search. Optional when Builder.io is connected for managed web search.\",\n docsUrl: \"https://brave.com/search/api/\",\n },\n {\n key: \"TAVILY_API_KEY\",\n label: \"Tavily API Key\",\n description:\n \"Enables the web-search agent tool via Tavily. Used as fallback when BRAVE_SEARCH_API_KEY is not set and before Builder-managed search.\",\n docsUrl: \"https://tavily.com/\",\n },\n {\n key: \"EXA_API_KEY\",\n label: \"Exa API Key\",\n description:\n \"Enables the web-search agent tool via Exa. Used as fallback when Brave and Tavily are not set and before Builder-managed search.\",\n docsUrl: \"https://exa.ai/\",\n },\n {\n key: \"FIRECRAWL_API_KEY\",\n label: \"Firecrawl API Key\",\n description:\n \"Enables the web-search agent tool via Firecrawl. Used as fallback when Brave, Tavily, and Exa are not set and before Builder-managed search.\",\n docsUrl: \"https://firecrawl.dev/\",\n },\n ];\n\n for (const entry of webSearchKeys) {\n if (!getRequiredSecret(entry.key)) {\n registerRequiredSecret({\n key: entry.key,\n label: entry.label,\n description: entry.description,\n docsUrl: entry.docsUrl,\n scope: \"workspace\",\n kind: \"api-key\",\n required: false,\n });\n }\n }\n\n if (!getRequiredSecret(\"GITHUB_TOKEN\")) {\n registerRequiredSecret({\n key: \"GITHUB_TOKEN\",\n label: \"GitHub token\",\n description:\n \"Enables connector-scoped repository file reads and writes for headless/cloud agent runs.\",\n docsUrl:\n \"https://docs.github.com/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens\",\n scope: \"workspace\",\n kind: \"api-key\",\n required: false,\n });\n }\n\n if (!getRequiredSecret(\"FIGMA_ACCESS_TOKEN\")) {\n registerRequiredSecret({\n key: \"FIGMA_ACCESS_TOKEN\",\n label: \"Figma access token\",\n description:\n \"Optional fallback for reading Figma file and node context when the hosted Figma MCP server is unavailable. Generate a personal access token with current_user:read and file_content:read.\",\n docsUrl:\n \"https://developers.figma.com/docs/rest-api/personal-access-tokens/\",\n scope: \"user\",\n kind: \"api-key\",\n required: false,\n validator: async (value) => {\n const response = await fetch(\"https://api.figma.com/v1/me\", {\n headers: {\n \"X-Figma-Token\": value,\n \"User-Agent\": \"AgentNative/1.0\",\n },\n });\n return response.ok\n ? { ok: true }\n : {\n ok: false,\n error: `Figma rejected the token (HTTP ${response.status}).`,\n };\n },\n });\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context-tools.d.ts","sourceRoot":"","sources":["../../../src/server/agent-chat/context-tools.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAWnE;;;;GAIG;AACH,eAAO,MAAM,0BAA0B,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"context-tools.d.ts","sourceRoot":"","sources":["../../../src/server/agent-chat/context-tools.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAWnE;;;;GAIG;AACH,eAAO,MAAM,0BAA0B,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAuL7D,CAAC;AAEF,wBAAgB,2BAA2B,IAAI,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CA+BzE;AAED;;;;;;;;;GASG;AACH,wBAAgB,wBAAwB,IAAI,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAsCtE;AAMD,wBAAgB,wBAAwB,CACtC,GAAG,EAAE,MAAM,EACX,YAAY,EAAE,OAAO,GACpB,MAAM,CAIR;AAED;;;;;;;;;GASG;AACH,wBAAgB,cAAc,IAAI,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAgP5D;AAED,wBAAgB,6BAA6B,IAAI,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAyD3E"}
|
|
@@ -91,6 +91,15 @@ Convert natural language to 5-field cron format:
|
|
|
91
91
|
- "every hour" → \`0 * * * *\`
|
|
92
92
|
- "every monday at 9am" → \`0 9 * * 1\`
|
|
93
93
|
|
|
94
|
+
When a recurring job needs a connected MCP, discover the exact MCP tool names
|
|
95
|
+
available in the current user/org context and pass them in the create call's
|
|
96
|
+
\`mcpTools\` array. Bind only the tools the job needs; do not put an MCP URL,
|
|
97
|
+
OAuth token, or arbitrary endpoint in the instructions. The scheduler resolves
|
|
98
|
+
the selected tools with the job owner's existing connector grant and fails
|
|
99
|
+
clearly if a connector is revoked or a selected tool disappears. For imports,
|
|
100
|
+
normalize the provider response and call the app's bounded idempotent import
|
|
101
|
+
action once with the full batch rather than issuing one write per item.
|
|
102
|
+
|
|
94
103
|
#### Suggesting "Save as automation"
|
|
95
104
|
|
|
96
105
|
When you finish a task that has obvious recurring value — daily inbox triage, weekly metrics summaries, archive sweeps, status digests, anything the user would plausibly want re-run on a fresh cadence — close the response with ONE short line offering to save it. Examples:
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context-tools.js","sourceRoot":"","sources":["../../../src/server/agent-chat/context-tools.ts"],"names":[],"mappings":"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","sourcesContent":["import { ACTION_CHAT_UI_DATA_WIDGET_RENDERER } from \"../../action-ui.js\";\nimport type { ActionEntry } from \"../../agent/production-agent.js\";\nimport { dataWidgetResultSchema } from \"../../data-widgets/index.js\";\nimport { getRequestRunContext } from \"../request-context.js\";\n\n// ---------------------------------------------------------------------------\n// Framework-owned \"context\" action entries: get-framework-context,\n// refresh-screen, the URL/ask-question tools, and the native data-widget\n// renderer. These are generic, template-agnostic tools registered into every\n// app's tool surface.\n// ---------------------------------------------------------------------------\n\n/**\n * Verbose framework sections returned by the `get-framework-context` tool.\n * Keyed by topic so the agent can request specific sections.\n * Not template-specific — lives outside buildFrameworkPrompts().\n */\nexport const FRAMEWORK_CONTEXT_SECTIONS: Record<string, string> = {\n embeds: `### Inline Embeds\n\nYou can embed an interactive view inline in your chat reply by writing an \\`embed\\` fenced code block. The chat renderer swaps the fence for a sandboxed iframe pointing at a route inside this app.\n\nSyntax:\n\n\\`\\`\\`\\`\n\\`\\`\\`embed\nsrc: /some/path?param=value\naspect: 16/9\ntitle: Optional label\n\\`\\`\\`\n\\`\\`\\`\\`\n\nKeys:\n- \\`src\\` (required) — **must be a same-origin path starting with \\`/\\`**. Cross-origin URLs are blocked. No \\`javascript:\\` or \\`data:\\` URLs.\n- \\`aspect\\` (optional) — one of \\`16/9\\` (default), \\`4/3\\`, \\`3/2\\`, \\`2/1\\`, \\`21/9\\`, \\`1/1\\`.\n- \\`title\\` (optional) — accessible label / hover tooltip.\n- \\`height\\` (optional) — fixed pixel height when aspect ratio isn't a good fit.\n\nUse for charts, visualizations, previews. Don't use for simple text/tables or external sites.`,\n\n \"chat-history\": `### Chat History\n\nYou can search and restore previous chat conversations using \\`chat-history\\`:\n- \\`chat-history\\` (action: \"search\") — Search or list past chat threads by keyword. Archived threads are excluded by default; pass \\`includeArchived: true\\` to also see them.\n- \\`chat-history\\` (action: \"open\") — Open a chat thread in the UI as a new tab and focus it\n- \\`chat-history\\` (actions: \"rename\", \"pin\", \"unpin\", \"archive\") — Organize a known chat thread by ID. Archiving a thread hides it from the default chat list and search.\n\nWhen the user asks to find a previous conversation, use \\`chat-history\\` with action \"search\" first to find matching threads, then action \"open\" to restore the one they want.`,\n\n \"agent-teams\": `### Agent Teams — Orchestration\n\nYou can delegate to background sub-agents with the \\`agent-teams\\` tool:\n- \\`agent-teams\\` (action: \"spawn\") — Launch a sub-agent on a task. It runs in its own thread with a clean context while you stay available; a live preview card appears in the chat. The spawn result confirms launch only, not completion. Optionally pass a custom agent profile from \\`agents/*.md\\` via the \\`agent\\` parameter.\n- \\`agent-teams\\` (action: \"status\") — Check a running sub-agent's progress.\n- \\`agent-teams\\` (action: \"read-result\") — Read a finished sub-agent's output.\n- \\`agent-teams\\` (action: \"send\") — Message a running sub-agent.\n- \\`agent-teams\\` (action: \"list\") — List sub-agent tasks.\n\nSub-agents inherit all of your template tools but **cannot spawn sub-agents themselves** — only you orchestrate.\n\n**User intent phrases.** If the user asks you to use a \"sub-agent\" or \"background agent\", that is explicit delegation intent. Also treat phrases like \"run these in the background\", \"kick off the rest\", \"run the queued items\", \"batch run these jobs\", \"parallelize this\", or \"start the next batch\" as delegation intent when the context is a set of independent work items.\n\n**Spawn is not completion.** A successful \\`spawn\\` call means the sub-agent started and is running. Tell the user it started, show the task id if useful, and then use \\`status\\`/\\`list\\`/\\`read-result\\` to monitor it. Never say the delegated task \"completed\", \"ran successfully\", or \"finished\" until \\`status\\` or \\`read-result\\` reports \\`completed\\` or \\`errored\\`. If a task is still running, say that plainly.\n\n**Default to doing the work yourself in this thread.** A sub-agent costs real tokens and adds a merge step, so reach for one only when delegation clearly pays for that overhead.\n\n**Delegate ONE sub-agent** when a task is self-contained and heavy: deep research, long multi-step content generation, or a noisy scan whose intermediate steps would clutter this thread. The sub-agent gets its own clean context and hands you back a distilled result.\n\n**Fan out to MULTIPLE sub-agents ONLY** for units of work that are genuinely independent and don't depend on each other's decisions — e.g. research three unrelated competitors, summarize five separate threads, draft sections that don't reference one another. Each gets a distinct slice.\n\n**Do NOT parallelize tightly-coupled work** — one cohesive artifact, edits that must agree with each other, or anything needing a single consistent voice or style. Parallel sub-agents can't see each other's choices and their outputs will clash. For coupled work, do it yourself, or chain sub-agents one at a time, feeding each result into the next.\n\n**Cap fan-out:** aim for 1, use up to ~3, and go beyond that only for clearly independent bulk work. More sub-agents means more tokens and a harder merge.\n\n**Briefing contract.** A sub-agent starts in a fresh thread and can only see the brief you give it — it cannot see this conversation or ask you to clarify before it runs. Make every brief self-contained:\n1. **Objective** — what \"done\" looks like, in a sentence or two.\n2. **Context** — the specific facts it needs from this conversation: IDs, names, the user's actual goal, constraints, prior decisions. Paste the specifics; don't assume it knows them.\n3. **Output format** — what to return and how (e.g. \"a 3-bullet summary with source links\", \"the drafted email body only\") so the result drops cleanly into your synthesis.\n4. **Boundaries** — what NOT to do, and for parallel sub-agents, which slice is theirs so they don't overlap.\n\nPut the objective and output format in \\`task\\`; put longer context in \\`instructions\\`.\n\n**Synthesis discipline.** After the sub-agents you depend on finish, poll \\`status\\`/\\`list\\` until they're complete, then pull each one's output with \\`read-result\\`. Do NOT paste their outputs back to back. Read all results, reconcile any disagreements, de-duplicate, and write ONE integrated answer in your own voice. If two sub-agents conflict, resolve it or flag the discrepancy explicitly rather than presenting both. When findings came from distinct investigations, briefly note which finding came from where so the user can trust the merge.`,\n\n \"recurring-jobs\": `### Recurring Jobs\n\nYou can create recurring jobs that run on a cron schedule. Jobs are resource files under \\`jobs/\\`.\n\n- \\`manage-jobs\\` (action: \"create\") — Create a new recurring job with a cron schedule and instructions\n- \\`manage-jobs\\` (action: \"list\") — List all recurring jobs and their status\n- \\`manage-jobs\\` (action: \"update\") — Update a job's schedule, instructions, or toggle enabled/disabled\n- Delete a job with the \\`resources\\` tool: \\`action: \"delete\"\\`, \\`path: \"jobs/<name>.md\"\\`\n\nConvert natural language to 5-field cron format:\n- \"every morning\" / \"daily at 9am\" → \\`0 9 * * *\\`\n- \"every weekday at 9am\" → \\`0 9 * * 1-5\\`\n- \"every hour\" → \\`0 * * * *\\`\n- \"every monday at 9am\" → \\`0 9 * * 1\\`\n\n#### Suggesting \"Save as automation\"\n\nWhen you finish a task that has obvious recurring value — daily inbox triage, weekly metrics summaries, archive sweeps, status digests, anything the user would plausibly want re-run on a fresh cadence — close the response with ONE short line offering to save it. Examples:\n\n- After \"Summarize my unread emails\": _\"Want me to run this every morning?\"_\n- After \"What's our top traffic source this week\": _\"Want a weekly digest on Mondays?\"_\n- After \"Archive emails older than 30 days\": _\"Should I run this every Sunday?\"_\n\nIf the user says yes, call \\`manage-jobs\\` (action: \"create\") with the original prompt as the job's instructions and the cadence they confirmed.\n\nDo NOT add this offer for one-shot work: lookups (find Alice, what's the schema, who reported X), single drafts/replies, navigation requests, or any task whose value is in the moment. Skip it when the prompt is already explicitly recurring (the user said \"every morning…\" — you'd be asking what they already told you). One short sentence at most; do not turn it into a list of cadence options.`,\n\n builder: `### Connecting Builder.io\n\nWhen the user asks to connect Builder.io or you hit a \"Builder not configured\" error, call the \\`connect-builder\\` tool. It renders a Connect/code-change card inline — do NOT write out multi-step setup instructions yourself. Inspect the returned \\`builderEnabled\\` flag: \\`true\\` means Builder Cloud Agents can take the code-change handoff, while \\`false\\` means this requires a code change and the user should edit locally or use Builder.io to edit this code in the cloud and continue customizing the app any way they like. If Builder Cloud Agents are not available for this workspace, never send the user to Builder org settings or beta settings.`,\n\n browser: `### Browser Automation\n\nYou can activate a real Chrome browser via Builder.io for tasks that need full page rendering:\n- Extracting design tokens from JS-heavy or SPA websites (computed styles, rendered colors/fonts)\n- Taking screenshots of live pages\n- Testing interactive flows on deployed URLs\n- Reading content from pages that require JavaScript execution\n\n**How to use:**\n1. In local development, call \\`set-browser-control\\` with \\`{\"enabled\":true,\"backend\":\"chrome-devtools\"}\\` after confirming once with the user. In production, use \\`activate-browser\\` for Builder-provisioned Chrome.\n2. On your next action, use \\`mcp__chrome-devtools__navigate_page\\`, \\`mcp__chrome-devtools__evaluate_script\\`, \\`mcp__chrome-devtools__take_screenshot\\`, etc.\n3. If Builder is not connected, call \\`connect-builder\\` first\n\n**When to recommend browser automation:**\n- User wants to import a design system from a URL (JS-rendered sites give almost no useful data from plain HTML fetch)\n- User asks you to check how a deployed site looks or behaves\n- Any task involving reading computed/rendered page state\n- When \\`web-request\\` returns minimal/skeleton HTML from a modern SPA\n\nPrefer \\`web-request\\` for simple API calls and static pages. Use browser automation when you need the real rendered page.`,\n\n \"call-agent\": `### call-agent — External Apps Only\n\nThe \\`call-agent\\` tool sends a message to a DIFFERENT, separately-deployed app's agent (A2A protocol). It is **not** for calling actions within the current app.\n\n**NEVER use \\`call-agent\\` to:**\n- Call your own app by name\n- Perform tasks you can accomplish with your own registered tools\n\n**ONLY use \\`call-agent\\` when:**\n- The user explicitly asks you to communicate with a different app\n- You need data that only another deployed app can provide\n- You need brand-consistent generated media and this app does not have a native generation action; call agent \"assets\" and keep returned asset IDs and URLs verbatim\n\nIf \\`call-agent\\` says a downstream agent accepted the subtask and will post its result separately, do not call that same agent again for the same subtask. Continue any remaining work and answer with the completed results you have.`,\n\n memory: `### Structured Memory\n\nYour memory index (\\`memory/MEMORY.md\\`) is loaded at the start of every conversation.\n\n**Tools:**\n- \\`save-memory\\` — Create or update a memory (name, type, description, content)\n- \\`delete-memory\\` — Remove a memory and its index entry\n- \\`resources\\` with \\`action: \"read\"\\` and \\`path: \"memory/<name>.md\"\\` — Read the full content of a specific memory\n\n**Memory types:** user, feedback, project, reference\n\n**When to save (proactively):**\n- User corrects your approach → \\`feedback\\`\n- User shares preferences → \\`user\\`\n- Non-obvious pattern or gotcha → \\`feedback\\`\n- Personal context (contacts, team) → \\`user\\`\n- Project context to track → \\`project\\`\n\n**Rules:**\n- Don't save things obvious from code or standard framework behavior\n- When updating, read first and merge — don't overwrite\n- Keep descriptions concise\n- One memory per logical topic`,\n\n \"sql-tools\": `### SQL Tools\n\nWhen database tools are enabled, \\`db-schema\\` refreshes the schema and \\`db-query\\` runs read-only SELECT queries with current user/org scoping. Raw SQL write tools are only available when the app explicitly opts into database write tools; by default, writes go through typed app actions. Some apps configure database tools as read-only or off; only use tools that are actually present in your tool list.\n\n- \\`db-schema\\` — refresh the full schema with indexes and foreign keys\n- \\`db-query\\` — run a SELECT (read-only; results already filtered to the current user/org)\n- \\`db-exec\\` — only when present: run INSERT / UPDATE / DELETE / REPLACE for scoped maintenance. For normal product data writes, use a typed app action instead.\n- \\`db-patch\\` — only when present: surgical search-and-replace on a large text column. If a typed app action exists for the resource, use that action.\n\n### When to pick which SQL tool\n- A template-specific action exists for the table → use that action (it encodes business rules and pushes live Yjs updates)\n- Read data → \\`db-query\\`. Never re-add \\`WHERE owner_email = ...\\` — scoping already applies it.\n- Raw write tools are present and no app action exists → use \\`db-exec\\` or \\`db-patch\\` only for deliberate maintenance, not normal product workflows.\n\n### External data sources vs the app database\nThe \\`db-*\\` tools ONLY query the app's own SQL database. They do NOT reach external data warehouses. If the user asks about tables NOT in the schema, use the appropriate template action instead.`,\n};\n\nexport function createFrameworkContextEntry(): Record<string, ActionEntry> {\n const topicList = Object.keys(FRAMEWORK_CONTEXT_SECTIONS).join(\", \");\n return {\n \"get-framework-context\": {\n tool: {\n description: `Read detailed framework instructions for a specific capability. Available topics: ${topicList}. Call with topic=\"all\" to get everything.`,\n parameters: {\n type: \"object\" as const,\n properties: {\n topic: {\n type: \"string\",\n description: `Topic to read. One of: ${topicList}, or \"all\" for everything.`,\n },\n },\n required: [\"topic\"],\n },\n },\n run: async (args: Record<string, string>) => {\n const topic = String(args.topic ?? \"all\").toLowerCase();\n if (topic === \"all\") {\n return Object.values(FRAMEWORK_CONTEXT_SECTIONS).join(\"\\n\\n\");\n }\n const section = FRAMEWORK_CONTEXT_SECTIONS[topic];\n if (!section) {\n return `Unknown topic \"${topic}\". Available: ${topicList}`;\n }\n return section;\n },\n readOnly: true,\n },\n };\n}\n\n/**\n * Creates the `refresh-screen` tool. Writes a bump to `application_state`\n * under a well-known key; the client's `useDbSync` watches for this and\n * invalidates react-query caches so the on-screen UI re-fetches its data\n * without a full page reload.\n *\n * This is the standard way for the agent to say \"the data on the screen\n * just changed, please refresh it\" — e.g. after editing a dashboard config,\n * updating a form schema, or mutating a row that the current view renders.\n */\nexport function createRefreshScreenEntry(): Record<string, ActionEntry> {\n return {\n \"refresh-screen\": {\n // Writes __screen_refresh__ to application_state, which emits its own\n // distinct `screen-refresh` poll event. Don't double-emit a generic\n // `action` event on top of that.\n readOnly: true,\n // Refetching volatile on-screen state is the entire point of this\n // tool — an identical repeat call (even with the same scope) is a\n // legitimate re-refresh, not a redundant read to skip.\n dedupe: false,\n tool: {\n description:\n \"Manually refresh the user's current screen. The framework ALREADY auto-refreshes after any successful mutating action tool call (template actions and any enabled raw DB write tools) — you do NOT need to call this after a normal action. Use it only when (a) you mutated data via a path the framework can't detect (e.g. a direct write to an external system the app mirrors), or (b) you want to pass a `scope` hint so the UI narrows which queries to refetch. The UI re-fetches its queries without a full page reload.\",\n parameters: {\n type: \"object\",\n properties: {\n scope: {\n type: \"string\",\n description:\n \"Optional hint describing what changed (e.g. 'dashboard', 'form', 'settings'). Templates may use it to narrow which queries to invalidate; if omitted, all queries are invalidated.\",\n },\n },\n },\n },\n run: async (args) => {\n const { writeAppState } =\n await import(\"../../application-state/script-helpers.js\");\n const nonce = Date.now();\n const scope = typeof args?.scope === \"string\" ? args.scope : undefined;\n await writeAppState(SCREEN_REFRESH_KEY, {\n nonce,\n ...(scope ? { scope } : {}),\n });\n return `refreshed${scope ? ` (scope: ${scope})` : \"\"}`;\n },\n },\n };\n}\n\n/** Well-known application-state key used by the refresh-screen tool. */\nconst SCREEN_REFRESH_KEY = \"__screen_refresh__\";\nconst SAFE_BROWSER_TAB_ID_RE = /^[A-Za-z0-9_-]{1,96}$/;\n\nexport function appStateKeyForBrowserTab(\n key: string,\n browserTabId: unknown,\n): string {\n if (typeof browserTabId !== \"string\") return key;\n const trimmed = browserTabId.trim();\n return SAFE_BROWSER_TAB_ID_RE.test(trimmed) ? `${key}:${trimmed}` : key;\n}\n\n/**\n * Creates the `set-search-params` / `set-url-path` tools. Writes a one-shot\n * URL command to application_state; the client's URLSync component applies\n * it via react-router (no full page reload) and then deletes the command.\n *\n * This is how the agent edits URL state — filter query params, route\n * changes, hash — without needing a per-template navigate action. The\n * current URL is visible to the agent via the auto-injected `<current-url>`\n * block, which includes parsed search params.\n */\nexport function createUrlTools(): Record<string, ActionEntry> {\n return {\n \"set-search-params\": {\n // Writes __set_url__ to application_state, which the app-state watcher\n // already surfaces as a poll event. No need to double-emit.\n readOnly: true,\n tool: {\n description:\n \"Update the URL query string on the user's current page. Use this to change dashboard/list filters, search terms, or any other state the app stores in `?foo=bar` style query params. One-shot — the UI applies it in ~1s without a page reload. See the current URL + parsed search params in the auto-injected `<current-url>` block. Keys are the exact query param names as they appear in the URL (e.g. `f_pubDateStart`, not just `pubDateStart`). Set a value to null or empty string to clear that param. By default merges over existing params — pass `merge: false` to replace them all.\",\n parameters: {\n type: \"object\",\n properties: {\n params: {\n type: \"object\",\n description:\n 'Map of query param → value. Each value is a string, or null/\"\" to clear. Example: {\"f_pubDateStart\": null, \"f_cadence\": \"MONTH\"}.',\n },\n merge: {\n type: \"string\",\n description:\n '\"true\" (default) merges over existing params; \"false\" replaces them entirely.',\n enum: [\"true\", \"false\"],\n },\n },\n required: [\"params\"],\n },\n },\n run: async (args) => {\n const params = (args?.params ?? {}) as unknown as Record<\n string,\n string | null\n >;\n const merge = (args as any)?.merge !== \"false\";\n const { writeAppState } =\n await import(\"../../application-state/script-helpers.js\");\n await writeAppState(\n appStateKeyForBrowserTab(\n \"__set_url__\",\n getRequestRunContext()?.browserTabId,\n ),\n {\n searchParams: params,\n mergeSearchParams: merge,\n // Unique-per-write token. The client's URLSync hook dedups by this\n // so a fire-and-forget DELETE that loses its race against the next\n // polling refetch can't cause the same URL command to be applied\n // repeatedly (which caused the editor to bounce between slides\n // when an agent turn errored partway through).\n _writeId: `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,\n },\n );\n const keys = Object.keys(params);\n return `set-search-params: ${keys.length} key${keys.length === 1 ? \"\" : \"s\"}${merge ? \"\" : \" (replace)\"}`;\n },\n },\n \"set-url-path\": {\n // Same as set-search-params — writes application_state, already emits\n // via the app-state watcher.\n readOnly: true,\n tool: {\n description:\n \"Navigate the user to a different pathname, optionally also setting search params. For most template-specific routing prefer the template's `navigate` action if it exists — this is the generic fallback. One-shot, applied by the client without a page reload.\",\n parameters: {\n type: \"object\",\n properties: {\n pathname: {\n type: \"string\",\n description: \"New URL pathname (e.g. '/adhoc/weekly').\",\n },\n params: {\n type: \"object\",\n description:\n 'Optional query params to set alongside the path change. String values set, null/\"\" clears.',\n },\n merge: {\n type: \"string\",\n description:\n '\"true\" (default) merges over existing params; \"false\" starts fresh.',\n enum: [\"true\", \"false\"],\n },\n },\n required: [\"pathname\"],\n },\n },\n run: async (args) => {\n const pathname = String(args?.pathname ?? \"\");\n if (!pathname.startsWith(\"/\")) {\n return \"Error: pathname must start with '/'.\";\n }\n const params = (args?.params ?? {}) as unknown as Record<\n string,\n string | null\n >;\n const merge = (args as any)?.merge !== \"false\";\n const { writeAppState } =\n await import(\"../../application-state/script-helpers.js\");\n await writeAppState(\n appStateKeyForBrowserTab(\n \"__set_url__\",\n getRequestRunContext()?.browserTabId,\n ),\n {\n pathname,\n searchParams: params,\n mergeSearchParams: merge,\n // See note in set-search-params: unique-per-write dedup token so a\n // race between GET and consume-DELETE in URLSync can't re-apply\n // this command.\n _writeId: `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,\n },\n );\n return `set-url-path: ${pathname}`;\n },\n },\n \"ask-question\": {\n tool: {\n description:\n \"Ask the user a multiple-choice clarifying question and render it inline in the chat. Use this ONLY when you are genuinely blocked on a decision you cannot resolve from context and a wrong guess would be costly — an ambiguous metric, date range, or grain; a real fork in approach. Present 2-5 concrete options and mark the most likely one recommended. Do NOT use it for confirmations, for things the user already specified, or to dodge easy work you could just do. Ask at most once per turn. Calling this yields the turn: stop and wait for the user's answer.\",\n parameters: {\n type: \"object\",\n properties: {\n question: {\n type: \"string\",\n description:\n \"The complete question to ask the user. Clear, specific, ends with a question mark.\",\n },\n header: {\n type: \"string\",\n description:\n 'Optional very short label (max ~12 chars) shown as a chip/heading above the question, e.g. \"Date range\", \"Approach\", \"Library\".',\n },\n options: {\n type: \"string\",\n description:\n 'A JSON array of 2-4 distinct, mutually-exclusive options (unless `allowMultiple` is true), each `{ \"label\": string, \"value\"?: string, \"description\"?: string, \"preview\"?: string, \"recommended\"?: boolean }`. `label` is 1-5 words; `description` explains the trade-off; `preview` is optional content (mockup, code snippet, short comparison) rendered under the option. `value` defaults to `label` when omitted. Mark the most likely option `\"recommended\": true`. Do NOT add an \"Other\" option — free text is provided automatically when `allowFreeText` is on.',\n },\n allowFreeText: {\n type: \"string\",\n description:\n 'Whether the user may also type a free-text \"Other\" answer. \"true\" (default) or \"false\".',\n enum: [\"true\", \"false\"],\n },\n allowMultiple: {\n type: \"string\",\n description:\n 'Whether the user may select more than one option (multi-select). \"true\" or \"false\" (default).',\n enum: [\"true\", \"false\"],\n },\n },\n required: [\"question\", \"options\"],\n },\n },\n run: async (args) => {\n const question = String(args?.question ?? \"\").trim();\n if (!question) return \"Error: 'question' is required.\";\n const header = String(args?.header ?? \"\").trim();\n const allowMultiple = String(args?.allowMultiple ?? \"\") === \"true\";\n const allowFreeText = String(args?.allowFreeText ?? \"true\") !== \"false\";\n\n let parsedOptions: unknown;\n try {\n parsedOptions = JSON.parse(String(args?.options ?? \"[]\"));\n } catch {\n return \"Error: 'options' must be a JSON array of { label, value?, description?, recommended? }.\";\n }\n if (!Array.isArray(parsedOptions) || parsedOptions.length === 0) {\n return \"Error: 'options' must be a non-empty JSON array of { label, value?, description?, recommended? }.\";\n }\n\n type AskOption = {\n label: string;\n value: string;\n description?: string;\n preview?: string;\n recommended?: boolean;\n };\n const options = parsedOptions\n .map((raw): AskOption | null => {\n const opt = (raw ?? {}) as Record<string, unknown>;\n const label =\n typeof opt.label === \"string\" && opt.label.trim()\n ? opt.label.trim()\n : typeof opt.value === \"string\"\n ? String(opt.value).trim()\n : \"\";\n if (!label) return null;\n const value =\n typeof opt.value === \"string\" && opt.value.trim()\n ? opt.value.trim()\n : label;\n const option: AskOption = { label, value };\n if (typeof opt.description === \"string\" && opt.description.trim()) {\n option.description = opt.description.trim();\n }\n if (typeof opt.preview === \"string\" && opt.preview.trim()) {\n option.preview = opt.preview;\n }\n if (opt.recommended === true) option.recommended = true;\n return option;\n })\n .filter((opt): opt is AskOption => opt !== null);\n if (options.length === 0) {\n return \"Error: 'options' must contain at least one option with a label.\";\n }\n\n // Shape must match the GuidedQuestionFlow renderer in\n // client/guided-questions.tsx: a `text-options` question whose options\n // carry `value`, with `multiSelect` for multi-pick and `allowOther` for\n // free text. The renderer otherwise injects \"Explore\"/\"Decide\" options,\n // which would be noise for a focused clarifying question, so disable them.\n const payload = {\n questions: [\n {\n id: \"q1\",\n type: \"text-options\" as const,\n question,\n ...(header ? { header } : {}),\n required: !allowFreeText,\n multiSelect: allowMultiple,\n allowOther: allowFreeText,\n includeExplore: false,\n includeDecide: false,\n options,\n },\n ],\n };\n\n const { writeAppState } =\n await import(\"../../application-state/script-helpers.js\");\n await writeAppState(\n appStateKeyForBrowserTab(\n \"guided-questions\",\n getRequestRunContext()?.browserTabId,\n ),\n payload,\n );\n return \"Asked the user a clarifying question and rendered it in the chat. Stop here and wait for their answer — do not proceed or assume an answer.\";\n },\n },\n };\n}\n\nexport function createDataWidgetActionEntries(): Record<string, ActionEntry> {\n return {\n \"render-data-widget\": {\n readOnly: true,\n parallelSafe: true,\n chatUI: {\n renderer: ACTION_CHAT_UI_DATA_WIDGET_RENDERER,\n title: \"Data widget\",\n description: \"Render a validated native data table or chart in chat.\",\n },\n tool: {\n description:\n \"Render a native Agent-Native chat data widget from compact, real data you already retrieved or the user provided. Use this for in-chat tables, charts, graphs, trends, and compact reports when no domain-specific action already returns a native widget. Never fabricate rows or metrics just to make a chart.\",\n parameters: {\n type: \"object\",\n properties: {\n widget: {\n type: \"string\",\n enum: [\"data-table\", \"data-chart\", \"data-insights\"],\n description:\n \"Widget kind. Use data-chart for a chart, data-table for a table, or data-insights for a combined summary/chart/table card.\",\n },\n widgetId: {\n type: \"string\",\n description: \"Optional stable widget identifier.\",\n },\n title: {\n type: \"string\",\n description: \"Optional widget title.\",\n },\n summary: {\n type: \"object\",\n description:\n \"Optional scalar summary values for data-insights cards.\",\n },\n display: {\n type: \"object\",\n description:\n \"Optional display metadata: title, description, primaryAction.\",\n },\n table: {\n type: \"object\",\n description:\n \"For data-table/data-insights: { title?, columns: [{ key, label, align? }], rows, totalRows?, sampledRows?, truncated? }.\",\n },\n chartSeries: {\n type: \"object\",\n description:\n \"For data-chart/data-insights: { type: 'bar'|'line'|'area', title?, xKey, series: [{ key, label, color? }], data, sampled? }.\",\n },\n },\n required: [\"widget\"],\n },\n },\n run: async (args) => dataWidgetResultSchema.parse(args),\n },\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"context-tools.js","sourceRoot":"","sources":["../../../src/server/agent-chat/context-tools.ts"],"names":[],"mappings":"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","sourcesContent":["import { ACTION_CHAT_UI_DATA_WIDGET_RENDERER } from \"../../action-ui.js\";\nimport type { ActionEntry } from \"../../agent/production-agent.js\";\nimport { dataWidgetResultSchema } from \"../../data-widgets/index.js\";\nimport { getRequestRunContext } from \"../request-context.js\";\n\n// ---------------------------------------------------------------------------\n// Framework-owned \"context\" action entries: get-framework-context,\n// refresh-screen, the URL/ask-question tools, and the native data-widget\n// renderer. These are generic, template-agnostic tools registered into every\n// app's tool surface.\n// ---------------------------------------------------------------------------\n\n/**\n * Verbose framework sections returned by the `get-framework-context` tool.\n * Keyed by topic so the agent can request specific sections.\n * Not template-specific — lives outside buildFrameworkPrompts().\n */\nexport const FRAMEWORK_CONTEXT_SECTIONS: Record<string, string> = {\n embeds: `### Inline Embeds\n\nYou can embed an interactive view inline in your chat reply by writing an \\`embed\\` fenced code block. The chat renderer swaps the fence for a sandboxed iframe pointing at a route inside this app.\n\nSyntax:\n\n\\`\\`\\`\\`\n\\`\\`\\`embed\nsrc: /some/path?param=value\naspect: 16/9\ntitle: Optional label\n\\`\\`\\`\n\\`\\`\\`\\`\n\nKeys:\n- \\`src\\` (required) — **must be a same-origin path starting with \\`/\\`**. Cross-origin URLs are blocked. No \\`javascript:\\` or \\`data:\\` URLs.\n- \\`aspect\\` (optional) — one of \\`16/9\\` (default), \\`4/3\\`, \\`3/2\\`, \\`2/1\\`, \\`21/9\\`, \\`1/1\\`.\n- \\`title\\` (optional) — accessible label / hover tooltip.\n- \\`height\\` (optional) — fixed pixel height when aspect ratio isn't a good fit.\n\nUse for charts, visualizations, previews. Don't use for simple text/tables or external sites.`,\n\n \"chat-history\": `### Chat History\n\nYou can search and restore previous chat conversations using \\`chat-history\\`:\n- \\`chat-history\\` (action: \"search\") — Search or list past chat threads by keyword. Archived threads are excluded by default; pass \\`includeArchived: true\\` to also see them.\n- \\`chat-history\\` (action: \"open\") — Open a chat thread in the UI as a new tab and focus it\n- \\`chat-history\\` (actions: \"rename\", \"pin\", \"unpin\", \"archive\") — Organize a known chat thread by ID. Archiving a thread hides it from the default chat list and search.\n\nWhen the user asks to find a previous conversation, use \\`chat-history\\` with action \"search\" first to find matching threads, then action \"open\" to restore the one they want.`,\n\n \"agent-teams\": `### Agent Teams — Orchestration\n\nYou can delegate to background sub-agents with the \\`agent-teams\\` tool:\n- \\`agent-teams\\` (action: \"spawn\") — Launch a sub-agent on a task. It runs in its own thread with a clean context while you stay available; a live preview card appears in the chat. The spawn result confirms launch only, not completion. Optionally pass a custom agent profile from \\`agents/*.md\\` via the \\`agent\\` parameter.\n- \\`agent-teams\\` (action: \"status\") — Check a running sub-agent's progress.\n- \\`agent-teams\\` (action: \"read-result\") — Read a finished sub-agent's output.\n- \\`agent-teams\\` (action: \"send\") — Message a running sub-agent.\n- \\`agent-teams\\` (action: \"list\") — List sub-agent tasks.\n\nSub-agents inherit all of your template tools but **cannot spawn sub-agents themselves** — only you orchestrate.\n\n**User intent phrases.** If the user asks you to use a \"sub-agent\" or \"background agent\", that is explicit delegation intent. Also treat phrases like \"run these in the background\", \"kick off the rest\", \"run the queued items\", \"batch run these jobs\", \"parallelize this\", or \"start the next batch\" as delegation intent when the context is a set of independent work items.\n\n**Spawn is not completion.** A successful \\`spawn\\` call means the sub-agent started and is running. Tell the user it started, show the task id if useful, and then use \\`status\\`/\\`list\\`/\\`read-result\\` to monitor it. Never say the delegated task \"completed\", \"ran successfully\", or \"finished\" until \\`status\\` or \\`read-result\\` reports \\`completed\\` or \\`errored\\`. If a task is still running, say that plainly.\n\n**Default to doing the work yourself in this thread.** A sub-agent costs real tokens and adds a merge step, so reach for one only when delegation clearly pays for that overhead.\n\n**Delegate ONE sub-agent** when a task is self-contained and heavy: deep research, long multi-step content generation, or a noisy scan whose intermediate steps would clutter this thread. The sub-agent gets its own clean context and hands you back a distilled result.\n\n**Fan out to MULTIPLE sub-agents ONLY** for units of work that are genuinely independent and don't depend on each other's decisions — e.g. research three unrelated competitors, summarize five separate threads, draft sections that don't reference one another. Each gets a distinct slice.\n\n**Do NOT parallelize tightly-coupled work** — one cohesive artifact, edits that must agree with each other, or anything needing a single consistent voice or style. Parallel sub-agents can't see each other's choices and their outputs will clash. For coupled work, do it yourself, or chain sub-agents one at a time, feeding each result into the next.\n\n**Cap fan-out:** aim for 1, use up to ~3, and go beyond that only for clearly independent bulk work. More sub-agents means more tokens and a harder merge.\n\n**Briefing contract.** A sub-agent starts in a fresh thread and can only see the brief you give it — it cannot see this conversation or ask you to clarify before it runs. Make every brief self-contained:\n1. **Objective** — what \"done\" looks like, in a sentence or two.\n2. **Context** — the specific facts it needs from this conversation: IDs, names, the user's actual goal, constraints, prior decisions. Paste the specifics; don't assume it knows them.\n3. **Output format** — what to return and how (e.g. \"a 3-bullet summary with source links\", \"the drafted email body only\") so the result drops cleanly into your synthesis.\n4. **Boundaries** — what NOT to do, and for parallel sub-agents, which slice is theirs so they don't overlap.\n\nPut the objective and output format in \\`task\\`; put longer context in \\`instructions\\`.\n\n**Synthesis discipline.** After the sub-agents you depend on finish, poll \\`status\\`/\\`list\\` until they're complete, then pull each one's output with \\`read-result\\`. Do NOT paste their outputs back to back. Read all results, reconcile any disagreements, de-duplicate, and write ONE integrated answer in your own voice. If two sub-agents conflict, resolve it or flag the discrepancy explicitly rather than presenting both. When findings came from distinct investigations, briefly note which finding came from where so the user can trust the merge.`,\n\n \"recurring-jobs\": `### Recurring Jobs\n\nYou can create recurring jobs that run on a cron schedule. Jobs are resource files under \\`jobs/\\`.\n\n- \\`manage-jobs\\` (action: \"create\") — Create a new recurring job with a cron schedule and instructions\n- \\`manage-jobs\\` (action: \"list\") — List all recurring jobs and their status\n- \\`manage-jobs\\` (action: \"update\") — Update a job's schedule, instructions, or toggle enabled/disabled\n- Delete a job with the \\`resources\\` tool: \\`action: \"delete\"\\`, \\`path: \"jobs/<name>.md\"\\`\n\nConvert natural language to 5-field cron format:\n- \"every morning\" / \"daily at 9am\" → \\`0 9 * * *\\`\n- \"every weekday at 9am\" → \\`0 9 * * 1-5\\`\n- \"every hour\" → \\`0 * * * *\\`\n- \"every monday at 9am\" → \\`0 9 * * 1\\`\n\nWhen a recurring job needs a connected MCP, discover the exact MCP tool names\navailable in the current user/org context and pass them in the create call's\n\\`mcpTools\\` array. Bind only the tools the job needs; do not put an MCP URL,\nOAuth token, or arbitrary endpoint in the instructions. The scheduler resolves\nthe selected tools with the job owner's existing connector grant and fails\nclearly if a connector is revoked or a selected tool disappears. For imports,\nnormalize the provider response and call the app's bounded idempotent import\naction once with the full batch rather than issuing one write per item.\n\n#### Suggesting \"Save as automation\"\n\nWhen you finish a task that has obvious recurring value — daily inbox triage, weekly metrics summaries, archive sweeps, status digests, anything the user would plausibly want re-run on a fresh cadence — close the response with ONE short line offering to save it. Examples:\n\n- After \"Summarize my unread emails\": _\"Want me to run this every morning?\"_\n- After \"What's our top traffic source this week\": _\"Want a weekly digest on Mondays?\"_\n- After \"Archive emails older than 30 days\": _\"Should I run this every Sunday?\"_\n\nIf the user says yes, call \\`manage-jobs\\` (action: \"create\") with the original prompt as the job's instructions and the cadence they confirmed.\n\nDo NOT add this offer for one-shot work: lookups (find Alice, what's the schema, who reported X), single drafts/replies, navigation requests, or any task whose value is in the moment. Skip it when the prompt is already explicitly recurring (the user said \"every morning…\" — you'd be asking what they already told you). One short sentence at most; do not turn it into a list of cadence options.`,\n\n builder: `### Connecting Builder.io\n\nWhen the user asks to connect Builder.io or you hit a \"Builder not configured\" error, call the \\`connect-builder\\` tool. It renders a Connect/code-change card inline — do NOT write out multi-step setup instructions yourself. Inspect the returned \\`builderEnabled\\` flag: \\`true\\` means Builder Cloud Agents can take the code-change handoff, while \\`false\\` means this requires a code change and the user should edit locally or use Builder.io to edit this code in the cloud and continue customizing the app any way they like. If Builder Cloud Agents are not available for this workspace, never send the user to Builder org settings or beta settings.`,\n\n browser: `### Browser Automation\n\nYou can activate a real Chrome browser via Builder.io for tasks that need full page rendering:\n- Extracting design tokens from JS-heavy or SPA websites (computed styles, rendered colors/fonts)\n- Taking screenshots of live pages\n- Testing interactive flows on deployed URLs\n- Reading content from pages that require JavaScript execution\n\n**How to use:**\n1. In local development, call \\`set-browser-control\\` with \\`{\"enabled\":true,\"backend\":\"chrome-devtools\"}\\` after confirming once with the user. In production, use \\`activate-browser\\` for Builder-provisioned Chrome.\n2. On your next action, use \\`mcp__chrome-devtools__navigate_page\\`, \\`mcp__chrome-devtools__evaluate_script\\`, \\`mcp__chrome-devtools__take_screenshot\\`, etc.\n3. If Builder is not connected, call \\`connect-builder\\` first\n\n**When to recommend browser automation:**\n- User wants to import a design system from a URL (JS-rendered sites give almost no useful data from plain HTML fetch)\n- User asks you to check how a deployed site looks or behaves\n- Any task involving reading computed/rendered page state\n- When \\`web-request\\` returns minimal/skeleton HTML from a modern SPA\n\nPrefer \\`web-request\\` for simple API calls and static pages. Use browser automation when you need the real rendered page.`,\n\n \"call-agent\": `### call-agent — External Apps Only\n\nThe \\`call-agent\\` tool sends a message to a DIFFERENT, separately-deployed app's agent (A2A protocol). It is **not** for calling actions within the current app.\n\n**NEVER use \\`call-agent\\` to:**\n- Call your own app by name\n- Perform tasks you can accomplish with your own registered tools\n\n**ONLY use \\`call-agent\\` when:**\n- The user explicitly asks you to communicate with a different app\n- You need data that only another deployed app can provide\n- You need brand-consistent generated media and this app does not have a native generation action; call agent \"assets\" and keep returned asset IDs and URLs verbatim\n\nIf \\`call-agent\\` says a downstream agent accepted the subtask and will post its result separately, do not call that same agent again for the same subtask. Continue any remaining work and answer with the completed results you have.`,\n\n memory: `### Structured Memory\n\nYour memory index (\\`memory/MEMORY.md\\`) is loaded at the start of every conversation.\n\n**Tools:**\n- \\`save-memory\\` — Create or update a memory (name, type, description, content)\n- \\`delete-memory\\` — Remove a memory and its index entry\n- \\`resources\\` with \\`action: \"read\"\\` and \\`path: \"memory/<name>.md\"\\` — Read the full content of a specific memory\n\n**Memory types:** user, feedback, project, reference\n\n**When to save (proactively):**\n- User corrects your approach → \\`feedback\\`\n- User shares preferences → \\`user\\`\n- Non-obvious pattern or gotcha → \\`feedback\\`\n- Personal context (contacts, team) → \\`user\\`\n- Project context to track → \\`project\\`\n\n**Rules:**\n- Don't save things obvious from code or standard framework behavior\n- When updating, read first and merge — don't overwrite\n- Keep descriptions concise\n- One memory per logical topic`,\n\n \"sql-tools\": `### SQL Tools\n\nWhen database tools are enabled, \\`db-schema\\` refreshes the schema and \\`db-query\\` runs read-only SELECT queries with current user/org scoping. Raw SQL write tools are only available when the app explicitly opts into database write tools; by default, writes go through typed app actions. Some apps configure database tools as read-only or off; only use tools that are actually present in your tool list.\n\n- \\`db-schema\\` — refresh the full schema with indexes and foreign keys\n- \\`db-query\\` — run a SELECT (read-only; results already filtered to the current user/org)\n- \\`db-exec\\` — only when present: run INSERT / UPDATE / DELETE / REPLACE for scoped maintenance. For normal product data writes, use a typed app action instead.\n- \\`db-patch\\` — only when present: surgical search-and-replace on a large text column. If a typed app action exists for the resource, use that action.\n\n### When to pick which SQL tool\n- A template-specific action exists for the table → use that action (it encodes business rules and pushes live Yjs updates)\n- Read data → \\`db-query\\`. Never re-add \\`WHERE owner_email = ...\\` — scoping already applies it.\n- Raw write tools are present and no app action exists → use \\`db-exec\\` or \\`db-patch\\` only for deliberate maintenance, not normal product workflows.\n\n### External data sources vs the app database\nThe \\`db-*\\` tools ONLY query the app's own SQL database. They do NOT reach external data warehouses. If the user asks about tables NOT in the schema, use the appropriate template action instead.`,\n};\n\nexport function createFrameworkContextEntry(): Record<string, ActionEntry> {\n const topicList = Object.keys(FRAMEWORK_CONTEXT_SECTIONS).join(\", \");\n return {\n \"get-framework-context\": {\n tool: {\n description: `Read detailed framework instructions for a specific capability. Available topics: ${topicList}. Call with topic=\"all\" to get everything.`,\n parameters: {\n type: \"object\" as const,\n properties: {\n topic: {\n type: \"string\",\n description: `Topic to read. One of: ${topicList}, or \"all\" for everything.`,\n },\n },\n required: [\"topic\"],\n },\n },\n run: async (args: Record<string, string>) => {\n const topic = String(args.topic ?? \"all\").toLowerCase();\n if (topic === \"all\") {\n return Object.values(FRAMEWORK_CONTEXT_SECTIONS).join(\"\\n\\n\");\n }\n const section = FRAMEWORK_CONTEXT_SECTIONS[topic];\n if (!section) {\n return `Unknown topic \"${topic}\". Available: ${topicList}`;\n }\n return section;\n },\n readOnly: true,\n },\n };\n}\n\n/**\n * Creates the `refresh-screen` tool. Writes a bump to `application_state`\n * under a well-known key; the client's `useDbSync` watches for this and\n * invalidates react-query caches so the on-screen UI re-fetches its data\n * without a full page reload.\n *\n * This is the standard way for the agent to say \"the data on the screen\n * just changed, please refresh it\" — e.g. after editing a dashboard config,\n * updating a form schema, or mutating a row that the current view renders.\n */\nexport function createRefreshScreenEntry(): Record<string, ActionEntry> {\n return {\n \"refresh-screen\": {\n // Writes __screen_refresh__ to application_state, which emits its own\n // distinct `screen-refresh` poll event. Don't double-emit a generic\n // `action` event on top of that.\n readOnly: true,\n // Refetching volatile on-screen state is the entire point of this\n // tool — an identical repeat call (even with the same scope) is a\n // legitimate re-refresh, not a redundant read to skip.\n dedupe: false,\n tool: {\n description:\n \"Manually refresh the user's current screen. The framework ALREADY auto-refreshes after any successful mutating action tool call (template actions and any enabled raw DB write tools) — you do NOT need to call this after a normal action. Use it only when (a) you mutated data via a path the framework can't detect (e.g. a direct write to an external system the app mirrors), or (b) you want to pass a `scope` hint so the UI narrows which queries to refetch. The UI re-fetches its queries without a full page reload.\",\n parameters: {\n type: \"object\",\n properties: {\n scope: {\n type: \"string\",\n description:\n \"Optional hint describing what changed (e.g. 'dashboard', 'form', 'settings'). Templates may use it to narrow which queries to invalidate; if omitted, all queries are invalidated.\",\n },\n },\n },\n },\n run: async (args) => {\n const { writeAppState } =\n await import(\"../../application-state/script-helpers.js\");\n const nonce = Date.now();\n const scope = typeof args?.scope === \"string\" ? args.scope : undefined;\n await writeAppState(SCREEN_REFRESH_KEY, {\n nonce,\n ...(scope ? { scope } : {}),\n });\n return `refreshed${scope ? ` (scope: ${scope})` : \"\"}`;\n },\n },\n };\n}\n\n/** Well-known application-state key used by the refresh-screen tool. */\nconst SCREEN_REFRESH_KEY = \"__screen_refresh__\";\nconst SAFE_BROWSER_TAB_ID_RE = /^[A-Za-z0-9_-]{1,96}$/;\n\nexport function appStateKeyForBrowserTab(\n key: string,\n browserTabId: unknown,\n): string {\n if (typeof browserTabId !== \"string\") return key;\n const trimmed = browserTabId.trim();\n return SAFE_BROWSER_TAB_ID_RE.test(trimmed) ? `${key}:${trimmed}` : key;\n}\n\n/**\n * Creates the `set-search-params` / `set-url-path` tools. Writes a one-shot\n * URL command to application_state; the client's URLSync component applies\n * it via react-router (no full page reload) and then deletes the command.\n *\n * This is how the agent edits URL state — filter query params, route\n * changes, hash — without needing a per-template navigate action. The\n * current URL is visible to the agent via the auto-injected `<current-url>`\n * block, which includes parsed search params.\n */\nexport function createUrlTools(): Record<string, ActionEntry> {\n return {\n \"set-search-params\": {\n // Writes __set_url__ to application_state, which the app-state watcher\n // already surfaces as a poll event. No need to double-emit.\n readOnly: true,\n tool: {\n description:\n \"Update the URL query string on the user's current page. Use this to change dashboard/list filters, search terms, or any other state the app stores in `?foo=bar` style query params. One-shot — the UI applies it in ~1s without a page reload. See the current URL + parsed search params in the auto-injected `<current-url>` block. Keys are the exact query param names as they appear in the URL (e.g. `f_pubDateStart`, not just `pubDateStart`). Set a value to null or empty string to clear that param. By default merges over existing params — pass `merge: false` to replace them all.\",\n parameters: {\n type: \"object\",\n properties: {\n params: {\n type: \"object\",\n description:\n 'Map of query param → value. Each value is a string, or null/\"\" to clear. Example: {\"f_pubDateStart\": null, \"f_cadence\": \"MONTH\"}.',\n },\n merge: {\n type: \"string\",\n description:\n '\"true\" (default) merges over existing params; \"false\" replaces them entirely.',\n enum: [\"true\", \"false\"],\n },\n },\n required: [\"params\"],\n },\n },\n run: async (args) => {\n const params = (args?.params ?? {}) as unknown as Record<\n string,\n string | null\n >;\n const merge = (args as any)?.merge !== \"false\";\n const { writeAppState } =\n await import(\"../../application-state/script-helpers.js\");\n await writeAppState(\n appStateKeyForBrowserTab(\n \"__set_url__\",\n getRequestRunContext()?.browserTabId,\n ),\n {\n searchParams: params,\n mergeSearchParams: merge,\n // Unique-per-write token. The client's URLSync hook dedups by this\n // so a fire-and-forget DELETE that loses its race against the next\n // polling refetch can't cause the same URL command to be applied\n // repeatedly (which caused the editor to bounce between slides\n // when an agent turn errored partway through).\n _writeId: `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,\n },\n );\n const keys = Object.keys(params);\n return `set-search-params: ${keys.length} key${keys.length === 1 ? \"\" : \"s\"}${merge ? \"\" : \" (replace)\"}`;\n },\n },\n \"set-url-path\": {\n // Same as set-search-params — writes application_state, already emits\n // via the app-state watcher.\n readOnly: true,\n tool: {\n description:\n \"Navigate the user to a different pathname, optionally also setting search params. For most template-specific routing prefer the template's `navigate` action if it exists — this is the generic fallback. One-shot, applied by the client without a page reload.\",\n parameters: {\n type: \"object\",\n properties: {\n pathname: {\n type: \"string\",\n description: \"New URL pathname (e.g. '/adhoc/weekly').\",\n },\n params: {\n type: \"object\",\n description:\n 'Optional query params to set alongside the path change. String values set, null/\"\" clears.',\n },\n merge: {\n type: \"string\",\n description:\n '\"true\" (default) merges over existing params; \"false\" starts fresh.',\n enum: [\"true\", \"false\"],\n },\n },\n required: [\"pathname\"],\n },\n },\n run: async (args) => {\n const pathname = String(args?.pathname ?? \"\");\n if (!pathname.startsWith(\"/\")) {\n return \"Error: pathname must start with '/'.\";\n }\n const params = (args?.params ?? {}) as unknown as Record<\n string,\n string | null\n >;\n const merge = (args as any)?.merge !== \"false\";\n const { writeAppState } =\n await import(\"../../application-state/script-helpers.js\");\n await writeAppState(\n appStateKeyForBrowserTab(\n \"__set_url__\",\n getRequestRunContext()?.browserTabId,\n ),\n {\n pathname,\n searchParams: params,\n mergeSearchParams: merge,\n // See note in set-search-params: unique-per-write dedup token so a\n // race between GET and consume-DELETE in URLSync can't re-apply\n // this command.\n _writeId: `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,\n },\n );\n return `set-url-path: ${pathname}`;\n },\n },\n \"ask-question\": {\n tool: {\n description:\n \"Ask the user a multiple-choice clarifying question and render it inline in the chat. Use this ONLY when you are genuinely blocked on a decision you cannot resolve from context and a wrong guess would be costly — an ambiguous metric, date range, or grain; a real fork in approach. Present 2-5 concrete options and mark the most likely one recommended. Do NOT use it for confirmations, for things the user already specified, or to dodge easy work you could just do. Ask at most once per turn. Calling this yields the turn: stop and wait for the user's answer.\",\n parameters: {\n type: \"object\",\n properties: {\n question: {\n type: \"string\",\n description:\n \"The complete question to ask the user. Clear, specific, ends with a question mark.\",\n },\n header: {\n type: \"string\",\n description:\n 'Optional very short label (max ~12 chars) shown as a chip/heading above the question, e.g. \"Date range\", \"Approach\", \"Library\".',\n },\n options: {\n type: \"string\",\n description:\n 'A JSON array of 2-4 distinct, mutually-exclusive options (unless `allowMultiple` is true), each `{ \"label\": string, \"value\"?: string, \"description\"?: string, \"preview\"?: string, \"recommended\"?: boolean }`. `label` is 1-5 words; `description` explains the trade-off; `preview` is optional content (mockup, code snippet, short comparison) rendered under the option. `value` defaults to `label` when omitted. Mark the most likely option `\"recommended\": true`. Do NOT add an \"Other\" option — free text is provided automatically when `allowFreeText` is on.',\n },\n allowFreeText: {\n type: \"string\",\n description:\n 'Whether the user may also type a free-text \"Other\" answer. \"true\" (default) or \"false\".',\n enum: [\"true\", \"false\"],\n },\n allowMultiple: {\n type: \"string\",\n description:\n 'Whether the user may select more than one option (multi-select). \"true\" or \"false\" (default).',\n enum: [\"true\", \"false\"],\n },\n },\n required: [\"question\", \"options\"],\n },\n },\n run: async (args) => {\n const question = String(args?.question ?? \"\").trim();\n if (!question) return \"Error: 'question' is required.\";\n const header = String(args?.header ?? \"\").trim();\n const allowMultiple = String(args?.allowMultiple ?? \"\") === \"true\";\n const allowFreeText = String(args?.allowFreeText ?? \"true\") !== \"false\";\n\n let parsedOptions: unknown;\n try {\n parsedOptions = JSON.parse(String(args?.options ?? \"[]\"));\n } catch {\n return \"Error: 'options' must be a JSON array of { label, value?, description?, recommended? }.\";\n }\n if (!Array.isArray(parsedOptions) || parsedOptions.length === 0) {\n return \"Error: 'options' must be a non-empty JSON array of { label, value?, description?, recommended? }.\";\n }\n\n type AskOption = {\n label: string;\n value: string;\n description?: string;\n preview?: string;\n recommended?: boolean;\n };\n const options = parsedOptions\n .map((raw): AskOption | null => {\n const opt = (raw ?? {}) as Record<string, unknown>;\n const label =\n typeof opt.label === \"string\" && opt.label.trim()\n ? opt.label.trim()\n : typeof opt.value === \"string\"\n ? String(opt.value).trim()\n : \"\";\n if (!label) return null;\n const value =\n typeof opt.value === \"string\" && opt.value.trim()\n ? opt.value.trim()\n : label;\n const option: AskOption = { label, value };\n if (typeof opt.description === \"string\" && opt.description.trim()) {\n option.description = opt.description.trim();\n }\n if (typeof opt.preview === \"string\" && opt.preview.trim()) {\n option.preview = opt.preview;\n }\n if (opt.recommended === true) option.recommended = true;\n return option;\n })\n .filter((opt): opt is AskOption => opt !== null);\n if (options.length === 0) {\n return \"Error: 'options' must contain at least one option with a label.\";\n }\n\n // Shape must match the GuidedQuestionFlow renderer in\n // client/guided-questions.tsx: a `text-options` question whose options\n // carry `value`, with `multiSelect` for multi-pick and `allowOther` for\n // free text. The renderer otherwise injects \"Explore\"/\"Decide\" options,\n // which would be noise for a focused clarifying question, so disable them.\n const payload = {\n questions: [\n {\n id: \"q1\",\n type: \"text-options\" as const,\n question,\n ...(header ? { header } : {}),\n required: !allowFreeText,\n multiSelect: allowMultiple,\n allowOther: allowFreeText,\n includeExplore: false,\n includeDecide: false,\n options,\n },\n ],\n };\n\n const { writeAppState } =\n await import(\"../../application-state/script-helpers.js\");\n await writeAppState(\n appStateKeyForBrowserTab(\n \"guided-questions\",\n getRequestRunContext()?.browserTabId,\n ),\n payload,\n );\n return \"Asked the user a clarifying question and rendered it in the chat. Stop here and wait for their answer — do not proceed or assume an answer.\";\n },\n },\n };\n}\n\nexport function createDataWidgetActionEntries(): Record<string, ActionEntry> {\n return {\n \"render-data-widget\": {\n readOnly: true,\n parallelSafe: true,\n chatUI: {\n renderer: ACTION_CHAT_UI_DATA_WIDGET_RENDERER,\n title: \"Data widget\",\n description: \"Render a validated native data table or chart in chat.\",\n },\n tool: {\n description:\n \"Render a native Agent-Native chat data widget from compact, real data you already retrieved or the user provided. Use this for in-chat tables, charts, graphs, trends, and compact reports when no domain-specific action already returns a native widget. Never fabricate rows or metrics just to make a chart.\",\n parameters: {\n type: \"object\",\n properties: {\n widget: {\n type: \"string\",\n enum: [\"data-table\", \"data-chart\", \"data-insights\"],\n description:\n \"Widget kind. Use data-chart for a chart, data-table for a table, or data-insights for a combined summary/chart/table card.\",\n },\n widgetId: {\n type: \"string\",\n description: \"Optional stable widget identifier.\",\n },\n title: {\n type: \"string\",\n description: \"Optional widget title.\",\n },\n summary: {\n type: \"object\",\n description:\n \"Optional scalar summary values for data-insights cards.\",\n },\n display: {\n type: \"object\",\n description:\n \"Optional display metadata: title, description, primaryAction.\",\n },\n table: {\n type: \"object\",\n description:\n \"For data-table/data-insights: { title?, columns: [{ key, label, align? }], rows, totalRows?, sampledRows?, truncated? }.\",\n },\n chartSeries: {\n type: \"object\",\n description:\n \"For data-chart/data-insights: { type: 'bar'|'line'|'area', title?, xKey, series: [{ key, label, color? }], data, sampled? }.\",\n },\n },\n required: [\"widget\"],\n },\n },\n run: async (args) => dataWidgetResultSchema.parse(args),\n },\n };\n}\n"]}
|
|
@@ -51,7 +51,7 @@ Keep \`create-extension\` payloads compact enough to finish quickly. For complex
|
|
|
51
51
|
|
|
52
52
|
Generated UI content can use appAction(), appFetch(), dbQuery(), extensionFetch(), extensionData, agentNative.ui.output(value, opts?), and agentNative.chat.send(...)/sendToAgentChat(...). Use appAction() for app data writes, and dbQuery() only for read-only inspection of known app SQL tables. It can receive chat inputs through slotContext/window.onSlotContext. Use agentNative.ui.output for passive current values from knobs, sliders, selections, and controls; it writes application state at \`inline-ui:<extensionId>:output\` scoped to the inline extension id returned by \`render-inline-extension\` or \`show-extension-inline\`. When the user later says "use that value", "apply the current setting", or similar, read it with \`readAppState("inline-ui:<id>:output")\` instead of asking them to send it again. Use agentNative.chat.send for visible submit/apply actions that should put a message into chat. Transient extensionData is browser-local and not agent-readable, synced, promoted, or garbage-collected; use application_state/appFetch, appAction, ui.output, or chat.send for anything the agent or app must observe. Use semantic Tailwind classes like bg-background, text-foreground, bg-primary, border-border, and text-muted-foreground so the UI inherits the parent app theme.
|
|
53
53
|
|
|
54
|
-
If the user asks to change, edit, fix, style, rename, or add behavior to an existing extension/widget/dashboard/calculator/mini-app, use the current extension id from \`<current-screen>\` or \`<current-url>\` when present. Call \`get-extension\` only if you need to inspect its content, then \`update-extension\` with
|
|
54
|
+
If the user asks to change, edit, fix, style, rename, or add behavior to an existing extension/widget/dashboard/calculator/mini-app, use the current extension id from \`<current-screen>\` or \`<current-url>\` when present. Call \`get-extension\` only if you need to inspect its content, then call \`update-extension\` with exactly \`id\`, \`operation\`, and \`payloadJson\`; encode the operation payload as a JSON string and never send empty placeholder fields. After one content read, keep the body in working memory and use \`operation="edit"\` with focused \`edits\`/\`patches\` inside \`payloadJson\`; do not loop on repeated \`get-extension\` + \`run-code\` string scans before writing. For a data-only repair, preserve the existing layout, CSS, copy, and interactions. Use \`operation="replace"\` only when the user explicitly requests a broad visual rewrite or supplies a complete replacement body. Use \`operation="metadata"\` for name/description/icon, and use \`set-resource-visibility\` for sharing changes. If a focused patch fails, read the current body and change the target rather than retrying identical arguments. Use \`list-extensions\` only when no current id/name is available. Existing extension edits are SQL data updates, not source-code changes, even when the request says "change the UI" or "fix this". Do **NOT** call \`connect-builder\` for existing extension edits.
|
|
55
55
|
|
|
56
56
|
In Act mode, when in doubt — if the request asks for a new small interactive utility and does not need reuse, choose \`render-inline-extension\`; if it mentions saving/reuse or asks for an extension/widget/dashboard/calculator/mini-app, choose \`create-extension\`. If it references an existing one or the current extension page, choose \`update-extension\`. Do **not** preface the call with planning text like "let me build the dashboard…" — just call the right extension action directly.
|
|
57
57
|
|
|
@@ -92,7 +92,7 @@ Keep the first \`create-extension\` call compact and working. If the request is
|
|
|
92
92
|
|
|
93
93
|
Generated UI can read chat inputs from slotContext/window.onSlotContext, see/update app state through appFetch/appAction, use extensionData, record passive current values through agentNative.ui.output(value, opts?), and send visible results through agentNative.chat.send(...) or sendToAgentChat(...). ui.output writes \`inline-ui:<extensionId>:output\` in application state; when the user asks to use the current slider/selection/value, read \`readAppState("inline-ui:<id>:output")\`. Transient extensionData is browser-local only, so do not rely on it for values the agent or app must observe. Use semantic Tailwind theme classes.
|
|
94
94
|
|
|
95
|
-
If the user asks to change, edit, fix, style, rename, or add behavior to an existing extension/widget/dashboard/calculator/mini-app, use the current extension id from \`<current-screen>\` or \`<current-url>\` when present. Call \`get-extension\` only if you need to inspect its content, then \`update-extension\` with
|
|
95
|
+
If the user asks to change, edit, fix, style, rename, or add behavior to an existing extension/widget/dashboard/calculator/mini-app, use the current extension id from \`<current-screen>\` or \`<current-url>\` when present. Call \`get-extension\` only if you need to inspect its content, then call \`update-extension\` with exactly \`id\`, \`operation\`, and \`payloadJson\`; encode the operation payload as a JSON string and never send empty placeholder fields. After one content read, use \`operation="edit"\` with focused \`edits\`/\`patches\` inside \`payloadJson\`; do not repeatedly re-read and scan the same HTML with \`run-code\` before writing. For a data-only repair, preserve the existing layout, CSS, copy, and interactions. Use \`operation="replace"\` only when the user explicitly requests a broad visual rewrite or supplies a complete replacement body. Use \`operation="metadata"\` for name/description/icon, and use \`set-resource-visibility\` for sharing changes. If a focused patch fails, read the current body and change the target rather than retrying identical arguments. Use \`list-extensions\` only when no current id/name is available. Existing extension edits are SQL data updates, not source-code changes. Do NOT call \`connect-builder\` for them.
|
|
96
96
|
|
|
97
97
|
For existing extensions, use \`get-extension\` or \`update-extension\` directly when \`<current-screen>\` or \`<current-url>\` provides an \`extensionId\`. Use \`list-extensions\` only to browse or resolve an unknown name. Use \`hide-extension\` when the user wants a shared extension removed only from their own view. Do not query the legacy \`tools\` table directly.
|
|
98
98
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"framework-prompts.js","sourceRoot":"","sources":["../../../src/server/agent-chat/framework-prompts.ts"],"names":[],"mappings":"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","sourcesContent":["import nodePath from \"node:path\";\n\nimport type { ActionEntry } from \"../../agent/production-agent.js\";\nimport type { DatabaseToolsOption } from \"../../scripts/db/tool-mode.js\";\nimport {\n buildFrameworkCore,\n buildFrameworkCoreCompact,\n type PromptExamples,\n} from \"../prompts/index.js\";\nimport { getRequestOrgId } from \"../request-context.js\";\nimport { loadSchemaPromptBlock } from \"../schema-prompt.js\";\nimport { resolveInitialToolNames } from \"./action-filters-a2a.js\";\nimport {\n createDataWidgetActionEntries,\n FRAMEWORK_CONTEXT_SECTIONS,\n} from \"./context-tools.js\";\nimport { lazyFs } from \"./lazy-fs.js\";\nimport { compactPromptLine } from \"./prompt-resources.js\";\n\n// ---------------------------------------------------------------------------\n// Framework-level system prompt assembly (production/dev, full/compact),\n// the \"Available Actions\" and corpus-tools prompt sections, the SQL schema\n// block, and the codebase file-tree walker used by a few dev-mode tools.\n// ---------------------------------------------------------------------------\n\nconst MAX_ACTION_SUMMARY_DESCRIPTION_CHARS = 140;\n\n/**\n * Framework-level instructions injected into every agent's system prompt.\n * Prompt text lives in packages/core/src/server/prompts/ so this file stays\n * focused on routing and assembly logic.\n *\n * buildFrameworkPrompts() is called once per plugin instantiation (not per\n * request) with the template's promptExamples, producing the four assembled\n * prompt strings used at request time.\n */\nexport function buildFrameworkPrompts(\n examples?: PromptExamples,\n options?: { databaseTools?: DatabaseToolsOption; extensionTools?: boolean },\n): {\n FRAMEWORK_CORE: string;\n FRAMEWORK_CORE_COMPACT: string;\n PROD_FRAMEWORK_PROMPT: string;\n DEV_FRAMEWORK_PROMPT: string;\n PROD_FRAMEWORK_PROMPT_COMPACT: string;\n DEV_FRAMEWORK_PROMPT_COMPACT: string;\n} {\n const FRAMEWORK_CORE = buildFrameworkCore(examples, options);\n const FRAMEWORK_CORE_COMPACT = buildFrameworkCoreCompact(examples, options);\n const extensionToolsEnabled = options?.extensionTools !== false;\n const planModeArtifactList = extensionToolsEnabled\n ? \"source-code handoffs and app-created artifacts such as extensions, widgets, dashboards, calculators, mini-apps, documents, designs, slides, or videos\"\n : \"source-code handoffs and app-created artifacts such as documents, designs, slides, or videos\";\n const planModeBlockedTools = extensionToolsEnabled\n ? \"`render-inline-extension`, `create-extension`, `update-extension`, `connect-builder`, or any action that creates, updates, deletes, sends, publishes, or persists data\"\n : \"`connect-builder`, or any action that creates, updates, deletes, sends, publishes, or persists data\";\n const extensionConnectBuilderGuard = extensionToolsEnabled\n ? \"If the complete request can be satisfied by a self-contained extension or an existing named slot, use `render-inline-extension`, `create-extension`, `show-extension-inline`, or `update-extension` instead. If the exact placement or behavior requires changing the host UI or no suitable slot exists, continue with the normal `connect-builder` source-change flow even if the user called it an extension; never stop at saying extensions cannot do it.\"\n : \"Because extension tools are disabled, do NOT invent an extension workflow. Only use `connect-builder` when the request genuinely requires changing the host app's source code.\";\n const extensionInstructionsFull = extensionToolsEnabled\n ? `### Generative UI and Extensions (Mini-Apps)\n\nIn Act mode, if the user asks for generated interactive UI in chat, choose the smallest extension action that matches the lifetime:\n\n- For a **one-time inline UI** that answers the current chat turn (knobs, controls, pickers, calculators, temporary dashboards, visualizers), call \\`render-inline-extension\\` immediately with a self-contained Alpine.js HTML body. It renders inside the transcript and is not saved.\n- For a **reusable or saved UI** (an extension/widget/dashboard/calculator/mini-app the user can reopen from Extensions), call \\`create-extension\\` with a self-contained Alpine.js HTML body. It saves to the Extensions view and also renders inline in chat.\n- To **reuse an existing saved extension inline**, call \\`show-extension-inline\\` with its id, or a search string when the id is unknown.\n\nThese are **NOT** source-code changes and do **NOT** go through \\`connect-builder\\`. Extensions are sandboxed mini-apps — no source files are touched, no PR is opened, no build is required. Saved extensions can be edited later via \\`update-extension\\`.\n\nIf the app exposes native actions or instructions for dashboards, reports, analyses, charts, documents, decks, or other domain artifacts, use those app-native actions first. Choose an extension only when the user explicitly asks for an extension/custom mini-app, or when the app's native artifact format cannot faithfully express the requested interaction.\n\nKeep \\`create-extension\\` payloads compact enough to finish quickly. For complex extensions, create a useful working v1 first, then call \\`update-extension\\` with focused edits for refinements instead of trying to assemble one enormous initial tool input.\n\nGenerated UI content can use appAction(), appFetch(), dbQuery(), extensionFetch(), extensionData, agentNative.ui.output(value, opts?), and agentNative.chat.send(...)/sendToAgentChat(...). Use appAction() for app data writes, and dbQuery() only for read-only inspection of known app SQL tables. It can receive chat inputs through slotContext/window.onSlotContext. Use agentNative.ui.output for passive current values from knobs, sliders, selections, and controls; it writes application state at \\`inline-ui:<extensionId>:output\\` scoped to the inline extension id returned by \\`render-inline-extension\\` or \\`show-extension-inline\\`. When the user later says \"use that value\", \"apply the current setting\", or similar, read it with \\`readAppState(\"inline-ui:<id>:output\")\\` instead of asking them to send it again. Use agentNative.chat.send for visible submit/apply actions that should put a message into chat. Transient extensionData is browser-local and not agent-readable, synced, promoted, or garbage-collected; use application_state/appFetch, appAction, ui.output, or chat.send for anything the agent or app must observe. Use semantic Tailwind classes like bg-background, text-foreground, bg-primary, border-border, and text-muted-foreground so the UI inherits the parent app theme.\n\nIf the user asks to change, edit, fix, style, rename, or add behavior to an existing extension/widget/dashboard/calculator/mini-app, use the current extension id from \\`<current-screen>\\` or \\`<current-url>\\` when present. Call \\`get-extension\\` only if you need to inspect its content, then \\`update-extension\\` with that id. After one content read, keep the body in working memory and move to focused \\`update-extension\\` \\`edits\\`/\\`patches\\`; do not loop on repeated \\`get-extension\\` + \\`run-code\\` string scans before writing. For a data-only repair, preserve the existing layout, CSS, copy, and interactions: never send a reconstructed full \\`content\\` body. The update action blocks full-body replacement by default; use \\`allowFullReplacement=true\\` only when the user explicitly requests a broad visual rewrite or supplies a complete replacement body. If a focused patch fails, read the current body and change the target rather than retrying identical arguments. Use \\`list-extensions\\` only when no current id/name is available. Existing extension edits are SQL data updates, not source-code changes, even when the request says \"change the UI\" or \"fix this\". Do **NOT** call \\`connect-builder\\` for existing extension edits.\n\nIn Act mode, when in doubt — if the request asks for a new small interactive utility and does not need reuse, choose \\`render-inline-extension\\`; if it mentions saving/reuse or asks for an extension/widget/dashboard/calculator/mini-app, choose \\`create-extension\\`. If it references an existing one or the current extension page, choose \\`update-extension\\`. Do **not** preface the call with planning text like \"let me build the dashboard…\" — just call the right extension action directly.\n\nNote: \"extension\" is the user-facing primitive (the sandboxed Alpine.js mini-app). Don't confuse it with the LLM concept of \"tools\" (function calls) — those are how you invoke ANY action, including \\`create-extension\\` itself.\n\nFor existing extensions, use \\`get-extension\\` or \\`update-extension\\` directly when \\`<current-screen>\\` or \\`<current-url>\\` provides an \\`extensionId\\`. Use \\`list-extensions\\` only to browse or resolve an unknown name. If the user wants a shared extension removed only from their view, use \\`hide-extension\\` — do not query or mutate the legacy \\`tools\\` table directly.\n\n### Extensions vs. Code Changes — Pick the Right Path\n\nRoute by the exact outcome, not by whether the user calls it an extension. Extensions render in their own sandboxed iframe, either on their own page or inside an existing named slot. They CANNOT change the host app's nav, restyle or inject elements into existing native components, replace built-in views, or render at an arbitrary location that has no slot.\n\n<routing>\n| The request is for… | Path |\n| ---------------------------------------------------------------- | ------------------------------ |\n| A one-off interactive answer inside chat (controls, picker, calculator, temporary visualizer) | \\`render-inline-extension\\` — inline only |\n| A new self-contained surface (widget, dashboard, calculator, viewer, list, tracker) | \\`create-extension\\` — ships instantly, no PR |\n| Loading a saved extension inside chat | \\`show-extension-inline\\` |\n| Editing an existing extension (fix, restyle, rename, add behavior) | \\`update-extension\\` |\n| The host app's own chrome (nav bar, sidebar, layout, routes, shipped components, existing styles, business logic) | \\`connect-builder\\` — a real source-code change |\n| UI inside or beside a native component where no named slot exists | \\`connect-builder\\` — add the native UI or a suitable slot in source |\n| Ambiguous, satisfiable either way (e.g. \"give me an unread view\") | \\`render-inline-extension\\` for chat-only, \\`create-extension\\` for reusable |\n</routing>\n\nIf an extension could only approximate the request in a different location, do not silently downgrade the requirement and do not end with \"extensions cannot do that.\" Briefly explain the boundary, then follow the normal source-code handoff so the app can still be customized fully.\n\nWorked examples: \"a widget showing unread emails grouped by sender\", \"a tracker for my newsletter subscriptions\", \"a custom kanban board with drag-and-drop rules the app does not have\" → \\`create-extension\\`. \"Add an Unread tab to the left navigation\", \"show local time beside every native Calendar attendee row\", \"make the subject lines wrap\", \"change the inbox grouping logic\", \"add a field to the compose form\" → \\`connect-builder\\`.`\n : `### Extensions Disabled\n\nExtension creation and management tools are disabled for this app. Do not claim you can create, edit, hide, or delete Agent-Native extensions unless the template exposes its own typed action for that workflow. For requests that would otherwise be handled as an extension/widget/dashboard/calculator mini-app, explain that this app has disabled extension tools and use the app's available actions instead.`;\n const extensionInstructionsCompact = extensionToolsEnabled\n ? `### Generative UI and Extensions (Mini-Apps)\n\nIn Act mode, if the user asks for generated interactive UI in chat, call \\`render-inline-extension\\` for one-time inline controls/knobs/calculators/visualizers that do not need saving. If the user asks for an **extension**, **widget**, **dashboard**, **calculator**, or **mini-app** that should be reusable or saved, call \\`create-extension\\` with a self-contained Alpine.js HTML body. To load a saved extension inline, call \\`show-extension-inline\\`. These are NOT code changes — extensions are sandboxed mini-apps. Do not preface with \"let me build…\" — just call the right extension action.\n\nUse app-native artifact actions first when they exist for dashboards, reports, analyses, charts, documents, decks, or similar domain artifacts. Pick \\`create-extension\\` only for explicit extension/custom mini-app requests or for behavior the native artifact format cannot support.\n\nKeep the first \\`create-extension\\` call compact and working. If the request is complex, create the v1 first and then refine with focused \\`update-extension\\` edits.\n\nGenerated UI can read chat inputs from slotContext/window.onSlotContext, see/update app state through appFetch/appAction, use extensionData, record passive current values through agentNative.ui.output(value, opts?), and send visible results through agentNative.chat.send(...) or sendToAgentChat(...). ui.output writes \\`inline-ui:<extensionId>:output\\` in application state; when the user asks to use the current slider/selection/value, read \\`readAppState(\"inline-ui:<id>:output\")\\`. Transient extensionData is browser-local only, so do not rely on it for values the agent or app must observe. Use semantic Tailwind theme classes.\n\nIf the user asks to change, edit, fix, style, rename, or add behavior to an existing extension/widget/dashboard/calculator/mini-app, use the current extension id from \\`<current-screen>\\` or \\`<current-url>\\` when present. Call \\`get-extension\\` only if you need to inspect its content, then \\`update-extension\\` with that id. After one content read, use focused \\`update-extension\\` \\`edits\\`/\\`patches\\`; do not repeatedly re-read and scan the same HTML with \\`run-code\\` before writing. For a data-only repair, preserve the existing layout, CSS, copy, and interactions: never send a reconstructed full \\`content\\` body. The update action blocks full-body replacement by default; use \\`allowFullReplacement=true\\` only when the user explicitly requests a broad visual rewrite or supplies a complete replacement body. If a focused patch fails, read the current body and change the target rather than retrying identical arguments. Use \\`list-extensions\\` only when no current id/name is available. Existing extension edits are SQL data updates, not source-code changes. Do NOT call \\`connect-builder\\` for them.\n\nFor existing extensions, use \\`get-extension\\` or \\`update-extension\\` directly when \\`<current-screen>\\` or \\`<current-url>\\` provides an \\`extensionId\\`. Use \\`list-extensions\\` only to browse or resolve an unknown name. Use \\`hide-extension\\` when the user wants a shared extension removed only from their own view. Do not query the legacy \\`tools\\` table directly.\n\n### Extensions vs. Code Changes — Pick the Right Path\n\nIf the user wants a **one-off interactive answer in chat**, use \\`render-inline-extension\\`. If they want a **new reusable self-contained surface** (custom widget, dashboard, list, viewer, calculator), use \\`create-extension\\` — extensions ship instantly without a PR. Extensions can render only on their own page or in an existing named slot; they cannot inject UI into arbitrary native components. If the exact request changes host chrome, native components, layout, styles, routes, business logic, or needs placement where no slot exists, treat it as a source-code change and use the normal \\`connect-builder\\` flow even if the user called it an extension. Never stop at \"extensions cannot do that\" or silently offer a different placement; explain the boundary briefly and continue the code-change handoff.`\n : `### Extensions Disabled\n\nExtension creation and management tools are disabled for this app. Do not claim you can create, edit, hide, or delete Agent-Native extensions unless the template exposes its own typed action for that workflow.`;\n\n const PROD_FRAMEWORK_PROMPT = `## Agent-Native Framework — Production Mode\n\nYou are an AI agent in an agent-native application, running in **production mode**.\n\nThe agent and the UI are equal partners — everything the UI can do, you can do via your tools, and vice versa. They share the same SQL database and stay in sync automatically.\n\n**In production mode, you operate through registered actions exposed as tools.** These are your capabilities — use them to read data, take actions, and help the user. You cannot edit source code or access the filesystem directly. Your tools are the app's API.\n\n### Plan Mode\n\nIf the current turn is in Plan mode, plan before anything gets written. This applies to ${planModeArtifactList}. Use only read-only tools, clarify the goal when needed, and return a concrete plan for approval. Do not call ${planModeBlockedTools} until the user switches back to Act mode.\n\n${extensionInstructionsFull}\n\n### Code Changes Not Available — Call \\`connect-builder\\` Immediately\n\n${extensionConnectBuilderGuard}\n\nIn Act mode, when the user asks you to change the UI, modify code, add a feature, fix a bug in the app itself, change styles, add a hook, create a component, add a route, add an integration, or anything else that requires editing source files — you MUST take exactly these steps, in order:\n\n1. Briefly acknowledge the user's specific request in their own terms — one short clause naming what they asked for (e.g. \"Got it — wider subject lines in the email list.\"). Do NOT restate the request verbatim, do NOT add a generic preamble, and do NOT promise outcomes. Skip this step entirely if the user already knows you're handing off (e.g. they said \"send this to Builder\").\n2. Call the \\`connect-builder\\` tool, passing the user's full request verbatim as the \\`prompt\\` argument. This renders an inline card. The returned \\`builderEnabled\\` flag is authoritative: \\`true\\` means Builder Cloud Agents can take the code-change handoff; \\`false\\` means this still requires a code change, but no Builder Cloud Agent can run from this workspace. If Builder is connected and \\`builderEnabled\\` is true, the card hands the prompt off to Builder's cloud agent on one click and returns a branch URL. If Builder is not connected and \\`builderEnabled\\` is true, it shows the Connect Builder flow. If \\`builderEnabled\\` is false, it still shows the card, but as a code-change fallback instead of a runnable cloud handoff.\n3. After the card renders, inspect the tool result and write one sentence that frames the next click around what the user just asked — not as a Builder pitch. If \\`builderEnabled\\` is true and the card can send, say something like \"Click Send to Builder and it'll wire that up for you.\" If the user needs to connect first, say something like \"Connect Builder once and it'll handle this and future changes.\" If \\`builderEnabled\\` is false, say: \"This requires a code change. Edit locally or use Builder.io to edit this code in the cloud and continue customizing the app any way you like.\" Do NOT say \"click Send to Builder\", mention a branch URL, say the card is pre-loaded, or imply a Builder Cloud Agent can run when \\`builderEnabled\\` is false.\n\nWhen \\`builderEnabled\\` is false, Builder Cloud Agents are not self-serve from Builder org settings. Do NOT tell the user to go to Builder org settings, beta features, \"Cloud Agents\", or \"AI Agents\" to enable them. The only allowed guidance is the card's code-change fallback: edit locally, use Agent Native Desktop, or use Builder.io to edit this code in the cloud and continue customizing the app any way you like.\n\n**Act-mode handoff — do exactly this:** The moment a code change is requested, call \\`connect-builder\\` with the user's verbatim request, then write one sentence framing the next click. That is the whole job: Builder plans and edits in its own sandbox, so the planning, file-mapping, and code all happen there, not here. Keep your turn to the call plus that one sentence — skip code exploration, implementation plans, \\`resources\\` writes of specs, and sub-agents (they have no code-editing tools either). You don't need filesystem access to recommend Builder, so don't reach for it or list tools you lack.\n\nBuilder Cloud Agents are the recommended path when \\`builderEnabled\\` is true because they are one-click and run in the cloud. Local dev, Agent Native Desktop, and Builder.io cloud editing are the fallback when \\`builderEnabled\\` is false.\n${FRAMEWORK_CORE}`;\n\n const DEV_FRAMEWORK_PROMPT = `## Agent-Native Framework — Development Mode\n\nYou are an AI agent in an agent-native application, running in **development mode**.\n\nThe agent and the UI are equal partners — everything the UI can do, you can do via tools/scripts, and vice versa. They share the same SQL database and stay in sync automatically.\n\n**In development mode, you have full local access — use it with senior-engineer judgment** (read before you edit, keep changes scoped, verify before you claim done):\n- Run any shell command via the \\`bash\\` tool (node, curl, pnpm, rg, git, etc.), including arbitrary code: \\`bash({ command: 'node -e \"console.log(1+1)\"' })\\`\n- Read and write any file on the filesystem; edit source, install packages, modify the app\n- Query and modify the database\n- Call external APIs (via bash with curl, or via scripts)\n\nWhen no dedicated tool/action exists for what you need, reach for \\`bash\\` — e.g. \\`bash({ command: 'curl -s https://api.example.com/data' })\\`.\n\n**Template-specific actions are invoked via bash, NOT as direct tools.** In dev mode, the only tools registered as native tool calls are framework-level utilities (bash, read, edit, write, database, resources, chat, teams, jobs). Anything from the template's \\`actions/\\` directory must be run through bash: \\`bash({ command: 'pnpm action <name> --arg value' })\\`. The \"Available Actions\" section below shows the exact CLI syntax for each one — copy that command verbatim and pass it to \\`bash\\`. Do not try to call template actions by name as if they were tools; they will not appear in your tool list.\n\nWhen editing code, follow the agent-native architecture:\n- Every feature needs all four areas: UI + scripts + skills/instructions + application-state sync\n- All SQL must be dialect-agnostic (works on SQLite and Postgres)\n- No Node.js-specific APIs in server routes (must work on Cloudflare Workers, etc.)\n- Use shadcn/ui components and Tabler Icons for all UI work\n${FRAMEWORK_CORE}`;\n\n const PROD_FRAMEWORK_PROMPT_COMPACT = `## Agent-Native Framework — Production Mode\n\nYou are an AI agent in an agent-native application, running in **production mode**.\n\nThe agent and the UI are equal partners — everything the UI can do, you can do via your tools, and vice versa. They share the same SQL database and stay in sync automatically.\n\n**In production mode, you operate through registered actions exposed as tools.** These are your capabilities — use them to read data, take actions, and help the user. You cannot edit source code or access the filesystem directly. Your tools are the app's API.\n\n### Plan Mode\n\nIf the turn is in Plan mode, plan before anything gets written — including ${planModeArtifactList}. Use read-only tools only and do not call ${planModeBlockedTools} until the user switches back to Act mode.\n\n${extensionInstructionsCompact}\n\n### Code Changes — Call \\`connect-builder\\`\n\nIn Act mode, when a request genuinely needs a source-code edit (per the rules above), do this in order: (1) briefly acknowledge the user's specific ask in their own terms — one short clause, no preamble — then (2) call \\`connect-builder\\` with the user's request as the \\`prompt\\`, then (3) inspect \\`builderEnabled\\` in the result and write one sentence framing the next click around what they asked for, not a Builder pitch. When \\`builderEnabled\\` is true, Builder Cloud Agents can take the handoff; when \\`builderEnabled\\` is false, say this requires a code change and they can edit locally or use Builder.io to edit this code in the cloud and continue customizing the app any way they like. Do NOT write code, list files, make plans, or spawn sub-agents. Mention \\`npx agent-native create <app-name>\\`, Agent Native Desktop, or the code-change fallback when Builder Cloud Agents aren't available. Never tell users to enable Builder Cloud Agents from Builder org settings, beta features, \"Cloud Agents\", or \"AI Agents\"; they are not self-serve there.\n${FRAMEWORK_CORE_COMPACT}`;\n\n const DEV_FRAMEWORK_PROMPT_COMPACT = `## Agent-Native Framework — Development Mode\n\nYou are an AI agent in an agent-native application, running in **development mode**.\n\nThe agent and the UI are equal partners — everything the UI can do, you can do via tools/scripts, and vice versa. They share the same SQL database and stay in sync automatically.\n\n**In development mode, you have full local access** — shell, filesystem, database, external APIs, source edits, and package installs. Use it with senior-engineer judgment: read before you edit, keep changes scoped, verify before you claim done.\n\n**Template-specific actions are invoked via bash, NOT as direct tools.** Run them with: \\`bash({ command: 'pnpm action <name> --arg value' })\\`. See the \"Available Actions\" section below for CLI syntax.\n\nWhen editing code, follow the agent-native architecture:\n- Every feature needs all four areas: UI + scripts + skills/instructions + application-state sync\n- All SQL must be dialect-agnostic (works on SQLite and Postgres)\n- No Node.js-specific APIs in server routes (must work on Cloudflare Workers, etc.)\n- Use shadcn/ui components and Tabler Icons for all UI work\n${FRAMEWORK_CORE_COMPACT}`;\n\n return {\n FRAMEWORK_CORE,\n FRAMEWORK_CORE_COMPACT,\n PROD_FRAMEWORK_PROMPT,\n DEV_FRAMEWORK_PROMPT,\n PROD_FRAMEWORK_PROMPT_COMPACT,\n DEV_FRAMEWORK_PROMPT_COMPACT,\n };\n}\n\nexport const _agentChatPromptSectionsForTests = (() => {\n // Built with default (no template-specific) examples for test stability.\n const {\n FRAMEWORK_CORE: frameworkCore,\n FRAMEWORK_CORE_COMPACT: frameworkCoreCompact,\n } = buildFrameworkPrompts();\n return {\n frameworkCore,\n frameworkCoreCompact,\n frameworkContextSections: FRAMEWORK_CONTEXT_SECTIONS,\n buildFrameworkPrompts,\n generateActionsPrompt,\n resolveInitialToolNames,\n createDataWidgetActionEntries,\n };\n})();\n\n/**\n * Build the per-request SQL-schema context block. Reads AGENT_ORG_ID live\n * from the environment so scheduler/A2A/HTTP call sites all see whatever\n * org was just resolved for this request.\n */\nexport async function buildSchemaBlock(\n owner: string,\n databaseTools: DatabaseToolsOption = \"read\",\n): Promise<string> {\n try {\n return await loadSchemaPromptBlock({\n owner,\n orgId: getRequestOrgId() ?? null,\n databaseTools,\n });\n } catch {\n return \"\";\n }\n}\n\n/**\n * Generates a system prompt section describing registered template actions.\n * This helps the agent prefer template-specific actions over raw db-query/db-exec.\n *\n * Two output modes:\n *\n * - `\"tool\"` — used in production, where template actions are registered\n * as native Anthropic tools. Output reads `name(arg*: type; ...) — desc`.\n * - `\"cli\"` — used in dev, where template actions are NOT registered as\n * native tools and must be invoked via `bash(command=\"pnpm action ...\")`.\n * Output reads `pnpm action name --arg <type> [--opt <type>] — desc`.\n */\nexport function generateActionsPrompt(\n registry: Record<string, ActionEntry>,\n mode: \"cli\" | \"tool\" = \"tool\",\n initialToolNames?: string[],\n): string {\n if (!registry || Object.keys(registry).length === 0) return \"\";\n\n const allActionEntries = Object.entries(registry);\n const initialNames = initialToolNames ? new Set(initialToolNames) : undefined;\n const actionEntries = initialNames\n ? allActionEntries.filter(([name]) => initialNames.has(name))\n : allActionEntries;\n const omittedActionCount = allActionEntries.length - actionEntries.length;\n const nativeWidgetNote = (entry: ActionEntry) =>\n entry.chatUI && typeof entry.chatUI.renderer === \"string\"\n ? ` Native chat widget: \\`${entry.chatUI.renderer}\\`.`\n : \"\";\n\n if (mode === \"tool\") {\n const summaryLines = actionEntries.map(([name, entry]) => {\n const desc = compactPromptLine(\n entry.tool.description,\n MAX_ACTION_SUMMARY_DESCRIPTION_CHARS,\n );\n return `- \\`${name}\\` — ${desc}${nativeWidgetNote(entry)}`;\n });\n\n return `\\n\\n## Available Actions\n\n**Use these actions directly as tool calls.** They handle database access, validation, and business logic internally. The native tool schemas contain the full parameter details.\n\n${summaryLines.join(\"\\n\")}${\n omittedActionCount > 0\n ? `\\n\\n${omittedActionCount} less-common app action${omittedActionCount === 1 ? \" is\" : \"s are\"} available on demand. Use \\`tool-search\\` with a specific capability query to load the matching schemas when needed.`\n : \"\"\n }`;\n }\n\n const lines = actionEntries.map(([name, entry]) => {\n const desc = entry.tool.description;\n const params = entry.tool.parameters?.properties;\n const requiredFields = new Set(entry.tool.parameters?.required ?? []);\n\n // CLI mode: emit `pnpm action <name> --required <type> [--optional <type>]`\n if (!params || Object.keys(params).length === 0) {\n return `- \\`pnpm action ${name}\\` — ${desc}${nativeWidgetNote(entry)}`;\n }\n const entries = Object.entries(params);\n // Required first (alphabetical), then optional (alphabetical)\n entries.sort(([a], [b]) => {\n const ar = requiredFields.has(a) ? 0 : 1;\n const br = requiredFields.has(b) ? 0 : 1;\n if (ar !== br) return ar - br;\n return a.localeCompare(b);\n });\n const required: string[] = [];\n const optional: string[] = [];\n const requiredNames: string[] = [];\n for (const [k, v] of entries) {\n const type = (v as { type?: string }).type ?? \"any\";\n const flag = `--${k} <${type}>`;\n if (requiredFields.has(k)) {\n required.push(flag);\n requiredNames.push(`--${k}`);\n } else {\n optional.push(`[${flag}]`);\n }\n }\n const cmd = [\"pnpm action \" + name, ...required, ...optional].join(\" \");\n const requiredNote =\n requiredNames.length > 0 ? ` Required: ${requiredNames.join(\", \")}.` : \"\";\n return `- \\`${cmd}\\` — ${desc}.${requiredNote}${nativeWidgetNote(entry)}`;\n });\n\n return `\\n\\n## Available Actions\n\n**These template actions are NOT exposed as direct tools in dev mode. To run any of them, use the \\`bash\\` tool with the exact command shown below.** Example: \\`bash(command=\"pnpm action add-slide --deckId abc --content 'Hello'\")\\`.\n\nDo NOT try to call these by name as if they were tools — they will not exist in your tool list. Always go through \\`bash\\`.\n\n${lines.join(\"\\n\")}`;\n}\n\n/**\n * Tool names `generateCorpusToolsPrompt` teaches BY NAME, in the same order\n * it lists them. Exported so callers that build a request's initial\n * engine-tool set can fold in exactly the subset present in a given\n * registry — keeping \"what the prompt just told the model exists\" and\n * \"what tools are actually callable on the first request\" in sync. See the\n * corpus-prompt/initial-tools note at this function's call site in\n * agent-chat-plugin.ts.\n */\nconst CORPUS_TOOL_NAMES = [\n \"provider-api-catalog\",\n \"provider-api-docs\",\n \"provider-api-request\",\n \"provider-corpus-job\",\n \"query-staged-dataset\",\n \"run-code\",\n] as const;\n\nexport function corpusToolNamesTaughtByPrompt(\n registry: Record<string, ActionEntry>,\n): string[] {\n return CORPUS_TOOL_NAMES.filter((name) => name in registry);\n}\n\nexport function generateCorpusToolsPrompt(\n registry: Record<string, ActionEntry>,\n): string {\n const hasProviderApi = \"provider-api-request\" in registry;\n const hasProviderCorpusJob = \"provider-corpus-job\" in registry;\n const providerDiscoveryTools = [\n \"provider-api-catalog\" in registry ? \"`provider-api-catalog`\" : null,\n \"provider-api-docs\" in registry ? \"`provider-api-docs`\" : null,\n ].filter(Boolean);\n const hasRunCode = \"run-code\" in registry;\n const hasStagedDataset = \"query-staged-dataset\" in registry;\n if (\n !hasProviderApi &&\n !hasProviderCorpusJob &&\n !hasRunCode &&\n !hasStagedDataset\n )\n return \"\";\n\n const available = [\n ...providerDiscoveryTools,\n hasProviderApi ? \"`provider-api-request`\" : null,\n hasProviderCorpusJob ? \"`provider-corpus-job`\" : null,\n hasStagedDataset ? \"`query-staged-dataset`\" : null,\n hasRunCode ? \"`run-code`\" : null,\n ].filter(Boolean);\n\n return `\\n\\n## Broad Provider And Corpus Workflows\n\nAvailable corpus-capable tools: ${available.join(\", \")}.\n\nFor broad provider searches, raw API access, multi-page cohorts, cross-source joins, classification/counting over records, or absence-sensitive answers, do not stop at a bounded shortcut action. Use the provider's broad API/search/list surface, fetch every relevant page or an explicit bounded cohort, stage/save large responses when needed, and reduce the corpus with durable corpus jobs, staged-dataset queries, or code execution.\n\nWhen \\`provider-corpus-job\\` is available, prefer it for transcript/message/ticket/issue/document scans that may exceed one turn, need provider-side backoff, or need a defensible \"not found\" conclusion. Use operation=\"start\" with mode=\"paginated-search\" for any paginated provider endpoint, or mode=\"batch-search\" when a prior cohort of ids/records must feed a second provider endpoint. Continue paused jobs with operation=\"continue\" until status is completed or quota_wait, then read operation=\"results\". In run-code, prefer providerFetchAll() for short cursor/page/offset pagination and providerRequest() when response status, headers, or truncation metadata matters. Report source, filters, row counts, pagination/truncation, failed pages, quota_wait times, and remaining gaps.`;\n}\n\n/**\n * Walks the local filesystem (dev mode only) to build a bounded file/folder\n * tree, used by a couple of dev-mode workspace-inspection tools.\n */\nexport async function collectFiles(\n dir: string,\n prefix: string,\n depth: number,\n results: Array<{ path: string; name: string; type: \"file\" | \"folder\" }>,\n): Promise<void> {\n if (depth > 4 || results.length >= 500) return;\n const skip = new Set([\n \"node_modules\",\n \".git\",\n \".next\",\n \".output\",\n \"dist\",\n \".cache\",\n \".turbo\",\n \"data\",\n ]);\n let entries: import(\"fs\").Dirent[];\n try {\n const fs = await lazyFs();\n entries = fs.readdirSync(dir, { withFileTypes: true });\n } catch {\n return;\n }\n for (const entry of entries) {\n if (results.length >= 500) return;\n if (skip.has(entry.name) || entry.name.startsWith(\".\")) continue;\n const relPath = prefix ? `${prefix}/${entry.name}` : entry.name;\n const isDir = entry.isDirectory();\n results.push({\n path: relPath,\n name: entry.name,\n type: isDir ? \"folder\" : \"file\",\n });\n if (isDir)\n await collectFiles(\n nodePath.join(dir, entry.name),\n relPath,\n depth + 1,\n results,\n );\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"framework-prompts.js","sourceRoot":"","sources":["../../../src/server/agent-chat/framework-prompts.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,WAAW,CAAC;AAIjC,OAAO,EACL,kBAAkB,EAClB,yBAAyB,GAE1B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,EACL,6BAA6B,EAC7B,0BAA0B,GAC3B,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAE1D,8EAA8E;AAC9E,yEAAyE;AACzE,2EAA2E;AAC3E,yEAAyE;AACzE,8EAA8E;AAE9E,MAAM,oCAAoC,GAAG,GAAG,CAAC;AAEjD;;;;;;;;GAQG;AACH,MAAM,UAAU,qBAAqB,CACnC,QAAyB,EACzB,OAA2E;IAS3E,MAAM,cAAc,GAAG,kBAAkB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC7D,MAAM,sBAAsB,GAAG,yBAAyB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC5E,MAAM,qBAAqB,GAAG,OAAO,EAAE,cAAc,KAAK,KAAK,CAAC;IAChE,MAAM,oBAAoB,GAAG,qBAAqB;QAChD,CAAC,CAAC,uJAAuJ;QACzJ,CAAC,CAAC,8FAA8F,CAAC;IACnG,MAAM,oBAAoB,GAAG,qBAAqB;QAChD,CAAC,CAAC,wKAAwK;QAC1K,CAAC,CAAC,qGAAqG,CAAC;IAC1G,MAAM,4BAA4B,GAAG,qBAAqB;QACxD,CAAC,CAAC,gcAAgc;QAClc,CAAC,CAAC,gLAAgL,CAAC;IACrL,MAAM,yBAAyB,GAAG,qBAAqB;QACrD,CAAC,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qbA0C+a;QACjb,CAAC,CAAC;;qZAE+Y,CAAC;IACpZ,MAAM,4BAA4B,GAAG,qBAAqB;QACxD,CAAC,CAAC;;;;;;;;;;;;;;;;0yBAgBoyB;QACtyB,CAAC,CAAC;;kNAE4M,CAAC;IAEjN,MAAM,qBAAqB,GAAG;;;;;;;;;;0FAU0D,oBAAoB,kHAAkH,oBAAoB;;EAElP,yBAAyB;;;;EAIzB,4BAA4B;;;;;;;;;;;;;EAa5B,cAAc,EAAE,CAAC;IAEjB,MAAM,oBAAoB,GAAG;;;;;;;;;;;;;;;;;;;;;EAqB7B,cAAc,EAAE,CAAC;IAEjB,MAAM,6BAA6B,GAAG;;;;;;;;;;6EAUqC,oBAAoB,8CAA8C,oBAAoB;;EAEjK,4BAA4B;;;;;EAK5B,sBAAsB,EAAE,CAAC;IAEzB,MAAM,4BAA4B,GAAG;;;;;;;;;;;;;;;EAerC,sBAAsB,EAAE,CAAC;IAEzB,OAAO;QACL,cAAc;QACd,sBAAsB;QACtB,qBAAqB;QACrB,oBAAoB;QACpB,6BAA6B;QAC7B,4BAA4B;KAC7B,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,MAAM,gCAAgC,GAAG,CAAC,GAAG,EAAE;IACpD,yEAAyE;IACzE,MAAM,EACJ,cAAc,EAAE,aAAa,EAC7B,sBAAsB,EAAE,oBAAoB,GAC7C,GAAG,qBAAqB,EAAE,CAAC;IAC5B,OAAO;QACL,aAAa;QACb,oBAAoB;QACpB,wBAAwB,EAAE,0BAA0B;QACpD,qBAAqB;QACrB,qBAAqB;QACrB,uBAAuB;QACvB,6BAA6B;KAC9B,CAAC;AACJ,CAAC,CAAC,EAAE,CAAC;AAEL;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,KAAa,EACb,aAAa,GAAwB,MAAM;IAE3C,IAAI,CAAC;QACH,OAAO,MAAM,qBAAqB,CAAC;YACjC,KAAK;YACL,KAAK,EAAE,eAAe,EAAE,IAAI,IAAI;YAChC,aAAa;SACd,CAAC,CAAC;IACL,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,qBAAqB,CACnC,QAAqC,EACrC,IAAI,GAAmB,MAAM,EAC7B,gBAA2B;IAE3B,IAAI,CAAC,QAAQ,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAE/D,MAAM,gBAAgB,GAAG,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAClD,MAAM,YAAY,GAAG,gBAAgB,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC9E,MAAM,aAAa,GAAG,YAAY;QAChC,CAAC,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC7D,CAAC,CAAC,gBAAgB,CAAC;IACrB,MAAM,kBAAkB,GAAG,gBAAgB,CAAC,MAAM,GAAG,aAAa,CAAC,MAAM,CAAC;IAC1E,MAAM,gBAAgB,GAAG,CAAC,KAAkB,EAAE,EAAE,CAC9C,KAAK,CAAC,MAAM,IAAI,OAAO,KAAK,CAAC,MAAM,CAAC,QAAQ,KAAK,QAAQ;QACvD,CAAC,CAAC,0BAA0B,KAAK,CAAC,MAAM,CAAC,QAAQ,KAAK;QACtD,CAAC,CAAC,EAAE,CAAC;IAET,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;QACpB,MAAM,YAAY,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE;YACvD,MAAM,IAAI,GAAG,iBAAiB,CAC5B,KAAK,CAAC,IAAI,CAAC,WAAW,EACtB,oCAAoC,CACrC,CAAC;YACF,OAAO,OAAO,IAAI,QAAQ,IAAI,GAAG,gBAAgB,CAAC,KAAK,CAAC,EAAE,CAAC;QAC7D,CAAC,CAAC,CAAC;QAEH,OAAO;;;;EAIT,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,GACnB,kBAAkB,GAAG,CAAC;YACpB,CAAC,CAAC,OAAO,kBAAkB,0BAA0B,kBAAkB,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,sHAAsH;YACrN,CAAC,CAAC,EACN,EAAE,CAAC;IACL,CAAC;IAED,MAAM,KAAK,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE;QAChD,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC;QACpC,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC;QACjD,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,EAAE,QAAQ,IAAI,EAAE,CAAC,CAAC;QAEtE,4EAA4E;QAC5E,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAChD,OAAO,mBAAmB,IAAI,QAAQ,IAAI,GAAG,gBAAgB,CAAC,KAAK,CAAC,EAAE,CAAC;QACzE,CAAC;QACD,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACvC,8DAA8D;QAC9D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE;YACxB,MAAM,EAAE,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACzC,MAAM,EAAE,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACzC,IAAI,EAAE,KAAK,EAAE;gBAAE,OAAO,EAAE,GAAG,EAAE,CAAC;YAC9B,OAAO,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;QAC5B,CAAC,CAAC,CAAC;QACH,MAAM,QAAQ,GAAa,EAAE,CAAC;QAC9B,MAAM,QAAQ,GAAa,EAAE,CAAC;QAC9B,MAAM,aAAa,GAAa,EAAE,CAAC;QACnC,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,OAAO,EAAE,CAAC;YAC7B,MAAM,IAAI,GAAI,CAAuB,CAAC,IAAI,IAAI,KAAK,CAAC;YACpD,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,IAAI,GAAG,CAAC;YAChC,IAAI,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC1B,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACpB,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YAC/B,CAAC;iBAAM,CAAC;gBACN,QAAQ,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,CAAC,CAAC;YAC7B,CAAC;QACH,CAAC;QACD,MAAM,GAAG,GAAG,CAAC,cAAc,GAAG,IAAI,EAAE,GAAG,QAAQ,EAAE,GAAG,QAAQ,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACxE,MAAM,YAAY,GAChB,aAAa,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,cAAc,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5E,OAAO,OAAO,GAAG,QAAQ,IAAI,IAAI,YAAY,GAAG,gBAAgB,CAAC,KAAK,CAAC,EAAE,CAAC;IAC5E,CAAC,CAAC,CAAC;IAEH,OAAO;;;;;;EAMP,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;AACrB,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,iBAAiB,GAAG;IACxB,sBAAsB;IACtB,mBAAmB;IACnB,sBAAsB;IACtB,qBAAqB;IACrB,sBAAsB;IACtB,UAAU;CACF,CAAC;AAEX,MAAM,UAAU,6BAA6B,CAC3C,QAAqC;IAErC,OAAO,iBAAiB,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,QAAQ,CAAC,CAAC;AAC9D,CAAC;AAED,MAAM,UAAU,yBAAyB,CACvC,QAAqC;IAErC,MAAM,cAAc,GAAG,sBAAsB,IAAI,QAAQ,CAAC;IAC1D,MAAM,oBAAoB,GAAG,qBAAqB,IAAI,QAAQ,CAAC;IAC/D,MAAM,sBAAsB,GAAG;QAC7B,sBAAsB,IAAI,QAAQ,CAAC,CAAC,CAAC,wBAAwB,CAAC,CAAC,CAAC,IAAI;QACpE,mBAAmB,IAAI,QAAQ,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,IAAI;KAC/D,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAClB,MAAM,UAAU,GAAG,UAAU,IAAI,QAAQ,CAAC;IAC1C,MAAM,gBAAgB,GAAG,sBAAsB,IAAI,QAAQ,CAAC;IAC5D,IACE,CAAC,cAAc;QACf,CAAC,oBAAoB;QACrB,CAAC,UAAU;QACX,CAAC,gBAAgB;QAEjB,OAAO,EAAE,CAAC;IAEZ,MAAM,SAAS,GAAG;QAChB,GAAG,sBAAsB;QACzB,cAAc,CAAC,CAAC,CAAC,wBAAwB,CAAC,CAAC,CAAC,IAAI;QAChD,oBAAoB,CAAC,CAAC,CAAC,uBAAuB,CAAC,CAAC,CAAC,IAAI;QACrD,gBAAgB,CAAC,CAAC,CAAC,wBAAwB,CAAC,CAAC,CAAC,IAAI;QAClD,UAAU,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI;KACjC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAElB,OAAO;;kCAEyB,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC;;;;6wBAIutB,CAAC;AAC9wB,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,GAAW,EACX,MAAc,EACd,KAAa,EACb,OAAuE;IAEvE,IAAI,KAAK,GAAG,CAAC,IAAI,OAAO,CAAC,MAAM,IAAI,GAAG;QAAE,OAAO;IAC/C,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC;QACnB,cAAc;QACd,MAAM;QACN,OAAO;QACP,SAAS;QACT,MAAM;QACN,QAAQ;QACR,QAAQ;QACR,MAAM;KACP,CAAC,CAAC;IACH,IAAI,OAA8B,CAAC;IACnC,IAAI,CAAC;QACH,MAAM,EAAE,GAAG,MAAM,MAAM,EAAE,CAAC;QAC1B,OAAO,GAAG,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IACzD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO;IACT,CAAC;IACD,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,OAAO,CAAC,MAAM,IAAI,GAAG;YAAE,OAAO;QAClC,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,SAAS;QACjE,MAAM,OAAO,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC;QAChE,MAAM,KAAK,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;QAClC,OAAO,CAAC,IAAI,CAAC;YACX,IAAI,EAAE,OAAO;YACb,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM;SAChC,CAAC,CAAC;QACH,IAAI,KAAK;YACP,MAAM,YAAY,CAChB,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,EAC9B,OAAO,EACP,KAAK,GAAG,CAAC,EACT,OAAO,CACR,CAAC;IACN,CAAC;AACH,CAAC","sourcesContent":["import nodePath from \"node:path\";\n\nimport type { ActionEntry } from \"../../agent/production-agent.js\";\nimport type { DatabaseToolsOption } from \"../../scripts/db/tool-mode.js\";\nimport {\n buildFrameworkCore,\n buildFrameworkCoreCompact,\n type PromptExamples,\n} from \"../prompts/index.js\";\nimport { getRequestOrgId } from \"../request-context.js\";\nimport { loadSchemaPromptBlock } from \"../schema-prompt.js\";\nimport { resolveInitialToolNames } from \"./action-filters-a2a.js\";\nimport {\n createDataWidgetActionEntries,\n FRAMEWORK_CONTEXT_SECTIONS,\n} from \"./context-tools.js\";\nimport { lazyFs } from \"./lazy-fs.js\";\nimport { compactPromptLine } from \"./prompt-resources.js\";\n\n// ---------------------------------------------------------------------------\n// Framework-level system prompt assembly (production/dev, full/compact),\n// the \"Available Actions\" and corpus-tools prompt sections, the SQL schema\n// block, and the codebase file-tree walker used by a few dev-mode tools.\n// ---------------------------------------------------------------------------\n\nconst MAX_ACTION_SUMMARY_DESCRIPTION_CHARS = 140;\n\n/**\n * Framework-level instructions injected into every agent's system prompt.\n * Prompt text lives in packages/core/src/server/prompts/ so this file stays\n * focused on routing and assembly logic.\n *\n * buildFrameworkPrompts() is called once per plugin instantiation (not per\n * request) with the template's promptExamples, producing the four assembled\n * prompt strings used at request time.\n */\nexport function buildFrameworkPrompts(\n examples?: PromptExamples,\n options?: { databaseTools?: DatabaseToolsOption; extensionTools?: boolean },\n): {\n FRAMEWORK_CORE: string;\n FRAMEWORK_CORE_COMPACT: string;\n PROD_FRAMEWORK_PROMPT: string;\n DEV_FRAMEWORK_PROMPT: string;\n PROD_FRAMEWORK_PROMPT_COMPACT: string;\n DEV_FRAMEWORK_PROMPT_COMPACT: string;\n} {\n const FRAMEWORK_CORE = buildFrameworkCore(examples, options);\n const FRAMEWORK_CORE_COMPACT = buildFrameworkCoreCompact(examples, options);\n const extensionToolsEnabled = options?.extensionTools !== false;\n const planModeArtifactList = extensionToolsEnabled\n ? \"source-code handoffs and app-created artifacts such as extensions, widgets, dashboards, calculators, mini-apps, documents, designs, slides, or videos\"\n : \"source-code handoffs and app-created artifacts such as documents, designs, slides, or videos\";\n const planModeBlockedTools = extensionToolsEnabled\n ? \"`render-inline-extension`, `create-extension`, `update-extension`, `connect-builder`, or any action that creates, updates, deletes, sends, publishes, or persists data\"\n : \"`connect-builder`, or any action that creates, updates, deletes, sends, publishes, or persists data\";\n const extensionConnectBuilderGuard = extensionToolsEnabled\n ? \"If the complete request can be satisfied by a self-contained extension or an existing named slot, use `render-inline-extension`, `create-extension`, `show-extension-inline`, or `update-extension` instead. If the exact placement or behavior requires changing the host UI or no suitable slot exists, continue with the normal `connect-builder` source-change flow even if the user called it an extension; never stop at saying extensions cannot do it.\"\n : \"Because extension tools are disabled, do NOT invent an extension workflow. Only use `connect-builder` when the request genuinely requires changing the host app's source code.\";\n const extensionInstructionsFull = extensionToolsEnabled\n ? `### Generative UI and Extensions (Mini-Apps)\n\nIn Act mode, if the user asks for generated interactive UI in chat, choose the smallest extension action that matches the lifetime:\n\n- For a **one-time inline UI** that answers the current chat turn (knobs, controls, pickers, calculators, temporary dashboards, visualizers), call \\`render-inline-extension\\` immediately with a self-contained Alpine.js HTML body. It renders inside the transcript and is not saved.\n- For a **reusable or saved UI** (an extension/widget/dashboard/calculator/mini-app the user can reopen from Extensions), call \\`create-extension\\` with a self-contained Alpine.js HTML body. It saves to the Extensions view and also renders inline in chat.\n- To **reuse an existing saved extension inline**, call \\`show-extension-inline\\` with its id, or a search string when the id is unknown.\n\nThese are **NOT** source-code changes and do **NOT** go through \\`connect-builder\\`. Extensions are sandboxed mini-apps — no source files are touched, no PR is opened, no build is required. Saved extensions can be edited later via \\`update-extension\\`.\n\nIf the app exposes native actions or instructions for dashboards, reports, analyses, charts, documents, decks, or other domain artifacts, use those app-native actions first. Choose an extension only when the user explicitly asks for an extension/custom mini-app, or when the app's native artifact format cannot faithfully express the requested interaction.\n\nKeep \\`create-extension\\` payloads compact enough to finish quickly. For complex extensions, create a useful working v1 first, then call \\`update-extension\\` with focused edits for refinements instead of trying to assemble one enormous initial tool input.\n\nGenerated UI content can use appAction(), appFetch(), dbQuery(), extensionFetch(), extensionData, agentNative.ui.output(value, opts?), and agentNative.chat.send(...)/sendToAgentChat(...). Use appAction() for app data writes, and dbQuery() only for read-only inspection of known app SQL tables. It can receive chat inputs through slotContext/window.onSlotContext. Use agentNative.ui.output for passive current values from knobs, sliders, selections, and controls; it writes application state at \\`inline-ui:<extensionId>:output\\` scoped to the inline extension id returned by \\`render-inline-extension\\` or \\`show-extension-inline\\`. When the user later says \"use that value\", \"apply the current setting\", or similar, read it with \\`readAppState(\"inline-ui:<id>:output\")\\` instead of asking them to send it again. Use agentNative.chat.send for visible submit/apply actions that should put a message into chat. Transient extensionData is browser-local and not agent-readable, synced, promoted, or garbage-collected; use application_state/appFetch, appAction, ui.output, or chat.send for anything the agent or app must observe. Use semantic Tailwind classes like bg-background, text-foreground, bg-primary, border-border, and text-muted-foreground so the UI inherits the parent app theme.\n\nIf the user asks to change, edit, fix, style, rename, or add behavior to an existing extension/widget/dashboard/calculator/mini-app, use the current extension id from \\`<current-screen>\\` or \\`<current-url>\\` when present. Call \\`get-extension\\` only if you need to inspect its content, then call \\`update-extension\\` with exactly \\`id\\`, \\`operation\\`, and \\`payloadJson\\`; encode the operation payload as a JSON string and never send empty placeholder fields. After one content read, keep the body in working memory and use \\`operation=\"edit\"\\` with focused \\`edits\\`/\\`patches\\` inside \\`payloadJson\\`; do not loop on repeated \\`get-extension\\` + \\`run-code\\` string scans before writing. For a data-only repair, preserve the existing layout, CSS, copy, and interactions. Use \\`operation=\"replace\"\\` only when the user explicitly requests a broad visual rewrite or supplies a complete replacement body. Use \\`operation=\"metadata\"\\` for name/description/icon, and use \\`set-resource-visibility\\` for sharing changes. If a focused patch fails, read the current body and change the target rather than retrying identical arguments. Use \\`list-extensions\\` only when no current id/name is available. Existing extension edits are SQL data updates, not source-code changes, even when the request says \"change the UI\" or \"fix this\". Do **NOT** call \\`connect-builder\\` for existing extension edits.\n\nIn Act mode, when in doubt — if the request asks for a new small interactive utility and does not need reuse, choose \\`render-inline-extension\\`; if it mentions saving/reuse or asks for an extension/widget/dashboard/calculator/mini-app, choose \\`create-extension\\`. If it references an existing one or the current extension page, choose \\`update-extension\\`. Do **not** preface the call with planning text like \"let me build the dashboard…\" — just call the right extension action directly.\n\nNote: \"extension\" is the user-facing primitive (the sandboxed Alpine.js mini-app). Don't confuse it with the LLM concept of \"tools\" (function calls) — those are how you invoke ANY action, including \\`create-extension\\` itself.\n\nFor existing extensions, use \\`get-extension\\` or \\`update-extension\\` directly when \\`<current-screen>\\` or \\`<current-url>\\` provides an \\`extensionId\\`. Use \\`list-extensions\\` only to browse or resolve an unknown name. If the user wants a shared extension removed only from their view, use \\`hide-extension\\` — do not query or mutate the legacy \\`tools\\` table directly.\n\n### Extensions vs. Code Changes — Pick the Right Path\n\nRoute by the exact outcome, not by whether the user calls it an extension. Extensions render in their own sandboxed iframe, either on their own page or inside an existing named slot. They CANNOT change the host app's nav, restyle or inject elements into existing native components, replace built-in views, or render at an arbitrary location that has no slot.\n\n<routing>\n| The request is for… | Path |\n| ---------------------------------------------------------------- | ------------------------------ |\n| A one-off interactive answer inside chat (controls, picker, calculator, temporary visualizer) | \\`render-inline-extension\\` — inline only |\n| A new self-contained surface (widget, dashboard, calculator, viewer, list, tracker) | \\`create-extension\\` — ships instantly, no PR |\n| Loading a saved extension inside chat | \\`show-extension-inline\\` |\n| Editing an existing extension (fix, restyle, rename, add behavior) | \\`update-extension\\` |\n| The host app's own chrome (nav bar, sidebar, layout, routes, shipped components, existing styles, business logic) | \\`connect-builder\\` — a real source-code change |\n| UI inside or beside a native component where no named slot exists | \\`connect-builder\\` — add the native UI or a suitable slot in source |\n| Ambiguous, satisfiable either way (e.g. \"give me an unread view\") | \\`render-inline-extension\\` for chat-only, \\`create-extension\\` for reusable |\n</routing>\n\nIf an extension could only approximate the request in a different location, do not silently downgrade the requirement and do not end with \"extensions cannot do that.\" Briefly explain the boundary, then follow the normal source-code handoff so the app can still be customized fully.\n\nWorked examples: \"a widget showing unread emails grouped by sender\", \"a tracker for my newsletter subscriptions\", \"a custom kanban board with drag-and-drop rules the app does not have\" → \\`create-extension\\`. \"Add an Unread tab to the left navigation\", \"show local time beside every native Calendar attendee row\", \"make the subject lines wrap\", \"change the inbox grouping logic\", \"add a field to the compose form\" → \\`connect-builder\\`.`\n : `### Extensions Disabled\n\nExtension creation and management tools are disabled for this app. Do not claim you can create, edit, hide, or delete Agent-Native extensions unless the template exposes its own typed action for that workflow. For requests that would otherwise be handled as an extension/widget/dashboard/calculator mini-app, explain that this app has disabled extension tools and use the app's available actions instead.`;\n const extensionInstructionsCompact = extensionToolsEnabled\n ? `### Generative UI and Extensions (Mini-Apps)\n\nIn Act mode, if the user asks for generated interactive UI in chat, call \\`render-inline-extension\\` for one-time inline controls/knobs/calculators/visualizers that do not need saving. If the user asks for an **extension**, **widget**, **dashboard**, **calculator**, or **mini-app** that should be reusable or saved, call \\`create-extension\\` with a self-contained Alpine.js HTML body. To load a saved extension inline, call \\`show-extension-inline\\`. These are NOT code changes — extensions are sandboxed mini-apps. Do not preface with \"let me build…\" — just call the right extension action.\n\nUse app-native artifact actions first when they exist for dashboards, reports, analyses, charts, documents, decks, or similar domain artifacts. Pick \\`create-extension\\` only for explicit extension/custom mini-app requests or for behavior the native artifact format cannot support.\n\nKeep the first \\`create-extension\\` call compact and working. If the request is complex, create the v1 first and then refine with focused \\`update-extension\\` edits.\n\nGenerated UI can read chat inputs from slotContext/window.onSlotContext, see/update app state through appFetch/appAction, use extensionData, record passive current values through agentNative.ui.output(value, opts?), and send visible results through agentNative.chat.send(...) or sendToAgentChat(...). ui.output writes \\`inline-ui:<extensionId>:output\\` in application state; when the user asks to use the current slider/selection/value, read \\`readAppState(\"inline-ui:<id>:output\")\\`. Transient extensionData is browser-local only, so do not rely on it for values the agent or app must observe. Use semantic Tailwind theme classes.\n\nIf the user asks to change, edit, fix, style, rename, or add behavior to an existing extension/widget/dashboard/calculator/mini-app, use the current extension id from \\`<current-screen>\\` or \\`<current-url>\\` when present. Call \\`get-extension\\` only if you need to inspect its content, then call \\`update-extension\\` with exactly \\`id\\`, \\`operation\\`, and \\`payloadJson\\`; encode the operation payload as a JSON string and never send empty placeholder fields. After one content read, use \\`operation=\"edit\"\\` with focused \\`edits\\`/\\`patches\\` inside \\`payloadJson\\`; do not repeatedly re-read and scan the same HTML with \\`run-code\\` before writing. For a data-only repair, preserve the existing layout, CSS, copy, and interactions. Use \\`operation=\"replace\"\\` only when the user explicitly requests a broad visual rewrite or supplies a complete replacement body. Use \\`operation=\"metadata\"\\` for name/description/icon, and use \\`set-resource-visibility\\` for sharing changes. If a focused patch fails, read the current body and change the target rather than retrying identical arguments. Use \\`list-extensions\\` only when no current id/name is available. Existing extension edits are SQL data updates, not source-code changes. Do NOT call \\`connect-builder\\` for them.\n\nFor existing extensions, use \\`get-extension\\` or \\`update-extension\\` directly when \\`<current-screen>\\` or \\`<current-url>\\` provides an \\`extensionId\\`. Use \\`list-extensions\\` only to browse or resolve an unknown name. Use \\`hide-extension\\` when the user wants a shared extension removed only from their own view. Do not query the legacy \\`tools\\` table directly.\n\n### Extensions vs. Code Changes — Pick the Right Path\n\nIf the user wants a **one-off interactive answer in chat**, use \\`render-inline-extension\\`. If they want a **new reusable self-contained surface** (custom widget, dashboard, list, viewer, calculator), use \\`create-extension\\` — extensions ship instantly without a PR. Extensions can render only on their own page or in an existing named slot; they cannot inject UI into arbitrary native components. If the exact request changes host chrome, native components, layout, styles, routes, business logic, or needs placement where no slot exists, treat it as a source-code change and use the normal \\`connect-builder\\` flow even if the user called it an extension. Never stop at \"extensions cannot do that\" or silently offer a different placement; explain the boundary briefly and continue the code-change handoff.`\n : `### Extensions Disabled\n\nExtension creation and management tools are disabled for this app. Do not claim you can create, edit, hide, or delete Agent-Native extensions unless the template exposes its own typed action for that workflow.`;\n\n const PROD_FRAMEWORK_PROMPT = `## Agent-Native Framework — Production Mode\n\nYou are an AI agent in an agent-native application, running in **production mode**.\n\nThe agent and the UI are equal partners — everything the UI can do, you can do via your tools, and vice versa. They share the same SQL database and stay in sync automatically.\n\n**In production mode, you operate through registered actions exposed as tools.** These are your capabilities — use them to read data, take actions, and help the user. You cannot edit source code or access the filesystem directly. Your tools are the app's API.\n\n### Plan Mode\n\nIf the current turn is in Plan mode, plan before anything gets written. This applies to ${planModeArtifactList}. Use only read-only tools, clarify the goal when needed, and return a concrete plan for approval. Do not call ${planModeBlockedTools} until the user switches back to Act mode.\n\n${extensionInstructionsFull}\n\n### Code Changes Not Available — Call \\`connect-builder\\` Immediately\n\n${extensionConnectBuilderGuard}\n\nIn Act mode, when the user asks you to change the UI, modify code, add a feature, fix a bug in the app itself, change styles, add a hook, create a component, add a route, add an integration, or anything else that requires editing source files — you MUST take exactly these steps, in order:\n\n1. Briefly acknowledge the user's specific request in their own terms — one short clause naming what they asked for (e.g. \"Got it — wider subject lines in the email list.\"). Do NOT restate the request verbatim, do NOT add a generic preamble, and do NOT promise outcomes. Skip this step entirely if the user already knows you're handing off (e.g. they said \"send this to Builder\").\n2. Call the \\`connect-builder\\` tool, passing the user's full request verbatim as the \\`prompt\\` argument. This renders an inline card. The returned \\`builderEnabled\\` flag is authoritative: \\`true\\` means Builder Cloud Agents can take the code-change handoff; \\`false\\` means this still requires a code change, but no Builder Cloud Agent can run from this workspace. If Builder is connected and \\`builderEnabled\\` is true, the card hands the prompt off to Builder's cloud agent on one click and returns a branch URL. If Builder is not connected and \\`builderEnabled\\` is true, it shows the Connect Builder flow. If \\`builderEnabled\\` is false, it still shows the card, but as a code-change fallback instead of a runnable cloud handoff.\n3. After the card renders, inspect the tool result and write one sentence that frames the next click around what the user just asked — not as a Builder pitch. If \\`builderEnabled\\` is true and the card can send, say something like \"Click Send to Builder and it'll wire that up for you.\" If the user needs to connect first, say something like \"Connect Builder once and it'll handle this and future changes.\" If \\`builderEnabled\\` is false, say: \"This requires a code change. Edit locally or use Builder.io to edit this code in the cloud and continue customizing the app any way you like.\" Do NOT say \"click Send to Builder\", mention a branch URL, say the card is pre-loaded, or imply a Builder Cloud Agent can run when \\`builderEnabled\\` is false.\n\nWhen \\`builderEnabled\\` is false, Builder Cloud Agents are not self-serve from Builder org settings. Do NOT tell the user to go to Builder org settings, beta features, \"Cloud Agents\", or \"AI Agents\" to enable them. The only allowed guidance is the card's code-change fallback: edit locally, use Agent Native Desktop, or use Builder.io to edit this code in the cloud and continue customizing the app any way you like.\n\n**Act-mode handoff — do exactly this:** The moment a code change is requested, call \\`connect-builder\\` with the user's verbatim request, then write one sentence framing the next click. That is the whole job: Builder plans and edits in its own sandbox, so the planning, file-mapping, and code all happen there, not here. Keep your turn to the call plus that one sentence — skip code exploration, implementation plans, \\`resources\\` writes of specs, and sub-agents (they have no code-editing tools either). You don't need filesystem access to recommend Builder, so don't reach for it or list tools you lack.\n\nBuilder Cloud Agents are the recommended path when \\`builderEnabled\\` is true because they are one-click and run in the cloud. Local dev, Agent Native Desktop, and Builder.io cloud editing are the fallback when \\`builderEnabled\\` is false.\n${FRAMEWORK_CORE}`;\n\n const DEV_FRAMEWORK_PROMPT = `## Agent-Native Framework — Development Mode\n\nYou are an AI agent in an agent-native application, running in **development mode**.\n\nThe agent and the UI are equal partners — everything the UI can do, you can do via tools/scripts, and vice versa. They share the same SQL database and stay in sync automatically.\n\n**In development mode, you have full local access — use it with senior-engineer judgment** (read before you edit, keep changes scoped, verify before you claim done):\n- Run any shell command via the \\`bash\\` tool (node, curl, pnpm, rg, git, etc.), including arbitrary code: \\`bash({ command: 'node -e \"console.log(1+1)\"' })\\`\n- Read and write any file on the filesystem; edit source, install packages, modify the app\n- Query and modify the database\n- Call external APIs (via bash with curl, or via scripts)\n\nWhen no dedicated tool/action exists for what you need, reach for \\`bash\\` — e.g. \\`bash({ command: 'curl -s https://api.example.com/data' })\\`.\n\n**Template-specific actions are invoked via bash, NOT as direct tools.** In dev mode, the only tools registered as native tool calls are framework-level utilities (bash, read, edit, write, database, resources, chat, teams, jobs). Anything from the template's \\`actions/\\` directory must be run through bash: \\`bash({ command: 'pnpm action <name> --arg value' })\\`. The \"Available Actions\" section below shows the exact CLI syntax for each one — copy that command verbatim and pass it to \\`bash\\`. Do not try to call template actions by name as if they were tools; they will not appear in your tool list.\n\nWhen editing code, follow the agent-native architecture:\n- Every feature needs all four areas: UI + scripts + skills/instructions + application-state sync\n- All SQL must be dialect-agnostic (works on SQLite and Postgres)\n- No Node.js-specific APIs in server routes (must work on Cloudflare Workers, etc.)\n- Use shadcn/ui components and Tabler Icons for all UI work\n${FRAMEWORK_CORE}`;\n\n const PROD_FRAMEWORK_PROMPT_COMPACT = `## Agent-Native Framework — Production Mode\n\nYou are an AI agent in an agent-native application, running in **production mode**.\n\nThe agent and the UI are equal partners — everything the UI can do, you can do via your tools, and vice versa. They share the same SQL database and stay in sync automatically.\n\n**In production mode, you operate through registered actions exposed as tools.** These are your capabilities — use them to read data, take actions, and help the user. You cannot edit source code or access the filesystem directly. Your tools are the app's API.\n\n### Plan Mode\n\nIf the turn is in Plan mode, plan before anything gets written — including ${planModeArtifactList}. Use read-only tools only and do not call ${planModeBlockedTools} until the user switches back to Act mode.\n\n${extensionInstructionsCompact}\n\n### Code Changes — Call \\`connect-builder\\`\n\nIn Act mode, when a request genuinely needs a source-code edit (per the rules above), do this in order: (1) briefly acknowledge the user's specific ask in their own terms — one short clause, no preamble — then (2) call \\`connect-builder\\` with the user's request as the \\`prompt\\`, then (3) inspect \\`builderEnabled\\` in the result and write one sentence framing the next click around what they asked for, not a Builder pitch. When \\`builderEnabled\\` is true, Builder Cloud Agents can take the handoff; when \\`builderEnabled\\` is false, say this requires a code change and they can edit locally or use Builder.io to edit this code in the cloud and continue customizing the app any way they like. Do NOT write code, list files, make plans, or spawn sub-agents. Mention \\`npx agent-native create <app-name>\\`, Agent Native Desktop, or the code-change fallback when Builder Cloud Agents aren't available. Never tell users to enable Builder Cloud Agents from Builder org settings, beta features, \"Cloud Agents\", or \"AI Agents\"; they are not self-serve there.\n${FRAMEWORK_CORE_COMPACT}`;\n\n const DEV_FRAMEWORK_PROMPT_COMPACT = `## Agent-Native Framework — Development Mode\n\nYou are an AI agent in an agent-native application, running in **development mode**.\n\nThe agent and the UI are equal partners — everything the UI can do, you can do via tools/scripts, and vice versa. They share the same SQL database and stay in sync automatically.\n\n**In development mode, you have full local access** — shell, filesystem, database, external APIs, source edits, and package installs. Use it with senior-engineer judgment: read before you edit, keep changes scoped, verify before you claim done.\n\n**Template-specific actions are invoked via bash, NOT as direct tools.** Run them with: \\`bash({ command: 'pnpm action <name> --arg value' })\\`. See the \"Available Actions\" section below for CLI syntax.\n\nWhen editing code, follow the agent-native architecture:\n- Every feature needs all four areas: UI + scripts + skills/instructions + application-state sync\n- All SQL must be dialect-agnostic (works on SQLite and Postgres)\n- No Node.js-specific APIs in server routes (must work on Cloudflare Workers, etc.)\n- Use shadcn/ui components and Tabler Icons for all UI work\n${FRAMEWORK_CORE_COMPACT}`;\n\n return {\n FRAMEWORK_CORE,\n FRAMEWORK_CORE_COMPACT,\n PROD_FRAMEWORK_PROMPT,\n DEV_FRAMEWORK_PROMPT,\n PROD_FRAMEWORK_PROMPT_COMPACT,\n DEV_FRAMEWORK_PROMPT_COMPACT,\n };\n}\n\nexport const _agentChatPromptSectionsForTests = (() => {\n // Built with default (no template-specific) examples for test stability.\n const {\n FRAMEWORK_CORE: frameworkCore,\n FRAMEWORK_CORE_COMPACT: frameworkCoreCompact,\n } = buildFrameworkPrompts();\n return {\n frameworkCore,\n frameworkCoreCompact,\n frameworkContextSections: FRAMEWORK_CONTEXT_SECTIONS,\n buildFrameworkPrompts,\n generateActionsPrompt,\n resolveInitialToolNames,\n createDataWidgetActionEntries,\n };\n})();\n\n/**\n * Build the per-request SQL-schema context block. Reads AGENT_ORG_ID live\n * from the environment so scheduler/A2A/HTTP call sites all see whatever\n * org was just resolved for this request.\n */\nexport async function buildSchemaBlock(\n owner: string,\n databaseTools: DatabaseToolsOption = \"read\",\n): Promise<string> {\n try {\n return await loadSchemaPromptBlock({\n owner,\n orgId: getRequestOrgId() ?? null,\n databaseTools,\n });\n } catch {\n return \"\";\n }\n}\n\n/**\n * Generates a system prompt section describing registered template actions.\n * This helps the agent prefer template-specific actions over raw db-query/db-exec.\n *\n * Two output modes:\n *\n * - `\"tool\"` — used in production, where template actions are registered\n * as native Anthropic tools. Output reads `name(arg*: type; ...) — desc`.\n * - `\"cli\"` — used in dev, where template actions are NOT registered as\n * native tools and must be invoked via `bash(command=\"pnpm action ...\")`.\n * Output reads `pnpm action name --arg <type> [--opt <type>] — desc`.\n */\nexport function generateActionsPrompt(\n registry: Record<string, ActionEntry>,\n mode: \"cli\" | \"tool\" = \"tool\",\n initialToolNames?: string[],\n): string {\n if (!registry || Object.keys(registry).length === 0) return \"\";\n\n const allActionEntries = Object.entries(registry);\n const initialNames = initialToolNames ? new Set(initialToolNames) : undefined;\n const actionEntries = initialNames\n ? allActionEntries.filter(([name]) => initialNames.has(name))\n : allActionEntries;\n const omittedActionCount = allActionEntries.length - actionEntries.length;\n const nativeWidgetNote = (entry: ActionEntry) =>\n entry.chatUI && typeof entry.chatUI.renderer === \"string\"\n ? ` Native chat widget: \\`${entry.chatUI.renderer}\\`.`\n : \"\";\n\n if (mode === \"tool\") {\n const summaryLines = actionEntries.map(([name, entry]) => {\n const desc = compactPromptLine(\n entry.tool.description,\n MAX_ACTION_SUMMARY_DESCRIPTION_CHARS,\n );\n return `- \\`${name}\\` — ${desc}${nativeWidgetNote(entry)}`;\n });\n\n return `\\n\\n## Available Actions\n\n**Use these actions directly as tool calls.** They handle database access, validation, and business logic internally. The native tool schemas contain the full parameter details.\n\n${summaryLines.join(\"\\n\")}${\n omittedActionCount > 0\n ? `\\n\\n${omittedActionCount} less-common app action${omittedActionCount === 1 ? \" is\" : \"s are\"} available on demand. Use \\`tool-search\\` with a specific capability query to load the matching schemas when needed.`\n : \"\"\n }`;\n }\n\n const lines = actionEntries.map(([name, entry]) => {\n const desc = entry.tool.description;\n const params = entry.tool.parameters?.properties;\n const requiredFields = new Set(entry.tool.parameters?.required ?? []);\n\n // CLI mode: emit `pnpm action <name> --required <type> [--optional <type>]`\n if (!params || Object.keys(params).length === 0) {\n return `- \\`pnpm action ${name}\\` — ${desc}${nativeWidgetNote(entry)}`;\n }\n const entries = Object.entries(params);\n // Required first (alphabetical), then optional (alphabetical)\n entries.sort(([a], [b]) => {\n const ar = requiredFields.has(a) ? 0 : 1;\n const br = requiredFields.has(b) ? 0 : 1;\n if (ar !== br) return ar - br;\n return a.localeCompare(b);\n });\n const required: string[] = [];\n const optional: string[] = [];\n const requiredNames: string[] = [];\n for (const [k, v] of entries) {\n const type = (v as { type?: string }).type ?? \"any\";\n const flag = `--${k} <${type}>`;\n if (requiredFields.has(k)) {\n required.push(flag);\n requiredNames.push(`--${k}`);\n } else {\n optional.push(`[${flag}]`);\n }\n }\n const cmd = [\"pnpm action \" + name, ...required, ...optional].join(\" \");\n const requiredNote =\n requiredNames.length > 0 ? ` Required: ${requiredNames.join(\", \")}.` : \"\";\n return `- \\`${cmd}\\` — ${desc}.${requiredNote}${nativeWidgetNote(entry)}`;\n });\n\n return `\\n\\n## Available Actions\n\n**These template actions are NOT exposed as direct tools in dev mode. To run any of them, use the \\`bash\\` tool with the exact command shown below.** Example: \\`bash(command=\"pnpm action add-slide --deckId abc --content 'Hello'\")\\`.\n\nDo NOT try to call these by name as if they were tools — they will not exist in your tool list. Always go through \\`bash\\`.\n\n${lines.join(\"\\n\")}`;\n}\n\n/**\n * Tool names `generateCorpusToolsPrompt` teaches BY NAME, in the same order\n * it lists them. Exported so callers that build a request's initial\n * engine-tool set can fold in exactly the subset present in a given\n * registry — keeping \"what the prompt just told the model exists\" and\n * \"what tools are actually callable on the first request\" in sync. See the\n * corpus-prompt/initial-tools note at this function's call site in\n * agent-chat-plugin.ts.\n */\nconst CORPUS_TOOL_NAMES = [\n \"provider-api-catalog\",\n \"provider-api-docs\",\n \"provider-api-request\",\n \"provider-corpus-job\",\n \"query-staged-dataset\",\n \"run-code\",\n] as const;\n\nexport function corpusToolNamesTaughtByPrompt(\n registry: Record<string, ActionEntry>,\n): string[] {\n return CORPUS_TOOL_NAMES.filter((name) => name in registry);\n}\n\nexport function generateCorpusToolsPrompt(\n registry: Record<string, ActionEntry>,\n): string {\n const hasProviderApi = \"provider-api-request\" in registry;\n const hasProviderCorpusJob = \"provider-corpus-job\" in registry;\n const providerDiscoveryTools = [\n \"provider-api-catalog\" in registry ? \"`provider-api-catalog`\" : null,\n \"provider-api-docs\" in registry ? \"`provider-api-docs`\" : null,\n ].filter(Boolean);\n const hasRunCode = \"run-code\" in registry;\n const hasStagedDataset = \"query-staged-dataset\" in registry;\n if (\n !hasProviderApi &&\n !hasProviderCorpusJob &&\n !hasRunCode &&\n !hasStagedDataset\n )\n return \"\";\n\n const available = [\n ...providerDiscoveryTools,\n hasProviderApi ? \"`provider-api-request`\" : null,\n hasProviderCorpusJob ? \"`provider-corpus-job`\" : null,\n hasStagedDataset ? \"`query-staged-dataset`\" : null,\n hasRunCode ? \"`run-code`\" : null,\n ].filter(Boolean);\n\n return `\\n\\n## Broad Provider And Corpus Workflows\n\nAvailable corpus-capable tools: ${available.join(\", \")}.\n\nFor broad provider searches, raw API access, multi-page cohorts, cross-source joins, classification/counting over records, or absence-sensitive answers, do not stop at a bounded shortcut action. Use the provider's broad API/search/list surface, fetch every relevant page or an explicit bounded cohort, stage/save large responses when needed, and reduce the corpus with durable corpus jobs, staged-dataset queries, or code execution.\n\nWhen \\`provider-corpus-job\\` is available, prefer it for transcript/message/ticket/issue/document scans that may exceed one turn, need provider-side backoff, or need a defensible \"not found\" conclusion. Use operation=\"start\" with mode=\"paginated-search\" for any paginated provider endpoint, or mode=\"batch-search\" when a prior cohort of ids/records must feed a second provider endpoint. Continue paused jobs with operation=\"continue\" until status is completed or quota_wait, then read operation=\"results\". In run-code, prefer providerFetchAll() for short cursor/page/offset pagination and providerRequest() when response status, headers, or truncation metadata matters. Report source, filters, row counts, pagination/truncation, failed pages, quota_wait times, and remaining gaps.`;\n}\n\n/**\n * Walks the local filesystem (dev mode only) to build a bounded file/folder\n * tree, used by a couple of dev-mode workspace-inspection tools.\n */\nexport async function collectFiles(\n dir: string,\n prefix: string,\n depth: number,\n results: Array<{ path: string; name: string; type: \"file\" | \"folder\" }>,\n): Promise<void> {\n if (depth > 4 || results.length >= 500) return;\n const skip = new Set([\n \"node_modules\",\n \".git\",\n \".next\",\n \".output\",\n \"dist\",\n \".cache\",\n \".turbo\",\n \"data\",\n ]);\n let entries: import(\"fs\").Dirent[];\n try {\n const fs = await lazyFs();\n entries = fs.readdirSync(dir, { withFileTypes: true });\n } catch {\n return;\n }\n for (const entry of entries) {\n if (results.length >= 500) return;\n if (skip.has(entry.name) || entry.name.startsWith(\".\")) continue;\n const relPath = prefix ? `${prefix}/${entry.name}` : entry.name;\n const isDir = entry.isDirectory();\n results.push({\n path: relPath,\n name: entry.name,\n type: isDir ? \"folder\" : \"file\",\n });\n if (isDir)\n await collectFiles(\n nodePath.join(dir, entry.name),\n relPath,\n depth + 1,\n results,\n );\n }\n}\n"]}
|