@orangecatai/adgen-canvas 0.0.35 → 0.0.37
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/dist/dev/{chunk-KJZTX4HK.js → chunk-2TI3DKZO.js} +3 -3
- package/dist/dev/{chunk-AVI2TDX6.js → chunk-X5D27DN4.js} +2 -2
- package/dist/dev/data/{image-JWQCODTZ.js → image-6PRWOWBV.js} +3 -3
- package/dist/dev/index.js +64 -67
- package/dist/dev/index.js.map +2 -2
- package/dist/dev/subset-shared.chunk.js +1 -1
- package/dist/dev/subset-worker.chunk.js +1 -1
- package/dist/prod/{chunk-TE4JIU3E.js → chunk-AE7ZZTR5.js} +1 -1
- package/dist/prod/{chunk-R3CESCMK.js → chunk-KY6F7LB5.js} +2 -2
- package/dist/prod/data/image-HNYRNFPK.js +1 -0
- package/dist/prod/index.js +55 -63
- package/dist/prod/subset-shared.chunk.js +1 -1
- package/dist/prod/subset-worker.chunk.js +1 -1
- package/dist/types/excalidraw/components/AIChatPanel.d.ts +7 -3
- package/dist/types/excalidraw/components/ai-chat/canvasTools.d.ts +12 -11
- package/dist/types/excalidraw/types.d.ts +9 -4
- package/package.json +2 -2
- package/dist/prod/data/image-EQCUXFMW.js +0 -1
- /package/dist/dev/{chunk-KJZTX4HK.js.map → chunk-2TI3DKZO.js.map} +0 -0
- /package/dist/dev/{chunk-AVI2TDX6.js.map → chunk-X5D27DN4.js.map} +0 -0
- /package/dist/dev/data/{image-JWQCODTZ.js.map → image-6PRWOWBV.js.map} +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
define_import_meta_env_default
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-X5D27DN4.js";
|
|
4
4
|
import {
|
|
5
5
|
__publicField
|
|
6
6
|
} from "./chunk-XDFCUUT6.js";
|
|
@@ -5155,7 +5155,7 @@ var parseFileContents = async (blob) => {
|
|
|
5155
5155
|
let contents;
|
|
5156
5156
|
if (blob.type === MIME_TYPES6.png) {
|
|
5157
5157
|
try {
|
|
5158
|
-
return await (await import("./data/image-
|
|
5158
|
+
return await (await import("./data/image-6PRWOWBV.js")).decodePngMetadata(blob);
|
|
5159
5159
|
} catch (error) {
|
|
5160
5160
|
if (error.message === "INVALID") {
|
|
5161
5161
|
throw new ImageSceneDataError(
|
|
@@ -5607,4 +5607,4 @@ export {
|
|
|
5607
5607
|
createFile,
|
|
5608
5608
|
normalizeFile
|
|
5609
5609
|
};
|
|
5610
|
-
//# sourceMappingURL=chunk-
|
|
5610
|
+
//# sourceMappingURL=chunk-2TI3DKZO.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// <define:import.meta.env>
|
|
2
|
-
var define_import_meta_env_default = { MODE: "development", VITE_APP_GEMINI_API_KEY: "", VITE_APP_OPENROUTER_API_KEY: "", VITE_APP_BACKEND_V2_GET_URL: "https://json-dev.excalidraw.com/api/v2/", VITE_APP_BACKEND_V2_POST_URL: "https://json-dev.excalidraw.com/api/v2/post/", VITE_APP_LIBRARY_URL: "https://libraries.excalidraw.com", VITE_APP_LIBRARY_BACKEND: "https://us-central1-excalidraw-room-persistence.cloudfunctions.net/libraries", VITE_APP_WS_SERVER_URL: "http://localhost:3002", VITE_APP_PLUS_LP: "https://plus.excalidraw.com", VITE_APP_PLUS_APP: "http://localhost:3000", VITE_APP_AI_BACKEND: "http://localhost:3016", VITE_APP_FIREBASE_CONFIG: '{"apiKey":"AIzaSyCMkxA60XIW8KbqMYL7edC4qT5l4qHX2h8","authDomain":"excalidraw-oss-dev.firebaseapp.com","projectId":"excalidraw-oss-dev","storageBucket":"excalidraw-oss-dev.appspot.com","messagingSenderId":"664559512677","appId":"1:664559512677:web:a385181f2928d328a7aa8c"}', VITE_APP_DEV_DISABLE_LIVE_RELOAD: "", VITE_APP_ENABLE_TRACKING: "true", FAST_REFRESH: "false", VITE_APP_PORT: "3001", VITE_APP_DEBUG_ENABLE_TEXT_CONTAINER_BOUNDING_BOX: "", VITE_APP_COLLAPSE_OVERLAY: "true", VITE_APP_ENABLE_ESLINT: "true", VITE_APP_ENABLE_PWA: "false", VITE_APP_PLUS_EXPORT_PUBLIC_KEY: "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAm2g5T+Rub6Kbf1Mf57t0\n7r2zeHuVg4dla3r5ryXMswtzz6x767octl6oLThn33mQsPSy3GKglFZoCTXJR4ij\nba8SxB04sL/N8eRrKja7TFWjCVtRwTTfyy771NYYNFVJclkxHyE5qw4m27crHF1y\nUNWEjuqNMi/lwAErS9fFa2oJlWyT8U7zzv/5kQREkxZI6y9v0AF3qcbsy2731FnD\ns9ChJvOUW9toIab2gsIdrKW8ZNpu084ZFVKb6LNjvIXI1Se4oMTHeszXzNptzlot\nkdxxjOoaQMAyfljFSot1F1FlU6MQlag7UnFGvFjRHN1JI5q4K+n3a67DX+TMyRqS\nHQIDAQAB", VITE_APP_DISABLE_PREVENT_UNLOAD: "", PKG_NAME: "@orangecatai/adgen-canvas", PKG_VERSION: "0.0.
|
|
2
|
+
var define_import_meta_env_default = { MODE: "development", VITE_APP_GEMINI_API_KEY: "", VITE_APP_OPENROUTER_API_KEY: "", VITE_APP_BACKEND_V2_GET_URL: "https://json-dev.excalidraw.com/api/v2/", VITE_APP_BACKEND_V2_POST_URL: "https://json-dev.excalidraw.com/api/v2/post/", VITE_APP_LIBRARY_URL: "https://libraries.excalidraw.com", VITE_APP_LIBRARY_BACKEND: "https://us-central1-excalidraw-room-persistence.cloudfunctions.net/libraries", VITE_APP_WS_SERVER_URL: "http://localhost:3002", VITE_APP_PLUS_LP: "https://plus.excalidraw.com", VITE_APP_PLUS_APP: "http://localhost:3000", VITE_APP_AI_BACKEND: "http://localhost:3016", VITE_APP_FIREBASE_CONFIG: '{"apiKey":"AIzaSyCMkxA60XIW8KbqMYL7edC4qT5l4qHX2h8","authDomain":"excalidraw-oss-dev.firebaseapp.com","projectId":"excalidraw-oss-dev","storageBucket":"excalidraw-oss-dev.appspot.com","messagingSenderId":"664559512677","appId":"1:664559512677:web:a385181f2928d328a7aa8c"}', VITE_APP_DEV_DISABLE_LIVE_RELOAD: "", VITE_APP_ENABLE_TRACKING: "true", FAST_REFRESH: "false", VITE_APP_PORT: "3001", VITE_APP_DEBUG_ENABLE_TEXT_CONTAINER_BOUNDING_BOX: "", VITE_APP_COLLAPSE_OVERLAY: "true", VITE_APP_ENABLE_ESLINT: "true", VITE_APP_ENABLE_PWA: "false", VITE_APP_PLUS_EXPORT_PUBLIC_KEY: "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAm2g5T+Rub6Kbf1Mf57t0\n7r2zeHuVg4dla3r5ryXMswtzz6x767octl6oLThn33mQsPSy3GKglFZoCTXJR4ij\nba8SxB04sL/N8eRrKja7TFWjCVtRwTTfyy771NYYNFVJclkxHyE5qw4m27crHF1y\nUNWEjuqNMi/lwAErS9fFa2oJlWyT8U7zzv/5kQREkxZI6y9v0AF3qcbsy2731FnD\ns9ChJvOUW9toIab2gsIdrKW8ZNpu084ZFVKb6LNjvIXI1Se4oMTHeszXzNptzlot\nkdxxjOoaQMAyfljFSot1F1FlU6MQlag7UnFGvFjRHN1JI5q4K+n3a67DX+TMyRqS\nHQIDAQAB", VITE_APP_DISABLE_PREVENT_UNLOAD: "", PKG_NAME: "@orangecatai/adgen-canvas", PKG_VERSION: "0.0.37", DEV: true };
|
|
3
3
|
|
|
4
4
|
export {
|
|
5
5
|
define_import_meta_env_default
|
|
6
6
|
};
|
|
7
|
-
//# sourceMappingURL=chunk-
|
|
7
|
+
//# sourceMappingURL=chunk-X5D27DN4.js.map
|
|
@@ -2,12 +2,12 @@ import {
|
|
|
2
2
|
decodePngMetadata,
|
|
3
3
|
encodePngMetadata,
|
|
4
4
|
getTEXtChunk
|
|
5
|
-
} from "../chunk-
|
|
6
|
-
import "../chunk-
|
|
5
|
+
} from "../chunk-2TI3DKZO.js";
|
|
6
|
+
import "../chunk-X5D27DN4.js";
|
|
7
7
|
import "../chunk-XDFCUUT6.js";
|
|
8
8
|
export {
|
|
9
9
|
decodePngMetadata,
|
|
10
10
|
encodePngMetadata,
|
|
11
11
|
getTEXtChunk
|
|
12
12
|
};
|
|
13
|
-
//# sourceMappingURL=image-
|
|
13
|
+
//# sourceMappingURL=image-6PRWOWBV.js.map
|
package/dist/dev/index.js
CHANGED
|
@@ -66,10 +66,10 @@ import {
|
|
|
66
66
|
serializeAsJSON,
|
|
67
67
|
serializeLibraryAsJSON,
|
|
68
68
|
strokeRectWithRotation_simple
|
|
69
|
-
} from "./chunk-
|
|
69
|
+
} from "./chunk-2TI3DKZO.js";
|
|
70
70
|
import {
|
|
71
71
|
define_import_meta_env_default
|
|
72
|
-
} from "./chunk-
|
|
72
|
+
} from "./chunk-X5D27DN4.js";
|
|
73
73
|
import {
|
|
74
74
|
en_default
|
|
75
75
|
} from "./chunk-LIELFD5T.js";
|
|
@@ -9797,7 +9797,7 @@ var exportCanvas = async (type, elements, appState, files, {
|
|
|
9797
9797
|
let blob = canvasToBlob(tempCanvas);
|
|
9798
9798
|
if (appState.exportEmbedScene) {
|
|
9799
9799
|
blob = blob.then(
|
|
9800
|
-
(blob2) => import("./data/image-
|
|
9800
|
+
(blob2) => import("./data/image-6PRWOWBV.js").then(
|
|
9801
9801
|
({ encodePngMetadata: encodePngMetadata2 }) => encodePngMetadata2({
|
|
9802
9802
|
blob: blob2,
|
|
9803
9803
|
metadata: serializeAsJSON(elements, appState, files, "local")
|
|
@@ -30463,7 +30463,7 @@ var TemplateBuilderPanelHost = ({
|
|
|
30463
30463
|
if (!panelState.isOpen) {
|
|
30464
30464
|
return null;
|
|
30465
30465
|
}
|
|
30466
|
-
const handleSaveTemplate = () => {
|
|
30466
|
+
const handleSaveTemplate = async () => {
|
|
30467
30467
|
const onSaveTemplate = app.props.onSaveTemplate;
|
|
30468
30468
|
if (!onSaveTemplate) {
|
|
30469
30469
|
return;
|
|
@@ -30511,7 +30511,27 @@ var TemplateBuilderPanelHost = ({
|
|
|
30511
30511
|
}
|
|
30512
30512
|
}
|
|
30513
30513
|
}
|
|
30514
|
-
|
|
30514
|
+
let thumbnailDataUrl;
|
|
30515
|
+
try {
|
|
30516
|
+
const blob = await exportToBlob({
|
|
30517
|
+
elements: [...frameChildren, frame],
|
|
30518
|
+
appState: app.state,
|
|
30519
|
+
files,
|
|
30520
|
+
exportingFrame: frame,
|
|
30521
|
+
exportPadding: 0,
|
|
30522
|
+
mimeType: "image/png"
|
|
30523
|
+
});
|
|
30524
|
+
thumbnailDataUrl = await new Promise((resolve, reject) => {
|
|
30525
|
+
const reader = new FileReader();
|
|
30526
|
+
reader.onload = () => resolve(reader.result);
|
|
30527
|
+
reader.onerror = () => reject(reader.error);
|
|
30528
|
+
reader.readAsDataURL(blob);
|
|
30529
|
+
});
|
|
30530
|
+
} catch {
|
|
30531
|
+
alert("Couldn't capture this template frame. Please try again.");
|
|
30532
|
+
return;
|
|
30533
|
+
}
|
|
30534
|
+
await onSaveTemplate({
|
|
30515
30535
|
name: panelState.templateName,
|
|
30516
30536
|
campaignTag: panelState.campaignTag || void 0,
|
|
30517
30537
|
label: `${Math.round(frame.width)}x${Math.round(frame.height)}`,
|
|
@@ -30521,7 +30541,8 @@ var TemplateBuilderPanelHost = ({
|
|
|
30521
30541
|
frame: { ...frame },
|
|
30522
30542
|
elements: frameChildren,
|
|
30523
30543
|
...Object.keys(templateFiles).length > 0 ? { files: templateFiles } : {}
|
|
30524
|
-
})
|
|
30544
|
+
}),
|
|
30545
|
+
thumbnailDataUrl
|
|
30525
30546
|
});
|
|
30526
30547
|
templateBuilderStore.close();
|
|
30527
30548
|
};
|
|
@@ -58739,31 +58760,16 @@ var BANNER_TOOLS = [
|
|
|
58739
58760
|
type: "function",
|
|
58740
58761
|
function: {
|
|
58741
58762
|
name: "list_brand_templates",
|
|
58742
|
-
description:
|
|
58743
|
-
|
|
58744
|
-
MANDATORY SEARCH PROTOCOL \u2014 follow exactly, no shortcuts:
|
|
58745
|
-
|
|
58746
|
-
ATTEMPT 1: Generate TWO sets of 10 keywords each from the user's request:
|
|
58747
|
-
- Set A (campaign tag variations): 10 synonyms/abbreviations/phrasings of the campaign topic (e.g. for "noida datacenter": ["datacenter", "data center", "dc", "noida dc", "noida datacenter", "data centre", "server farm", "cloud infra", "hyperscale", "colocation"])
|
|
58748
|
-
- Set B (template name variations): 10 different name keywords the template might have (e.g. ["noida", "datacenter campaign", "new datacenter", "dc launch", "infrastructure", "cloud", "enterprise", "b2b", "tech", "facility"])
|
|
58749
|
-
Merge all 20 into the keywords array. Call list_brand_templates with all 20.
|
|
58750
|
-
|
|
58751
|
-
IF templates returned is empty \u2192 ATTEMPT 2 (MANDATORY \u2014 do NOT skip):
|
|
58752
|
-
Generate a completely DIFFERENT set of 20 keywords \u2014 do not reuse any from attempt 1. Think laterally: different synonyms, related industry terms, the city name, brand-adjacent words, seasonal terms. Call list_brand_templates again with the new 20.
|
|
58753
|
-
|
|
58754
|
-
ONLY after both attempts return empty \u2192 tell the user no matching template was found.
|
|
58755
|
-
|
|
58756
|
-
If no search context exists, call with an empty keywords array to list all templates.`,
|
|
58763
|
+
description: "Search saved brand templates semantically against the full ad brief. Results are ranked from captions generated from the actual template frame. Use the returned visual description, campaign fit, dimensions, and ID to decide whether to use a template.",
|
|
58757
58764
|
parameters: {
|
|
58758
58765
|
type: "object",
|
|
58759
58766
|
properties: {
|
|
58760
|
-
|
|
58761
|
-
type: "
|
|
58762
|
-
|
|
58763
|
-
description: "Up to 20 keyword variations to search across template names, campaign tags, and labels. All are OR-matched case-insensitively. Generate 10 tag synonyms + 10 name variations from the user's request."
|
|
58767
|
+
brief: {
|
|
58768
|
+
type: "string",
|
|
58769
|
+
description: "The user's complete ad brief, including campaign, subject, style, copy, and requested dimensions when known."
|
|
58764
58770
|
}
|
|
58765
58771
|
},
|
|
58766
|
-
required: [],
|
|
58772
|
+
required: ["brief"],
|
|
58767
58773
|
additionalProperties: false
|
|
58768
58774
|
}
|
|
58769
58775
|
}
|
|
@@ -60450,17 +60456,12 @@ async function execFinalizeAd(args, ctx) {
|
|
|
60450
60456
|
};
|
|
60451
60457
|
}
|
|
60452
60458
|
async function execListBrandTemplates(args, ctx) {
|
|
60453
|
-
|
|
60454
|
-
if (Array.isArray(args.keywords) && args.keywords.length > 0) {
|
|
60455
|
-
keywords = args.keywords;
|
|
60456
|
-
} else if (args.query || args.campaignTag) {
|
|
60457
|
-
keywords = [args.query ?? args.campaignTag];
|
|
60458
|
-
}
|
|
60459
|
+
const brief = typeof args.brief === "string" ? args.brief : "";
|
|
60459
60460
|
if (!ctx.onListBrandTemplates) {
|
|
60460
60461
|
return { success: true, statusMessage: "No template list configured" };
|
|
60461
60462
|
}
|
|
60462
60463
|
try {
|
|
60463
|
-
const templates = await ctx.onListBrandTemplates(
|
|
60464
|
+
const templates = await ctx.onListBrandTemplates(brief);
|
|
60464
60465
|
if (templates.length === 0) {
|
|
60465
60466
|
return {
|
|
60466
60467
|
success: true,
|
|
@@ -60468,28 +60469,18 @@ async function execListBrandTemplates(args, ctx) {
|
|
|
60468
60469
|
statusMessage: "No templates found"
|
|
60469
60470
|
};
|
|
60470
60471
|
}
|
|
60471
|
-
if (keywords && keywords.length > 0) {
|
|
60472
|
-
const kws = keywords.map((k) => k.toLowerCase());
|
|
60473
|
-
templates.sort((a, b) => {
|
|
60474
|
-
const scoreA = kws.filter(
|
|
60475
|
-
(k) => a.name.toLowerCase().includes(k) || (a.campaignTag ?? "").toLowerCase().includes(k) || (a.label ?? "").toLowerCase().includes(k)
|
|
60476
|
-
).length;
|
|
60477
|
-
const scoreB = kws.filter(
|
|
60478
|
-
(k) => b.name.toLowerCase().includes(k) || (b.campaignTag ?? "").toLowerCase().includes(k) || (b.label ?? "").toLowerCase().includes(k)
|
|
60479
|
-
).length;
|
|
60480
|
-
return scoreB - scoreA;
|
|
60481
|
-
});
|
|
60482
|
-
}
|
|
60483
60472
|
const list = templates.map((t2) => {
|
|
60484
60473
|
const dims = t2.width && t2.height ? ` (${t2.width}x${t2.height})` : "";
|
|
60485
|
-
|
|
60474
|
+
const metadata = t2.visualMetadata;
|
|
60475
|
+
return `Template: ${t2.name}${dims} [id:${t2.id}]
|
|
60476
|
+
Caption: ${metadata?.caption ?? "No caption"}
|
|
60477
|
+
Layout: ${metadata?.layout ?? "No layout description"}
|
|
60478
|
+
Best for: ${(metadata?.useCases ?? []).join(", ") || "unspecified"}`;
|
|
60486
60479
|
}).join("\n");
|
|
60487
|
-
const previews = templates.filter((t2) => t2.thumbnailDataUrl).slice(0, 3).map((t2) => ({ name: t2.name, dataUrl: t2.thumbnailDataUrl }));
|
|
60488
60480
|
return {
|
|
60489
60481
|
success: true,
|
|
60490
60482
|
data: { templates, summary: list },
|
|
60491
|
-
statusMessage: `Found ${templates.length} template(s)
|
|
60492
|
-
previewDataUrls: previews.length > 0 ? previews : void 0
|
|
60483
|
+
statusMessage: `Found ${templates.length} template(s)`
|
|
60493
60484
|
};
|
|
60494
60485
|
} catch {
|
|
60495
60486
|
return {
|
|
@@ -60571,6 +60562,13 @@ async function execLoadTemplateIntoFrame(args, ctx) {
|
|
|
60571
60562
|
);
|
|
60572
60563
|
const scaleX = targetFrame.width / (templateFrame.width || 1);
|
|
60573
60564
|
const scaleY = targetFrame.height / (templateFrame.height || 1);
|
|
60565
|
+
if (Math.abs(scaleX - scaleY) > 0.01) {
|
|
60566
|
+
return {
|
|
60567
|
+
success: false,
|
|
60568
|
+
error: `Template is ${Math.round(templateFrame.width)}x${Math.round(templateFrame.height)} and cannot be stretched into ${Math.round(targetFrame.width)}x${Math.round(targetFrame.height)}. Tell the user you will make the native template size first, then resize it afterward.`,
|
|
60569
|
+
statusMessage: "Template aspect ratio mismatch"
|
|
60570
|
+
};
|
|
60571
|
+
}
|
|
60574
60572
|
const offsetX = targetFrame.x - templateFrame.x * scaleX;
|
|
60575
60573
|
const offsetY = targetFrame.y - templateFrame.y * scaleY;
|
|
60576
60574
|
const importedElements = templateElements.map(
|
|
@@ -61145,7 +61143,7 @@ Aim for typography that is crisp and legible with copy correctly spelled.
|
|
|
61145
61143
|
|
|
61146
61144
|
Brand context is mandatory input, not optional decoration. The generated ad must reflect the brand kit / brand code, the approved copy, and the visual direction \u2014 never generate something arbitrary.
|
|
61147
61145
|
|
|
61148
|
-
BRAND REFERENCES are auto-fetched
|
|
61146
|
+
BRAND REFERENCES are auto-fetched at the start of every session: visual previews for assets/creatives, and text-only semantic captions for up to 2 ranked templates. Check them before deciding how to generate:
|
|
61149
61147
|
|
|
61150
61148
|
- If a **template** clearly fits the user's request \u2192 use it: \`load_template_into_frame\` + \`fill_template_slots\`. Do NOT call \`generate_image\` on a template ad.
|
|
61151
61149
|
- If a **brand asset or ad creative** is relevant \u2192 pass its image as a reference to \`generate_image\` so the output matches existing brand visuals.
|
|
@@ -61153,11 +61151,11 @@ BRAND REFERENCES are auto-fetched and provided to you as visual context at the s
|
|
|
61153
61151
|
|
|
61154
61152
|
You may still call \`search_brand_assets()\`, \`search_ad_creatives()\`, or \`list_brand_templates()\` explicitly if the user asks for something specific that may not have been in the auto-fetched top 2.
|
|
61155
61153
|
|
|
61156
|
-
TEMPLATE BANK (when using a template): call \`list_brand_templates()
|
|
61154
|
+
TEMPLATE BANK (when using a template): call \`list_brand_templates()\` with the full brief, present the semantic match, then:
|
|
61157
61155
|
1. \`load_template_into_frame(frameId, variantId)\`
|
|
61158
61156
|
2. \`get_frame_elements(frameId)\` to see the slots
|
|
61159
61157
|
3. \`fill_template_slots(frameId, headline, subhead, cta, background_color, product_image_url, logo_url)\` \u2014 all slots in one call.
|
|
61160
|
-
Template text slots are fixed-size boxes \u2014 keep copy tight (headline \u22645 words, subhead \u22648, cta \u22643, signoff \u22644). After \`fill_template_slots\`, the template ad is done \u2014 do NOT call \`generate_image\` or \`generate_html_banner\` on it. The quality review runs automatically.`;
|
|
61158
|
+
Template text slots are fixed-size boxes \u2014 keep copy tight (headline \u22645 words, subhead \u22648, cta \u22643, signoff \u22644). A template's listed dimensions are authoritative: if the user requested an incompatible aspect ratio (for example, a 1:1 template for a 16:9 deliverable), tell them that you will make the ad at the template's native 1:1 size first and later use resize for 16:9. Create the template frame at its native dimensions; never stretch it to the requested ratio. After \`fill_template_slots\`, the template ad is done \u2014 do NOT call \`generate_image\` or \`generate_html_banner\` on it. The quality review runs automatically.`;
|
|
61161
61159
|
var MAX_ITERATIONS = 15;
|
|
61162
61160
|
async function callOpenRouter(messages, chatUrl, signal, webSearchEnabled, chatModel, onContentChunk, tools = CANVAS_TOOLS) {
|
|
61163
61161
|
const baseModel = chatModel || "minimax/minimax-m3";
|
|
@@ -61335,15 +61333,10 @@ ${elementContext}`
|
|
|
61335
61333
|
{
|
|
61336
61334
|
const lastUserText = [...userMessages].reverse().find((m) => m.role === "user")?.content ?? "";
|
|
61337
61335
|
if (lastUserText && (toolCtx.onSearchBrandAssets || toolCtx.onSearchAdCreatives || toolCtx.onListBrandTemplates)) {
|
|
61338
|
-
const keywords = [
|
|
61339
|
-
...new Set(
|
|
61340
|
-
lastUserText.toLowerCase().replace(/[^\w\s]/g, " ").split(/\s+/).filter((w) => w.length > 3)
|
|
61341
|
-
)
|
|
61342
|
-
].slice(0, 10);
|
|
61343
61336
|
const [assetRes, creativeRes, templateRes] = await Promise.allSettled([
|
|
61344
61337
|
toolCtx.onSearchBrandAssets ? toolCtx.onSearchBrandAssets(lastUserText) : Promise.resolve([]),
|
|
61345
61338
|
toolCtx.onSearchAdCreatives ? toolCtx.onSearchAdCreatives(lastUserText) : Promise.resolve([]),
|
|
61346
|
-
toolCtx.onListBrandTemplates ? toolCtx.onListBrandTemplates(
|
|
61339
|
+
toolCtx.onListBrandTemplates ? toolCtx.onListBrandTemplates(lastUserText) : Promise.resolve([])
|
|
61347
61340
|
]);
|
|
61348
61341
|
const top2Assets = (assetRes.status === "fulfilled" ? assetRes.value : []).filter(
|
|
61349
61342
|
(a) => a.previewDataUrl && isRasterImageDataUrl2(a.previewDataUrl)
|
|
@@ -61351,9 +61344,7 @@ ${elementContext}`
|
|
|
61351
61344
|
const top2Creatives = (creativeRes.status === "fulfilled" ? creativeRes.value : []).filter(
|
|
61352
61345
|
(c) => c.previewDataUrl && isRasterImageDataUrl2(c.previewDataUrl)
|
|
61353
61346
|
).slice(0, 2);
|
|
61354
|
-
const top2Templates = (templateRes.status === "fulfilled" ? templateRes.value : []).
|
|
61355
|
-
(t2) => t2.thumbnailDataUrl && isRasterImageDataUrl2(t2.thumbnailDataUrl)
|
|
61356
|
-
).slice(0, 2);
|
|
61347
|
+
const top2Templates = (templateRes.status === "fulfilled" ? templateRes.value : []).slice(0, 2);
|
|
61357
61348
|
console.log(
|
|
61358
61349
|
`[agent:pre-fetch] brand assets=${top2Assets.length}/${assetRes.status === "fulfilled" ? assetRes.value.length : "err"} ad-creatives=${top2Creatives.length}/${creativeRes.status === "fulfilled" ? creativeRes.value.length : "err"} templates=${top2Templates.length}/${templateRes.status === "fulfilled" ? templateRes.value.length : "err"}`
|
|
61359
61350
|
);
|
|
@@ -61365,12 +61356,19 @@ ${elementContext}`
|
|
|
61365
61356
|
...top2Creatives.map((c) => ({
|
|
61366
61357
|
label: `Ad Creative \u2014 ${c.name}`,
|
|
61367
61358
|
dataUrl: c.previewDataUrl
|
|
61368
|
-
})),
|
|
61369
|
-
...top2Templates.map((t2) => ({
|
|
61370
|
-
label: `Template \u2014 ${t2.name}`,
|
|
61371
|
-
dataUrl: t2.thumbnailDataUrl
|
|
61372
61359
|
}))
|
|
61373
61360
|
];
|
|
61361
|
+
if (top2Templates.length > 0) {
|
|
61362
|
+
messages.push({
|
|
61363
|
+
role: "system",
|
|
61364
|
+
content: `SEMANTIC TEMPLATE MATCHES (ranked; no template images attached):
|
|
61365
|
+
${top2Templates.map((t2) => {
|
|
61366
|
+
const dims = t2.width && t2.height ? `${t2.width}x${t2.height}` : "unknown dimensions";
|
|
61367
|
+
return `\u2022 ${t2.name} [id:${t2.id}, ${dims}] \u2014 ${t2.visualMetadata?.caption ?? "No caption"}. Layout: ${t2.visualMetadata?.layout ?? "unspecified"}. Best for: ${(t2.visualMetadata?.useCases ?? []).join(", ") || "unspecified"}.`;
|
|
61368
|
+
}).join("\n")}
|
|
61369
|
+
Use a matching template at its native dimensions. Do not attach its thumbnail or send it to an image model.`
|
|
61370
|
+
});
|
|
61371
|
+
}
|
|
61374
61372
|
const budgetedPreviews = [];
|
|
61375
61373
|
for (const p of previews) {
|
|
61376
61374
|
if (brandContextImagesUsed >= MAX_TOTAL_IMAGES) {
|
|
@@ -61726,8 +61724,7 @@ Use the frameId="${imageGenData.frameId}" for all elements. Keep all elements wi
|
|
|
61726
61724
|
const searchToolNames = /* @__PURE__ */ new Set([
|
|
61727
61725
|
"find_brand_asset",
|
|
61728
61726
|
"search_brand_assets",
|
|
61729
|
-
"search_ad_creatives"
|
|
61730
|
-
"list_brand_templates"
|
|
61727
|
+
"search_ad_creatives"
|
|
61731
61728
|
]);
|
|
61732
61729
|
const assetSearchResult = result;
|
|
61733
61730
|
if (searchToolNames.has(name) && result.success && assetSearchResult.previewDataUrls?.length) {
|