@agent-native/core 0.80.10 → 0.81.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/corpus/README.md +1 -1
- package/corpus/core/CHANGELOG.md +53 -0
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/agent/production-agent.ts +108 -15
- package/corpus/core/src/cli/design-connect.ts +419 -19
- package/corpus/core/src/client/AssistantChat.tsx +123 -26
- package/corpus/core/src/client/ConnectBuilderCard.tsx +1 -0
- package/corpus/core/src/client/chat/index.ts +1 -0
- package/corpus/core/src/client/chat/run-recovery.tsx +9 -7
- package/corpus/core/src/client/chat-view-transition.ts +33 -2
- package/corpus/core/src/client/composer/PromptComposer.tsx +21 -2
- package/corpus/core/src/client/index.ts +1 -0
- package/corpus/core/src/client/org/OrgSwitcher.tsx +26 -4
- package/corpus/core/src/client/sharing/ShareButton.tsx +3 -3
- package/corpus/core/src/client/sse-event-processor.ts +9 -0
- package/corpus/core/src/client/use-agent-chat-home-handoff.ts +31 -3
- package/corpus/core/src/db/client.ts +29 -2
- package/corpus/core/src/provider-api/index.ts +29 -0
- package/corpus/core/src/server/core-routes-plugin.ts +58 -20
- package/corpus/core/src/styles/agent-native.css +54 -0
- package/corpus/core/src/usage/store.ts +2 -2
- package/corpus/templates/analytics/app/components/layout/Layout.tsx +118 -10
- package/corpus/templates/analytics/app/components/layout/layout-route-policy.ts +7 -0
- package/corpus/templates/analytics/app/global.css +8 -0
- package/corpus/templates/analytics/app/hooks/use-navigation-state.ts +7 -1
- package/corpus/templates/analytics/app/lib/chat-handoff.ts +34 -0
- package/corpus/templates/analytics/app/pages/Ask.tsx +9 -18
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +2 -2
- package/corpus/templates/analytics/app/pages/sessions/SessionDetailPage.tsx +109 -21
- package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +4 -6
- package/corpus/templates/analytics/changelog/2026-06-30-ask-opens-a-fresh-chat-unless-you-were-just-chatting-and-das.md +6 -0
- package/corpus/templates/analytics/changelog/2026-06-30-dashboard-email-reports-are-more-reliable-and-use-cleaner.md +6 -0
- package/corpus/templates/analytics/changelog/2026-06-30-dashboard-toolbar-controls-use-a-quieter-share-button-and-ve.md +6 -0
- package/corpus/templates/analytics/changelog/2026-06-30-session-replay-rows-show-whole-minute-durations-in-the-playl.md +6 -0
- package/corpus/templates/analytics/changelog/2026-06-30-session-replays-now-render-captured-styling-and-keep-the-eve.md +6 -0
- package/corpus/templates/analytics/server/jobs/dashboard-report.ts +16 -3
- package/corpus/templates/analytics/server/lib/dashboard-report.ts +31 -14
- package/corpus/templates/assets/.agents/skills/image-generation/SKILL.md +9 -2
- package/corpus/templates/assets/AGENTS.md +4 -0
- package/corpus/templates/assets/actions/_tool-activity.ts +46 -0
- package/corpus/templates/assets/actions/generate-image-batch.ts +26 -5
- package/corpus/templates/assets/actions/generate-image.ts +118 -67
- package/corpus/templates/assets/actions/list-draft-assets.ts +50 -0
- package/corpus/templates/assets/actions/open-asset-picker.ts +9 -0
- package/corpus/templates/assets/actions/rerun-generation-run.ts +52 -31
- package/corpus/templates/assets/app/components/create/RecentDraftsSection.tsx +100 -0
- package/corpus/templates/assets/app/global.css +15 -0
- package/corpus/templates/assets/app/hooks/use-navigation-state.ts +4 -0
- package/corpus/templates/assets/app/i18n/zh-TW.ts +7 -0
- package/corpus/templates/assets/app/i18n-data.ts +61 -0
- package/corpus/templates/assets/app/routes/_index.tsx +4 -0
- package/corpus/templates/assets/app/routes/library.tsx +233 -52
- package/corpus/templates/assets/changelog/2026-06-29-image-generation-can-now-render-requested-text-and-respect-b.md +6 -0
- package/corpus/templates/assets/changelog/2026-06-30-image-generation-no-longer-looks-stuck-while-the-provider-is-still-working.md +6 -0
- package/corpus/templates/assets/changelog/2026-06-30-tagged-presets-now-control-the-image-aspect-ratio.md +6 -0
- package/corpus/templates/assets/changelog/2026-06-30-the-assets-picker-now-supports-a-vertical-embedded-layout-fo.md +6 -0
- package/corpus/templates/assets/server/lib/generation.ts +135 -11
- package/corpus/templates/assets/shared/api.ts +4 -0
- package/corpus/templates/clips/actions/finalize-recording.ts +1 -12
- package/corpus/templates/clips/actions/list-ai-requests.ts +60 -0
- package/corpus/templates/clips/app/hooks/use-auto-title.ts +24 -25
- package/corpus/templates/clips/app/routes/r.$recordingId.tsx +10 -5
- package/corpus/templates/clips/app/routes/share.$shareId.tsx +6 -8
- package/corpus/templates/clips/changelog/2026-06-30-extension-save-recovery-avoids-false-upload-failures.md +6 -0
- package/corpus/templates/clips/changelog/2026-06-30-longer-chrome-extension-recordings-now-keep-saving-reliably-.md +6 -0
- package/corpus/templates/clips/chrome-extension/public/manifest.json +1 -1
- package/corpus/templates/clips/chrome-extension/src/background.ts +19 -10
- package/corpus/templates/clips/chrome-extension/src/content-script.ts +38 -12
- package/corpus/templates/clips/chrome-extension/src/finalize-recovery.ts +224 -0
- package/corpus/templates/clips/chrome-extension/src/offscreen.ts +119 -16
- package/corpus/templates/clips/chrome-extension/src/overlay.ts +16 -0
- package/corpus/templates/clips/server/lib/recording-upload-state.ts +48 -0
- package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/abort.post.ts +9 -1
- package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/chunk.post.ts +63 -13
- package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/status.get.ts +74 -0
- package/corpus/templates/design/.agents/skills/design-systems/SKILL.md +32 -0
- package/corpus/templates/design/AGENTS.md +27 -0
- package/corpus/templates/design/CODE_NATIVE_DESIGN_STUDIO_IMPLEMENTATION_PLAN.md +1 -1
- package/corpus/templates/design/DESIGN-STUDIO-PLAN.md +5 -5
- package/corpus/templates/design/actions/apply-component-prop-edit.ts +76 -25
- package/corpus/templates/design/actions/apply-design-state.ts +17 -4
- package/corpus/templates/design/actions/apply-motion-edit.ts +76 -115
- package/corpus/templates/design/actions/apply-shader-fill.ts +148 -56
- package/corpus/templates/design/actions/capture-design-state.ts +27 -4
- package/corpus/templates/design/actions/connect-localhost.ts +59 -22
- package/corpus/templates/design/actions/delete-design.ts +20 -0
- package/corpus/templates/design/actions/export-zip.ts +23 -8
- package/corpus/templates/design/actions/generate-design.ts +53 -1
- package/corpus/templates/design/actions/get-component-details.ts +21 -26
- package/corpus/templates/design/actions/get-motion-timeline.ts +135 -10
- package/corpus/templates/design/actions/grant-localhost-write-consent.ts +116 -0
- package/corpus/templates/design/actions/import-design-tokens.ts +521 -0
- package/corpus/templates/design/actions/index-design-tokens.ts +18 -5
- package/corpus/templates/design/actions/insert-design-native-asset.ts +268 -0
- package/corpus/templates/design/actions/insert-figma-library-asset.ts +233 -0
- package/corpus/templates/design/actions/list-design-extensions.ts +32 -10
- package/corpus/templates/design/actions/list-design-native-assets.ts +105 -0
- package/corpus/templates/design/actions/list-design-states.ts +19 -1
- package/corpus/templates/design/actions/list-figma-library-assets.ts +292 -0
- package/corpus/templates/design/actions/migrate-board-objects-to-file.ts +238 -0
- package/corpus/templates/design/actions/navigate.ts +18 -3
- package/corpus/templates/design/actions/open-component-source.ts +7 -2
- package/corpus/templates/design/actions/preview-component-prop-edit.ts +32 -26
- package/corpus/templates/design/actions/preview-shader-fill.ts +9 -11
- package/corpus/templates/design/actions/provider-api-catalog.ts +2 -2
- package/corpus/templates/design/actions/provider-api-docs.ts +1 -1
- package/corpus/templates/design/actions/provider-api-request.ts +3 -3
- package/corpus/templates/design/actions/revoke-localhost-write-consent.ts +48 -0
- package/corpus/templates/design/actions/run-design-audit.ts +74 -10
- package/corpus/templates/design/actions/run-design-extension-action.ts +1 -1
- package/corpus/templates/design/actions/view-screen.ts +1 -1
- package/corpus/templates/design/actions/write-local-file.ts +213 -0
- package/corpus/templates/design/app/components/design/DesignCanvas.tsx +244 -3197
- package/corpus/templates/design/app/components/design/DesignEditorSkeleton.tsx +30 -20
- package/corpus/templates/design/app/components/design/DesignExtensionsPanel.tsx +795 -289
- package/corpus/templates/design/app/components/design/EditPanel.tsx +635 -234
- package/corpus/templates/design/app/components/design/LayersPanel.tsx +124 -32
- package/corpus/templates/design/app/components/design/LocalhostWriteConsentDialog.tsx +161 -0
- package/corpus/templates/design/app/components/design/MotionDock.tsx +244 -266
- package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +491 -56
- package/corpus/templates/design/app/components/design/ReviewPanel.tsx +55 -67
- package/corpus/templates/design/app/components/design/StatesPanel.tsx +38 -63
- package/corpus/templates/design/app/components/design/TokensPanel.tsx +264 -8
- package/corpus/templates/design/app/components/design/bridge/codegen.ts +125 -0
- package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +4037 -0
- package/corpus/templates/design/app/components/design/bridge/embedded-wheel.bridge.ts +62 -0
- package/corpus/templates/design/app/components/design/bridge/hit-test.bridge.ts +272 -0
- package/corpus/templates/design/app/components/design/bridge/nav.bridge.ts +116 -0
- package/corpus/templates/design/app/components/design/bridge/sample.bridge.ts +24 -0
- package/corpus/templates/design/app/components/design/bridge/shader-fill-preview.bridge.ts +78 -0
- package/corpus/templates/design/app/components/design/bridge/tsconfig.json +17 -0
- package/corpus/templates/design/app/components/design/bridge/tweak.bridge.ts +28 -0
- package/corpus/templates/design/app/components/design/bridge/zoom.bridge.ts +43 -0
- package/corpus/templates/design/app/components/design/inspector/DesignColorPicker.tsx +45 -16
- package/corpus/templates/design/app/components/design/inspector/ImageFillControls.tsx +88 -9
- package/corpus/templates/design/app/components/editor/PromptDialog.tsx +94 -9
- package/corpus/templates/design/app/components/layout/Layout.tsx +19 -3
- package/corpus/templates/design/app/components/layout/Sidebar.tsx +1 -1
- package/corpus/templates/design/app/global.css +7 -0
- package/corpus/templates/design/app/hooks/use-navigation-state.ts +23 -0
- package/corpus/templates/design/app/i18n/zh-TW.ts +22 -0
- package/corpus/templates/design/app/i18n-data.ts +369 -0
- package/corpus/templates/design/app/lib/pending-generation.ts +1 -0
- package/corpus/templates/design/app/pages/DesignEditor.tsx +3024 -616
- package/corpus/templates/design/app/pages/Index.tsx +5 -1
- package/corpus/templates/design/changelog/2026-06-30-applying-the-one-click-fix-for-a-small-tap-target-accessibil.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-canvas-creation-screen-dragging-undo-redo-and-image-fill-edi.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-component-prop-edits-and-shader-fills-now-preserve-rapid-sam.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-design-can-browse-figma-library-components-and-insert-them-i.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-design-now-has-a-figma-style-left-rail-for-file-agent-assets.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-design-now-has-native-components-embedded-media-and-figma-im.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-design-preview-now-includes-a-publish-app-waitlist-option-fr.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-design-s-left-rail-now-matches-the-sidebar-chrome-and-uses-t.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-design-s-tools-create-menu-now-stays-compact-instead-of-rend.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-design-starter-prompts-now-begin-generating-immediately-and-.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-design-token-edits-now-stay-visible-in-previews-and-token-li.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-design-tools-now-use-a-quieter-figma-style-list-layout.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-drawing-rectangles-on-the-all-screens-canvas-no-longer-flash.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-fixed-code-native-design-studio-edits-so-component-props-mot.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-fixed-visual-editing-hover-overlays-and-spacing-handles-so-s.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-motion-edits-now-save-automatically-without-a-separate-css-a.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-motion-timelines-now-reopen-as-editable-tracks-after-writing.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-new-design-prompts-with-uploaded-screenshots-work-reliably-o.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-screen-previews-in-all-screens-view-now-keep-rounded-outline.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-selection-outlines-now-sit-flush-on-rectangles-drawn-directl.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-share-options-use-a-tighter-design-editor-popover-with-compa.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-the-collapsed-motion-panel-now-stays-tucked-under-the-left-s.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-the-design-inspector-now-shows-states-and-review-in-a-tighte.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-the-sidebar-keeps-the-organization-picker-space-stable-while.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-tokens-can-now-be-imported-from-pasted-notes-code-files-fold.md +6 -0
- package/corpus/templates/design/e2e/global-setup.ts +94 -2
- package/corpus/templates/design/e2e/helpers.ts +168 -65
- package/corpus/templates/design/package.json +3 -1
- package/corpus/templates/design/server/db/schema.ts +23 -0
- package/corpus/templates/design/server/handlers/uploads.ts +22 -1
- package/corpus/templates/design/server/lib/provider-api.ts +7 -4
- package/corpus/templates/design/server/lib/verify-write-grant.ts +108 -0
- package/corpus/templates/design/server/plugins/db.ts +39 -0
- package/corpus/templates/design/server/register-secrets.ts +38 -0
- package/corpus/templates/design/shared/board-file.ts +228 -0
- package/corpus/templates/design/shared/board-objects.ts +288 -0
- package/corpus/templates/design/shared/code-layer.ts +52 -0
- package/corpus/templates/design/shared/component-model.ts +35 -0
- package/corpus/templates/design/shared/motion-compiler.ts +137 -15
- package/corpus/templates/design/shared/motion-timeline.ts +2 -2
- package/corpus/templates/design/shared/resolve-tweaks.ts +32 -9
- package/corpus/templates/design/tsconfig.json +2 -1
- package/corpus/templates/slides/AGENTS.md +9 -0
- package/corpus/templates/slides/app/components/editor/EditorToolbar.tsx +4 -0
- package/corpus/templates/slides/app/components/editor/ExportMenu.tsx +4 -24
- package/corpus/templates/slides/app/lib/export-pdf-client.ts +29 -20
- package/corpus/templates/slides/app/lib/export-pptx-client.ts +365 -0
- package/corpus/templates/slides/app/pages/DeckEditor.tsx +12 -9
- package/corpus/templates/slides/app/vite-env.d.ts +18 -0
- package/corpus/templates/slides/changelog/2026-06-30-powerpoint-downloads-now-preserve-the-rendered-slide-layout-.md +6 -0
- package/corpus/templates/slides/changelog/2026-06-30-unavailable-decks-open-in-a-cleaner-full-height-centered-sta.md +6 -0
- package/corpus/templates/slides/package.json +1 -0
- package/corpus/templates/slides/vite.config.ts +1 -0
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +94 -10
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/cli/design-connect.d.ts +25 -0
- package/dist/cli/design-connect.d.ts.map +1 -1
- package/dist/cli/design-connect.js +357 -18
- package/dist/cli/design-connect.js.map +1 -1
- package/dist/client/AssistantChat.d.ts +14 -0
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +115 -22
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/ConnectBuilderCard.d.ts.map +1 -1
- package/dist/client/ConnectBuilderCard.js +1 -0
- package/dist/client/ConnectBuilderCard.js.map +1 -1
- package/dist/client/chat/index.d.ts +1 -1
- package/dist/client/chat/index.d.ts.map +1 -1
- package/dist/client/chat/index.js +1 -1
- package/dist/client/chat/index.js.map +1 -1
- package/dist/client/chat/run-recovery.d.ts.map +1 -1
- package/dist/client/chat/run-recovery.js +5 -5
- package/dist/client/chat/run-recovery.js.map +1 -1
- package/dist/client/chat-view-transition.d.ts +6 -0
- package/dist/client/chat-view-transition.d.ts.map +1 -1
- package/dist/client/chat-view-transition.js +23 -2
- package/dist/client/chat-view-transition.js.map +1 -1
- package/dist/client/composer/PromptComposer.d.ts.map +1 -1
- package/dist/client/composer/PromptComposer.js +3 -2
- package/dist/client/composer/PromptComposer.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/org/OrgSwitcher.d.ts.map +1 -1
- package/dist/client/org/OrgSwitcher.js +11 -4
- package/dist/client/org/OrgSwitcher.js.map +1 -1
- package/dist/client/sharing/ShareButton.js +3 -3
- package/dist/client/sharing/ShareButton.js.map +1 -1
- package/dist/client/sse-event-processor.d.ts.map +1 -1
- package/dist/client/sse-event-processor.js +10 -0
- package/dist/client/sse-event-processor.js.map +1 -1
- package/dist/client/use-agent-chat-home-handoff.d.ts +8 -2
- package/dist/client/use-agent-chat-home-handoff.d.ts.map +1 -1
- package/dist/client/use-agent-chat-home-handoff.js +20 -6
- package/dist/client/use-agent-chat-home-handoff.js.map +1 -1
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/awareness.d.ts.map +1 -1
- package/dist/collab/routes.d.ts +2 -2
- package/dist/db/client.d.ts +1 -0
- package/dist/db/client.d.ts.map +1 -1
- package/dist/db/client.js +28 -2
- package/dist/db/client.js.map +1 -1
- package/dist/notifications/routes.d.ts +3 -3
- package/dist/observability/routes.d.ts +3 -3
- package/dist/progress/routes.d.ts +1 -1
- package/dist/provider-api/index.d.ts +5 -4
- package/dist/provider-api/index.d.ts.map +1 -1
- package/dist/provider-api/index.js +28 -0
- package/dist/provider-api/index.js.map +1 -1
- package/dist/resources/handlers.d.ts +3 -3
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/core-routes-plugin.d.ts +25 -0
- package/dist/server/core-routes-plugin.d.ts.map +1 -1
- package/dist/server/core-routes-plugin.js +43 -18
- package/dist/server/core-routes-plugin.js.map +1 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/dist/styles/agent-native.css +54 -0
- package/dist/usage/store.js +2 -2
- package/dist/usage/store.js.map +1 -1
- package/package.json +1 -1
|
@@ -21,6 +21,7 @@ import {
|
|
|
21
21
|
DEFAULT_GENERATION_REFERENCE_LIMIT,
|
|
22
22
|
generateWithManagedImageProvider,
|
|
23
23
|
isImageGenerationSetupError,
|
|
24
|
+
resolveImageModelForRequest,
|
|
24
25
|
selectReferences,
|
|
25
26
|
} from "../server/lib/generation.js";
|
|
26
27
|
import { compositeLogo } from "../server/lib/image-processing.js";
|
|
@@ -35,7 +36,6 @@ import {
|
|
|
35
36
|
IMAGE_SIZES,
|
|
36
37
|
STYLE_STRENGTHS,
|
|
37
38
|
type ImageCategory,
|
|
38
|
-
type ImageModel,
|
|
39
39
|
type ImageQualityTier,
|
|
40
40
|
type StyleBrief,
|
|
41
41
|
} from "../shared/api.js";
|
|
@@ -44,22 +44,11 @@ import {
|
|
|
44
44
|
serializeAsset,
|
|
45
45
|
} from "./_helpers.js";
|
|
46
46
|
import { readImageModelDefault } from "./_image-model-default.js";
|
|
47
|
+
import { withToolActivity } from "./_tool-activity.js";
|
|
47
48
|
import { upsertVariantSlot, wasVariantSlotDismissed } from "./variant-slots.js";
|
|
48
49
|
|
|
49
50
|
const IMAGE_GENERATION_TOOL_TIMEOUT_MS = 12 * 60_000;
|
|
50
51
|
|
|
51
|
-
function resolveModelForTier(
|
|
52
|
-
tier: ImageQualityTier | undefined,
|
|
53
|
-
category: ImageCategory | undefined,
|
|
54
|
-
): ImageModel | undefined {
|
|
55
|
-
if (!tier) return undefined;
|
|
56
|
-
if (tier === "fast") return "gemini-3.1-flash-image";
|
|
57
|
-
if (tier === "best") return "gemini-3-pro-image";
|
|
58
|
-
return ["hero", "landing", "logo", "campaign"].includes(category ?? "")
|
|
59
|
-
? "gemini-3-pro-image"
|
|
60
|
-
: "gemini-3.1-flash-image";
|
|
61
|
-
}
|
|
62
|
-
|
|
63
52
|
export default defineAction({
|
|
64
53
|
description:
|
|
65
54
|
"Generate one brand-consistent image from a brand kit/library. This is synchronous for images and returns the final asset with preview/download/embed URLs. Use @brand-kit mentions as libraryId and @preset mentions as presetId when present. Use generate-image-batch for multiple independent slots; do not poll image runs after this action returns.",
|
|
@@ -71,11 +60,38 @@ export default defineAction({
|
|
|
71
60
|
"Brand kit/library ID. Pass the refId from a brand-kit @mention, or choose a kit from view-screen/list-libraries.",
|
|
72
61
|
),
|
|
73
62
|
collectionId: z.string().optional(),
|
|
74
|
-
presetId: z
|
|
63
|
+
presetId: z
|
|
64
|
+
.string()
|
|
65
|
+
.optional()
|
|
66
|
+
.describe(
|
|
67
|
+
"Generation preset ID (from a @preset mention or list-generation-presets). A preset already defines aspectRatio, imageSize, model, tier, and category. When you set presetId, OMIT those args so the preset's values are used; only pass one of them when the user explicitly asks for a value that differs from the preset.",
|
|
68
|
+
),
|
|
75
69
|
sessionId: z.string().optional(),
|
|
76
70
|
prompt: z.string().min(1),
|
|
77
|
-
|
|
78
|
-
|
|
71
|
+
embeddedText: z
|
|
72
|
+
.string()
|
|
73
|
+
.optional()
|
|
74
|
+
.describe(
|
|
75
|
+
"Exact words to render inside the image, spelled exactly. When set, the image is allowed to contain this text; when omitted, the image avoids embedded text.",
|
|
76
|
+
),
|
|
77
|
+
textPlacement: z
|
|
78
|
+
.string()
|
|
79
|
+
.optional()
|
|
80
|
+
.describe(
|
|
81
|
+
"Where/how the embedded text should appear, e.g. 'centered headline', 'lower-left label'.",
|
|
82
|
+
),
|
|
83
|
+
aspectRatio: z
|
|
84
|
+
.enum(ASPECT_RATIOS)
|
|
85
|
+
.optional()
|
|
86
|
+
.describe(
|
|
87
|
+
"Image aspect ratio. When a presetId is set, omit this — the preset's aspect ratio is used. Pass a value only when there is no preset, or when the user explicitly asks for a ratio different from the preset's.",
|
|
88
|
+
),
|
|
89
|
+
imageSize: z
|
|
90
|
+
.enum(IMAGE_SIZES)
|
|
91
|
+
.optional()
|
|
92
|
+
.describe(
|
|
93
|
+
"Output resolution tier. When a presetId is set, omit this — the preset's size is used unless the user explicitly requests a different one.",
|
|
94
|
+
),
|
|
79
95
|
model: z.enum(IMAGE_MODELS).optional(),
|
|
80
96
|
tier: z.enum(IMAGE_QUALITY_TIERS).optional(),
|
|
81
97
|
intent: z.enum(GENERATION_INTENTS).default("generate"),
|
|
@@ -251,11 +267,15 @@ export default defineAction({
|
|
|
251
267
|
const category = (args.categories?.[0] ??
|
|
252
268
|
preset?.category ??
|
|
253
269
|
collection?.category) as ImageCategory | undefined;
|
|
254
|
-
const resolvedModel = (
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
270
|
+
const resolvedModel = resolveImageModelForRequest({
|
|
271
|
+
explicitModel: args.model,
|
|
272
|
+
imageModelDefault,
|
|
273
|
+
explicitTier: args.tier,
|
|
274
|
+
resolvedTier,
|
|
275
|
+
category,
|
|
276
|
+
presetModel: preset?.model as (typeof IMAGE_MODELS)[number] | undefined,
|
|
277
|
+
embeddedText: args.embeddedText,
|
|
278
|
+
}) as (typeof IMAGE_MODELS)[number];
|
|
259
279
|
const resolvedCategories =
|
|
260
280
|
args.categories ??
|
|
261
281
|
(preset?.category ? ([preset.category] as any) : undefined);
|
|
@@ -297,6 +317,8 @@ export default defineAction({
|
|
|
297
317
|
.filter((item) => item?.trim())
|
|
298
318
|
.join("\n\n"),
|
|
299
319
|
prompt: promptForRun,
|
|
320
|
+
embeddedText: args.embeddedText,
|
|
321
|
+
textPlacement: args.textPlacement,
|
|
300
322
|
referenceCount: references.length,
|
|
301
323
|
includeLogo: args.includeLogo,
|
|
302
324
|
aspectRatio: resolvedAspectRatio,
|
|
@@ -346,6 +368,8 @@ export default defineAction({
|
|
|
346
368
|
collectionId: resolvedCollectionId ?? null,
|
|
347
369
|
presetId: preset?.id ?? null,
|
|
348
370
|
sessionId: session?.id ?? null,
|
|
371
|
+
embeddedText: args.embeddedText ?? null,
|
|
372
|
+
textPlacement: args.textPlacement ?? null,
|
|
349
373
|
customInstructions: library.customInstructions ?? "",
|
|
350
374
|
};
|
|
351
375
|
const dismissibleSlot = args.dismissible !== false && Boolean(slotId);
|
|
@@ -357,6 +381,8 @@ export default defineAction({
|
|
|
357
381
|
dismissible: dismissibleSlot,
|
|
358
382
|
sourceAssetId: args.sourceAssetId,
|
|
359
383
|
subjectAssetId: args.subjectAssetId,
|
|
384
|
+
embeddedText: args.embeddedText,
|
|
385
|
+
textPlacement: args.textPlacement,
|
|
360
386
|
intent: args.intent,
|
|
361
387
|
styleStrength: args.styleStrength,
|
|
362
388
|
tier: resolvedTier,
|
|
@@ -404,22 +430,36 @@ export default defineAction({
|
|
|
404
430
|
});
|
|
405
431
|
|
|
406
432
|
try {
|
|
407
|
-
const generated = await
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
433
|
+
const generated = await withToolActivity(
|
|
434
|
+
context,
|
|
435
|
+
{
|
|
436
|
+
label: "Generating image.",
|
|
437
|
+
ongoingLabel: "Still generating image.",
|
|
438
|
+
// Intentionally no explicit `tool`: withToolActivity falls back to
|
|
439
|
+
// context.actionName, which is the ACTUAL dispatched tool. When this
|
|
440
|
+
// action is invoked directly that is "generate-image"; when it runs as
|
|
441
|
+
// a sub-step of generate-image-batch / rerun-generation-run it is the
|
|
442
|
+
// parent tool, so the activity event matches the real tool_start card
|
|
443
|
+
// instead of spawning an orphan "generate-image" activity card.
|
|
444
|
+
},
|
|
445
|
+
() =>
|
|
446
|
+
generateWithManagedImageProvider({
|
|
447
|
+
prompt: promptForRun,
|
|
448
|
+
compiledPrompt,
|
|
449
|
+
references,
|
|
450
|
+
model: resolvedModel,
|
|
451
|
+
aspectRatio: resolvedAspectRatio,
|
|
452
|
+
imageSize: resolvedImageSize,
|
|
453
|
+
groundingMode: args.groundingMode,
|
|
454
|
+
intent: args.intent,
|
|
455
|
+
styleStrength: args.styleStrength,
|
|
456
|
+
runId,
|
|
457
|
+
libraryId: args.libraryId,
|
|
458
|
+
collectionId: resolvedCollectionId ?? null,
|
|
459
|
+
source: args.source,
|
|
460
|
+
callerAppId: args.callerAppId,
|
|
461
|
+
}),
|
|
462
|
+
);
|
|
423
463
|
await deleteAppState("image-generation-setup").catch(() => {});
|
|
424
464
|
let image = generated.image;
|
|
425
465
|
let mimeType = generated.mimeType;
|
|
@@ -468,37 +508,48 @@ export default defineAction({
|
|
|
468
508
|
Artifacts: [],
|
|
469
509
|
};
|
|
470
510
|
}
|
|
471
|
-
const asset = await
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
model: generated.model,
|
|
480
|
-
aspectRatio: resolvedAspectRatio,
|
|
481
|
-
imageSize: resolvedImageSize,
|
|
482
|
-
generationRunId: runId,
|
|
483
|
-
metadata: {
|
|
484
|
-
provider: generated.provider,
|
|
485
|
-
compiledPrompt,
|
|
486
|
-
referenceAssetIds: references.map((ref) => ref.id),
|
|
487
|
-
sourceAssetId: args.sourceAssetId,
|
|
488
|
-
subjectAssetId: args.subjectAssetId,
|
|
489
|
-
intent: args.intent,
|
|
490
|
-
styleStrength: args.styleStrength,
|
|
491
|
-
tier: resolvedTier,
|
|
492
|
-
includeLogo: args.includeLogo,
|
|
493
|
-
presetId: preset?.id,
|
|
494
|
-
sessionId: session?.id,
|
|
495
|
-
generated: true,
|
|
496
|
-
sourceUrl: generated.sourceUrl,
|
|
497
|
-
providerGenerationId: generated.providerGenerationId,
|
|
498
|
-
creditsCharged: generated.creditsCharged,
|
|
511
|
+
const asset = await withToolActivity(
|
|
512
|
+
context,
|
|
513
|
+
{
|
|
514
|
+
label: "Saving generated image.",
|
|
515
|
+
ongoingLabel: "Still saving generated image.",
|
|
516
|
+
// See above: omit `tool` so the activity is tagged with the real
|
|
517
|
+
// dispatched tool (context.actionName) rather than a hardcoded
|
|
518
|
+
// "generate-image" that orphans under batch/rerun.
|
|
499
519
|
},
|
|
500
|
-
|
|
501
|
-
|
|
520
|
+
() =>
|
|
521
|
+
createAssetFromBuffer({
|
|
522
|
+
libraryId: args.libraryId,
|
|
523
|
+
collectionId: resolvedCollectionId ?? null,
|
|
524
|
+
buffer: image,
|
|
525
|
+
mimeType,
|
|
526
|
+
role: "generated",
|
|
527
|
+
status: "candidate",
|
|
528
|
+
prompt: args.prompt,
|
|
529
|
+
model: generated.model,
|
|
530
|
+
aspectRatio: resolvedAspectRatio,
|
|
531
|
+
imageSize: resolvedImageSize,
|
|
532
|
+
generationRunId: runId,
|
|
533
|
+
metadata: {
|
|
534
|
+
provider: generated.provider,
|
|
535
|
+
compiledPrompt,
|
|
536
|
+
referenceAssetIds: references.map((ref) => ref.id),
|
|
537
|
+
sourceAssetId: args.sourceAssetId,
|
|
538
|
+
subjectAssetId: args.subjectAssetId,
|
|
539
|
+
intent: args.intent,
|
|
540
|
+
styleStrength: args.styleStrength,
|
|
541
|
+
tier: resolvedTier,
|
|
542
|
+
includeLogo: args.includeLogo,
|
|
543
|
+
presetId: preset?.id,
|
|
544
|
+
sessionId: session?.id,
|
|
545
|
+
generated: true,
|
|
546
|
+
sourceUrl: generated.sourceUrl,
|
|
547
|
+
providerGenerationId: generated.providerGenerationId,
|
|
548
|
+
creditsCharged: generated.creditsCharged,
|
|
549
|
+
},
|
|
550
|
+
category,
|
|
551
|
+
}),
|
|
552
|
+
);
|
|
502
553
|
if (session) {
|
|
503
554
|
const itemCreatedAt = nowIso();
|
|
504
555
|
await db.insert(schema.assetGenerationSessionItems).values({
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { defineAction } from "@agent-native/core";
|
|
2
|
+
import { accessFilter } from "@agent-native/core/sharing";
|
|
3
|
+
import { and, desc, eq, inArray, isNull } from "drizzle-orm";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
|
|
6
|
+
import { getDb, schema } from "../server/db/index.js";
|
|
7
|
+
import { serializeAsset } from "./_helpers.js";
|
|
8
|
+
|
|
9
|
+
export default defineAction({
|
|
10
|
+
description:
|
|
11
|
+
"List unsaved draft generations (generated candidate assets) across accessible libraries, newest first.",
|
|
12
|
+
schema: z.object({
|
|
13
|
+
libraryId: z.string().optional(),
|
|
14
|
+
limit: z.coerce.number().int().min(1).max(500).optional(),
|
|
15
|
+
}),
|
|
16
|
+
http: { method: "GET" },
|
|
17
|
+
readOnly: true,
|
|
18
|
+
run: async ({ libraryId, limit }) => {
|
|
19
|
+
const db = getDb();
|
|
20
|
+
const libraryFilters = [
|
|
21
|
+
accessFilter(schema.assetLibraries, schema.assetLibraryShares),
|
|
22
|
+
isNull(schema.assetLibraries.archivedAt),
|
|
23
|
+
];
|
|
24
|
+
if (libraryId) libraryFilters.push(eq(schema.assetLibraries.id, libraryId));
|
|
25
|
+
const accessibleLibraries = await db
|
|
26
|
+
.select({ id: schema.assetLibraries.id })
|
|
27
|
+
.from(schema.assetLibraries)
|
|
28
|
+
.where(and(...libraryFilters));
|
|
29
|
+
const libraryIds = accessibleLibraries.map((row) => row.id);
|
|
30
|
+
if (!libraryIds.length) return { count: 0, assets: [] };
|
|
31
|
+
|
|
32
|
+
const rows = await db
|
|
33
|
+
.select()
|
|
34
|
+
.from(schema.assets)
|
|
35
|
+
.where(
|
|
36
|
+
and(
|
|
37
|
+
inArray(schema.assets.libraryId, libraryIds),
|
|
38
|
+
eq(schema.assets.role, "generated"),
|
|
39
|
+
eq(schema.assets.status, "candidate"),
|
|
40
|
+
),
|
|
41
|
+
)
|
|
42
|
+
.orderBy(desc(schema.assets.createdAt))
|
|
43
|
+
.limit(limit ?? 50);
|
|
44
|
+
|
|
45
|
+
return {
|
|
46
|
+
count: rows.length,
|
|
47
|
+
assets: rows.map((row) => serializeAsset(row)),
|
|
48
|
+
};
|
|
49
|
+
},
|
|
50
|
+
});
|
|
@@ -7,6 +7,7 @@ import { z } from "zod";
|
|
|
7
7
|
import { IMAGE_QUALITY_TIERS, STYLE_STRENGTHS } from "../shared/api.js";
|
|
8
8
|
|
|
9
9
|
const mediaTypeSchema = z.enum(["image", "video"]);
|
|
10
|
+
const layoutSchema = z.enum(["default", "vertical"]);
|
|
10
11
|
const booleanParam = z.preprocess((value) => {
|
|
11
12
|
if (typeof value === "boolean") return value;
|
|
12
13
|
if (typeof value !== "string") return value;
|
|
@@ -77,6 +78,11 @@ const schema = z.object({
|
|
|
77
78
|
.string()
|
|
78
79
|
.optional()
|
|
79
80
|
.describe("Calling app id, for audit grouping, e.g. design."),
|
|
81
|
+
layout: layoutSchema
|
|
82
|
+
.default("default")
|
|
83
|
+
.describe(
|
|
84
|
+
"Picker layout density. Use vertical when embedding in a narrow sidebar.",
|
|
85
|
+
),
|
|
80
86
|
});
|
|
81
87
|
|
|
82
88
|
type OpenAssetPickerArgs = z.infer<typeof schema>;
|
|
@@ -132,6 +138,7 @@ function pickerPath(args: Partial<OpenAssetPickerArgs>): string {
|
|
|
132
138
|
}
|
|
133
139
|
if (args.includeLogo) params.set("includeLogo", "1");
|
|
134
140
|
if (args.callerAppId?.trim()) params.set("callerAppId", args.callerAppId);
|
|
141
|
+
if (args.layout === "vertical") params.set("layout", "vertical");
|
|
135
142
|
for (const runId of args.candidateRunIds ?? []) {
|
|
136
143
|
if (runId.trim()) params.append("candidateRunIds", runId.trim());
|
|
137
144
|
}
|
|
@@ -206,6 +213,7 @@ const action = defineAction({
|
|
|
206
213
|
prompt: args.prompt ?? null,
|
|
207
214
|
aspectRatio: args.aspectRatio ?? null,
|
|
208
215
|
presetId: args.presetId ?? null,
|
|
216
|
+
layout: args.layout,
|
|
209
217
|
_writeId: `open-asset-picker-${Date.now()}-${Math.random()
|
|
210
218
|
.toString(36)
|
|
211
219
|
.slice(2, 8)}`,
|
|
@@ -219,6 +227,7 @@ const action = defineAction({
|
|
|
219
227
|
path,
|
|
220
228
|
url: path,
|
|
221
229
|
embed: true,
|
|
230
|
+
layout: args.layout,
|
|
222
231
|
title:
|
|
223
232
|
args.mediaType === "video"
|
|
224
233
|
? "Select a video asset"
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { defineAction } from "@agent-native/core";
|
|
2
|
+
import type { ActionRunContext } from "@agent-native/core/action";
|
|
2
3
|
import { assertAccess } from "@agent-native/core/sharing";
|
|
3
4
|
import { eq } from "drizzle-orm";
|
|
4
5
|
import { z } from "zod";
|
|
@@ -30,7 +31,10 @@ export default defineAction({
|
|
|
30
31
|
),
|
|
31
32
|
}),
|
|
32
33
|
parallelSafe: true,
|
|
33
|
-
run: async (
|
|
34
|
+
run: async (
|
|
35
|
+
{ runId, slotId, sessionId, source, callerAppId },
|
|
36
|
+
context?: ActionRunContext,
|
|
37
|
+
) => {
|
|
34
38
|
const db = getDb();
|
|
35
39
|
const [run] = await db
|
|
36
40
|
.select()
|
|
@@ -52,6 +56,8 @@ export default defineAction({
|
|
|
52
56
|
intent?: string;
|
|
53
57
|
styleStrength?: string;
|
|
54
58
|
subjectAssetId?: string;
|
|
59
|
+
embeddedText?: string | null;
|
|
60
|
+
textPlacement?: string | null;
|
|
55
61
|
};
|
|
56
62
|
includeLogo?: boolean;
|
|
57
63
|
categories?: string[];
|
|
@@ -60,39 +66,54 @@ export default defineAction({
|
|
|
60
66
|
intent?: string;
|
|
61
67
|
styleStrength?: string;
|
|
62
68
|
tier?: string | null;
|
|
69
|
+
embeddedText?: string | null;
|
|
70
|
+
textPlacement?: string | null;
|
|
63
71
|
}>(run.metadata, {});
|
|
64
72
|
const categories =
|
|
65
73
|
metadata.settingsUsed?.categories ?? metadata.categories ?? undefined;
|
|
66
74
|
|
|
67
|
-
return generateImage.run(
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
metadata.settingsUsed?.
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
metadata.
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
75
|
+
return generateImage.run(
|
|
76
|
+
{
|
|
77
|
+
libraryId: run.libraryId,
|
|
78
|
+
collectionId: run.collectionId ?? undefined,
|
|
79
|
+
presetId: run.presetId ?? undefined,
|
|
80
|
+
sessionId: resolvedSessionId,
|
|
81
|
+
prompt: run.prompt,
|
|
82
|
+
embeddedText:
|
|
83
|
+
metadata.settingsUsed?.embeddedText ??
|
|
84
|
+
metadata.embeddedText ??
|
|
85
|
+
undefined,
|
|
86
|
+
textPlacement:
|
|
87
|
+
metadata.settingsUsed?.textPlacement ??
|
|
88
|
+
metadata.textPlacement ??
|
|
89
|
+
undefined,
|
|
90
|
+
aspectRatio: run.aspectRatio as any,
|
|
91
|
+
imageSize: run.imageSize as any,
|
|
92
|
+
model: run.model as any,
|
|
93
|
+
tier: (metadata.settingsUsed?.tier ??
|
|
94
|
+
metadata.tier ??
|
|
95
|
+
undefined) as any,
|
|
96
|
+
intent: (metadata.settingsUsed?.intent ??
|
|
97
|
+
metadata.intent ??
|
|
98
|
+
"generate") as any,
|
|
99
|
+
styleStrength: (metadata.settingsUsed?.styleStrength ??
|
|
100
|
+
metadata.styleStrength ??
|
|
101
|
+
"balanced") as any,
|
|
102
|
+
categories: categories as any,
|
|
103
|
+
includeLogo: Boolean(
|
|
104
|
+
metadata.settingsUsed?.includeLogo ?? metadata.includeLogo,
|
|
105
|
+
),
|
|
106
|
+
groundingMode: run.groundingMode as any,
|
|
107
|
+
sourceAssetId: metadata.sourceAssetId,
|
|
108
|
+
subjectAssetId:
|
|
109
|
+
metadata.settingsUsed?.subjectAssetId ??
|
|
110
|
+
metadata.subjectAssetId ??
|
|
111
|
+
undefined,
|
|
112
|
+
slotId,
|
|
113
|
+
source,
|
|
114
|
+
callerAppId,
|
|
115
|
+
},
|
|
116
|
+
context,
|
|
117
|
+
);
|
|
97
118
|
},
|
|
98
119
|
});
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { useActionQuery, useT } from "@agent-native/core/client";
|
|
2
|
+
import { IconArrowUpRight, IconPhoto } from "@tabler/icons-react";
|
|
3
|
+
import { Link } from "react-router";
|
|
4
|
+
|
|
5
|
+
import { Button } from "@/components/ui/button";
|
|
6
|
+
import { Skeleton } from "@/components/ui/skeleton";
|
|
7
|
+
|
|
8
|
+
type DraftAsset = {
|
|
9
|
+
id: string;
|
|
10
|
+
title?: string | null;
|
|
11
|
+
prompt?: string | null;
|
|
12
|
+
mediaType?: string | null;
|
|
13
|
+
mimeType?: string | null;
|
|
14
|
+
thumbnailUrl?: string | null;
|
|
15
|
+
previewUrl?: string | null;
|
|
16
|
+
url?: string | null;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const RECENT_DRAFTS_LIMIT = 5;
|
|
20
|
+
|
|
21
|
+
export function RecentDraftsSection() {
|
|
22
|
+
const t = useT();
|
|
23
|
+
const { data, isLoading } = useActionQuery("list-draft-assets", {
|
|
24
|
+
limit: RECENT_DRAFTS_LIMIT,
|
|
25
|
+
});
|
|
26
|
+
const drafts = ((data as any)?.assets ?? []) as DraftAsset[];
|
|
27
|
+
|
|
28
|
+
if (!isLoading && drafts.length === 0) return null;
|
|
29
|
+
|
|
30
|
+
return (
|
|
31
|
+
<section className="space-y-3">
|
|
32
|
+
<div className="flex flex-wrap items-center justify-between gap-3">
|
|
33
|
+
<h2 className="text-sm font-semibold text-foreground">
|
|
34
|
+
{t("library.recentDrafts")}
|
|
35
|
+
</h2>
|
|
36
|
+
<Button asChild variant="outline" size="sm">
|
|
37
|
+
<Link to="/library?tab=drafts">
|
|
38
|
+
{t("library.viewAllDrafts")}
|
|
39
|
+
<IconArrowUpRight size={15} className="ml-1.5" />
|
|
40
|
+
</Link>
|
|
41
|
+
</Button>
|
|
42
|
+
</div>
|
|
43
|
+
|
|
44
|
+
<div className="grid grid-cols-3 gap-3 sm:grid-cols-5">
|
|
45
|
+
{isLoading
|
|
46
|
+
? Array.from({ length: RECENT_DRAFTS_LIMIT }).map((_, index) => (
|
|
47
|
+
<Skeleton key={index} className="aspect-square rounded-lg" />
|
|
48
|
+
))
|
|
49
|
+
: drafts.map((draft) => (
|
|
50
|
+
<Link
|
|
51
|
+
key={draft.id}
|
|
52
|
+
to={`/asset/${encodeURIComponent(draft.id)}`}
|
|
53
|
+
title={draft.title || draft.prompt || t("library.draftAsset")}
|
|
54
|
+
className="group block overflow-hidden rounded-lg border border-border bg-card shadow-sm transition hover:border-primary/60 hover:shadow-md focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
|
|
55
|
+
>
|
|
56
|
+
<div className="aspect-square bg-muted">
|
|
57
|
+
<DraftThumbnail draft={draft} />
|
|
58
|
+
</div>
|
|
59
|
+
</Link>
|
|
60
|
+
))}
|
|
61
|
+
</div>
|
|
62
|
+
</section>
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function DraftThumbnail({ draft }: { draft: DraftAsset }) {
|
|
67
|
+
const t = useT();
|
|
68
|
+
const isVideo =
|
|
69
|
+
draft.mediaType === "video" || draft.mimeType?.startsWith("video/");
|
|
70
|
+
const source = draft.thumbnailUrl ?? draft.previewUrl ?? draft.url ?? "";
|
|
71
|
+
|
|
72
|
+
if (isVideo && !draft.thumbnailUrl) {
|
|
73
|
+
return (
|
|
74
|
+
<video
|
|
75
|
+
src={draft.previewUrl ?? draft.url ?? undefined}
|
|
76
|
+
muted
|
|
77
|
+
playsInline
|
|
78
|
+
preload="metadata"
|
|
79
|
+
className="h-full w-full object-cover transition group-hover:scale-[1.02]"
|
|
80
|
+
/>
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (!source) {
|
|
85
|
+
return (
|
|
86
|
+
<div className="flex h-full w-full items-center justify-center text-muted-foreground">
|
|
87
|
+
<IconPhoto className="size-5" />
|
|
88
|
+
</div>
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return (
|
|
93
|
+
<img
|
|
94
|
+
src={source}
|
|
95
|
+
alt={draft.title ?? draft.prompt ?? t("library.draftAsset")}
|
|
96
|
+
loading="lazy"
|
|
97
|
+
className="h-full w-full object-cover transition group-hover:scale-[1.02]"
|
|
98
|
+
/>
|
|
99
|
+
);
|
|
100
|
+
}
|
|
@@ -191,6 +191,21 @@
|
|
|
191
191
|
}
|
|
192
192
|
}
|
|
193
193
|
|
|
194
|
+
.assets-picker-vertical .assets-library-dense-grid,
|
|
195
|
+
.assets-picker-vertical .assets-library-grid {
|
|
196
|
+
grid-template-columns: minmax(0, 1fr);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
.assets-picker-vertical [role="tablist"] {
|
|
200
|
+
width: 100%;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
.assets-picker-vertical [role="tab"] {
|
|
204
|
+
min-width: 0;
|
|
205
|
+
flex: 1 1 0;
|
|
206
|
+
padding-inline: 0.5rem;
|
|
207
|
+
}
|
|
208
|
+
|
|
194
209
|
@container agent-native-main (min-width: 980px) {
|
|
195
210
|
.assets-brand-kit-preview-grid {
|
|
196
211
|
grid-template-columns: minmax(0, 1fr) 284px;
|
|
@@ -73,6 +73,7 @@ function navigationFromPath(pathname: string, search = "") {
|
|
|
73
73
|
query: optionalParam(params, "q"),
|
|
74
74
|
prompt: optionalParam(params, "prompt"),
|
|
75
75
|
aspectRatio: optionalParam(params, "aspectRatio"),
|
|
76
|
+
layout: params.get("layout") === "vertical" ? "vertical" : undefined,
|
|
76
77
|
};
|
|
77
78
|
}
|
|
78
79
|
const queryLibraryId = optionalParam(params, "libraryId");
|
|
@@ -153,6 +154,9 @@ function pathFromCommand(command: any): string | null {
|
|
|
153
154
|
if (typeof command.aspectRatio === "string" && command.aspectRatio.trim()) {
|
|
154
155
|
params.set("aspectRatio", command.aspectRatio.trim());
|
|
155
156
|
}
|
|
157
|
+
if (command.layout === "vertical") {
|
|
158
|
+
params.set("layout", "vertical");
|
|
159
|
+
}
|
|
156
160
|
const query = params.toString();
|
|
157
161
|
return query ? `/library?${query}` : "/library";
|
|
158
162
|
}
|
|
@@ -628,6 +628,13 @@ const messages = {
|
|
|
628
628
|
videosCount: "{{count}} 個影片",
|
|
629
629
|
},
|
|
630
630
|
library: {
|
|
631
|
+
drafts: "草稿",
|
|
632
|
+
allLibraries: "所有資料庫",
|
|
633
|
+
noDrafts: "尚無草稿。",
|
|
634
|
+
noMatchingDrafts: "沒有符合的草稿。",
|
|
635
|
+
recentDrafts: "最近草稿",
|
|
636
|
+
viewAllDrafts: "查看所有草稿",
|
|
637
|
+
draftAsset: "草稿資產",
|
|
631
638
|
addedToReferences: "已新增到參考。",
|
|
632
639
|
addedAssetsToReferences: "已將 {{count}} 個資產新增到參考。",
|
|
633
640
|
add: "新增",
|