@agent-native/core 0.98.0 → 0.98.2
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 +32 -0
- package/corpus/core/docs/content/locales/ar-SA/pr-visual-recap.mdx +25 -1
- package/corpus/core/docs/content/locales/ar-SA/template-plan.mdx +1 -1
- package/corpus/core/docs/content/locales/de-DE/pr-visual-recap.mdx +25 -1
- package/corpus/core/docs/content/locales/de-DE/template-plan.mdx +1 -1
- package/corpus/core/docs/content/locales/es-ES/pr-visual-recap.mdx +25 -1
- package/corpus/core/docs/content/locales/es-ES/template-plan.mdx +1 -1
- package/corpus/core/docs/content/locales/fr-FR/pr-visual-recap.mdx +25 -1
- package/corpus/core/docs/content/locales/fr-FR/template-plan.mdx +1 -1
- package/corpus/core/docs/content/locales/hi-IN/pr-visual-recap.mdx +25 -1
- package/corpus/core/docs/content/locales/hi-IN/template-plan.mdx +1 -1
- package/corpus/core/docs/content/locales/ja-JP/pr-visual-recap.mdx +25 -1
- package/corpus/core/docs/content/locales/ja-JP/template-plan.mdx +1 -1
- package/corpus/core/docs/content/locales/ko-KR/pr-visual-recap.mdx +25 -1
- package/corpus/core/docs/content/locales/ko-KR/template-plan.mdx +1 -1
- package/corpus/core/docs/content/locales/pt-BR/pr-visual-recap.mdx +25 -1
- package/corpus/core/docs/content/locales/pt-BR/template-plan.mdx +1 -1
- package/corpus/core/docs/content/locales/zh-CN/pr-visual-recap.mdx +25 -1
- package/corpus/core/docs/content/locales/zh-CN/template-plan.mdx +1 -1
- package/corpus/core/docs/content/locales/zh-TW/pr-visual-recap.mdx +25 -1
- package/corpus/core/docs/content/locales/zh-TW/template-plan.mdx +1 -1
- package/corpus/core/docs/content/pr-visual-recap.mdx +50 -1
- package/corpus/core/docs/content/template-plan.mdx +1 -1
- package/corpus/core/package.json +2 -2
- package/corpus/core/src/action-change-marker.ts +8 -1
- package/corpus/core/src/changelog/parse.ts +8 -3
- package/corpus/core/src/cli/plan-local.ts +43 -11
- package/corpus/core/src/cli/pr-visual-recap-workflow.ts +2 -9
- package/corpus/core/src/cli/recap.ts +356 -4
- package/corpus/core/src/cli/skills-content/local-files.ts +17 -12
- package/corpus/core/src/client/AgentPanel.tsx +2 -3
- package/corpus/core/src/client/AssistantChat.tsx +83 -39
- package/corpus/core/src/client/analytics.ts +125 -14
- package/corpus/core/src/client/blocks/library/wireframe-kit.tsx +16 -2
- package/corpus/core/src/client/chat-model-groups.ts +28 -0
- package/corpus/core/src/client/composer/RealtimeVoiceMode.tsx +442 -85
- package/corpus/core/src/client/composer/TiptapComposer.tsx +46 -29
- package/corpus/core/src/client/composer/VoiceButton.tsx +2 -1
- package/corpus/core/src/client/composer/index.ts +5 -0
- package/corpus/core/src/client/composer/useRealtimeVoiceMode.tsx +1206 -67
- package/corpus/core/src/client/index.ts +10 -0
- package/corpus/core/src/client/progress/RunsTray.tsx +13 -1
- package/corpus/core/src/client/session-replay.ts +10 -0
- package/corpus/core/src/client/settings/DemoModeSection.tsx +4 -28
- package/corpus/core/src/client/settings/SecretsSection.tsx +387 -266
- package/corpus/core/src/client/settings/SettingsPanel.tsx +117 -38
- package/corpus/core/src/client/url-scrub.ts +13 -0
- package/corpus/core/src/client/use-action.ts +12 -0
- package/corpus/core/src/client/use-agent-chat-home-handoff.ts +8 -1
- package/corpus/core/src/client/use-agent-engine-configured.ts +17 -3
- package/corpus/core/src/client/use-db-sync.ts +84 -34
- package/corpus/core/src/client/use-demo-mode-status.ts +44 -0
- package/corpus/core/src/client/use-pausing-interval.ts +14 -4
- package/corpus/core/src/integrations/scope-store.ts +1 -1
- package/corpus/core/src/integrations/usage-budget-store.ts +1 -1
- package/corpus/core/src/localization/default-messages.ts +44 -1
- package/corpus/core/src/mcp-client/workspace-servers.ts +4 -4
- package/corpus/core/src/secrets/crypto.ts +28 -8
- package/corpus/core/src/server/action-change.ts +5 -1
- package/corpus/core/src/server/action-routes.ts +8 -0
- package/corpus/core/src/server/poll.ts +1 -0
- package/corpus/core/src/server/realtime-voice.ts +299 -13
- package/corpus/core/src/styles/agent-native.css +2 -2
- package/corpus/core/src/templates/default/.agents/skills/real-time-sync/SKILL.md +2 -2
- package/corpus/core/src/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +2 -2
- package/corpus/core/src/templates/workspace-core/.agents/skills/secrets/SKILL.md +7 -3
- package/corpus/core/src/templates/workspace-core/.agents/skills/voice-transcription/SKILL.md +39 -9
- package/corpus/core/src/vite/client.ts +9 -1
- package/corpus/templates/analytics/.agents/skills/real-time-sync/SKILL.md +2 -2
- package/corpus/templates/analytics/.agents/skills/session-replay/SKILL.md +10 -5
- package/corpus/templates/analytics/AGENTS.md +17 -13
- package/corpus/templates/analytics/actions/navigate.ts +59 -5
- package/corpus/templates/analytics/actions/view-screen.ts +3 -6
- package/corpus/templates/analytics/app/components/ProviderCorpusJobNotifier.tsx +20 -3
- package/corpus/templates/analytics/app/components/dashboard/SqlChart.tsx +20 -5
- package/corpus/templates/analytics/app/components/layout/Header.tsx +1 -1
- package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +21 -6
- package/corpus/templates/analytics/app/global.css +19 -20
- package/corpus/templates/analytics/app/lib/demo-chart-trend.ts +156 -0
- package/corpus/templates/analytics/app/lib/provider-corpus-job-sync.ts +26 -0
- package/corpus/templates/analytics/app/pages/Settings.tsx +35 -341
- package/corpus/templates/analytics/app/pages/monitoring/ErrorsPanel.tsx +38 -7
- package/corpus/templates/analytics/app/pages/monitoring/MonitoringPage.tsx +1 -1
- package/corpus/templates/analytics/app/pages/monitoring/errors/i18n.ts +3 -0
- package/corpus/templates/analytics/app/pages/sessions/SessionDetailPage.tsx +333 -272
- package/corpus/templates/analytics/app/pages/sessions/SessionDevToolsPanel.tsx +72 -17
- package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +297 -108
- package/corpus/templates/analytics/app/root.tsx +28 -8
- package/corpus/templates/analytics/changelog/2026-06-24-first-party-signup-and-pageview-panels-now-honor-dashboard-filters.md +2 -1
- package/corpus/templates/analytics/changelog/2026-06-25-referrer-dashboard-panels-show-external-domains.md +2 -1
- package/corpus/templates/analytics/changelog/2026-07-06-mobile-chat-header-is-more-compact-and-the-menu-button-opens-navigation.md +1 -0
- package/corpus/templates/analytics/changelog/2026-07-08-dashboard-history-and-chat-context.md +1 -0
- package/corpus/templates/analytics/changelog/2026-07-08-settings-are-cleaner-searchable-and-alerts-have-their-own-tab.md +1 -0
- package/corpus/templates/analytics/changelog/2026-07-08-sidebar-sections-stay-collapsed-until-opened.md +1 -0
- package/corpus/templates/analytics/changelog/2026-07-11-analytics-no-longer-repeatedly-restarts-background-requests-.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-11-analytics-only-asks-for-replay-storage-when-you-enable-sessi.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-11-charts-now-show-their-loading-skeleton-while-refreshing.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-11-realtime-voice-now-shows-a-clear-connection-indicator-comple.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-11-replay-event-counts-stay-hidden-until-recordings-finish-load.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-11-replay-storage-key-mismatches-show-actionable-setup-guidance.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-11-replay-timelines-group-continuous-scrolling-and-dev-tools-co.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-11-session-filters-now-stay-compact-in-a-settings-menu-at-mediu.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-11-session-replay-console-errors-now-link-to-matching-issues-or.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-11-session-replays-load-large-recordings-faster-and-surface-fai.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-11-session-replays-preserve-recorded-styles-and-viewport-layout.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-11-session-replays-stay-centered-instead-of-clipping-wide-recor.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-12-daily-dashboard-emails-reliably-include-the-complete-dashboa.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-12-demo-mode-charts-trend-upward.md +6 -0
- package/corpus/templates/analytics/package.json +1 -1
- package/corpus/templates/analytics/seeds/dashboards/agent-native-templates-first-party.json +1 -303
- package/corpus/templates/analytics/server/handlers/session-replay.ts +57 -0
- package/corpus/templates/analytics/server/jobs/dashboard-report.ts +2 -0
- package/corpus/templates/analytics/server/lib/dashboard-catalog.ts +1 -1
- package/corpus/templates/analytics/server/lib/dashboard-report.ts +17 -33
- package/corpus/templates/analytics/server/lib/demo-dashboards.ts +16 -3
- package/corpus/templates/analytics/server/lib/session-replay-agent-context.ts +12 -0
- package/corpus/templates/analytics/server/lib/session-replay.ts +208 -2
- package/corpus/templates/analytics/server/plugins/onboarding.ts +7 -79
- package/corpus/templates/analytics/server/routes/api/session-replay/recordings/[recordingId]/chunks.get.ts +1 -0
- package/corpus/templates/assets/.agents/skills/real-time-sync/SKILL.md +2 -2
- package/corpus/templates/assets/app/global.css +4 -4
- package/corpus/templates/assets/app/routes/brand-kits.$id.tsx +0 -1
- package/corpus/templates/assets/app/routes/library.tsx +0 -1
- package/corpus/templates/brain/.agents/skills/real-time-sync/SKILL.md +2 -2
- package/corpus/templates/brain/app/global.css +5 -5
- package/corpus/templates/brain/app/root.tsx +0 -3
- package/corpus/templates/calendar/.agents/skills/real-time-sync/SKILL.md +2 -2
- package/corpus/templates/calendar/app/root.tsx +1 -0
- package/corpus/templates/chat/.agents/skills/real-time-sync/SKILL.md +2 -2
- package/corpus/templates/clips/app/components/player/video-player.tsx +5 -1
- package/corpus/templates/clips/app/hooks/use-auto-title.ts +74 -8
- package/corpus/templates/clips/app/hooks/use-library.ts +12 -25
- package/corpus/templates/clips/app/routes/_app.settings._index.tsx +20 -22
- package/corpus/templates/clips/changelog/2026-07-11-clips-no-longer-stay-stuck-on-preparing-clip-when-they-are-r.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-11-generated-titles-no-longer-cause-continuous-background-refreshes.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-11-s3-storage-setup-stays-collapsed-until-you-choose-it-as-the-.md +6 -0
- package/corpus/templates/content/.agents/skills/real-time-sync/SKILL.md +2 -2
- package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +2 -2
- package/corpus/templates/content/app/hooks/use-comments.ts +0 -1
- package/corpus/templates/content/changelog/2026-07-11-comments-now-update-from-live-collaboration-events-without-c.md +6 -0
- package/corpus/templates/content/changelog/2026-07-12-the-left-sidebar-stays-fixed-horizontally-while-scrolling-on.md +6 -0
- package/corpus/templates/design/app/components/layout/Header.tsx +1 -1
- package/corpus/templates/forms/.agents/skills/real-time-sync/SKILL.md +2 -2
- package/corpus/templates/macros/app/components/layout/AppLayout.tsx +1 -2
- package/corpus/templates/macros/app/root.tsx +0 -3
- package/corpus/templates/mail/.agents/skills/real-time-sync/SKILL.md +2 -2
- package/corpus/templates/mail/app/hooks/use-compose-state.ts +1 -0
- package/corpus/templates/mail/app/root.tsx +1 -12
- package/corpus/templates/plan/.agents/skills/real-time-sync/SKILL.md +2 -2
- package/corpus/templates/plan/.agents/skills/visual-plan/references/local-files.md +17 -12
- package/corpus/templates/plan/.agents/skills/visual-recap/references/local-files.md +17 -12
- package/corpus/templates/plan/actions/validate-local-plan-source.ts +4 -4
- package/corpus/templates/plan/app/components/layout/Sidebar.tsx +2 -1
- package/corpus/templates/plan/app/hooks/use-navigation-state.ts +5 -2
- package/corpus/templates/plan/app/hooks/use-plans.ts +6 -13
- package/corpus/templates/plan/app/lib/plan-local-bridge.ts +41 -0
- package/corpus/templates/plan/app/lib/plan-tracking.ts +3 -0
- package/corpus/templates/plan/app/pages/PlansPage.tsx +14 -36
- package/corpus/templates/plan/app/root.tsx +13 -3
- package/corpus/templates/plan/changelog/2026-07-11-plan-refreshes-only-when-content-changes.md +6 -0
- package/corpus/templates/plan/changelog/2026-07-12-local-plan-source-now-stays-on-device.md +6 -0
- package/corpus/templates/slides/app/components/comments/SlideCommentsPanel.tsx +4 -1
- package/corpus/templates/slides/app/components/editor/EditorToolbar.tsx +1 -1
- package/corpus/templates/slides/app/components/layout/Header.tsx +1 -1
- package/corpus/templates/slides/app/context/DeckContext.tsx +1 -0
- package/corpus/templates/slides/app/hooks/use-slide-comments.ts +7 -31
- package/corpus/templates/slides/changelog/2026-07-11-comments-now-update-from-live-collaboration-events-without-c.md +6 -0
- package/dist/action-change-marker.d.ts +1 -0
- package/dist/action-change-marker.d.ts.map +1 -1
- package/dist/action-change-marker.js +7 -1
- package/dist/action-change-marker.js.map +1 -1
- package/dist/changelog/parse.d.ts +4 -2
- package/dist/changelog/parse.d.ts.map +1 -1
- package/dist/changelog/parse.js +5 -3
- package/dist/changelog/parse.js.map +1 -1
- package/dist/cli/plan-local.d.ts +6 -6
- package/dist/cli/plan-local.d.ts.map +1 -1
- package/dist/cli/plan-local.js +36 -7
- package/dist/cli/plan-local.js.map +1 -1
- package/dist/cli/pr-visual-recap-workflow.d.ts +2 -8
- package/dist/cli/pr-visual-recap-workflow.d.ts.map +1 -1
- package/dist/cli/pr-visual-recap-workflow.js +2 -8
- package/dist/cli/pr-visual-recap-workflow.js.map +1 -1
- package/dist/cli/recap.d.ts +22 -1
- package/dist/cli/recap.d.ts.map +1 -1
- package/dist/cli/recap.js +286 -2
- package/dist/cli/recap.js.map +1 -1
- package/dist/cli/skills-content/local-files.d.ts +1 -1
- package/dist/cli/skills-content/local-files.d.ts.map +1 -1
- package/dist/cli/skills-content/local-files.js +17 -12
- package/dist/cli/skills-content/local-files.js.map +1 -1
- package/dist/client/AgentPanel.d.ts.map +1 -1
- package/dist/client/AgentPanel.js +2 -3
- package/dist/client/AgentPanel.js.map +1 -1
- package/dist/client/AssistantChat.d.ts +7 -0
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +62 -40
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/analytics.d.ts +8 -0
- package/dist/client/analytics.d.ts.map +1 -1
- package/dist/client/analytics.js +103 -13
- package/dist/client/analytics.js.map +1 -1
- package/dist/client/blocks/library/wireframe-kit.d.ts +2 -0
- package/dist/client/blocks/library/wireframe-kit.d.ts.map +1 -1
- package/dist/client/blocks/library/wireframe-kit.js +9 -2
- package/dist/client/blocks/library/wireframe-kit.js.map +1 -1
- package/dist/client/chat-model-groups.d.ts.map +1 -1
- package/dist/client/chat-model-groups.js +24 -0
- package/dist/client/chat-model-groups.js.map +1 -1
- package/dist/client/composer/RealtimeVoiceMode.d.ts +40 -4
- package/dist/client/composer/RealtimeVoiceMode.d.ts.map +1 -1
- package/dist/client/composer/RealtimeVoiceMode.js +172 -42
- package/dist/client/composer/RealtimeVoiceMode.js.map +1 -1
- package/dist/client/composer/TiptapComposer.d.ts +4 -0
- package/dist/client/composer/TiptapComposer.d.ts.map +1 -1
- package/dist/client/composer/TiptapComposer.js +47 -29
- package/dist/client/composer/TiptapComposer.js.map +1 -1
- package/dist/client/composer/VoiceButton.d.ts.map +1 -1
- package/dist/client/composer/VoiceButton.js +2 -2
- package/dist/client/composer/VoiceButton.js.map +1 -1
- package/dist/client/composer/index.d.ts +2 -2
- package/dist/client/composer/index.d.ts.map +1 -1
- package/dist/client/composer/index.js +1 -1
- package/dist/client/composer/index.js.map +1 -1
- package/dist/client/composer/useRealtimeVoiceMode.d.ts +100 -3
- package/dist/client/composer/useRealtimeVoiceMode.d.ts.map +1 -1
- package/dist/client/composer/useRealtimeVoiceMode.js +952 -51
- package/dist/client/composer/useRealtimeVoiceMode.js.map +1 -1
- package/dist/client/index.d.ts +3 -2
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +3 -2
- package/dist/client/index.js.map +1 -1
- package/dist/client/progress/RunsTray.d.ts.map +1 -1
- package/dist/client/progress/RunsTray.js +10 -1
- package/dist/client/progress/RunsTray.js.map +1 -1
- package/dist/client/session-replay.d.ts +2 -0
- package/dist/client/session-replay.d.ts.map +1 -1
- package/dist/client/session-replay.js +7 -0
- package/dist/client/session-replay.js.map +1 -1
- package/dist/client/settings/DemoModeSection.d.ts.map +1 -1
- package/dist/client/settings/DemoModeSection.js +4 -23
- package/dist/client/settings/DemoModeSection.js.map +1 -1
- package/dist/client/settings/SecretsSection.d.ts +2 -3
- package/dist/client/settings/SecretsSection.d.ts.map +1 -1
- package/dist/client/settings/SecretsSection.js +46 -22
- package/dist/client/settings/SecretsSection.js.map +1 -1
- package/dist/client/settings/SettingsPanel.d.ts +9 -0
- package/dist/client/settings/SettingsPanel.d.ts.map +1 -1
- package/dist/client/settings/SettingsPanel.js +46 -12
- package/dist/client/settings/SettingsPanel.js.map +1 -1
- package/dist/client/url-scrub.d.ts.map +1 -1
- package/dist/client/url-scrub.js +14 -0
- package/dist/client/url-scrub.js.map +1 -1
- package/dist/client/use-action.d.ts +2 -0
- package/dist/client/use-action.d.ts.map +1 -1
- package/dist/client/use-action.js +10 -0
- package/dist/client/use-action.js.map +1 -1
- package/dist/client/use-agent-chat-home-handoff.d.ts +2 -0
- package/dist/client/use-agent-chat-home-handoff.d.ts.map +1 -1
- package/dist/client/use-agent-chat-home-handoff.js +7 -1
- package/dist/client/use-agent-chat-home-handoff.js.map +1 -1
- package/dist/client/use-agent-engine-configured.d.ts.map +1 -1
- package/dist/client/use-agent-engine-configured.js +17 -3
- package/dist/client/use-agent-engine-configured.js.map +1 -1
- package/dist/client/use-db-sync.d.ts +8 -2
- package/dist/client/use-db-sync.d.ts.map +1 -1
- package/dist/client/use-db-sync.js +57 -32
- package/dist/client/use-db-sync.js.map +1 -1
- package/dist/client/use-demo-mode-status.d.ts +12 -0
- package/dist/client/use-demo-mode-status.d.ts.map +1 -0
- package/dist/client/use-demo-mode-status.js +30 -0
- package/dist/client/use-demo-mode-status.js.map +1 -0
- package/dist/client/use-pausing-interval.d.ts.map +1 -1
- package/dist/client/use-pausing-interval.js +16 -4
- package/dist/client/use-pausing-interval.js.map +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/integrations/scope-store.js +1 -1
- package/dist/integrations/scope-store.js.map +1 -1
- package/dist/integrations/usage-budget-store.js +1 -1
- package/dist/integrations/usage-budget-store.js.map +1 -1
- package/dist/localization/default-messages.d.ts +41 -1
- package/dist/localization/default-messages.d.ts.map +1 -1
- package/dist/localization/default-messages.js +41 -1
- package/dist/localization/default-messages.js.map +1 -1
- package/dist/mcp-client/workspace-servers.js +4 -4
- package/dist/mcp-client/workspace-servers.js.map +1 -1
- package/dist/notifications/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/crypto.d.ts +7 -6
- package/dist/secrets/crypto.d.ts.map +1 -1
- package/dist/secrets/crypto.js +30 -11
- package/dist/secrets/crypto.js.map +1 -1
- package/dist/server/action-change.d.ts +1 -0
- package/dist/server/action-change.d.ts.map +1 -1
- package/dist/server/action-change.js +4 -1
- package/dist/server/action-change.js.map +1 -1
- package/dist/server/action-routes.d.ts.map +1 -1
- package/dist/server/action-routes.js +5 -0
- package/dist/server/action-routes.js.map +1 -1
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/poll.d.ts.map +1 -1
- package/dist/server/poll.js +1 -0
- package/dist/server/poll.js.map +1 -1
- package/dist/server/realtime-voice.d.ts +7 -0
- package/dist/server/realtime-voice.d.ts.map +1 -1
- package/dist/server/realtime-voice.js +222 -12
- package/dist/server/realtime-voice.js.map +1 -1
- package/dist/styles/agent-native.css +2 -2
- package/dist/templates/default/.agents/skills/real-time-sync/SKILL.md +2 -2
- package/dist/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +2 -2
- package/dist/templates/workspace-core/.agents/skills/secrets/SKILL.md +7 -3
- package/dist/templates/workspace-core/.agents/skills/voice-transcription/SKILL.md +39 -9
- package/dist/vite/client.d.ts.map +1 -1
- package/dist/vite/client.js +6 -1
- package/dist/vite/client.js.map +1 -1
- package/docs/content/locales/ar-SA/pr-visual-recap.mdx +25 -1
- package/docs/content/locales/ar-SA/template-plan.mdx +1 -1
- package/docs/content/locales/de-DE/pr-visual-recap.mdx +25 -1
- package/docs/content/locales/de-DE/template-plan.mdx +1 -1
- package/docs/content/locales/es-ES/pr-visual-recap.mdx +25 -1
- package/docs/content/locales/es-ES/template-plan.mdx +1 -1
- package/docs/content/locales/fr-FR/pr-visual-recap.mdx +25 -1
- package/docs/content/locales/fr-FR/template-plan.mdx +1 -1
- package/docs/content/locales/hi-IN/pr-visual-recap.mdx +25 -1
- package/docs/content/locales/hi-IN/template-plan.mdx +1 -1
- package/docs/content/locales/ja-JP/pr-visual-recap.mdx +25 -1
- package/docs/content/locales/ja-JP/template-plan.mdx +1 -1
- package/docs/content/locales/ko-KR/pr-visual-recap.mdx +25 -1
- package/docs/content/locales/ko-KR/template-plan.mdx +1 -1
- package/docs/content/locales/pt-BR/pr-visual-recap.mdx +25 -1
- package/docs/content/locales/pt-BR/template-plan.mdx +1 -1
- package/docs/content/locales/zh-CN/pr-visual-recap.mdx +25 -1
- package/docs/content/locales/zh-CN/template-plan.mdx +1 -1
- package/docs/content/locales/zh-TW/pr-visual-recap.mdx +25 -1
- package/docs/content/locales/zh-TW/template-plan.mdx +1 -1
- package/docs/content/pr-visual-recap.mdx +50 -1
- package/docs/content/template-plan.mdx +1 -1
- package/package.json +2 -2
- package/src/templates/default/.agents/skills/real-time-sync/SKILL.md +2 -2
- package/src/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +2 -2
- package/src/templates/workspace-core/.agents/skills/secrets/SKILL.md +7 -3
- package/src/templates/workspace-core/.agents/skills/voice-transcription/SKILL.md +39 -9
|
@@ -103,6 +103,8 @@ export const PR_VISUAL_RECAP_SETUP: string[] = [
|
|
|
103
103
|
" VISUAL_RECAP_API_KEY (secret) + VISUAL_RECAP_AGENT=openai-compatible + VISUAL_RECAP_BASE_URL (variable) — use DeepSeek, Kimi, or any OpenAI-compatible API",
|
|
104
104
|
" VISUAL_RECAP_MODEL (variable, required for openai-compatible) — provider model id; optional override for Claude/Codex",
|
|
105
105
|
" VISUAL_RECAP_REASONING (variable) — reasoning depth (none|minimal|low|medium|high|xhigh; Codex only)",
|
|
106
|
+
' VISUAL_RECAP_RUNS_ON (variable) — JSON hosted label or self-hosted label array; defaults to "ubuntu-latest"',
|
|
107
|
+
" VISUAL_RECAP_GATE_RUNS_ON (variable) — trusted same-repo authors only; plain single gate label; defaults to ubuntu-latest",
|
|
106
108
|
" VISUAL_RECAP_SKILL_SOURCE=repo (variable) — pin CI to the repo-local visual-recap skill instead of latest bundled guidance",
|
|
107
109
|
" VISUAL_RECAP_SECRET_SCAN=off|high-confidence|strict (variable) — default high-confidence; strict restores generic TOKEN/SECRET assignment suppression",
|
|
108
110
|
" PLAN_RECAP_APP_URL (secret) — only when self-hosting the plan app (defaults to https://plan.agent-native.com)",
|
|
@@ -170,12 +172,22 @@ export function buildReusableCallerWorkflow(
|
|
|
170
172
|
ref?: string;
|
|
171
173
|
agent?: RecapAgentValue;
|
|
172
174
|
model?: string;
|
|
175
|
+
runsOn?: string;
|
|
176
|
+
gateRunsOn?: string;
|
|
173
177
|
} = {},
|
|
174
178
|
): string {
|
|
175
179
|
const ref = (options.ref ?? "main").replace(/^@/, "");
|
|
176
180
|
const agentValue =
|
|
177
181
|
options.agent ?? "${{ vars.VISUAL_RECAP_AGENT || 'claude' }}";
|
|
178
182
|
const modelValue = options.model ?? "${{ vars.VISUAL_RECAP_MODEL || '' }}";
|
|
183
|
+
const runsOnValue =
|
|
184
|
+
options.runsOn === undefined
|
|
185
|
+
? "${{ vars.VISUAL_RECAP_RUNS_ON || '\"ubuntu-latest\"' }}"
|
|
186
|
+
: JSON.stringify(options.runsOn);
|
|
187
|
+
const gateRunsOnValue =
|
|
188
|
+
options.gateRunsOn === undefined
|
|
189
|
+
? "${{ vars.VISUAL_RECAP_GATE_RUNS_ON || 'ubuntu-latest' }}"
|
|
190
|
+
: JSON.stringify(options.gateRunsOn);
|
|
179
191
|
return (
|
|
180
192
|
`name: PR Visual Recap\n` +
|
|
181
193
|
`\n` +
|
|
@@ -210,6 +222,8 @@ export function buildReusableCallerWorkflow(
|
|
|
210
222
|
` reasoning: \${{ vars.VISUAL_RECAP_REASONING || '' }}\n` +
|
|
211
223
|
` skill-source: \${{ vars.VISUAL_RECAP_SKILL_SOURCE || 'auto' }}\n` +
|
|
212
224
|
` secret-scan: \${{ vars.VISUAL_RECAP_SECRET_SCAN || 'high-confidence' }}\n` +
|
|
225
|
+
` runs-on: ${runsOnValue}\n` +
|
|
226
|
+
` gate-runs-on: ${gateRunsOnValue}\n` +
|
|
213
227
|
` # cli-version: "latest" # pin to a specific @agent-native/core version\n` +
|
|
214
228
|
``
|
|
215
229
|
);
|
|
@@ -226,6 +240,8 @@ export function writePrVisualRecapReusableCallerWorkflow(
|
|
|
226
240
|
ref?: string;
|
|
227
241
|
agent?: RecapAgentValue;
|
|
228
242
|
model?: string;
|
|
243
|
+
runsOn?: string;
|
|
244
|
+
gateRunsOn?: string;
|
|
229
245
|
} = {},
|
|
230
246
|
): WriteWorkflowResult {
|
|
231
247
|
const dir = path.resolve(baseDir, ".github", "workflows");
|
|
@@ -236,6 +252,8 @@ export function writePrVisualRecapReusableCallerWorkflow(
|
|
|
236
252
|
ref: options.ref,
|
|
237
253
|
agent: options.agent,
|
|
238
254
|
model: options.model,
|
|
255
|
+
runsOn: options.runsOn,
|
|
256
|
+
gateRunsOn: options.gateRunsOn,
|
|
239
257
|
});
|
|
240
258
|
if (fs.existsSync(file)) {
|
|
241
259
|
const current = fs.readFileSync(file, "utf8");
|
|
@@ -414,6 +432,40 @@ function listGithubVariables(repo?: string): Map<string, string> | null {
|
|
|
414
432
|
}
|
|
415
433
|
}
|
|
416
434
|
|
|
435
|
+
function listGithubOrganizationVariables(
|
|
436
|
+
repo: string,
|
|
437
|
+
): Map<string, string> | null {
|
|
438
|
+
const result = gh([
|
|
439
|
+
"api",
|
|
440
|
+
"--paginate",
|
|
441
|
+
"--slurp",
|
|
442
|
+
`repos/${repo}/actions/organization-variables?per_page=30`,
|
|
443
|
+
]);
|
|
444
|
+
if (!result.ok) return null;
|
|
445
|
+
try {
|
|
446
|
+
const parsed = JSON.parse(result.stdout) as unknown;
|
|
447
|
+
const pages = Array.isArray(parsed) ? parsed : [parsed];
|
|
448
|
+
const out = new Map<string, string>();
|
|
449
|
+
for (const page of pages) {
|
|
450
|
+
if (!page || typeof page !== "object") continue;
|
|
451
|
+
const variables = (page as Record<string, unknown>).variables;
|
|
452
|
+
if (!Array.isArray(variables)) continue;
|
|
453
|
+
for (const variable of variables) {
|
|
454
|
+
if (!variable || typeof variable !== "object") continue;
|
|
455
|
+
const record = variable as Record<string, unknown>;
|
|
456
|
+
if (typeof record.name !== "string") continue;
|
|
457
|
+
out.set(
|
|
458
|
+
record.name,
|
|
459
|
+
typeof record.value === "string" ? record.value : "",
|
|
460
|
+
);
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
return out;
|
|
464
|
+
} catch {
|
|
465
|
+
return null;
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
|
|
417
469
|
function setGithubSecret(
|
|
418
470
|
name: string,
|
|
419
471
|
value: string | undefined,
|
|
@@ -440,6 +492,63 @@ function setGithubVariable(
|
|
|
440
492
|
return gh(args).ok ? "set" : "failed";
|
|
441
493
|
}
|
|
442
494
|
|
|
495
|
+
export interface RecapRunner {
|
|
496
|
+
name: string;
|
|
497
|
+
status: string;
|
|
498
|
+
labels: string[];
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
function listGithubRunners(repo: string): RecapRunner[] | null {
|
|
502
|
+
const result = gh([
|
|
503
|
+
"api",
|
|
504
|
+
"--paginate",
|
|
505
|
+
"--slurp",
|
|
506
|
+
`repos/${repo}/actions/runners?per_page=100`,
|
|
507
|
+
]);
|
|
508
|
+
if (!result.ok) return null;
|
|
509
|
+
try {
|
|
510
|
+
const parsed = JSON.parse(result.stdout) as unknown;
|
|
511
|
+
const pages = Array.isArray(parsed) ? parsed : [parsed];
|
|
512
|
+
const runners: RecapRunner[] = [];
|
|
513
|
+
for (const page of pages) {
|
|
514
|
+
if (!page || typeof page !== "object") continue;
|
|
515
|
+
const entries = (page as Record<string, unknown>).runners;
|
|
516
|
+
if (!Array.isArray(entries)) continue;
|
|
517
|
+
for (const entry of entries) {
|
|
518
|
+
if (!entry || typeof entry !== "object") continue;
|
|
519
|
+
const record = entry as Record<string, unknown>;
|
|
520
|
+
if (typeof record.name !== "string") continue;
|
|
521
|
+
const rawLabels = Array.isArray(record.labels) ? record.labels : [];
|
|
522
|
+
runners.push({
|
|
523
|
+
name: record.name,
|
|
524
|
+
status: typeof record.status === "string" ? record.status : "",
|
|
525
|
+
labels: rawLabels.flatMap((label) => {
|
|
526
|
+
if (typeof label === "string") return [label];
|
|
527
|
+
if (!label || typeof label !== "object") return [];
|
|
528
|
+
const name = (label as Record<string, unknown>).name;
|
|
529
|
+
return typeof name === "string" ? [name] : [];
|
|
530
|
+
}),
|
|
531
|
+
});
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
return runners;
|
|
535
|
+
} catch {
|
|
536
|
+
return null;
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
export function matchingRecapRunners(
|
|
541
|
+
runners: RecapRunner[],
|
|
542
|
+
requiredLabels: string[],
|
|
543
|
+
): RecapRunner[] {
|
|
544
|
+
const required = requiredLabels.map((label) => label.toLowerCase());
|
|
545
|
+
return runners.filter((runner) => {
|
|
546
|
+
if (runner.status.toLowerCase() !== "online") return false;
|
|
547
|
+
const labels = new Set(runner.labels.map((label) => label.toLowerCase()));
|
|
548
|
+
return required.every((label) => labels.has(label));
|
|
549
|
+
});
|
|
550
|
+
}
|
|
551
|
+
|
|
443
552
|
export interface RecapSetupPlan {
|
|
444
553
|
agent: RecapAgent;
|
|
445
554
|
appUrl: string;
|
|
@@ -454,7 +563,11 @@ export interface RecapSetupPlan {
|
|
|
454
563
|
}
|
|
455
564
|
|
|
456
565
|
export interface RecapVariableRequirement {
|
|
457
|
-
name:
|
|
566
|
+
name:
|
|
567
|
+
| "VISUAL_RECAP_BASE_URL"
|
|
568
|
+
| "VISUAL_RECAP_MODEL"
|
|
569
|
+
| "VISUAL_RECAP_RUNS_ON"
|
|
570
|
+
| "VISUAL_RECAP_GATE_RUNS_ON";
|
|
458
571
|
example: string;
|
|
459
572
|
}
|
|
460
573
|
|
|
@@ -471,6 +584,113 @@ const OPENAI_COMPATIBLE_VARIABLE_REQUIREMENTS = [
|
|
|
471
584
|
{ name: "VISUAL_RECAP_MODEL", example: "provider-model-id" },
|
|
472
585
|
] as const satisfies readonly RecapVariableRequirement[];
|
|
473
586
|
|
|
587
|
+
const RECAP_RUNS_ON_REQUIREMENT = {
|
|
588
|
+
name: "VISUAL_RECAP_RUNS_ON",
|
|
589
|
+
example: '["self-hosted","linux","x64","visual-recap"]',
|
|
590
|
+
} as const satisfies RecapVariableRequirement;
|
|
591
|
+
|
|
592
|
+
const RECAP_GATE_RUNS_ON_REQUIREMENT = {
|
|
593
|
+
name: "VISUAL_RECAP_GATE_RUNS_ON",
|
|
594
|
+
example: "visual-recap-gate",
|
|
595
|
+
} as const satisfies RecapVariableRequirement;
|
|
596
|
+
|
|
597
|
+
export interface RecapRunsOnConfig {
|
|
598
|
+
json: string;
|
|
599
|
+
labels: string[];
|
|
600
|
+
selfHosted: boolean;
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
/** Parse the JSON consumed by GitHub Actions `fromJSON(...)` for `runs-on`. */
|
|
604
|
+
export function parseRecapRunsOn(value: string): RecapRunsOnConfig {
|
|
605
|
+
let parsed: unknown;
|
|
606
|
+
try {
|
|
607
|
+
parsed = JSON.parse(value);
|
|
608
|
+
} catch {
|
|
609
|
+
throw new Error(
|
|
610
|
+
'VISUAL_RECAP_RUNS_ON must be valid JSON, such as "ubuntu-latest" or ["self-hosted","linux","x64"]',
|
|
611
|
+
);
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
if (typeof parsed === "string") {
|
|
615
|
+
if (!/^(?:ubuntu|windows|macos)-[A-Za-z0-9.-]+$/.test(parsed)) {
|
|
616
|
+
throw new Error(
|
|
617
|
+
"VISUAL_RECAP_RUNS_ON JSON strings must name a standard GitHub-hosted ubuntu-, windows-, or macos- runner",
|
|
618
|
+
);
|
|
619
|
+
}
|
|
620
|
+
return {
|
|
621
|
+
json: JSON.stringify(parsed),
|
|
622
|
+
labels: [parsed],
|
|
623
|
+
selfHosted: false,
|
|
624
|
+
};
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
if (!Array.isArray(parsed) || parsed.length === 0 || parsed.length > 20) {
|
|
628
|
+
throw new Error(
|
|
629
|
+
"VISUAL_RECAP_RUNS_ON must be a hosted runner JSON string or an array of 1-20 self-hosted labels",
|
|
630
|
+
);
|
|
631
|
+
}
|
|
632
|
+
if (
|
|
633
|
+
parsed.some(
|
|
634
|
+
(label) =>
|
|
635
|
+
typeof label !== "string" ||
|
|
636
|
+
label.length === 0 ||
|
|
637
|
+
label.length > 100 ||
|
|
638
|
+
/[\p{C}]/u.test(label),
|
|
639
|
+
)
|
|
640
|
+
) {
|
|
641
|
+
throw new Error(
|
|
642
|
+
"VISUAL_RECAP_RUNS_ON labels must be non-empty strings up to 100 characters without control characters",
|
|
643
|
+
);
|
|
644
|
+
}
|
|
645
|
+
const labels = parsed as string[];
|
|
646
|
+
if (!labels.includes("self-hosted")) {
|
|
647
|
+
throw new Error(
|
|
648
|
+
'VISUAL_RECAP_RUNS_ON label arrays must include the exact "self-hosted" label',
|
|
649
|
+
);
|
|
650
|
+
}
|
|
651
|
+
if (
|
|
652
|
+
new Set(labels.map((label) => label.toLowerCase())).size !== labels.length
|
|
653
|
+
) {
|
|
654
|
+
throw new Error("VISUAL_RECAP_RUNS_ON labels must be unique");
|
|
655
|
+
}
|
|
656
|
+
return { json: JSON.stringify(labels), labels, selfHosted: true };
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
/** Validate the plain label used directly by the gate job's `runs-on`. */
|
|
660
|
+
export function parseRecapGateRunsOn(value: string): string {
|
|
661
|
+
const label = value.trim();
|
|
662
|
+
if (!/^[A-Za-z0-9._-]{1,100}$/.test(label)) {
|
|
663
|
+
throw new Error(
|
|
664
|
+
"VISUAL_RECAP_GATE_RUNS_ON must be one plain runner label (1-100 letters, numbers, dots, underscores, or hyphens)",
|
|
665
|
+
);
|
|
666
|
+
}
|
|
667
|
+
return label;
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
function recapRunsOnProblem(value: string): RecapVariableProblem | null {
|
|
671
|
+
try {
|
|
672
|
+
parseRecapRunsOn(value);
|
|
673
|
+
return null;
|
|
674
|
+
} catch (error) {
|
|
675
|
+
return {
|
|
676
|
+
requirement: RECAP_RUNS_ON_REQUIREMENT,
|
|
677
|
+
reason: error instanceof Error ? error.message : String(error),
|
|
678
|
+
};
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
function recapGateRunsOnProblem(value: string): RecapVariableProblem | null {
|
|
683
|
+
try {
|
|
684
|
+
parseRecapGateRunsOn(value);
|
|
685
|
+
return null;
|
|
686
|
+
} catch (error) {
|
|
687
|
+
return {
|
|
688
|
+
requirement: RECAP_GATE_RUNS_ON_REQUIREMENT,
|
|
689
|
+
reason: error instanceof Error ? error.message : String(error),
|
|
690
|
+
};
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
|
|
474
694
|
const RECAP_MODEL_PATTERN = /^[a-zA-Z0-9._-]{1,80}$/;
|
|
475
695
|
const OPENAI_COMPATIBLE_RECAP_MODEL_PATTERN = /^[^\p{C}\p{Z}]{1,200}$/u;
|
|
476
696
|
|
|
@@ -517,6 +737,8 @@ export function buildRecapSetupPlan(input: {
|
|
|
517
737
|
appUrl?: string;
|
|
518
738
|
agent?: string;
|
|
519
739
|
repo?: string;
|
|
740
|
+
runsOn?: string;
|
|
741
|
+
gateRunsOn?: string;
|
|
520
742
|
env?: NodeJS.ProcessEnv;
|
|
521
743
|
}): RecapSetupPlan {
|
|
522
744
|
const env = input.env ?? process.env;
|
|
@@ -551,13 +773,28 @@ export function buildRecapSetupPlan(input: {
|
|
|
551
773
|
const baseUrl = envValue(env, "VISUAL_RECAP_BASE_URL");
|
|
552
774
|
if (baseUrl) variableValues.VISUAL_RECAP_BASE_URL = baseUrl;
|
|
553
775
|
}
|
|
554
|
-
const variableProblems =
|
|
776
|
+
const variableProblems: RecapVariableProblem[] =
|
|
555
777
|
agent === "openai-compatible"
|
|
556
778
|
? validateOpenAiCompatibleRecapVariables({
|
|
557
779
|
baseUrl: variableValues.VISUAL_RECAP_BASE_URL,
|
|
558
780
|
model: variableValues.VISUAL_RECAP_MODEL,
|
|
559
781
|
})
|
|
560
782
|
: [];
|
|
783
|
+
const runsOn = input.runsOn ?? envValue(env, "VISUAL_RECAP_RUNS_ON");
|
|
784
|
+
if (runsOn) {
|
|
785
|
+
const problem = recapRunsOnProblem(runsOn);
|
|
786
|
+
if (problem) variableProblems.push(problem);
|
|
787
|
+
else variableValues.VISUAL_RECAP_RUNS_ON = parseRecapRunsOn(runsOn).json;
|
|
788
|
+
}
|
|
789
|
+
const gateRunsOn =
|
|
790
|
+
input.gateRunsOn ?? envValue(env, "VISUAL_RECAP_GATE_RUNS_ON");
|
|
791
|
+
if (gateRunsOn) {
|
|
792
|
+
const problem = recapGateRunsOnProblem(gateRunsOn);
|
|
793
|
+
if (problem) variableProblems.push(problem);
|
|
794
|
+
else
|
|
795
|
+
variableValues.VISUAL_RECAP_GATE_RUNS_ON =
|
|
796
|
+
parseRecapGateRunsOn(gateRunsOn);
|
|
797
|
+
}
|
|
561
798
|
return {
|
|
562
799
|
agent,
|
|
563
800
|
appUrl,
|
|
@@ -596,7 +833,19 @@ function runSetup(args: Record<string, string | boolean>): void {
|
|
|
596
833
|
appUrl: optionalArg(args, "app-url"),
|
|
597
834
|
agent: optionalArg(args, "agent"),
|
|
598
835
|
repo,
|
|
836
|
+
runsOn: optionalArg(args, "runs-on"),
|
|
837
|
+
gateRunsOn: optionalArg(args, "gate-runs-on"),
|
|
599
838
|
});
|
|
839
|
+
const runnerProblem = plan.variableProblems.find(
|
|
840
|
+
(problem) =>
|
|
841
|
+
problem.requirement.name === "VISUAL_RECAP_RUNS_ON" ||
|
|
842
|
+
problem.requirement.name === "VISUAL_RECAP_GATE_RUNS_ON",
|
|
843
|
+
);
|
|
844
|
+
if (runnerProblem) {
|
|
845
|
+
process.stderr.write(`recap setup: ${runnerProblem.reason}.\n`);
|
|
846
|
+
process.exitCode = 1;
|
|
847
|
+
return;
|
|
848
|
+
}
|
|
600
849
|
const lines = [
|
|
601
850
|
reusable
|
|
602
851
|
? "PR Visual Recap setup (reusable workflow)"
|
|
@@ -616,6 +865,8 @@ function runSetup(args: Record<string, string | boolean>): void {
|
|
|
616
865
|
force,
|
|
617
866
|
ref: optionalArg(args, "ref") ?? "main",
|
|
618
867
|
agent: plan.agent !== "claude" ? plan.agent : undefined,
|
|
868
|
+
runsOn: plan.variableValues.VISUAL_RECAP_RUNS_ON,
|
|
869
|
+
gateRunsOn: plan.variableValues.VISUAL_RECAP_GATE_RUNS_ON,
|
|
619
870
|
});
|
|
620
871
|
if (result.status === "refused") {
|
|
621
872
|
process.stderr.write(`recap setup: ${result.message}\n`);
|
|
@@ -736,6 +987,12 @@ function runDoctor(args: Record<string, string | boolean>): void {
|
|
|
736
987
|
const baseDir = process.cwd();
|
|
737
988
|
const repo = resolveGithubRepo(optionalArg(args, "repo"));
|
|
738
989
|
const variables = listGithubVariables(repo);
|
|
990
|
+
if (variables && repo) {
|
|
991
|
+
const organizationVariables = listGithubOrganizationVariables(repo);
|
|
992
|
+
for (const [name, value] of organizationVariables ?? []) {
|
|
993
|
+
if (!variables.has(name)) variables.set(name, value);
|
|
994
|
+
}
|
|
995
|
+
}
|
|
739
996
|
const agent = normalizeRecapAgent(
|
|
740
997
|
optionalArg(args, "agent") ??
|
|
741
998
|
variables?.get("VISUAL_RECAP_AGENT") ??
|
|
@@ -843,6 +1100,90 @@ function runDoctor(args: Record<string, string | boolean>): void {
|
|
|
843
1100
|
);
|
|
844
1101
|
}
|
|
845
1102
|
}
|
|
1103
|
+
|
|
1104
|
+
const configuredRunsOn = variables.get("VISUAL_RECAP_RUNS_ON")?.trim();
|
|
1105
|
+
if (!configuredRunsOn) {
|
|
1106
|
+
lines.push('[ok] Recap runner: "ubuntu-latest".');
|
|
1107
|
+
} else {
|
|
1108
|
+
const problem = recapRunsOnProblem(configuredRunsOn);
|
|
1109
|
+
if (problem) {
|
|
1110
|
+
ok = false;
|
|
1111
|
+
lines.push(`[invalid] ${problem.reason}.`);
|
|
1112
|
+
lines.push(
|
|
1113
|
+
` Set it with: ${commandForMissingVariable(
|
|
1114
|
+
RECAP_RUNS_ON_REQUIREMENT.name,
|
|
1115
|
+
RECAP_RUNS_ON_REQUIREMENT.example,
|
|
1116
|
+
repo,
|
|
1117
|
+
)}`,
|
|
1118
|
+
);
|
|
1119
|
+
} else {
|
|
1120
|
+
const runsOn = parseRecapRunsOn(configuredRunsOn);
|
|
1121
|
+
lines.push(`[ok] Recap runner configuration: ${runsOn.json}.`);
|
|
1122
|
+
if (runsOn.selfHosted && repo) {
|
|
1123
|
+
const runners = listGithubRunners(repo);
|
|
1124
|
+
if (!runners) {
|
|
1125
|
+
lines.push(
|
|
1126
|
+
"[warn] Could not verify self-hosted runners with gh; repository Administration read access is required.",
|
|
1127
|
+
);
|
|
1128
|
+
} else {
|
|
1129
|
+
const matches = matchingRecapRunners(runners, runsOn.labels);
|
|
1130
|
+
if (matches.length === 0) {
|
|
1131
|
+
ok = false;
|
|
1132
|
+
lines.push(
|
|
1133
|
+
`[missing] No online self-hosted runner matches: ${runsOn.labels.join(", ")}.`,
|
|
1134
|
+
);
|
|
1135
|
+
} else {
|
|
1136
|
+
lines.push(
|
|
1137
|
+
`[ok] Matching online self-hosted runner: ${matches.map((runner) => runner.name).join(", ")}.`,
|
|
1138
|
+
);
|
|
1139
|
+
}
|
|
1140
|
+
}
|
|
1141
|
+
}
|
|
1142
|
+
}
|
|
1143
|
+
}
|
|
1144
|
+
|
|
1145
|
+
const configuredGateRunsOn =
|
|
1146
|
+
variables.get("VISUAL_RECAP_GATE_RUNS_ON")?.trim() || "ubuntu-latest";
|
|
1147
|
+
const gateProblem = recapGateRunsOnProblem(configuredGateRunsOn);
|
|
1148
|
+
if (gateProblem) {
|
|
1149
|
+
ok = false;
|
|
1150
|
+
lines.push(`[invalid] ${gateProblem.reason}.`);
|
|
1151
|
+
lines.push(
|
|
1152
|
+
` Set it with: ${commandForMissingVariable(
|
|
1153
|
+
RECAP_GATE_RUNS_ON_REQUIREMENT.name,
|
|
1154
|
+
RECAP_GATE_RUNS_ON_REQUIREMENT.example,
|
|
1155
|
+
repo,
|
|
1156
|
+
)}`,
|
|
1157
|
+
);
|
|
1158
|
+
} else {
|
|
1159
|
+
const gateLabel = parseRecapGateRunsOn(configuredGateRunsOn);
|
|
1160
|
+
lines.push(
|
|
1161
|
+
`[ok] Gate runner label for trusted same-repo authors: ${gateLabel}.`,
|
|
1162
|
+
);
|
|
1163
|
+
if (
|
|
1164
|
+
!/^(?:ubuntu|windows|macos)-[A-Za-z0-9.-]+$/.test(gateLabel) &&
|
|
1165
|
+
repo
|
|
1166
|
+
) {
|
|
1167
|
+
const runners = listGithubRunners(repo);
|
|
1168
|
+
if (!runners) {
|
|
1169
|
+
lines.push(
|
|
1170
|
+
"[warn] Could not verify the gate runner with gh; repository Administration read access is required.",
|
|
1171
|
+
);
|
|
1172
|
+
} else {
|
|
1173
|
+
const matches = matchingRecapRunners(runners, [gateLabel]);
|
|
1174
|
+
if (matches.length === 0) {
|
|
1175
|
+
ok = false;
|
|
1176
|
+
lines.push(
|
|
1177
|
+
`[missing] No online self-hosted gate runner matches: ${gateLabel}.`,
|
|
1178
|
+
);
|
|
1179
|
+
} else {
|
|
1180
|
+
lines.push(
|
|
1181
|
+
`[ok] Matching online gate runner: ${matches.map((runner) => runner.name).join(", ")}.`,
|
|
1182
|
+
);
|
|
1183
|
+
}
|
|
1184
|
+
}
|
|
1185
|
+
}
|
|
1186
|
+
}
|
|
846
1187
|
}
|
|
847
1188
|
|
|
848
1189
|
process.stdout.write(`${lines.join("\n")}\n`);
|
|
@@ -4466,7 +4807,7 @@ function runAgentSummary(args: Record<string, string | boolean>): void {
|
|
|
4466
4807
|
const HELP = `npx @agent-native/core@latest recap — PR visual recap helpers (used by the GitHub Action)
|
|
4467
4808
|
|
|
4468
4809
|
Usage:
|
|
4469
|
-
npx @agent-native/core@latest recap setup [--repo owner/name] [--agent claude|codex|openai-compatible] [--app-url <url>] [--skip-secrets] [--dry-run] [--force]
|
|
4810
|
+
npx @agent-native/core@latest recap setup [--repo owner/name] [--agent claude|codex|openai-compatible] [--app-url <url>] [--runs-on <json>] [--gate-runs-on <label>] [--skip-secrets] [--dry-run] [--force]
|
|
4470
4811
|
npx @agent-native/core@latest recap doctor [--repo owner/name] [--agent claude|codex|openai-compatible] [--app-url <url>]
|
|
4471
4812
|
npx @agent-native/core@latest recap collect-diff --base <baseSha> --head <headSha> [--out recap.diff] [--stat recap.stat]
|
|
4472
4813
|
npx @agent-native/core@latest recap block-reference [--app-url <url>] [--out recap-blocks.md]
|
|
@@ -4519,11 +4860,22 @@ Usage:
|
|
|
4519
4860
|
Write/refresh .github/workflows/pr-visual-recap.yml, then configure GitHub
|
|
4520
4861
|
Actions secrets and variables with gh when values are available from env or
|
|
4521
4862
|
the local Plans publish-token store. Missing values are printed as exact next
|
|
4522
|
-
commands; secret values are sent to gh through stdin, never argv.
|
|
4863
|
+
commands; secret values are sent to gh through stdin, never argv. Pass
|
|
4864
|
+
--runs-on '["self-hosted","linux","x64","visual-recap"]' to opt into a
|
|
4865
|
+
trusted self-hosted runner label set. In self-hosted-only repos, pass
|
|
4866
|
+
--gate-runs-on visual-recap-gate for a dedicated, preferably ephemeral,
|
|
4867
|
+
single-label gate runner. It is used only for trusted same-repo OWNER,
|
|
4868
|
+
MEMBER, or COLLABORATOR authors. The stock gate does not check out the PR
|
|
4869
|
+
tree; it evaluates workflow logic and PR metadata. Fork and untrusted PRs
|
|
4870
|
+
use GitHub-hosted ubuntu-latest instead, so they may remain unscheduled when
|
|
4871
|
+
a repository disables GitHub-hosted runners.
|
|
4523
4872
|
npx @agent-native/core@latest recap doctor
|
|
4524
4873
|
Check workflow presence/drift, local Plans publish-token availability, gh
|
|
4525
4874
|
repo access, and required GitHub Actions secrets and variables for the
|
|
4526
4875
|
selected backend, including provider-variable validity.
|
|
4876
|
+
Self-hosted runner JSON and the plain gate runner label are validated, and
|
|
4877
|
+
matching online runners are checked when the GitHub token has repository
|
|
4878
|
+
Administration read access.
|
|
4527
4879
|
`;
|
|
4528
4880
|
|
|
4529
4881
|
export async function runRecap(argv: string[]): Promise<void> {
|
|
@@ -36,9 +36,9 @@ The local-files contract:
|
|
|
36
36
|
— encode multiline code as JSON string attributes such as \`code={"const x =\\n y"}\`
|
|
37
37
|
(a static template literal is accepted only when it has no \`\${...}\`
|
|
38
38
|
interpolation). \`plan local check\` is a quick OFFLINE lint (a subset of the
|
|
39
|
-
renderer schema), so a green \`check\` does not guarantee the plan renders
|
|
40
|
-
\`plan local verify\`
|
|
41
|
-
|
|
39
|
+
renderer schema), so a green \`check\` does not guarantee the plan renders.
|
|
40
|
+
\`plan local verify\` also stays on-device: it uses the offline lint unless it
|
|
41
|
+
can reach a Plan renderer on an explicit loopback \`--app-url\`.
|
|
42
42
|
- **Write a local MDX folder.** Use \`plans/<slug>/\` to check the artifact into the
|
|
43
43
|
repo, or a repo-ignored/temporary folder such as \`.agent-native/plans/<slug>/\`
|
|
44
44
|
or \`/tmp/agent-native-plans/<slug>/\` when it should not be checked in. The
|
|
@@ -53,7 +53,10 @@ The local-files contract:
|
|
|
53
53
|
(use \`--kind plan\` for plans, \`--kind recap\` for recaps). Report the local
|
|
54
54
|
bridge URL from stdout or \`<plan-dir>/.plan-url\`; treat \`.plan-url\` as a local
|
|
55
55
|
token file and do not commit it. The URL opens the hosted Plan UI but reads from
|
|
56
|
-
the localhost bridge on this machine, so it is not shareable across machines.
|
|
56
|
+
the localhost bridge on this machine, so it is not shareable across machines.
|
|
57
|
+
The token is carried in the URL fragment (which is not sent to the hosted
|
|
58
|
+
origin), and the local-plan route disables DOM autocapture and session replay
|
|
59
|
+
while retaining sanitized pageviews and error monitoring. On
|
|
57
60
|
macOS \`--open\` prefers Chromium browsers; if Safari opens, switch to
|
|
58
61
|
Chrome/Chromium because Safari can block the hosted HTTPS page from fetching the
|
|
59
62
|
HTTP localhost bridge. If the Plan app itself is running locally with the same
|
|
@@ -63,14 +66,16 @@ The local-files contract:
|
|
|
63
66
|
running local Plan app.
|
|
64
67
|
- **Headless verify.** Run
|
|
65
68
|
\`npx @agent-native/core@latest plan local verify --dir <plan-dir> --kind <plan|recap>\`.
|
|
66
|
-
It starts the bridge
|
|
67
|
-
|
|
68
|
-
|
|
69
|
+
It starts the bridge and checks the private-network preflight and JSON payload
|
|
70
|
+
entirely on loopback. It never sends MDX or assets to a remote validation
|
|
71
|
+
action. When \`--app-url\` points to a loopback Plan app, verify also validates
|
|
72
|
+
against that local app's real renderer schema via \`validate-local-plan-source\`.
|
|
73
|
+
A non-\`ok\` result with
|
|
69
74
|
\`validation.valid: false\` lists the renderer's exact schema-path issues (e.g.
|
|
70
75
|
\`blocks[1].data.tabs[0]...\`); fix those before handing off. If \`validation.ran\`
|
|
71
|
-
is \`false\`,
|
|
72
|
-
|
|
73
|
-
|
|
76
|
+
is \`false\`, verify used the offline lint because the app URL was remote or the
|
|
77
|
+
local Plan app was unavailable. Run a local Plan app and pass
|
|
78
|
+
\`--app-url http://localhost:8096\` for the authoritative check. If the browser hangs on
|
|
74
79
|
"Loading plan", fetch the \`bridgeUrl\` from the verify/serve JSON to read the
|
|
75
80
|
concrete validation error.
|
|
76
81
|
- **Never call hosted tools for that plan/recap.** Do not call
|
|
@@ -86,8 +91,8 @@ The local-files contract:
|
|
|
86
91
|
attachment, and publish/export receipts are unavailable until the user
|
|
87
92
|
explicitly opts into publishing.
|
|
88
93
|
|
|
89
|
-
Local-files mode
|
|
90
|
-
Plan database. It does not by itself make the coding agent's language model local;
|
|
94
|
+
Local-files mode prevents plan/recap content from being uploaded to the
|
|
95
|
+
Agent-Native Plan server or database. It does not by itself make the coding agent's language model local;
|
|
91
96
|
for that stronger boundary the host agent/model must also be local or otherwise
|
|
92
97
|
approved by the user.
|
|
93
98
|
|
|
@@ -1271,7 +1271,7 @@ function AgentPanelInner({
|
|
|
1271
1271
|
)}
|
|
1272
1272
|
{mode === "chat" && (
|
|
1273
1273
|
<RunsTrayMenuItem
|
|
1274
|
-
pollMs={
|
|
1274
|
+
pollMs={0}
|
|
1275
1275
|
limit={12}
|
|
1276
1276
|
showRecent={true}
|
|
1277
1277
|
onOpenThread={openRunThread}
|
|
@@ -1986,7 +1986,7 @@ const SIDEBAR_ANIMATION_MS = 260;
|
|
|
1986
1986
|
const SIDEBAR_OVERLAY_Z_INDEX = 70;
|
|
1987
1987
|
const SIDEBAR_FULLSCREEN_Z_INDEX = 90;
|
|
1988
1988
|
/** Max width of the centered chat column in fullscreen mode (Claude-style). */
|
|
1989
|
-
const FULLSCREEN_CONTENT_MAX_PX =
|
|
1989
|
+
const FULLSCREEN_CONTENT_MAX_PX = 570;
|
|
1990
1990
|
|
|
1991
1991
|
function ResizeHandle({
|
|
1992
1992
|
position,
|
|
@@ -2194,7 +2194,6 @@ function URLSync({ browserTabId }: { browserTabId?: string }) {
|
|
|
2194
2194
|
return null;
|
|
2195
2195
|
}
|
|
2196
2196
|
},
|
|
2197
|
-
refetchInterval: 2_000,
|
|
2198
2197
|
retry: false,
|
|
2199
2198
|
});
|
|
2200
2199
|
|