@agent-native/core 0.100.1 → 0.101.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 +73 -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/AssistantChat.tsx +4 -0
- 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/composer/PromptComposer.tsx +4 -0
- package/corpus/core/src/client/composer/TiptapComposer.tsx +30 -3
- 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/integrations/webhook-handler.ts +4 -2
- 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 +98 -47
- package/corpus/core/src/secrets/index.ts +2 -1
- package/corpus/core/src/secrets/schema.ts +3 -0
- package/corpus/core/src/secrets/storage.ts +164 -31
- 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 +1 -0
- 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/server/lib/dashboard-report.ts +156 -3
- package/corpus/templates/assets/app/components/generation/GenerationResults.tsx +402 -142
- package/corpus/templates/assets/app/components/layout/Layout.tsx +4 -0
- package/corpus/templates/assets/app/hooks/use-navigation-state.ts +3 -1
- 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-assets-keeps-the-right-chat-sidebar-closed-when-the-full-pag.md +6 -0
- 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/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/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/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/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/AssistantChat.d.ts +2 -0
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +2 -2
- package/dist/client/AssistantChat.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/composer/PromptComposer.d.ts +2 -0
- package/dist/client/composer/PromptComposer.d.ts.map +1 -1
- package/dist/client/composer/PromptComposer.js +2 -2
- package/dist/client/composer/PromptComposer.js.map +1 -1
- package/dist/client/composer/TiptapComposer.d.ts +3 -1
- package/dist/client/composer/TiptapComposer.d.ts.map +1 -1
- package/dist/client/composer/TiptapComposer.js +20 -5
- package/dist/client/composer/TiptapComposer.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/file-upload/actions/upload-image.d.ts +1 -1
- package/dist/integrations/webhook-handler.d.ts.map +1 -1
- package/dist/integrations/webhook-handler.js +3 -2
- package/dist/integrations/webhook-handler.js.map +1 -1
- package/dist/notifications/routes.d.ts +3 -3
- 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 +2 -2
- 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 +35 -13
- package/dist/secrets/crypto.d.ts.map +1 -1
- package/dist/secrets/crypto.js +78 -41
- package/dist/secrets/crypto.js.map +1 -1
- package/dist/secrets/index.d.ts.map +1 -1
- package/dist/secrets/index.js +2 -1
- package/dist/secrets/index.js.map +1 -1
- package/dist/secrets/routes.d.ts +9 -9
- package/dist/secrets/schema.d.ts +20 -1
- package/dist/secrets/schema.d.ts.map +1 -1
- package/dist/secrets/schema.js +3 -0
- package/dist/secrets/schema.js.map +1 -1
- package/dist/secrets/storage.d.ts +7 -7
- package/dist/secrets/storage.d.ts.map +1 -1
- package/dist/secrets/storage.js +121 -30
- 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.map +1 -1
- package/dist/server/agent-chat-plugin.js +1 -0
- package/dist/server/agent-chat-plugin.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/forms/server/routes/api/forms/og/[slug]/og.png.get.ts +0 -45
|
@@ -0,0 +1,353 @@
|
|
|
1
|
+
//! Live chunk uploader for the custom capture pipeline.
|
|
2
|
+
//!
|
|
3
|
+
//! Tails the growing fragmented MP4 during recording and streams whole
|
|
4
|
+
//! chunks to the server by index, then drains the tail and closes the
|
|
5
|
+
//! sequence on finalize. Owns the uploader task lifecycle
|
|
6
|
+
//! (`LiveUploadCtrl` / `LiveUpload`); the parent `native_screen` module
|
|
7
|
+
//! decides when to attach, finalize, or abandon it.
|
|
8
|
+
|
|
9
|
+
use super::*;
|
|
10
|
+
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
// Live upload (custom pipeline)
|
|
13
|
+
//
|
|
14
|
+
// Streams the growing fragmented MP4 to the server in UPLOAD_CHUNK_BYTES slices
|
|
15
|
+
// while recording is still in progress, instead of waiting for stop+finalize.
|
|
16
|
+
// Safe because the custom writer produces an append-only file (movie
|
|
17
|
+
// fragments): byte ranges we upload never change. The server concatenates the
|
|
18
|
+
// uploaded chunks in index order to reproduce the exact file.
|
|
19
|
+
// ---------------------------------------------------------------------------
|
|
20
|
+
|
|
21
|
+
const LIVE_UPLOAD_POLL_MS: u64 = 250;
|
|
22
|
+
/// Attempts per chunk before the live upload gives up (the stop path then
|
|
23
|
+
/// saves the clip locally for manual retry).
|
|
24
|
+
const LIVE_UPLOAD_CHUNK_ATTEMPTS: u32 = 5;
|
|
25
|
+
/// First retry backoff; doubles per attempt (0.5s, 1s, 2s, 4s).
|
|
26
|
+
const LIVE_UPLOAD_RETRY_BASE_MS: u64 = 500;
|
|
27
|
+
|
|
28
|
+
pub(super) struct LiveUploadCtrl {
|
|
29
|
+
/// Set once the writer is finalized: drain the tail and send the final post.
|
|
30
|
+
pub(super) finalize: AtomicBool,
|
|
31
|
+
/// Abort without finalizing (cancel / discard / error).
|
|
32
|
+
pub(super) cancelled: AtomicBool,
|
|
33
|
+
/// Recorded media duration in ms; set just before `finalize`.
|
|
34
|
+
pub(super) duration_ms: AtomicU64,
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
pub(super) struct LiveUpload {
|
|
38
|
+
pub(super) ctrl: Arc<LiveUploadCtrl>,
|
|
39
|
+
/// Resolves with the total bytes uploaded, or an error string.
|
|
40
|
+
pub(super) result_rx: tokio::sync::oneshot::Receiver<Result<u64, String>>,
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
struct LiveUploadParams {
|
|
44
|
+
path: PathBuf,
|
|
45
|
+
server_url: String,
|
|
46
|
+
recording_id: String,
|
|
47
|
+
auth_token: String,
|
|
48
|
+
cookie: String,
|
|
49
|
+
mime_type: String,
|
|
50
|
+
width: Option<u32>,
|
|
51
|
+
height: Option<u32>,
|
|
52
|
+
has_audio: bool,
|
|
53
|
+
has_camera: bool,
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/// Spawn the background uploader and return a handle the stop path uses to
|
|
57
|
+
/// finalize (or cancel) it.
|
|
58
|
+
fn spawn_live_uploader(app: AppHandle, params: LiveUploadParams) -> LiveUpload {
|
|
59
|
+
let ctrl = Arc::new(LiveUploadCtrl {
|
|
60
|
+
finalize: AtomicBool::new(false),
|
|
61
|
+
cancelled: AtomicBool::new(false),
|
|
62
|
+
duration_ms: AtomicU64::new(0),
|
|
63
|
+
});
|
|
64
|
+
let (tx, rx) = tokio::sync::oneshot::channel();
|
|
65
|
+
let ctrl_task = ctrl.clone();
|
|
66
|
+
tauri::async_runtime::spawn(async move {
|
|
67
|
+
let result = live_upload_loop(app, ctrl_task, params).await;
|
|
68
|
+
let _ = tx.send(result);
|
|
69
|
+
});
|
|
70
|
+
LiveUpload {
|
|
71
|
+
ctrl,
|
|
72
|
+
result_rx: rx,
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/// Build and attach a live uploader to an already-recording session. No-op when
|
|
77
|
+
/// live upload is disabled, the session isn't the custom pipeline, an uploader
|
|
78
|
+
/// is already attached, or no server URL was provided (local-only recordings).
|
|
79
|
+
pub(super) fn attach_live_uploader_to_session(
|
|
80
|
+
app: &AppHandle,
|
|
81
|
+
session: &mut NativeFullscreenSession,
|
|
82
|
+
recording_id: &str,
|
|
83
|
+
server_url: Option<&str>,
|
|
84
|
+
auth_token: Option<&str>,
|
|
85
|
+
cookie: Option<&str>,
|
|
86
|
+
has_audio: bool,
|
|
87
|
+
has_camera: bool,
|
|
88
|
+
) {
|
|
89
|
+
let segmented_writer = matches!(
|
|
90
|
+
session.backend.as_ref(),
|
|
91
|
+
Some(NativeFullscreenBackend::CustomScreenCaptureKit { writer, .. })
|
|
92
|
+
if writer.segmented()
|
|
93
|
+
);
|
|
94
|
+
if !segmented_writer {
|
|
95
|
+
eprintln!(
|
|
96
|
+
"[live-upload] writer not in append-only segmented mode (live upload off at writer creation, or not the custom pipeline); skipping for {recording_id}"
|
|
97
|
+
);
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
if session.live_upload.is_some() {
|
|
101
|
+
eprintln!("[live-upload] already attached; skipping for {recording_id}");
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
let server_url = match server_url {
|
|
105
|
+
Some(s) if !s.trim().is_empty() => s.to_string(),
|
|
106
|
+
_ => {
|
|
107
|
+
eprintln!("[live-upload] no server URL (local-only?); skipping for {recording_id}");
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
let has_auth = auth_token.is_some_and(|t| !t.trim().is_empty())
|
|
113
|
+
|| cookie.is_some_and(|c| !c.trim().is_empty());
|
|
114
|
+
if !has_auth {
|
|
115
|
+
eprintln!(
|
|
116
|
+
"[live-upload] no auth credentials yet (session not fully propagated?); skipping live upload for {recording_id}, will upload at stop"
|
|
117
|
+
);
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
eprintln!(
|
|
121
|
+
"[live-upload] attaching uploader for {recording_id}: file={} server={server_url} has_audio={has_audio} has_camera={has_camera} size={:?}",
|
|
122
|
+
session.path.display(),
|
|
123
|
+
std::fs::metadata(&session.path).map(|m| m.len()).ok(),
|
|
124
|
+
);
|
|
125
|
+
let params = LiveUploadParams {
|
|
126
|
+
path: session.path.clone(),
|
|
127
|
+
server_url,
|
|
128
|
+
recording_id: recording_id.to_string(),
|
|
129
|
+
auth_token: auth_token.unwrap_or_default().to_string(),
|
|
130
|
+
cookie: cookie.unwrap_or_default().to_string(),
|
|
131
|
+
mime_type: session.mime_type.to_string(),
|
|
132
|
+
width: session.width,
|
|
133
|
+
height: session.height,
|
|
134
|
+
has_audio,
|
|
135
|
+
has_camera,
|
|
136
|
+
};
|
|
137
|
+
session.live_upload = Some(spawn_live_uploader(app.clone(), params));
|
|
138
|
+
session.had_live_upload = true;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/// Read exactly `len` bytes at `offset` from a file that is still being written.
|
|
142
|
+
/// Safe here because the custom writer only appends, so bytes below the current
|
|
143
|
+
/// length are stable.
|
|
144
|
+
fn read_file_range(path: &Path, offset: u64, len: usize) -> Result<Vec<u8>, String> {
|
|
145
|
+
let mut file = File::open(path).map_err(|e| format!("live upload open failed: {e}"))?;
|
|
146
|
+
file.seek(SeekFrom::Start(offset))
|
|
147
|
+
.map_err(|e| format!("live upload seek failed: {e}"))?;
|
|
148
|
+
let mut buf = vec![0_u8; len];
|
|
149
|
+
file.read_exact(&mut buf)
|
|
150
|
+
.map_err(|e| format!("live upload read failed: {e}"))?;
|
|
151
|
+
Ok(buf)
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/// Send one live-upload POST, retrying transient failures with exponential
|
|
155
|
+
/// backoff. Bails out between attempts if the upload is cancelled.
|
|
156
|
+
async fn send_live_upload_post_with_retry(
|
|
157
|
+
client: &reqwest::Client,
|
|
158
|
+
ctrl: &LiveUploadCtrl,
|
|
159
|
+
params: &LiveUploadParams,
|
|
160
|
+
index: usize,
|
|
161
|
+
total: usize,
|
|
162
|
+
is_final: bool,
|
|
163
|
+
duration_ms: Option<u128>,
|
|
164
|
+
bytes: &[u8],
|
|
165
|
+
) -> Result<(), String> {
|
|
166
|
+
let rec = ¶ms.recording_id;
|
|
167
|
+
let mut attempt: u32 = 0;
|
|
168
|
+
loop {
|
|
169
|
+
// The uploader task can outlive an abandoned session (pause/discard
|
|
170
|
+
// set `cancelled` and drop the handle), so bail before spending a
|
|
171
|
+
// network attempt. An already in-flight POST still runs to completion
|
|
172
|
+
// — narrow accepted race; the full re-upload path resets server
|
|
173
|
+
// chunks first, and re-uploaded indexes overwrite stale ones.
|
|
174
|
+
if ctrl.cancelled.load(Ordering::SeqCst) {
|
|
175
|
+
return Err("live upload cancelled".into());
|
|
176
|
+
}
|
|
177
|
+
attempt += 1;
|
|
178
|
+
let result = send_upload_post(
|
|
179
|
+
client,
|
|
180
|
+
¶ms.server_url,
|
|
181
|
+
¶ms.recording_id,
|
|
182
|
+
¶ms.auth_token,
|
|
183
|
+
¶ms.cookie,
|
|
184
|
+
index,
|
|
185
|
+
total,
|
|
186
|
+
is_final,
|
|
187
|
+
duration_ms,
|
|
188
|
+
¶ms.mime_type,
|
|
189
|
+
params.width,
|
|
190
|
+
params.height,
|
|
191
|
+
params.has_audio,
|
|
192
|
+
params.has_camera,
|
|
193
|
+
NativeUploadMode::Buffered,
|
|
194
|
+
false,
|
|
195
|
+
bytes.to_vec(),
|
|
196
|
+
)
|
|
197
|
+
.await;
|
|
198
|
+
let err = match result {
|
|
199
|
+
Ok(()) => return Ok(()),
|
|
200
|
+
Err(err) => err,
|
|
201
|
+
};
|
|
202
|
+
if attempt >= LIVE_UPLOAD_CHUNK_ATTEMPTS {
|
|
203
|
+
return Err(err);
|
|
204
|
+
}
|
|
205
|
+
let backoff_ms = LIVE_UPLOAD_RETRY_BASE_MS << (attempt - 1);
|
|
206
|
+
eprintln!(
|
|
207
|
+
"[live-upload] {rec}: chunk #{index} attempt {attempt}/{LIVE_UPLOAD_CHUNK_ATTEMPTS} failed: {err}; retrying in {backoff_ms}ms"
|
|
208
|
+
);
|
|
209
|
+
tokio::time::sleep(Duration::from_millis(backoff_ms)).await;
|
|
210
|
+
if ctrl.cancelled.load(Ordering::SeqCst) {
|
|
211
|
+
return Err("live upload cancelled".into());
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
async fn live_upload_loop(
|
|
217
|
+
app: AppHandle,
|
|
218
|
+
ctrl: Arc<LiveUploadCtrl>,
|
|
219
|
+
params: LiveUploadParams,
|
|
220
|
+
) -> Result<u64, String> {
|
|
221
|
+
let rec = params.recording_id.clone();
|
|
222
|
+
eprintln!(
|
|
223
|
+
"[live-upload] loop started for {rec}: file={} chunk={} bytes",
|
|
224
|
+
params.path.display(),
|
|
225
|
+
UPLOAD_CHUNK_BYTES
|
|
226
|
+
);
|
|
227
|
+
let client = reqwest::Client::builder()
|
|
228
|
+
.timeout(Duration::from_secs(180))
|
|
229
|
+
.build()
|
|
230
|
+
.map_err(|e| {
|
|
231
|
+
let msg = format!("live upload client failed: {e}");
|
|
232
|
+
eprintln!("[live-upload] {rec}: {msg}");
|
|
233
|
+
msg
|
|
234
|
+
})?;
|
|
235
|
+
|
|
236
|
+
let mut offset: u64 = 0;
|
|
237
|
+
let mut index: usize = 0;
|
|
238
|
+
let chunk = UPLOAD_CHUNK_BYTES as u64;
|
|
239
|
+
let mut wait_logged = false;
|
|
240
|
+
|
|
241
|
+
loop {
|
|
242
|
+
if ctrl.cancelled.load(Ordering::SeqCst) {
|
|
243
|
+
eprintln!("[live-upload] {rec}: cancelled after {index} chunk(s), {offset} bytes sent");
|
|
244
|
+
return Err("live upload cancelled".into());
|
|
245
|
+
}
|
|
246
|
+
let finalize = ctrl.finalize.load(Ordering::SeqCst);
|
|
247
|
+
let file_len = std::fs::metadata(¶ms.path)
|
|
248
|
+
.map(|m| m.len())
|
|
249
|
+
.unwrap_or(offset);
|
|
250
|
+
|
|
251
|
+
// While recording, only upload whole chunks — the last partial chunk
|
|
252
|
+
// may still be growing. On finalize, drain everything that remains.
|
|
253
|
+
while file_len.saturating_sub(offset) >= chunk {
|
|
254
|
+
wait_logged = false;
|
|
255
|
+
let bytes = read_file_range(¶ms.path, offset, chunk as usize)?;
|
|
256
|
+
eprintln!(
|
|
257
|
+
"[live-upload] {rec}: sending chunk #{index} offset={offset} size={} (file now {file_len})",
|
|
258
|
+
bytes.len()
|
|
259
|
+
);
|
|
260
|
+
if let Err(e) = send_live_upload_post_with_retry(
|
|
261
|
+
&client, &ctrl, ¶ms, index, 0, false, None, &bytes,
|
|
262
|
+
)
|
|
263
|
+
.await
|
|
264
|
+
{
|
|
265
|
+
eprintln!("[live-upload] {rec}: chunk #{index} failed: {e}");
|
|
266
|
+
return Err(e);
|
|
267
|
+
}
|
|
268
|
+
offset += chunk;
|
|
269
|
+
index += 1;
|
|
270
|
+
emit_native_upload_progress(&app, "uploading", "Uploading clip", None, None);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
if finalize {
|
|
274
|
+
let final_len = std::fs::metadata(¶ms.path)
|
|
275
|
+
.map(|m| m.len())
|
|
276
|
+
.unwrap_or(offset);
|
|
277
|
+
let duration_ms = ctrl.duration_ms.load(Ordering::SeqCst) as u128;
|
|
278
|
+
eprintln!(
|
|
279
|
+
"[live-upload] {rec}: finalizing — {index} chunk(s) sent, draining tail (offset={offset}, final_len={final_len})"
|
|
280
|
+
);
|
|
281
|
+
emit_native_upload_progress(&app, "processing", "Uploading clip", None, None);
|
|
282
|
+
|
|
283
|
+
// The last tail chunk doubles as the final post (data + is_final).
|
|
284
|
+
// The server's resumable-session path relays chunks to GCS, whose
|
|
285
|
+
// protocol requires every NON-final chunk to be a multiple of
|
|
286
|
+
// 256 KiB — only the final chunk may have arbitrary size. Sending
|
|
287
|
+
// the arbitrary-sized tail as non-final followed by an empty final
|
|
288
|
+
// sentinel makes GCS silently commit only the aligned prefix, and
|
|
289
|
+
// the session close then fails forever with 308 (incomplete).
|
|
290
|
+
let mut final_sent = false;
|
|
291
|
+
while final_len > offset {
|
|
292
|
+
let take = chunk.min(final_len - offset);
|
|
293
|
+
let is_last = offset + take >= final_len;
|
|
294
|
+
let bytes = read_file_range(¶ms.path, offset, take as usize)?;
|
|
295
|
+
let (total, duration) = if is_last {
|
|
296
|
+
(index + 1, Some(duration_ms))
|
|
297
|
+
} else {
|
|
298
|
+
(0, None)
|
|
299
|
+
};
|
|
300
|
+
eprintln!(
|
|
301
|
+
"[live-upload] {rec}: sending tail chunk #{index} offset={offset} size={take} final={is_last}"
|
|
302
|
+
);
|
|
303
|
+
if let Err(e) = send_live_upload_post_with_retry(
|
|
304
|
+
&client, &ctrl, ¶ms, index, total, is_last, duration, &bytes,
|
|
305
|
+
)
|
|
306
|
+
.await
|
|
307
|
+
{
|
|
308
|
+
eprintln!("[live-upload] {rec}: tail chunk #{index} failed: {e}");
|
|
309
|
+
return Err(e);
|
|
310
|
+
}
|
|
311
|
+
offset += take;
|
|
312
|
+
index += 1;
|
|
313
|
+
final_sent = final_sent || is_last;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
// No tail bytes left: close with the empty final sentinel. All
|
|
317
|
+
// streamed chunks were whole UPLOAD_CHUNK_BYTES (256 KiB aligned),
|
|
318
|
+
// so the provider can close the session on the declared total.
|
|
319
|
+
if !final_sent {
|
|
320
|
+
eprintln!(
|
|
321
|
+
"[live-upload] {rec}: sending final post #{index} (total={}, duration_ms={duration_ms})",
|
|
322
|
+
index + 1
|
|
323
|
+
);
|
|
324
|
+
if let Err(e) = send_live_upload_post_with_retry(
|
|
325
|
+
&client,
|
|
326
|
+
&ctrl,
|
|
327
|
+
¶ms,
|
|
328
|
+
index,
|
|
329
|
+
index + 1,
|
|
330
|
+
true,
|
|
331
|
+
Some(duration_ms),
|
|
332
|
+
&[],
|
|
333
|
+
)
|
|
334
|
+
.await
|
|
335
|
+
{
|
|
336
|
+
eprintln!("[live-upload] {rec}: final post failed: {e}");
|
|
337
|
+
return Err(e);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
emit_native_upload_progress(&app, "opening", "Uploading clip", None, Some(1.0));
|
|
341
|
+
eprintln!("[live-upload] {rec}: done — {index} post(s), {final_len} bytes total");
|
|
342
|
+
return Ok(final_len);
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
if !wait_logged {
|
|
346
|
+
eprintln!(
|
|
347
|
+
"[live-upload] {rec}: waiting for data (file={file_len}, sent={offset}, need {chunk}/chunk)"
|
|
348
|
+
);
|
|
349
|
+
wait_logged = true;
|
|
350
|
+
}
|
|
351
|
+
tokio::time::sleep(Duration::from_millis(LIVE_UPLOAD_POLL_MS)).await;
|
|
352
|
+
}
|
|
353
|
+
}
|