@agent-native/core 0.77.24 → 0.78.1
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 +20 -0
- package/corpus/core/docs/content/template-analytics.md +5 -0
- package/corpus/core/docs/content/tracking.md +45 -0
- package/corpus/core/package.json +3 -1
- package/corpus/core/src/agent/types.ts +22 -0
- package/corpus/core/src/client/AgentPanel.tsx +34 -18
- package/corpus/core/src/client/AssistantChat.tsx +40 -0
- package/corpus/core/src/client/agent-chat.ts +173 -0
- package/corpus/core/src/client/analytics.ts +141 -5
- package/corpus/core/src/client/composer/TiptapComposer.tsx +316 -60
- package/corpus/core/src/client/composer/extensions/MentionReference.tsx +3 -0
- package/corpus/core/src/client/composer/types.ts +22 -0
- package/corpus/core/src/client/index.ts +14 -0
- package/corpus/core/src/client/session-replay.ts +800 -0
- package/corpus/core/src/db/schema.ts +12 -0
- package/corpus/core/src/deploy/build.ts +75 -0
- package/corpus/core/src/private-blob/index.ts +18 -0
- package/corpus/core/src/private-blob/registry.ts +241 -0
- package/corpus/core/src/private-blob/types.ts +55 -0
- package/corpus/core/src/scripts/utils.ts +34 -6
- package/corpus/core/src/server/agent-chat-plugin.ts +10 -0
- package/corpus/core/src/server/email.ts +5 -0
- package/corpus/core/src/server/index.ts +1 -0
- package/corpus/core/src/styles/agent-native.css +24 -0
- package/corpus/templates/analytics/.agents/skills/dashboard-management/SKILL.md +1 -1
- package/corpus/templates/analytics/.agents/skills/session-replay/SKILL.md +43 -0
- package/corpus/templates/analytics/AGENTS.md +32 -1
- package/corpus/templates/analytics/DEVELOPING.md +9 -1
- package/corpus/templates/analytics/actions/delete-dashboard-report-subscription.ts +24 -0
- package/corpus/templates/analytics/actions/get-session-replay-events.ts +50 -0
- package/corpus/templates/analytics/actions/get-session-replay-summary.ts +27 -0
- package/corpus/templates/analytics/actions/list-dashboard-report-subscriptions.ts +24 -0
- package/corpus/templates/analytics/actions/list-session-recordings.ts +59 -0
- package/corpus/templates/analytics/actions/navigate.ts +15 -5
- package/corpus/templates/analytics/actions/query-agent-native-analytics.ts +2 -2
- package/corpus/templates/analytics/actions/save-dashboard-report-subscription.ts +36 -0
- package/corpus/templates/analytics/actions/send-dashboard-report-now.ts +60 -0
- package/corpus/templates/analytics/actions/view-screen.ts +50 -2
- package/corpus/templates/analytics/app/components/dashboard/SqlChart.tsx +51 -2
- package/corpus/templates/analytics/app/components/layout/Header.tsx +4 -1
- package/corpus/templates/analytics/app/components/layout/Layout.tsx +14 -2
- package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +6 -6
- package/corpus/templates/analytics/app/hooks/use-navigation-state.ts +35 -6
- package/corpus/templates/analytics/app/i18n-data.ts +1119 -0
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/EmailReportDialog.tsx +437 -0
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/SqlChartCard.tsx +11 -12
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/dashboard-layout.ts +43 -0
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +136 -43
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/report-filters.ts +26 -0
- package/corpus/templates/analytics/app/pages/sessions/SessionDetailPage.tsx +450 -0
- package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +419 -0
- package/corpus/templates/analytics/app/routes/overview.tsx +13 -6
- package/corpus/templates/analytics/app/routes/sessions.$recordingId.tsx +10 -0
- package/corpus/templates/analytics/app/routes/sessions._index.tsx +10 -0
- package/corpus/templates/analytics/changelog/2026-06-25-analytics-now-opens-directly-to-ask-instead-of-the-old-overv.md +6 -0
- package/corpus/templates/analytics/changelog/2026-06-25-dashboard-charts-now-show-reliable-blue-placement-lines-whil.md +6 -0
- package/corpus/templates/analytics/changelog/2026-06-26-dashboards-can-now-send-scheduled-daily-email-reports-from-t.md +6 -0
- package/corpus/templates/analytics/changelog/2026-06-26-session-replay-browser-sessions-can-now-be-reviewed-from.md +6 -0
- package/corpus/templates/analytics/package.json +5 -2
- package/corpus/templates/analytics/scripts/emit-netlify-dashboard-report-cron.ts +131 -0
- package/corpus/templates/analytics/scripts/seed-session-replay.ts +198 -0
- package/corpus/templates/analytics/seeds/dashboards/agent-native-templates-first-party.json +140 -27
- package/corpus/templates/analytics/server/db/index.ts +12 -0
- package/corpus/templates/analytics/server/db/schema.ts +131 -0
- package/corpus/templates/analytics/server/handlers/session-replay.ts +281 -0
- package/corpus/templates/analytics/server/handlers/sql-query.ts +8 -348
- package/corpus/templates/analytics/server/jobs/dashboard-report.ts +66 -0
- package/corpus/templates/analytics/server/jobs/session-replay-retention.ts +29 -0
- package/corpus/templates/analytics/server/lib/dashboard-panel-query.ts +365 -0
- package/corpus/templates/analytics/server/lib/dashboard-report-subscriptions.ts +473 -0
- package/corpus/templates/analytics/server/lib/dashboard-report.ts +405 -0
- package/corpus/templates/analytics/server/lib/first-party-analytics.ts +63 -18
- package/corpus/templates/analytics/server/lib/first-party-metric-catalog.ts +98 -26
- package/corpus/templates/analytics/server/lib/session-replay.ts +1645 -0
- package/corpus/templates/analytics/server/plugins/auth.ts +1 -1
- package/corpus/templates/analytics/server/plugins/dashboard-report-jobs.ts +47 -0
- package/corpus/templates/analytics/server/plugins/db.ts +200 -0
- package/corpus/templates/analytics/server/plugins/session-replay-retention-jobs.ts +41 -0
- package/corpus/templates/analytics/server/routes/api/analytics/replay.options.ts +1 -0
- package/corpus/templates/analytics/server/routes/api/analytics/replay.post.ts +1 -0
- package/corpus/templates/analytics/server/routes/api/dashboard-reports/run.post.ts +61 -0
- package/corpus/templates/analytics/server/routes/api/session-replay/recordings/[recordingId]/chunks/[seq].get.ts +1 -0
- package/corpus/templates/analytics/server/routes/api/session-replay/recordings/[recordingId]/events.get.ts +1 -0
- package/corpus/templates/analytics/server/routes/api/session-replay/recordings/[recordingId]/manifest.get.ts +1 -0
- package/corpus/templates/analytics/server/routes/api/session-replay/recordings/[recordingId].get.ts +1 -0
- package/corpus/templates/analytics/server/routes/api/session-replay/recordings.get.ts +1 -0
- package/corpus/templates/assets/.agents/skills/asset-generation/SKILL.md +10 -2
- package/corpus/templates/assets/.agents/skills/image-generation/SKILL.md +14 -7
- package/corpus/templates/assets/.agents/skills/library-management/SKILL.md +12 -0
- package/corpus/templates/assets/AGENTS.md +18 -3
- package/corpus/templates/assets/actions/_image-model-default.ts +24 -0
- package/corpus/templates/assets/actions/dismiss-variant-slots.ts +15 -22
- package/corpus/templates/assets/actions/generate-asset.ts +30 -23
- package/corpus/templates/assets/actions/generate-image-batch.ts +76 -29
- package/corpus/templates/assets/actions/generate-image.ts +46 -30
- package/corpus/templates/assets/actions/generate-video.ts +18 -3
- package/corpus/templates/assets/actions/list-assets.ts +39 -8
- package/corpus/templates/assets/actions/list-libraries.ts +24 -2
- package/corpus/templates/assets/actions/navigate.ts +1 -1
- package/corpus/templates/assets/actions/open-asset-picker.ts +38 -1
- package/corpus/templates/assets/actions/refresh-generation-run.ts +10 -0
- package/corpus/templates/assets/actions/save-generated-image.ts +21 -19
- package/corpus/templates/assets/actions/variant-slots.ts +131 -28
- package/corpus/templates/assets/actions/view-screen.ts +9 -0
- package/corpus/templates/assets/app/components/generation/GenerationResults.tsx +425 -0
- package/corpus/templates/assets/app/components/layout/Header.tsx +3 -1
- package/corpus/templates/assets/app/components/layout/Layout.tsx +5 -0
- package/corpus/templates/assets/app/components/layout/Sidebar.tsx +4 -6
- package/corpus/templates/assets/app/hooks/use-navigation-state.ts +47 -21
- package/corpus/templates/assets/app/i18n-data.ts +1815 -0
- package/corpus/templates/assets/app/lib/libraries.ts +6 -0
- package/corpus/templates/assets/app/lib/picker-chat-handoff.ts +71 -0
- package/corpus/templates/assets/app/routes/_index.tsx +4 -0
- package/corpus/templates/assets/app/routes/asset.$id.tsx +2 -2
- package/corpus/templates/assets/app/routes/audit.tsx +1 -1
- package/corpus/templates/assets/app/routes/brand-kits.$id.tsx +1557 -2164
- package/corpus/templates/assets/app/routes/brand-kits._index.tsx +7 -191
- package/corpus/templates/assets/app/routes/brand-kits.tsx +1 -5
- package/corpus/templates/assets/app/routes/libraries.tsx +4 -4
- package/corpus/templates/assets/app/routes/library.$id.tsx +9 -7
- package/corpus/templates/assets/app/routes/library.tsx +1454 -175
- package/corpus/templates/assets/server/db/index.ts +1 -1
- package/corpus/templates/assets/server/lib/generation.ts +86 -15
- package/corpus/templates/assets/server/plugins/agent-chat.ts +196 -0
- package/corpus/templates/assets/server/plugins/db.ts +5 -0
- package/corpus/templates/assets/shared/api.ts +6 -3
- package/dist/agent/types.d.ts +21 -0
- package/dist/agent/types.d.ts.map +1 -1
- package/dist/agent/types.js.map +1 -1
- package/dist/client/AgentPanel.d.ts +6 -2
- package/dist/client/AgentPanel.d.ts.map +1 -1
- package/dist/client/AgentPanel.js +10 -4
- package/dist/client/AgentPanel.js.map +1 -1
- package/dist/client/AssistantChat.d.ts +6 -0
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +15 -3
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/agent-chat.d.ts +32 -0
- package/dist/client/agent-chat.d.ts.map +1 -1
- package/dist/client/agent-chat.js +113 -0
- package/dist/client/agent-chat.js.map +1 -1
- package/dist/client/analytics.d.ts +22 -3
- package/dist/client/analytics.d.ts.map +1 -1
- package/dist/client/analytics.js +96 -4
- package/dist/client/analytics.js.map +1 -1
- package/dist/client/composer/TiptapComposer.d.ts +2 -1
- package/dist/client/composer/TiptapComposer.d.ts.map +1 -1
- package/dist/client/composer/TiptapComposer.js +228 -56
- package/dist/client/composer/TiptapComposer.js.map +1 -1
- package/dist/client/composer/extensions/MentionReference.d.ts.map +1 -1
- package/dist/client/composer/extensions/MentionReference.js +3 -0
- package/dist/client/composer/extensions/MentionReference.js.map +1 -1
- package/dist/client/composer/types.d.ts +21 -0
- package/dist/client/composer/types.d.ts.map +1 -1
- package/dist/client/composer/types.js.map +1 -1
- package/dist/client/index.d.ts +2 -2
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +2 -2
- package/dist/client/index.js.map +1 -1
- package/dist/client/session-replay.d.ts +41 -0
- package/dist/client/session-replay.d.ts.map +1 -0
- package/dist/client/session-replay.js +595 -0
- package/dist/client/session-replay.js.map +1 -0
- 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/schema.d.ts +3 -1
- package/dist/db/schema.d.ts.map +1 -1
- package/dist/db/schema.js +6 -2
- package/dist/db/schema.js.map +1 -1
- package/dist/deploy/build.d.ts +8 -0
- package/dist/deploy/build.d.ts.map +1 -1
- package/dist/deploy/build.js +66 -0
- package/dist/deploy/build.js.map +1 -1
- package/dist/file-upload/actions/upload-image.d.ts +2 -2
- package/dist/notifications/routes.d.ts +3 -3
- package/dist/observability/routes.d.ts +8 -8
- package/dist/private-blob/index.d.ts +3 -0
- package/dist/private-blob/index.d.ts.map +1 -0
- package/dist/private-blob/index.js +2 -0
- package/dist/private-blob/index.js.map +1 -0
- package/dist/private-blob/registry.d.ts +10 -0
- package/dist/private-blob/registry.d.ts.map +1 -0
- package/dist/private-blob/registry.js +152 -0
- package/dist/private-blob/registry.js.map +1 -0
- package/dist/private-blob/types.d.ts +51 -0
- package/dist/private-blob/types.d.ts.map +1 -0
- package/dist/private-blob/types.js +2 -0
- package/dist/private-blob/types.js.map +1 -0
- package/dist/resources/handlers.d.ts +3 -3
- package/dist/scripts/utils.d.ts +4 -4
- package/dist/scripts/utils.d.ts.map +1 -1
- package/dist/scripts/utils.js +30 -6
- package/dist/scripts/utils.js.map +1 -1
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +5 -0
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/agent-engine-api-key-route.d.ts +2 -2
- package/dist/server/email.d.ts +2 -0
- package/dist/server/email.d.ts.map +1 -1
- package/dist/server/email.js +3 -0
- package/dist/server/email.js.map +1 -1
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js.map +1 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/dist/styles/agent-native.css +24 -0
- package/docs/content/template-analytics.md +5 -0
- package/docs/content/tracking.md +45 -0
- package/package.json +3 -1
- package/corpus/templates/analytics/app/pages/overview/OverviewPage.tsx +0 -209
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { defineAction, embedApp } from "@agent-native/core";
|
|
2
|
+
import type { ActionRunContext } from "@agent-native/core/action";
|
|
2
3
|
import { z } from "zod";
|
|
3
4
|
|
|
4
5
|
import {
|
|
@@ -116,16 +117,19 @@ const action = defineAction({
|
|
|
116
117
|
view: "picker",
|
|
117
118
|
};
|
|
118
119
|
},
|
|
119
|
-
run: async (args) => {
|
|
120
|
+
run: async (args, context?: ActionRunContext) => {
|
|
120
121
|
if (args.mediaType === "video") {
|
|
121
|
-
const picker = (await openAssetPicker.run(
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
122
|
+
const picker = (await openAssetPicker.run(
|
|
123
|
+
{
|
|
124
|
+
mediaType: "video",
|
|
125
|
+
prompt: args.prompt,
|
|
126
|
+
libraryId: args.libraryId,
|
|
127
|
+
libraryHint: args.libraryHint,
|
|
128
|
+
count: args.count,
|
|
129
|
+
callerAppId: args.callerAppId,
|
|
130
|
+
},
|
|
131
|
+
context,
|
|
132
|
+
)) as Record<string, unknown>;
|
|
129
133
|
return {
|
|
130
134
|
...picker,
|
|
131
135
|
generated: false,
|
|
@@ -134,20 +138,23 @@ const action = defineAction({
|
|
|
134
138
|
};
|
|
135
139
|
}
|
|
136
140
|
|
|
137
|
-
const picker = (await openAssetPicker.run(
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
141
|
+
const picker = (await openAssetPicker.run(
|
|
142
|
+
{
|
|
143
|
+
mediaType: "image",
|
|
144
|
+
prompt: args.prompt,
|
|
145
|
+
libraryId: args.libraryId,
|
|
146
|
+
libraryHint: args.libraryHint,
|
|
147
|
+
aspectRatio: args.aspectRatio,
|
|
148
|
+
presetId: args.presetId,
|
|
149
|
+
count: args.count,
|
|
150
|
+
autoGenerate: true,
|
|
151
|
+
tier: args.tier,
|
|
152
|
+
styleStrength: args.styleStrength,
|
|
153
|
+
includeLogo: args.includeLogo,
|
|
154
|
+
callerAppId: args.callerAppId,
|
|
155
|
+
},
|
|
156
|
+
context,
|
|
157
|
+
)) as Record<string, unknown>;
|
|
151
158
|
return {
|
|
152
159
|
...picker,
|
|
153
160
|
generated: false,
|
|
@@ -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 { nanoid } from "nanoid";
|
|
@@ -17,13 +18,20 @@ import {
|
|
|
17
18
|
STYLE_STRENGTHS,
|
|
18
19
|
} from "../shared/api.js";
|
|
19
20
|
import { requireGenerationSessionInLibrary } from "./_helpers.js";
|
|
21
|
+
import { readImageModelDefault } from "./_image-model-default.js";
|
|
20
22
|
import generateImage from "./generate-image.js";
|
|
23
|
+
import { upsertVariantSlot } from "./variant-slots.js";
|
|
21
24
|
|
|
22
25
|
export default defineAction({
|
|
23
26
|
description:
|
|
24
|
-
"Generate several brand-consistent images in parallel from one library. This is synchronous for images: one call waits for every slot and returns final image artifacts. Use this for slide decks, landing pages, and multi-slot design work. Do not call get-generation-run or refresh-generation-run after a normal image batch result.",
|
|
27
|
+
"Generate several brand-consistent images in parallel from one brand kit/library. Use @brand-kit mentions as libraryId and @preset mentions as presetId when present. This is synchronous for images: one call waits for every slot and returns final image artifacts. Use this for slide decks, landing pages, and multi-slot design work. Do not call get-generation-run or refresh-generation-run after a normal image batch result.",
|
|
25
28
|
schema: z.object({
|
|
26
|
-
libraryId: z
|
|
29
|
+
libraryId: z
|
|
30
|
+
.string()
|
|
31
|
+
.optional()
|
|
32
|
+
.describe(
|
|
33
|
+
"Brand kit/library ID. Pass the refId from a brand-kit @mention, or choose a kit from view-screen/list-libraries.",
|
|
34
|
+
),
|
|
27
35
|
collectionId: z.string().optional(),
|
|
28
36
|
presetId: z.string().optional(),
|
|
29
37
|
sessionId: z.string().optional(),
|
|
@@ -45,6 +53,12 @@ export default defineAction({
|
|
|
45
53
|
)
|
|
46
54
|
.min(1)
|
|
47
55
|
.max(12),
|
|
56
|
+
variantScopeId: z
|
|
57
|
+
.string()
|
|
58
|
+
.optional()
|
|
59
|
+
.describe(
|
|
60
|
+
"Internal UI state scope for live candidate slots. Usually omitted; embedded picker UIs pass a browser-tab scope.",
|
|
61
|
+
),
|
|
48
62
|
model: z.enum(IMAGE_MODELS).optional(),
|
|
49
63
|
tier: z.enum(IMAGE_QUALITY_TIERS).optional(),
|
|
50
64
|
intent: z.enum(GENERATION_INTENTS).default("generate"),
|
|
@@ -60,41 +74,74 @@ export default defineAction({
|
|
|
60
74
|
),
|
|
61
75
|
}),
|
|
62
76
|
parallelSafe: true,
|
|
63
|
-
run: async ({ slots, ...
|
|
77
|
+
run: async ({ slots, ...inputBase }, context?: ActionRunContext) => {
|
|
78
|
+
const imageModelDefault = await readImageModelDefault();
|
|
79
|
+
const libraryId = inputBase.libraryId;
|
|
80
|
+
if (!libraryId) {
|
|
81
|
+
throw new Error(
|
|
82
|
+
"No brand kit selected. Tag a brand kit with @ or pass libraryId.",
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
const base = {
|
|
86
|
+
...inputBase,
|
|
87
|
+
libraryId,
|
|
88
|
+
model: inputBase.model ?? imageModelDefault,
|
|
89
|
+
};
|
|
64
90
|
await assertAccess("asset-library", base.libraryId, "editor");
|
|
65
91
|
if (base.sessionId) {
|
|
66
92
|
await requireGenerationSessionInLibrary(base.sessionId, base.libraryId);
|
|
67
93
|
}
|
|
68
|
-
const limit = pLimit(4);
|
|
69
94
|
const variantBatchId = nanoid();
|
|
95
|
+
await Promise.all(
|
|
96
|
+
slots.map((slot, index) =>
|
|
97
|
+
upsertVariantSlot({
|
|
98
|
+
runId: `pending-${variantBatchId}-${index + 1}`,
|
|
99
|
+
batchId: variantBatchId,
|
|
100
|
+
libraryId: base.libraryId,
|
|
101
|
+
collectionId: base.collectionId ?? null,
|
|
102
|
+
presetId: base.presetId ?? null,
|
|
103
|
+
sessionId: base.sessionId ?? null,
|
|
104
|
+
threadId: context?.threadId ?? null,
|
|
105
|
+
variantScopeId: base.variantScopeId ?? null,
|
|
106
|
+
prompt: slot.prompt,
|
|
107
|
+
slotId: slot.slotId,
|
|
108
|
+
status: "pending",
|
|
109
|
+
}),
|
|
110
|
+
),
|
|
111
|
+
);
|
|
112
|
+
const limit = pLimit(4);
|
|
70
113
|
const results = await Promise.allSettled(
|
|
71
114
|
slots.map((slot) =>
|
|
72
115
|
limit(() =>
|
|
73
|
-
generateImage.run(
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
116
|
+
generateImage.run(
|
|
117
|
+
{
|
|
118
|
+
libraryId: base.libraryId,
|
|
119
|
+
collectionId: base.collectionId,
|
|
120
|
+
presetId: base.presetId,
|
|
121
|
+
sessionId: base.sessionId,
|
|
122
|
+
prompt: slot.prompt,
|
|
123
|
+
aspectRatio: slot.aspectRatio,
|
|
124
|
+
imageSize: slot.imageSize,
|
|
125
|
+
model: base.model,
|
|
126
|
+
tier: base.tier,
|
|
127
|
+
intent: slot.intent ?? base.intent,
|
|
128
|
+
styleStrength: slot.styleStrength ?? base.styleStrength,
|
|
129
|
+
categories: slot.categories,
|
|
130
|
+
referenceAssetIds: slot.referenceAssetIds,
|
|
131
|
+
includeLogo: base.includeLogo,
|
|
132
|
+
groundingMode: base.groundingMode,
|
|
133
|
+
slotId: slot.slotId,
|
|
134
|
+
variantBatchId,
|
|
135
|
+
variantScopeId: base.variantScopeId,
|
|
136
|
+
dismissible: slot.dismissible,
|
|
137
|
+
sourceAssetId: slot.sourceAssetId,
|
|
138
|
+
subjectAssetId: slot.subjectAssetId,
|
|
139
|
+
source: base.source,
|
|
140
|
+
callerAppId: base.callerAppId,
|
|
141
|
+
activateSessionAsset: false,
|
|
142
|
+
},
|
|
143
|
+
context,
|
|
144
|
+
),
|
|
98
145
|
),
|
|
99
146
|
),
|
|
100
147
|
);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { defineAction } from "@agent-native/core";
|
|
2
|
+
import type { ActionRunContext } from "@agent-native/core/action";
|
|
2
3
|
import {
|
|
3
|
-
readAppState,
|
|
4
4
|
writeAppState,
|
|
5
5
|
deleteAppState,
|
|
6
6
|
} from "@agent-native/core/application-state";
|
|
@@ -43,6 +43,7 @@ import {
|
|
|
43
43
|
requireGenerationSessionInLibrary,
|
|
44
44
|
serializeAsset,
|
|
45
45
|
} from "./_helpers.js";
|
|
46
|
+
import { readImageModelDefault } from "./_image-model-default.js";
|
|
46
47
|
import { upsertVariantSlot, wasVariantSlotDismissed } from "./variant-slots.js";
|
|
47
48
|
|
|
48
49
|
function resolveModelForTier(
|
|
@@ -57,33 +58,16 @@ function resolveModelForTier(
|
|
|
57
58
|
: "gemini-3.1-flash-image";
|
|
58
59
|
}
|
|
59
60
|
|
|
60
|
-
/**
|
|
61
|
-
* The user's default image model, chosen from the composer's model picker and
|
|
62
|
-
* persisted in per-user application state. Used as a fallback when no explicit
|
|
63
|
-
* model, tier, or preset model is supplied. Returns undefined when unset or
|
|
64
|
-
* invalid so the hardcoded default still applies.
|
|
65
|
-
*/
|
|
66
|
-
async function readUserDefaultImageModel(): Promise<ImageModel | undefined> {
|
|
67
|
-
try {
|
|
68
|
-
const stored = await readAppState("imageGenerationModel");
|
|
69
|
-
const model = stored?.model;
|
|
70
|
-
if (
|
|
71
|
-
typeof model === "string" &&
|
|
72
|
-
(IMAGE_MODELS as readonly string[]).includes(model)
|
|
73
|
-
) {
|
|
74
|
-
return model as ImageModel;
|
|
75
|
-
}
|
|
76
|
-
} catch {
|
|
77
|
-
// No request context or read failure — fall back to defaults below.
|
|
78
|
-
}
|
|
79
|
-
return undefined;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
61
|
export default defineAction({
|
|
83
62
|
description:
|
|
84
|
-
"Generate one brand-consistent image from a library. This is synchronous for images and returns the final asset with preview/download/embed URLs. Use generate-image-batch for multiple independent slots; do not poll image runs after this action returns.",
|
|
63
|
+
"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.",
|
|
85
64
|
schema: z.object({
|
|
86
|
-
libraryId: z
|
|
65
|
+
libraryId: z
|
|
66
|
+
.string()
|
|
67
|
+
.optional()
|
|
68
|
+
.describe(
|
|
69
|
+
"Brand kit/library ID. Pass the refId from a brand-kit @mention, or choose a kit from view-screen/list-libraries.",
|
|
70
|
+
),
|
|
87
71
|
collectionId: z.string().optional(),
|
|
88
72
|
presetId: z.string().optional(),
|
|
89
73
|
sessionId: z.string().optional(),
|
|
@@ -104,6 +88,12 @@ export default defineAction({
|
|
|
104
88
|
includeLogo: z.coerce.boolean().default(false),
|
|
105
89
|
slotId: z.string().optional(),
|
|
106
90
|
variantBatchId: z.string().optional(),
|
|
91
|
+
variantScopeId: z
|
|
92
|
+
.string()
|
|
93
|
+
.optional()
|
|
94
|
+
.describe(
|
|
95
|
+
"Internal UI state scope for live candidate slots. Usually omitted; embedded picker UIs pass a browser-tab scope.",
|
|
96
|
+
),
|
|
107
97
|
dismissible: z.coerce
|
|
108
98
|
.boolean()
|
|
109
99
|
.default(true)
|
|
@@ -135,7 +125,18 @@ export default defineAction({
|
|
|
135
125
|
),
|
|
136
126
|
}),
|
|
137
127
|
parallelSafe: true,
|
|
138
|
-
run: async (
|
|
128
|
+
run: async (input, context?: ActionRunContext) => {
|
|
129
|
+
const imageModelDefault = await readImageModelDefault();
|
|
130
|
+
const libraryId = input.libraryId;
|
|
131
|
+
if (!libraryId) {
|
|
132
|
+
throw new Error(
|
|
133
|
+
"No brand kit selected. Tag a brand kit with @ or pass libraryId.",
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
const args = {
|
|
137
|
+
...input,
|
|
138
|
+
libraryId,
|
|
139
|
+
};
|
|
139
140
|
await assertAccess("asset-library", args.libraryId, "editor");
|
|
140
141
|
const db = getDb();
|
|
141
142
|
const [library] = await db
|
|
@@ -248,9 +249,9 @@ export default defineAction({
|
|
|
248
249
|
preset?.category ??
|
|
249
250
|
collection?.category) as ImageCategory | undefined;
|
|
250
251
|
const resolvedModel = (args.model ??
|
|
252
|
+
imageModelDefault ??
|
|
251
253
|
resolveModelForTier(resolvedTier, category) ??
|
|
252
254
|
preset?.model ??
|
|
253
|
-
(await readUserDefaultImageModel()) ??
|
|
254
255
|
"gemini-3.1-flash-image") as (typeof IMAGE_MODELS)[number];
|
|
255
256
|
const resolvedCategories =
|
|
256
257
|
args.categories ??
|
|
@@ -303,6 +304,8 @@ export default defineAction({
|
|
|
303
304
|
});
|
|
304
305
|
const runId = nanoid();
|
|
305
306
|
const now = nowIso();
|
|
307
|
+
const slotId = args.slotId ?? runId;
|
|
308
|
+
const variantScopeId = args.variantScopeId ?? context?.threadId ?? null;
|
|
306
309
|
// Capture identity at insert time so the org-admin audit log can filter
|
|
307
310
|
// by owner / org without re-resolving who triggered the run later.
|
|
308
311
|
const ownerEmail = getRequestUserEmail() ?? null;
|
|
@@ -342,11 +345,12 @@ export default defineAction({
|
|
|
342
345
|
sessionId: session?.id ?? null,
|
|
343
346
|
customInstructions: library.customInstructions ?? "",
|
|
344
347
|
};
|
|
345
|
-
const slotId = args.slotId ?? runId;
|
|
346
348
|
const dismissibleSlot = args.dismissible !== false && Boolean(slotId);
|
|
347
349
|
const baseMetadata = {
|
|
348
350
|
slotId,
|
|
349
351
|
variantBatchId: args.variantBatchId ?? null,
|
|
352
|
+
threadId: context?.threadId ?? null,
|
|
353
|
+
variantScopeId,
|
|
350
354
|
dismissible: dismissibleSlot,
|
|
351
355
|
sourceAssetId: args.sourceAssetId,
|
|
352
356
|
subjectAssetId: args.subjectAssetId,
|
|
@@ -389,6 +393,8 @@ export default defineAction({
|
|
|
389
393
|
collectionId: resolvedCollectionId ?? null,
|
|
390
394
|
presetId: preset?.id ?? null,
|
|
391
395
|
sessionId: session?.id ?? null,
|
|
396
|
+
threadId: context?.threadId ?? null,
|
|
397
|
+
variantScopeId,
|
|
392
398
|
prompt: args.prompt,
|
|
393
399
|
slotId,
|
|
394
400
|
status: "pending",
|
|
@@ -430,7 +436,10 @@ export default defineAction({
|
|
|
430
436
|
}
|
|
431
437
|
if (
|
|
432
438
|
dismissibleSlot &&
|
|
433
|
-
(await wasVariantSlotDismissed(args.libraryId, slotId
|
|
439
|
+
(await wasVariantSlotDismissed(args.libraryId, slotId, {
|
|
440
|
+
threadId: context?.threadId ?? null,
|
|
441
|
+
variantScopeId,
|
|
442
|
+
}))
|
|
434
443
|
) {
|
|
435
444
|
await db
|
|
436
445
|
.update(schema.assetGenerationRuns)
|
|
@@ -539,6 +548,8 @@ export default defineAction({
|
|
|
539
548
|
collectionId: resolvedCollectionId ?? null,
|
|
540
549
|
presetId: preset?.id ?? null,
|
|
541
550
|
sessionId: session?.id ?? null,
|
|
551
|
+
threadId: context?.threadId ?? null,
|
|
552
|
+
variantScopeId,
|
|
542
553
|
prompt: args.prompt,
|
|
543
554
|
slotId,
|
|
544
555
|
status: "ready",
|
|
@@ -570,7 +581,10 @@ export default defineAction({
|
|
|
570
581
|
.where(eq(schema.assetGenerationRuns.id, runId));
|
|
571
582
|
if (
|
|
572
583
|
dismissibleSlot &&
|
|
573
|
-
(await wasVariantSlotDismissed(args.libraryId, slotId
|
|
584
|
+
(await wasVariantSlotDismissed(args.libraryId, slotId, {
|
|
585
|
+
threadId: context?.threadId ?? null,
|
|
586
|
+
variantScopeId,
|
|
587
|
+
}))
|
|
574
588
|
) {
|
|
575
589
|
throw err;
|
|
576
590
|
}
|
|
@@ -581,6 +595,8 @@ export default defineAction({
|
|
|
581
595
|
collectionId: resolvedCollectionId ?? null,
|
|
582
596
|
presetId: preset?.id ?? null,
|
|
583
597
|
sessionId: session?.id ?? null,
|
|
598
|
+
threadId: context?.threadId ?? null,
|
|
599
|
+
variantScopeId,
|
|
584
600
|
prompt: args.prompt,
|
|
585
601
|
slotId,
|
|
586
602
|
status: "failed",
|
|
@@ -32,9 +32,14 @@ import { serializeAsset, serializeGenerationRun } from "./_helpers.js";
|
|
|
32
32
|
|
|
33
33
|
export default defineAction({
|
|
34
34
|
description:
|
|
35
|
-
"Start an async Veo video generation run from
|
|
35
|
+
"Start an async Veo video generation run from a brand kit/library. Use a media-type @mention with refId video to choose this instead of image generation, and use a brand-kit @mention as libraryId. Poll the returned run with refresh-generation-run until it completes and creates a video asset.",
|
|
36
36
|
schema: z.object({
|
|
37
|
-
libraryId: z
|
|
37
|
+
libraryId: z
|
|
38
|
+
.string()
|
|
39
|
+
.optional()
|
|
40
|
+
.describe(
|
|
41
|
+
"Brand kit/library ID. Pass the refId from a brand-kit @mention, or choose a kit from view-screen/list-libraries.",
|
|
42
|
+
),
|
|
38
43
|
folderId: z.string().min(1).nullable().optional(),
|
|
39
44
|
collectionId: z.string().optional(),
|
|
40
45
|
prompt: z.string().min(1),
|
|
@@ -66,7 +71,17 @@ export default defineAction({
|
|
|
66
71
|
callerAppId: z.string().optional(),
|
|
67
72
|
waitForCompletion: z.coerce.boolean().default(false),
|
|
68
73
|
}),
|
|
69
|
-
run: async (
|
|
74
|
+
run: async (input) => {
|
|
75
|
+
const libraryId = input.libraryId;
|
|
76
|
+
if (!libraryId) {
|
|
77
|
+
throw new Error(
|
|
78
|
+
"No brand kit selected. Tag a brand kit with @ or pass libraryId.",
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
const args = {
|
|
82
|
+
...input,
|
|
83
|
+
libraryId,
|
|
84
|
+
};
|
|
70
85
|
await assertAccess("asset-library", args.libraryId, "editor");
|
|
71
86
|
const db = getDb();
|
|
72
87
|
const [library] = await db
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { defineAction } from "@agent-native/core";
|
|
2
|
-
import {
|
|
2
|
+
import { accessFilter } from "@agent-native/core/sharing";
|
|
3
|
+
import { and, desc, eq, inArray, isNull } from "drizzle-orm";
|
|
3
4
|
import { z } from "zod";
|
|
4
5
|
|
|
5
6
|
import { getDb, schema } from "../server/db/index.js";
|
|
@@ -17,9 +18,9 @@ import {
|
|
|
17
18
|
|
|
18
19
|
export default defineAction({
|
|
19
20
|
description:
|
|
20
|
-
"List DAM assets in
|
|
21
|
+
"List DAM assets in one library, or across all accessible libraries when libraryId is omitted. Optionally filter by folder, collection, media type, status, role, category, or text query.",
|
|
21
22
|
schema: z.object({
|
|
22
|
-
libraryId: z.string(),
|
|
23
|
+
libraryId: z.string().optional(),
|
|
23
24
|
collectionId: z.string().optional(),
|
|
24
25
|
folderId: z.string().nullable().optional(),
|
|
25
26
|
mediaType: z.enum(ASSET_MEDIA_TYPES).optional(),
|
|
@@ -51,8 +52,32 @@ export default defineAction({
|
|
|
51
52
|
includeCandidates,
|
|
52
53
|
candidateRunIds,
|
|
53
54
|
}) => {
|
|
54
|
-
|
|
55
|
-
const
|
|
55
|
+
const db = getDb();
|
|
56
|
+
const libraryRows = libraryId
|
|
57
|
+
? [await requireLibrary(libraryId)]
|
|
58
|
+
: await db
|
|
59
|
+
.select({
|
|
60
|
+
id: schema.assetLibraries.id,
|
|
61
|
+
title: schema.assetLibraries.title,
|
|
62
|
+
})
|
|
63
|
+
.from(schema.assetLibraries)
|
|
64
|
+
.where(
|
|
65
|
+
and(
|
|
66
|
+
accessFilter(schema.assetLibraries, schema.assetLibraryShares),
|
|
67
|
+
isNull(schema.assetLibraries.archivedAt),
|
|
68
|
+
),
|
|
69
|
+
);
|
|
70
|
+
const libraryIds = libraryRows.map((library) => library.id);
|
|
71
|
+
if (!libraryIds.length) return { count: 0, assets: [] };
|
|
72
|
+
|
|
73
|
+
const libraryTitleById = new Map(
|
|
74
|
+
libraryRows.map((library) => [library.id, library.title]),
|
|
75
|
+
);
|
|
76
|
+
const filters = [
|
|
77
|
+
libraryId
|
|
78
|
+
? eq(schema.assets.libraryId, libraryId)
|
|
79
|
+
: inArray(schema.assets.libraryId, libraryIds),
|
|
80
|
+
];
|
|
56
81
|
if (collectionId)
|
|
57
82
|
filters.push(eq(schema.assets.collectionId, collectionId));
|
|
58
83
|
if (folderId !== undefined) {
|
|
@@ -67,7 +92,6 @@ export default defineAction({
|
|
|
67
92
|
if (role) filters.push(eq(schema.assets.role, role));
|
|
68
93
|
const normalizedQuery = query?.trim().toLowerCase();
|
|
69
94
|
const candidateRunIdSet = new Set(candidateRunIds ?? []);
|
|
70
|
-
const db = getDb();
|
|
71
95
|
const [rows, lineageRows] = await Promise.all([
|
|
72
96
|
db
|
|
73
97
|
.select()
|
|
@@ -89,7 +113,11 @@ export default defineAction({
|
|
|
89
113
|
createdAt: schema.assets.createdAt,
|
|
90
114
|
})
|
|
91
115
|
.from(schema.assets)
|
|
92
|
-
.where(
|
|
116
|
+
.where(
|
|
117
|
+
libraryId
|
|
118
|
+
? eq(schema.assets.libraryId, libraryId)
|
|
119
|
+
: inArray(schema.assets.libraryId, libraryIds),
|
|
120
|
+
),
|
|
93
121
|
]);
|
|
94
122
|
const lineageById = buildAssetLineage(lineageRows);
|
|
95
123
|
const assets = rows
|
|
@@ -111,7 +139,10 @@ export default defineAction({
|
|
|
111
139
|
);
|
|
112
140
|
})
|
|
113
141
|
.filter((asset) => assetMatchesSearch(asset, normalizedQuery, category))
|
|
114
|
-
.map((asset) =>
|
|
142
|
+
.map((asset) => ({
|
|
143
|
+
...serializeAsset(asset, lineageById.get(asset.id) ?? null),
|
|
144
|
+
libraryTitle: libraryTitleById.get(asset.libraryId) ?? null,
|
|
145
|
+
}));
|
|
115
146
|
return { count: assets.length, assets };
|
|
116
147
|
},
|
|
117
148
|
});
|
|
@@ -67,10 +67,11 @@ export default defineAction({
|
|
|
67
67
|
"List asset libraries accessible to the current user, including counts and preview thumbnails.",
|
|
68
68
|
schema: z.object({
|
|
69
69
|
compact: z.coerce.boolean().optional(),
|
|
70
|
+
includeFolders: z.coerce.boolean().optional(),
|
|
70
71
|
}),
|
|
71
72
|
http: { method: "GET" },
|
|
72
73
|
readOnly: true,
|
|
73
|
-
run: async ({ compact }) => {
|
|
74
|
+
run: async ({ compact, includeFolders }) => {
|
|
74
75
|
const db = getDb();
|
|
75
76
|
const rows = await db
|
|
76
77
|
.select()
|
|
@@ -93,8 +94,23 @@ export default defineAction({
|
|
|
93
94
|
),
|
|
94
95
|
)
|
|
95
96
|
: [];
|
|
97
|
+
const folders =
|
|
98
|
+
includeFolders && rows.length
|
|
99
|
+
? await db
|
|
100
|
+
.select()
|
|
101
|
+
.from(schema.assetFolders)
|
|
102
|
+
.where(
|
|
103
|
+
inArray(
|
|
104
|
+
schema.assetFolders.libraryId,
|
|
105
|
+
rows.map((row) => row.id),
|
|
106
|
+
),
|
|
107
|
+
)
|
|
108
|
+
: [];
|
|
96
109
|
const libraries = rows.map((row) => {
|
|
97
110
|
const libAssets = assets.filter((asset) => asset.libraryId === row.id);
|
|
111
|
+
const libFolders = includeFolders
|
|
112
|
+
? folders.filter((folder) => folder.libraryId === row.id)
|
|
113
|
+
: undefined;
|
|
98
114
|
const visibleAssets = libAssets.filter((asset) =>
|
|
99
115
|
shouldIncludeAssetInLibraryResults(asset),
|
|
100
116
|
);
|
|
@@ -106,7 +122,12 @@ export default defineAction({
|
|
|
106
122
|
const previewAssets = uniqueAssets([cover, ...imageAssets]).slice(0, 4);
|
|
107
123
|
const base = serializeLibrary(row);
|
|
108
124
|
return compact
|
|
109
|
-
? {
|
|
125
|
+
? {
|
|
126
|
+
id: base.id,
|
|
127
|
+
title: base.title,
|
|
128
|
+
description: base.description,
|
|
129
|
+
...(includeFolders ? { folders: libFolders } : {}),
|
|
130
|
+
}
|
|
110
131
|
: {
|
|
111
132
|
...base,
|
|
112
133
|
referenceCount: visibleAssets.filter((asset) =>
|
|
@@ -122,6 +143,7 @@ export default defineAction({
|
|
|
122
143
|
).length,
|
|
123
144
|
coverAsset: cover ? serializeAsset(cover) : null,
|
|
124
145
|
previewAssets: previewAssets.map(serializeAsset),
|
|
146
|
+
...(includeFolders ? { folders: libFolders } : {}),
|
|
125
147
|
};
|
|
126
148
|
});
|
|
127
149
|
return { count: libraries.length, libraries };
|
|
@@ -4,7 +4,7 @@ import { z } from "zod";
|
|
|
4
4
|
|
|
5
5
|
export default defineAction({
|
|
6
6
|
description:
|
|
7
|
-
"Navigate the Assets UI. Views (internal keys, with the surface they open): create, picker (the image Library
|
|
7
|
+
"Navigate the Assets UI. Views (internal keys, with the surface they open): create, picker (the embedded image Library picker), libraries (the unified Library workspace), library (a single Brand Kit inside Library), asset, generation-session, generation-run, extensions, audit, settings. Use threadId to open a specific create/chat thread; use libraryId, assetId, sessionId, runId, or extensionId where appropriate.",
|
|
8
8
|
schema: z.object({
|
|
9
9
|
view: z
|
|
10
10
|
.enum([
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import { defineAction, embedApp } from "@agent-native/core";
|
|
2
|
+
import type { ActionRunContext } from "@agent-native/core/action";
|
|
3
|
+
import { writeAppState } from "@agent-native/core/application-state";
|
|
4
|
+
import { getRequestRunContext } from "@agent-native/core/server/request-context";
|
|
2
5
|
import { z } from "zod";
|
|
3
6
|
|
|
4
7
|
import { IMAGE_QUALITY_TIERS, STYLE_STRENGTHS } from "../shared/api.js";
|
|
@@ -77,6 +80,7 @@ const schema = z.object({
|
|
|
77
80
|
});
|
|
78
81
|
|
|
79
82
|
type OpenAssetPickerArgs = z.infer<typeof schema>;
|
|
83
|
+
const SAFE_BROWSER_TAB_ID_RE = /^[A-Za-z0-9_-]{1,96}$/;
|
|
80
84
|
|
|
81
85
|
type ActionWithToolParameters = {
|
|
82
86
|
tool: { parameters?: { properties?: Record<string, any> } };
|
|
@@ -109,6 +113,7 @@ const FALLBACK_INSTRUCTIONS =
|
|
|
109
113
|
|
|
110
114
|
function pickerPath(args: Partial<OpenAssetPickerArgs>): string {
|
|
111
115
|
const params = new URLSearchParams();
|
|
116
|
+
params.set("__an_picker", "1");
|
|
112
117
|
params.set("mediaType", args.mediaType ?? "image");
|
|
113
118
|
if (args.prompt?.trim()) params.set("prompt", args.prompt.trim());
|
|
114
119
|
if (args.query?.trim()) params.set("q", args.query.trim());
|
|
@@ -134,6 +139,21 @@ function pickerPath(args: Partial<OpenAssetPickerArgs>): string {
|
|
|
134
139
|
return `/library?${params.toString()}`;
|
|
135
140
|
}
|
|
136
141
|
|
|
142
|
+
function navigateCommandKey(): string | null {
|
|
143
|
+
const browserTabId = getRequestRunContext()?.browserTabId?.trim();
|
|
144
|
+
if (browserTabId && SAFE_BROWSER_TAB_ID_RE.test(browserTabId)) {
|
|
145
|
+
return `navigate:${browserTabId}`;
|
|
146
|
+
}
|
|
147
|
+
return null;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function shouldWriteNavigateCommand(
|
|
151
|
+
context: ActionRunContext | undefined,
|
|
152
|
+
commandKey: string | null,
|
|
153
|
+
): commandKey is string {
|
|
154
|
+
return Boolean(commandKey) && context?.caller !== "mcp";
|
|
155
|
+
}
|
|
156
|
+
|
|
137
157
|
const action = defineAction({
|
|
138
158
|
description:
|
|
139
159
|
'Open the image Library picker inline so a person can browse, search, generate, and select an image or video asset. When the user asks to create a specific image and choose the best one, pass prompt, autoGenerate: true, and count: 3 so the Library opens with generated candidates. If the host can only open a browser link (e.g. a CLI or code editor), surface that link: after the user picks, the page auto-copies a short paste-back summary — or the user can simply tell you which candidate they want (e.g. "use image A"). Use search-assets, generate-image, generate-video, and export-asset for unattended flows.',
|
|
@@ -173,8 +193,25 @@ const action = defineAction({
|
|
|
173
193
|
view: "picker",
|
|
174
194
|
};
|
|
175
195
|
},
|
|
176
|
-
run: async (args) => {
|
|
196
|
+
run: async (args, context) => {
|
|
177
197
|
const path = pickerPath(args);
|
|
198
|
+
const commandKey = navigateCommandKey();
|
|
199
|
+
if (shouldWriteNavigateCommand(context, commandKey)) {
|
|
200
|
+
const command = {
|
|
201
|
+
view: "picker" as const,
|
|
202
|
+
mediaType: args.mediaType,
|
|
203
|
+
path,
|
|
204
|
+
libraryId: args.libraryId ?? null,
|
|
205
|
+
query: args.query ?? null,
|
|
206
|
+
prompt: args.prompt ?? null,
|
|
207
|
+
aspectRatio: args.aspectRatio ?? null,
|
|
208
|
+
presetId: args.presetId ?? null,
|
|
209
|
+
_writeId: `open-asset-picker-${Date.now()}-${Math.random()
|
|
210
|
+
.toString(36)
|
|
211
|
+
.slice(2, 8)}`,
|
|
212
|
+
};
|
|
213
|
+
await writeAppState(commandKey, command);
|
|
214
|
+
}
|
|
178
215
|
return {
|
|
179
216
|
app: "assets",
|
|
180
217
|
view: "picker",
|
|
@@ -36,6 +36,14 @@ async function syncImageVariantSlot(
|
|
|
36
36
|
typeof metadata.variantBatchId === "string" && metadata.variantBatchId
|
|
37
37
|
? metadata.variantBatchId
|
|
38
38
|
: null;
|
|
39
|
+
const threadId =
|
|
40
|
+
typeof metadata.threadId === "string" && metadata.threadId
|
|
41
|
+
? metadata.threadId
|
|
42
|
+
: null;
|
|
43
|
+
const variantScopeId =
|
|
44
|
+
typeof metadata.variantScopeId === "string" && metadata.variantScopeId
|
|
45
|
+
? metadata.variantScopeId
|
|
46
|
+
: null;
|
|
39
47
|
const serialized = options.asset ? serializeAsset(options.asset) : null;
|
|
40
48
|
|
|
41
49
|
await upsertVariantSlot({
|
|
@@ -45,6 +53,8 @@ async function syncImageVariantSlot(
|
|
|
45
53
|
collectionId: run.collectionId ?? null,
|
|
46
54
|
presetId: run.presetId ?? null,
|
|
47
55
|
sessionId: run.sessionId ?? null,
|
|
56
|
+
threadId,
|
|
57
|
+
variantScopeId,
|
|
48
58
|
prompt: run.prompt,
|
|
49
59
|
slotId,
|
|
50
60
|
status,
|