@agent-native/core 0.100.2 → 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 +65 -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/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/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/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/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/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/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/routes.d.ts +9 -9
- 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
|
@@ -1,13 +1,22 @@
|
|
|
1
1
|
import {
|
|
2
2
|
readClientAppState,
|
|
3
|
-
|
|
3
|
+
setAgentChatContextItem,
|
|
4
4
|
useActionMutation,
|
|
5
5
|
useActionQuery,
|
|
6
6
|
useT,
|
|
7
7
|
} from "@agent-native/core/client";
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
IconChevronLeft,
|
|
10
|
+
IconChevronRight,
|
|
11
|
+
IconDeviceFloppy,
|
|
12
|
+
IconMessageCircle,
|
|
13
|
+
IconPhoto,
|
|
14
|
+
IconTrash,
|
|
15
|
+
IconX,
|
|
16
|
+
} from "@tabler/icons-react";
|
|
9
17
|
import { useQuery, useQueryClient } from "@tanstack/react-query";
|
|
10
18
|
import { useEffect, useMemo, useRef, useState } from "react";
|
|
19
|
+
import { Link } from "react-router";
|
|
11
20
|
import { toast } from "sonner";
|
|
12
21
|
|
|
13
22
|
import {
|
|
@@ -22,7 +31,20 @@ import {
|
|
|
22
31
|
} from "@/components/ui/alert-dialog";
|
|
23
32
|
import { Badge } from "@/components/ui/badge";
|
|
24
33
|
import { Button } from "@/components/ui/button";
|
|
34
|
+
import {
|
|
35
|
+
Dialog,
|
|
36
|
+
DialogClose,
|
|
37
|
+
DialogContent,
|
|
38
|
+
DialogDescription,
|
|
39
|
+
DialogTitle,
|
|
40
|
+
} from "@/components/ui/dialog";
|
|
25
41
|
import { Spinner } from "@/components/ui/spinner";
|
|
42
|
+
import {
|
|
43
|
+
Tooltip,
|
|
44
|
+
TooltipContent,
|
|
45
|
+
TooltipProvider,
|
|
46
|
+
TooltipTrigger,
|
|
47
|
+
} from "@/components/ui/tooltip";
|
|
26
48
|
import { assetPreviewSources } from "@/lib/asset-preview-sources";
|
|
27
49
|
|
|
28
50
|
import type {
|
|
@@ -34,6 +56,8 @@ type LibraryListResult = {
|
|
|
34
56
|
libraries?: ImageLibrarySummary[];
|
|
35
57
|
};
|
|
36
58
|
|
|
59
|
+
type VariantSlot = AssetVariantState["slots"][number];
|
|
60
|
+
|
|
37
61
|
function variantStateKey(threadId: string | null) {
|
|
38
62
|
return threadId ? `asset-variants:${threadId}` : "asset-variants";
|
|
39
63
|
}
|
|
@@ -46,15 +70,13 @@ function variantStateKey(threadId: string | null) {
|
|
|
46
70
|
// its finished image arrives.
|
|
47
71
|
const STALE_PENDING_RUN_MS = 10 * 60 * 1000;
|
|
48
72
|
|
|
49
|
-
function slotTime(slot:
|
|
73
|
+
function slotTime(slot: VariantSlot): number {
|
|
50
74
|
const raw = slot.createdAt ?? slot.updatedAt ?? "";
|
|
51
75
|
const time = Date.parse(raw);
|
|
52
76
|
return Number.isNaN(time) ? 0 : time;
|
|
53
77
|
}
|
|
54
78
|
|
|
55
|
-
function stalePendingRunId(
|
|
56
|
-
slot: AssetVariantState["slots"][number],
|
|
57
|
-
): string | null {
|
|
79
|
+
function stalePendingRunId(slot: VariantSlot): string | null {
|
|
58
80
|
if (slot.status !== "pending") return null;
|
|
59
81
|
if (!slot.runId) return null;
|
|
60
82
|
const timestamp = slotTime(slot);
|
|
@@ -66,6 +88,7 @@ export function GenerationResults({ threadId }: { threadId: string | null }) {
|
|
|
66
88
|
const t = useT();
|
|
67
89
|
const queryClient = useQueryClient();
|
|
68
90
|
const [clearAllOpen, setClearAllOpen] = useState(false);
|
|
91
|
+
const [previewSlotId, setPreviewSlotId] = useState<string | null>(null);
|
|
69
92
|
const stateKey = variantStateKey(threadId);
|
|
70
93
|
const stateQueryKey = useMemo(() => ["app-state", stateKey], [stateKey]);
|
|
71
94
|
const { data: variants } = useQuery({
|
|
@@ -137,6 +160,11 @@ export function GenerationResults({ threadId }: { threadId: string | null }) {
|
|
|
137
160
|
);
|
|
138
161
|
}, [belongsToThread, queryClient, refreshGeneration, slots, stateQueryKey]);
|
|
139
162
|
|
|
163
|
+
const previewSlot = useMemo(
|
|
164
|
+
() => slots.find((slot) => slot.slotId === previewSlotId) ?? null,
|
|
165
|
+
[previewSlotId, slots],
|
|
166
|
+
);
|
|
167
|
+
|
|
140
168
|
if (!belongsToThread || !variants) return null;
|
|
141
169
|
if (slots.length === 0) return null;
|
|
142
170
|
|
|
@@ -169,6 +197,65 @@ export function GenerationResults({ threadId }: { threadId: string | null }) {
|
|
|
169
197
|
);
|
|
170
198
|
}
|
|
171
199
|
|
|
200
|
+
function saveSlot(slot: VariantSlot, onDone?: () => void) {
|
|
201
|
+
if (!slot.assetId && !slot.slotId) return;
|
|
202
|
+
saveGenerated.mutate(
|
|
203
|
+
{
|
|
204
|
+
...(slot.assetId ? { assetId: slot.assetId } : {}),
|
|
205
|
+
...(slot.slotId ? { slotId: slot.slotId } : {}),
|
|
206
|
+
threadId,
|
|
207
|
+
},
|
|
208
|
+
{
|
|
209
|
+
onSuccess: () => {
|
|
210
|
+
toast.success(t("library.savedGeneratedAsset"));
|
|
211
|
+
void queryClient.invalidateQueries({ queryKey: stateQueryKey });
|
|
212
|
+
void queryClient.invalidateQueries({
|
|
213
|
+
queryKey: ["action", "get-library"],
|
|
214
|
+
});
|
|
215
|
+
onDone?.();
|
|
216
|
+
},
|
|
217
|
+
onError: (error) =>
|
|
218
|
+
toast.error(error.message || t("library.couldNotSaveCandidate")),
|
|
219
|
+
},
|
|
220
|
+
);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
function dismissSlotById(slot: VariantSlot, onDone?: () => void) {
|
|
224
|
+
dismissSlot.mutate(
|
|
225
|
+
{ slotId: slot.slotId, threadId },
|
|
226
|
+
{
|
|
227
|
+
onSuccess: () => {
|
|
228
|
+
void queryClient.invalidateQueries({ queryKey: stateQueryKey });
|
|
229
|
+
onDone?.();
|
|
230
|
+
},
|
|
231
|
+
onError: (error) =>
|
|
232
|
+
toast.error(error.message || t("library.couldNotDismissCandidate")),
|
|
233
|
+
},
|
|
234
|
+
);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
function refineSlot(slot: VariantSlot, variantNumber: number) {
|
|
238
|
+
if (!slot.assetId) return;
|
|
239
|
+
const variantLabel = t("library.variantWithNumber", {
|
|
240
|
+
number: variantNumber,
|
|
241
|
+
});
|
|
242
|
+
setAgentChatContextItem({
|
|
243
|
+
key: "refine-asset:" + slot.assetId,
|
|
244
|
+
title: t("library.refine") + " : " + variantLabel,
|
|
245
|
+
context: [
|
|
246
|
+
"## Assets candidate",
|
|
247
|
+
`Asset ID: ${slot.assetId}`,
|
|
248
|
+
`Run ID: ${slot.runId ?? "unknown"}`,
|
|
249
|
+
`Prompt: ${variants?.prompt ?? ""}`,
|
|
250
|
+
libraryTitle ? `Brand kit: ${libraryTitle}` : "",
|
|
251
|
+
"Use refine-image with assetId when the user describes the change.",
|
|
252
|
+
]
|
|
253
|
+
.filter(Boolean)
|
|
254
|
+
.join("\n"),
|
|
255
|
+
openSidebar: true,
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
|
|
172
259
|
return (
|
|
173
260
|
<>
|
|
174
261
|
<AlertDialog open={clearAllOpen} onOpenChange={setClearAllOpen}>
|
|
@@ -206,6 +293,27 @@ export function GenerationResults({ threadId }: { threadId: string | null }) {
|
|
|
206
293
|
</AlertDialogContent>
|
|
207
294
|
</AlertDialog>
|
|
208
295
|
|
|
296
|
+
<GenerationPreviewDialog
|
|
297
|
+
slot={previewSlot}
|
|
298
|
+
slots={slots}
|
|
299
|
+
prompt={variants.prompt}
|
|
300
|
+
libraryTitle={libraryTitle}
|
|
301
|
+
isSaving={saveGenerated.isPending}
|
|
302
|
+
isDismissing={dismissSlot.isPending}
|
|
303
|
+
onOpenChange={(open) => {
|
|
304
|
+
if (!open) setPreviewSlotId(null);
|
|
305
|
+
}}
|
|
306
|
+
onSelect={setPreviewSlotId}
|
|
307
|
+
onSave={(slot) => saveSlot(slot, () => setPreviewSlotId(null))}
|
|
308
|
+
onRefine={(slot, variantNumber) => {
|
|
309
|
+
refineSlot(slot, variantNumber);
|
|
310
|
+
setPreviewSlotId(null);
|
|
311
|
+
}}
|
|
312
|
+
onDismiss={(slot) =>
|
|
313
|
+
dismissSlotById(slot, () => setPreviewSlotId(null))
|
|
314
|
+
}
|
|
315
|
+
/>
|
|
316
|
+
|
|
209
317
|
<section className="mx-auto mb-4 w-full max-w-[760px] px-4">
|
|
210
318
|
<div className="overflow-hidden rounded-xl border border-border bg-card shadow-sm">
|
|
211
319
|
<div className="flex items-start justify-between gap-3 border-b border-border/80 px-3 py-3">
|
|
@@ -244,64 +352,18 @@ export function GenerationResults({ threadId }: { threadId: string | null }) {
|
|
|
244
352
|
</div>
|
|
245
353
|
|
|
246
354
|
<div className="max-h-[min(640px,52vh)] overflow-y-auto p-3">
|
|
247
|
-
<div
|
|
248
|
-
className={
|
|
249
|
-
slots.length === 1
|
|
250
|
-
? "grid grid-cols-1 gap-3"
|
|
251
|
-
: "grid grid-cols-1 gap-3 sm:grid-cols-2"
|
|
252
|
-
}
|
|
253
|
-
>
|
|
355
|
+
<div className="assets-library-grid grid grid-cols-2 gap-3 sm:grid-cols-3">
|
|
254
356
|
{slots.map((slot, index) => (
|
|
255
|
-
<
|
|
357
|
+
<GenerationDraftCard
|
|
256
358
|
key={slot.slotId}
|
|
257
359
|
slot={slot}
|
|
258
|
-
|
|
259
|
-
prompt={variants.prompt}
|
|
260
|
-
libraryTitle={libraryTitle}
|
|
360
|
+
variantNumber={index + 1}
|
|
261
361
|
isSaving={saveGenerated.isPending}
|
|
262
362
|
isDismissing={dismissSlot.isPending}
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
...(slot.assetId ? { assetId: slot.assetId } : {}),
|
|
268
|
-
...(slot.slotId ? { slotId: slot.slotId } : {}),
|
|
269
|
-
threadId,
|
|
270
|
-
},
|
|
271
|
-
{
|
|
272
|
-
onSuccess: () => {
|
|
273
|
-
toast.success(t("library.savedGeneratedAsset"));
|
|
274
|
-
void queryClient.invalidateQueries({
|
|
275
|
-
queryKey: stateQueryKey,
|
|
276
|
-
});
|
|
277
|
-
void queryClient.invalidateQueries({
|
|
278
|
-
queryKey: ["action", "get-library"],
|
|
279
|
-
});
|
|
280
|
-
},
|
|
281
|
-
onError: (error) =>
|
|
282
|
-
toast.error(
|
|
283
|
-
error.message || t("library.couldNotSaveCandidate"),
|
|
284
|
-
),
|
|
285
|
-
},
|
|
286
|
-
);
|
|
287
|
-
}}
|
|
288
|
-
onDismiss={() => {
|
|
289
|
-
dismissSlot.mutate(
|
|
290
|
-
{ slotId: slot.slotId, threadId },
|
|
291
|
-
{
|
|
292
|
-
onSuccess: () => {
|
|
293
|
-
void queryClient.invalidateQueries({
|
|
294
|
-
queryKey: stateQueryKey,
|
|
295
|
-
});
|
|
296
|
-
},
|
|
297
|
-
onError: (error) =>
|
|
298
|
-
toast.error(
|
|
299
|
-
error.message ||
|
|
300
|
-
t("library.couldNotDismissCandidate"),
|
|
301
|
-
),
|
|
302
|
-
},
|
|
303
|
-
);
|
|
304
|
-
}}
|
|
363
|
+
onPreview={() => setPreviewSlotId(slot.slotId)}
|
|
364
|
+
onSave={() => saveSlot(slot)}
|
|
365
|
+
onRefine={() => refineSlot(slot, index + 1)}
|
|
366
|
+
onDismiss={() => dismissSlotById(slot)}
|
|
305
367
|
/>
|
|
306
368
|
))}
|
|
307
369
|
</div>
|
|
@@ -312,117 +374,315 @@ export function GenerationResults({ threadId }: { threadId: string | null }) {
|
|
|
312
374
|
);
|
|
313
375
|
}
|
|
314
376
|
|
|
315
|
-
function
|
|
377
|
+
function GenerationDraftCard({
|
|
316
378
|
slot,
|
|
317
|
-
|
|
318
|
-
prompt,
|
|
319
|
-
libraryTitle,
|
|
379
|
+
variantNumber,
|
|
320
380
|
isSaving,
|
|
321
381
|
isDismissing,
|
|
382
|
+
onPreview,
|
|
322
383
|
onSave,
|
|
384
|
+
onRefine,
|
|
323
385
|
onDismiss,
|
|
324
386
|
}: {
|
|
325
|
-
slot:
|
|
326
|
-
|
|
327
|
-
prompt: string;
|
|
328
|
-
libraryTitle: string | null;
|
|
387
|
+
slot: VariantSlot;
|
|
388
|
+
variantNumber: number;
|
|
329
389
|
isSaving: boolean;
|
|
330
390
|
isDismissing: boolean;
|
|
391
|
+
onPreview: () => void;
|
|
331
392
|
onSave: () => void;
|
|
393
|
+
onRefine: () => void;
|
|
332
394
|
onDismiss: () => void;
|
|
333
395
|
}) {
|
|
334
|
-
const ready = slot.status === "ready" && Boolean(slot.assetId);
|
|
335
396
|
const t = useT();
|
|
397
|
+
const ready = slot.status === "ready" && Boolean(slot.assetId);
|
|
398
|
+
const variantLabel = t("library.variantWithNumber", {
|
|
399
|
+
number: variantNumber,
|
|
400
|
+
});
|
|
336
401
|
return (
|
|
337
|
-
<
|
|
338
|
-
<div className="relative
|
|
339
|
-
<
|
|
340
|
-
|
|
341
|
-
{
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
</div>
|
|
351
|
-
<div className="space-y-2 p-2.5">
|
|
352
|
-
<div className="min-w-0 text-xs">
|
|
353
|
-
<div className="truncate font-medium">
|
|
354
|
-
{slot.status === "ready"
|
|
355
|
-
? t("library.readyToSave")
|
|
356
|
-
: slot.status === "pending"
|
|
357
|
-
? t("library.stillRendering")
|
|
358
|
-
: t("library.generationFailed")}
|
|
402
|
+
<div className="overflow-hidden rounded-lg border border-border/80 bg-background transition hover:border-foreground/25 hover:bg-muted/10">
|
|
403
|
+
<div className="group relative">
|
|
404
|
+
<button
|
|
405
|
+
type="button"
|
|
406
|
+
aria-label={t("library.selectAsset", { title: variantLabel })}
|
|
407
|
+
title={variantLabel}
|
|
408
|
+
onClick={() => {
|
|
409
|
+
if (ready) onPreview();
|
|
410
|
+
}}
|
|
411
|
+
className="block w-full text-left focus-visible:outline-none"
|
|
412
|
+
>
|
|
413
|
+
<div className="aspect-[4/3] bg-muted/40">
|
|
414
|
+
<GenerationSlotPreview slot={slot} />
|
|
359
415
|
</div>
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
416
|
+
</button>
|
|
417
|
+
|
|
418
|
+
{slot.status !== "ready" ? (
|
|
419
|
+
<div className="absolute left-2 top-2 z-10 flex items-center gap-1 rounded-full border border-border/70 bg-background/90 px-2 py-1 text-[11px] font-medium shadow-sm">
|
|
420
|
+
{slot.status === "pending" ? <Spinner className="h-3 w-3" /> : null}
|
|
421
|
+
<span>
|
|
422
|
+
{slot.status === "pending"
|
|
423
|
+
? t("library.generating")
|
|
424
|
+
: t("library.failed")}
|
|
425
|
+
</span>
|
|
363
426
|
</div>
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
className="
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
427
|
+
) : null}
|
|
428
|
+
|
|
429
|
+
{ready ? (
|
|
430
|
+
<TooltipProvider>
|
|
431
|
+
<div className="absolute right-2 top-2 z-10 flex items-center gap-1.5 opacity-0 transition group-hover:opacity-100 focus-within:opacity-100">
|
|
432
|
+
<Tooltip>
|
|
433
|
+
<TooltipTrigger asChild>
|
|
434
|
+
<button
|
|
435
|
+
type="button"
|
|
436
|
+
aria-label={t("library.save")}
|
|
437
|
+
disabled={isSaving}
|
|
438
|
+
onClick={(event) => {
|
|
439
|
+
event.stopPropagation();
|
|
440
|
+
onSave();
|
|
441
|
+
}}
|
|
442
|
+
className="inline-flex h-8 w-8 items-center justify-center rounded-full bg-background/90 text-foreground shadow-sm transition hover:bg-primary hover:text-primary-foreground focus:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:opacity-60"
|
|
443
|
+
>
|
|
444
|
+
{isSaving ? (
|
|
445
|
+
<Spinner className="h-4 w-4" />
|
|
446
|
+
) : (
|
|
447
|
+
<IconDeviceFloppy className="h-4 w-4" />
|
|
448
|
+
)}
|
|
449
|
+
</button>
|
|
450
|
+
</TooltipTrigger>
|
|
451
|
+
<TooltipContent>{t("library.save")}</TooltipContent>
|
|
452
|
+
</Tooltip>
|
|
453
|
+
<Tooltip>
|
|
454
|
+
<TooltipTrigger asChild>
|
|
455
|
+
<button
|
|
456
|
+
type="button"
|
|
457
|
+
aria-label={t("library.refine")}
|
|
458
|
+
onClick={(event) => {
|
|
459
|
+
event.stopPropagation();
|
|
460
|
+
onRefine();
|
|
461
|
+
}}
|
|
462
|
+
className="inline-flex h-8 w-8 items-center justify-center rounded-full bg-background/90 text-foreground shadow-sm transition hover:bg-primary hover:text-primary-foreground focus:outline-none focus-visible:ring-2 focus-visible:ring-ring"
|
|
463
|
+
>
|
|
464
|
+
<IconMessageCircle className="h-4 w-4" />
|
|
465
|
+
</button>
|
|
466
|
+
</TooltipTrigger>
|
|
467
|
+
<TooltipContent>{t("library.refine")}</TooltipContent>
|
|
468
|
+
</Tooltip>
|
|
469
|
+
<Tooltip>
|
|
470
|
+
<TooltipTrigger asChild>
|
|
471
|
+
<button
|
|
472
|
+
type="button"
|
|
473
|
+
aria-label={t("library.deleteCandidate")}
|
|
474
|
+
disabled={isDismissing}
|
|
475
|
+
onClick={(event) => {
|
|
476
|
+
event.stopPropagation();
|
|
477
|
+
onDismiss();
|
|
478
|
+
}}
|
|
479
|
+
className="inline-flex h-8 w-8 items-center justify-center rounded-full bg-background/90 text-foreground shadow-sm transition hover:bg-destructive hover:text-destructive-foreground focus:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:opacity-60"
|
|
480
|
+
>
|
|
481
|
+
<IconTrash className="h-4 w-4" />
|
|
482
|
+
</button>
|
|
483
|
+
</TooltipTrigger>
|
|
484
|
+
<TooltipContent>{t("library.deleteCandidate")}</TooltipContent>
|
|
485
|
+
</Tooltip>
|
|
486
|
+
</div>
|
|
487
|
+
</TooltipProvider>
|
|
488
|
+
) : (
|
|
489
|
+
<button
|
|
490
|
+
type="button"
|
|
406
491
|
aria-label={t("library.deleteCandidate")}
|
|
492
|
+
disabled={isDismissing}
|
|
493
|
+
onClick={(event) => {
|
|
494
|
+
event.stopPropagation();
|
|
495
|
+
onDismiss();
|
|
496
|
+
}}
|
|
497
|
+
className="absolute right-2 top-2 z-10 inline-flex h-8 w-8 items-center justify-center rounded-full bg-background/90 text-muted-foreground shadow-sm transition hover:bg-destructive hover:text-destructive-foreground focus-visible:ring-2 focus-visible:ring-ring disabled:opacity-60"
|
|
407
498
|
>
|
|
408
|
-
<IconTrash className="h-
|
|
409
|
-
</
|
|
410
|
-
|
|
499
|
+
<IconTrash className="h-4 w-4" />
|
|
500
|
+
</button>
|
|
501
|
+
)}
|
|
502
|
+
</div>
|
|
503
|
+
<div className="px-2 py-1.5 text-center text-xs font-medium text-muted-foreground">
|
|
504
|
+
{variantLabel}
|
|
411
505
|
</div>
|
|
412
|
-
</
|
|
506
|
+
</div>
|
|
413
507
|
);
|
|
414
508
|
}
|
|
415
509
|
|
|
416
|
-
function
|
|
510
|
+
function GenerationPreviewDialog({
|
|
417
511
|
slot,
|
|
512
|
+
slots,
|
|
513
|
+
prompt,
|
|
514
|
+
libraryTitle,
|
|
515
|
+
isSaving,
|
|
516
|
+
isDismissing,
|
|
517
|
+
onOpenChange,
|
|
518
|
+
onSelect,
|
|
519
|
+
onSave,
|
|
520
|
+
onRefine,
|
|
521
|
+
onDismiss,
|
|
418
522
|
}: {
|
|
419
|
-
slot:
|
|
523
|
+
slot: VariantSlot | null;
|
|
524
|
+
slots: VariantSlot[];
|
|
525
|
+
prompt: string;
|
|
526
|
+
libraryTitle: string | null;
|
|
527
|
+
isSaving: boolean;
|
|
528
|
+
isDismissing: boolean;
|
|
529
|
+
onOpenChange: (open: boolean) => void;
|
|
530
|
+
onSelect: (slotId: string) => void;
|
|
531
|
+
onSave: (slot: VariantSlot) => void;
|
|
532
|
+
onRefine: (slot: VariantSlot, variantNumber: number) => void;
|
|
533
|
+
onDismiss: (slot: VariantSlot) => void;
|
|
420
534
|
}) {
|
|
535
|
+
const t = useT();
|
|
536
|
+
const previewableSlots = useMemo(
|
|
537
|
+
() =>
|
|
538
|
+
slots.filter((item) => item.status === "ready" && Boolean(item.assetId)),
|
|
539
|
+
[slots],
|
|
540
|
+
);
|
|
541
|
+
const previewIndex = slot
|
|
542
|
+
? previewableSlots.findIndex((item) => item.slotId === slot.slotId)
|
|
543
|
+
: -1;
|
|
544
|
+
const hasPrev = previewIndex > 0;
|
|
545
|
+
const hasNext =
|
|
546
|
+
previewIndex >= 0 && previewIndex < previewableSlots.length - 1;
|
|
547
|
+
const showPreviousSlot = () => {
|
|
548
|
+
if (hasPrev) onSelect(previewableSlots[previewIndex - 1].slotId);
|
|
549
|
+
};
|
|
550
|
+
const showNextSlot = () => {
|
|
551
|
+
if (hasNext) onSelect(previewableSlots[previewIndex + 1].slotId);
|
|
552
|
+
};
|
|
553
|
+
const sources = slot ? assetPreviewSources(slot, "preview") : [];
|
|
554
|
+
const src = sources[0];
|
|
555
|
+
const variantNumber = slot
|
|
556
|
+
? slots.findIndex((item) => item.slotId === slot.slotId) + 1
|
|
557
|
+
: 0;
|
|
558
|
+
const variantLabel = t("library.variantWithNumber", {
|
|
559
|
+
number: variantNumber,
|
|
560
|
+
});
|
|
561
|
+
return (
|
|
562
|
+
<Dialog open={Boolean(slot)} onOpenChange={onOpenChange}>
|
|
563
|
+
{slot ? (
|
|
564
|
+
<DialogContent
|
|
565
|
+
hideClose
|
|
566
|
+
onKeyDown={(event) => {
|
|
567
|
+
if (event.key === "ArrowLeft") showPreviousSlot();
|
|
568
|
+
if (event.key === "ArrowRight") showNextSlot();
|
|
569
|
+
}}
|
|
570
|
+
className="flex max-h-[85vh] w-[calc(100vw-24px)] max-w-4xl flex-col gap-0 overflow-hidden p-0"
|
|
571
|
+
>
|
|
572
|
+
<DialogTitle className="sr-only">{variantLabel}</DialogTitle>
|
|
573
|
+
<DialogDescription className="sr-only">
|
|
574
|
+
{prompt || t("library.readyToSave")}
|
|
575
|
+
</DialogDescription>
|
|
576
|
+
|
|
577
|
+
<div className="flex shrink-0 items-center justify-between gap-3 border-b border-border/80 px-4 py-3">
|
|
578
|
+
<p className="min-w-0 truncate text-sm font-medium">
|
|
579
|
+
{variantLabel}
|
|
580
|
+
</p>
|
|
581
|
+
<div className="flex shrink-0 items-center gap-2">
|
|
582
|
+
<Button
|
|
583
|
+
size="sm"
|
|
584
|
+
disabled={isSaving || !slot.assetId}
|
|
585
|
+
onClick={() => onSave(slot)}
|
|
586
|
+
>
|
|
587
|
+
{isSaving ? <Spinner className="h-4 w-4" /> : t("library.save")}
|
|
588
|
+
</Button>
|
|
589
|
+
<Button
|
|
590
|
+
variant="outline"
|
|
591
|
+
size="sm"
|
|
592
|
+
className="gap-1"
|
|
593
|
+
disabled={!slot.assetId}
|
|
594
|
+
onClick={() => onRefine(slot, variantNumber)}
|
|
595
|
+
>
|
|
596
|
+
<IconMessageCircle className="h-4 w-4" />
|
|
597
|
+
{t("library.refine")}
|
|
598
|
+
</Button>
|
|
599
|
+
{slot.assetId ? (
|
|
600
|
+
<Button asChild variant="outline" size="sm">
|
|
601
|
+
<Link
|
|
602
|
+
to={`/asset/${encodeURIComponent(slot.assetId)}`}
|
|
603
|
+
onClick={() => onOpenChange(false)}
|
|
604
|
+
>
|
|
605
|
+
{t("library.viewDetails")}
|
|
606
|
+
</Link>
|
|
607
|
+
</Button>
|
|
608
|
+
) : null}
|
|
609
|
+
<Button
|
|
610
|
+
variant="outline"
|
|
611
|
+
size="icon"
|
|
612
|
+
className="h-8 w-8 text-muted-foreground hover:bg-destructive/10 hover:text-destructive"
|
|
613
|
+
disabled={isDismissing}
|
|
614
|
+
onClick={() => onDismiss(slot)}
|
|
615
|
+
aria-label={t("library.deleteCandidate")}
|
|
616
|
+
>
|
|
617
|
+
{isDismissing ? (
|
|
618
|
+
<Spinner className="h-4 w-4" />
|
|
619
|
+
) : (
|
|
620
|
+
<IconTrash className="h-4 w-4" />
|
|
621
|
+
)}
|
|
622
|
+
</Button>
|
|
623
|
+
<DialogClose
|
|
624
|
+
aria-label={t("library.closePreview")}
|
|
625
|
+
className="inline-flex h-8 w-8 shrink-0 items-center justify-center rounded-md text-muted-foreground transition hover:bg-accent hover:text-foreground focus:outline-none focus-visible:ring-2 focus-visible:ring-ring"
|
|
626
|
+
>
|
|
627
|
+
<IconX className="h-4 w-4" />
|
|
628
|
+
</DialogClose>
|
|
629
|
+
</div>
|
|
630
|
+
</div>
|
|
631
|
+
|
|
632
|
+
<div className="flex min-h-0 flex-1 items-center justify-center overflow-auto bg-muted/20 p-4 sm:p-6">
|
|
633
|
+
{src ? (
|
|
634
|
+
<img
|
|
635
|
+
src={src}
|
|
636
|
+
alt={prompt || ""}
|
|
637
|
+
className="max-h-full max-w-full rounded-lg bg-black object-contain"
|
|
638
|
+
/>
|
|
639
|
+
) : (
|
|
640
|
+
<div className="flex h-64 w-full items-center justify-center rounded-lg bg-muted">
|
|
641
|
+
<IconPhoto className="h-8 w-8 text-muted-foreground" />
|
|
642
|
+
</div>
|
|
643
|
+
)}
|
|
644
|
+
</div>
|
|
645
|
+
|
|
646
|
+
{hasPrev || hasNext ? (
|
|
647
|
+
<div className="flex shrink-0 items-center justify-center gap-2 border-t border-border/80 py-3">
|
|
648
|
+
<button
|
|
649
|
+
type="button"
|
|
650
|
+
aria-label={t("library.previousImage")}
|
|
651
|
+
onClick={showPreviousSlot}
|
|
652
|
+
disabled={!hasPrev}
|
|
653
|
+
className="inline-flex h-9 w-9 items-center justify-center rounded-full text-foreground transition hover:bg-accent focus:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-40"
|
|
654
|
+
>
|
|
655
|
+
<IconChevronLeft className="h-5 w-5" />
|
|
656
|
+
</button>
|
|
657
|
+
<button
|
|
658
|
+
type="button"
|
|
659
|
+
aria-label={t("library.nextImage")}
|
|
660
|
+
onClick={showNextSlot}
|
|
661
|
+
disabled={!hasNext}
|
|
662
|
+
className="inline-flex h-9 w-9 items-center justify-center rounded-full text-foreground transition hover:bg-accent focus:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-40"
|
|
663
|
+
>
|
|
664
|
+
<IconChevronRight className="h-5 w-5" />
|
|
665
|
+
</button>
|
|
666
|
+
</div>
|
|
667
|
+
) : null}
|
|
668
|
+
</DialogContent>
|
|
669
|
+
) : null}
|
|
670
|
+
</Dialog>
|
|
671
|
+
);
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
function GenerationSlotPreview({ slot }: { slot: VariantSlot }) {
|
|
421
675
|
const t = useT();
|
|
422
676
|
const sources = assetPreviewSources(slot, "thumbnail");
|
|
423
677
|
const src = sources[0];
|
|
424
678
|
if (src) {
|
|
425
|
-
return
|
|
679
|
+
return (
|
|
680
|
+
<img
|
|
681
|
+
src={src}
|
|
682
|
+
alt=""
|
|
683
|
+
className="h-full w-full object-contain transition group-hover:scale-[1.02]"
|
|
684
|
+
/>
|
|
685
|
+
);
|
|
426
686
|
}
|
|
427
687
|
if (slot.status === "failed") {
|
|
428
688
|
return (
|
|
@@ -812,6 +812,7 @@ const enUS = {
|
|
|
812
812
|
candidates: "Candidates",
|
|
813
813
|
candidateActions: "Candidate actions",
|
|
814
814
|
candidateWithNumber: "Candidate {{number}}",
|
|
815
|
+
variantWithNumber: "Variant {{number}}",
|
|
815
816
|
checkingImageLibraries: "Checking image libraries...",
|
|
816
817
|
checking: "Checking",
|
|
817
818
|
checkingUpload: "Checking upload",
|