@agent-native/core 0.121.1 → 0.122.0
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/corpus/README.md +2 -2
- package/corpus/core/CHANGELOG.md +145 -0
- package/corpus/core/docs/content/actions.mdx +2 -2
- package/corpus/core/docs/content/agent-surfaces.mdx +1 -1
- package/corpus/core/docs/content/authentication.mdx +2 -0
- package/corpus/core/docs/content/deployment.mdx +36 -0
- package/corpus/core/docs/content/getting-started.mdx +477 -115
- package/corpus/core/docs/content/http-api.mdx +266 -0
- package/corpus/core/docs/content/syncing-template-changes.mdx +159 -0
- package/corpus/core/package.json +2 -1
- package/corpus/core/src/a2a/activity.ts +38 -27
- package/corpus/core/src/agent/engine/builder-engine.ts +35 -4
- package/corpus/core/src/agent/run-manager.ts +20 -1
- package/corpus/core/src/agent/run-store.ts +4 -1
- package/corpus/core/src/agent/types.ts +28 -8
- package/corpus/core/src/chat-threads/store.ts +45 -0
- package/corpus/core/src/checkpoints/index.ts +2 -0
- package/corpus/core/src/checkpoints/route-match.ts +13 -0
- package/corpus/core/src/cli/create.ts +105 -17
- package/corpus/core/src/cli/index.ts +20 -0
- package/corpus/core/src/cli/template-baseline.ts +410 -0
- package/corpus/core/src/cli/template-sync.ts +1004 -0
- package/corpus/core/src/cli/templates-meta.ts +1 -0
- package/corpus/core/src/client/AssistantChat.tsx +38 -12
- package/corpus/core/src/client/NewWorkspaceAppFlow.tsx +75 -10
- package/corpus/core/src/client/chat/message-components.tsx +127 -66
- package/corpus/core/src/client/chat/tool-call-display.tsx +29 -5
- package/corpus/core/src/client/error-format.ts +18 -0
- package/corpus/core/src/client/org/OrgSwitcher.tsx +30 -8
- package/corpus/core/src/client/org/TeamPage.tsx +7 -6
- package/corpus/core/src/client/sse-event-processor.ts +3 -0
- package/corpus/core/src/data-widgets/index.ts +41 -0
- package/corpus/core/src/deploy/build.ts +11 -9
- package/corpus/core/src/integrations/webhook-handler.ts +63 -9
- package/corpus/core/src/org/auto-join-domain.ts +4 -3
- package/corpus/core/src/org/context.ts +108 -39
- package/corpus/core/src/org/index.ts +5 -0
- package/corpus/core/src/org/service-identity.ts +60 -0
- package/corpus/core/src/provider-api/index.ts +22 -1
- package/corpus/core/src/scripts/docs/search.ts +12 -1
- package/corpus/core/src/server/agent-chat/context-tools.ts +9 -4
- package/corpus/core/src/server/agent-chat/framework-prompts.ts +38 -66
- package/corpus/core/src/server/agent-chat-plugin.ts +17 -10
- package/corpus/core/src/server/agents-bundle.ts +84 -5
- package/corpus/core/src/server/auth.ts +4 -3
- package/corpus/core/src/server/builder-browser.ts +47 -19
- package/corpus/core/src/server/core-routes-plugin.ts +2 -2
- package/corpus/core/src/server/credential-provider.ts +209 -68
- package/corpus/core/src/server/index.ts +3 -0
- package/corpus/core/src/server/prompts/framework-core-compact.ts +6 -13
- package/corpus/core/src/server/prompts/framework-core.ts +9 -21
- package/corpus/core/src/server/prompts/index.ts +0 -1
- package/corpus/core/src/server/prompts/shared-rules.ts +19 -11
- package/corpus/core/src/server/ssr-handler.ts +13 -2
- package/corpus/core/src/settings/user-settings.ts +13 -1
- package/corpus/core/src/shared/cache-control.ts +141 -0
- package/corpus/core/src/templates/chat/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
- package/corpus/core/src/templates/chat/_gitignore +1 -0
- package/corpus/core/src/templates/default/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
- package/corpus/core/src/templates/headless/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
- package/corpus/core/src/templates/workspace-core/.agents/skills/performance/SKILL.md +19 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
- package/corpus/core/src/templates/workspace-core/.agents/skills/visual-answer/SKILL.md +1 -0
- package/corpus/core/src/vite/agents-bundle-plugin.ts +7 -6
- package/corpus/core/src/vite/client.ts +5 -0
- package/corpus/templates/analytics/.agents/skills/adhoc-analysis/SKILL.md +4 -5
- package/corpus/templates/analytics/.agents/skills/admin-surfaces/SKILL.md +55 -0
- package/corpus/templates/analytics/.agents/skills/dashboard-management/SKILL.md +10 -0
- package/corpus/templates/analytics/.agents/skills/dashboard-management/references/template-catalog-and-demo.md +62 -0
- package/corpus/templates/analytics/.agents/skills/dashboard-ops/SKILL.md +85 -0
- package/corpus/templates/analytics/.agents/skills/data-querying/SKILL.md +27 -2
- package/corpus/templates/analytics/.agents/skills/data-querying/references/inline-chart-embeds.md +139 -0
- package/corpus/templates/analytics/.agents/skills/monitoring/SKILL.md +77 -0
- package/corpus/templates/analytics/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
- package/corpus/templates/analytics/AGENTS.md +91 -563
- package/corpus/templates/analytics/_gitignore +1 -0
- package/corpus/templates/analytics/actions/bigquery.ts +12 -4
- package/corpus/templates/analytics/actions/generate-chart.ts +5 -5
- package/corpus/templates/analytics/app/components/dashboard/SqlChart.tsx +30 -1
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/DashboardFilterBar.tsx +3 -0
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/SqlChartCard.tsx +1 -1
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +1 -0
- package/corpus/templates/analytics/changelog/2026-07-24-analytics-finds-saved-dashboards-and-queries-far-more-reliab.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-24-notion-access-errors-now-explain-that-a-page-needs-sharing-w.md +6 -0
- package/corpus/templates/analytics/server/lib/agent-chat-plan-mode.ts +7 -0
- package/corpus/templates/analytics/server/lib/analytics-query-catalog.ts +191 -30
- package/corpus/templates/analytics/server/lib/bigquery.ts +11 -1
- package/corpus/templates/analytics/server/lib/notion.ts +15 -4
- package/corpus/templates/analytics/server/plugins/agent-chat.ts +10 -0
- package/corpus/templates/assets/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
- package/corpus/templates/brain/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
- package/corpus/templates/brain/_gitignore +1 -0
- package/corpus/templates/calendar/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
- package/corpus/templates/calendar/_gitignore +1 -0
- package/corpus/templates/chat/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
- package/corpus/templates/chat/_gitignore +1 -0
- package/corpus/templates/clips/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
- package/corpus/templates/clips/.agents/skills/video-sharing/SKILL.md +34 -0
- package/corpus/templates/clips/AGENTS.md +5 -4
- package/corpus/templates/clips/_gitignore +1 -0
- package/corpus/templates/clips/actions/cleanup-transcript.ts +5 -0
- package/corpus/templates/clips/actions/get-recording-insights.ts +44 -8
- package/corpus/templates/clips/actions/get-recording-player-data.ts +39 -70
- package/corpus/templates/clips/actions/list-clip-views.ts +2 -4
- package/corpus/templates/clips/actions/list-recordings.ts +69 -19
- package/corpus/templates/clips/actions/list-viewers.ts +5 -2
- package/corpus/templates/clips/actions/regenerate-summary.ts +5 -1
- package/corpus/templates/clips/actions/request-transcript.ts +28 -1
- package/corpus/templates/clips/app/components/editor/stitch-manager.tsx +21 -1
- package/corpus/templates/clips/app/components/meetings/quick-ask-sidebar.tsx +14 -1
- package/corpus/templates/clips/app/components/player/insights-panel.tsx +8 -20
- package/corpus/templates/clips/app/components/player/recording-views-badge.tsx +335 -0
- package/corpus/templates/clips/app/components/player/video-player.tsx +13 -8
- package/corpus/templates/clips/app/components/sharing/share-ui.tsx +2 -1
- package/corpus/templates/clips/app/i18n/en-US.ts +13 -2
- package/corpus/templates/clips/app/lib/capture-permissions.ts +110 -0
- package/corpus/templates/clips/app/lib/recording-link.ts +32 -0
- package/corpus/templates/clips/app/routes/_app.meetings.$meetingId.tsx +27 -0
- package/corpus/templates/clips/app/routes/r.$recordingId.tsx +46 -15
- package/corpus/templates/clips/app/routes/record.tsx +77 -31
- package/corpus/templates/clips/app/routes/share.$shareId.tsx +42 -31
- package/corpus/templates/clips/changelog/2026-07-24-clip-pages-now-show-a-view-count-with-viewer-avatars-next-to.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-24-clip-summaries-read-like-a-description-you-d-write-yourself-.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-24-clip-view-counts-now-separate-human-views-from-agent-views-s.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-24-clips-actions-can-now-be-called-by-org-service-tokens-so-ext.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-24-clips-no-longer-briefly-shows-a-dock-icon-while-launching.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-24-fixed-owner-and-editor-share-links-redirecting-to-the-record.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-24-meeting-and-note-recordings-now-start-as-a-compact-pill-on-t.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-24-new-clips-now-copy-a-shareable-link-instead-of-the-owner-onl.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-24-opening-a-share-link-as-the-clip-s-owner-now-goes-straight-t.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-24-permissions-and-rewind-controls-now-use-compact-consistent-h.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-24-quitting-the-desktop-app-no-longer-shows-a-false-macos-crash.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-24-screen-recording-permission-errors-now-name-the-exact-app-to.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-24-the-desktop-app-now-copies-a-new-clip-s-share-link-to-your-c.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-24-the-recording-toolbar-now-stays-above-other-apps-including-o.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-24-transcript-captions-now-use-real-speech-timings-instead-of-a.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-24-video-playback-no-longer-stutters-and-replays-the-last-momen.md +6 -0
- package/corpus/templates/clips/chrome-extension/src/background.ts +17 -1
- package/corpus/templates/clips/desktop/package.json +2 -0
- package/corpus/templates/clips/desktop/src/app.tsx +89 -0
- package/corpus/templates/clips/desktop/src/hooks/useMeetingTranscription.ts +9 -3
- package/corpus/templates/clips/desktop/src/lib/audio-meter.ts +51 -0
- package/corpus/templates/clips/desktop/src/lib/native-notification.ts +44 -0
- package/corpus/templates/clips/desktop/src/lib/recording-link.ts +67 -0
- package/corpus/templates/clips/desktop/src/overlays/live-audio-bars.tsx +35 -35
- package/corpus/templates/clips/desktop/src/overlays/live-transcript.tsx +3 -2
- package/corpus/templates/clips/desktop/src/overlays/recording-pill.tsx +47 -46
- package/corpus/templates/clips/desktop/src/styles.css +127 -78
- package/corpus/templates/clips/desktop/src-tauri/Cargo.toml +7 -0
- package/corpus/templates/clips/desktop/src-tauri/Info.plist +6 -0
- package/corpus/templates/clips/desktop/src-tauri/capabilities/default.json +1 -0
- package/corpus/templates/clips/desktop/src-tauri/src/clips/mod.rs +7 -3
- package/corpus/templates/clips/desktop/src-tauri/src/lib.rs +4 -1
- package/corpus/templates/clips/desktop/src-tauri/src/main.rs +8 -0
- package/corpus/templates/clips/desktop/src-tauri/src/recording_indicator.rs +21 -10
- package/corpus/templates/clips/desktop/src-tauri/src/util.rs +40 -0
- package/corpus/templates/clips/server/db/schema.ts +25 -0
- package/corpus/templates/clips/server/lib/agent-views.ts +145 -0
- package/corpus/templates/clips/server/lib/public-agent-context.ts +7 -0
- package/corpus/templates/clips/server/lib/recording-share-grant.ts +79 -0
- package/corpus/templates/clips/server/lib/recordings.ts +51 -3
- package/corpus/templates/clips/server/plugins/db.ts +23 -0
- package/corpus/templates/clips/server/routes/api/public-recording.get.ts +49 -17
- package/corpus/templates/clips/shared/recording-link.ts +43 -0
- package/corpus/templates/clips/shared/share-attribution.ts +4 -0
- package/corpus/templates/clips/shared/share-dashboard-redirect.ts +42 -0
- package/corpus/templates/clips/shared/view-analytics.ts +26 -0
- package/corpus/templates/content/.agents/skills/content/SKILL.md +5 -0
- package/corpus/templates/content/.agents/skills/content/references/local-file-mode.md +135 -0
- package/corpus/templates/content/.agents/skills/document-editing/SKILL.md +12 -0
- package/corpus/templates/content/.agents/skills/document-editing/references/databases.md +238 -0
- package/corpus/templates/content/.agents/skills/document-editing/references/document-behavior.md +91 -0
- package/corpus/templates/content/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
- package/corpus/templates/content/AGENTS.md +62 -583
- package/corpus/templates/content/_gitignore +1 -0
- package/corpus/templates/design/.agents/skills/creative-context/SKILL.md +11 -0
- package/corpus/templates/design/.agents/skills/design-generation/SKILL.md +50 -8
- package/corpus/templates/design/.agents/skills/design-generation/references/code-layers.md +81 -0
- package/corpus/templates/design/.agents/skills/design-generation/references/code-workspace.md +42 -0
- package/corpus/templates/design/.agents/skills/design-generation/references/editor-extensions.md +34 -0
- package/corpus/templates/design/.agents/skills/responsive-breakpoints/SKILL.md +4 -1
- package/corpus/templates/design/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
- package/corpus/templates/design/.agents/skills/visual-edit/SKILL.md +17 -0
- package/corpus/templates/design/.generated/bridge/editor-chrome.generated.ts +8196 -0
- package/corpus/templates/design/.generated/bridge/embedded-wheel.generated.ts +265 -0
- package/corpus/templates/design/.generated/bridge/hit-test.generated.ts +642 -0
- package/corpus/templates/design/.generated/bridge/motion-preview.generated.ts +571 -0
- package/corpus/templates/design/.generated/bridge/nav.generated.ts +91 -0
- package/corpus/templates/design/.generated/bridge/sample.generated.ts +23 -0
- package/corpus/templates/design/.generated/bridge/shader-fill-preview.generated.ts +263 -0
- package/corpus/templates/design/.generated/bridge/shader-runtime.generated.ts +518 -0
- package/corpus/templates/design/.generated/bridge/tweak.generated.ts +20 -0
- package/corpus/templates/design/.generated/bridge/zoom.generated.ts +32 -0
- package/corpus/templates/design/AGENTS.md +88 -503
- package/corpus/templates/design/_gitignore +1 -0
- package/corpus/templates/dispatch/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
- package/corpus/templates/dispatch/_gitignore +1 -0
- package/corpus/templates/dispatch/changelog/2026-07-24-signing-in-now-puts-you-in-your-companys-workspace.md +6 -0
- package/corpus/templates/forms/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
- package/corpus/templates/forms/_gitignore +1 -0
- package/corpus/templates/forms/server/lib/public-form-ssr.ts +2 -2
- package/corpus/templates/macros/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
- package/corpus/templates/macros/_gitignore +1 -0
- package/corpus/templates/mail/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
- package/corpus/templates/mail/_gitignore +1 -0
- package/corpus/templates/plan/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
- package/corpus/templates/plan/_gitignore +1 -0
- package/corpus/templates/slides/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
- package/corpus/templates/slides/_gitignore +1 -0
- package/corpus/templates/slides/server/plugins/db.ts +4 -0
- package/corpus/templates/tasks/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
- package/corpus/templates/tasks/AGENTS.md +1 -1
- package/corpus/templates/tasks/_gitignore +1 -0
- package/dist/a2a/activity.d.ts +4 -1
- package/dist/a2a/activity.d.ts.map +1 -1
- package/dist/a2a/activity.js +27 -16
- package/dist/a2a/activity.js.map +1 -1
- package/dist/agent/engine/builder-engine.d.ts +1 -0
- package/dist/agent/engine/builder-engine.d.ts.map +1 -1
- package/dist/agent/engine/builder-engine.js +31 -4
- package/dist/agent/engine/builder-engine.js.map +1 -1
- package/dist/agent/run-manager.d.ts.map +1 -1
- package/dist/agent/run-manager.js +18 -1
- package/dist/agent/run-manager.js.map +1 -1
- package/dist/agent/run-store.d.ts +1 -0
- package/dist/agent/run-store.d.ts.map +1 -1
- package/dist/agent/run-store.js +2 -1
- package/dist/agent/run-store.js.map +1 -1
- package/dist/agent/types.d.ts +12 -1
- package/dist/agent/types.d.ts.map +1 -1
- package/dist/agent/types.js +21 -1
- package/dist/agent/types.js.map +1 -1
- package/dist/chat-threads/store.d.ts +10 -0
- package/dist/chat-threads/store.d.ts.map +1 -1
- package/dist/chat-threads/store.js +41 -0
- package/dist/chat-threads/store.js.map +1 -1
- package/dist/checkpoints/index.d.ts +1 -0
- package/dist/checkpoints/index.d.ts.map +1 -1
- package/dist/checkpoints/index.js +1 -0
- package/dist/checkpoints/index.js.map +1 -1
- package/dist/checkpoints/route-match.d.ts +8 -0
- package/dist/checkpoints/route-match.d.ts.map +1 -0
- package/dist/checkpoints/route-match.js +13 -0
- package/dist/checkpoints/route-match.js.map +1 -0
- package/dist/cli/create.d.ts +35 -4
- package/dist/cli/create.d.ts.map +1 -1
- package/dist/cli/create.js +69 -19
- package/dist/cli/create.js.map +1 -1
- package/dist/cli/index.js +19 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/template-baseline.d.ts +54 -0
- package/dist/cli/template-baseline.d.ts.map +1 -0
- package/dist/cli/template-baseline.js +334 -0
- package/dist/cli/template-baseline.js.map +1 -0
- package/dist/cli/template-sync.d.ts +57 -0
- package/dist/cli/template-sync.d.ts.map +1 -0
- package/dist/cli/template-sync.js +787 -0
- package/dist/cli/template-sync.js.map +1 -0
- package/dist/cli/templates-meta.d.ts.map +1 -1
- package/dist/cli/templates-meta.js +1 -0
- package/dist/cli/templates-meta.js.map +1 -1
- package/dist/client/AssistantChat.d.ts +2 -1
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +38 -10
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/NewWorkspaceAppFlow.d.ts.map +1 -1
- package/dist/client/NewWorkspaceAppFlow.js +32 -2
- package/dist/client/NewWorkspaceAppFlow.js.map +1 -1
- package/dist/client/chat/message-components.d.ts +20 -0
- package/dist/client/chat/message-components.d.ts.map +1 -1
- package/dist/client/chat/message-components.js +81 -46
- package/dist/client/chat/message-components.js.map +1 -1
- package/dist/client/chat/tool-call-display.d.ts.map +1 -1
- package/dist/client/chat/tool-call-display.js +14 -6
- package/dist/client/chat/tool-call-display.js.map +1 -1
- package/dist/client/error-format.d.ts.map +1 -1
- package/dist/client/error-format.js +13 -0
- package/dist/client/error-format.js.map +1 -1
- package/dist/client/org/OrgSwitcher.d.ts +8 -1
- package/dist/client/org/OrgSwitcher.d.ts.map +1 -1
- package/dist/client/org/OrgSwitcher.js +3 -2
- package/dist/client/org/OrgSwitcher.js.map +1 -1
- package/dist/client/org/TeamPage.d.ts.map +1 -1
- package/dist/client/org/TeamPage.js +1 -1
- package/dist/client/org/TeamPage.js.map +1 -1
- package/dist/client/sse-event-processor.d.ts.map +1 -1
- package/dist/client/sse-event-processor.js +3 -0
- package/dist/client/sse-event-processor.js.map +1 -1
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/awareness.d.ts.map +1 -1
- package/dist/data-widgets/index.d.ts +3 -0
- package/dist/data-widgets/index.d.ts.map +1 -1
- package/dist/data-widgets/index.js +33 -0
- package/dist/data-widgets/index.js.map +1 -1
- package/dist/deploy/build.d.ts.map +1 -1
- package/dist/deploy/build.js +11 -7
- package/dist/deploy/build.js.map +1 -1
- package/dist/eject/provider-api-definitions.d.ts +1 -0
- package/dist/eject/provider-api-definitions.d.ts.map +1 -1
- package/dist/integrations/webhook-handler.d.ts.map +1 -1
- package/dist/integrations/webhook-handler.js +46 -9
- package/dist/integrations/webhook-handler.js.map +1 -1
- package/dist/notifications/routes.d.ts +3 -3
- package/dist/observability/routes.d.ts +3 -3
- package/dist/org/auto-join-domain.d.ts +3 -2
- package/dist/org/auto-join-domain.d.ts.map +1 -1
- package/dist/org/auto-join-domain.js +1 -1
- package/dist/org/auto-join-domain.js.map +1 -1
- package/dist/org/context.d.ts.map +1 -1
- package/dist/org/context.js +84 -28
- package/dist/org/context.js.map +1 -1
- package/dist/org/index.d.ts +1 -0
- package/dist/org/index.d.ts.map +1 -1
- package/dist/org/index.js +1 -0
- package/dist/org/index.js.map +1 -1
- package/dist/org/service-identity.d.ts +43 -0
- package/dist/org/service-identity.d.ts.map +1 -0
- package/dist/org/service-identity.js +34 -0
- package/dist/org/service-identity.js.map +1 -0
- package/dist/provider-api/actions/custom-provider-registration.d.ts +14 -14
- package/dist/provider-api/actions/provider-api.d.ts +13 -11
- package/dist/provider-api/actions/provider-api.d.ts.map +1 -1
- package/dist/provider-api/index.d.ts +4 -0
- package/dist/provider-api/index.d.ts.map +1 -1
- package/dist/provider-api/index.js +17 -1
- package/dist/provider-api/index.js.map +1 -1
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/scripts/docs/search.d.ts.map +1 -1
- package/dist/scripts/docs/search.js +12 -1
- package/dist/scripts/docs/search.js.map +1 -1
- package/dist/server/agent-chat/context-tools.d.ts.map +1 -1
- package/dist/server/agent-chat/context-tools.js +3 -3
- package/dist/server/agent-chat/context-tools.js.map +1 -1
- package/dist/server/agent-chat/framework-prompts.d.ts +8 -3
- package/dist/server/agent-chat/framework-prompts.d.ts.map +1 -1
- package/dist/server/agent-chat/framework-prompts.js +33 -62
- 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 +16 -10
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/agents-bundle.d.ts +18 -0
- package/dist/server/agents-bundle.d.ts.map +1 -1
- package/dist/server/agents-bundle.js +70 -4
- package/dist/server/agents-bundle.js.map +1 -1
- package/dist/server/auth.d.ts.map +1 -1
- package/dist/server/auth.js +4 -3
- package/dist/server/auth.js.map +1 -1
- package/dist/server/builder-browser.d.ts.map +1 -1
- package/dist/server/builder-browser.js +43 -19
- package/dist/server/builder-browser.js.map +1 -1
- package/dist/server/core-routes-plugin.js +2 -2
- package/dist/server/core-routes-plugin.js.map +1 -1
- package/dist/server/credential-provider.d.ts +38 -2
- package/dist/server/credential-provider.d.ts.map +1 -1
- package/dist/server/credential-provider.js +142 -64
- package/dist/server/credential-provider.js.map +1 -1
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +1 -1
- package/dist/server/index.js.map +1 -1
- package/dist/server/prompts/framework-core-compact.d.ts +1 -1
- package/dist/server/prompts/framework-core-compact.d.ts.map +1 -1
- package/dist/server/prompts/framework-core-compact.js +7 -13
- package/dist/server/prompts/framework-core-compact.js.map +1 -1
- package/dist/server/prompts/framework-core.d.ts +1 -1
- package/dist/server/prompts/framework-core.d.ts.map +1 -1
- package/dist/server/prompts/framework-core.js +10 -21
- package/dist/server/prompts/framework-core.js.map +1 -1
- package/dist/server/prompts/index.d.ts +1 -1
- package/dist/server/prompts/index.d.ts.map +1 -1
- package/dist/server/prompts/index.js +1 -1
- package/dist/server/prompts/index.js.map +1 -1
- package/dist/server/prompts/shared-rules.d.ts +16 -10
- package/dist/server/prompts/shared-rules.d.ts.map +1 -1
- package/dist/server/prompts/shared-rules.js +19 -10
- package/dist/server/prompts/shared-rules.js.map +1 -1
- package/dist/server/ssr-handler.d.ts +1 -1
- package/dist/server/ssr-handler.d.ts.map +1 -1
- package/dist/server/ssr-handler.js +10 -3
- package/dist/server/ssr-handler.js.map +1 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/dist/settings/user-settings.d.ts.map +1 -1
- package/dist/settings/user-settings.js +13 -1
- package/dist/settings/user-settings.js.map +1 -1
- package/dist/shared/cache-control.d.ts +52 -0
- package/dist/shared/cache-control.d.ts.map +1 -1
- package/dist/shared/cache-control.js +107 -0
- package/dist/shared/cache-control.js.map +1 -1
- package/dist/templates/chat/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
- package/dist/templates/chat/_gitignore +1 -0
- package/dist/templates/default/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
- package/dist/templates/headless/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
- package/dist/templates/workspace-core/.agents/skills/performance/SKILL.md +19 -0
- package/dist/templates/workspace-core/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
- package/dist/templates/workspace-core/.agents/skills/visual-answer/SKILL.md +1 -0
- package/dist/vite/agents-bundle-plugin.d.ts.map +1 -1
- package/dist/vite/agents-bundle-plugin.js +8 -7
- package/dist/vite/agents-bundle-plugin.js.map +1 -1
- package/dist/vite/client.d.ts.map +1 -1
- package/dist/vite/client.js +2 -0
- package/dist/vite/client.js.map +1 -1
- package/docs/content/actions.mdx +2 -2
- package/docs/content/agent-surfaces.mdx +1 -1
- package/docs/content/authentication.mdx +2 -0
- package/docs/content/deployment.mdx +36 -0
- package/docs/content/getting-started.mdx +477 -115
- package/docs/content/http-api.mdx +266 -0
- package/docs/content/syncing-template-changes.mdx +159 -0
- package/package.json +4 -3
- package/src/a2a/activity.ts +38 -27
- package/src/agent/engine/builder-engine.ts +35 -4
- package/src/agent/run-manager.ts +20 -1
- package/src/agent/run-store.ts +4 -1
- package/src/agent/types.ts +28 -8
- package/src/chat-threads/store.ts +45 -0
- package/src/checkpoints/index.ts +2 -0
- package/src/checkpoints/route-match.ts +13 -0
- package/src/cli/create.ts +105 -17
- package/src/cli/index.ts +20 -0
- package/src/cli/template-baseline.ts +410 -0
- package/src/cli/template-sync.ts +1004 -0
- package/src/cli/templates-meta.ts +1 -0
- package/src/client/AssistantChat.tsx +38 -12
- package/src/client/NewWorkspaceAppFlow.tsx +75 -10
- package/src/client/chat/message-components.tsx +127 -66
- package/src/client/chat/tool-call-display.tsx +29 -5
- package/src/client/error-format.ts +18 -0
- package/src/client/org/OrgSwitcher.tsx +30 -8
- package/src/client/org/TeamPage.tsx +7 -6
- package/src/client/sse-event-processor.ts +3 -0
- package/src/data-widgets/index.ts +41 -0
- package/src/deploy/build.ts +11 -9
- package/src/integrations/webhook-handler.ts +63 -9
- package/src/org/auto-join-domain.ts +4 -3
- package/src/org/context.ts +108 -39
- package/src/org/index.ts +5 -0
- package/src/org/service-identity.ts +60 -0
- package/src/provider-api/index.ts +22 -1
- package/src/scripts/docs/search.ts +12 -1
- package/src/server/__snapshots__/agent-chat-plugin.surface.spec.ts.snap +25 -36
- package/src/server/agent-chat/context-tools.ts +9 -4
- package/src/server/agent-chat/framework-prompts.ts +38 -66
- package/src/server/agent-chat-plugin.ts +17 -10
- package/src/server/agents-bundle.ts +84 -5
- package/src/server/auth.ts +4 -3
- package/src/server/builder-browser.ts +47 -19
- package/src/server/core-routes-plugin.ts +2 -2
- package/src/server/credential-provider.ts +209 -68
- package/src/server/index.ts +3 -0
- package/src/server/prompts/framework-core-compact.ts +6 -13
- package/src/server/prompts/framework-core.ts +9 -21
- package/src/server/prompts/index.ts +0 -1
- package/src/server/prompts/shared-rules.ts +19 -11
- package/src/server/ssr-handler.ts +13 -2
- package/src/settings/user-settings.ts +13 -1
- package/src/shared/cache-control.ts +141 -0
- package/src/templates/chat/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
- package/src/templates/chat/_gitignore +1 -0
- package/src/templates/default/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
- package/src/templates/headless/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
- package/src/templates/workspace-core/.agents/skills/performance/SKILL.md +19 -0
- package/src/templates/workspace-core/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
- package/src/templates/workspace-core/.agents/skills/visual-answer/SKILL.md +1 -0
- package/src/vite/agents-bundle-plugin.ts +7 -6
- package/src/vite/client.ts +5 -0
|
@@ -101,7 +101,11 @@ export default defineAction({
|
|
|
101
101
|
`Regenerate the description for recording ${args.recordingId}. ` +
|
|
102
102
|
`Read the transcript in this request's context and call ` +
|
|
103
103
|
`\`update-recording --id=${args.recordingId} --description="..."\` with a 2–4 ` +
|
|
104
|
-
`sentence summary of what the recording covers. Title: "${rec.title}"
|
|
104
|
+
`sentence summary of what the recording covers. Title: "${rec.title}". ` +
|
|
105
|
+
`Write the description the way the person who made this recording would ` +
|
|
106
|
+
`describe it themselves: lead with the subject matter, and never use ` +
|
|
107
|
+
`outside-narrator framing like "the speaker", "the presenter", "the video", ` +
|
|
108
|
+
`"this recording", or "this clip".`;
|
|
105
109
|
|
|
106
110
|
const request = {
|
|
107
111
|
kind: "regenerate-summary" as const,
|
|
@@ -437,6 +437,26 @@ function fullTextSegmentJson(
|
|
|
437
437
|
return JSON.stringify(buildCaptionSegmentsFromText(text, durationMs));
|
|
438
438
|
}
|
|
439
439
|
|
|
440
|
+
/**
|
|
441
|
+
* Pick the segments to store after cleanup rewrites the transcript text.
|
|
442
|
+
*
|
|
443
|
+
* Measured timings from the capture engine always win.
|
|
444
|
+
* `buildCaptionSegmentsFromText` spaces cues in proportion to word count, so
|
|
445
|
+
* re-synthesizing over real timestamps spreads a short transcript evenly across
|
|
446
|
+
* the whole recording — which reads as minute-long gaps of dropped speech even
|
|
447
|
+
* when nothing was dropped there.
|
|
448
|
+
*/
|
|
449
|
+
export function resolveCleanupSegmentsJson(
|
|
450
|
+
priorSegmentsJson: string | null | undefined,
|
|
451
|
+
cleanedText: string,
|
|
452
|
+
durationMs: number | null | undefined,
|
|
453
|
+
): string {
|
|
454
|
+
if (parseTranscriptSegments(priorSegmentsJson).length > 1) {
|
|
455
|
+
return priorSegmentsJson as string;
|
|
456
|
+
}
|
|
457
|
+
return fullTextSegmentJson(cleanedText, durationMs);
|
|
458
|
+
}
|
|
459
|
+
|
|
440
460
|
export function isSafeTranscriptCleanupReplacement(
|
|
441
461
|
sourceText: string,
|
|
442
462
|
cleanedText: string,
|
|
@@ -642,12 +662,14 @@ async function cleanupNativeTranscript({
|
|
|
642
662
|
ownerEmail,
|
|
643
663
|
fullText,
|
|
644
664
|
durationMs,
|
|
665
|
+
segmentsJson,
|
|
645
666
|
}: {
|
|
646
667
|
db: ReturnType<typeof getDb>;
|
|
647
668
|
recordingId: string;
|
|
648
669
|
ownerEmail: string;
|
|
649
670
|
fullText: string;
|
|
650
671
|
durationMs: number | null | undefined;
|
|
672
|
+
segmentsJson?: string | null;
|
|
651
673
|
}): Promise<{ cleaned: boolean; provider?: string }> {
|
|
652
674
|
const sourceText = fullText.trim();
|
|
653
675
|
if (!sourceText) return { cleaned: false };
|
|
@@ -704,7 +726,11 @@ async function cleanupNativeTranscript({
|
|
|
704
726
|
status: "ready",
|
|
705
727
|
failureReason: null,
|
|
706
728
|
language,
|
|
707
|
-
segmentsJson:
|
|
729
|
+
segmentsJson: resolveCleanupSegmentsJson(
|
|
730
|
+
segmentsJson,
|
|
731
|
+
cleanedText,
|
|
732
|
+
durationMs,
|
|
733
|
+
),
|
|
708
734
|
fullText: cleanedText,
|
|
709
735
|
retryCount: 0,
|
|
710
736
|
updatedAt: now,
|
|
@@ -855,6 +881,7 @@ async function completeReadyTranscript({
|
|
|
855
881
|
ownerEmail,
|
|
856
882
|
fullText,
|
|
857
883
|
durationMs: recForTitle?.durationMs,
|
|
884
|
+
segmentsJson,
|
|
858
885
|
}).catch((err) => {
|
|
859
886
|
console.warn(
|
|
860
887
|
`[clips] native transcript cleanup failed for ${recordingId}:`,
|
|
@@ -23,6 +23,7 @@ import {
|
|
|
23
23
|
} from "@/components/ui/dialog";
|
|
24
24
|
import { ScrollArea } from "@/components/ui/scroll-area";
|
|
25
25
|
import { exportConcat } from "@/lib/ffmpeg-export";
|
|
26
|
+
import { copyRecordingShareLink } from "@/lib/recording-link";
|
|
26
27
|
import { formatMs } from "@/lib/timestamp-mapping";
|
|
27
28
|
import { uploadFileClient } from "@/lib/upload-file-client";
|
|
28
29
|
import { cn } from "@/lib/utils";
|
|
@@ -142,7 +143,26 @@ export function StitchManager({
|
|
|
142
143
|
videoUrl,
|
|
143
144
|
durationMs: totalDuration,
|
|
144
145
|
});
|
|
145
|
-
|
|
146
|
+
const newRecordingId = (result as { id?: string } | null)?.id;
|
|
147
|
+
if (newRecordingId) {
|
|
148
|
+
const copied = await copyRecordingShareLink(newRecordingId);
|
|
149
|
+
if (copied) {
|
|
150
|
+
toast.success(t("stitchManager.created"), {
|
|
151
|
+
description: t("recordRoute.linkCopied"),
|
|
152
|
+
});
|
|
153
|
+
} else {
|
|
154
|
+
toast.success(t("stitchManager.created"), {
|
|
155
|
+
action: {
|
|
156
|
+
label: t("recordRoute.copyLinkAction"),
|
|
157
|
+
onClick: () => {
|
|
158
|
+
void copyRecordingShareLink(newRecordingId);
|
|
159
|
+
},
|
|
160
|
+
},
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
} else {
|
|
164
|
+
toast.success(t("stitchManager.created"));
|
|
165
|
+
}
|
|
146
166
|
onOpenChange(false);
|
|
147
167
|
return result;
|
|
148
168
|
} catch (err: any) {
|
|
@@ -78,6 +78,7 @@ export function QuickAskSidebar({
|
|
|
78
78
|
const [open, setOpen] = useState(false);
|
|
79
79
|
const [draft, setDraft] = useState("");
|
|
80
80
|
const [history, setHistory] = useState<ChatTurn[]>([]);
|
|
81
|
+
const [pendingAsk, setPendingAsk] = useState<string | null>(null);
|
|
81
82
|
const textareaRef = useRef<HTMLTextAreaElement>(null);
|
|
82
83
|
|
|
83
84
|
// Single global keydown listener; toggles on Cmd/Ctrl+J. Esc is handled
|
|
@@ -94,11 +95,17 @@ export function QuickAskSidebar({
|
|
|
94
95
|
return () => window.removeEventListener("keydown", onKeyDown);
|
|
95
96
|
}, []);
|
|
96
97
|
|
|
98
|
+
// The desktop pill's "Ask anything" bar hands its question over as `?ask=`
|
|
99
|
+
// alongside `?chat=1`, so the question the user typed on the overlay lands
|
|
100
|
+
// in the agent chat here instead of being retyped.
|
|
97
101
|
useEffect(() => {
|
|
98
102
|
const params = new URLSearchParams(window.location.search);
|
|
99
|
-
|
|
103
|
+
const askParam = params.get("ask")?.trim();
|
|
104
|
+
if (params.get("chat") !== "1" && !askParam) return;
|
|
100
105
|
setOpen(true);
|
|
106
|
+
if (askParam) setPendingAsk(askParam);
|
|
101
107
|
params.delete("chat");
|
|
108
|
+
params.delete("ask");
|
|
102
109
|
const nextQuery = params.toString();
|
|
103
110
|
window.history.replaceState(
|
|
104
111
|
window.history.state,
|
|
@@ -155,6 +162,12 @@ export function QuickAskSidebar({
|
|
|
155
162
|
[meetingId, meetingTitle, segments, t],
|
|
156
163
|
);
|
|
157
164
|
|
|
165
|
+
useEffect(() => {
|
|
166
|
+
if (!pendingAsk) return;
|
|
167
|
+
setPendingAsk(null);
|
|
168
|
+
send(pendingAsk);
|
|
169
|
+
}, [pendingAsk, send]);
|
|
170
|
+
|
|
158
171
|
return (
|
|
159
172
|
<Sheet open={open} onOpenChange={setOpen}>
|
|
160
173
|
<SheetContent
|
|
@@ -16,8 +16,11 @@ import {
|
|
|
16
16
|
CartesianGrid,
|
|
17
17
|
} from "recharts";
|
|
18
18
|
|
|
19
|
+
import {
|
|
20
|
+
ViewerAvatar,
|
|
21
|
+
viewerLabel,
|
|
22
|
+
} from "@/components/player/recording-views-badge";
|
|
19
23
|
import { ViewedByPopover } from "@/components/sharing/viewed-by-popover";
|
|
20
|
-
import { Avatar, AvatarFallback } from "@/components/ui/avatar";
|
|
21
24
|
|
|
22
25
|
export interface InsightsPanelProps {
|
|
23
26
|
recordingId: string;
|
|
@@ -152,20 +155,13 @@ export function InsightsPanel({ recordingId, durationMs }: InsightsPanelProps) {
|
|
|
152
155
|
{viewers.slice(0, 12).map((v, i) => (
|
|
153
156
|
<div
|
|
154
157
|
key={i}
|
|
155
|
-
className="flex items-center gap-2 rounded-full border border-border bg-card
|
|
158
|
+
className="flex items-center gap-2 rounded-full border border-border bg-card pe-3 ps-0.5 py-0.5"
|
|
156
159
|
title={v.viewerEmail ?? t("recordingInsights.anonymous")}
|
|
157
160
|
>
|
|
158
|
-
<
|
|
159
|
-
<AvatarFallback className="text-[10px] bg-primary text-primary-foreground">
|
|
160
|
-
{initials(v.viewerName || v.viewerEmail || "?")}
|
|
161
|
-
</AvatarFallback>
|
|
162
|
-
</Avatar>
|
|
161
|
+
<ViewerAvatar viewer={v} />
|
|
163
162
|
<span className="text-xs">
|
|
164
|
-
{v.
|
|
165
|
-
|
|
166
|
-
? v.viewerEmail.split("@")[0]
|
|
167
|
-
: t("recordingInsights.anon"))}
|
|
168
|
-
<span className="text-muted-foreground ml-1">
|
|
163
|
+
{viewerLabel(v, t("recordingInsights.anonymous"))}
|
|
164
|
+
<span className="text-muted-foreground ms-1">
|
|
169
165
|
{Math.round(v.completedPct)}%
|
|
170
166
|
</span>
|
|
171
167
|
</span>
|
|
@@ -207,14 +203,6 @@ function Stat({
|
|
|
207
203
|
);
|
|
208
204
|
}
|
|
209
205
|
|
|
210
|
-
function initials(s: string): string {
|
|
211
|
-
return s
|
|
212
|
-
.split(/\s+|@/)
|
|
213
|
-
.slice(0, 2)
|
|
214
|
-
.map((p) => p[0]?.toUpperCase() ?? "")
|
|
215
|
-
.join("");
|
|
216
|
-
}
|
|
217
|
-
|
|
218
206
|
function msCompact(ms: number): string {
|
|
219
207
|
const s = Math.floor(ms / 1000);
|
|
220
208
|
const m = Math.floor(s / 60);
|
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
import { useActionQuery } from "@agent-native/core/client/hooks";
|
|
2
|
+
import { useT } from "@agent-native/core/client/i18n";
|
|
3
|
+
import { IconTerminal2, IconUser } from "@tabler/icons-react";
|
|
4
|
+
import { useState } from "react";
|
|
5
|
+
|
|
6
|
+
import { Avatar, AvatarFallback } from "@/components/ui/avatar";
|
|
7
|
+
import { Button } from "@/components/ui/button";
|
|
8
|
+
import {
|
|
9
|
+
Popover,
|
|
10
|
+
PopoverContent,
|
|
11
|
+
PopoverTrigger,
|
|
12
|
+
} from "@/components/ui/popover";
|
|
13
|
+
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
|
14
|
+
import { cn } from "@/lib/utils";
|
|
15
|
+
|
|
16
|
+
interface ViewerRow {
|
|
17
|
+
id: string;
|
|
18
|
+
viewerEmail: string | null;
|
|
19
|
+
viewerName: string | null;
|
|
20
|
+
totalWatchMs: number;
|
|
21
|
+
completedPct: number;
|
|
22
|
+
countedView: boolean;
|
|
23
|
+
ctaClicked: boolean;
|
|
24
|
+
firstViewedAt: string | null;
|
|
25
|
+
lastViewedAt: string | null;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
interface AgentViewerRow {
|
|
29
|
+
agentLabel: string;
|
|
30
|
+
views: number;
|
|
31
|
+
lastSeenAt: string;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
interface Insights {
|
|
35
|
+
views: number;
|
|
36
|
+
agentViews: number;
|
|
37
|
+
agentViewers: AgentViewerRow[];
|
|
38
|
+
uniqueViewers: number;
|
|
39
|
+
completionRate: number;
|
|
40
|
+
ctaConversionRate: number;
|
|
41
|
+
dropOff: { bucket: number; watching: number }[];
|
|
42
|
+
topViewers: {
|
|
43
|
+
viewerEmail: string | null;
|
|
44
|
+
viewerName: string | null;
|
|
45
|
+
totalWatchMs: number;
|
|
46
|
+
completedPct: number;
|
|
47
|
+
}[];
|
|
48
|
+
durationMs: number;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export interface RecordingViewsBadgeProps {
|
|
52
|
+
recordingId: string;
|
|
53
|
+
/** Public counted-view total. Rendered as-is when details are unavailable. */
|
|
54
|
+
viewCount: number;
|
|
55
|
+
/** True only for owner/editor — gates avatars, the popover, and all viewer identities. */
|
|
56
|
+
canViewDetails: boolean;
|
|
57
|
+
/** Optional: called by the popover's "More insights" button. Omit to hide that button. */
|
|
58
|
+
onOpenInsights?: () => void;
|
|
59
|
+
className?: string;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Header-sized view counter. Viewer identities are owner/editor-only, so a
|
|
64
|
+
* visitor gets plain text and fires no viewer queries at all — `canViewDetails`
|
|
65
|
+
* is the client half of the server-side access check on `list-viewers`.
|
|
66
|
+
*/
|
|
67
|
+
export function RecordingViewsBadge({
|
|
68
|
+
recordingId,
|
|
69
|
+
viewCount,
|
|
70
|
+
canViewDetails,
|
|
71
|
+
onOpenInsights,
|
|
72
|
+
className,
|
|
73
|
+
}: RecordingViewsBadgeProps): React.ReactElement | null {
|
|
74
|
+
const t = useT();
|
|
75
|
+
const [open, setOpen] = useState(false);
|
|
76
|
+
|
|
77
|
+
const viewersQuery = useActionQuery<{ viewers: ViewerRow[] }>(
|
|
78
|
+
"list-viewers",
|
|
79
|
+
{ recordingId, limit: 12 },
|
|
80
|
+
{ enabled: canViewDetails },
|
|
81
|
+
);
|
|
82
|
+
const insightsQuery = useActionQuery<Insights>(
|
|
83
|
+
"get-recording-insights",
|
|
84
|
+
{ recordingId },
|
|
85
|
+
{ enabled: canViewDetails && open },
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
const countLabel = t("recordingInsights.viewsCount", { count: viewCount });
|
|
89
|
+
|
|
90
|
+
if (viewCount <= 0 && !canViewDetails) return null;
|
|
91
|
+
|
|
92
|
+
if (!canViewDetails) {
|
|
93
|
+
return (
|
|
94
|
+
<span
|
|
95
|
+
className={cn("text-sm text-muted-foreground tabular-nums", className)}
|
|
96
|
+
>
|
|
97
|
+
{countLabel}
|
|
98
|
+
</span>
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const viewers = viewersQuery.data?.viewers ?? [];
|
|
103
|
+
const insights = insightsQuery.data;
|
|
104
|
+
const agentViewers = insights?.agentViewers ?? [];
|
|
105
|
+
const summary = insights
|
|
106
|
+
? t("recordingInsights.totalViewsSummary", {
|
|
107
|
+
total: insights.views,
|
|
108
|
+
unique: insights.uniqueViewers,
|
|
109
|
+
})
|
|
110
|
+
: countLabel;
|
|
111
|
+
|
|
112
|
+
return (
|
|
113
|
+
<Popover open={open} onOpenChange={setOpen}>
|
|
114
|
+
<PopoverTrigger asChild onClick={(e) => e.stopPropagation()}>
|
|
115
|
+
<button
|
|
116
|
+
type="button"
|
|
117
|
+
className={cn(
|
|
118
|
+
"inline-flex cursor-pointer items-center gap-2 rounded-full border border-border bg-card px-2 py-1 text-sm text-muted-foreground hover:bg-accent hover:text-accent-foreground",
|
|
119
|
+
className,
|
|
120
|
+
)}
|
|
121
|
+
>
|
|
122
|
+
{viewers.length > 0 ? (
|
|
123
|
+
<span className="hidden -space-x-1.5 sm:flex">
|
|
124
|
+
{viewers.slice(0, 3).map((v) => (
|
|
125
|
+
<ViewerAvatar
|
|
126
|
+
key={v.id}
|
|
127
|
+
viewer={v}
|
|
128
|
+
className="h-6 w-6 ring-2 ring-card"
|
|
129
|
+
/>
|
|
130
|
+
))}
|
|
131
|
+
</span>
|
|
132
|
+
) : null}
|
|
133
|
+
<span className="tabular-nums">{countLabel}</span>
|
|
134
|
+
</button>
|
|
135
|
+
</PopoverTrigger>
|
|
136
|
+
<PopoverContent
|
|
137
|
+
align="end"
|
|
138
|
+
className="w-80 p-0"
|
|
139
|
+
onClick={(e) => e.stopPropagation()}
|
|
140
|
+
>
|
|
141
|
+
<Tabs defaultValue="views">
|
|
142
|
+
<div className="p-2 pb-0">
|
|
143
|
+
<TabsList className="grid h-8 w-full grid-cols-2">
|
|
144
|
+
<TabsTrigger value="views" className="text-xs">
|
|
145
|
+
{t("recordingInsights.viewsTab")}
|
|
146
|
+
</TabsTrigger>
|
|
147
|
+
<TabsTrigger value="insights" className="text-xs">
|
|
148
|
+
{t("recordingInsights.insightsTab")}
|
|
149
|
+
</TabsTrigger>
|
|
150
|
+
</TabsList>
|
|
151
|
+
</div>
|
|
152
|
+
|
|
153
|
+
<TabsContent value="views" className="mt-2">
|
|
154
|
+
<div className="border-y border-border px-3 py-2 text-xs text-muted-foreground">
|
|
155
|
+
{summary}
|
|
156
|
+
</div>
|
|
157
|
+
<div className="max-h-80 overflow-y-auto p-1.5">
|
|
158
|
+
<p className="px-2 pt-1 pb-1.5 text-xs font-medium text-muted-foreground">
|
|
159
|
+
{t("recordingInsights.humanViews")}
|
|
160
|
+
</p>
|
|
161
|
+
{viewersQuery.isLoading ? (
|
|
162
|
+
<p className="px-2 py-3 text-sm text-muted-foreground">
|
|
163
|
+
{t("recordingInsights.loading")}
|
|
164
|
+
</p>
|
|
165
|
+
) : viewers.length === 0 ? (
|
|
166
|
+
<p className="px-2 py-3 text-sm text-muted-foreground">
|
|
167
|
+
{t("recordingInsights.noViewsYet")}
|
|
168
|
+
</p>
|
|
169
|
+
) : (
|
|
170
|
+
<ul className="space-y-0.5">
|
|
171
|
+
{viewers.map((v) => (
|
|
172
|
+
<li
|
|
173
|
+
key={v.id}
|
|
174
|
+
className="flex items-center gap-2 rounded-md px-2 py-1.5"
|
|
175
|
+
>
|
|
176
|
+
<ViewerAvatar viewer={v} />
|
|
177
|
+
<span className="min-w-0 flex-1 truncate text-sm text-foreground">
|
|
178
|
+
{viewerLabel(v, t("recordingInsights.anonymous"))}
|
|
179
|
+
</span>
|
|
180
|
+
<span className="shrink-0 text-xs text-muted-foreground tabular-nums">
|
|
181
|
+
{Math.round(v.completedPct)}%
|
|
182
|
+
</span>
|
|
183
|
+
</li>
|
|
184
|
+
))}
|
|
185
|
+
</ul>
|
|
186
|
+
)}
|
|
187
|
+
|
|
188
|
+
<p className="mt-2 border-t border-border px-2 pt-2.5 pb-1.5 text-xs font-medium text-muted-foreground">
|
|
189
|
+
{t("recordingInsights.agentViews")}
|
|
190
|
+
</p>
|
|
191
|
+
{agentViewers.length === 0 ? (
|
|
192
|
+
<p className="px-2 py-1.5 text-sm text-muted-foreground">
|
|
193
|
+
{t("recordingInsights.noAgentViewsYet")}
|
|
194
|
+
</p>
|
|
195
|
+
) : (
|
|
196
|
+
<ul className="space-y-0.5">
|
|
197
|
+
{agentViewers.map((a) => (
|
|
198
|
+
<li
|
|
199
|
+
key={a.agentLabel}
|
|
200
|
+
className="flex items-center gap-2 rounded-md px-2 py-1.5"
|
|
201
|
+
>
|
|
202
|
+
<span className="flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-muted text-muted-foreground">
|
|
203
|
+
<IconTerminal2 className="h-3.5 w-3.5" />
|
|
204
|
+
</span>
|
|
205
|
+
<span className="min-w-0 flex-1 truncate text-sm text-foreground">
|
|
206
|
+
{a.agentLabel}
|
|
207
|
+
</span>
|
|
208
|
+
<span className="shrink-0 text-xs text-muted-foreground tabular-nums">
|
|
209
|
+
{t("recordingInsights.viewsCount", { count: a.views })}
|
|
210
|
+
</span>
|
|
211
|
+
</li>
|
|
212
|
+
))}
|
|
213
|
+
</ul>
|
|
214
|
+
)}
|
|
215
|
+
</div>
|
|
216
|
+
</TabsContent>
|
|
217
|
+
|
|
218
|
+
<TabsContent value="insights" className="mt-2 space-y-3 p-3 pt-1">
|
|
219
|
+
{insightsQuery.isLoading ? (
|
|
220
|
+
<p className="py-3 text-sm text-muted-foreground">
|
|
221
|
+
{t("recordingInsights.loading")}
|
|
222
|
+
</p>
|
|
223
|
+
) : (
|
|
224
|
+
<>
|
|
225
|
+
<div className="grid grid-cols-2 gap-2">
|
|
226
|
+
<StatCard
|
|
227
|
+
label={t("recordingInsights.humanViews")}
|
|
228
|
+
value={insights?.views ?? viewCount}
|
|
229
|
+
/>
|
|
230
|
+
<StatCard
|
|
231
|
+
label={t("recordingInsights.agentViews")}
|
|
232
|
+
value={insights?.agentViews ?? 0}
|
|
233
|
+
/>
|
|
234
|
+
</div>
|
|
235
|
+
<div className="grid grid-cols-3 gap-2 text-xs text-muted-foreground">
|
|
236
|
+
<MiniStat
|
|
237
|
+
label={t("recordingInsights.uniqueViewers")}
|
|
238
|
+
value={insights?.uniqueViewers ?? 0}
|
|
239
|
+
/>
|
|
240
|
+
<MiniStat
|
|
241
|
+
label={t("recordingInsights.completion")}
|
|
242
|
+
value={`${Math.round(insights?.completionRate ?? 0)}%`}
|
|
243
|
+
/>
|
|
244
|
+
<MiniStat
|
|
245
|
+
label={t("recordingInsights.ctaConversion")}
|
|
246
|
+
value={`${Math.round(insights?.ctaConversionRate ?? 0)}%`}
|
|
247
|
+
/>
|
|
248
|
+
</div>
|
|
249
|
+
</>
|
|
250
|
+
)}
|
|
251
|
+
{onOpenInsights ? (
|
|
252
|
+
<Button
|
|
253
|
+
type="button"
|
|
254
|
+
variant="outline"
|
|
255
|
+
size="sm"
|
|
256
|
+
className="w-full cursor-pointer"
|
|
257
|
+
onClick={() => {
|
|
258
|
+
setOpen(false);
|
|
259
|
+
onOpenInsights();
|
|
260
|
+
}}
|
|
261
|
+
>
|
|
262
|
+
{t("recordingInsights.moreInsights")}
|
|
263
|
+
</Button>
|
|
264
|
+
) : null}
|
|
265
|
+
</TabsContent>
|
|
266
|
+
</Tabs>
|
|
267
|
+
</PopoverContent>
|
|
268
|
+
</Popover>
|
|
269
|
+
);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/** Identity fields every viewer surface shares — `list-viewers` rows and the
|
|
273
|
+
* leaner `topViewers` rows from `get-recording-insights` alike. */
|
|
274
|
+
export interface ViewerIdentity {
|
|
275
|
+
viewerEmail: string | null;
|
|
276
|
+
viewerName: string | null;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
export function ViewerAvatar({
|
|
280
|
+
viewer,
|
|
281
|
+
className,
|
|
282
|
+
}: {
|
|
283
|
+
viewer: ViewerIdentity;
|
|
284
|
+
className?: string;
|
|
285
|
+
}) {
|
|
286
|
+
const anonymous = !viewer.viewerName && !viewer.viewerEmail;
|
|
287
|
+
return (
|
|
288
|
+
<Avatar className={cn("h-6 w-6 shrink-0", className)}>
|
|
289
|
+
<AvatarFallback className="bg-primary text-[10px] text-primary-foreground">
|
|
290
|
+
{anonymous ? (
|
|
291
|
+
<IconUser className="h-3 w-3" />
|
|
292
|
+
) : (
|
|
293
|
+
initials(viewer.viewerName || viewer.viewerEmail || "?")
|
|
294
|
+
)}
|
|
295
|
+
</AvatarFallback>
|
|
296
|
+
</Avatar>
|
|
297
|
+
);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
function MiniStat({ label, value }: { label: string; value: string | number }) {
|
|
301
|
+
return (
|
|
302
|
+
<div className="min-w-0">
|
|
303
|
+
<div className="truncate">{label}</div>
|
|
304
|
+
<div className="mt-0.5 text-foreground tabular-nums">{value}</div>
|
|
305
|
+
</div>
|
|
306
|
+
);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
function StatCard({ label, value }: { label: string; value: string | number }) {
|
|
310
|
+
return (
|
|
311
|
+
<div className="rounded-lg border border-border bg-card p-2.5">
|
|
312
|
+
<div className="text-xs text-muted-foreground">{label}</div>
|
|
313
|
+
<div className="mt-0.5 text-xl font-semibold text-foreground tabular-nums">
|
|
314
|
+
{value}
|
|
315
|
+
</div>
|
|
316
|
+
</div>
|
|
317
|
+
);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
export function viewerLabel(
|
|
321
|
+
viewer: ViewerIdentity,
|
|
322
|
+
anonymousLabel: string,
|
|
323
|
+
): string {
|
|
324
|
+
if (viewer.viewerName) return viewer.viewerName;
|
|
325
|
+
if (viewer.viewerEmail) return viewer.viewerEmail.split("@")[0];
|
|
326
|
+
return anonymousLabel;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
function initials(s: string): string {
|
|
330
|
+
return s
|
|
331
|
+
.split(/\s+|@/)
|
|
332
|
+
.slice(0, 2)
|
|
333
|
+
.map((p) => p[0]?.toUpperCase() ?? "")
|
|
334
|
+
.join("");
|
|
335
|
+
}
|
|
@@ -1400,7 +1400,10 @@ export const VideoPlayer = forwardRef<VideoPlayerHandle, VideoPlayerProps>(
|
|
|
1400
1400
|
v,
|
|
1401
1401
|
resolvedDurationMs,
|
|
1402
1402
|
);
|
|
1403
|
-
|
|
1403
|
+
// Only ever correct forward (skipping a trimmed range). Seeking
|
|
1404
|
+
// backwards here flushes the decode pipeline and replays from the
|
|
1405
|
+
// previous keyframe, which reads as a stutter with a buffering flash.
|
|
1406
|
+
if (visibleMs > ms) {
|
|
1404
1407
|
v.currentTime = visibleMs / 1000;
|
|
1405
1408
|
setCurrentMs(visibleMs);
|
|
1406
1409
|
if (visibleMs > 0) {
|
|
@@ -1815,21 +1818,23 @@ function CenterPlaybackOverlay({
|
|
|
1815
1818
|
* trustworthy finite number we have — preferring the resolved duration from
|
|
1816
1819
|
* the player, then falling back to `video.duration`, then the seekable range.
|
|
1817
1820
|
*/
|
|
1818
|
-
function clampSeek(
|
|
1821
|
+
export function clampSeek(
|
|
1819
1822
|
ms: number,
|
|
1820
1823
|
v: HTMLVideoElement,
|
|
1821
1824
|
resolvedDurationMs: number,
|
|
1822
1825
|
): number {
|
|
1823
|
-
|
|
1826
|
+
// Clamp in integer milliseconds. Routing through seconds and back loses 1ms
|
|
1827
|
+
// for ~1% of integer inputs (1001 -> 1000), which the timeupdate handler
|
|
1828
|
+
// would then "correct" by seeking the player backwards.
|
|
1829
|
+
let maxMs = Number.POSITIVE_INFINITY;
|
|
1824
1830
|
if (resolvedDurationMs > 0) {
|
|
1825
|
-
|
|
1831
|
+
maxMs = resolvedDurationMs;
|
|
1826
1832
|
} else if (Number.isFinite(v.duration) && v.duration > 0) {
|
|
1827
|
-
|
|
1833
|
+
maxMs = v.duration * 1000;
|
|
1828
1834
|
} else if (v.seekable && v.seekable.length > 0) {
|
|
1829
|
-
|
|
1835
|
+
maxMs = v.seekable.end(v.seekable.length - 1) * 1000;
|
|
1830
1836
|
}
|
|
1831
|
-
|
|
1832
|
-
return Math.floor(sec * 1000);
|
|
1837
|
+
return Math.floor(Math.max(0, Math.min(maxMs, ms)));
|
|
1833
1838
|
}
|
|
1834
1839
|
|
|
1835
1840
|
function skipExcludedRange(
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { writeClipboardText } from "@agent-native/core/client/clipboard";
|
|
1
2
|
import {
|
|
2
3
|
useActionMutation,
|
|
3
4
|
useActionQuery,
|
|
@@ -70,7 +71,7 @@ export const ROLE_OPTIONS: Array<{ value: Role; label: string }> = [
|
|
|
70
71
|
];
|
|
71
72
|
|
|
72
73
|
export function copyToClipboard(value: string): void {
|
|
73
|
-
|
|
74
|
+
void writeClipboardText(value);
|
|
74
75
|
}
|
|
75
76
|
|
|
76
77
|
// ---------------------------------------------------------------------------
|
|
@@ -288,7 +288,6 @@ const messages = {
|
|
|
288
288
|
storageConnectedChecking: "Storage connected. Checking this clip...",
|
|
289
289
|
signInToFinish: "Sign in to finish",
|
|
290
290
|
signInIfYours: "Sign in if this is yours",
|
|
291
|
-
openDashboard: "Open dashboard",
|
|
292
291
|
checkAgain: "Check again",
|
|
293
292
|
backToHome: "Back to home",
|
|
294
293
|
generatingTitle: "Generating title",
|
|
@@ -807,11 +806,21 @@ All notable user-facing changes to Clips are documented here. Open it any time f
|
|
|
807
806
|
recentViewers: "Recent viewers",
|
|
808
807
|
noViewers: "No viewers yet.",
|
|
809
808
|
anonymous: "Anonymous",
|
|
810
|
-
anon: "Anon",
|
|
811
809
|
moreViewers: "+{{count}} more",
|
|
812
810
|
viewedBy: "Viewed by",
|
|
813
811
|
someone: "Someone",
|
|
814
812
|
noViewsYet: "No views yet.",
|
|
813
|
+
viewsCount_one: "{{count}} view",
|
|
814
|
+
viewsCount_other: "{{count}} views",
|
|
815
|
+
totalViewsSummary: "{{total}} total views, {{unique}} unique viewers",
|
|
816
|
+
viewsTab: "Views",
|
|
817
|
+
insightsTab: "Insights",
|
|
818
|
+
humanViews: "Human views",
|
|
819
|
+
agentViews: "Agent views",
|
|
820
|
+
noAgentViewsYet: "No agent views yet.",
|
|
821
|
+
totalVideoViews: "Total video views",
|
|
822
|
+
averageCompletionRate: "Average completion rate",
|
|
823
|
+
moreInsights: "More insights",
|
|
815
824
|
},
|
|
816
825
|
libraryGrid: {
|
|
817
826
|
spaceRoot: "Space root",
|
|
@@ -1291,6 +1300,8 @@ All notable user-facing changes to Clips are documented here. Open it any time f
|
|
|
1291
1300
|
couldNotImportLoom: "Could not import that Loom.",
|
|
1292
1301
|
recordingReadyToUpload: "Recording is ready to upload",
|
|
1293
1302
|
recordingSaved: "Recording saved",
|
|
1303
|
+
linkCopied: "Link copied",
|
|
1304
|
+
copyLinkAction: "Copy link",
|
|
1294
1305
|
noLocalRecordingData: "No local recording data is available to download.",
|
|
1295
1306
|
recordingDownloadStarted: "Recording download started",
|
|
1296
1307
|
backToLibrary: "Back to library",
|