@agent-native/core 0.98.16 → 0.99.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 +21 -0
- package/corpus/core/docs/content/actions.mdx +1 -1
- package/corpus/core/docs/content/authentication.mdx +1 -1
- package/corpus/core/docs/content/dispatch.mdx +3 -3
- package/corpus/core/docs/content/external-agents.mdx +30 -19
- package/corpus/core/docs/content/locales/ar-SA/actions.mdx +1 -1
- package/corpus/core/docs/content/locales/ar-SA/authentication.mdx +1 -1
- package/corpus/core/docs/content/locales/ar-SA/dispatch.mdx +3 -3
- package/corpus/core/docs/content/locales/ar-SA/external-agents.mdx +23 -19
- package/corpus/core/docs/content/locales/ar-SA/mcp-clients.mdx +31 -3
- package/corpus/core/docs/content/locales/ar-SA/mcp-protocol.mdx +29 -15
- package/corpus/core/docs/content/locales/ar-SA/plan-plugin.mdx +3 -3
- package/corpus/core/docs/content/locales/ar-SA/server.mdx +2 -2
- package/corpus/core/docs/content/locales/ar-SA/skills-guide.mdx +1 -1
- package/corpus/core/docs/content/locales/ar-SA/template-assets.mdx +1 -1
- package/corpus/core/docs/content/locales/ar-SA/template-dispatch.mdx +2 -2
- package/corpus/core/docs/content/locales/ar-SA/template-plan.mdx +3 -3
- package/corpus/core/docs/content/locales/de-DE/actions.mdx +1 -1
- package/corpus/core/docs/content/locales/de-DE/authentication.mdx +1 -1
- package/corpus/core/docs/content/locales/de-DE/dispatch.mdx +3 -3
- package/corpus/core/docs/content/locales/de-DE/external-agents.mdx +23 -19
- package/corpus/core/docs/content/locales/de-DE/mcp-clients.mdx +37 -3
- package/corpus/core/docs/content/locales/de-DE/mcp-protocol.mdx +29 -15
- package/corpus/core/docs/content/locales/de-DE/plan-plugin.mdx +3 -3
- package/corpus/core/docs/content/locales/de-DE/server.mdx +2 -2
- package/corpus/core/docs/content/locales/de-DE/skills-guide.mdx +1 -1
- package/corpus/core/docs/content/locales/de-DE/template-assets.mdx +1 -1
- package/corpus/core/docs/content/locales/de-DE/template-dispatch.mdx +2 -2
- package/corpus/core/docs/content/locales/de-DE/template-plan.mdx +3 -3
- package/corpus/core/docs/content/locales/es-ES/actions.mdx +1 -1
- package/corpus/core/docs/content/locales/es-ES/authentication.mdx +1 -1
- package/corpus/core/docs/content/locales/es-ES/dispatch.mdx +3 -3
- package/corpus/core/docs/content/locales/es-ES/external-agents.mdx +32 -19
- package/corpus/core/docs/content/locales/es-ES/mcp-clients.mdx +17 -3
- package/corpus/core/docs/content/locales/es-ES/mcp-protocol.mdx +38 -15
- package/corpus/core/docs/content/locales/es-ES/plan-plugin.mdx +3 -3
- package/corpus/core/docs/content/locales/es-ES/server.mdx +2 -2
- package/corpus/core/docs/content/locales/es-ES/skills-guide.mdx +1 -1
- package/corpus/core/docs/content/locales/es-ES/template-assets.mdx +1 -1
- package/corpus/core/docs/content/locales/es-ES/template-dispatch.mdx +2 -2
- package/corpus/core/docs/content/locales/es-ES/template-plan.mdx +3 -3
- package/corpus/core/docs/content/locales/fr-FR/actions.mdx +1 -1
- package/corpus/core/docs/content/locales/fr-FR/authentication.mdx +1 -1
- package/corpus/core/docs/content/locales/fr-FR/dispatch.mdx +3 -3
- package/corpus/core/docs/content/locales/fr-FR/external-agents.mdx +23 -19
- package/corpus/core/docs/content/locales/fr-FR/mcp-clients.mdx +17 -3
- package/corpus/core/docs/content/locales/fr-FR/mcp-protocol.mdx +29 -15
- package/corpus/core/docs/content/locales/fr-FR/plan-plugin.mdx +3 -3
- package/corpus/core/docs/content/locales/fr-FR/server.mdx +2 -2
- package/corpus/core/docs/content/locales/fr-FR/skills-guide.mdx +1 -1
- package/corpus/core/docs/content/locales/fr-FR/template-assets.mdx +1 -1
- package/corpus/core/docs/content/locales/fr-FR/template-dispatch.mdx +2 -2
- package/corpus/core/docs/content/locales/fr-FR/template-plan.mdx +3 -3
- package/corpus/core/docs/content/locales/hi-IN/actions.mdx +1 -1
- package/corpus/core/docs/content/locales/hi-IN/authentication.mdx +1 -1
- package/corpus/core/docs/content/locales/hi-IN/dispatch.mdx +3 -3
- package/corpus/core/docs/content/locales/hi-IN/external-agents.mdx +31 -19
- package/corpus/core/docs/content/locales/hi-IN/mcp-clients.mdx +17 -3
- package/corpus/core/docs/content/locales/hi-IN/mcp-protocol.mdx +36 -15
- package/corpus/core/docs/content/locales/hi-IN/plan-plugin.mdx +3 -3
- package/corpus/core/docs/content/locales/hi-IN/server.mdx +2 -2
- package/corpus/core/docs/content/locales/hi-IN/skills-guide.mdx +1 -1
- package/corpus/core/docs/content/locales/hi-IN/template-assets.mdx +1 -1
- package/corpus/core/docs/content/locales/hi-IN/template-dispatch.mdx +2 -2
- package/corpus/core/docs/content/locales/hi-IN/template-plan.mdx +3 -3
- package/corpus/core/docs/content/locales/ja-JP/actions.mdx +1 -1
- package/corpus/core/docs/content/locales/ja-JP/authentication.mdx +1 -1
- package/corpus/core/docs/content/locales/ja-JP/dispatch.mdx +3 -3
- package/corpus/core/docs/content/locales/ja-JP/external-agents.mdx +23 -19
- package/corpus/core/docs/content/locales/ja-JP/mcp-clients.mdx +34 -3
- package/corpus/core/docs/content/locales/ja-JP/mcp-protocol.mdx +29 -15
- package/corpus/core/docs/content/locales/ja-JP/plan-plugin.mdx +3 -3
- package/corpus/core/docs/content/locales/ja-JP/server.mdx +2 -2
- package/corpus/core/docs/content/locales/ja-JP/skills-guide.mdx +1 -1
- package/corpus/core/docs/content/locales/ja-JP/template-assets.mdx +1 -1
- package/corpus/core/docs/content/locales/ja-JP/template-dispatch.mdx +2 -2
- package/corpus/core/docs/content/locales/ja-JP/template-plan.mdx +3 -3
- package/corpus/core/docs/content/locales/ko-KR/actions.mdx +1 -1
- package/corpus/core/docs/content/locales/ko-KR/authentication.mdx +1 -1
- package/corpus/core/docs/content/locales/ko-KR/dispatch.mdx +3 -3
- package/corpus/core/docs/content/locales/ko-KR/external-agents.mdx +30 -19
- package/corpus/core/docs/content/locales/ko-KR/mcp-clients.mdx +33 -3
- package/corpus/core/docs/content/locales/ko-KR/mcp-protocol.mdx +36 -15
- package/corpus/core/docs/content/locales/ko-KR/plan-plugin.mdx +3 -3
- package/corpus/core/docs/content/locales/ko-KR/server.mdx +2 -2
- package/corpus/core/docs/content/locales/ko-KR/skills-guide.mdx +1 -1
- package/corpus/core/docs/content/locales/ko-KR/template-assets.mdx +1 -1
- package/corpus/core/docs/content/locales/ko-KR/template-dispatch.mdx +2 -2
- package/corpus/core/docs/content/locales/ko-KR/template-plan.mdx +3 -3
- package/corpus/core/docs/content/locales/pt-BR/actions.mdx +1 -1
- package/corpus/core/docs/content/locales/pt-BR/authentication.mdx +1 -1
- package/corpus/core/docs/content/locales/pt-BR/dispatch.mdx +3 -3
- package/corpus/core/docs/content/locales/pt-BR/external-agents.mdx +32 -19
- package/corpus/core/docs/content/locales/pt-BR/mcp-clients.mdx +34 -3
- package/corpus/core/docs/content/locales/pt-BR/mcp-protocol.mdx +32 -15
- package/corpus/core/docs/content/locales/pt-BR/plan-plugin.mdx +3 -3
- package/corpus/core/docs/content/locales/pt-BR/server.mdx +2 -2
- package/corpus/core/docs/content/locales/pt-BR/skills-guide.mdx +1 -1
- package/corpus/core/docs/content/locales/pt-BR/template-assets.mdx +1 -1
- package/corpus/core/docs/content/locales/pt-BR/template-dispatch.mdx +2 -2
- package/corpus/core/docs/content/locales/pt-BR/template-plan.mdx +3 -3
- package/corpus/core/docs/content/locales/zh-CN/actions.mdx +1 -1
- package/corpus/core/docs/content/locales/zh-CN/authentication.mdx +1 -1
- package/corpus/core/docs/content/locales/zh-CN/dispatch.mdx +3 -3
- package/corpus/core/docs/content/locales/zh-CN/external-agents.mdx +23 -19
- package/corpus/core/docs/content/locales/zh-CN/mcp-clients.mdx +28 -3
- package/corpus/core/docs/content/locales/zh-CN/mcp-protocol.mdx +29 -15
- package/corpus/core/docs/content/locales/zh-CN/plan-plugin.mdx +3 -3
- package/corpus/core/docs/content/locales/zh-CN/server.mdx +2 -2
- package/corpus/core/docs/content/locales/zh-CN/skills-guide.mdx +1 -1
- package/corpus/core/docs/content/locales/zh-CN/template-assets.mdx +1 -1
- package/corpus/core/docs/content/locales/zh-CN/template-dispatch.mdx +2 -2
- package/corpus/core/docs/content/locales/zh-CN/template-plan.mdx +3 -3
- package/corpus/core/docs/content/locales/zh-TW/actions.mdx +1 -1
- package/corpus/core/docs/content/locales/zh-TW/authentication.mdx +1 -1
- package/corpus/core/docs/content/locales/zh-TW/dispatch.mdx +3 -3
- package/corpus/core/docs/content/locales/zh-TW/external-agents.mdx +23 -19
- package/corpus/core/docs/content/locales/zh-TW/mcp-clients.mdx +28 -3
- package/corpus/core/docs/content/locales/zh-TW/mcp-protocol.mdx +30 -15
- package/corpus/core/docs/content/locales/zh-TW/plan-plugin.mdx +3 -3
- package/corpus/core/docs/content/locales/zh-TW/server.mdx +2 -2
- package/corpus/core/docs/content/locales/zh-TW/skills-guide.mdx +1 -1
- package/corpus/core/docs/content/locales/zh-TW/template-assets.mdx +1 -1
- package/corpus/core/docs/content/locales/zh-TW/template-dispatch.mdx +2 -2
- package/corpus/core/docs/content/locales/zh-TW/template-plan.mdx +3 -3
- package/corpus/core/docs/content/mcp-clients.mdx +31 -4
- package/corpus/core/docs/content/mcp-protocol.mdx +35 -15
- package/corpus/core/docs/content/plan-plugin.mdx +3 -3
- package/corpus/core/docs/content/server.mdx +2 -2
- package/corpus/core/docs/content/skills-guide.mdx +1 -1
- package/corpus/core/docs/content/template-assets.mdx +1 -1
- package/corpus/core/docs/content/template-dispatch.mdx +2 -2
- package/corpus/core/docs/content/template-plan.mdx +3 -3
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/a2a/client.ts +3 -0
- package/corpus/core/src/a2a/handlers.ts +95 -7
- package/corpus/core/src/cli/connect.ts +50 -24
- package/corpus/core/src/cli/mcp-config-writers.ts +10 -0
- package/corpus/core/src/cli/mcp.ts +5 -5
- package/corpus/core/src/cli/skills-content/assets-skill.ts +1 -1
- package/corpus/core/src/cli/skills-content/design-exploration-skill.ts +1 -1
- package/corpus/core/src/cli/skills-content/help.ts +1 -1
- package/corpus/core/src/cli/skills-content/plan-setup-auth.ts +1 -1
- package/corpus/core/src/cli/skills-content/visual-plan-skill.ts +1 -1
- package/corpus/core/src/cli/skills-content/visual-recap-skill.ts +2 -2
- package/corpus/core/src/cli/skills.ts +23 -12
- package/corpus/core/src/client/resources/McpIntegrationDialog.tsx +5 -0
- package/corpus/core/src/client/resources/mcp-integration-catalog.ts +17 -0
- package/corpus/core/src/embedding/agent.ts +8 -6
- package/corpus/core/src/localization/default-messages.ts +7 -0
- package/corpus/core/src/mcp/ask-app-inline-tasks.ts +125 -0
- package/corpus/core/src/mcp/build-server.ts +65 -3
- package/corpus/core/src/mcp/builtin-tools.ts +186 -22
- package/corpus/core/src/mcp/connect-route.ts +17 -14
- package/corpus/core/src/mcp/oauth-route.ts +38 -13
- package/corpus/core/src/mcp/route-paths.ts +34 -0
- package/corpus/core/src/mcp/server.ts +21 -10
- package/corpus/core/src/mcp/stdio.ts +34 -16
- package/corpus/core/src/mcp/workspace-resolve.ts +2 -1
- package/corpus/core/src/mcp-client/manager.ts +5 -3
- package/corpus/core/src/mcp-client/remote-store.ts +10 -10
- package/corpus/core/src/server/agent-chat-plugin.ts +59 -8
- package/corpus/core/src/server/auth.ts +22 -6
- package/corpus/core/src/server/core-routes-plugin.ts +30 -24
- package/corpus/core/src/server/csrf.ts +17 -0
- package/corpus/core/src/server/framework-request-handler.ts +8 -2
- package/corpus/core/src/server/google-oauth.ts +6 -0
- package/corpus/core/src/server/http-response-telemetry.ts +6 -1
- package/corpus/core/src/server/recap-image-route.ts +3 -3
- package/corpus/core/src/server/security-headers.ts +7 -1
- package/corpus/core/src/server/ssr-handler.ts +2 -0
- package/corpus/core/src/shared/cache-control.ts +6 -4
- package/corpus/core/src/templates/default/.agents/skills/security/SKILL.md +10 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/authentication/SKILL.md +15 -6
- package/corpus/core/src/templates/workspace-core/.agents/skills/external-agents/SKILL.md +16 -10
- package/corpus/core/src/templates/workspace-core/.agents/skills/performance/SKILL.md +20 -1
- package/corpus/core/src/templates/workspace-core/.agents/skills/security/SKILL.md +10 -0
- package/corpus/templates/analytics/.agents/skills/security/SKILL.md +10 -0
- package/corpus/templates/analytics/app/global.css +63 -4
- package/corpus/templates/analytics/app/pages/sessions/SessionDetailPage.tsx +8 -5
- package/corpus/templates/analytics/changelog/2026-07-13-daily-dashboard-emails-recover-more-reliably-from-serverless.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-13-session-replays-keep-a-visible-mac-style-cursor-over-the-vis.md +6 -0
- package/corpus/templates/analytics/server/jobs/dashboard-report.ts +21 -2
- package/corpus/templates/analytics/server/lib/dashboard-report-subscriptions.ts +57 -1
- package/corpus/templates/analytics/server/lib/dashboard-report.ts +266 -28
- package/corpus/templates/analytics/server/routes/[...page].get.ts +0 -2
- package/corpus/templates/assets/.agents/skills/security/SKILL.md +10 -0
- package/corpus/templates/assets/agent-native.app-skill.json +1 -1
- package/corpus/templates/brain/.agents/skills/security/SKILL.md +10 -0
- package/corpus/templates/calendar/.agents/skills/security/SKILL.md +10 -0
- package/corpus/templates/calendar/AGENTS.md +2 -1
- package/corpus/templates/calendar/app/components/calendar/EventDetailPopover.tsx +0 -19
- package/corpus/templates/calendar/app/lib/attendee-local-time.ts +14 -5
- package/corpus/templates/calendar/changelog/2026-07-13-your-local-time-now-follows-your-browser-timezone-and-event-.md +6 -0
- package/corpus/templates/chat/.agents/skills/security/SKILL.md +10 -0
- package/corpus/templates/clips/.agents/skills/recording/SKILL.md +7 -2
- package/corpus/templates/clips/.agents/skills/security/SKILL.md +10 -0
- package/corpus/templates/clips/AGENTS.md +7 -0
- package/corpus/templates/clips/actions/list-meetings.ts +19 -4
- package/corpus/templates/clips/actions/start-meeting-recording.ts +7 -1
- package/corpus/templates/clips/app/components/meetings/transcript-bubbles.tsx +75 -78
- package/corpus/templates/clips/app/components/recorder/confetti-canvas.tsx +18 -1
- package/corpus/templates/clips/app/components/recorder/recorder-engine.ts +6 -12
- package/corpus/templates/clips/app/components/recorder/recording-toolbar.tsx +19 -2
- package/corpus/templates/clips/app/lib/camera-composite.ts +70 -10
- package/corpus/templates/clips/app/routes/_app.meetings.$meetingId.tsx +1 -1
- package/corpus/templates/clips/app/routes/record.tsx +5 -25
- package/corpus/templates/clips/changelog/2026-07-13-clips-desktop-now-requires-macos-13-for-native-capture.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-13-clips-hide-solo-meeting-reminders.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-13-clips-now-removes-duplicate-mic-and-system-transcript-turns-.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-13-desktop-recordings-run-cooler-and-quieter-live-transcription.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-13-meeting-recordings-now-stop-after-a-calendar-meeting-ends-an.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-13-meeting-transcripts-now-use-a-clean-agent-chat-style-reading.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-13-screen-recordings-use-less-processing-power-during-longer-ca.md +6 -0
- package/corpus/templates/clips/chrome-extension/src/background.ts +5 -3
- package/corpus/templates/clips/chrome-extension/src/offscreen.ts +17 -14
- package/corpus/templates/clips/chrome-extension/src/overlay.ts +8 -2
- package/corpus/templates/clips/desktop/README.md +3 -0
- package/corpus/templates/clips/desktop/src/hooks/useMeetingTranscription.ts +9 -0
- package/corpus/templates/clips/desktop/src/lib/recorder.ts +8 -2
- package/corpus/templates/clips/desktop/src/lib/silence-events.ts +1 -0
- package/corpus/templates/clips/desktop/src/lib/transcription-capture.ts +5 -0
- package/corpus/templates/clips/desktop/src/lib/transcription-engine.ts +134 -5
- package/corpus/templates/clips/desktop/src/lib/upload-video-stream.ts +28 -0
- package/corpus/templates/clips/desktop/src/overlays/flow-bar.tsx +10 -3
- package/corpus/templates/clips/desktop/src/overlays/meeting-notification.tsx +42 -9
- package/corpus/templates/clips/desktop/src/overlays/recording-pill.tsx +10 -2
- package/corpus/templates/clips/desktop/src-tauri/Cargo.toml +6 -1
- package/corpus/templates/clips/desktop/src-tauri/src/notifications.rs +77 -1
- package/corpus/templates/clips/desktop/src-tauri/src/silence_detector.rs +104 -25
- package/corpus/templates/clips/desktop/src-tauri/src/system_audio.rs +4 -0
- package/corpus/templates/clips/desktop/src-tauri/src/whisper_speech.rs +287 -32
- package/corpus/templates/clips/desktop/src-tauri/tauri.conf.json +1 -1
- package/corpus/templates/clips/server/lib/calendar-event-classification.ts +28 -0
- package/corpus/templates/clips/server/routes/[...page].get.ts +1 -59
- package/corpus/templates/clips/shared/recording-capture.ts +37 -0
- package/corpus/templates/content/.agents/skills/security/SKILL.md +10 -0
- package/corpus/templates/content/agent-native.app-skill.json +1 -1
- package/corpus/templates/content/server/routes/[...page].get.ts +1 -15
- package/corpus/templates/design/.agents/skills/security/SKILL.md +10 -0
- package/corpus/templates/design/actions/connect-assets-mcp.ts +1 -1
- package/corpus/templates/design/agent-native.app-skill.json +1 -1
- package/corpus/templates/design/app/components/design/DesignCanvas.tsx +88 -12
- package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +1 -0
- package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +4 -1
- package/corpus/templates/design/changelog/2026-07-13-adding-shapes-preserves-canvas-background.md +6 -0
- package/corpus/templates/design/changelog/2026-07-13-clicking-quickly-between-overlapping-elements-no-longer-bounc.md +6 -0
- package/corpus/templates/design/server/plugins/assets-mcp.ts +1 -1
- package/corpus/templates/design/server/routes/[...page].get.ts +0 -2
- package/corpus/templates/dispatch/.agents/skills/security/SKILL.md +10 -0
- package/corpus/templates/forms/.agents/skills/security/SKILL.md +10 -0
- package/corpus/templates/macros/.agents/skills/security/SKILL.md +10 -0
- package/corpus/templates/mail/.agents/skills/security/SKILL.md +10 -0
- package/corpus/templates/plan/.agents/skills/security/SKILL.md +10 -0
- package/corpus/templates/plan/.agents/skills/visual-plan/SKILL.md +1 -1
- package/corpus/templates/plan/.agents/skills/visual-recap/SKILL.md +2 -2
- package/corpus/templates/plan/agent-native.app-skill.json +1 -1
- package/corpus/templates/plan/app/lib/plan-local-bridge.ts +6 -1
- package/corpus/templates/plan/app/pages/PlansPage.tsx +15 -6
- package/corpus/templates/plan/changelog/2026-07-13-fixed-local-plan-previews-continuously-flickering-while-revi.md +6 -0
- package/corpus/templates/plan/server/routes/[...page].get.ts +0 -2
- package/corpus/templates/slides/.agents/skills/security/SKILL.md +10 -0
- package/dist/a2a/client.d.ts +2 -0
- package/dist/a2a/client.d.ts.map +1 -1
- package/dist/a2a/client.js +2 -0
- package/dist/a2a/client.js.map +1 -1
- package/dist/a2a/handlers.d.ts.map +1 -1
- package/dist/a2a/handlers.js +84 -7
- package/dist/a2a/handlers.js.map +1 -1
- package/dist/cli/connect.d.ts +2 -2
- package/dist/cli/connect.d.ts.map +1 -1
- package/dist/cli/connect.js +45 -23
- package/dist/cli/connect.js.map +1 -1
- package/dist/cli/mcp-config-writers.d.ts.map +1 -1
- package/dist/cli/mcp-config-writers.js +7 -0
- package/dist/cli/mcp-config-writers.js.map +1 -1
- package/dist/cli/mcp.js +5 -3
- package/dist/cli/mcp.js.map +1 -1
- package/dist/cli/skills-content/assets-skill.d.ts +1 -1
- package/dist/cli/skills-content/assets-skill.d.ts.map +1 -1
- package/dist/cli/skills-content/assets-skill.js +1 -1
- package/dist/cli/skills-content/assets-skill.js.map +1 -1
- package/dist/cli/skills-content/design-exploration-skill.d.ts +1 -1
- package/dist/cli/skills-content/design-exploration-skill.d.ts.map +1 -1
- package/dist/cli/skills-content/design-exploration-skill.js +1 -1
- package/dist/cli/skills-content/design-exploration-skill.js.map +1 -1
- package/dist/cli/skills-content/help.d.ts +1 -1
- package/dist/cli/skills-content/help.d.ts.map +1 -1
- package/dist/cli/skills-content/help.js +1 -1
- package/dist/cli/skills-content/help.js.map +1 -1
- package/dist/cli/skills-content/plan-setup-auth.d.ts +1 -1
- package/dist/cli/skills-content/plan-setup-auth.d.ts.map +1 -1
- package/dist/cli/skills-content/plan-setup-auth.js +1 -1
- package/dist/cli/skills-content/plan-setup-auth.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 +1 -1
- package/dist/cli/skills-content/visual-plan-skill.js.map +1 -1
- package/dist/cli/skills-content/visual-recap-skill.d.ts +1 -1
- package/dist/cli/skills-content/visual-recap-skill.d.ts.map +1 -1
- package/dist/cli/skills-content/visual-recap-skill.js +2 -2
- package/dist/cli/skills-content/visual-recap-skill.js.map +1 -1
- package/dist/cli/skills.d.ts.map +1 -1
- package/dist/cli/skills.js +16 -12
- package/dist/cli/skills.js.map +1 -1
- package/dist/client/resources/McpIntegrationDialog.d.ts.map +1 -1
- package/dist/client/resources/McpIntegrationDialog.js +1 -1
- package/dist/client/resources/McpIntegrationDialog.js.map +1 -1
- package/dist/client/resources/mcp-integration-catalog.d.ts +1 -0
- package/dist/client/resources/mcp-integration-catalog.d.ts.map +1 -1
- package/dist/client/resources/mcp-integration-catalog.js +14 -0
- package/dist/client/resources/mcp-integration-catalog.js.map +1 -1
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/awareness.d.ts.map +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/embedding/agent.d.ts.map +1 -1
- package/dist/embedding/agent.js +6 -7
- package/dist/embedding/agent.js.map +1 -1
- package/dist/localization/default-messages.d.ts +5 -0
- package/dist/localization/default-messages.d.ts.map +1 -1
- package/dist/localization/default-messages.js +5 -0
- package/dist/localization/default-messages.js.map +1 -1
- package/dist/mcp/ask-app-inline-tasks.d.ts +47 -0
- package/dist/mcp/ask-app-inline-tasks.d.ts.map +1 -0
- package/dist/mcp/ask-app-inline-tasks.js +87 -0
- package/dist/mcp/ask-app-inline-tasks.js.map +1 -0
- package/dist/mcp/build-server.d.ts.map +1 -1
- package/dist/mcp/build-server.js +56 -3
- package/dist/mcp/build-server.js.map +1 -1
- package/dist/mcp/builtin-tools.d.ts.map +1 -1
- package/dist/mcp/builtin-tools.js +141 -21
- package/dist/mcp/builtin-tools.js.map +1 -1
- package/dist/mcp/connect-route.d.ts +12 -10
- package/dist/mcp/connect-route.d.ts.map +1 -1
- package/dist/mcp/connect-route.js +17 -14
- package/dist/mcp/connect-route.js.map +1 -1
- package/dist/mcp/oauth-route.d.ts +1 -1
- package/dist/mcp/oauth-route.d.ts.map +1 -1
- package/dist/mcp/oauth-route.js +30 -13
- package/dist/mcp/oauth-route.js.map +1 -1
- package/dist/mcp/route-paths.d.ts +13 -0
- package/dist/mcp/route-paths.d.ts.map +1 -0
- package/dist/mcp/route-paths.js +27 -0
- package/dist/mcp/route-paths.js.map +1 -0
- package/dist/mcp/server.d.ts +2 -1
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +14 -6
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/stdio.d.ts +7 -6
- package/dist/mcp/stdio.d.ts.map +1 -1
- package/dist/mcp/stdio.js +27 -15
- package/dist/mcp/stdio.js.map +1 -1
- package/dist/mcp/workspace-resolve.d.ts +2 -1
- package/dist/mcp/workspace-resolve.d.ts.map +1 -1
- package/dist/mcp/workspace-resolve.js +2 -1
- package/dist/mcp/workspace-resolve.js.map +1 -1
- package/dist/mcp-client/manager.js +6 -3
- package/dist/mcp-client/manager.js.map +1 -1
- package/dist/mcp-client/remote-store.js +5 -7
- package/dist/mcp-client/remote-store.js.map +1 -1
- package/dist/notifications/routes.d.ts +2 -2
- package/dist/observability/routes.d.ts +3 -3
- package/dist/progress/routes.d.ts +1 -1
- package/dist/provider-api/corpus-jobs.d.ts +2 -2
- package/dist/resources/handlers.d.ts +3 -3
- package/dist/secrets/routes.d.ts +6 -6
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +60 -9
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/auth.d.ts.map +1 -1
- package/dist/server/auth.js +16 -6
- package/dist/server/auth.js.map +1 -1
- package/dist/server/core-routes-plugin.d.ts +4 -3
- package/dist/server/core-routes-plugin.d.ts.map +1 -1
- package/dist/server/core-routes-plugin.js +20 -15
- package/dist/server/core-routes-plugin.js.map +1 -1
- package/dist/server/csrf.d.ts.map +1 -1
- package/dist/server/csrf.js +11 -0
- package/dist/server/csrf.js.map +1 -1
- package/dist/server/framework-request-handler.d.ts.map +1 -1
- package/dist/server/framework-request-handler.js +8 -2
- package/dist/server/framework-request-handler.js.map +1 -1
- package/dist/server/google-oauth.d.ts +2 -0
- package/dist/server/google-oauth.d.ts.map +1 -1
- package/dist/server/google-oauth.js +5 -0
- package/dist/server/google-oauth.js.map +1 -1
- package/dist/server/http-response-telemetry.d.ts.map +1 -1
- package/dist/server/http-response-telemetry.js +4 -1
- package/dist/server/http-response-telemetry.js.map +1 -1
- package/dist/server/recap-image-route.js +3 -3
- package/dist/server/recap-image-route.js.map +1 -1
- package/dist/server/security-headers.d.ts.map +1 -1
- package/dist/server/security-headers.js +4 -1
- package/dist/server/security-headers.js.map +1 -1
- package/dist/server/ssr-handler.d.ts.map +1 -1
- package/dist/server/ssr-handler.js +3 -1
- package/dist/server/ssr-handler.js.map +1 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/dist/shared/cache-control.d.ts +7 -6
- package/dist/shared/cache-control.d.ts.map +1 -1
- package/dist/shared/cache-control.js +4 -3
- package/dist/shared/cache-control.js.map +1 -1
- package/dist/templates/default/.agents/skills/security/SKILL.md +10 -0
- package/dist/templates/workspace-core/.agents/skills/authentication/SKILL.md +15 -6
- package/dist/templates/workspace-core/.agents/skills/external-agents/SKILL.md +16 -10
- package/dist/templates/workspace-core/.agents/skills/performance/SKILL.md +20 -1
- package/dist/templates/workspace-core/.agents/skills/security/SKILL.md +10 -0
- package/docs/content/actions.mdx +1 -1
- package/docs/content/authentication.mdx +1 -1
- package/docs/content/dispatch.mdx +3 -3
- package/docs/content/external-agents.mdx +30 -19
- package/docs/content/locales/ar-SA/actions.mdx +1 -1
- package/docs/content/locales/ar-SA/authentication.mdx +1 -1
- package/docs/content/locales/ar-SA/dispatch.mdx +3 -3
- package/docs/content/locales/ar-SA/external-agents.mdx +23 -19
- package/docs/content/locales/ar-SA/mcp-clients.mdx +31 -3
- package/docs/content/locales/ar-SA/mcp-protocol.mdx +29 -15
- package/docs/content/locales/ar-SA/plan-plugin.mdx +3 -3
- package/docs/content/locales/ar-SA/server.mdx +2 -2
- package/docs/content/locales/ar-SA/skills-guide.mdx +1 -1
- package/docs/content/locales/ar-SA/template-assets.mdx +1 -1
- package/docs/content/locales/ar-SA/template-dispatch.mdx +2 -2
- package/docs/content/locales/ar-SA/template-plan.mdx +3 -3
- package/docs/content/locales/de-DE/actions.mdx +1 -1
- package/docs/content/locales/de-DE/authentication.mdx +1 -1
- package/docs/content/locales/de-DE/dispatch.mdx +3 -3
- package/docs/content/locales/de-DE/external-agents.mdx +23 -19
- package/docs/content/locales/de-DE/mcp-clients.mdx +37 -3
- package/docs/content/locales/de-DE/mcp-protocol.mdx +29 -15
- package/docs/content/locales/de-DE/plan-plugin.mdx +3 -3
- package/docs/content/locales/de-DE/server.mdx +2 -2
- package/docs/content/locales/de-DE/skills-guide.mdx +1 -1
- package/docs/content/locales/de-DE/template-assets.mdx +1 -1
- package/docs/content/locales/de-DE/template-dispatch.mdx +2 -2
- package/docs/content/locales/de-DE/template-plan.mdx +3 -3
- package/docs/content/locales/es-ES/actions.mdx +1 -1
- package/docs/content/locales/es-ES/authentication.mdx +1 -1
- package/docs/content/locales/es-ES/dispatch.mdx +3 -3
- package/docs/content/locales/es-ES/external-agents.mdx +32 -19
- package/docs/content/locales/es-ES/mcp-clients.mdx +17 -3
- package/docs/content/locales/es-ES/mcp-protocol.mdx +38 -15
- package/docs/content/locales/es-ES/plan-plugin.mdx +3 -3
- package/docs/content/locales/es-ES/server.mdx +2 -2
- package/docs/content/locales/es-ES/skills-guide.mdx +1 -1
- package/docs/content/locales/es-ES/template-assets.mdx +1 -1
- package/docs/content/locales/es-ES/template-dispatch.mdx +2 -2
- package/docs/content/locales/es-ES/template-plan.mdx +3 -3
- package/docs/content/locales/fr-FR/actions.mdx +1 -1
- package/docs/content/locales/fr-FR/authentication.mdx +1 -1
- package/docs/content/locales/fr-FR/dispatch.mdx +3 -3
- package/docs/content/locales/fr-FR/external-agents.mdx +23 -19
- package/docs/content/locales/fr-FR/mcp-clients.mdx +17 -3
- package/docs/content/locales/fr-FR/mcp-protocol.mdx +29 -15
- package/docs/content/locales/fr-FR/plan-plugin.mdx +3 -3
- package/docs/content/locales/fr-FR/server.mdx +2 -2
- package/docs/content/locales/fr-FR/skills-guide.mdx +1 -1
- package/docs/content/locales/fr-FR/template-assets.mdx +1 -1
- package/docs/content/locales/fr-FR/template-dispatch.mdx +2 -2
- package/docs/content/locales/fr-FR/template-plan.mdx +3 -3
- package/docs/content/locales/hi-IN/actions.mdx +1 -1
- package/docs/content/locales/hi-IN/authentication.mdx +1 -1
- package/docs/content/locales/hi-IN/dispatch.mdx +3 -3
- package/docs/content/locales/hi-IN/external-agents.mdx +31 -19
- package/docs/content/locales/hi-IN/mcp-clients.mdx +17 -3
- package/docs/content/locales/hi-IN/mcp-protocol.mdx +36 -15
- package/docs/content/locales/hi-IN/plan-plugin.mdx +3 -3
- package/docs/content/locales/hi-IN/server.mdx +2 -2
- package/docs/content/locales/hi-IN/skills-guide.mdx +1 -1
- package/docs/content/locales/hi-IN/template-assets.mdx +1 -1
- package/docs/content/locales/hi-IN/template-dispatch.mdx +2 -2
- package/docs/content/locales/hi-IN/template-plan.mdx +3 -3
- package/docs/content/locales/ja-JP/actions.mdx +1 -1
- package/docs/content/locales/ja-JP/authentication.mdx +1 -1
- package/docs/content/locales/ja-JP/dispatch.mdx +3 -3
- package/docs/content/locales/ja-JP/external-agents.mdx +23 -19
- package/docs/content/locales/ja-JP/mcp-clients.mdx +34 -3
- package/docs/content/locales/ja-JP/mcp-protocol.mdx +29 -15
- package/docs/content/locales/ja-JP/plan-plugin.mdx +3 -3
- package/docs/content/locales/ja-JP/server.mdx +2 -2
- package/docs/content/locales/ja-JP/skills-guide.mdx +1 -1
- package/docs/content/locales/ja-JP/template-assets.mdx +1 -1
- package/docs/content/locales/ja-JP/template-dispatch.mdx +2 -2
- package/docs/content/locales/ja-JP/template-plan.mdx +3 -3
- package/docs/content/locales/ko-KR/actions.mdx +1 -1
- package/docs/content/locales/ko-KR/authentication.mdx +1 -1
- package/docs/content/locales/ko-KR/dispatch.mdx +3 -3
- package/docs/content/locales/ko-KR/external-agents.mdx +30 -19
- package/docs/content/locales/ko-KR/mcp-clients.mdx +33 -3
- package/docs/content/locales/ko-KR/mcp-protocol.mdx +36 -15
- package/docs/content/locales/ko-KR/plan-plugin.mdx +3 -3
- package/docs/content/locales/ko-KR/server.mdx +2 -2
- package/docs/content/locales/ko-KR/skills-guide.mdx +1 -1
- package/docs/content/locales/ko-KR/template-assets.mdx +1 -1
- package/docs/content/locales/ko-KR/template-dispatch.mdx +2 -2
- package/docs/content/locales/ko-KR/template-plan.mdx +3 -3
- package/docs/content/locales/pt-BR/actions.mdx +1 -1
- package/docs/content/locales/pt-BR/authentication.mdx +1 -1
- package/docs/content/locales/pt-BR/dispatch.mdx +3 -3
- package/docs/content/locales/pt-BR/external-agents.mdx +32 -19
- package/docs/content/locales/pt-BR/mcp-clients.mdx +34 -3
- package/docs/content/locales/pt-BR/mcp-protocol.mdx +32 -15
- package/docs/content/locales/pt-BR/plan-plugin.mdx +3 -3
- package/docs/content/locales/pt-BR/server.mdx +2 -2
- package/docs/content/locales/pt-BR/skills-guide.mdx +1 -1
- package/docs/content/locales/pt-BR/template-assets.mdx +1 -1
- package/docs/content/locales/pt-BR/template-dispatch.mdx +2 -2
- package/docs/content/locales/pt-BR/template-plan.mdx +3 -3
- package/docs/content/locales/zh-CN/actions.mdx +1 -1
- package/docs/content/locales/zh-CN/authentication.mdx +1 -1
- package/docs/content/locales/zh-CN/dispatch.mdx +3 -3
- package/docs/content/locales/zh-CN/external-agents.mdx +23 -19
- package/docs/content/locales/zh-CN/mcp-clients.mdx +28 -3
- package/docs/content/locales/zh-CN/mcp-protocol.mdx +29 -15
- package/docs/content/locales/zh-CN/plan-plugin.mdx +3 -3
- package/docs/content/locales/zh-CN/server.mdx +2 -2
- package/docs/content/locales/zh-CN/skills-guide.mdx +1 -1
- package/docs/content/locales/zh-CN/template-assets.mdx +1 -1
- package/docs/content/locales/zh-CN/template-dispatch.mdx +2 -2
- package/docs/content/locales/zh-CN/template-plan.mdx +3 -3
- package/docs/content/locales/zh-TW/actions.mdx +1 -1
- package/docs/content/locales/zh-TW/authentication.mdx +1 -1
- package/docs/content/locales/zh-TW/dispatch.mdx +3 -3
- package/docs/content/locales/zh-TW/external-agents.mdx +23 -19
- package/docs/content/locales/zh-TW/mcp-clients.mdx +28 -3
- package/docs/content/locales/zh-TW/mcp-protocol.mdx +30 -15
- package/docs/content/locales/zh-TW/plan-plugin.mdx +3 -3
- package/docs/content/locales/zh-TW/server.mdx +2 -2
- package/docs/content/locales/zh-TW/skills-guide.mdx +1 -1
- package/docs/content/locales/zh-TW/template-assets.mdx +1 -1
- package/docs/content/locales/zh-TW/template-dispatch.mdx +2 -2
- package/docs/content/locales/zh-TW/template-plan.mdx +3 -3
- package/docs/content/mcp-clients.mdx +31 -4
- package/docs/content/mcp-protocol.mdx +35 -15
- package/docs/content/plan-plugin.mdx +3 -3
- package/docs/content/server.mdx +2 -2
- package/docs/content/skills-guide.mdx +1 -1
- package/docs/content/template-assets.mdx +1 -1
- package/docs/content/template-dispatch.mdx +2 -2
- package/docs/content/template-plan.mdx +3 -3
- package/package.json +1 -1
- package/src/templates/default/.agents/skills/security/SKILL.md +10 -0
- package/src/templates/workspace-core/.agents/skills/authentication/SKILL.md +15 -6
- package/src/templates/workspace-core/.agents/skills/external-agents/SKILL.md +16 -10
- package/src/templates/workspace-core/.agents/skills/performance/SKILL.md +20 -1
- package/src/templates/workspace-core/.agents/skills/security/SKILL.md +10 -0
|
@@ -3,6 +3,7 @@ import { runWithRequestContext } from "@agent-native/core/server/request-context
|
|
|
3
3
|
import { sendDashboardReportSubscription } from "../lib/dashboard-report";
|
|
4
4
|
import {
|
|
5
5
|
claimDueDashboardReportSubscriptions,
|
|
6
|
+
dashboardReportRetryAt,
|
|
6
7
|
markDashboardReportResult,
|
|
7
8
|
} from "../lib/dashboard-report-subscriptions";
|
|
8
9
|
|
|
@@ -41,22 +42,40 @@ export async function runDashboardReportsOnce(): Promise<{
|
|
|
41
42
|
for (const sub of batch) {
|
|
42
43
|
processed++;
|
|
43
44
|
try {
|
|
45
|
+
const retryAt = dashboardReportRetryAt(sub);
|
|
44
46
|
const result = await runWithRequestContext(
|
|
45
47
|
{
|
|
46
48
|
userEmail: sub.ownerEmail,
|
|
47
49
|
orgId: sub.orgId ?? undefined,
|
|
48
50
|
},
|
|
49
|
-
() =>
|
|
51
|
+
() =>
|
|
52
|
+
sendDashboardReportSubscription(sub, {
|
|
53
|
+
skipEmailWithoutScreenshot: retryAt !== null,
|
|
54
|
+
}),
|
|
50
55
|
);
|
|
51
56
|
if (!result.screenshotAttached) {
|
|
52
57
|
const message = result.screenshotError
|
|
53
58
|
? `Dashboard screenshot unavailable: ${result.screenshotError}`
|
|
54
59
|
: "Dashboard screenshot unavailable";
|
|
60
|
+
if (retryAt && !result.emailsSent) {
|
|
61
|
+
console.error(
|
|
62
|
+
`[dashboard-report] Subscription ${sub.id} skipped sending without a screenshot, will retry:`,
|
|
63
|
+
message,
|
|
64
|
+
);
|
|
65
|
+
await markDashboardReportResult(
|
|
66
|
+
sub,
|
|
67
|
+
"error",
|
|
68
|
+
`${message} (retry scheduled)`,
|
|
69
|
+
{ nextRunAt: retryAt },
|
|
70
|
+
);
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
failed++;
|
|
55
74
|
console.error(
|
|
56
75
|
`[dashboard-report] Subscription ${sub.id} sent without a screenshot:`,
|
|
57
76
|
message,
|
|
58
77
|
);
|
|
59
|
-
await markDashboardReportResult(sub, "
|
|
78
|
+
await markDashboardReportResult(sub, "error", message);
|
|
60
79
|
continue;
|
|
61
80
|
}
|
|
62
81
|
await markDashboardReportResult(sub, "success");
|
|
@@ -158,6 +158,19 @@ function calendarDayAfter(parts: { year: number; month: number; day: number }) {
|
|
|
158
158
|
};
|
|
159
159
|
}
|
|
160
160
|
|
|
161
|
+
function calendarDayBefore(parts: {
|
|
162
|
+
year: number;
|
|
163
|
+
month: number;
|
|
164
|
+
day: number;
|
|
165
|
+
}) {
|
|
166
|
+
const prev = new Date(Date.UTC(parts.year, parts.month - 1, parts.day - 1));
|
|
167
|
+
return {
|
|
168
|
+
year: prev.getUTCFullYear(),
|
|
169
|
+
month: prev.getUTCMonth() + 1,
|
|
170
|
+
day: prev.getUTCDate(),
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
|
|
161
174
|
function zonedTimeToUtc(
|
|
162
175
|
parts: { year: number; month: number; day: number },
|
|
163
176
|
hour: number,
|
|
@@ -205,6 +218,47 @@ export function nextDailyRunAt(
|
|
|
205
218
|
return candidate.toISOString();
|
|
206
219
|
}
|
|
207
220
|
|
|
221
|
+
export function lastDailyRunAt(
|
|
222
|
+
timeOfDay: string,
|
|
223
|
+
timeZone: string,
|
|
224
|
+
from: Date = new Date(),
|
|
225
|
+
): string {
|
|
226
|
+
const [hour, minute] = assertTimeOfDay(timeOfDay).split(":").map(Number);
|
|
227
|
+
const timezone = assertTimezone(timeZone);
|
|
228
|
+
const today = getZonedParts(from, timezone);
|
|
229
|
+
let candidate = zonedTimeToUtc(today, hour, minute, timezone);
|
|
230
|
+
if (candidate.getTime() > from.getTime()) {
|
|
231
|
+
candidate = zonedTimeToUtc(
|
|
232
|
+
calendarDayBefore(today),
|
|
233
|
+
hour,
|
|
234
|
+
minute,
|
|
235
|
+
timezone,
|
|
236
|
+
);
|
|
237
|
+
}
|
|
238
|
+
return candidate.toISOString();
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
const DASHBOARD_REPORT_RETRY_WINDOW_MS = 60 * 60 * 1000;
|
|
242
|
+
const DASHBOARD_REPORT_RETRY_DELAY_MS = 10 * 60 * 1000;
|
|
243
|
+
|
|
244
|
+
export function dashboardReportRetryAt(
|
|
245
|
+
sub: DashboardReportSubscription,
|
|
246
|
+
now: Date = new Date(),
|
|
247
|
+
): string | null {
|
|
248
|
+
if (!sub.enabled) return null;
|
|
249
|
+
try {
|
|
250
|
+
const anchor = Date.parse(lastDailyRunAt(sub.timeOfDay, sub.timezone, now));
|
|
251
|
+
if (now.getTime() - anchor < DASHBOARD_REPORT_RETRY_WINDOW_MS) {
|
|
252
|
+
return new Date(
|
|
253
|
+
now.getTime() + DASHBOARD_REPORT_RETRY_DELAY_MS,
|
|
254
|
+
).toISOString();
|
|
255
|
+
}
|
|
256
|
+
return null;
|
|
257
|
+
} catch {
|
|
258
|
+
return null;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
208
262
|
function rowToSubscription(row: any): DashboardReportSubscription {
|
|
209
263
|
return {
|
|
210
264
|
id: row.id,
|
|
@@ -477,6 +531,7 @@ export async function markDashboardReportResult(
|
|
|
477
531
|
sub: DashboardReportSubscription,
|
|
478
532
|
status: "success" | "error",
|
|
479
533
|
error?: string,
|
|
534
|
+
options?: { nextRunAt?: string },
|
|
480
535
|
): Promise<void> {
|
|
481
536
|
const now = nowIso();
|
|
482
537
|
const db = getDb() as any;
|
|
@@ -486,7 +541,8 @@ export async function markDashboardReportResult(
|
|
|
486
541
|
lastStatus: status,
|
|
487
542
|
lastError: error ? error.slice(0, 500) : null,
|
|
488
543
|
nextRunAt: sub.enabled
|
|
489
|
-
?
|
|
544
|
+
? (options?.nextRunAt ??
|
|
545
|
+
nextDailyRunAt(sub.timeOfDay, sub.timezone, new Date()))
|
|
490
546
|
: null,
|
|
491
547
|
updatedAt: now,
|
|
492
548
|
})
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
1
2
|
import { existsSync } from "node:fs";
|
|
3
|
+
import { readdir, rm, stat } from "node:fs/promises";
|
|
4
|
+
import { tmpdir } from "node:os";
|
|
5
|
+
import { join } from "node:path";
|
|
2
6
|
|
|
3
7
|
import {
|
|
4
8
|
getAppProductionUrl,
|
|
@@ -44,11 +48,24 @@ const DASHBOARD_REPORT_CID = "dashboard-report-snapshot";
|
|
|
44
48
|
const LOCAL_SCREENSHOT_TIMEOUT_MS = 90_000;
|
|
45
49
|
const SERVERLESS_SCREENSHOT_TIMEOUT_MS = 90_000;
|
|
46
50
|
const SERVERLESS_SECOND_READY_TIMEOUT_MS = 45_000;
|
|
51
|
+
const SERVERLESS_FULL_ATTEMPT_TIMEOUT_MS = 125_000;
|
|
52
|
+
const SERVERLESS_LIGHTWEIGHT_ATTEMPT_TIMEOUT_MS = 85_000;
|
|
53
|
+
const BROWSER_CLEANUP_TIMEOUT_MS = 10_000;
|
|
47
54
|
const SCREENSHOT_VIEWPORT_PADDING = 64;
|
|
48
55
|
|
|
49
56
|
type DashboardScreenshotAttempt = {
|
|
50
57
|
label: "full" | "full-lightweight";
|
|
51
58
|
viewport: { width: number; height: number };
|
|
59
|
+
captureScale?: number;
|
|
60
|
+
readyTimeout?: number;
|
|
61
|
+
secondReadyTimeout?: number;
|
|
62
|
+
totalTimeout?: number;
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
type LaunchedScreenshotBrowser = {
|
|
66
|
+
browser: any;
|
|
67
|
+
cleanup: () => Promise<void>;
|
|
68
|
+
newPage: () => Promise<any>;
|
|
52
69
|
};
|
|
53
70
|
|
|
54
71
|
function daysAgo(n: number): string {
|
|
@@ -216,14 +233,44 @@ function localChromiumExecutablePath(): string | null {
|
|
|
216
233
|
return candidates.find((candidate) => existsSync(candidate)) ?? null;
|
|
217
234
|
}
|
|
218
235
|
|
|
219
|
-
async function
|
|
236
|
+
async function sweepStaleScreenshotProfiles(): Promise<void> {
|
|
237
|
+
let entries: string[];
|
|
238
|
+
try {
|
|
239
|
+
entries = await readdir(tmpdir());
|
|
240
|
+
} catch {
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
const stale = entries
|
|
244
|
+
.filter((entry) => entry.startsWith("dashboard-report-playwright-"))
|
|
245
|
+
.slice(0, 8);
|
|
246
|
+
for (const entry of stale) {
|
|
247
|
+
const full = join(tmpdir(), entry);
|
|
248
|
+
const info = await stat(full).catch(() => null);
|
|
249
|
+
if (info && Date.now() - info.mtimeMs > 30 * 60_000) {
|
|
250
|
+
await rm(full, { recursive: true, force: true }).catch(() => {});
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
async function launchScreenshotBrowser(
|
|
256
|
+
viewport: DashboardScreenshotAttempt["viewport"],
|
|
257
|
+
): Promise<LaunchedScreenshotBrowser> {
|
|
220
258
|
const { chromium: playwright } = await import("playwright-core");
|
|
221
259
|
const localExecutablePath = localChromiumExecutablePath();
|
|
222
260
|
if (localExecutablePath) {
|
|
223
|
-
|
|
261
|
+
const browser = await playwright.launch({
|
|
224
262
|
executablePath: localExecutablePath,
|
|
225
263
|
headless: true,
|
|
226
264
|
});
|
|
265
|
+
return {
|
|
266
|
+
browser,
|
|
267
|
+
cleanup: async () => {},
|
|
268
|
+
newPage: () =>
|
|
269
|
+
browser.newPage({
|
|
270
|
+
viewport,
|
|
271
|
+
deviceScaleFactor: 1,
|
|
272
|
+
}),
|
|
273
|
+
};
|
|
227
274
|
}
|
|
228
275
|
|
|
229
276
|
if (isServerlessBrowserRuntime()) {
|
|
@@ -232,19 +279,54 @@ async function launchScreenshotBrowser() {
|
|
|
232
279
|
const packUrl =
|
|
233
280
|
process.env.DASHBOARD_REPORT_CHROMIUM_PACK_URL?.trim() ||
|
|
234
281
|
DEFAULT_SERVERLESS_CHROMIUM_PACK_URL;
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
282
|
+
await sweepStaleScreenshotProfiles();
|
|
283
|
+
const userDataDir = join(
|
|
284
|
+
tmpdir(),
|
|
285
|
+
`dashboard-report-playwright-${randomUUID()}`,
|
|
286
|
+
);
|
|
287
|
+
const cleanup = async () => {
|
|
288
|
+
await rm(userDataDir, { recursive: true, force: true }).catch((err) => {
|
|
289
|
+
console.error(
|
|
290
|
+
"[dashboard-report] Failed to clean Chromium profile:",
|
|
291
|
+
errorMessage(err),
|
|
292
|
+
);
|
|
293
|
+
});
|
|
294
|
+
};
|
|
295
|
+
|
|
296
|
+
try {
|
|
297
|
+
const browser = await playwright.launchPersistentContext(userDataDir, {
|
|
298
|
+
args: [
|
|
299
|
+
...chromium.args,
|
|
300
|
+
"--disable-dev-shm-usage",
|
|
301
|
+
"--disable-gpu",
|
|
302
|
+
"--hide-scrollbars",
|
|
303
|
+
],
|
|
304
|
+
deviceScaleFactor: 1,
|
|
305
|
+
executablePath: await chromium.executablePath(packUrl),
|
|
306
|
+
headless: true,
|
|
307
|
+
viewport,
|
|
308
|
+
});
|
|
309
|
+
return {
|
|
310
|
+
browser,
|
|
311
|
+
cleanup,
|
|
312
|
+
newPage: () => browser.newPage(),
|
|
313
|
+
};
|
|
314
|
+
} catch (err) {
|
|
315
|
+
await cleanup();
|
|
316
|
+
throw err;
|
|
317
|
+
}
|
|
245
318
|
}
|
|
246
319
|
|
|
247
|
-
|
|
320
|
+
const browser = await playwright.launch({ headless: true });
|
|
321
|
+
return {
|
|
322
|
+
browser,
|
|
323
|
+
cleanup: async () => {},
|
|
324
|
+
newPage: () =>
|
|
325
|
+
browser.newPage({
|
|
326
|
+
viewport,
|
|
327
|
+
deviceScaleFactor: 1,
|
|
328
|
+
}),
|
|
329
|
+
};
|
|
248
330
|
}
|
|
249
331
|
|
|
250
332
|
function screenshotTimeoutMs(): number {
|
|
@@ -350,6 +432,40 @@ async function fitViewportWidthToDashboardCapture(
|
|
|
350
432
|
await page.waitForTimeout(250);
|
|
351
433
|
}
|
|
352
434
|
|
|
435
|
+
async function scaleDashboardCapture(
|
|
436
|
+
page: any,
|
|
437
|
+
scale: number | undefined,
|
|
438
|
+
): Promise<void> {
|
|
439
|
+
if (!scale || scale >= 1) return;
|
|
440
|
+
await page.evaluate(`(() => {
|
|
441
|
+
const root = document.querySelector("[data-dashboard-report-capture]");
|
|
442
|
+
if (root instanceof HTMLElement) root.style.zoom = "${scale}";
|
|
443
|
+
})()`);
|
|
444
|
+
await page.waitForTimeout(250);
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
async function runBoundedBrowserCleanup(
|
|
448
|
+
label: string,
|
|
449
|
+
operation: () => Promise<void>,
|
|
450
|
+
): Promise<void> {
|
|
451
|
+
let timeout: ReturnType<typeof setTimeout> | undefined;
|
|
452
|
+
try {
|
|
453
|
+
await Promise.race([
|
|
454
|
+
operation(),
|
|
455
|
+
new Promise<never>((_, reject) => {
|
|
456
|
+
timeout = setTimeout(
|
|
457
|
+
() => reject(new Error(`${label} exceeded cleanup timeout`)),
|
|
458
|
+
BROWSER_CLEANUP_TIMEOUT_MS,
|
|
459
|
+
);
|
|
460
|
+
}),
|
|
461
|
+
]);
|
|
462
|
+
} catch (err) {
|
|
463
|
+
console.error(`[dashboard-report] ${label}:`, errorMessage(err));
|
|
464
|
+
} finally {
|
|
465
|
+
if (timeout) clearTimeout(timeout);
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
|
|
353
469
|
async function captureDashboardPng(
|
|
354
470
|
sub: DashboardReportSubscription,
|
|
355
471
|
snapshot: ReportSnapshot,
|
|
@@ -373,13 +489,47 @@ async function captureDashboardPng(
|
|
|
373
489
|
screenshotUrl.searchParams.set(EMBED_MODE_QUERY_PARAM, "1");
|
|
374
490
|
screenshotUrl.searchParams.set(EMBED_TOKEN_QUERY_PARAM, token);
|
|
375
491
|
|
|
376
|
-
|
|
492
|
+
let browser: any;
|
|
493
|
+
let cleanup = async () => {};
|
|
494
|
+
let newPage = async (): Promise<any> => {
|
|
495
|
+
throw new Error("Screenshot browser did not provide a page factory");
|
|
496
|
+
};
|
|
497
|
+
let launchPromise: Promise<LaunchedScreenshotBrowser> | undefined;
|
|
498
|
+
let launchTimeout: ReturnType<typeof setTimeout> | undefined;
|
|
499
|
+
let captureStage = "launching the screenshot browser";
|
|
500
|
+
let attemptTimedOut = false;
|
|
501
|
+
const attemptTimeout = attempt.totalTimeout
|
|
502
|
+
? setTimeout(() => {
|
|
503
|
+
attemptTimedOut = true;
|
|
504
|
+
if (browser) void browser.close().catch(() => {});
|
|
505
|
+
}, attempt.totalTimeout)
|
|
506
|
+
: null;
|
|
377
507
|
try {
|
|
508
|
+
launchPromise = launchScreenshotBrowser(attempt.viewport);
|
|
509
|
+
const launched = attempt.totalTimeout
|
|
510
|
+
? await Promise.race([
|
|
511
|
+
launchPromise,
|
|
512
|
+
new Promise<never>((_, reject) => {
|
|
513
|
+
launchTimeout = setTimeout(() => {
|
|
514
|
+
attemptTimedOut = true;
|
|
515
|
+
reject(
|
|
516
|
+
new Error(
|
|
517
|
+
`${attempt.label} browser launch exceeded ${attempt.totalTimeout}ms`,
|
|
518
|
+
),
|
|
519
|
+
);
|
|
520
|
+
}, attempt.totalTimeout);
|
|
521
|
+
}),
|
|
522
|
+
])
|
|
523
|
+
: await launchPromise;
|
|
524
|
+
browser = launched.browser;
|
|
525
|
+
cleanup = launched.cleanup;
|
|
526
|
+
newPage = launched.newPage;
|
|
527
|
+
if (attemptTimedOut) {
|
|
528
|
+
throw new Error("Screenshot browser launch exceeded attempt timeout");
|
|
529
|
+
}
|
|
530
|
+
|
|
378
531
|
const timeout = screenshotTimeoutMs();
|
|
379
|
-
const page = await
|
|
380
|
-
viewport: attempt.viewport,
|
|
381
|
-
deviceScaleFactor: 1,
|
|
382
|
-
});
|
|
532
|
+
const page = await newPage();
|
|
383
533
|
page.setDefaultTimeout(timeout);
|
|
384
534
|
await page.emulateMedia({ media: "screen", colorScheme: "light" });
|
|
385
535
|
await page.addInitScript(() => {
|
|
@@ -390,14 +540,24 @@ async function captureDashboardPng(
|
|
|
390
540
|
timeout,
|
|
391
541
|
});
|
|
392
542
|
|
|
543
|
+
captureStage = "waiting for the report surface";
|
|
393
544
|
const capture = page.locator("[data-dashboard-report-capture]");
|
|
394
545
|
await capture.waitFor({ state: "visible", timeout });
|
|
395
|
-
|
|
546
|
+
captureStage = "waiting for dashboard queries";
|
|
547
|
+
await waitForDashboardReportReady(page, attempt.readyTimeout ?? timeout);
|
|
548
|
+
captureStage = "rendering lazy dashboard panels";
|
|
396
549
|
await scrollDashboardForLazyRendering(page);
|
|
397
|
-
|
|
550
|
+
captureStage = "waiting for lazy dashboard panels";
|
|
551
|
+
await waitForDashboardReportReady(
|
|
552
|
+
page,
|
|
553
|
+
attempt.secondReadyTimeout ?? secondReadyTimeoutMs(),
|
|
554
|
+
);
|
|
398
555
|
|
|
556
|
+
captureStage = "sizing the dashboard capture";
|
|
399
557
|
await fitViewportWidthToDashboardCapture(page, capture, attempt.viewport);
|
|
558
|
+
await scaleDashboardCapture(page, attempt.captureScale);
|
|
400
559
|
await capture.scrollIntoViewIfNeeded();
|
|
560
|
+
captureStage = "rasterizing the dashboard PNG";
|
|
401
561
|
const image = await capture.screenshot({
|
|
402
562
|
type: "png",
|
|
403
563
|
animations: "disabled",
|
|
@@ -406,8 +566,39 @@ async function captureDashboardPng(
|
|
|
406
566
|
throw new Error("Dashboard screenshot was empty");
|
|
407
567
|
}
|
|
408
568
|
return Buffer.from(image);
|
|
569
|
+
} catch (err) {
|
|
570
|
+
if (attemptTimedOut) {
|
|
571
|
+
throw new Error(
|
|
572
|
+
`${attempt.label} capture exceeded ${attempt.totalTimeout}ms while ${captureStage}`,
|
|
573
|
+
);
|
|
574
|
+
}
|
|
575
|
+
throw new Error(`${captureStage}: ${errorMessage(err)}`);
|
|
409
576
|
} finally {
|
|
410
|
-
|
|
577
|
+
if (attemptTimeout) clearTimeout(attemptTimeout);
|
|
578
|
+
if (launchTimeout) clearTimeout(launchTimeout);
|
|
579
|
+
if (!browser && launchPromise) {
|
|
580
|
+
void launchPromise.then(
|
|
581
|
+
async (lateBrowser) => {
|
|
582
|
+
await runBoundedBrowserCleanup(
|
|
583
|
+
"Failed to close late screenshot browser",
|
|
584
|
+
() => lateBrowser.browser.close(),
|
|
585
|
+
);
|
|
586
|
+
await runBoundedBrowserCleanup(
|
|
587
|
+
"Failed to clean late Chromium profile",
|
|
588
|
+
lateBrowser.cleanup,
|
|
589
|
+
);
|
|
590
|
+
},
|
|
591
|
+
() => {
|
|
592
|
+
// The launch rejection was already handled by the race above.
|
|
593
|
+
},
|
|
594
|
+
);
|
|
595
|
+
}
|
|
596
|
+
if (browser) {
|
|
597
|
+
await runBoundedBrowserCleanup("Failed to close screenshot browser", () =>
|
|
598
|
+
browser.close(),
|
|
599
|
+
);
|
|
600
|
+
}
|
|
601
|
+
await runBoundedBrowserCleanup("Failed to clean Chromium profile", cleanup);
|
|
411
602
|
}
|
|
412
603
|
}
|
|
413
604
|
|
|
@@ -419,6 +610,11 @@ function errorMessage(err: unknown): string {
|
|
|
419
610
|
);
|
|
420
611
|
}
|
|
421
612
|
|
|
613
|
+
function storedAttemptError(message: string): string {
|
|
614
|
+
const normalized = message.replace(/\s+/g, " ").trim();
|
|
615
|
+
return normalized.length > 220 ? `${normalized.slice(0, 219)}…` : normalized;
|
|
616
|
+
}
|
|
617
|
+
|
|
422
618
|
async function captureDashboardPngWithFallback(
|
|
423
619
|
sub: DashboardReportSubscription,
|
|
424
620
|
snapshot: ReportSnapshot,
|
|
@@ -427,11 +623,33 @@ async function captureDashboardPngWithFallback(
|
|
|
427
623
|
mode: "full" | "full-lightweight" | "none";
|
|
428
624
|
error?: string;
|
|
429
625
|
}> {
|
|
626
|
+
const serverless = isServerlessBrowserRuntime();
|
|
430
627
|
const attempts: DashboardScreenshotAttempt[] = [
|
|
431
|
-
{
|
|
432
|
-
|
|
628
|
+
{
|
|
629
|
+
label: "full",
|
|
630
|
+
viewport: { width: 1440, height: 1800 },
|
|
631
|
+
captureScale: 0.85,
|
|
632
|
+
...(serverless
|
|
633
|
+
? {
|
|
634
|
+
secondReadyTimeout: 25_000,
|
|
635
|
+
totalTimeout: SERVERLESS_FULL_ATTEMPT_TIMEOUT_MS,
|
|
636
|
+
}
|
|
637
|
+
: {}),
|
|
638
|
+
},
|
|
639
|
+
{
|
|
640
|
+
label: "full-lightweight",
|
|
641
|
+
viewport: { width: 1200, height: 1400 },
|
|
642
|
+
captureScale: 0.7,
|
|
643
|
+
...(serverless
|
|
644
|
+
? {
|
|
645
|
+
readyTimeout: 55_000,
|
|
646
|
+
secondReadyTimeout: 15_000,
|
|
647
|
+
totalTimeout: SERVERLESS_LIGHTWEIGHT_ATTEMPT_TIMEOUT_MS,
|
|
648
|
+
}
|
|
649
|
+
: {}),
|
|
650
|
+
},
|
|
433
651
|
];
|
|
434
|
-
|
|
652
|
+
const errors: string[] = [];
|
|
435
653
|
|
|
436
654
|
for (const attempt of attempts) {
|
|
437
655
|
try {
|
|
@@ -440,15 +658,20 @@ async function captureDashboardPngWithFallback(
|
|
|
440
658
|
mode: attempt.label,
|
|
441
659
|
};
|
|
442
660
|
} catch (err) {
|
|
443
|
-
|
|
661
|
+
const attemptError = errorMessage(err);
|
|
662
|
+
errors.push(`${attempt.label}: ${storedAttemptError(attemptError)}`);
|
|
444
663
|
console.error(
|
|
445
664
|
`[dashboard-report] ${attempt.label} screenshot failed for subscription ${sub.id}:`,
|
|
446
|
-
|
|
665
|
+
attemptError,
|
|
447
666
|
);
|
|
448
667
|
}
|
|
449
668
|
}
|
|
450
669
|
|
|
451
|
-
return {
|
|
670
|
+
return {
|
|
671
|
+
png: null,
|
|
672
|
+
mode: "none",
|
|
673
|
+
...(errors.length ? { error: errors.join(" | ") } : {}),
|
|
674
|
+
};
|
|
452
675
|
}
|
|
453
676
|
|
|
454
677
|
function reportDate(snapshot: ReportSnapshot): string {
|
|
@@ -518,13 +741,17 @@ function reportFilename(title: string): string {
|
|
|
518
741
|
|
|
519
742
|
export async function sendDashboardReportSubscription(
|
|
520
743
|
sub: DashboardReportSubscription,
|
|
521
|
-
options: {
|
|
744
|
+
options: {
|
|
745
|
+
requireScreenshot?: boolean;
|
|
746
|
+
skipEmailWithoutScreenshot?: boolean;
|
|
747
|
+
} = {},
|
|
522
748
|
): Promise<{
|
|
523
749
|
dashboardUrl: string;
|
|
524
750
|
recipientCount: number;
|
|
525
751
|
screenshotAttached: boolean;
|
|
526
752
|
screenshotMode: "full" | "full-lightweight" | "none";
|
|
527
753
|
screenshotError?: string;
|
|
754
|
+
emailsSent: boolean;
|
|
528
755
|
}> {
|
|
529
756
|
const snapshot = await collectReportSnapshot(sub);
|
|
530
757
|
const capture = await captureDashboardPngWithFallback(sub, snapshot);
|
|
@@ -535,6 +762,16 @@ export async function sendDashboardReportSubscription(
|
|
|
535
762
|
: "Dashboard screenshot unavailable",
|
|
536
763
|
);
|
|
537
764
|
}
|
|
765
|
+
if (!capture.png && options.skipEmailWithoutScreenshot) {
|
|
766
|
+
return {
|
|
767
|
+
dashboardUrl: snapshot.dashboardUrl,
|
|
768
|
+
recipientCount: sub.recipients.length,
|
|
769
|
+
screenshotAttached: false,
|
|
770
|
+
screenshotMode: capture.mode,
|
|
771
|
+
emailsSent: false,
|
|
772
|
+
...(capture.error ? { screenshotError: capture.error } : {}),
|
|
773
|
+
};
|
|
774
|
+
}
|
|
538
775
|
const screenshotAttached = Boolean(capture.png);
|
|
539
776
|
const html = renderReportEmailHtml(snapshot, { screenshotAttached });
|
|
540
777
|
const text = renderReportText(snapshot, { screenshotAttached });
|
|
@@ -565,6 +802,7 @@ export async function sendDashboardReportSubscription(
|
|
|
565
802
|
recipientCount: sub.recipients.length,
|
|
566
803
|
screenshotAttached,
|
|
567
804
|
screenshotMode: capture.mode,
|
|
805
|
+
emailsSent: true,
|
|
568
806
|
...(capture.error ? { screenshotError: capture.error } : {}),
|
|
569
807
|
};
|
|
570
808
|
}
|
|
@@ -161,9 +161,7 @@ export default defineEventHandler(async (event) => {
|
|
|
161
161
|
const headers = new Headers(response.headers);
|
|
162
162
|
headers.delete("content-length");
|
|
163
163
|
if (discovery.privateResponse) {
|
|
164
|
-
headers.set("Cache-Control", "private, max-age=0, no-store");
|
|
165
164
|
headers.set("Referrer-Policy", "no-referrer");
|
|
166
|
-
setResponseHeader(event, "Cache-Control", "private, max-age=0, no-store");
|
|
167
165
|
setResponseHeader(event, "Referrer-Policy", "no-referrer");
|
|
168
166
|
}
|
|
169
167
|
|
|
@@ -147,6 +147,16 @@ export default defineEventHandler(async (event) => {
|
|
|
147
147
|
|
|
148
148
|
- Never create unprotected routes that modify data.
|
|
149
149
|
|
|
150
|
+
**Exception — the SSR HTML/`.data` catch-all is deliberately session-blind.**
|
|
151
|
+
The rule above is for routes that read or mutate user data. The SSR page
|
|
152
|
+
render and React Router `.data` route are different: they serve one
|
|
153
|
+
impersonal, public-cacheable shell to every visitor by design, and loaders on
|
|
154
|
+
that path render no user data. Do not "fix" this by adding `getSession`,
|
|
155
|
+
`private`, or `no-store` to it — that regresses the CDN cache contract for the
|
|
156
|
+
whole site. Data scoping lives in actions and API routes; the client gates
|
|
157
|
+
private UI after the shell loads. See the `authentication` skill and
|
|
158
|
+
`guard:ssr-cache-shell` / `ssr-handler.spec.ts`.
|
|
159
|
+
|
|
150
160
|
## Human-in-the-Loop Approval for High-Consequence Actions
|
|
151
161
|
|
|
152
162
|
For a small set of outward-facing, hard-to-undo operations — sending an email, charging a card, deleting an account, posting publicly — auth and access control are necessary but not sufficient: you also do not want the **agent** to perform them autonomously. Set `needsApproval` on the `defineAction` so the agent cannot run the action without a human approving the specific call.
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"description": "Create, search, select, and export brand image and video assets from the Assets app.",
|
|
6
6
|
"hosted": {
|
|
7
7
|
"url": "https://assets.agent-native.com",
|
|
8
|
-
"mcpUrl": "https://assets.agent-native.com/
|
|
8
|
+
"mcpUrl": "https://assets.agent-native.com/mcp"
|
|
9
9
|
},
|
|
10
10
|
"mcp": {
|
|
11
11
|
"serverName": "agent-native-assets"
|
|
@@ -147,6 +147,16 @@ export default defineEventHandler(async (event) => {
|
|
|
147
147
|
|
|
148
148
|
- Never create unprotected routes that modify data.
|
|
149
149
|
|
|
150
|
+
**Exception — the SSR HTML/`.data` catch-all is deliberately session-blind.**
|
|
151
|
+
The rule above is for routes that read or mutate user data. The SSR page
|
|
152
|
+
render and React Router `.data` route are different: they serve one
|
|
153
|
+
impersonal, public-cacheable shell to every visitor by design, and loaders on
|
|
154
|
+
that path render no user data. Do not "fix" this by adding `getSession`,
|
|
155
|
+
`private`, or `no-store` to it — that regresses the CDN cache contract for the
|
|
156
|
+
whole site. Data scoping lives in actions and API routes; the client gates
|
|
157
|
+
private UI after the shell loads. See the `authentication` skill and
|
|
158
|
+
`guard:ssr-cache-shell` / `ssr-handler.spec.ts`.
|
|
159
|
+
|
|
150
160
|
## Human-in-the-Loop Approval for High-Consequence Actions
|
|
151
161
|
|
|
152
162
|
For a small set of outward-facing, hard-to-undo operations — sending an email, charging a card, deleting an account, posting publicly — auth and access control are necessary but not sufficient: you also do not want the **agent** to perform them autonomously. Set `needsApproval` on the `defineAction` so the agent cannot run the action without a human approving the specific call.
|
|
@@ -147,6 +147,16 @@ export default defineEventHandler(async (event) => {
|
|
|
147
147
|
|
|
148
148
|
- Never create unprotected routes that modify data.
|
|
149
149
|
|
|
150
|
+
**Exception — the SSR HTML/`.data` catch-all is deliberately session-blind.**
|
|
151
|
+
The rule above is for routes that read or mutate user data. The SSR page
|
|
152
|
+
render and React Router `.data` route are different: they serve one
|
|
153
|
+
impersonal, public-cacheable shell to every visitor by design, and loaders on
|
|
154
|
+
that path render no user data. Do not "fix" this by adding `getSession`,
|
|
155
|
+
`private`, or `no-store` to it — that regresses the CDN cache contract for the
|
|
156
|
+
whole site. Data scoping lives in actions and API routes; the client gates
|
|
157
|
+
private UI after the shell loads. See the `authentication` skill and
|
|
158
|
+
`guard:ssr-cache-shell` / `ssr-handler.spec.ts`.
|
|
159
|
+
|
|
150
160
|
## Human-in-the-Loop Approval for High-Consequence Actions
|
|
151
161
|
|
|
152
162
|
For a small set of outward-facing, hard-to-undo operations — sending an email, charging a card, deleting an account, posting publicly — auth and access control are necessary but not sufficient: you also do not want the **agent** to perform them autonomously. Set `needsApproval` on the `defineAction` so the agent cannot run the action without a human approving the specific call.
|
|
@@ -67,7 +67,8 @@ Detailed event, availability, booking, storage, and UI rules live in
|
|
|
67
67
|
- Use `get-attendee-timezones` / `set-attendee-timezone` to read or save
|
|
68
68
|
per-guest IANA timezone overrides (`attendee-timezones` user setting). The UI
|
|
69
69
|
shows each guest's local event-start time when a timezone is known (self from
|
|
70
|
-
the
|
|
70
|
+
the browser zone; others from `attendee.timeZone` or the override map, with
|
|
71
|
+
the event zone as a fallback for the organizer).
|
|
71
72
|
- Use `rsvp-event` for invitation responses. Pass `note` when the user wants a
|
|
72
73
|
visible RSVP comment on a declined or tentative response; pass an empty note to
|
|
73
74
|
clear an existing RSVP comment.
|
|
@@ -11,7 +11,6 @@ import {
|
|
|
11
11
|
IconMapPin,
|
|
12
12
|
IconUser,
|
|
13
13
|
IconVideo,
|
|
14
|
-
IconGlobe,
|
|
15
14
|
IconRefresh,
|
|
16
15
|
IconBell,
|
|
17
16
|
IconChevronRight,
|
|
@@ -86,7 +85,6 @@ import {
|
|
|
86
85
|
dateTimeInTimezoneToIso,
|
|
87
86
|
formatRecurrenceText,
|
|
88
87
|
formatReminderText,
|
|
89
|
-
formatTimezoneLabel,
|
|
90
88
|
getEventEndValidationMessage,
|
|
91
89
|
getLocalTimezone,
|
|
92
90
|
getRecurrencePreset,
|
|
@@ -1274,17 +1272,6 @@ export function EventDetailPopover({
|
|
|
1274
1272
|
? t("eventForm.loadingRepeat")
|
|
1275
1273
|
: formatRecurrenceText(recurrenceRules) ||
|
|
1276
1274
|
(isRecurringEvent ? t("eventForm.repeats") : null);
|
|
1277
|
-
// Show the browser's local timezone offset (this is what the user sees times in)
|
|
1278
|
-
const localOffsetMinutes = -new Date().getTimezoneOffset();
|
|
1279
|
-
const localOffsetSign = localOffsetMinutes >= 0 ? "+" : "-";
|
|
1280
|
-
const localOffsetH = Math.floor(Math.abs(localOffsetMinutes) / 60);
|
|
1281
|
-
const localOffsetM = Math.abs(localOffsetMinutes) % 60;
|
|
1282
|
-
const tzLabel = event.startTimeZone
|
|
1283
|
-
? formatTimezoneLabel(event.startTimeZone)
|
|
1284
|
-
: localOffsetM
|
|
1285
|
-
? `GMT${localOffsetSign}${localOffsetH}:${String(localOffsetM).padStart(2, "0")}`
|
|
1286
|
-
: `GMT${localOffsetSign}${localOffsetH}`;
|
|
1287
|
-
|
|
1288
1275
|
const handleOpenChange = useCallback(
|
|
1289
1276
|
(newOpen: boolean) => {
|
|
1290
1277
|
if (!newOpen && open) {
|
|
@@ -1726,12 +1713,6 @@ export function EventDetailPopover({
|
|
|
1726
1713
|
/>
|
|
1727
1714
|
)}
|
|
1728
1715
|
|
|
1729
|
-
{/* Timezone */}
|
|
1730
|
-
<div className="flex items-center gap-3 py-1.5">
|
|
1731
|
-
<IconGlobe className="h-4 w-4 shrink-0 text-muted-foreground" />
|
|
1732
|
-
<span className="text-sm text-muted-foreground">{tzLabel}</span>
|
|
1733
|
-
</div>
|
|
1734
|
-
|
|
1735
1716
|
{/* Recurrence */}
|
|
1736
1717
|
{editingField === "recurrence" ? (
|
|
1737
1718
|
<div className="flex items-start gap-3 py-1.5">
|