@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
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: agent-native-docs
|
|
3
|
+
description: >-
|
|
4
|
+
How to find version-matched Agent Native framework docs and source bundled in
|
|
5
|
+
node_modules. Use before implementing or answering questions about
|
|
6
|
+
@agent-native/core APIs, generated apps, workspaces, templates, or advanced
|
|
7
|
+
features.
|
|
8
|
+
scope: dev
|
|
9
|
+
metadata:
|
|
10
|
+
internal: true
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# Agent Native Docs Lookup
|
|
14
|
+
|
|
15
|
+
## Rule
|
|
16
|
+
|
|
17
|
+
Before implementing or explaining non-trivial Agent Native behavior, read the
|
|
18
|
+
version-matched docs installed with `@agent-native/core`. When examples,
|
|
19
|
+
imports, or implementation details matter, inspect the packaged source corpus
|
|
20
|
+
too.
|
|
21
|
+
|
|
22
|
+
## Why
|
|
23
|
+
|
|
24
|
+
Generated apps and workspaces may be on a different framework version than the
|
|
25
|
+
public docs or model memory. The installed package is the source that matches
|
|
26
|
+
the app in front of you. It also includes a source-only corpus of core and
|
|
27
|
+
first-party templates so agents can replicate current best-practice patterns
|
|
28
|
+
without needing the framework monorepo checkout.
|
|
29
|
+
|
|
30
|
+
## How
|
|
31
|
+
|
|
32
|
+
From a generated app directory:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
pnpm action docs-search --query "<feature>"
|
|
36
|
+
pnpm action docs-search --slug <slug>
|
|
37
|
+
pnpm action docs-search --list
|
|
38
|
+
pnpm action source-search --query "<pattern>"
|
|
39
|
+
pnpm action source-search --path templates/plan/AGENTS.md
|
|
40
|
+
pnpm action source-search --path toolkit/src/index.ts
|
|
41
|
+
pnpm action source-search --list
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
The headless `pnpm agent` loop and built-in app agent also expose a read-only
|
|
45
|
+
`docs-search` tool with the same `query`, `slug`, and `list` options, plus a
|
|
46
|
+
read-only `source-search` tool with `query`, `path`, and `list`.
|
|
47
|
+
|
|
48
|
+
If the action runner is unavailable, search the package directly:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
rg -n "actions|automations|a2a|sharing" node_modules/@agent-native/core/docs
|
|
52
|
+
rg -n "defineAction|useActionQuery" node_modules/@agent-native/core/corpus
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Then read `node_modules/@agent-native/core/docs/AGENTS.md` or the matching file
|
|
56
|
+
under `node_modules/@agent-native/core/docs/content/`. For source examples,
|
|
57
|
+
read files under `node_modules/@agent-native/core/corpus/core/` or
|
|
58
|
+
`node_modules/@agent-native/core/corpus/templates/`.
|
|
59
|
+
|
|
60
|
+
Toolkit source is searchable at `toolkit/` in the Core corpus and also ships as
|
|
61
|
+
readable TypeScript under `node_modules/@agent-native/toolkit/src/`. Read
|
|
62
|
+
`customizing-agent-native` before taking ownership of a shared component: inspect package
|
|
63
|
+
source as a read-only reference, then configure, compose, or eject the smallest
|
|
64
|
+
supported unit into app-owned source. Preserve public actions, application
|
|
65
|
+
state, auth, and agent-chat runtime contracts. Never edit `node_modules` or
|
|
66
|
+
deep-import its private source. Manual copying is only the fallback described by
|
|
67
|
+
an unknown third-party package's add-style blueprint.
|
|
68
|
+
|
|
69
|
+
## Reuse Proven Patterns (rg + cp)
|
|
70
|
+
|
|
71
|
+
Version-matched installed source outranks web docs or memory: it is the exact
|
|
72
|
+
code shipping with this app. `node_modules/@agent-native/core/corpus/templates/`
|
|
73
|
+
holds source for every first-party template, not just the one this app started
|
|
74
|
+
from, so a pattern from the mail template is fair game for a tasks app. Grep
|
|
75
|
+
across it, then copy a whole file as a starting point instead of writing the
|
|
76
|
+
pattern from scratch:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
# Find how other templates solved a similar problem
|
|
80
|
+
rg -n "drag.*drop|reorder" node_modules/@agent-native/core/corpus/templates
|
|
81
|
+
|
|
82
|
+
# Grab a proven action file as a starting point, then adapt names/schema
|
|
83
|
+
cp node_modules/@agent-native/core/corpus/templates/mail/actions/archive-email.ts \
|
|
84
|
+
actions/archive-item.ts
|
|
85
|
+
|
|
86
|
+
# Read the full framework source behind an API, not just the corpus copy
|
|
87
|
+
rg -n "defineAction" node_modules/@agent-native/core/src/action.ts
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Copying template-level app code (actions, components, skill files) is the
|
|
91
|
+
expected reuse path — templates exist to be forked. This is different from
|
|
92
|
+
copying `core`/`toolkit` **runtime internals**: for those, follow
|
|
93
|
+
`customizing-agent-native`'s configure/compose/eject ladder instead of
|
|
94
|
+
hand-duplicating framework logic.
|
|
95
|
+
|
|
96
|
+
## Useful Slugs
|
|
97
|
+
|
|
98
|
+
| Need | Slugs |
|
|
99
|
+
| ------------------------------ | ------------------------------------------------------------- |
|
|
100
|
+
| Actions and typed client calls | `actions`, `client` |
|
|
101
|
+
| SQL, auth, access, sharing | `database`, `authentication`, `security`, `sharing` |
|
|
102
|
+
| UI state visible to the agent | `context-awareness` |
|
|
103
|
+
| Headless and chat-first apps | `pure-agent-apps`, `agent-surfaces`, `using-your-agent` |
|
|
104
|
+
| Automations and schedules | `automations`, `recurring-jobs` |
|
|
105
|
+
| Cross-app and external agents | `a2a-protocol`, `external-agents`, `mcp-protocol`, `mcp-apps` |
|
|
106
|
+
| Skills and instructions | `skills-guide`, `writing-agent-instructions` |
|
|
107
|
+
|
|
108
|
+
## Don't
|
|
109
|
+
|
|
110
|
+
- Do not rely on memory for framework APIs when package docs are present.
|
|
111
|
+
- Do not add custom REST wrappers for app data before reading `actions`.
|
|
112
|
+
- Do not add inline LLM calls before reading `using-your-agent` and
|
|
113
|
+
`agent-surfaces`.
|
|
114
|
+
- Do not copy framework runtime internals when a public API or narrow UI copy
|
|
115
|
+
will do; read `customizing-agent-native` for the supported override ladder.
|
|
@@ -21,6 +21,13 @@ ladder.
|
|
|
21
21
|
- Never hardcode API keys, tokens, webhook URLs, signing secrets, private Builder/internal data, customer data, or credential-looking literals. Use secrets/OAuth/runtime configuration and obvious placeholders in examples.
|
|
22
22
|
- Use actions for recording metadata, transcripts, cleanup, summaries, chapters,
|
|
23
23
|
comments, spaces/folders, meetings, and sharing. Do not bypass access helpers.
|
|
24
|
+
- Use `prepare-crm-call-evidence` only for a viewer-accessible recording
|
|
25
|
+
explicitly identified by a user action or the exact approved CRM A2A recipe.
|
|
26
|
+
It returns an opaque clip ID, durable HTTPS `/r/<id>` page, and optional
|
|
27
|
+
capture time for CRM; it never returns the event media URL, a transcript,
|
|
28
|
+
temporary token, quote, or summary. A CRM recipe may install a Clips-owned
|
|
29
|
+
`clip.created` trigger only through an exact user-approved A2A automation
|
|
30
|
+
definition.
|
|
24
31
|
- Organization admins can use `set-organization-branding` with
|
|
25
32
|
`defaultVisibility=public|org|private` to choose the visibility applied when
|
|
26
33
|
new recordings omit an explicit visibility. The default remains `public`, and
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { defineAction } from "@agent-native/core/action";
|
|
2
|
+
import { getRequestContext } from "@agent-native/core/server";
|
|
3
|
+
import { assertAccess } from "@agent-native/core/sharing";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
|
|
6
|
+
import { getServerAppBasePath } from "../server/lib/public-agent-context.js";
|
|
7
|
+
|
|
8
|
+
function clipsOrigin(): string {
|
|
9
|
+
const raw = getRequestContext()?.requestOrigin || process.env.APP_URL;
|
|
10
|
+
if (!raw) {
|
|
11
|
+
throw new Error(
|
|
12
|
+
"Clips needs an HTTPS APP_URL before it can prepare CRM evidence links.",
|
|
13
|
+
);
|
|
14
|
+
}
|
|
15
|
+
let url: URL;
|
|
16
|
+
try {
|
|
17
|
+
url = new URL(raw);
|
|
18
|
+
} catch {
|
|
19
|
+
throw new Error(
|
|
20
|
+
"Clips needs a valid HTTPS APP_URL before it can prepare CRM evidence links.",
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
if (url.protocol !== "https:") {
|
|
24
|
+
throw new Error(
|
|
25
|
+
"Clips needs an HTTPS APP_URL before it can prepare CRM evidence links.",
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
return url.origin;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export default defineAction({
|
|
32
|
+
description:
|
|
33
|
+
"Prepare one access-gated Clips recording as bounded CRM call evidence. Returns only an opaque recording id, durable HTTPS recording page, and optional capture time; never media, a transcript, or a temporary access token.",
|
|
34
|
+
schema: z.object({
|
|
35
|
+
recordingId: z.string().trim().min(1).max(256),
|
|
36
|
+
}),
|
|
37
|
+
readOnly: true,
|
|
38
|
+
run: async ({ recordingId }) => {
|
|
39
|
+
const access = await assertAccess("recording", recordingId, "viewer");
|
|
40
|
+
const recording = access.resource as {
|
|
41
|
+
id: string;
|
|
42
|
+
createdAt?: string | null;
|
|
43
|
+
archivedAt?: string | null;
|
|
44
|
+
trashedAt?: string | null;
|
|
45
|
+
};
|
|
46
|
+
if (recording.archivedAt || recording.trashedAt) {
|
|
47
|
+
throw new Error("Archived or trashed Clips cannot be attached to CRM.");
|
|
48
|
+
}
|
|
49
|
+
const sourceUrl = `${clipsOrigin()}${getServerAppBasePath()}/r/${encodeURIComponent(recording.id)}`;
|
|
50
|
+
return {
|
|
51
|
+
sourceApp: "clips" as const,
|
|
52
|
+
artifactType: "call-evidence" as const,
|
|
53
|
+
artifactId: recording.id,
|
|
54
|
+
sourceUrl,
|
|
55
|
+
...(recording.createdAt ? { capturedAt: recording.createdAt } : {}),
|
|
56
|
+
};
|
|
57
|
+
},
|
|
58
|
+
});
|
|
@@ -1524,25 +1524,32 @@ export class RecorderEngine {
|
|
|
1524
1524
|
return this.compressAndReupload(meta);
|
|
1525
1525
|
}
|
|
1526
1526
|
|
|
1527
|
-
await this.resetUploadedChunks(null, signal);
|
|
1527
|
+
const uploadMode = await this.resetUploadedChunks(null, signal);
|
|
1528
1528
|
this.transition("uploading", { progress: 0 });
|
|
1529
1529
|
const assembled = new Blob(this.localChunks, { type: this.mimeType });
|
|
1530
|
-
return
|
|
1530
|
+
return uploadMode === "streaming"
|
|
1531
|
+
? this.uploadBlobInStreamingChunks(assembled, this.mimeType, meta, signal)
|
|
1532
|
+
: this.uploadBlobInSlices(assembled, this.mimeType, meta, signal);
|
|
1531
1533
|
}
|
|
1532
1534
|
|
|
1533
1535
|
private async resetUploadedChunks(
|
|
1534
1536
|
compression: CompressionUploadMeta | null,
|
|
1535
1537
|
signal?: AbortSignal,
|
|
1536
|
-
): Promise<
|
|
1538
|
+
): Promise<UploadMode> {
|
|
1537
1539
|
const resetUrl = `${appBasePath()}/api/uploads/${
|
|
1538
1540
|
this.opts.recordingId
|
|
1539
1541
|
}/reset-chunks`;
|
|
1542
|
+
const uploadMimeType = compression?.outputMimeType || this.mimeType;
|
|
1540
1543
|
let resetRes: Response;
|
|
1541
1544
|
try {
|
|
1542
1545
|
resetRes = await fetch(resetUrl, {
|
|
1543
1546
|
method: "POST",
|
|
1544
1547
|
headers: { "Content-Type": "application/json" },
|
|
1545
|
-
body: JSON.stringify({
|
|
1548
|
+
body: JSON.stringify({
|
|
1549
|
+
compression,
|
|
1550
|
+
requestStreaming: this.uploadMode === "streaming",
|
|
1551
|
+
mimeType: uploadMimeType,
|
|
1552
|
+
}),
|
|
1546
1553
|
signal,
|
|
1547
1554
|
});
|
|
1548
1555
|
} catch (err) {
|
|
@@ -1566,6 +1573,17 @@ export class RecorderEngine {
|
|
|
1566
1573
|
}). ${text || resetRes.statusText}`,
|
|
1567
1574
|
);
|
|
1568
1575
|
}
|
|
1576
|
+
const reset = (await resetRes.json().catch(() => null)) as {
|
|
1577
|
+
uploadMode?: unknown;
|
|
1578
|
+
} | null;
|
|
1579
|
+
if (reset?.uploadMode !== "streaming" && reset?.uploadMode !== "buffered") {
|
|
1580
|
+
throw new Error(
|
|
1581
|
+
"Couldn't prepare the recording for re-upload (reset-chunks returned no upload mode).",
|
|
1582
|
+
);
|
|
1583
|
+
}
|
|
1584
|
+
const uploadMode = reset.uploadMode;
|
|
1585
|
+
this.uploadMode = uploadMode;
|
|
1586
|
+
return uploadMode;
|
|
1569
1587
|
}
|
|
1570
1588
|
|
|
1571
1589
|
// -------------------------------------------------------------------------
|
|
@@ -1653,7 +1671,10 @@ export class RecorderEngine {
|
|
|
1653
1671
|
outputMimeType: compression.outputMimeType,
|
|
1654
1672
|
}
|
|
1655
1673
|
: null;
|
|
1656
|
-
await this.resetUploadedChunks(
|
|
1674
|
+
const uploadMode = await this.resetUploadedChunks(
|
|
1675
|
+
compressionPayload,
|
|
1676
|
+
abort.signal,
|
|
1677
|
+
);
|
|
1657
1678
|
|
|
1658
1679
|
if (compressionError) {
|
|
1659
1680
|
// Compression itself failed — we still hold the original assembled
|
|
@@ -1680,12 +1701,19 @@ export class RecorderEngine {
|
|
|
1680
1701
|
}
|
|
1681
1702
|
|
|
1682
1703
|
this.transition("uploading", { progress: 0 });
|
|
1683
|
-
return
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1704
|
+
return uploadMode === "streaming"
|
|
1705
|
+
? this.uploadBlobInStreamingChunks(
|
|
1706
|
+
finalBlob,
|
|
1707
|
+
compression.outputMimeType,
|
|
1708
|
+
meta,
|
|
1709
|
+
abort.signal,
|
|
1710
|
+
)
|
|
1711
|
+
: this.uploadBlobInSlices(
|
|
1712
|
+
finalBlob,
|
|
1713
|
+
compression.outputMimeType,
|
|
1714
|
+
meta,
|
|
1715
|
+
abort.signal,
|
|
1716
|
+
);
|
|
1689
1717
|
} finally {
|
|
1690
1718
|
// Always release the controller reference even on throw — otherwise
|
|
1691
1719
|
// a subsequent cancel() would abort a freshly-started compression.
|
|
@@ -2025,6 +2053,55 @@ export class RecorderEngine {
|
|
|
2025
2053
|
return results[finalSlice.index];
|
|
2026
2054
|
}
|
|
2027
2055
|
|
|
2056
|
+
private async uploadBlobInStreamingChunks(
|
|
2057
|
+
blob: Blob,
|
|
2058
|
+
mimeType: string,
|
|
2059
|
+
meta: {
|
|
2060
|
+
durationMs: number;
|
|
2061
|
+
dimensions: { width: number; height: number };
|
|
2062
|
+
hasAudio: boolean;
|
|
2063
|
+
hasCamera: boolean;
|
|
2064
|
+
},
|
|
2065
|
+
signal?: AbortSignal,
|
|
2066
|
+
): Promise<Record<string, unknown> | undefined> {
|
|
2067
|
+
if (blob.size === 0) {
|
|
2068
|
+
throw new Error("Cannot retry an empty recording upload.");
|
|
2069
|
+
}
|
|
2070
|
+
|
|
2071
|
+
this.chunkIndex = 0;
|
|
2072
|
+
const totalChunks = Math.ceil(blob.size / STREAM_CHUNK_BYTES);
|
|
2073
|
+
let result: Record<string, unknown> | undefined;
|
|
2074
|
+
|
|
2075
|
+
for (let index = 0; index < totalChunks; index++) {
|
|
2076
|
+
const start = index * STREAM_CHUNK_BYTES;
|
|
2077
|
+
const end = Math.min(start + STREAM_CHUNK_BYTES, blob.size);
|
|
2078
|
+
const isFinal = index === totalChunks - 1;
|
|
2079
|
+
const chunk = blob.slice(start, end, mimeType);
|
|
2080
|
+
result = await this.uploadChunk(chunk, this.chunkIndex++, {
|
|
2081
|
+
isFinal,
|
|
2082
|
+
total: totalChunks,
|
|
2083
|
+
mimeType,
|
|
2084
|
+
...(isFinal
|
|
2085
|
+
? {
|
|
2086
|
+
durationMs: meta.durationMs,
|
|
2087
|
+
width: meta.dimensions.width,
|
|
2088
|
+
height: meta.dimensions.height,
|
|
2089
|
+
hasAudio: meta.hasAudio,
|
|
2090
|
+
hasCamera: meta.hasCamera,
|
|
2091
|
+
}
|
|
2092
|
+
: {}),
|
|
2093
|
+
signal,
|
|
2094
|
+
});
|
|
2095
|
+
this.opts.onChunk?.({
|
|
2096
|
+
index,
|
|
2097
|
+
bytes: chunk.size,
|
|
2098
|
+
total: totalChunks,
|
|
2099
|
+
});
|
|
2100
|
+
}
|
|
2101
|
+
|
|
2102
|
+
return result;
|
|
2103
|
+
}
|
|
2104
|
+
|
|
2028
2105
|
private async uploadChunk(
|
|
2029
2106
|
blob: Blob,
|
|
2030
2107
|
index: number,
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
|
+
restartUploadModeFromResponse,
|
|
3
|
+
restartUploadResetBody,
|
|
2
4
|
shouldReconcilePersistedRecording,
|
|
3
5
|
type OffscreenRecordingState,
|
|
4
6
|
} from "./native-recording-state";
|
|
@@ -166,6 +168,7 @@ type NativeRecording = {
|
|
|
166
168
|
// fallback so it is never lost; these describe that saved file.
|
|
167
169
|
savedToDisk?: boolean;
|
|
168
170
|
savedFilename?: string;
|
|
171
|
+
mimeType?: string;
|
|
169
172
|
};
|
|
170
173
|
|
|
171
174
|
type OffscreenStatusMessage = {
|
|
@@ -179,6 +182,7 @@ type OffscreenStatusMessage = {
|
|
|
179
182
|
savedToDisk?: boolean;
|
|
180
183
|
savedFilename?: string;
|
|
181
184
|
recordingStep?: string;
|
|
185
|
+
mimeType?: string;
|
|
182
186
|
};
|
|
183
187
|
|
|
184
188
|
type ExtensionErrorMessage = {
|
|
@@ -1512,8 +1516,8 @@ async function handleOverlayRestart() {
|
|
|
1512
1516
|
// so we must not leave the overlay stuck mid-recording/paused with no
|
|
1513
1517
|
// recorder behind it — tear the overlay back down and release those streams,
|
|
1514
1518
|
// matching the re-arm failure handling just below.
|
|
1515
|
-
const
|
|
1516
|
-
if (!
|
|
1519
|
+
const uploadMode = await resetRecordingChunks(recording);
|
|
1520
|
+
if (!uploadMode) {
|
|
1517
1521
|
recording.status = "error";
|
|
1518
1522
|
recording.error =
|
|
1519
1523
|
"Could not clear the previous take before restarting. Stop and start a new recording.";
|
|
@@ -1530,6 +1534,7 @@ async function handleOverlayRestart() {
|
|
|
1530
1534
|
error: recording.error,
|
|
1531
1535
|
};
|
|
1532
1536
|
}
|
|
1537
|
+
recording.uploadMode = uploadMode;
|
|
1533
1538
|
overlayPhase = "countdown";
|
|
1534
1539
|
overlayBaseElapsedMs = 0;
|
|
1535
1540
|
overlayBaseEpochMs = nowMs();
|
|
@@ -1579,18 +1584,25 @@ async function handleOverlayRestart() {
|
|
|
1579
1584
|
|
|
1580
1585
|
async function resetRecordingChunks(
|
|
1581
1586
|
recording: NativeRecording,
|
|
1582
|
-
): Promise<
|
|
1587
|
+
): Promise<UploadMode | null> {
|
|
1583
1588
|
const url = `${recording.clipsBaseUrl}/api/uploads/${encodeURIComponent(
|
|
1584
1589
|
recording.recordingId,
|
|
1585
1590
|
)}/reset-chunks`;
|
|
1586
|
-
const headers =
|
|
1591
|
+
const headers = {
|
|
1592
|
+
...(await authHeaders(settingsFromRecording(recording))),
|
|
1593
|
+
"Content-Type": "application/json",
|
|
1594
|
+
};
|
|
1587
1595
|
const response = await fetch(url, {
|
|
1588
1596
|
method: "POST",
|
|
1589
1597
|
headers,
|
|
1590
1598
|
credentials: "include",
|
|
1591
1599
|
cache: "no-store",
|
|
1600
|
+
body: JSON.stringify(
|
|
1601
|
+
restartUploadResetBody(recording.mimeType ?? "video/webm"),
|
|
1602
|
+
),
|
|
1592
1603
|
}).catch(() => undefined);
|
|
1593
|
-
|
|
1604
|
+
if (!response?.ok) return null;
|
|
1605
|
+
return restartUploadModeFromResponse(await response.json().catch(() => null));
|
|
1594
1606
|
}
|
|
1595
1607
|
|
|
1596
1608
|
// Finalize a successful save: open the clip and tear down the "Saving…" overlay.
|
|
@@ -2399,6 +2411,9 @@ async function dispatchRuntimeMessage(message: unknown): Promise<unknown> {
|
|
|
2399
2411
|
activeNativeRecording,
|
|
2400
2412
|
);
|
|
2401
2413
|
}
|
|
2414
|
+
if (typeof status.mimeType === "string") {
|
|
2415
|
+
activeNativeRecording.mimeType = status.mimeType;
|
|
2416
|
+
}
|
|
2402
2417
|
if (status.status === "error") {
|
|
2403
2418
|
activeNativeRecording.savedToDisk = status.savedToDisk === true;
|
|
2404
2419
|
activeNativeRecording.savedFilename =
|
|
@@ -6,6 +6,8 @@ export type NativeRecordingStateStatus =
|
|
|
6
6
|
| "complete"
|
|
7
7
|
| "error";
|
|
8
8
|
|
|
9
|
+
export type RestartUploadMode = "streaming" | "buffered";
|
|
10
|
+
|
|
9
11
|
export type OffscreenRecordingState = {
|
|
10
12
|
activeSessionId?: string;
|
|
11
13
|
preparedSessionId?: string;
|
|
@@ -30,3 +32,20 @@ export function shouldReconcilePersistedRecording(
|
|
|
30
32
|
if (status === "error" || status === "complete") return false;
|
|
31
33
|
return !hasLiveOffscreenSession(sessionId, state);
|
|
32
34
|
}
|
|
35
|
+
|
|
36
|
+
export function restartUploadResetBody(mimeType: string): {
|
|
37
|
+
requestStreaming: true;
|
|
38
|
+
mimeType: string;
|
|
39
|
+
} {
|
|
40
|
+
return { requestStreaming: true, mimeType };
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function restartUploadModeFromResponse(
|
|
44
|
+
value: unknown,
|
|
45
|
+
): RestartUploadMode | null {
|
|
46
|
+
if (!value || typeof value !== "object") return null;
|
|
47
|
+
const uploadMode = (value as { uploadMode?: unknown }).uploadMode;
|
|
48
|
+
return uploadMode === "streaming" || uploadMode === "buffered"
|
|
49
|
+
? uploadMode
|
|
50
|
+
: null;
|
|
51
|
+
}
|
|
@@ -56,6 +56,8 @@ const STORAGE_SETUP_REQUIRED_MESSAGE =
|
|
|
56
56
|
const STORAGE_SETUP_FAILURE_RE =
|
|
57
57
|
/video storage is not connected|no video storage configured|file upload provider|storage provider|connect builder|s3-compatible/i;
|
|
58
58
|
const CHUNK_UPLOAD_MAX_ATTEMPTS = 3;
|
|
59
|
+
const CHUNK_UPLOAD_TIMEOUT_MS = 60_000;
|
|
60
|
+
const FINAL_CHUNK_UPLOAD_TIMEOUT_MS = 180_000;
|
|
59
61
|
const RETRYABLE_CHUNK_UPLOAD_STATUSES = new Set([
|
|
60
62
|
408, 425, 429, 500, 502, 503, 504,
|
|
61
63
|
]);
|
|
@@ -860,6 +862,11 @@ async function uploadChunk(
|
|
|
860
862
|
headers,
|
|
861
863
|
credentials: "include",
|
|
862
864
|
body,
|
|
865
|
+
signal: AbortSignal.timeout(
|
|
866
|
+
extra.isFinal
|
|
867
|
+
? FINAL_CHUNK_UPLOAD_TIMEOUT_MS
|
|
868
|
+
: CHUNK_UPLOAD_TIMEOUT_MS,
|
|
869
|
+
),
|
|
863
870
|
});
|
|
864
871
|
} catch (err) {
|
|
865
872
|
if (attempt >= CHUNK_UPLOAD_MAX_ATTEMPTS) throw err;
|
|
@@ -1387,6 +1394,7 @@ function startRecorderNow(recording: ActiveRecording): void {
|
|
|
1387
1394
|
height: recording.dimensions.height,
|
|
1388
1395
|
hasAudio: recording.hasAudio,
|
|
1389
1396
|
hasCamera: recording.hasCamera,
|
|
1397
|
+
mimeType: recording.mimeType,
|
|
1390
1398
|
});
|
|
1391
1399
|
} catch (err) {
|
|
1392
1400
|
captureExtensionError(err, {
|
|
@@ -344,6 +344,14 @@ export function RecordingPill() {
|
|
|
344
344
|
void toggleExpanded();
|
|
345
345
|
};
|
|
346
346
|
|
|
347
|
+
const handlePillMouseUp = (e: React.MouseEvent) => {
|
|
348
|
+
const start = dragStartScreenPointRef.current;
|
|
349
|
+
if (isDirectPillClick(start, { x: e.screenX, y: e.screenY })) return;
|
|
350
|
+
void invoke("recording_pill_save_position").catch((err) => {
|
|
351
|
+
console.warn("[clips-pill] save position failed", err);
|
|
352
|
+
});
|
|
353
|
+
};
|
|
354
|
+
|
|
347
355
|
const mm = String(Math.floor(elapsed / 60)).padStart(2, "0");
|
|
348
356
|
const ss = String(elapsed % 60).padStart(2, "0");
|
|
349
357
|
const stopLabel =
|
|
@@ -356,6 +364,7 @@ export function RecordingPill() {
|
|
|
356
364
|
hovered ? " pill-hovered" : ""
|
|
357
365
|
}`}
|
|
358
366
|
onMouseDown={handlePillMouseDown}
|
|
367
|
+
onMouseUp={handlePillMouseUp}
|
|
359
368
|
>
|
|
360
369
|
<div
|
|
361
370
|
className={`pill-header${
|
|
@@ -130,20 +130,32 @@ fn pill_detached_position_path(app: &AppHandle) -> Option<PathBuf> {
|
|
|
130
130
|
Some(dir.join("pill-position-detached.json"))
|
|
131
131
|
}
|
|
132
132
|
|
|
133
|
-
|
|
133
|
+
#[derive(Deserialize)]
|
|
134
|
+
struct MeetingPillPosition {
|
|
135
|
+
x: i32,
|
|
136
|
+
y: i32,
|
|
137
|
+
#[serde(default)]
|
|
138
|
+
anchor: Option<String>,
|
|
139
|
+
#[serde(default)]
|
|
140
|
+
width: Option<u32>,
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
fn load_meeting_position(app: &AppHandle) -> Option<MeetingPillPosition> {
|
|
134
144
|
let path = pill_meeting_position_path(app)?;
|
|
135
145
|
let bytes = std::fs::read(&path).ok()?;
|
|
136
|
-
|
|
137
|
-
let x = value.get("x")?.as_i64()? as i32;
|
|
138
|
-
let y = value.get("y")?.as_i64()? as i32;
|
|
139
|
-
Some((x, y))
|
|
146
|
+
serde_json::from_slice(&bytes).ok()
|
|
140
147
|
}
|
|
141
148
|
|
|
142
|
-
fn save_meeting_position_to_disk(app: &AppHandle, x: i32, y: i32) {
|
|
149
|
+
fn save_meeting_position_to_disk(app: &AppHandle, x: i32, y: i32, width: u32) {
|
|
143
150
|
let Some(path) = pill_meeting_position_path(app) else {
|
|
144
151
|
return;
|
|
145
152
|
};
|
|
146
|
-
let body = match serde_json::to_vec(&serde_json::json!({
|
|
153
|
+
let body = match serde_json::to_vec(&serde_json::json!({
|
|
154
|
+
"x": x + width as i32,
|
|
155
|
+
"y": y,
|
|
156
|
+
"anchor": "right",
|
|
157
|
+
"width": width,
|
|
158
|
+
})) {
|
|
147
159
|
Ok(b) => b,
|
|
148
160
|
Err(_) => return,
|
|
149
161
|
};
|
|
@@ -313,7 +325,28 @@ fn anchored_rect(
|
|
|
313
325
|
let (_, h_exp) = pill_size_physical(app, true);
|
|
314
326
|
let max_y_exp = (my + mh as i32 - h_exp as i32).max(my);
|
|
315
327
|
let (x, y) = match load_meeting_position(app) {
|
|
316
|
-
Some(
|
|
328
|
+
Some(position) if position.anchor.as_deref() == Some("right") => {
|
|
329
|
+
let saved_width = position.width.unwrap_or(w);
|
|
330
|
+
(
|
|
331
|
+
(position.x - saved_width as i32).clamp(mx, max_x),
|
|
332
|
+
position.y.clamp(my, max_y_exp),
|
|
333
|
+
)
|
|
334
|
+
}
|
|
335
|
+
Some(position) => {
|
|
336
|
+
let (expanded_w, _) = pill_size_physical(app, true);
|
|
337
|
+
let right_margin = (PILL_RIGHT_MARGIN_LOGICAL as f64 * scale_factor(app)) as i32;
|
|
338
|
+
let legacy_right_edge = position.x + expanded_w as i32;
|
|
339
|
+
let monitor_right = mx + mw as i32;
|
|
340
|
+
if (legacy_right_edge - (monitor_right - right_margin)).abs() <= 4 {
|
|
341
|
+
save_meeting_position_to_disk(app, position.x, position.y, expanded_w);
|
|
342
|
+
(
|
|
343
|
+
(legacy_right_edge - w as i32).clamp(mx, max_x),
|
|
344
|
+
position.y.clamp(my, max_y_exp),
|
|
345
|
+
)
|
|
346
|
+
} else {
|
|
347
|
+
(position.x.clamp(mx, max_x), position.y.clamp(my, max_y_exp))
|
|
348
|
+
}
|
|
349
|
+
}
|
|
317
350
|
None => default_center_right(app, w, h),
|
|
318
351
|
};
|
|
319
352
|
return (w, h, x, y);
|
|
@@ -492,35 +525,28 @@ pub async fn recording_pill_expand(app: AppHandle, expanded: bool) -> Result<(),
|
|
|
492
525
|
pub async fn recording_pill_hide(app: AppHandle) -> Result<(), String> {
|
|
493
526
|
stop_pill_hover_tracking();
|
|
494
527
|
if let Some(w) = app.get_webview_window(PILL_LABEL) {
|
|
495
|
-
// Snapshot current position before close so the next show re-opens
|
|
496
|
-
// at the user's chosen spot.
|
|
497
|
-
if let Ok(pos) = w.outer_position() {
|
|
498
|
-
if PILL_DETACHED.load(Ordering::Relaxed) {
|
|
499
|
-
save_detached_position_to_disk(&app, pos.x, pos.y);
|
|
500
|
-
} else if PILL_RIGHT_SIDE.load(Ordering::Relaxed) {
|
|
501
|
-
save_meeting_position_to_disk(&app, pos.x, pos.y);
|
|
502
|
-
} else {
|
|
503
|
-
save_pill_position_to_disk(&app, pos.x, pos.y);
|
|
504
|
-
}
|
|
505
|
-
}
|
|
506
528
|
let _ = w.close();
|
|
507
529
|
}
|
|
508
530
|
Ok(())
|
|
509
531
|
}
|
|
510
532
|
|
|
511
|
-
/// Persist the pill's current position. Called by the React side after the
|
|
512
|
-
/// user drag-moves it (mouseup) so the next `show` reopens at the chosen
|
|
513
|
-
/// spot.
|
|
514
533
|
#[tauri::command]
|
|
515
|
-
pub async fn recording_pill_save_position(app: AppHandle
|
|
516
|
-
|
|
517
|
-
|
|
534
|
+
pub async fn recording_pill_save_position(app: AppHandle) -> Result<(), String> {
|
|
535
|
+
let Some(window) = app.get_webview_window(PILL_LABEL) else {
|
|
536
|
+
return Ok(());
|
|
537
|
+
};
|
|
538
|
+
let Ok(position) = window.outer_position() else {
|
|
539
|
+
return Ok(());
|
|
540
|
+
};
|
|
541
|
+
|
|
518
542
|
if PILL_DETACHED.load(Ordering::Relaxed) {
|
|
519
|
-
save_detached_position_to_disk(&app, x, y);
|
|
543
|
+
save_detached_position_to_disk(&app, position.x, position.y);
|
|
520
544
|
} else if PILL_RIGHT_SIDE.load(Ordering::Relaxed) {
|
|
521
|
-
|
|
545
|
+
if let Ok(size) = window.outer_size() {
|
|
546
|
+
save_meeting_position_to_disk(&app, position.x, position.y, size.width);
|
|
547
|
+
}
|
|
522
548
|
} else {
|
|
523
|
-
save_pill_position_to_disk(&app, x, y);
|
|
549
|
+
save_pill_position_to_disk(&app, position.x, position.y);
|
|
524
550
|
}
|
|
525
551
|
Ok(())
|
|
526
552
|
}
|