@agent-native/core 0.100.2 → 0.101.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/corpus/README.md +2 -2
- package/corpus/core/CHANGELOG.md +83 -0
- package/corpus/core/docs/content/locales/ar-SA/pr-visual-recap.mdx +48 -30
- package/corpus/core/docs/content/locales/ar-SA/template-plan.mdx +7 -0
- package/corpus/core/docs/content/locales/de-DE/pr-visual-recap.mdx +48 -30
- package/corpus/core/docs/content/locales/de-DE/template-plan.mdx +7 -0
- package/corpus/core/docs/content/locales/es-ES/pr-visual-recap.mdx +48 -30
- package/corpus/core/docs/content/locales/es-ES/template-plan.mdx +14 -0
- package/corpus/core/docs/content/locales/fr-FR/pr-visual-recap.mdx +48 -30
- package/corpus/core/docs/content/locales/fr-FR/template-plan.mdx +7 -0
- package/corpus/core/docs/content/locales/hi-IN/pr-visual-recap.mdx +48 -30
- package/corpus/core/docs/content/locales/hi-IN/template-plan.mdx +7 -0
- package/corpus/core/docs/content/locales/ja-JP/pr-visual-recap.mdx +48 -30
- package/corpus/core/docs/content/locales/ja-JP/template-plan.mdx +7 -0
- package/corpus/core/docs/content/locales/ko-KR/pr-visual-recap.mdx +48 -30
- package/corpus/core/docs/content/locales/ko-KR/template-plan.mdx +7 -0
- package/corpus/core/docs/content/locales/pt-BR/pr-visual-recap.mdx +48 -30
- package/corpus/core/docs/content/locales/pt-BR/template-plan.mdx +14 -0
- package/corpus/core/docs/content/locales/zh-CN/pr-visual-recap.mdx +48 -30
- package/corpus/core/docs/content/locales/zh-CN/template-plan.mdx +7 -0
- package/corpus/core/docs/content/locales/zh-TW/pr-visual-recap.mdx +48 -30
- package/corpus/core/docs/content/locales/zh-TW/template-plan.mdx +7 -0
- package/corpus/core/docs/content/pr-visual-recap.mdx +50 -32
- package/corpus/core/docs/content/template-plan.mdx +14 -0
- package/corpus/core/docs/content/toolkit-comments-review.mdx +16 -2
- package/corpus/core/package.json +4 -1
- package/corpus/core/src/a2a/index.ts +2 -1
- package/corpus/core/src/a2a/server.ts +34 -9
- package/corpus/core/src/agent/production-agent.ts +56 -10
- package/corpus/core/src/cli/create.ts +47 -19
- package/corpus/core/src/cli/pr-visual-recap-workflow.ts +2 -3
- package/corpus/core/src/cli/recap.ts +3 -4932
- package/corpus/core/src/cli/skills-content/visual-plan-skill.ts +6 -4
- package/corpus/core/src/cli/skills-content/visual-recap-skill.ts +7 -1
- package/corpus/core/src/client/AgentPanel.tsx +19 -17
- package/corpus/core/src/client/analytics.ts +8 -1
- package/corpus/core/src/client/chat/markdown-renderer.tsx +54 -8
- package/corpus/core/src/client/chat/message-components.tsx +8 -2
- package/corpus/core/src/client/clipboard.ts +28 -1
- package/corpus/core/src/client/guided-questions.tsx +4 -0
- package/corpus/core/src/client/i18n.tsx +2 -1
- package/corpus/core/src/client/index.ts +4 -0
- package/corpus/core/src/client/review/ReviewCommentComposer.tsx +108 -0
- package/corpus/core/src/client/review/ReviewThreadPanel.tsx +482 -150
- package/corpus/core/src/client/review/index.ts +8 -0
- package/corpus/core/src/client/review/use-review.ts +35 -1
- package/corpus/core/src/client/use-agent-chat-context.ts +3 -2
- package/corpus/core/src/credentials/index.ts +41 -8
- package/corpus/core/src/extensions/fetch-tool.ts +33 -3
- package/corpus/core/src/notifications/channels.ts +20 -6
- package/corpus/core/src/review/actions/create-review-comment.ts +2 -1
- package/corpus/core/src/review/actions/get-review-feedback.ts +6 -11
- package/corpus/core/src/review/actions/list-review-comments.ts +38 -4
- package/corpus/core/src/review/actions/reply-review-comment.ts +33 -22
- package/corpus/core/src/review/actions/resolve-review-thread.ts +29 -2
- package/corpus/core/src/review/actions/send-review-thread-to-agent.ts +62 -0
- package/corpus/core/src/review/identity.ts +101 -0
- package/corpus/core/src/review/index.ts +14 -0
- package/corpus/core/src/review/store.ts +315 -8
- package/corpus/core/src/review/types.ts +4 -0
- package/corpus/core/src/secrets/crypto.ts +26 -10
- package/corpus/core/src/secrets/storage.ts +16 -3
- package/corpus/core/src/server/action-discovery.ts +4 -0
- package/corpus/core/src/server/action-routes.ts +125 -4
- package/corpus/core/src/server/agent-chat/plugin-options.ts +16 -0
- package/corpus/core/src/server/agent-chat-plugin.ts +61 -7
- package/corpus/core/src/server/derived-secret.ts +5 -1
- package/corpus/core/src/server/index.ts +8 -0
- package/corpus/core/src/vite/action-types-plugin.ts +4 -0
- package/corpus/templates/analytics/changelog/2026-07-14-daily-dashboard-email-captures-authenticate-with-a-sessi.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-14-long-running-cross-app-analyses-now-continue-reliably-in-the.md +6 -0
- package/corpus/templates/analytics/server/lib/dashboard-report.ts +156 -3
- package/corpus/templates/analytics/server/plugins/agent-chat.ts +8 -4
- package/corpus/templates/assets/app/components/generation/GenerationResults.tsx +402 -142
- package/corpus/templates/assets/app/i18n/zh-TW.ts +1 -0
- package/corpus/templates/assets/app/i18n-data.ts +1 -0
- package/corpus/templates/assets/app/routes/library.tsx +187 -48
- package/corpus/templates/assets/changelog/2026-07-13-merged-the-candidates-panel-into-the-library-as-a-drafts-tab.md +6 -0
- package/corpus/templates/chat/app/lib/agent-page.tsx +40 -0
- package/corpus/templates/chat/app/routes/agent.tsx +5 -3
- package/corpus/templates/chat/changelog/2026-07-14-fixed-chat-template-startup-with-older-core-versions.md +6 -0
- package/corpus/templates/clips/.agents/skills/ai-video-tools/SKILL.md +5 -0
- package/corpus/templates/clips/AGENTS.md +4 -0
- package/corpus/templates/clips/actions/get-feature-flags.ts +30 -0
- package/corpus/templates/clips/actions/lib/transcript-preview.ts +48 -0
- package/corpus/templates/clips/actions/request-transcript.ts +41 -1
- package/corpus/templates/clips/actions/view-screen.ts +5 -9
- package/corpus/templates/clips/app/components/library/library-layout.tsx +1 -1
- package/corpus/templates/clips/app/components/player/share-dialog.tsx +44 -81
- package/corpus/templates/clips/app/components/player/video-player.tsx +39 -1
- package/corpus/templates/clips/app/hooks/use-desktop-promo.ts +6 -12
- package/corpus/templates/clips/app/hooks/use-mse-video-source.ts +146 -0
- package/corpus/templates/clips/app/i18n/ar-SA.ts +0 -8
- package/corpus/templates/clips/app/i18n/de-DE.ts +0 -9
- package/corpus/templates/clips/app/i18n/en-US.ts +0 -8
- package/corpus/templates/clips/app/i18n/es-ES.ts +0 -9
- package/corpus/templates/clips/app/i18n/fr-FR.ts +0 -9
- package/corpus/templates/clips/app/i18n/hi-IN.ts +0 -8
- package/corpus/templates/clips/app/i18n/ja-JP.ts +0 -9
- package/corpus/templates/clips/app/i18n/ko-KR.ts +0 -9
- package/corpus/templates/clips/app/i18n/pt-BR.ts +0 -9
- package/corpus/templates/clips/app/i18n/zh-CN.ts +0 -7
- package/corpus/templates/clips/app/i18n/zh-TW.ts +0 -7
- package/corpus/templates/clips/app/lib/capture-install-options.ts +21 -0
- package/corpus/templates/clips/app/lib/fmp4.ts +271 -0
- package/corpus/templates/clips/app/lib/mse-video-loader.ts +585 -0
- package/corpus/templates/clips/app/routes/_app.dictate.tsx +0 -4
- package/corpus/templates/clips/app/routes/_app.meetings.$meetingId.tsx +5 -13
- package/corpus/templates/clips/app/routes/_app.meetings._index.tsx +2 -37
- package/corpus/templates/clips/app/routes/download.tsx +3 -2
- package/corpus/templates/clips/changelog/2026-07-10-shared-clips-now-start-playing-instantly-instead-of-showing-.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-14-clips-now-distinguishes-transcript-previews-from-incomplete-.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-14-desktop-app-prompts-stay-hidden-after-you-download-the-insta.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-14-share-dialogs-show-separate-links-for-people-and-agents.md +6 -0
- package/corpus/templates/clips/desktop/src/lib/recorder.ts +5 -0
- package/corpus/templates/clips/desktop/src/overlays/recording-pill.tsx +10 -0
- package/corpus/templates/clips/desktop/src-tauri/src/lib.rs +4 -0
- package/corpus/templates/clips/desktop/src-tauri/src/native_screen/custom_capture.rs +2518 -0
- package/corpus/templates/clips/desktop/src-tauri/src/native_screen/live_upload.rs +353 -0
- package/corpus/templates/clips/desktop/src-tauri/src/native_screen.rs +558 -67
- package/corpus/templates/clips/desktop/src-tauri/src/recording_indicator.rs +11 -1
- package/corpus/templates/clips/desktop/src-tauri/src/remote_flags.rs +188 -0
- package/corpus/templates/clips/desktop/src-tauri/src/whisper_speech.rs +1 -1
- package/corpus/templates/clips/server/lib/post-finalize-dispatch.ts +1 -0
- package/corpus/templates/clips/server/plugins/agent-chat.ts +5 -0
- package/corpus/templates/clips/server/routes/api/_agent-native-background/post-finalize-worker.post.ts +5 -1
- package/corpus/templates/clips/shared/feature-flags.ts +41 -0
- package/corpus/templates/design/.agents/skills/design-generation/SKILL.md +3 -0
- package/corpus/templates/design/.agents/skills/design-review-feedback/SKILL.md +42 -0
- package/corpus/templates/design/AGENTS.md +6 -0
- package/corpus/templates/design/README.md +1 -0
- package/corpus/templates/design/actions/navigate.ts +4 -4
- package/corpus/templates/design/actions/view-screen.ts +116 -2
- package/corpus/templates/design/agent-native.app-skill.json +5 -0
- package/corpus/templates/design/app/components/design/DesignCanvas.tsx +52 -59
- package/corpus/templates/design/app/components/design/DesignExtensionsPanel.tsx +13 -9
- package/corpus/templates/design/app/components/design/EditPanel.tsx +79 -11
- package/corpus/templates/design/app/components/design/LayersPanel.tsx +78 -65
- package/corpus/templates/design/app/components/design/ReviewCommentsPanel.tsx +161 -0
- package/corpus/templates/design/app/components/design/ReviewStatusControl.tsx +96 -0
- package/corpus/templates/design/app/components/design/bridge/hit-test.bridge.ts +166 -0
- package/corpus/templates/design/app/components/layout/Layout.tsx +1 -0
- package/corpus/templates/design/app/components/visual-editor/ReviewCanvasPins.tsx +1077 -0
- package/corpus/templates/design/app/components/visual-editor/index.ts +1 -0
- package/corpus/templates/design/app/components/visual-editor/review-canvas-state.ts +42 -0
- package/corpus/templates/design/app/hooks/use-design-systems.ts +2 -2
- package/corpus/templates/design/app/hooks/use-navigation-state.ts +9 -6
- package/corpus/templates/design/app/hooks/use-question-flow.ts +7 -1
- package/corpus/templates/design/app/i18n/ar-SA.ts +56 -1
- package/corpus/templates/design/app/i18n/de-DE.ts +57 -1
- package/corpus/templates/design/app/i18n/en-US.ts +56 -1
- package/corpus/templates/design/app/i18n/es-ES.ts +56 -1
- package/corpus/templates/design/app/i18n/fr-FR.ts +57 -1
- package/corpus/templates/design/app/i18n/hi-IN.ts +56 -1
- package/corpus/templates/design/app/i18n/ja-JP.ts +56 -1
- package/corpus/templates/design/app/i18n/ko-KR.ts +56 -1
- package/corpus/templates/design/app/i18n/pt-BR.ts +57 -1
- package/corpus/templates/design/app/i18n/zh-CN.ts +56 -1
- package/corpus/templates/design/app/i18n/zh-TW.ts +51 -0
- package/corpus/templates/design/app/pages/Present.tsx +172 -14
- package/corpus/templates/design/app/pages/design-editor/overview-camera.ts +23 -0
- package/corpus/templates/design/app/pages/design-editor/tool-state.ts +10 -0
- package/corpus/templates/design/app/pages/present-review-state.ts +18 -0
- package/corpus/templates/design/app/public-routes.ts +8 -0
- package/corpus/templates/design/app/root.tsx +7 -6
- package/corpus/templates/design/changelog/2026-07-13-dragged-design-assets-now-appear-at-the-visible-drop-locatio.md +6 -0
- package/corpus/templates/design/changelog/2026-07-13-reviewers-can-pin-comments-on-shared-designs-and-apply-verif.md +6 -0
- package/corpus/templates/design/server/plugins/agent-chat.ts +10 -0
- package/corpus/templates/design/server/plugins/auth.ts +7 -5
- package/corpus/templates/design/server/plugins/review.ts +9 -0
- package/corpus/templates/design/shared/review-anchor.ts +83 -0
- package/corpus/templates/design/shared/review-summary.ts +25 -0
- package/corpus/templates/dispatch/changelog/2026-07-14-dispatch-now-distinguishes-connected-agents-from-locally-mou.md +6 -0
- package/corpus/templates/forms/.agents/skills/form-publishing/SKILL.md +2 -0
- package/corpus/templates/forms/AGENTS.md +4 -0
- package/corpus/templates/forms/actions/create-form.ts +2 -1
- package/corpus/templates/forms/actions/update-form.ts +5 -2
- package/corpus/templates/forms/app/i18n/ar-SA.ts +3 -0
- package/corpus/templates/forms/app/i18n/de-DE.ts +3 -0
- package/corpus/templates/forms/app/i18n/en-US.ts +3 -0
- package/corpus/templates/forms/app/i18n/es-ES.ts +3 -0
- package/corpus/templates/forms/app/i18n/fr-FR.ts +3 -0
- package/corpus/templates/forms/app/i18n/hi-IN.ts +3 -0
- package/corpus/templates/forms/app/i18n/ja-JP.ts +3 -0
- package/corpus/templates/forms/app/i18n/ko-KR.ts +3 -0
- package/corpus/templates/forms/app/i18n/pt-BR.ts +3 -0
- package/corpus/templates/forms/app/i18n/zh-CN.ts +3 -0
- package/corpus/templates/forms/app/i18n/zh-TW.ts +3 -0
- package/corpus/templates/forms/app/pages/FormBuilderPage.tsx +19 -0
- package/corpus/templates/forms/changelog/2026-07-14-fixed-the-ask-forms-loading-input-appearing-above-the-welcom.md +6 -0
- package/corpus/templates/forms/changelog/2026-07-14-form-social-previews-now-show-the-form-title-description-and.md +6 -0
- package/corpus/templates/forms/changelog/2026-07-14-forms-can-email-the-form-owner-when-new-responses-arrive.md +6 -0
- package/corpus/templates/forms/server/handlers/submissions.ts +17 -0
- package/corpus/templates/forms/server/lib/form-og-image.ts +64 -6
- package/corpus/templates/forms/server/lib/public-form-ssr.ts +6 -2
- package/corpus/templates/forms/server/lib/response-email.ts +65 -0
- package/corpus/templates/forms/server/plugins/agent-chat.ts +1 -0
- package/corpus/templates/forms/server/routes/api/forms/og/[...slug]/og.png.get.ts +184 -0
- package/corpus/templates/forms/shared/types.ts +2 -0
- package/corpus/templates/plan/.agents/skills/visual-plan/SKILL.md +6 -4
- package/corpus/templates/plan/.agents/skills/visual-recap/SKILL.md +7 -1
- package/dist/a2a/index.d.ts +2 -1
- package/dist/a2a/index.d.ts.map +1 -1
- package/dist/a2a/index.js +1 -1
- package/dist/a2a/index.js.map +1 -1
- package/dist/a2a/server.d.ts +25 -0
- package/dist/a2a/server.d.ts.map +1 -1
- package/dist/a2a/server.js +30 -6
- package/dist/a2a/server.js.map +1 -1
- package/dist/agent/production-agent.d.ts +2 -0
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +37 -12
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/cli/create.d.ts +5 -3
- package/dist/cli/create.d.ts.map +1 -1
- package/dist/cli/create.js +44 -19
- package/dist/cli/create.js.map +1 -1
- package/dist/cli/pr-visual-recap-workflow.d.ts +2 -2
- package/dist/cli/pr-visual-recap-workflow.d.ts.map +1 -1
- package/dist/cli/pr-visual-recap-workflow.js +2 -2
- package/dist/cli/pr-visual-recap-workflow.js.map +1 -1
- package/dist/cli/recap.d.ts +3 -562
- package/dist/cli/recap.d.ts.map +1 -1
- package/dist/cli/recap.js +3 -3875
- package/dist/cli/recap.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 +6 -4
- 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 +7 -1
- package/dist/cli/skills-content/visual-recap-skill.js.map +1 -1
- package/dist/client/AgentPanel.d.ts.map +1 -1
- package/dist/client/AgentPanel.js +3 -3
- package/dist/client/AgentPanel.js.map +1 -1
- package/dist/client/analytics.d.ts +5 -0
- package/dist/client/analytics.d.ts.map +1 -1
- package/dist/client/analytics.js +3 -1
- package/dist/client/analytics.js.map +1 -1
- package/dist/client/chat/markdown-renderer.d.ts +1 -0
- package/dist/client/chat/markdown-renderer.d.ts.map +1 -1
- package/dist/client/chat/markdown-renderer.js +36 -1
- package/dist/client/chat/markdown-renderer.js.map +1 -1
- package/dist/client/chat/message-components.d.ts.map +1 -1
- package/dist/client/chat/message-components.js +5 -2
- package/dist/client/chat/message-components.js.map +1 -1
- package/dist/client/clipboard.d.ts +3 -1
- package/dist/client/clipboard.d.ts.map +1 -1
- package/dist/client/clipboard.js +24 -1
- package/dist/client/clipboard.js.map +1 -1
- package/dist/client/guided-questions.d.ts +3 -1
- package/dist/client/guided-questions.d.ts.map +1 -1
- package/dist/client/guided-questions.js +2 -1
- package/dist/client/guided-questions.js.map +1 -1
- package/dist/client/i18n.d.ts.map +1 -1
- package/dist/client/i18n.js +3 -1
- package/dist/client/i18n.js.map +1 -1
- package/dist/client/index.d.ts +1 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +1 -1
- package/dist/client/index.js.map +1 -1
- package/dist/client/review/ReviewCommentComposer.d.ts +18 -0
- package/dist/client/review/ReviewCommentComposer.d.ts.map +1 -0
- package/dist/client/review/ReviewCommentComposer.js +30 -0
- package/dist/client/review/ReviewCommentComposer.js.map +1 -0
- package/dist/client/review/ReviewThreadPanel.d.ts +28 -1
- package/dist/client/review/ReviewThreadPanel.d.ts.map +1 -1
- package/dist/client/review/ReviewThreadPanel.js +151 -39
- package/dist/client/review/ReviewThreadPanel.js.map +1 -1
- package/dist/client/review/index.d.ts +3 -2
- package/dist/client/review/index.d.ts.map +1 -1
- package/dist/client/review/index.js +2 -1
- package/dist/client/review/index.js.map +1 -1
- package/dist/client/review/use-review.d.ts +23 -0
- package/dist/client/review/use-review.d.ts.map +1 -1
- package/dist/client/review/use-review.js +3 -0
- package/dist/client/review/use-review.js.map +1 -1
- package/dist/client/use-agent-chat-context.d.ts +1 -1
- package/dist/client/use-agent-chat-context.d.ts.map +1 -1
- package/dist/client/use-agent-chat-context.js +4 -2
- package/dist/client/use-agent-chat-context.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/credentials/index.d.ts +12 -7
- package/dist/credentials/index.d.ts.map +1 -1
- package/dist/credentials/index.js +33 -8
- package/dist/credentials/index.js.map +1 -1
- package/dist/extensions/fetch-tool.d.ts +13 -1
- package/dist/extensions/fetch-tool.d.ts.map +1 -1
- package/dist/extensions/fetch-tool.js +9 -2
- package/dist/extensions/fetch-tool.js.map +1 -1
- package/dist/notifications/channels.js +20 -4
- package/dist/notifications/channels.js.map +1 -1
- package/dist/observability/routes.d.ts +5 -5
- 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/review/actions/create-review-comment.js +2 -1
- package/dist/review/actions/create-review-comment.js.map +1 -1
- package/dist/review/actions/get-review-feedback.js +6 -11
- package/dist/review/actions/get-review-feedback.js.map +1 -1
- package/dist/review/actions/list-review-comments.d.ts +1 -0
- package/dist/review/actions/list-review-comments.js +25 -4
- package/dist/review/actions/list-review-comments.js.map +1 -1
- package/dist/review/actions/reply-review-comment.js +12 -5
- package/dist/review/actions/reply-review-comment.js.map +1 -1
- package/dist/review/actions/resolve-review-thread.d.ts +3 -0
- package/dist/review/actions/resolve-review-thread.js +20 -3
- package/dist/review/actions/resolve-review-thread.js.map +1 -1
- package/dist/review/actions/send-review-thread-to-agent.d.ts +17 -0
- package/dist/review/actions/send-review-thread-to-agent.d.ts.map +1 -0
- package/dist/review/actions/send-review-thread-to-agent.js +49 -0
- package/dist/review/actions/send-review-thread-to-agent.js.map +1 -0
- package/dist/review/identity.d.ts +6 -0
- package/dist/review/identity.d.ts.map +1 -0
- package/dist/review/identity.js +68 -0
- package/dist/review/identity.js.map +1 -0
- package/dist/review/index.d.ts +3 -1
- package/dist/review/index.d.ts.map +1 -1
- package/dist/review/index.js +2 -1
- package/dist/review/index.js.map +1 -1
- package/dist/review/store.d.ts +36 -0
- package/dist/review/store.d.ts.map +1 -1
- package/dist/review/store.js +223 -8
- package/dist/review/store.js.map +1 -1
- package/dist/review/types.d.ts +4 -0
- package/dist/review/types.d.ts.map +1 -1
- package/dist/review/types.js.map +1 -1
- package/dist/secrets/crypto.d.ts +15 -7
- package/dist/secrets/crypto.d.ts.map +1 -1
- package/dist/secrets/crypto.js +23 -10
- package/dist/secrets/crypto.js.map +1 -1
- package/dist/secrets/routes.d.ts +9 -9
- package/dist/secrets/storage.d.ts.map +1 -1
- package/dist/secrets/storage.js +16 -3
- package/dist/secrets/storage.js.map +1 -1
- package/dist/server/action-discovery.d.ts.map +1 -1
- package/dist/server/action-discovery.js +4 -0
- package/dist/server/action-discovery.js.map +1 -1
- package/dist/server/action-routes.d.ts +45 -0
- package/dist/server/action-routes.d.ts.map +1 -1
- package/dist/server/action-routes.js +71 -5
- package/dist/server/action-routes.js.map +1 -1
- package/dist/server/agent-chat/plugin-options.d.ts +16 -0
- package/dist/server/agent-chat/plugin-options.d.ts.map +1 -1
- package/dist/server/agent-chat/plugin-options.js.map +1 -1
- package/dist/server/agent-chat-plugin.d.ts +20 -0
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +39 -4
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/derived-secret.d.ts +1 -1
- package/dist/server/derived-secret.d.ts.map +1 -1
- package/dist/server/derived-secret.js.map +1 -1
- package/dist/server/index.d.ts +3 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +2 -0
- package/dist/server/index.js.map +1 -1
- package/dist/vite/action-types-plugin.d.ts.map +1 -1
- package/dist/vite/action-types-plugin.js +4 -0
- package/dist/vite/action-types-plugin.js.map +1 -1
- package/docs/content/locales/ar-SA/pr-visual-recap.mdx +48 -30
- package/docs/content/locales/ar-SA/template-plan.mdx +7 -0
- package/docs/content/locales/de-DE/pr-visual-recap.mdx +48 -30
- package/docs/content/locales/de-DE/template-plan.mdx +7 -0
- package/docs/content/locales/es-ES/pr-visual-recap.mdx +48 -30
- package/docs/content/locales/es-ES/template-plan.mdx +14 -0
- package/docs/content/locales/fr-FR/pr-visual-recap.mdx +48 -30
- package/docs/content/locales/fr-FR/template-plan.mdx +7 -0
- package/docs/content/locales/hi-IN/pr-visual-recap.mdx +48 -30
- package/docs/content/locales/hi-IN/template-plan.mdx +7 -0
- package/docs/content/locales/ja-JP/pr-visual-recap.mdx +48 -30
- package/docs/content/locales/ja-JP/template-plan.mdx +7 -0
- package/docs/content/locales/ko-KR/pr-visual-recap.mdx +48 -30
- package/docs/content/locales/ko-KR/template-plan.mdx +7 -0
- package/docs/content/locales/pt-BR/pr-visual-recap.mdx +48 -30
- package/docs/content/locales/pt-BR/template-plan.mdx +14 -0
- package/docs/content/locales/zh-CN/pr-visual-recap.mdx +48 -30
- package/docs/content/locales/zh-CN/template-plan.mdx +7 -0
- package/docs/content/locales/zh-TW/pr-visual-recap.mdx +48 -30
- package/docs/content/locales/zh-TW/template-plan.mdx +7 -0
- package/docs/content/pr-visual-recap.mdx +50 -32
- package/docs/content/template-plan.mdx +14 -0
- package/docs/content/toolkit-comments-review.mdx +16 -2
- package/package.json +4 -1
- package/corpus/templates/clips/app/components/sharing/slack-share-hint.tsx +0 -68
- package/corpus/templates/forms/server/routes/api/forms/og/[slug]/og.png.get.ts +0 -45
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
+
createError,
|
|
2
3
|
defineEventHandler,
|
|
3
4
|
setResponseStatus,
|
|
4
5
|
setResponseHeader,
|
|
@@ -10,6 +11,7 @@ import {
|
|
|
10
11
|
|
|
11
12
|
import { isAgentActionStopError } from "../action.js";
|
|
12
13
|
import type { ActionEntry } from "../agent/production-agent.js";
|
|
14
|
+
import { resolveOrgIdForEmail } from "../org/context.js";
|
|
13
15
|
import { readBody } from "../server/h3-helpers.js";
|
|
14
16
|
import { EMBED_TARGET_HEADER } from "../shared/embed-auth.js";
|
|
15
17
|
import {
|
|
@@ -18,6 +20,10 @@ import {
|
|
|
18
20
|
shouldAllowMcpEmbedCredentials,
|
|
19
21
|
} from "../shared/mcp-embed-headers.js";
|
|
20
22
|
import { notifyActionChange } from "./action-change.js";
|
|
23
|
+
import {
|
|
24
|
+
seedAgentRunOwnerContext,
|
|
25
|
+
type AgentRunOwnerContext,
|
|
26
|
+
} from "./agent-run-context.js";
|
|
21
27
|
import {
|
|
22
28
|
getAllowedCorsOrigin as resolveAllowedCorsOrigin,
|
|
23
29
|
readCorsAllowedOrigins,
|
|
@@ -164,6 +170,51 @@ function handleOptionsRequest(event: any): string {
|
|
|
164
170
|
return "";
|
|
165
171
|
}
|
|
166
172
|
|
|
173
|
+
/**
|
|
174
|
+
* Declarative auth adapter for the HTTP action route. Its `resolveCaller` runs
|
|
175
|
+
* BEFORE the framework's `getOwnerFromEvent` / `getSession` chain, letting an
|
|
176
|
+
* app accept caller identities `getSession` doesn't understand (e.g. an A2A
|
|
177
|
+
* JWT) without reaching into request context from a Nitro `request` hook.
|
|
178
|
+
*
|
|
179
|
+
* Scoped to `/_agent-native/actions/*` only — it does not affect other routes.
|
|
180
|
+
*/
|
|
181
|
+
export type ActionRouteResolvedCaller = AgentRunOwnerContext & {
|
|
182
|
+
/**
|
|
183
|
+
* Org to scope the request to, verified from the same credential as the
|
|
184
|
+
* caller identity (e.g. the A2A token's org claim). When omitted, the org
|
|
185
|
+
* is derived from the verified owner email via the framework's owner→org
|
|
186
|
+
* membership lookup. The ambient session/org state on the request is never
|
|
187
|
+
* consulted for adapter-resolved callers: a request can carry both a valid
|
|
188
|
+
* A2A bearer and an unrelated browser cookie, and the cookie user's org
|
|
189
|
+
* must not leak into the token caller's request context.
|
|
190
|
+
*/
|
|
191
|
+
orgId?: string;
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
export interface ActionRouteAuthAdapter {
|
|
195
|
+
/**
|
|
196
|
+
* Resolve a caller from the raw event before the cookie/bearer chain.
|
|
197
|
+
*
|
|
198
|
+
* - Return the resolved caller to run the action scoped to that identity.
|
|
199
|
+
* Org scoping comes exclusively from the caller: the returned `orgId` if
|
|
200
|
+
* set, otherwise the owner-email membership lookup — never from the
|
|
201
|
+
* request's session cookie or org context.
|
|
202
|
+
* - Return `null` when the credential isn't yours to judge — the request
|
|
203
|
+
* defers to `getOwnerFromEvent` / `getSession`.
|
|
204
|
+
* - THROW to hard-reject: the credential is present but invalid (e.g. an
|
|
205
|
+
* expired or forged A2A bearer). The action route responds 401 and does
|
|
206
|
+
* NOT fall through to the cookie/session chain, so a valid same-origin
|
|
207
|
+
* session cookie can't be used to execute the request as the logged-in
|
|
208
|
+
* user. Do not throw merely to signal "not mine" — return `null` for that.
|
|
209
|
+
*/
|
|
210
|
+
resolveCaller?: (
|
|
211
|
+
event: any,
|
|
212
|
+
) =>
|
|
213
|
+
| ActionRouteResolvedCaller
|
|
214
|
+
| null
|
|
215
|
+
| Promise<ActionRouteResolvedCaller | null>;
|
|
216
|
+
}
|
|
217
|
+
|
|
167
218
|
export interface MountActionRoutesOptions {
|
|
168
219
|
/** Resolve owner email from the H3 event (for data scoping). */
|
|
169
220
|
getOwnerFromEvent?: (event: any) => string | Promise<string>;
|
|
@@ -173,6 +224,18 @@ export interface MountActionRoutesOptions {
|
|
|
173
224
|
) => string | undefined | Promise<string | undefined>;
|
|
174
225
|
/** Resolve org ID from the H3 event (for org scoping). */
|
|
175
226
|
resolveOrgId?: (event: any) => string | null | Promise<string | null>;
|
|
227
|
+
/**
|
|
228
|
+
* Optional caller resolver that runs before the `getOwnerFromEvent` /
|
|
229
|
+
* `getSession` chain. Lets apps accept A2A JWTs (or other bearer schemes) on
|
|
230
|
+
* the action route declaratively. See {@link ActionRouteAuthAdapter}.
|
|
231
|
+
*/
|
|
232
|
+
actionRouteAuth?: ActionRouteAuthAdapter;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
function normalizeOrgId(value: string | null | undefined): string | undefined {
|
|
236
|
+
return typeof value === "string" && value.trim().length > 0
|
|
237
|
+
? value.trim()
|
|
238
|
+
: undefined;
|
|
176
239
|
}
|
|
177
240
|
|
|
178
241
|
function isAuthResolutionFailure(error: unknown): boolean {
|
|
@@ -259,7 +322,42 @@ export function mountActionRoutes(
|
|
|
259
322
|
// Resolve auth context for per-request scoping
|
|
260
323
|
let userEmail: string | undefined;
|
|
261
324
|
let userName: string | undefined;
|
|
262
|
-
|
|
325
|
+
// An app-supplied auth adapter runs first: it can accept caller
|
|
326
|
+
// identities the framework's getSession chain doesn't understand (e.g.
|
|
327
|
+
// an A2A JWT). A resolved caller is seeded onto the event context so any
|
|
328
|
+
// downstream resolveAgentRunOwnerContext (nested agent runs) sees the
|
|
329
|
+
// same identity. The adapter is only consulted for the action route, so
|
|
330
|
+
// it can't affect other surfaces.
|
|
331
|
+
//
|
|
332
|
+
// Contract: `resolveCaller` returning `null` means "this credential
|
|
333
|
+
// isn't mine — defer to the cookie/session chain below". THROWING means
|
|
334
|
+
// "the credential is mine but invalid" (e.g. an expired/forged A2A
|
|
335
|
+
// bearer) and is a hard rejection: we surface a 401 instead of falling
|
|
336
|
+
// through, so a live same-origin session cookie can't silently execute
|
|
337
|
+
// the request as the logged-in user.
|
|
338
|
+
let resolvedCaller: ActionRouteResolvedCaller | null = null;
|
|
339
|
+
if (options?.actionRouteAuth?.resolveCaller) {
|
|
340
|
+
let caller: ActionRouteResolvedCaller | null;
|
|
341
|
+
try {
|
|
342
|
+
caller = await options.actionRouteAuth.resolveCaller(event);
|
|
343
|
+
} catch {
|
|
344
|
+
throw createError({
|
|
345
|
+
statusCode: 401,
|
|
346
|
+
statusMessage: "Unauthorized",
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
if (caller) {
|
|
350
|
+
seedAgentRunOwnerContext(event, {
|
|
351
|
+
owner: caller.owner,
|
|
352
|
+
anonymous: caller.anonymous,
|
|
353
|
+
name: caller.name,
|
|
354
|
+
});
|
|
355
|
+
userEmail = caller.owner;
|
|
356
|
+
userName = caller.name;
|
|
357
|
+
resolvedCaller = caller;
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
if (!resolvedCaller && options?.getOwnerFromEvent) {
|
|
263
361
|
try {
|
|
264
362
|
userEmail = await options.getOwnerFromEvent(event);
|
|
265
363
|
userName = options?.getUserNameFromEvent
|
|
@@ -277,9 +375,32 @@ export function mountActionRoutes(
|
|
|
277
375
|
}
|
|
278
376
|
}
|
|
279
377
|
}
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
378
|
+
// Org scoping. For adapter-resolved callers the org must come
|
|
379
|
+
// exclusively from the verified credential: the adapter-asserted
|
|
380
|
+
// orgId when present, otherwise the owner-email membership lookup.
|
|
381
|
+
// The request's ambient session/org state (`resolveOrgId`, usually
|
|
382
|
+
// getSession-backed) is deliberately NOT consulted — a request can
|
|
383
|
+
// carry both a valid A2A bearer and an unrelated same-origin browser
|
|
384
|
+
// cookie, and the cookie user's org must not become the org the
|
|
385
|
+
// token caller's actions execute under. Non-adapter callers keep the
|
|
386
|
+
// original resolveOrgId-only behavior.
|
|
387
|
+
let orgId: string | undefined;
|
|
388
|
+
if (resolvedCaller) {
|
|
389
|
+
orgId = normalizeOrgId(resolvedCaller.orgId);
|
|
390
|
+
if (!orgId && resolvedCaller.owner && !resolvedCaller.anonymous) {
|
|
391
|
+
try {
|
|
392
|
+
orgId = normalizeOrgId(
|
|
393
|
+
await resolveOrgIdForEmail(resolvedCaller.owner),
|
|
394
|
+
);
|
|
395
|
+
} catch {
|
|
396
|
+
// Org tables may not exist yet on first boot.
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
} else {
|
|
400
|
+
orgId = options?.resolveOrgId
|
|
401
|
+
? ((await options.resolveOrgId(event)) ?? undefined)
|
|
402
|
+
: undefined;
|
|
403
|
+
}
|
|
283
404
|
const timezone = readTimezoneHeader(event);
|
|
284
405
|
|
|
285
406
|
return runWithRequestContext(
|
|
@@ -109,6 +109,22 @@ export interface AgentChatPluginOptions {
|
|
|
109
109
|
* agent mutations.
|
|
110
110
|
*/
|
|
111
111
|
anonymousReadOnly?: boolean;
|
|
112
|
+
/**
|
|
113
|
+
* Optional auth adapter for the HTTP action route
|
|
114
|
+
* (`/_agent-native/actions/*`). Its `resolveCaller` runs before the
|
|
115
|
+
* cookie/bearer `getSession` chain, letting an app accept caller identities
|
|
116
|
+
* `getSession` doesn't understand (e.g. an A2A JWT verified with
|
|
117
|
+
* `verifyA2AToken`) declaratively, instead of pre-seeding request context
|
|
118
|
+
* from a Nitro `request` hook.
|
|
119
|
+
*
|
|
120
|
+
* Returning `null` defers to the normal chain; THROWING hard-rejects with a
|
|
121
|
+
* 401 (an invalid/forged credential must not fall through to a same-origin
|
|
122
|
+
* session cookie). A resolved caller's org comes exclusively from the
|
|
123
|
+
* verified credential — the returned `orgId` or the owner-email membership
|
|
124
|
+
* lookup — never from the request's session cookie.
|
|
125
|
+
* See {@link import("../action-routes.js").ActionRouteAuthAdapter}.
|
|
126
|
+
*/
|
|
127
|
+
actionRouteAuth?: import("../action-routes.js").ActionRouteAuthAdapter;
|
|
112
128
|
/**
|
|
113
129
|
* Optional callback to append template-specific context to the system
|
|
114
130
|
* prompt on each request. Runs after AGENTS.md / skills / memory are
|
|
@@ -134,6 +134,7 @@ import {
|
|
|
134
134
|
WORKSPACE_OWNER,
|
|
135
135
|
} from "../resources/store.js";
|
|
136
136
|
import { normalizeDatabaseToolsMode } from "../scripts/db/tool-mode.js";
|
|
137
|
+
import type { ResolvedKeyReference } from "../secrets/substitution.js";
|
|
137
138
|
import { getSetting, putSetting } from "../settings/store.js";
|
|
138
139
|
import {
|
|
139
140
|
handleSharedThreadRequest,
|
|
@@ -323,6 +324,41 @@ const generateTitleRateLimit = new Map<string, number[]>();
|
|
|
323
324
|
* so the common small-map case stays O(1). */
|
|
324
325
|
const RATE_LIMIT_SWEEP_THRESHOLD = 1000;
|
|
325
326
|
|
|
327
|
+
/**
|
|
328
|
+
* Pick the URL allowlist to enforce for a `${keys.NAME}` reference used by
|
|
329
|
+
* the agent fetch tool.
|
|
330
|
+
*
|
|
331
|
+
* SECURITY (audit 05 H2 alignment): the allowlist check must stay
|
|
332
|
+
* consistent with the scope a key actually resolved at (see the
|
|
333
|
+
* `getKeyAllowlist` docstring in secrets/substitution.ts). Since the fetch
|
|
334
|
+
* tool now resolves keys via `resolveKeyReferencesWithRequestScopes` — which
|
|
335
|
+
* cascades user → org → workspace scope — a plain user-scope-only allowlist
|
|
336
|
+
* lookup would silently miss an allowlist configured on the org/workspace
|
|
337
|
+
* row that actually supplied the value. When `resolvedKeys` reports which
|
|
338
|
+
* scope a key resolved at, look up the allowlist there; only fall back to
|
|
339
|
+
* the legacy user-scope lookup for a key the resolver didn't report (should
|
|
340
|
+
* not normally happen — every key the cascade resolves reports a ref).
|
|
341
|
+
*/
|
|
342
|
+
export async function resolveFetchToolKeyAllowlist(
|
|
343
|
+
keyName: string,
|
|
344
|
+
resolvedKeys: ResolvedKeyReference[] | undefined,
|
|
345
|
+
owner: string,
|
|
346
|
+
deps: {
|
|
347
|
+
getKeyAllowlist: (
|
|
348
|
+
name: string,
|
|
349
|
+
scope: "user",
|
|
350
|
+
scopeId: string,
|
|
351
|
+
) => Promise<string[] | null>;
|
|
352
|
+
getResolvedKeyAllowlist: (
|
|
353
|
+
ref: ResolvedKeyReference,
|
|
354
|
+
) => Promise<string[] | null>;
|
|
355
|
+
},
|
|
356
|
+
): Promise<string[] | null> {
|
|
357
|
+
const ref = resolvedKeys?.find((candidate) => candidate.name === keyName);
|
|
358
|
+
if (ref) return deps.getResolvedKeyAllowlist(ref);
|
|
359
|
+
return deps.getKeyAllowlist(keyName, "user", owner);
|
|
360
|
+
}
|
|
361
|
+
|
|
326
362
|
export function createAgentChatPlugin(
|
|
327
363
|
options?: AgentChatPluginOptions,
|
|
328
364
|
): NitroPluginDef {
|
|
@@ -793,21 +829,38 @@ export function createAgentChatPlugin(
|
|
|
793
829
|
try {
|
|
794
830
|
const { createFetchToolEntry } =
|
|
795
831
|
await import("../extensions/fetch-tool.js");
|
|
796
|
-
|
|
797
|
-
|
|
832
|
+
// Resolve `${keys.NAME}` through the same request-scope cascade
|
|
833
|
+
// already used by extension fetches (extensions/routes.ts) and
|
|
834
|
+
// automation connector headers (automation/index.ts): user scope
|
|
835
|
+
// first (personal overrides win), then the active org scope (the
|
|
836
|
+
// Dispatch vault syncs workspace secrets here), then workspace
|
|
837
|
+
// scope. Org/workspace vault rows are write-gated (org-admin +
|
|
838
|
+
// Dispatch vault UI), so this is safe to read by default — unlike
|
|
839
|
+
// the opt-in-only user→workspace fallback in resolveKeyReferences
|
|
840
|
+
// (see audit 05 H2 in secrets/substitution.ts), which stays off.
|
|
841
|
+
// Previously this tool only looked at scope "user", so a
|
|
842
|
+
// ${keys.NAME} reference to a key synced into the org/workspace
|
|
843
|
+
// vault could never resolve here even though the same key already
|
|
844
|
+
// worked for extension fetches and automations.
|
|
845
|
+
const {
|
|
846
|
+
resolveKeyReferencesWithRequestScopes,
|
|
847
|
+
validateUrlAllowlist,
|
|
848
|
+
getKeyAllowlist,
|
|
849
|
+
getResolvedKeyAllowlist,
|
|
850
|
+
} = await import("../secrets/substitution.js");
|
|
798
851
|
fetchTool = createFetchToolEntry({
|
|
799
852
|
resolveKeys: async (text) =>
|
|
800
|
-
|
|
853
|
+
resolveKeyReferencesWithRequestScopes(
|
|
801
854
|
text,
|
|
802
|
-
"user",
|
|
803
855
|
requireCurrentRunOwner("resolve key references"),
|
|
804
856
|
),
|
|
805
|
-
validateUrl: async (url, usedKeys) => {
|
|
857
|
+
validateUrl: async (url, usedKeys, resolvedKeys) => {
|
|
806
858
|
for (const keyName of usedKeys) {
|
|
807
|
-
const allowlist = await
|
|
859
|
+
const allowlist = await resolveFetchToolKeyAllowlist(
|
|
808
860
|
keyName,
|
|
809
|
-
|
|
861
|
+
resolvedKeys,
|
|
810
862
|
requireCurrentRunOwner("validate URL allowlist"),
|
|
863
|
+
{ getKeyAllowlist, getResolvedKeyAllowlist },
|
|
811
864
|
);
|
|
812
865
|
if (allowlist && !validateUrlAllowlist(url, allowlist)) {
|
|
813
866
|
return false;
|
|
@@ -1804,6 +1857,7 @@ export function createAgentChatPlugin(
|
|
|
1804
1857
|
getOwnerFromEvent,
|
|
1805
1858
|
getUserNameFromEvent,
|
|
1806
1859
|
resolveOrgId: options?.resolveOrgId,
|
|
1860
|
+
actionRouteAuth: options?.actionRouteAuth,
|
|
1807
1861
|
});
|
|
1808
1862
|
}
|
|
1809
1863
|
|
|
@@ -20,7 +20,11 @@ export function deriveServerSecret(
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
export function getWorkspaceA2ADerivedSecret(
|
|
23
|
-
purpose:
|
|
23
|
+
purpose:
|
|
24
|
+
| "better-auth"
|
|
25
|
+
| "oauth-state"
|
|
26
|
+
| "short-lived-token"
|
|
27
|
+
| "secrets-encryption",
|
|
24
28
|
): string | undefined {
|
|
25
29
|
if (!isWorkspaceRuntime()) return undefined;
|
|
26
30
|
const rootSecret = process.env.A2A_SECRET?.trim();
|
|
@@ -241,6 +241,7 @@ export {
|
|
|
241
241
|
renderAgentNativeOgImageSvg,
|
|
242
242
|
type AgentNativeOgImageInput,
|
|
243
243
|
} from "./social-og-image.js";
|
|
244
|
+
export { resolveOgFontFiles } from "./og-fonts.js";
|
|
244
245
|
export {
|
|
245
246
|
createBrowserSessionActionEntries,
|
|
246
247
|
type CreateBrowserSessionActionEntriesOptions,
|
|
@@ -320,7 +321,14 @@ export {
|
|
|
320
321
|
export {
|
|
321
322
|
mountActionRoutes,
|
|
322
323
|
type MountActionRoutesOptions,
|
|
324
|
+
type ActionRouteAuthAdapter,
|
|
325
|
+
type ActionRouteResolvedCaller,
|
|
323
326
|
} from "./action-routes.js";
|
|
327
|
+
export {
|
|
328
|
+
AGENT_RUN_OWNER_CONTEXT_KEY,
|
|
329
|
+
seedAgentRunOwnerContext,
|
|
330
|
+
type AgentRunOwnerContext,
|
|
331
|
+
} from "./agent-run-context.js";
|
|
324
332
|
export {
|
|
325
333
|
runWithRequestContext,
|
|
326
334
|
hasRequestContext,
|
|
@@ -141,6 +141,10 @@ const CORE_SHARING_ACTIONS: Array<{ name: string; specifier: string }> = [
|
|
|
141
141
|
name: "set-review-status",
|
|
142
142
|
specifier: "@agent-native/core/review/actions/set-review-status",
|
|
143
143
|
},
|
|
144
|
+
{
|
|
145
|
+
name: "send-review-thread-to-agent",
|
|
146
|
+
specifier: "@agent-native/core/review/actions/send-review-thread-to-agent",
|
|
147
|
+
},
|
|
144
148
|
];
|
|
145
149
|
|
|
146
150
|
function isRuntimeSourceFile(filename: string): boolean {
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
} from "@agent-native/core/server";
|
|
12
12
|
import {
|
|
13
13
|
EMBED_MODE_QUERY_PARAM,
|
|
14
|
+
EMBED_SESSION_COOKIE,
|
|
14
15
|
EMBED_TOKEN_QUERY_PARAM,
|
|
15
16
|
} from "@agent-native/core/shared";
|
|
16
17
|
|
|
@@ -60,6 +61,7 @@ type DashboardScreenshotAttempt = {
|
|
|
60
61
|
readyTimeout?: number;
|
|
61
62
|
secondReadyTimeout?: number;
|
|
62
63
|
totalTimeout?: number;
|
|
64
|
+
reportPanelLimit?: number;
|
|
63
65
|
};
|
|
64
66
|
|
|
65
67
|
type LaunchedScreenshotBrowser = {
|
|
@@ -466,6 +468,96 @@ async function runBoundedBrowserCleanup(
|
|
|
466
468
|
}
|
|
467
469
|
}
|
|
468
470
|
|
|
471
|
+
const DIAGNOSTICS_PROBE_TIMEOUT_MS = 2_000;
|
|
472
|
+
const DIAGNOSTICS_MAX_LENGTH = 700;
|
|
473
|
+
const DIAGNOSTICS_COLLECTOR_LIMIT = 5;
|
|
474
|
+
|
|
475
|
+
// Best-effort page inspection used when the report surface never becomes
|
|
476
|
+
// visible, so failures carry enough state to tell wrong-page/wedged-renderer/
|
|
477
|
+
// auth-bounce apart. Must never throw and must stay bounded even if the page
|
|
478
|
+
// is hung.
|
|
479
|
+
async function collectPageDiagnostics(
|
|
480
|
+
page: any,
|
|
481
|
+
consoleErrors: string[],
|
|
482
|
+
failedRequests: string[],
|
|
483
|
+
): Promise<string> {
|
|
484
|
+
try {
|
|
485
|
+
let responsive = true;
|
|
486
|
+
let probeTimeout: ReturnType<typeof setTimeout> | undefined;
|
|
487
|
+
try {
|
|
488
|
+
await Promise.race([
|
|
489
|
+
Promise.resolve(page.evaluate("1")),
|
|
490
|
+
new Promise((_, reject) => {
|
|
491
|
+
probeTimeout = setTimeout(
|
|
492
|
+
() => reject(new Error("diagnostics probe timed out")),
|
|
493
|
+
DIAGNOSTICS_PROBE_TIMEOUT_MS,
|
|
494
|
+
);
|
|
495
|
+
}),
|
|
496
|
+
]);
|
|
497
|
+
} catch {
|
|
498
|
+
responsive = false;
|
|
499
|
+
} finally {
|
|
500
|
+
if (probeTimeout) clearTimeout(probeTimeout);
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
if (!responsive) {
|
|
504
|
+
return `page unresponsive (renderer hung or crashed); consoleErrors=${JSON.stringify(
|
|
505
|
+
consoleErrors,
|
|
506
|
+
)} failedRequests=${JSON.stringify(failedRequests)}`.slice(
|
|
507
|
+
0,
|
|
508
|
+
DIAGNOSTICS_MAX_LENGTH,
|
|
509
|
+
);
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
let url = "";
|
|
513
|
+
try {
|
|
514
|
+
url = page.url();
|
|
515
|
+
} catch {
|
|
516
|
+
// page may already be closed; leave url empty
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
let title = "";
|
|
520
|
+
let bodyText = "";
|
|
521
|
+
let detailsTimeout: ReturnType<typeof setTimeout> | undefined;
|
|
522
|
+
try {
|
|
523
|
+
// page.evaluate ignores setDefaultTimeout, so race it like the probe —
|
|
524
|
+
// a renderer that wedges after the probe must not stall diagnostics.
|
|
525
|
+
const details = await Promise.race([
|
|
526
|
+
Promise.resolve(
|
|
527
|
+
page.evaluate(
|
|
528
|
+
`(() => ({
|
|
529
|
+
title: document.title,
|
|
530
|
+
bodyText: document.body?.innerText?.slice(0, 240) ?? "",
|
|
531
|
+
}))()`,
|
|
532
|
+
),
|
|
533
|
+
),
|
|
534
|
+
new Promise<never>((_, reject) => {
|
|
535
|
+
detailsTimeout = setTimeout(
|
|
536
|
+
() => reject(new Error("diagnostics details timed out")),
|
|
537
|
+
DIAGNOSTICS_PROBE_TIMEOUT_MS,
|
|
538
|
+
);
|
|
539
|
+
}),
|
|
540
|
+
]);
|
|
541
|
+
title = (details as any)?.title ?? "";
|
|
542
|
+
bodyText = (details as any)?.bodyText ?? "";
|
|
543
|
+
} catch {
|
|
544
|
+
// best effort; leave title/bodyText empty
|
|
545
|
+
} finally {
|
|
546
|
+
if (detailsTimeout) clearTimeout(detailsTimeout);
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
return `page state: ${JSON.stringify({
|
|
550
|
+
url,
|
|
551
|
+
title,
|
|
552
|
+
bodyText,
|
|
553
|
+
consoleErrors,
|
|
554
|
+
failedRequests,
|
|
555
|
+
})}`.slice(0, DIAGNOSTICS_MAX_LENGTH);
|
|
556
|
+
} catch {
|
|
557
|
+
return "diagnostics unavailable";
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
|
|
469
561
|
async function captureDashboardPng(
|
|
470
562
|
sub: DashboardReportSubscription,
|
|
471
563
|
snapshot: ReportSnapshot,
|
|
@@ -488,6 +580,12 @@ async function captureDashboardPng(
|
|
|
488
580
|
const screenshotUrl = new URL(targetPath, `${dashboardBaseUrl()}/`);
|
|
489
581
|
screenshotUrl.searchParams.set(EMBED_MODE_QUERY_PARAM, "1");
|
|
490
582
|
screenshotUrl.searchParams.set(EMBED_TOKEN_QUERY_PARAM, token);
|
|
583
|
+
if (attempt.reportPanelLimit) {
|
|
584
|
+
screenshotUrl.searchParams.set(
|
|
585
|
+
"reportPanelLimit",
|
|
586
|
+
String(attempt.reportPanelLimit),
|
|
587
|
+
);
|
|
588
|
+
}
|
|
491
589
|
|
|
492
590
|
let browser: any;
|
|
493
591
|
let cleanup = async () => {};
|
|
@@ -498,6 +596,7 @@ async function captureDashboardPng(
|
|
|
498
596
|
let launchTimeout: ReturnType<typeof setTimeout> | undefined;
|
|
499
597
|
let captureStage = "launching the screenshot browser";
|
|
500
598
|
let attemptTimedOut = false;
|
|
599
|
+
let lastDiagnostics: string | null = null;
|
|
501
600
|
const attemptTimeout = attempt.totalTimeout
|
|
502
601
|
? setTimeout(() => {
|
|
503
602
|
attemptTimedOut = true;
|
|
@@ -530,6 +629,51 @@ async function captureDashboardPng(
|
|
|
530
629
|
|
|
531
630
|
const timeout = screenshotTimeoutMs();
|
|
532
631
|
const page = await newPage();
|
|
632
|
+
|
|
633
|
+
// Belt-and-braces auth: the query token authenticates only after the
|
|
634
|
+
// client-side bootstrap harvests it from the URL, which gives the
|
|
635
|
+
// stripped-down serverless browser several ways to end up session-less.
|
|
636
|
+
// Seeding the same signed token as a cookie authenticates every request
|
|
637
|
+
// server-side with no client cooperation. Never abort the capture over
|
|
638
|
+
// this — the query token path still exists.
|
|
639
|
+
try {
|
|
640
|
+
await page.context().addCookies([
|
|
641
|
+
{
|
|
642
|
+
name: EMBED_SESSION_COOKIE,
|
|
643
|
+
value: token,
|
|
644
|
+
url: `${dashboardBaseUrl()}/`,
|
|
645
|
+
},
|
|
646
|
+
]);
|
|
647
|
+
} catch (err) {
|
|
648
|
+
console.warn(
|
|
649
|
+
"[dashboard-report] Failed to pre-seed embed session cookie:",
|
|
650
|
+
errorMessage(err),
|
|
651
|
+
);
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
// Bounded diagnostics collectors so a failed wait carries evidence of
|
|
655
|
+
// wrong-page/wedged-renderer/auth-bounce instead of a bare timeout.
|
|
656
|
+
const consoleErrors: string[] = [];
|
|
657
|
+
page.on("console", (msg: any) => {
|
|
658
|
+
if (msg.type() !== "error") return;
|
|
659
|
+
if (consoleErrors.length >= DIAGNOSTICS_COLLECTOR_LIMIT) return;
|
|
660
|
+
consoleErrors.push(msg.text().slice(0, 160));
|
|
661
|
+
});
|
|
662
|
+
const failedRequests: string[] = [];
|
|
663
|
+
page.on("requestfailed", (req: any) => {
|
|
664
|
+
if (failedRequests.length >= DIAGNOSTICS_COLLECTOR_LIMIT) return;
|
|
665
|
+
failedRequests.push(
|
|
666
|
+
`${req.method()} ${req.url().slice(0, 120)}: ${req.failure()?.errorText ?? "failed"}`,
|
|
667
|
+
);
|
|
668
|
+
});
|
|
669
|
+
page.on("response", (res: any) => {
|
|
670
|
+
if (res.status() < 400) return;
|
|
671
|
+
if (failedRequests.length >= DIAGNOSTICS_COLLECTOR_LIMIT) return;
|
|
672
|
+
failedRequests.push(
|
|
673
|
+
`${res.request().method()} ${res.url().slice(0, 120)}: HTTP ${res.status()}`,
|
|
674
|
+
);
|
|
675
|
+
});
|
|
676
|
+
|
|
533
677
|
page.setDefaultTimeout(timeout);
|
|
534
678
|
await page.emulateMedia({ media: "screen", colorScheme: "light" });
|
|
535
679
|
await page.addInitScript(() => {
|
|
@@ -542,7 +686,14 @@ async function captureDashboardPng(
|
|
|
542
686
|
|
|
543
687
|
captureStage = "waiting for the report surface";
|
|
544
688
|
const capture = page.locator("[data-dashboard-report-capture]");
|
|
545
|
-
|
|
689
|
+
try {
|
|
690
|
+
await capture.waitFor({ state: "visible", timeout });
|
|
691
|
+
} catch (err) {
|
|
692
|
+
lastDiagnostics = errorMessage(
|
|
693
|
+
await collectPageDiagnostics(page, consoleErrors, failedRequests),
|
|
694
|
+
);
|
|
695
|
+
throw new Error(`${errorMessage(err)}; ${lastDiagnostics}`);
|
|
696
|
+
}
|
|
546
697
|
captureStage = "waiting for dashboard queries";
|
|
547
698
|
await waitForDashboardReportReady(page, attempt.readyTimeout ?? timeout);
|
|
548
699
|
captureStage = "rendering lazy dashboard panels";
|
|
@@ -569,7 +720,8 @@ async function captureDashboardPng(
|
|
|
569
720
|
} catch (err) {
|
|
570
721
|
if (attemptTimedOut) {
|
|
571
722
|
throw new Error(
|
|
572
|
-
`${attempt.label} capture exceeded ${attempt.totalTimeout}ms while ${captureStage}
|
|
723
|
+
`${attempt.label} capture exceeded ${attempt.totalTimeout}ms while ${captureStage}` +
|
|
724
|
+
(lastDiagnostics ? `; ${lastDiagnostics}` : ""),
|
|
573
725
|
);
|
|
574
726
|
}
|
|
575
727
|
throw new Error(`${captureStage}: ${errorMessage(err)}`);
|
|
@@ -612,7 +764,7 @@ function errorMessage(err: unknown): string {
|
|
|
612
764
|
|
|
613
765
|
function storedAttemptError(message: string): string {
|
|
614
766
|
const normalized = message.replace(/\s+/g, " ").trim();
|
|
615
|
-
return normalized.length >
|
|
767
|
+
return normalized.length > 400 ? `${normalized.slice(0, 399)}…` : normalized;
|
|
616
768
|
}
|
|
617
769
|
|
|
618
770
|
async function captureDashboardPngWithFallback(
|
|
@@ -640,6 +792,7 @@ async function captureDashboardPngWithFallback(
|
|
|
640
792
|
label: "full-lightweight",
|
|
641
793
|
viewport: { width: 1200, height: 1400 },
|
|
642
794
|
captureScale: 0.7,
|
|
795
|
+
reportPanelLimit: 8,
|
|
643
796
|
...(serverless
|
|
644
797
|
? {
|
|
645
798
|
readyTimeout: 55_000,
|
|
@@ -27,6 +27,9 @@ import {
|
|
|
27
27
|
needsCorpusWorkflowForCoverageSensitiveRequest,
|
|
28
28
|
needsSourceRecordBodyWorkflowForCoverageSensitiveRequest,
|
|
29
29
|
} from "../lib/real-data-actions";
|
|
30
|
+
|
|
31
|
+
const ANALYTICS_BACKGROUND_RUN_SOFT_TIMEOUT_MS = 13 * 60_000;
|
|
32
|
+
|
|
30
33
|
export const SIMPLE_TIME_BOUNDED_METRIC_FAST_PATH_GUIDANCE =
|
|
31
34
|
"SIMPLE TIME-BOUNDED METRIC FAST PATH — When the data dictionary or a known canonical source identifies the metric, run one bounded aggregate. Once it returns a valid result, answer the explicit question immediately with the source, time window, row count, and only necessary caveats. Do not schema-discover, retry, enrich, cross-check, or add breakdowns after that successful result unless the query failed or the result conflicts with the known metric definition. This does not waive the real-data requirement: never answer from a guess, stale value, or unverified result. ";
|
|
32
35
|
|
|
@@ -271,10 +274,11 @@ export default createAgentChatPlugin({
|
|
|
271
274
|
// Operators deploying to trusted internal environments can set
|
|
272
275
|
// AGENT_PROD_CODE_EXECUTION=trusted to also enable bash/read/edit/write.
|
|
273
276
|
codeExecution: { production: "sandboxed" },
|
|
274
|
-
//
|
|
275
|
-
//
|
|
276
|
-
//
|
|
277
|
-
durableBackgroundRuns:
|
|
277
|
+
// Long-running A2A analysis belongs on the durable worker so provider
|
|
278
|
+
// pagination, cross-source joins, and corpus reduction can outlive the
|
|
279
|
+
// standard serverless request budget without orphaning the task.
|
|
280
|
+
durableBackgroundRuns: true,
|
|
281
|
+
runSoftTimeoutMs: ANALYTICS_BACKGROUND_RUN_SOFT_TIMEOUT_MS,
|
|
278
282
|
connectorCatalog: [...ANALYTICS_CONNECTOR_CATALOG],
|
|
279
283
|
externalAgents: {
|
|
280
284
|
// Keep the direct MCP surface deliberately curated. External agents
|