@agent-native/core 0.176.0-nightly-20260828040116 → 0.176.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 +1 -1
- package/corpus/templates/analytics/CHANGELOG.md +15 -0
- package/corpus/templates/analytics/docs/schemas/first-party-analytics.md +19 -18
- package/corpus/templates/analytics/docs/schemas/tracked-events.md +5 -1
- package/corpus/templates/assets/.agents/skills/asset-generation/SKILL.md +8 -6
- package/corpus/templates/assets/.agents/skills/assets-navigation/SKILL.md +9 -6
- package/corpus/templates/assets/.agents/skills/image-generation/SKILL.md +22 -21
- package/corpus/templates/assets/.agents/skills/library-management/SKILL.md +1 -1
- package/corpus/templates/assets/.agents/skills/logo-composite/SKILL.md +11 -9
- package/corpus/templates/assets/AGENTS.md +16 -11
- package/corpus/templates/assets/CHANGELOG.md +6 -0
- package/corpus/templates/assets/actions/_helpers.ts +15 -0
- package/corpus/templates/assets/actions/_template-access.ts +71 -0
- package/corpus/templates/assets/actions/_template-input.ts +51 -0
- package/corpus/templates/assets/actions/associate-template.ts +39 -0
- package/corpus/templates/assets/actions/create-generation-preset.ts +3 -68
- package/corpus/templates/assets/actions/create-generation-session.ts +7 -10
- package/corpus/templates/assets/actions/create-library-from-preset.ts +2 -2
- package/corpus/templates/assets/actions/create-library.ts +2 -2
- package/corpus/templates/assets/actions/create-template.ts +86 -0
- package/corpus/templates/assets/actions/delete-generation-preset.ts +3 -29
- package/corpus/templates/assets/actions/delete-library.ts +11 -2
- package/corpus/templates/assets/actions/delete-template.ts +36 -0
- package/corpus/templates/assets/actions/duplicate-library.ts +9 -5
- package/corpus/templates/assets/actions/duplicate-template.ts +81 -0
- package/corpus/templates/assets/actions/generate-asset.ts +6 -3
- package/corpus/templates/assets/actions/generate-image-batch.ts +6 -5
- package/corpus/templates/assets/actions/generate-image.ts +23 -18
- package/corpus/templates/assets/actions/get-generation-session.ts +14 -5
- package/corpus/templates/assets/actions/get-template.ts +25 -0
- package/corpus/templates/assets/actions/list-generation-presets.ts +8 -26
- package/corpus/templates/assets/actions/list-templates.ts +90 -0
- package/corpus/templates/assets/actions/merge-duplicate-templates.ts +178 -0
- package/corpus/templates/assets/actions/navigate.ts +4 -1
- package/corpus/templates/assets/actions/rerun-generation-run.ts +3 -5
- package/corpus/templates/assets/actions/update-generation-preset.ts +4 -88
- package/corpus/templates/assets/actions/update-template.ts +87 -0
- package/corpus/templates/assets/actions/view-screen.ts +10 -0
- package/corpus/templates/assets/app/components/layout/Sidebar.tsx +6 -1
- package/corpus/templates/assets/app/components/library/CreateTemplateDialog.tsx +214 -0
- package/corpus/templates/assets/app/components/library/TemplatesPanel.tsx +116 -0
- package/corpus/templates/assets/app/hooks/use-navigation-state.ts +11 -2
- package/corpus/templates/assets/app/i18n-data.ts +393 -0
- package/corpus/templates/assets/app/lib/asset-urls.ts +34 -0
- package/corpus/templates/assets/app/lib/picker-chat-handoff.ts +9 -5
- package/corpus/templates/assets/app/lib/template-composer-reference.ts +62 -0
- package/corpus/templates/assets/app/routes/brand-kits.$id.tsx +2 -2
- package/corpus/templates/assets/app/routes/brand-kits.$id_.presets.$presetId.tsx +7 -2431
- package/corpus/templates/assets/app/routes/brand-kits.$id_.settings.tsx +4 -7
- package/corpus/templates/assets/app/routes/library.tsx +15 -31
- package/corpus/templates/assets/app/routes/templates.$templateId.tsx +2492 -0
- package/corpus/templates/assets/app/routes/templates._index.tsx +360 -0
- package/corpus/templates/assets/app/routes/templates.tsx +11 -0
- package/corpus/templates/assets/changelog/2026-08-26-templates-across-brand-kits.md +5 -0
- package/corpus/templates/assets/server/db/index.ts +10 -0
- package/corpus/templates/assets/server/db/schema.ts +25 -0
- package/corpus/templates/assets/server/lib/generation-presets.ts +94 -32
- package/corpus/templates/assets/server/lib/{preset-chat-context.ts → template-chat-context.ts} +48 -34
- package/corpus/templates/assets/server/plugins/agent-chat.ts +72 -64
- package/corpus/templates/assets/server/plugins/creative-context.ts +0 -2
- package/corpus/templates/assets/server/plugins/db.ts +87 -0
- package/corpus/templates/assets/shared/api.ts +12 -0
- package/corpus/templates/chat/CHANGELOG.md +11 -0
- package/corpus/templates/clips/app/components/library/search-bar.tsx +7 -1
- package/corpus/templates/clips/app/routes/share.$shareId.tsx +1 -1
- package/corpus/templates/design/.generated/bridge/editor-chrome.generated.ts +262 -6
- package/corpus/templates/design/CHANGELOG.md +28 -0
- package/corpus/templates/design/actions/update-file.ts +4 -6
- package/corpus/templates/design/app/components/design/DesignCanvas.tsx +5 -2
- package/corpus/templates/design/app/components/design/EditPanel.tsx +8 -0
- package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +397 -12
- package/corpus/templates/design/app/components/design/edit-panel/layout-properties.tsx +15 -0
- package/corpus/templates/design/app/components/design/edit-panel/style-change-types.ts +14 -0
- package/corpus/templates/design/app/components/design/inspector/AutoLayoutMatrix.tsx +352 -111
- package/corpus/templates/design/app/components/design/inspector/design-icons.tsx +1 -0
- package/corpus/templates/design/app/pages/DesignEditor.tsx +85 -5
- package/corpus/templates/design/app/pages/design-editor/commands/apply-layout-flow.ts +78 -0
- package/corpus/templates/design/app/pages/design-editor/commands/pasted-image-files.ts +110 -14
- package/corpus/templates/design/changelog/2026-08-27-grid-auto-layout-now-lays-children-out-in-cells-and-shows-the-cell-grid.md +6 -0
- package/corpus/templates/design/changelog/2026-08-27-outermost-frames-now-show-their-name-on-the-canvas.md +6 -0
- package/corpus/templates/design/server/source-workspace.ts +1 -7
- package/corpus/templates/design/shared/code-layer.ts +46 -10
- package/corpus/templates/design/shared/locked-layers.ts +178 -64
- package/corpus/templates/factory/AGENTS.md +2 -1
- package/corpus/templates/factory/actions/govern-agent-native-pull-request.ts +757 -42
- package/corpus/templates/factory/actions/ingest-github-observation.ts +10 -1
- package/corpus/templates/factory/actions/reconcile-triage-run.ts +3 -0
- package/corpus/templates/factory/server/plugins/factory-scheduler-job.ts +10 -1
- package/corpus/templates/factory/server/triage/ai-services-git.ts +6 -0
- package/corpus/templates/factory/server/triage/contracts.ts +1 -0
- package/corpus/templates/factory/server/triage/github-client.ts +93 -15
- package/corpus/templates/factory/server/triage/pr-monitor.ts +3 -0
- package/corpus/templates/factory/server/triage/pr-policy.ts +243 -31
- package/corpus/templates/factory/server/triage/review-skill-alignment.ts +16 -4
- package/corpus/templates/slides/CHANGELOG.md +15 -0
- package/corpus/templates/slides/app/components/deck/SlideRenderer.tsx +7 -2
- package/corpus/templates/slides/app/components/editor/EditorToolbar.tsx +37 -1
- package/corpus/templates/slides/app/components/editor/SlideEditor.tsx +941 -219
- package/corpus/templates/slides/app/components/editor/SlidesLayersPanel.tsx +209 -0
- package/corpus/templates/slides/app/components/editor/slide-object-interactions.ts +194 -4
- package/corpus/templates/slides/app/components/editor/slide-style.ts +36 -0
- package/corpus/templates/slides/app/context/DeckContext.tsx +2 -0
- package/corpus/templates/slides/app/i18n/en-US.ts +4 -0
- package/corpus/templates/slides/app/lib/sanitize-slide-html.ts +26 -8
- package/corpus/templates/slides/app/lib/slide-image-replacement.ts +83 -2
- package/corpus/templates/slides/app/pages/DeckEditor.tsx +213 -51
- package/corpus/templates/slides/app/root.tsx +25 -6
- package/dist/observability/routes.d.ts +3 -3
- package/dist/observability/traces.d.ts +8 -0
- package/dist/observability/traces.js +27 -0
- package/dist/progress/routes.d.ts +1 -1
- package/dist/secrets/routes.d.ts +9 -9
- package/dist/templates/chat/CHANGELOG.md +11 -0
- package/package.json +3 -3
- package/src/templates/chat/CHANGELOG.md +11 -0
- package/corpus/templates/assets/app/components/library/GenerationPresetsPanel.tsx +0 -326
|
@@ -1,11 +1,6 @@
|
|
|
1
1
|
import { defineAction } from "@agent-native/core/action";
|
|
2
|
-
import { assertAccess } from "@agent-native/core/sharing";
|
|
3
|
-
import { eq } from "drizzle-orm";
|
|
4
|
-
import { nanoid } from "nanoid";
|
|
5
2
|
import { z } from "zod";
|
|
6
3
|
|
|
7
|
-
import { getDb, schema } from "../server/db/index.js";
|
|
8
|
-
import { nowIso, stringifyJson } from "../server/lib/json.js";
|
|
9
4
|
import {
|
|
10
5
|
ASPECT_RATIOS,
|
|
11
6
|
GENERATION_PRESET_REFERENCE_POLICIES,
|
|
@@ -14,16 +9,11 @@ import {
|
|
|
14
9
|
IMAGE_SIZES,
|
|
15
10
|
} from "../shared/api.js";
|
|
16
11
|
import { generationPresetSettingsSchema } from "./_generation-preset-settings.js";
|
|
17
|
-
import
|
|
18
|
-
import {
|
|
19
|
-
assertPresetReferenceAssetsValid,
|
|
20
|
-
assertPresetReferenceModelCompatible,
|
|
21
|
-
assertPresetSkeletonAssetsValid,
|
|
22
|
-
} from "./_preset-skeleton-validation.js";
|
|
12
|
+
import createTemplate from "./create-template.js";
|
|
23
13
|
|
|
24
14
|
export default defineAction({
|
|
25
15
|
description:
|
|
26
|
-
"Create a reusable deliverable preset for an asset library.
|
|
16
|
+
"Deprecated — use create-template. Create a reusable deliverable preset for an asset library.",
|
|
27
17
|
schema: z.object({
|
|
28
18
|
libraryId: z.string(),
|
|
29
19
|
collectionId: z.string().nullable().optional(),
|
|
@@ -47,60 +37,5 @@ export default defineAction({
|
|
|
47
37
|
settings: generationPresetSettingsSchema.optional(),
|
|
48
38
|
sortOrder: z.coerce.number().optional(),
|
|
49
39
|
}),
|
|
50
|
-
run: async (args) =>
|
|
51
|
-
const db = getDb();
|
|
52
|
-
await assertAccess("asset-library", args.libraryId, "editor");
|
|
53
|
-
if (args.collectionId) {
|
|
54
|
-
const [collection] = await db
|
|
55
|
-
.select()
|
|
56
|
-
.from(schema.assetCollections)
|
|
57
|
-
.where(eq(schema.assetCollections.id, args.collectionId))
|
|
58
|
-
.limit(1);
|
|
59
|
-
if (!collection || collection.libraryId !== args.libraryId) {
|
|
60
|
-
throw new Error("Collection does not belong to this asset library.");
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
const settings = {
|
|
64
|
-
...(args.settings ?? {}),
|
|
65
|
-
...(args.includeLogo !== undefined
|
|
66
|
-
? { includeLogo: args.includeLogo }
|
|
67
|
-
: {}),
|
|
68
|
-
};
|
|
69
|
-
await assertPresetSkeletonAssetsValid({
|
|
70
|
-
db,
|
|
71
|
-
libraryId: args.libraryId,
|
|
72
|
-
settings,
|
|
73
|
-
});
|
|
74
|
-
await assertPresetReferenceAssetsValid({
|
|
75
|
-
db,
|
|
76
|
-
libraryId: args.libraryId,
|
|
77
|
-
settings,
|
|
78
|
-
});
|
|
79
|
-
assertPresetReferenceModelCompatible({
|
|
80
|
-
model: args.model,
|
|
81
|
-
settings,
|
|
82
|
-
});
|
|
83
|
-
const now = nowIso();
|
|
84
|
-
const row = {
|
|
85
|
-
id: nanoid(),
|
|
86
|
-
libraryId: args.libraryId,
|
|
87
|
-
collectionId: args.collectionId ?? null,
|
|
88
|
-
title: args.title,
|
|
89
|
-
description: args.description ?? null,
|
|
90
|
-
category: args.category,
|
|
91
|
-
mediaType: "image",
|
|
92
|
-
promptTemplate: args.promptTemplate ?? null,
|
|
93
|
-
aspectRatio: args.aspectRatio,
|
|
94
|
-
imageSize: args.imageSize,
|
|
95
|
-
model: args.model,
|
|
96
|
-
textPolicy: args.textPolicy,
|
|
97
|
-
referencePolicy: args.referencePolicy,
|
|
98
|
-
settings: stringifyJson(settings),
|
|
99
|
-
sortOrder: args.sortOrder ?? 100,
|
|
100
|
-
createdAt: now,
|
|
101
|
-
updatedAt: now,
|
|
102
|
-
};
|
|
103
|
-
await db.insert(schema.assetGenerationPresets).values(row);
|
|
104
|
-
return serializeGenerationPreset(row);
|
|
105
|
-
},
|
|
40
|
+
run: async (args) => createTemplate.run(args),
|
|
106
41
|
});
|
|
@@ -13,6 +13,7 @@ import { z } from "zod";
|
|
|
13
13
|
import { getDb, schema } from "../server/db/index.js";
|
|
14
14
|
import { nowIso, stringifyJson } from "../server/lib/json.js";
|
|
15
15
|
import { serializeGenerationSession } from "./_helpers.js";
|
|
16
|
+
import { resolveTemplateAccess } from "./_template-access.js";
|
|
16
17
|
|
|
17
18
|
export default defineAction({
|
|
18
19
|
description:
|
|
@@ -60,23 +61,19 @@ export default defineAction({
|
|
|
60
61
|
throw new Error("Collection does not belong to this asset library.");
|
|
61
62
|
}
|
|
62
63
|
}
|
|
63
|
-
let preset: typeof schema.
|
|
64
|
+
let preset: typeof schema.assetTemplates.$inferSelect | null = null;
|
|
64
65
|
if (args.presetId) {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
.limit(1);
|
|
70
|
-
preset = row ?? null;
|
|
71
|
-
if (!preset || preset.libraryId !== args.libraryId) {
|
|
72
|
-
throw new Error("Generation preset does not belong to this library.");
|
|
66
|
+
preset = (await resolveTemplateAccess(args.presetId, "viewer")).resource;
|
|
67
|
+
if (!preset) throw new Error("Template not found.");
|
|
68
|
+
if (preset.libraryId && preset.libraryId !== args.libraryId) {
|
|
69
|
+
throw new Error("Template is associated to a different brand kit.");
|
|
73
70
|
}
|
|
74
71
|
if (
|
|
75
72
|
args.collectionId &&
|
|
76
73
|
preset.collectionId &&
|
|
77
74
|
preset.collectionId !== args.collectionId
|
|
78
75
|
) {
|
|
79
|
-
throw new Error("
|
|
76
|
+
throw new Error("Template is associated to a different collection.");
|
|
80
77
|
}
|
|
81
78
|
}
|
|
82
79
|
const assetIds = [...new Set(args.assetIds ?? [])];
|
|
@@ -13,7 +13,7 @@ import { z } from "zod";
|
|
|
13
13
|
|
|
14
14
|
import { getDb, schema } from "../server/db/index.js";
|
|
15
15
|
import { createAssetFromBuffer } from "../server/lib/assets.js";
|
|
16
|
-
import {
|
|
16
|
+
import { ensureDefaultTemplates } from "../server/lib/generation-presets.js";
|
|
17
17
|
import { nowIso, stringifyJson } from "../server/lib/json.js";
|
|
18
18
|
import {
|
|
19
19
|
DEFAULT_LIBRARY_PRESET_VERSION,
|
|
@@ -141,7 +141,7 @@ export default defineAction({
|
|
|
141
141
|
|
|
142
142
|
const db = getDb();
|
|
143
143
|
await db.insert(schema.assetLibraries).values(row);
|
|
144
|
-
await
|
|
144
|
+
await ensureDefaultTemplates({ db, ownerEmail, orgId: row.orgId, now });
|
|
145
145
|
|
|
146
146
|
const referenceAssets = [];
|
|
147
147
|
const referenceSeedErrors = [];
|
|
@@ -7,7 +7,7 @@ import { nanoid } from "nanoid";
|
|
|
7
7
|
import { z } from "zod";
|
|
8
8
|
|
|
9
9
|
import { getDb, schema } from "../server/db/index.js";
|
|
10
|
-
import {
|
|
10
|
+
import { ensureDefaultTemplates } from "../server/lib/generation-presets.js";
|
|
11
11
|
import { nowIso, stringifyJson } from "../server/lib/json.js";
|
|
12
12
|
import { serializeLibrary } from "./_helpers.js";
|
|
13
13
|
|
|
@@ -57,7 +57,7 @@ export default defineAction({
|
|
|
57
57
|
};
|
|
58
58
|
const db = getDb();
|
|
59
59
|
await db.insert(schema.assetLibraries).values(row);
|
|
60
|
-
await
|
|
60
|
+
await ensureDefaultTemplates({ db, ownerEmail, orgId: row.orgId, now });
|
|
61
61
|
return serializeLibrary(row);
|
|
62
62
|
},
|
|
63
63
|
});
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { defineAction } from "@agent-native/core/action";
|
|
2
|
+
import {
|
|
3
|
+
getRequestOrgId,
|
|
4
|
+
getRequestUserEmail,
|
|
5
|
+
} from "@agent-native/core/server/request-context";
|
|
6
|
+
import { eq } from "drizzle-orm";
|
|
7
|
+
import { nanoid } from "nanoid";
|
|
8
|
+
import { z } from "zod";
|
|
9
|
+
|
|
10
|
+
import { getDb, schema } from "../server/db/index.js";
|
|
11
|
+
import { nowIso, stringifyJson } from "../server/lib/json.js";
|
|
12
|
+
import { serializeTemplate } from "./_helpers.js";
|
|
13
|
+
import {
|
|
14
|
+
assertPresetReferenceAssetsValid,
|
|
15
|
+
assertPresetReferenceModelCompatible,
|
|
16
|
+
assertPresetSkeletonAssetsValid,
|
|
17
|
+
} from "./_preset-skeleton-validation.js";
|
|
18
|
+
import { assertTemplateTargetLibraryAccess } from "./_template-access.js";
|
|
19
|
+
import { templateFieldsSchema, templateHasPins } from "./_template-input.js";
|
|
20
|
+
|
|
21
|
+
export default defineAction({
|
|
22
|
+
description:
|
|
23
|
+
"Create a reusable asset template. A template may be global or associated with one Brand Kit.",
|
|
24
|
+
schema: templateFieldsSchema.extend({ title: z.string().min(1) }),
|
|
25
|
+
run: async (args) => {
|
|
26
|
+
const ownerEmail = getRequestUserEmail();
|
|
27
|
+
if (!ownerEmail) throw new Error("Not authenticated");
|
|
28
|
+
const libraryId = args.libraryId ?? null;
|
|
29
|
+
await assertTemplateTargetLibraryAccess(libraryId);
|
|
30
|
+
const db = getDb();
|
|
31
|
+
if (args.collectionId) {
|
|
32
|
+
if (!libraryId)
|
|
33
|
+
throw new Error("A collection requires an associated Brand Kit.");
|
|
34
|
+
const [collection] = await db
|
|
35
|
+
.select()
|
|
36
|
+
.from(schema.assetCollections)
|
|
37
|
+
.where(eq(schema.assetCollections.id, args.collectionId))
|
|
38
|
+
.limit(1);
|
|
39
|
+
if (!collection || collection.libraryId !== libraryId)
|
|
40
|
+
throw new Error("Collection does not belong to this asset library.");
|
|
41
|
+
}
|
|
42
|
+
const settings = {
|
|
43
|
+
...(args.settings ?? {}),
|
|
44
|
+
...(args.includeLogo === undefined
|
|
45
|
+
? {}
|
|
46
|
+
: { includeLogo: args.includeLogo }),
|
|
47
|
+
};
|
|
48
|
+
if (!libraryId && templateHasPins(settings).length)
|
|
49
|
+
throw new Error(
|
|
50
|
+
"Global templates cannot pin images, use a skeleton, or composite a canonical logo.",
|
|
51
|
+
);
|
|
52
|
+
if (libraryId) {
|
|
53
|
+
await assertPresetSkeletonAssetsValid({ db, libraryId, settings });
|
|
54
|
+
await assertPresetReferenceAssetsValid({ db, libraryId, settings });
|
|
55
|
+
}
|
|
56
|
+
assertPresetReferenceModelCompatible({
|
|
57
|
+
model: args.model ?? "gemini-3.1-flash-image",
|
|
58
|
+
settings,
|
|
59
|
+
});
|
|
60
|
+
const now = nowIso();
|
|
61
|
+
const row = {
|
|
62
|
+
id: nanoid(),
|
|
63
|
+
libraryId,
|
|
64
|
+
collectionId: args.collectionId ?? null,
|
|
65
|
+
title: args.title,
|
|
66
|
+
description: args.description ?? null,
|
|
67
|
+
category: args.category ?? "style-only",
|
|
68
|
+
mediaType: "image",
|
|
69
|
+
promptTemplate: args.promptTemplate ?? null,
|
|
70
|
+
aspectRatio: args.aspectRatio ?? "16:9",
|
|
71
|
+
imageSize: args.imageSize ?? "2K",
|
|
72
|
+
model: args.model ?? "gemini-3.1-flash-image",
|
|
73
|
+
textPolicy: args.textPolicy ?? "",
|
|
74
|
+
referencePolicy: args.referencePolicy ?? "auto",
|
|
75
|
+
settings: stringifyJson(settings),
|
|
76
|
+
sortOrder: args.sortOrder ?? 100,
|
|
77
|
+
ownerEmail,
|
|
78
|
+
orgId: getRequestOrgId(),
|
|
79
|
+
visibility: "private" as const,
|
|
80
|
+
createdAt: now,
|
|
81
|
+
updatedAt: now,
|
|
82
|
+
};
|
|
83
|
+
await db.insert(schema.assetTemplates).values(row);
|
|
84
|
+
return serializeTemplate(row);
|
|
85
|
+
},
|
|
86
|
+
});
|
|
@@ -1,36 +1,10 @@
|
|
|
1
1
|
import { defineAction } from "@agent-native/core/action";
|
|
2
|
-
import { assertAccess } from "@agent-native/core/sharing";
|
|
3
|
-
import { eq } from "drizzle-orm";
|
|
4
2
|
import { z } from "zod";
|
|
5
3
|
|
|
6
|
-
import
|
|
4
|
+
import deleteTemplate from "./delete-template.js";
|
|
7
5
|
|
|
8
6
|
export default defineAction({
|
|
9
|
-
description:
|
|
10
|
-
"Delete a generation preset from an asset library. Existing generation runs keep their captured settings.",
|
|
7
|
+
description: "Deprecated — use delete-template. Delete a generation preset.",
|
|
11
8
|
schema: z.object({ id: z.string() }),
|
|
12
|
-
run: async (
|
|
13
|
-
const db = getDb();
|
|
14
|
-
const [preset] = await db
|
|
15
|
-
.select()
|
|
16
|
-
.from(schema.assetGenerationPresets)
|
|
17
|
-
.where(eq(schema.assetGenerationPresets.id, id))
|
|
18
|
-
.limit(1);
|
|
19
|
-
if (!preset) throw new Error("Generation preset not found.");
|
|
20
|
-
await assertAccess("asset-library", preset.libraryId, "editor");
|
|
21
|
-
const [referencingSession] = await db
|
|
22
|
-
.select({ id: schema.assetGenerationSessions.id })
|
|
23
|
-
.from(schema.assetGenerationSessions)
|
|
24
|
-
.where(eq(schema.assetGenerationSessions.presetId, id))
|
|
25
|
-
.limit(1);
|
|
26
|
-
if (referencingSession) {
|
|
27
|
-
throw new Error(
|
|
28
|
-
"Generation preset is used by an existing handoff session and cannot be deleted.",
|
|
29
|
-
);
|
|
30
|
-
}
|
|
31
|
-
await db
|
|
32
|
-
.delete(schema.assetGenerationPresets)
|
|
33
|
-
.where(eq(schema.assetGenerationPresets.id, id));
|
|
34
|
-
return { id, deleted: true };
|
|
35
|
-
},
|
|
9
|
+
run: async (args) => deleteTemplate.run(args),
|
|
36
10
|
});
|
|
@@ -16,6 +16,10 @@ export default defineAction({
|
|
|
16
16
|
.select({ id: schema.assetGenerationSessions.id })
|
|
17
17
|
.from(schema.assetGenerationSessions)
|
|
18
18
|
.where(eq(schema.assetGenerationSessions.libraryId, id));
|
|
19
|
+
const templates = await db
|
|
20
|
+
.select({ id: schema.assetTemplates.id })
|
|
21
|
+
.from(schema.assetTemplates)
|
|
22
|
+
.where(eq(schema.assetTemplates.libraryId, id));
|
|
19
23
|
for (const session of sessions) {
|
|
20
24
|
await db
|
|
21
25
|
.delete(schema.assetGenerationSessionItems)
|
|
@@ -24,9 +28,14 @@ export default defineAction({
|
|
|
24
28
|
await db
|
|
25
29
|
.delete(schema.assetGenerationSessions)
|
|
26
30
|
.where(eq(schema.assetGenerationSessions.libraryId, id));
|
|
31
|
+
for (const template of templates) {
|
|
32
|
+
await db
|
|
33
|
+
.delete(schema.assetTemplateShares)
|
|
34
|
+
.where(eq(schema.assetTemplateShares.resourceId, template.id));
|
|
35
|
+
}
|
|
27
36
|
await db
|
|
28
|
-
.delete(schema.
|
|
29
|
-
.where(eq(schema.
|
|
37
|
+
.delete(schema.assetTemplates)
|
|
38
|
+
.where(eq(schema.assetTemplates.libraryId, id));
|
|
30
39
|
await db.delete(schema.assets).where(eq(schema.assets.libraryId, id));
|
|
31
40
|
await db
|
|
32
41
|
.delete(schema.assetGenerationRuns)
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { defineAction } from "@agent-native/core/action";
|
|
2
|
+
import { eq } from "drizzle-orm";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
|
|
5
|
+
import { getDb, schema } from "../server/db/index.js";
|
|
6
|
+
import { resolveTemplateAccess } from "./_template-access.js";
|
|
7
|
+
|
|
8
|
+
export default defineAction({
|
|
9
|
+
description:
|
|
10
|
+
"Delete an asset template when no handoff session references it.",
|
|
11
|
+
schema: z.object({ id: z.string() }),
|
|
12
|
+
run: async ({ id }) => {
|
|
13
|
+
await resolveTemplateAccess(id, "editor");
|
|
14
|
+
const db = getDb();
|
|
15
|
+
const [[session], [run]] = await Promise.all([
|
|
16
|
+
db
|
|
17
|
+
.select({ id: schema.assetGenerationSessions.id })
|
|
18
|
+
.from(schema.assetGenerationSessions)
|
|
19
|
+
.where(eq(schema.assetGenerationSessions.presetId, id))
|
|
20
|
+
.limit(1),
|
|
21
|
+
db
|
|
22
|
+
.select({ id: schema.assetGenerationRuns.id })
|
|
23
|
+
.from(schema.assetGenerationRuns)
|
|
24
|
+
.where(eq(schema.assetGenerationRuns.presetId, id))
|
|
25
|
+
.limit(1),
|
|
26
|
+
]);
|
|
27
|
+
if (session || run) throw new Error("template-in-use");
|
|
28
|
+
await db
|
|
29
|
+
.delete(schema.assetTemplateShares)
|
|
30
|
+
.where(eq(schema.assetTemplateShares.resourceId, id));
|
|
31
|
+
await db
|
|
32
|
+
.delete(schema.assetTemplates)
|
|
33
|
+
.where(eq(schema.assetTemplates.id, id));
|
|
34
|
+
return { id, deleted: true };
|
|
35
|
+
},
|
|
36
|
+
});
|
|
@@ -15,7 +15,7 @@ import { normalizePresetReferences } from "../server/lib/preset-references.js";
|
|
|
15
15
|
import { normalizePresetSkeletonSpec } from "../server/lib/preset-skeleton.js";
|
|
16
16
|
import {
|
|
17
17
|
serializeAsset,
|
|
18
|
-
|
|
18
|
+
serializeTemplate,
|
|
19
19
|
serializeLibrary,
|
|
20
20
|
} from "./_helpers.js";
|
|
21
21
|
|
|
@@ -117,6 +117,7 @@ export default defineAction({
|
|
|
117
117
|
|
|
118
118
|
const ownerEmail = getRequestUserEmail();
|
|
119
119
|
if (!ownerEmail) throw new Error("no authenticated user");
|
|
120
|
+
const orgId = getRequestOrgId();
|
|
120
121
|
|
|
121
122
|
const db = getDb();
|
|
122
123
|
const [source] = await db
|
|
@@ -141,8 +142,8 @@ export default defineAction({
|
|
|
141
142
|
.where(eq(schema.assetFolders.libraryId, id)),
|
|
142
143
|
db
|
|
143
144
|
.select()
|
|
144
|
-
.from(schema.
|
|
145
|
-
.where(eq(schema.
|
|
145
|
+
.from(schema.assetTemplates)
|
|
146
|
+
.where(eq(schema.assetTemplates.libraryId, id)),
|
|
146
147
|
db
|
|
147
148
|
.select()
|
|
148
149
|
.from(schema.assets)
|
|
@@ -231,6 +232,9 @@ export default defineAction({
|
|
|
231
232
|
referencePolicy: preset.referencePolicy,
|
|
232
233
|
settings: remapJsonText(preset.settings, allIds),
|
|
233
234
|
sortOrder: preset.sortOrder,
|
|
235
|
+
ownerEmail,
|
|
236
|
+
orgId,
|
|
237
|
+
visibility: "private" as const,
|
|
234
238
|
createdAt: now,
|
|
235
239
|
updatedAt: now,
|
|
236
240
|
}));
|
|
@@ -296,7 +300,7 @@ export default defineAction({
|
|
|
296
300
|
await tx.insert(schema.assetFolders).values(copiedFolders);
|
|
297
301
|
}
|
|
298
302
|
if (copiedPresets.length) {
|
|
299
|
-
await tx.insert(schema.
|
|
303
|
+
await tx.insert(schema.assetTemplates).values(copiedPresets);
|
|
300
304
|
}
|
|
301
305
|
if (copiedAssets.length) {
|
|
302
306
|
await tx.insert(schema.assets).values(copiedAssets);
|
|
@@ -314,7 +318,7 @@ export default defineAction({
|
|
|
314
318
|
},
|
|
315
319
|
collections: copiedCollections,
|
|
316
320
|
folders: copiedFolders,
|
|
317
|
-
generationPresets: copiedPresets.map(
|
|
321
|
+
generationPresets: copiedPresets.map(serializeTemplate),
|
|
318
322
|
assets: copiedAssets.map(serializeAsset),
|
|
319
323
|
};
|
|
320
324
|
},
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { defineAction } from "@agent-native/core/action";
|
|
2
|
+
import {
|
|
3
|
+
getRequestOrgId,
|
|
4
|
+
getRequestUserEmail,
|
|
5
|
+
} from "@agent-native/core/server/request-context";
|
|
6
|
+
import { nanoid } from "nanoid";
|
|
7
|
+
import { z } from "zod";
|
|
8
|
+
|
|
9
|
+
import { getDb, schema } from "../server/db/index.js";
|
|
10
|
+
import { nowIso, parseJson, stringifyJson } from "../server/lib/json.js";
|
|
11
|
+
import { serializeTemplate } from "./_helpers.js";
|
|
12
|
+
import {
|
|
13
|
+
assertTemplateTargetLibraryAccess,
|
|
14
|
+
resolveTemplateAccess,
|
|
15
|
+
} from "./_template-access.js";
|
|
16
|
+
import { templateHasPins } from "./_template-input.js";
|
|
17
|
+
|
|
18
|
+
export default defineAction({
|
|
19
|
+
description: "Copy an asset template into global scope or a Brand Kit.",
|
|
20
|
+
schema: z.object({
|
|
21
|
+
id: z.string(),
|
|
22
|
+
libraryId: z.string().nullable().optional(),
|
|
23
|
+
title: z.string().min(1).optional(),
|
|
24
|
+
dropPins: z.boolean().optional(),
|
|
25
|
+
}),
|
|
26
|
+
run: async ({ id, libraryId, title, dropPins }) => {
|
|
27
|
+
const source = (await resolveTemplateAccess(id, "viewer")).resource;
|
|
28
|
+
const ownerEmail = getRequestUserEmail();
|
|
29
|
+
if (!ownerEmail) throw new Error("Not authenticated");
|
|
30
|
+
const targetLibraryId =
|
|
31
|
+
libraryId === undefined ? source.libraryId : libraryId;
|
|
32
|
+
await assertTemplateTargetLibraryAccess(targetLibraryId);
|
|
33
|
+
const settings = parseJson<Record<string, unknown>>(source.settings, {});
|
|
34
|
+
const pins = templateHasPins(settings);
|
|
35
|
+
if (!targetLibraryId && pins.length && !dropPins)
|
|
36
|
+
throw new Error(
|
|
37
|
+
`Copying this template globally requires dropPins: true (${pins.join(", ")}).`,
|
|
38
|
+
);
|
|
39
|
+
const copiedSettings =
|
|
40
|
+
!targetLibraryId && pins.length
|
|
41
|
+
? {
|
|
42
|
+
...settings,
|
|
43
|
+
includeLogo: false,
|
|
44
|
+
skeletonSpec: null,
|
|
45
|
+
presetReferences: Array.isArray(settings.presetReferences)
|
|
46
|
+
? settings.presetReferences.map((entry: any) => ({
|
|
47
|
+
...entry,
|
|
48
|
+
assetIds: [],
|
|
49
|
+
}))
|
|
50
|
+
: settings.presetReferences,
|
|
51
|
+
}
|
|
52
|
+
: settings;
|
|
53
|
+
if (
|
|
54
|
+
targetLibraryId &&
|
|
55
|
+
source.libraryId &&
|
|
56
|
+
source.libraryId !== targetLibraryId &&
|
|
57
|
+
pins.length
|
|
58
|
+
) {
|
|
59
|
+
throw new Error(
|
|
60
|
+
"Copying pinned templates into another Brand Kit is not supported until its pinned assets are copied.",
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
const now = nowIso();
|
|
64
|
+
const row = {
|
|
65
|
+
...source,
|
|
66
|
+
id: nanoid(),
|
|
67
|
+
libraryId: targetLibraryId ?? null,
|
|
68
|
+
collectionId:
|
|
69
|
+
targetLibraryId === source.libraryId ? source.collectionId : null,
|
|
70
|
+
title: title ?? `${source.title} (copy)`,
|
|
71
|
+
settings: stringifyJson(copiedSettings),
|
|
72
|
+
ownerEmail,
|
|
73
|
+
orgId: getRequestOrgId(),
|
|
74
|
+
visibility: "private" as const,
|
|
75
|
+
createdAt: now,
|
|
76
|
+
updatedAt: now,
|
|
77
|
+
};
|
|
78
|
+
await getDb().insert(schema.assetTemplates).values(row);
|
|
79
|
+
return serializeTemplate(row);
|
|
80
|
+
},
|
|
81
|
+
});
|
|
@@ -41,10 +41,13 @@ const schema = z.object({
|
|
|
41
41
|
"Brand, campaign, or use-case hint used when matching a library.",
|
|
42
42
|
),
|
|
43
43
|
aspectRatio: z.enum(ASPECT_RATIOS).default("16:9"),
|
|
44
|
-
|
|
44
|
+
templateId: z
|
|
45
45
|
.string()
|
|
46
46
|
.optional()
|
|
47
|
-
.describe(
|
|
47
|
+
.describe(
|
|
48
|
+
"Optional template ID from the selected Brand Kit or global templates.",
|
|
49
|
+
),
|
|
50
|
+
presetId: z.string().optional().describe("Deprecated — use templateId."),
|
|
48
51
|
count: z.coerce
|
|
49
52
|
.number()
|
|
50
53
|
.int()
|
|
@@ -199,7 +202,7 @@ const action = defineAction({
|
|
|
199
202
|
libraryId: args.libraryId,
|
|
200
203
|
libraryHint: args.libraryHint,
|
|
201
204
|
aspectRatio: args.aspectRatio,
|
|
202
|
-
presetId: args.presetId,
|
|
205
|
+
presetId: args.templateId ?? args.presetId,
|
|
203
206
|
count: args.count,
|
|
204
207
|
autoGenerate: true,
|
|
205
208
|
tier: args.tier,
|
|
@@ -40,6 +40,7 @@ const imageBatchAgentInputSchema = z.object({
|
|
|
40
40
|
.describe("Brand kit/library ID to use for every generated image."),
|
|
41
41
|
collectionId: z.string().optional(),
|
|
42
42
|
presetId: z.string().optional(),
|
|
43
|
+
templateId: z.string().optional(),
|
|
43
44
|
presetReferenceFills: z.array(presetReferenceFillSchema).max(6).optional(),
|
|
44
45
|
sessionId: z.string().optional(),
|
|
45
46
|
slots: z
|
|
@@ -78,12 +79,11 @@ export default defineAction({
|
|
|
78
79
|
"Brand kit/library ID. Pass the refId from a brand-kit @mention, or choose a kit from view-screen/list-libraries.",
|
|
79
80
|
),
|
|
80
81
|
collectionId: z.string().optional(),
|
|
81
|
-
|
|
82
|
+
templateId: z
|
|
82
83
|
.string()
|
|
83
84
|
.optional()
|
|
84
|
-
.describe(
|
|
85
|
-
|
|
86
|
-
),
|
|
85
|
+
.describe("Template ID from a @template mention or list-templates."),
|
|
86
|
+
presetId: z.string().optional().describe("Deprecated — use templateId."),
|
|
87
87
|
presetReferenceFills: z
|
|
88
88
|
.array(presetReferenceFillSchema)
|
|
89
89
|
.max(6)
|
|
@@ -231,7 +231,7 @@ export default defineAction({
|
|
|
231
231
|
batchId: variantBatchId,
|
|
232
232
|
libraryId: base.libraryId,
|
|
233
233
|
collectionId: base.collectionId ?? null,
|
|
234
|
-
presetId: base.presetId ?? null,
|
|
234
|
+
presetId: base.templateId ?? base.presetId ?? null,
|
|
235
235
|
sessionId: base.sessionId ?? null,
|
|
236
236
|
threadId: context?.threadId ?? null,
|
|
237
237
|
variantScopeId: base.variantScopeId ?? null,
|
|
@@ -249,6 +249,7 @@ export default defineAction({
|
|
|
249
249
|
{
|
|
250
250
|
libraryId: base.libraryId,
|
|
251
251
|
collectionId: base.collectionId,
|
|
252
|
+
templateId: base.templateId,
|
|
252
253
|
presetId: base.presetId,
|
|
253
254
|
presetReferenceFills: base.presetReferenceFills,
|
|
254
255
|
sessionId: base.sessionId,
|
|
@@ -74,6 +74,7 @@ import {
|
|
|
74
74
|
serializeAsset,
|
|
75
75
|
} from "./_helpers.js";
|
|
76
76
|
import { readImageModelDefault } from "./_image-model-default.js";
|
|
77
|
+
import { resolveTemplateAccess } from "./_template-access.js";
|
|
77
78
|
import { withToolActivity } from "./_tool-activity.js";
|
|
78
79
|
import { upsertVariantSlot, wasVariantSlotDismissed } from "./variant-slots.js";
|
|
79
80
|
|
|
@@ -84,6 +85,15 @@ const presetReferenceFillSchema = z.object({
|
|
|
84
85
|
assetIds: z.array(z.string().min(1)).min(1).max(4),
|
|
85
86
|
});
|
|
86
87
|
|
|
88
|
+
export function assertTemplateMatchesLibrary(
|
|
89
|
+
template: { libraryId: string | null } | null,
|
|
90
|
+
libraryId: string,
|
|
91
|
+
) {
|
|
92
|
+
if (template?.libraryId && template.libraryId !== libraryId) {
|
|
93
|
+
throw new Error("Template is associated to a different brand kit.");
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
87
97
|
const imageGenerationAgentInputSchema = z.object({
|
|
88
98
|
libraryId: z
|
|
89
99
|
.string()
|
|
@@ -91,6 +101,7 @@ const imageGenerationAgentInputSchema = z.object({
|
|
|
91
101
|
.describe("Brand kit/library ID to use for this image."),
|
|
92
102
|
collectionId: z.string().optional(),
|
|
93
103
|
presetId: z.string().optional(),
|
|
104
|
+
templateId: z.string().optional(),
|
|
94
105
|
sessionId: z.string().optional(),
|
|
95
106
|
prompt: z.string().min(1),
|
|
96
107
|
embeddedText: z.string().optional(),
|
|
@@ -121,12 +132,11 @@ export default defineAction({
|
|
|
121
132
|
"Brand kit/library ID. Pass the refId from a brand-kit @mention, or choose a kit from view-screen/list-libraries.",
|
|
122
133
|
),
|
|
123
134
|
collectionId: z.string().optional(),
|
|
124
|
-
|
|
135
|
+
templateId: z
|
|
125
136
|
.string()
|
|
126
137
|
.optional()
|
|
127
|
-
.describe(
|
|
128
|
-
|
|
129
|
-
),
|
|
138
|
+
.describe("Template ID from a @template mention or list-templates."),
|
|
139
|
+
presetId: z.string().optional().describe("Deprecated — use templateId."),
|
|
130
140
|
sessionId: z.string().optional(),
|
|
131
141
|
prompt: z.string().min(1),
|
|
132
142
|
embeddedText: z
|
|
@@ -419,8 +429,8 @@ export default defineAction({
|
|
|
419
429
|
];
|
|
420
430
|
if (
|
|
421
431
|
session?.presetId &&
|
|
422
|
-
args.presetId &&
|
|
423
|
-
args.presetId !== session.presetId
|
|
432
|
+
(args.templateId ?? args.presetId) &&
|
|
433
|
+
(args.templateId ?? args.presetId) !== session.presetId
|
|
424
434
|
) {
|
|
425
435
|
throw new Error("Generation preset does not match this session.");
|
|
426
436
|
}
|
|
@@ -431,20 +441,15 @@ export default defineAction({
|
|
|
431
441
|
) {
|
|
432
442
|
throw new Error("Collection does not match this session.");
|
|
433
443
|
}
|
|
434
|
-
const resolvedPresetId =
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
.where(eq(schema.assetGenerationPresets.id, resolvedPresetId))
|
|
440
|
-
.limit(1)
|
|
441
|
-
: [null];
|
|
444
|
+
const resolvedPresetId =
|
|
445
|
+
session?.presetId ?? args.templateId ?? args.presetId ?? undefined;
|
|
446
|
+
const preset = resolvedPresetId
|
|
447
|
+
? (await resolveTemplateAccess(resolvedPresetId, "viewer")).resource
|
|
448
|
+
: null;
|
|
442
449
|
if (resolvedPresetId && !preset) {
|
|
443
|
-
throw new Error("
|
|
444
|
-
}
|
|
445
|
-
if (preset && preset.libraryId !== args.libraryId) {
|
|
446
|
-
throw new Error("Generation preset does not belong to this library.");
|
|
450
|
+
throw new Error("Template not found.");
|
|
447
451
|
}
|
|
452
|
+
assertTemplateMatchesLibrary(preset, args.libraryId);
|
|
448
453
|
if (
|
|
449
454
|
session?.collectionId &&
|
|
450
455
|
preset?.collectionId &&
|