@orangecatai/element 0.0.3 → 0.0.4
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/index.js +28 -2
- package/dist/dev/index.js.map +2 -2
- package/dist/prod/index.js +9 -9
- package/dist/types/common/src/constants.d.ts +4 -0
- package/dist/types/element/src/Scene.d.ts +1 -1
- package/dist/types/element/src/frame.d.ts +2 -2
- package/dist/types/element/src/newElement.d.ts +10 -1
- package/dist/types/element/src/typeChecks.d.ts +2 -1
- package/dist/types/element/src/types.d.ts +17 -2
- package/dist/types/excalidraw/actions/actionFrame.d.ts +41 -0
- package/dist/types/excalidraw/actions/actionLinearEditor.d.ts +41 -0
- package/dist/types/excalidraw/components/AIChatPanel.d.ts +70 -8
- package/dist/types/excalidraw/components/App.d.ts +10 -0
- package/dist/types/excalidraw/components/ImageEditToolbar.d.ts +0 -1
- package/dist/types/excalidraw/components/ImageGeneratorPanel.d.ts +53 -12
- package/dist/types/excalidraw/components/StockImagePanel.d.ts +49 -0
- package/dist/types/excalidraw/components/VideoElement.d.ts +9 -0
- package/dist/types/excalidraw/components/VideoGeneratorPanel.d.ts +149 -0
- package/dist/types/excalidraw/components/ai-chat/AdGenShimmerLayer.d.ts +10 -0
- package/dist/types/excalidraw/components/ai-chat/adGenShimmerStore.d.ts +12 -0
- package/dist/types/excalidraw/components/ai-chat/agentLoop.d.ts +8 -6
- package/dist/types/excalidraw/components/ai-chat/audioUtils.d.ts +0 -5
- package/dist/types/excalidraw/components/ai-chat/canvasTools.d.ts +96 -29
- package/dist/types/excalidraw/components/ai-chat/reviewerAgent.d.ts +21 -11
- package/dist/types/excalidraw/components/auto-resize/AutoResizePanel.d.ts +2 -2
- package/dist/types/excalidraw/components/auto-resize/autoResizeEngine.d.ts +43 -2
- package/dist/types/excalidraw/components/icons.d.ts +2 -0
- package/dist/types/excalidraw/components/main-menu/DefaultItems.d.ts +4 -0
- package/dist/types/excalidraw/data/blob.d.ts +4 -1
- package/dist/types/excalidraw/index.d.ts +6 -2
- package/dist/types/excalidraw/scene/types.d.ts +1 -0
- package/dist/types/excalidraw/types.d.ts +83 -21
- package/dist/types/excalidraw/utils/brandContextUtils.d.ts +23 -0
- package/dist/types/excalidraw/utils/imageApi.d.ts +19 -0
- package/dist/types/excalidraw/utils/videoApi.d.ts +30 -0
- package/dist/types/utils/src/shape.d.ts +2 -2
- package/package.json +2 -2
- package/dist/types/excalidraw/utils/geminiApiKey.d.ts +0 -1
- package/dist/types/excalidraw/utils/leonardoApiKey.d.ts +0 -1
- package/dist/types/excalidraw/utils/openRouterApiKey.d.ts +0 -1
- package/dist/types/excalidraw/utils/removeBgApiKey.d.ts +0 -1
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import "./VideoGeneratorPanel.scss";
|
|
2
|
+
import type { ExcalidrawFrameLikeElement, NonDeletedExcalidrawElement } from "@orangecatai/element/types";
|
|
3
|
+
import type { AppClassProperties } from "../types";
|
|
4
|
+
declare const VIDEO_MODEL_CONFIG: {
|
|
5
|
+
readonly "veo 3.1 fast": {
|
|
6
|
+
readonly modelId: "google/veo-3.1-fast";
|
|
7
|
+
readonly supportsFirstFrame: true;
|
|
8
|
+
readonly supportsLastFrame: true;
|
|
9
|
+
readonly audioMode: "always-on";
|
|
10
|
+
readonly supportsDuration: true;
|
|
11
|
+
readonly durationMode: "choices";
|
|
12
|
+
readonly durationValues: readonly [4, 6, 8];
|
|
13
|
+
readonly supportsResolution: true;
|
|
14
|
+
readonly supportedResolutions: readonly ["720p", "1080p", "4K"];
|
|
15
|
+
readonly supportsNegativePrompt: false;
|
|
16
|
+
readonly supportedRatios: readonly ["16:9", "9:16"];
|
|
17
|
+
readonly frameInputMode: "dual-frame";
|
|
18
|
+
readonly supportsInputReferences: false;
|
|
19
|
+
readonly supportsSeed: true;
|
|
20
|
+
};
|
|
21
|
+
readonly "veo 3.1 lite": {
|
|
22
|
+
readonly modelId: "google/veo-3.1-lite";
|
|
23
|
+
readonly supportsFirstFrame: true;
|
|
24
|
+
readonly supportsLastFrame: true;
|
|
25
|
+
readonly audioMode: "always-on";
|
|
26
|
+
readonly supportsDuration: true;
|
|
27
|
+
readonly durationMode: "choices";
|
|
28
|
+
readonly durationValues: readonly [4, 6, 8];
|
|
29
|
+
readonly supportsResolution: true;
|
|
30
|
+
readonly supportedResolutions: readonly ["720p", "1080p"];
|
|
31
|
+
readonly supportsNegativePrompt: false;
|
|
32
|
+
readonly supportedRatios: readonly ["16:9", "9:16"];
|
|
33
|
+
readonly frameInputMode: "dual-frame";
|
|
34
|
+
readonly supportsInputReferences: false;
|
|
35
|
+
readonly supportsSeed: true;
|
|
36
|
+
};
|
|
37
|
+
readonly "kling v3 pro": {
|
|
38
|
+
readonly modelId: "kwaivgi/kling-v3.0-pro";
|
|
39
|
+
readonly supportsFirstFrame: true;
|
|
40
|
+
readonly supportsLastFrame: true;
|
|
41
|
+
readonly audioMode: "toggle";
|
|
42
|
+
readonly supportsDuration: true;
|
|
43
|
+
readonly durationMode: "slider";
|
|
44
|
+
readonly minDuration: 3;
|
|
45
|
+
readonly maxDuration: 15;
|
|
46
|
+
readonly supportsResolution: false;
|
|
47
|
+
readonly supportsNegativePrompt: true;
|
|
48
|
+
readonly supportedRatios: readonly ["16:9", "9:16", "1:1"];
|
|
49
|
+
readonly frameInputMode: "dual-frame";
|
|
50
|
+
readonly supportsInputReferences: false;
|
|
51
|
+
readonly supportsSeed: true;
|
|
52
|
+
};
|
|
53
|
+
readonly "kling v3 std": {
|
|
54
|
+
readonly modelId: "kwaivgi/kling-v3.0-std";
|
|
55
|
+
readonly supportsFirstFrame: true;
|
|
56
|
+
readonly supportsLastFrame: true;
|
|
57
|
+
readonly audioMode: "toggle";
|
|
58
|
+
readonly supportsDuration: true;
|
|
59
|
+
readonly durationMode: "slider";
|
|
60
|
+
readonly minDuration: 3;
|
|
61
|
+
readonly maxDuration: 15;
|
|
62
|
+
readonly supportsResolution: false;
|
|
63
|
+
readonly supportsNegativePrompt: true;
|
|
64
|
+
readonly supportedRatios: readonly ["16:9", "9:16", "1:1"];
|
|
65
|
+
readonly frameInputMode: "dual-frame";
|
|
66
|
+
readonly supportsInputReferences: false;
|
|
67
|
+
readonly supportsSeed: true;
|
|
68
|
+
};
|
|
69
|
+
readonly "seedance 2.0": {
|
|
70
|
+
readonly modelId: "bytedance/seedance-2.0";
|
|
71
|
+
readonly supportsFirstFrame: true;
|
|
72
|
+
readonly supportsLastFrame: true;
|
|
73
|
+
readonly audioMode: "always-on";
|
|
74
|
+
readonly supportsDuration: true;
|
|
75
|
+
readonly durationMode: "slider";
|
|
76
|
+
readonly minDuration: 4;
|
|
77
|
+
readonly maxDuration: 15;
|
|
78
|
+
readonly supportsResolution: true;
|
|
79
|
+
readonly supportedResolutions: readonly ["480p", "720p", "1080p", "4K"];
|
|
80
|
+
readonly supportsNegativePrompt: false;
|
|
81
|
+
readonly supportedRatios: readonly ["16:9", "9:16", "1:1", "4:3", "3:4", "21:9", "9:21"];
|
|
82
|
+
readonly frameInputMode: "dual-frame";
|
|
83
|
+
readonly supportsInputReferences: true;
|
|
84
|
+
readonly supportsSeed: true;
|
|
85
|
+
};
|
|
86
|
+
readonly "seedance 2.0 fast": {
|
|
87
|
+
readonly modelId: "bytedance/seedance-2.0-fast";
|
|
88
|
+
readonly supportsFirstFrame: true;
|
|
89
|
+
readonly supportsLastFrame: true;
|
|
90
|
+
readonly audioMode: "always-on";
|
|
91
|
+
readonly supportsDuration: true;
|
|
92
|
+
readonly durationMode: "slider";
|
|
93
|
+
readonly minDuration: 4;
|
|
94
|
+
readonly maxDuration: 15;
|
|
95
|
+
readonly supportsResolution: true;
|
|
96
|
+
readonly supportedResolutions: readonly ["480p", "720p"];
|
|
97
|
+
readonly supportsNegativePrompt: false;
|
|
98
|
+
readonly supportedRatios: readonly ["16:9", "9:16", "1:1", "4:3", "3:4", "21:9", "9:21"];
|
|
99
|
+
readonly frameInputMode: "dual-frame";
|
|
100
|
+
readonly supportsInputReferences: true;
|
|
101
|
+
readonly supportsSeed: true;
|
|
102
|
+
};
|
|
103
|
+
readonly "happyhorse 1.1": {
|
|
104
|
+
readonly modelId: "alibaba/happyhorse-1.1";
|
|
105
|
+
readonly supportsFirstFrame: true;
|
|
106
|
+
readonly supportsLastFrame: false;
|
|
107
|
+
readonly audioMode: "none";
|
|
108
|
+
readonly supportsDuration: true;
|
|
109
|
+
readonly durationMode: "slider";
|
|
110
|
+
readonly minDuration: 3;
|
|
111
|
+
readonly maxDuration: 15;
|
|
112
|
+
readonly supportsResolution: true;
|
|
113
|
+
readonly supportedResolutions: readonly ["720p", "1080p"];
|
|
114
|
+
readonly supportsNegativePrompt: false;
|
|
115
|
+
readonly supportedRatios: readonly ["16:9", "9:16", "1:1", "4:3", "3:4", "21:9", "9:21"];
|
|
116
|
+
readonly frameInputMode: "start-only";
|
|
117
|
+
readonly supportsInputReferences: false;
|
|
118
|
+
readonly supportsSeed: true;
|
|
119
|
+
};
|
|
120
|
+
readonly "grok video": {
|
|
121
|
+
readonly modelId: "x-ai/grok-imagine-video";
|
|
122
|
+
readonly supportsFirstFrame: true;
|
|
123
|
+
readonly supportsLastFrame: false;
|
|
124
|
+
readonly audioMode: "none";
|
|
125
|
+
readonly supportsDuration: true;
|
|
126
|
+
readonly durationMode: "slider";
|
|
127
|
+
readonly minDuration: 1;
|
|
128
|
+
readonly maxDuration: 15;
|
|
129
|
+
readonly supportsResolution: true;
|
|
130
|
+
readonly supportedResolutions: readonly ["480p", "720p"];
|
|
131
|
+
readonly supportsNegativePrompt: false;
|
|
132
|
+
readonly supportedRatios: readonly ["16:9", "9:16", "1:1", "4:3", "3:4", "3:2", "2:3"];
|
|
133
|
+
readonly frameInputMode: "start-only";
|
|
134
|
+
readonly supportsInputReferences: false;
|
|
135
|
+
readonly supportsSeed: true;
|
|
136
|
+
};
|
|
137
|
+
};
|
|
138
|
+
export type VideoModelName = keyof typeof VIDEO_MODEL_CONFIG;
|
|
139
|
+
export declare const VIDEO_MODEL_NAMES: VideoModelName[];
|
|
140
|
+
export declare const VideoGeneratorPanel: ({ element, app, onBeforeVideoGen, onAfterVideoGen, }: {
|
|
141
|
+
element: NonDeletedExcalidrawElement & ExcalidrawFrameLikeElement;
|
|
142
|
+
app: AppClassProperties;
|
|
143
|
+
onBeforeVideoGen?: () => Promise<{
|
|
144
|
+
allowed: boolean;
|
|
145
|
+
error?: string;
|
|
146
|
+
}>;
|
|
147
|
+
onAfterVideoGen?: () => void;
|
|
148
|
+
}) => import("react/jsx-runtime").JSX.Element | null;
|
|
149
|
+
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Renders a shimmer overlay on top of frames that are currently being
|
|
3
|
+
* generated by the AI chat agent (create_frame → generate_image → review).
|
|
4
|
+
*
|
|
5
|
+
* Rendered unconditionally from App.tsx alongside AutoResizeShimmerLayer.
|
|
6
|
+
* Uses useExcalidrawAppState() so it repositions correctly on scroll/zoom.
|
|
7
|
+
* Reads current frame position from scene elements so it follows the frame
|
|
8
|
+
* if the user drags it during generation.
|
|
9
|
+
*/
|
|
10
|
+
export declare const AdGenShimmerLayer: () => import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export type AdGenFrameInfo = {
|
|
2
|
+
frameId: string;
|
|
3
|
+
};
|
|
4
|
+
type Listener = () => void;
|
|
5
|
+
export declare const adGenShimmerStore: {
|
|
6
|
+
startGenerating(frameId: string): void;
|
|
7
|
+
stopGenerating(frameId: string): void;
|
|
8
|
+
clear(): void;
|
|
9
|
+
getLoadingFrames(): AdGenFrameInfo[];
|
|
10
|
+
subscribe(fn: Listener): () => void;
|
|
11
|
+
};
|
|
12
|
+
export {};
|
|
@@ -8,6 +8,12 @@ type ContentPart = {
|
|
|
8
8
|
image_url: {
|
|
9
9
|
url: string;
|
|
10
10
|
};
|
|
11
|
+
} | {
|
|
12
|
+
type: "file";
|
|
13
|
+
file: {
|
|
14
|
+
filename: string;
|
|
15
|
+
file_data: string;
|
|
16
|
+
};
|
|
11
17
|
};
|
|
12
18
|
export type AgentMessage = {
|
|
13
19
|
role: "system";
|
|
@@ -54,13 +60,9 @@ export type AgentResult = {
|
|
|
54
60
|
reply: string;
|
|
55
61
|
toolActions: ToolAction[];
|
|
56
62
|
};
|
|
57
|
-
/**
|
|
58
|
-
* Converts a BrandContext object to a concise system message string.
|
|
59
|
-
*/
|
|
60
|
-
export declare function buildBrandContextMessage(ctx: BrandContext): string;
|
|
61
63
|
export type FileAttachment = {
|
|
62
64
|
name: string;
|
|
63
|
-
type: "image" | "text";
|
|
65
|
+
type: "image" | "text" | "pdf" | "docx";
|
|
64
66
|
dataUrl?: string;
|
|
65
67
|
textContent?: string;
|
|
66
68
|
};
|
|
@@ -78,7 +80,7 @@ export declare function runAgentLoop(opts: {
|
|
|
78
80
|
frameScreenshot?: string;
|
|
79
81
|
fileAttachments?: FileAttachment[];
|
|
80
82
|
webSearchEnabled?: boolean;
|
|
81
|
-
|
|
83
|
+
chatUrl: string;
|
|
82
84
|
chatModel?: string;
|
|
83
85
|
agentImageModel?: string;
|
|
84
86
|
toolCtx: ToolExecutionContext;
|
|
@@ -3,8 +3,3 @@
|
|
|
3
3
|
* using the Web Audio API. Mistral Voxtral only accepts mp3 or wav.
|
|
4
4
|
*/
|
|
5
5
|
export declare function blobToWavBase64(blob: Blob): Promise<string>;
|
|
6
|
-
/**
|
|
7
|
-
* Sends a base64-encoded audio string to the OpenRouter Voxtral model for
|
|
8
|
-
* transcription. `format` must be "wav" or "mp3".
|
|
9
|
-
*/
|
|
10
|
-
export declare function transcribeAudio(base64Audio: string, format: string, apiKey: string, voiceModel?: string): Promise<string>;
|
|
@@ -297,7 +297,7 @@ export declare const BANNER_TOOLS: readonly [{
|
|
|
297
297
|
readonly type: "function";
|
|
298
298
|
readonly function: {
|
|
299
299
|
readonly name: "generate_image";
|
|
300
|
-
readonly description: "Generate
|
|
300
|
+
readonly description: "Generate the COMPLETE advertisement as a single AI image and place it into the frame. The image must contain BOTH the visuals AND all copy (headline, subheadline, CTA button, sign-off/brand name) rendered as legible text inside the image — this is the entire ad, not a text-free background. Fill the whole frame (x:0, y:0, width:frameW, height:frameH). Use referenceImageIndex when the user attached an image to use as a subject/style reference. Your prompt must spell on-image text exactly and specify brand colors, typographic style, composition, and dimensions. Do NOT call generate_html_banner afterwards — there is no separate text layer.";
|
|
301
301
|
readonly parameters: {
|
|
302
302
|
readonly type: "object";
|
|
303
303
|
readonly properties: {
|
|
@@ -307,7 +307,7 @@ export declare const BANNER_TOOLS: readonly [{
|
|
|
307
307
|
};
|
|
308
308
|
readonly prompt: {
|
|
309
309
|
readonly type: "string";
|
|
310
|
-
readonly description: "Detailed
|
|
310
|
+
readonly description: "Detailed prompt for the COMPLETE ad: the visual scene PLUS the exact on-image copy (quote headline/subheadline/CTA/sign-off verbatim), brand colors per element, typographic style described in words, composition/layout, and the target dimensions/aspect.";
|
|
311
311
|
};
|
|
312
312
|
readonly x: {
|
|
313
313
|
readonly type: "number";
|
|
@@ -334,27 +334,6 @@ export declare const BANNER_TOOLS: readonly [{
|
|
|
334
334
|
readonly additionalProperties: false;
|
|
335
335
|
};
|
|
336
336
|
};
|
|
337
|
-
}, {
|
|
338
|
-
readonly type: "function";
|
|
339
|
-
readonly function: {
|
|
340
|
-
readonly name: "generate_html_banner";
|
|
341
|
-
readonly description: "Place HTML/CSS text and shape elements into an EXISTING frame on the canvas. Always call create_frame first to get a frameId, then generate_image, then call this with that frameId. frameId is required — this tool does NOT create frames.";
|
|
342
|
-
readonly parameters: {
|
|
343
|
-
readonly type: "object";
|
|
344
|
-
readonly properties: {
|
|
345
|
-
readonly html: {
|
|
346
|
-
readonly type: "string";
|
|
347
|
-
readonly description: "Complete self-contained HTML with inline <style>. All layer elements must use position:absolute with explicit left/top/width/height in px. Root div must have class='canvas'.";
|
|
348
|
-
};
|
|
349
|
-
readonly frameId: {
|
|
350
|
-
readonly type: "string";
|
|
351
|
-
readonly description: "Required. The ID of the frame created by create_frame. Adds HTML elements into this existing frame, preserving existing children like images.";
|
|
352
|
-
};
|
|
353
|
-
};
|
|
354
|
-
readonly required: readonly ["html", "frameId"];
|
|
355
|
-
readonly additionalProperties: false;
|
|
356
|
-
};
|
|
357
|
-
};
|
|
358
337
|
}, {
|
|
359
338
|
readonly type: "function";
|
|
360
339
|
readonly function: {
|
|
@@ -436,6 +415,18 @@ export declare const BANNER_TOOLS: readonly [{
|
|
|
436
415
|
readonly additionalProperties: false;
|
|
437
416
|
};
|
|
438
417
|
};
|
|
418
|
+
}, {
|
|
419
|
+
readonly type: "function";
|
|
420
|
+
readonly function: {
|
|
421
|
+
readonly name: "list_frames";
|
|
422
|
+
readonly description: "List all frames currently on the canvas. Returns each frame's id, name, width, height, and child element count. Call this when you need to find a frameId and none was provided by the user.";
|
|
423
|
+
readonly parameters: {
|
|
424
|
+
readonly type: "object";
|
|
425
|
+
readonly properties: {};
|
|
426
|
+
readonly required: readonly [];
|
|
427
|
+
readonly additionalProperties: false;
|
|
428
|
+
};
|
|
429
|
+
};
|
|
439
430
|
}, {
|
|
440
431
|
readonly type: "function";
|
|
441
432
|
readonly function: {
|
|
@@ -458,6 +449,23 @@ export declare const BANNER_TOOLS: readonly [{
|
|
|
458
449
|
readonly additionalProperties: false;
|
|
459
450
|
};
|
|
460
451
|
};
|
|
452
|
+
}, {
|
|
453
|
+
readonly type: "function";
|
|
454
|
+
readonly function: {
|
|
455
|
+
readonly name: "search_ad_creatives";
|
|
456
|
+
readonly description: "Search uploaded ad creatives (past static ads) by name or tag keywords. Returns top 3 matches with visual previews. Use this to find reference ads for inspiration or remixing.";
|
|
457
|
+
readonly parameters: {
|
|
458
|
+
readonly type: "object";
|
|
459
|
+
readonly properties: {
|
|
460
|
+
readonly query: {
|
|
461
|
+
readonly type: "string";
|
|
462
|
+
readonly description: "Search query — name or tag keywords";
|
|
463
|
+
};
|
|
464
|
+
};
|
|
465
|
+
readonly required: readonly ["query"];
|
|
466
|
+
readonly additionalProperties: false;
|
|
467
|
+
};
|
|
468
|
+
};
|
|
461
469
|
}, {
|
|
462
470
|
readonly type: "function";
|
|
463
471
|
readonly function: {
|
|
@@ -580,17 +588,42 @@ export declare const BANNER_TOOLS: readonly [{
|
|
|
580
588
|
}, {
|
|
581
589
|
readonly type: "function";
|
|
582
590
|
readonly function: {
|
|
583
|
-
readonly name: "
|
|
584
|
-
readonly description: "
|
|
591
|
+
readonly name: "place_brand_asset";
|
|
592
|
+
readonly description: "Place a brand image asset or ad creative directly into a frame as an image element. Use after search_brand_assets or search_ad_creatives to insert the found asset. Maintains the asset's aspect ratio inside the frame.";
|
|
585
593
|
readonly parameters: {
|
|
586
594
|
readonly type: "object";
|
|
587
595
|
readonly properties: {
|
|
588
596
|
readonly frameId: {
|
|
589
597
|
readonly type: "string";
|
|
590
|
-
readonly description: "
|
|
598
|
+
readonly description: "The frame to place the asset in";
|
|
599
|
+
};
|
|
600
|
+
readonly assetId: {
|
|
601
|
+
readonly type: "string";
|
|
602
|
+
readonly description: "Asset ID from search_brand_assets or search_ad_creatives [id:...] field";
|
|
603
|
+
};
|
|
604
|
+
readonly assetType: {
|
|
605
|
+
readonly type: "string";
|
|
606
|
+
readonly enum: readonly ["image-asset", "ad-creative"];
|
|
607
|
+
readonly description: "Type of asset — defaults to image-asset";
|
|
608
|
+
};
|
|
609
|
+
readonly x: {
|
|
610
|
+
readonly type: "number";
|
|
611
|
+
readonly description: "X offset from frame left edge (optional, centers by default)";
|
|
612
|
+
};
|
|
613
|
+
readonly y: {
|
|
614
|
+
readonly type: "number";
|
|
615
|
+
readonly description: "Y offset from frame top edge (optional, centers by default)";
|
|
616
|
+
};
|
|
617
|
+
readonly width: {
|
|
618
|
+
readonly type: "number";
|
|
619
|
+
readonly description: "Width of placed image (optional, auto-fits to frame by default)";
|
|
620
|
+
};
|
|
621
|
+
readonly height: {
|
|
622
|
+
readonly type: "number";
|
|
623
|
+
readonly description: "Height of placed image (optional, auto-fits to frame by default)";
|
|
591
624
|
};
|
|
592
625
|
};
|
|
593
|
-
readonly required: readonly ["frameId"];
|
|
626
|
+
readonly required: readonly ["frameId", "assetId"];
|
|
594
627
|
readonly additionalProperties: false;
|
|
595
628
|
};
|
|
596
629
|
};
|
|
@@ -611,9 +644,10 @@ export declare function getFrameContext(api: ExcalidrawImperativeAPI, frameId: s
|
|
|
611
644
|
} | null;
|
|
612
645
|
export type ToolExecutionContext = {
|
|
613
646
|
excalidrawAPI: ExcalidrawImperativeAPI;
|
|
614
|
-
|
|
647
|
+
/** Host proxy URL for the agent's generate_image tool. Key stays server-side. */
|
|
648
|
+
imageGenUrl: string;
|
|
615
649
|
signal?: AbortSignal;
|
|
616
|
-
/** Override
|
|
650
|
+
/** Override OpenRouter model ID for the agent's generate_image tool. */
|
|
617
651
|
agentImageModel?: string;
|
|
618
652
|
/**
|
|
619
653
|
* Maps lowercase brand font-family names to their registered Excalidraw
|
|
@@ -628,6 +662,19 @@ export type ToolExecutionContext = {
|
|
|
628
662
|
brandHeadlineFontName?: string;
|
|
629
663
|
/** Brand body font file name. Sourced from brand DNA. */
|
|
630
664
|
brandBodyFontName?: string;
|
|
665
|
+
/** Data URL of the master brand logo — passed as a visual reference image to the image generation model. */
|
|
666
|
+
brandLogoDataUrl?: string;
|
|
667
|
+
/** Data URL of text rendered in the brand headline font — passed as a visual reference to the image generation model. */
|
|
668
|
+
brandFontPreviewDataUrl?: string;
|
|
669
|
+
/** Data URL of text rendered in the brand body font — passed as a second visual reference to the image generation model. */
|
|
670
|
+
brandBodyFontPreviewDataUrl?: string;
|
|
671
|
+
/**
|
|
672
|
+
* Fetchable URL of the actual headline font file (.ttf/.otf), e.g. a presigned
|
|
673
|
+
* S3 URL. Only consumed by image models that accept a font file as input
|
|
674
|
+
* (Sourceful Riverflow v2+ -> OpenRouter `image_config.font_inputs`). Other
|
|
675
|
+
* models ignore it.
|
|
676
|
+
*/
|
|
677
|
+
brandFontUrl?: string;
|
|
631
678
|
/**
|
|
632
679
|
* Excalidraw fontFamilyId for the brand headline font.
|
|
633
680
|
* When set, ALL text elements (add_text, fill_template_slots headline slots)
|
|
@@ -655,6 +702,15 @@ export type ToolExecutionContext = {
|
|
|
655
702
|
tags: string[];
|
|
656
703
|
assetType: string;
|
|
657
704
|
blobUrl: string;
|
|
705
|
+
previewDataUrl?: string;
|
|
706
|
+
}>>;
|
|
707
|
+
onSearchAdCreatives?: (query: string) => Promise<Array<{
|
|
708
|
+
id: string;
|
|
709
|
+
name: string;
|
|
710
|
+
tags: string[];
|
|
711
|
+
mimeType: string;
|
|
712
|
+
blobUrl: string;
|
|
713
|
+
previewDataUrl?: string;
|
|
658
714
|
}>>;
|
|
659
715
|
onListBrandTemplates?: (keywords?: string[]) => Promise<Array<{
|
|
660
716
|
id: string;
|
|
@@ -664,10 +720,21 @@ export type ToolExecutionContext = {
|
|
|
664
720
|
width?: number;
|
|
665
721
|
height?: number;
|
|
666
722
|
thumbnailBlobUrl?: string;
|
|
723
|
+
thumbnailDataUrl?: string;
|
|
667
724
|
}>>;
|
|
668
725
|
onGetTemplateVariant?: (variantId: string) => Promise<{
|
|
669
726
|
canvasJson: string;
|
|
670
727
|
}>;
|
|
728
|
+
onFindBrandAssets?: (type: "image-asset" | "ad-creative" | "template", keywords: string[]) => Promise<{
|
|
729
|
+
results: Array<{
|
|
730
|
+
id: string;
|
|
731
|
+
name: string;
|
|
732
|
+
tags?: string[];
|
|
733
|
+
width?: number | null;
|
|
734
|
+
height?: number | null;
|
|
735
|
+
previewDataUrl: string;
|
|
736
|
+
}>;
|
|
737
|
+
}>;
|
|
671
738
|
/**
|
|
672
739
|
* Internal cache: populated by execGetTemplateVariant so that
|
|
673
740
|
* execLoadTemplateIntoFrame can reuse the already-fetched JSON without a
|
|
@@ -1,19 +1,28 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* reviewerAgent.ts
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
4
|
+
* Brand Governance Agent — stateless reviewer that runs after the main agent
|
|
5
|
+
* generates a complete ad image (visuals + all copy baked in) and calls
|
|
6
|
+
* finalize_ad. It receives a focused context (the rendered screenshot, frame
|
|
7
|
+
* dimensions, brand guidelines, original user brief) and returns a precise
|
|
8
|
+
* critique covering creative quality AND brand-governance compliance:
|
|
9
|
+
* copy correctness, brand tone, logo usage, claim accuracy, legal mandatories,
|
|
10
|
+
* offer disclaimers, regulatory sensitivity, prohibited language, competitive
|
|
11
|
+
* claims, and data/privacy concerns.
|
|
9
12
|
*
|
|
10
|
-
* The reviewer is a separate LLM call from the main agent loop so it
|
|
11
|
-
*
|
|
13
|
+
* The reviewer is a separate LLM call from the main agent loop so it brings an
|
|
14
|
+
* independent eye to the generated ad. Because the ad is a single image, every
|
|
15
|
+
* fix is applied by regenerating the image with a revised prompt — there is no
|
|
16
|
+
* HTML/CSS layer to patch.
|
|
17
|
+
*
|
|
18
|
+
* @deprecated note (2026-06-17): this reviewer previously audited an HTML text
|
|
19
|
+
* layer composited over a text-free image and emitted CSS-only fixes. That
|
|
20
|
+
* flow is gone — see the image-first agent loop in agentLoop.ts.
|
|
12
21
|
*/
|
|
13
22
|
import type { BrandContext } from "../../types";
|
|
14
23
|
export type ReviewIssue = {
|
|
15
|
-
/** Which design element is affected */
|
|
16
|
-
element: "headline" | "subheadline" | "cta" | "image" | "layout" | "brand";
|
|
24
|
+
/** Which design element or governance dimension is affected */
|
|
25
|
+
element: "headline" | "subheadline" | "cta" | "image" | "layout" | "brand" | "brand_tone" | "logo" | "claim" | "legal" | "disclaimer" | "regulatory" | "prohibited_language" | "competitive_claim" | "privacy";
|
|
17
26
|
/** How bad it is */
|
|
18
27
|
severity: "critical" | "major" | "minor";
|
|
19
28
|
/** What is wrong — one sentence */
|
|
@@ -56,8 +65,9 @@ export declare function runReviewerAgent(opts: {
|
|
|
56
65
|
/** Original user request — first message only, not full conversation history */
|
|
57
66
|
userBrief: string;
|
|
58
67
|
brandContext?: BrandContext;
|
|
59
|
-
|
|
60
|
-
|
|
68
|
+
/** Host proxy URL for the reviewer's OpenRouter call. Key stays server-side. */
|
|
69
|
+
chatUrl: string;
|
|
70
|
+
/** OpenRouter model tag. Must be vision-capable. Defaults to minimax/minimax-m3 */
|
|
61
71
|
reviewerModel?: string;
|
|
62
72
|
signal?: AbortSignal;
|
|
63
73
|
iteration: number;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import "./AutoResizePanel.scss";
|
|
2
2
|
import type { ExcalidrawFrameLikeElement, NonDeletedExcalidrawElement } from "@orangecatai/element/types";
|
|
3
3
|
import type { AppClassProperties } from "../../types";
|
|
4
|
-
export declare const AutoResizePanel: ({ element, app, onClose, onBeforeAutoResize, onAfterAutoResize, onRunningChange,
|
|
4
|
+
export declare const AutoResizePanel: ({ element, app, onClose, onBeforeAutoResize, onAfterAutoResize, onRunningChange, autoResizeUrl, chatModel, agentImageModel, }: {
|
|
5
5
|
element: NonDeletedExcalidrawElement & ExcalidrawFrameLikeElement;
|
|
6
6
|
app: AppClassProperties;
|
|
7
7
|
onClose: () => void;
|
|
@@ -11,7 +11,7 @@ export declare const AutoResizePanel: ({ element, app, onClose, onBeforeAutoResi
|
|
|
11
11
|
}>;
|
|
12
12
|
onAfterAutoResize?: () => void;
|
|
13
13
|
onRunningChange?: (running: boolean) => void;
|
|
14
|
-
|
|
14
|
+
autoResizeUrl: string;
|
|
15
15
|
chatModel: string;
|
|
16
16
|
agentImageModel?: string;
|
|
17
17
|
}) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -69,6 +69,37 @@ export declare function extractFrameInfo(elements: readonly ExcalidrawElement[],
|
|
|
69
69
|
export declare function computeCropLoss(sourceAR: number, targetAR: number): number;
|
|
70
70
|
export declare function needsBackgroundRegeneration(srcW: number, srcH: number, tgtW: number, tgtH: number): boolean;
|
|
71
71
|
export declare function nearestGeminiAspectRatio(w: number, h: number): string;
|
|
72
|
+
/**
|
|
73
|
+
* Resolution dimensions available for each aspect ratio in Gemini 3.1 Flash
|
|
74
|
+
* Image (Nano Banana 2). Maps aspect ratio → resolution level → [width, height].
|
|
75
|
+
* Exported so the Auto Resize panel can build its dimension presets from the
|
|
76
|
+
* exact model-supported sizes instead of duplicating the numbers.
|
|
77
|
+
*/
|
|
78
|
+
export declare const GEMINI_RESOLUTION_TABLE: Record<string, Record<string, [number, number]>>;
|
|
79
|
+
/**
|
|
80
|
+
* Resolution levels offered by the Auto Resize panel.
|
|
81
|
+
* Nano Banana (gemini-2.5-flash-image) and Nano Banana 2 (gemini-3.1-flash-image-preview)
|
|
82
|
+
* both support 0.5K–4K. 0.5K is the fastest/cheapest tier.
|
|
83
|
+
*/
|
|
84
|
+
export declare const AUTO_RESIZE_RESOLUTIONS: readonly ["0.5K", "1K", "2K", "4K"];
|
|
85
|
+
export type AutoResizeResolution = typeof AUTO_RESIZE_RESOLUTIONS[number];
|
|
86
|
+
/**
|
|
87
|
+
* Aspect ratios the Nano Banana 2 / Gemini 3.1 Flash Image model supports,
|
|
88
|
+
* ordered for display (common first, then the ultrawide / extreme-narrow ones).
|
|
89
|
+
* Each carries a human label for the panel.
|
|
90
|
+
*/
|
|
91
|
+
export declare const AUTO_RESIZE_ASPECT_RATIOS: {
|
|
92
|
+
ratio: string;
|
|
93
|
+
desc: string;
|
|
94
|
+
}[];
|
|
95
|
+
/**
|
|
96
|
+
* Concrete pixel dimensions for a given aspect ratio + resolution, straight from
|
|
97
|
+
* the Nano Banana 2 resolution table. Falls back to 1:1 / 1K if unknown.
|
|
98
|
+
*/
|
|
99
|
+
export declare function geminiDimsFor(ratio: string, resolution: string): {
|
|
100
|
+
width: number;
|
|
101
|
+
height: number;
|
|
102
|
+
};
|
|
72
103
|
/**
|
|
73
104
|
* Selects the optimal resolution for a given target dimension and aspect ratio.
|
|
74
105
|
* Chooses the resolution level that is closest to (but preferably >= ) the target size.
|
|
@@ -126,8 +157,7 @@ export declare function runAutoResize(opts: {
|
|
|
126
157
|
sourceFrameId: string;
|
|
127
158
|
targetDimensions: TargetDimension[];
|
|
128
159
|
app: AppClassProperties;
|
|
129
|
-
|
|
130
|
-
openRouterApiKey: string;
|
|
160
|
+
autoResizeUrl: string;
|
|
131
161
|
chatModel?: string;
|
|
132
162
|
agentImageModel?: string;
|
|
133
163
|
customFontMap?: Record<string, number>;
|
|
@@ -140,5 +170,16 @@ export declare function runAutoResize(opts: {
|
|
|
140
170
|
signal?: AbortSignal;
|
|
141
171
|
/** Pass the result of preCreateAllFrames() to skip redundant frame creation */
|
|
142
172
|
preCreatedFrameInfos?: PreCreatedFrameInfo[];
|
|
173
|
+
/**
|
|
174
|
+
* Brand assets handed to the image model so the recomposed ad keeps the brand
|
|
175
|
+
* logo, typeface, and (for font-aware models) the real font file. Sourced from
|
|
176
|
+
* `app.state.brandContext` by the panel.
|
|
177
|
+
*/
|
|
178
|
+
brandImages?: {
|
|
179
|
+
logo?: string;
|
|
180
|
+
fontPreview?: string;
|
|
181
|
+
fontUrl?: string;
|
|
182
|
+
name?: string;
|
|
183
|
+
};
|
|
143
184
|
}): Promise<DimensionResult[]>;
|
|
144
185
|
export {};
|
|
@@ -33,6 +33,7 @@ export declare const FreedrawIcon: import("react/jsx-runtime").JSX.Element;
|
|
|
33
33
|
export declare const TextIcon: import("react/jsx-runtime").JSX.Element;
|
|
34
34
|
export declare const TextSizeIcon: import("react/jsx-runtime").JSX.Element;
|
|
35
35
|
export declare const ImageIcon: import("react/jsx-runtime").JSX.Element;
|
|
36
|
+
export declare const VideoIcon: import("react/jsx-runtime").JSX.Element;
|
|
36
37
|
export declare const EraserIcon: import("react/jsx-runtime").JSX.Element;
|
|
37
38
|
export declare const ZoomInIcon: import("react/jsx-runtime").JSX.Element;
|
|
38
39
|
export declare const ZoomOutIcon: import("react/jsx-runtime").JSX.Element;
|
|
@@ -189,6 +190,7 @@ export declare const eyeDropperIcon: import("react/jsx-runtime").JSX.Element;
|
|
|
189
190
|
export declare const extraToolsIcon: import("react/jsx-runtime").JSX.Element;
|
|
190
191
|
export declare const frameToolIcon: import("react/jsx-runtime").JSX.Element;
|
|
191
192
|
export declare const imageGeneratorToolIcon: import("react/jsx-runtime").JSX.Element;
|
|
193
|
+
export declare const videoGeneratorToolIcon: import("react/jsx-runtime").JSX.Element;
|
|
192
194
|
export declare const mermaidLogoIcon: import("react/jsx-runtime").JSX.Element;
|
|
193
195
|
export declare const RetryIcon: import("react/jsx-runtime").JSX.Element;
|
|
194
196
|
export declare const stackPushIcon: import("react/jsx-runtime").JSX.Element;
|
|
@@ -12,6 +12,10 @@ export declare const SaveAsImage: {
|
|
|
12
12
|
(): import("react/jsx-runtime").JSX.Element;
|
|
13
13
|
displayName: string;
|
|
14
14
|
};
|
|
15
|
+
export declare const UploadVideo: {
|
|
16
|
+
(): import("react/jsx-runtime").JSX.Element;
|
|
17
|
+
displayName: string;
|
|
18
|
+
};
|
|
15
19
|
export declare const CommandPalette: {
|
|
16
20
|
(opts?: {
|
|
17
21
|
className?: string;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { IMAGE_MIME_TYPES, MIME_TYPES } from "@orangecatai/common";
|
|
1
|
+
import { IMAGE_MIME_TYPES, VIDEO_MIME_TYPES, MIME_TYPES } from "@orangecatai/common";
|
|
2
2
|
import type { ExcalidrawElement, FileId } from "@orangecatai/element/types";
|
|
3
3
|
import type { ValueOf } from "@orangecatai/common/utility-types";
|
|
4
4
|
import type { AppState, DataURL, LibraryItem } from "../types";
|
|
@@ -12,6 +12,9 @@ export declare const isSupportedImageFileType: (type: string | null | undefined)
|
|
|
12
12
|
export declare const isSupportedImageFile: (blob: Blob | null | undefined) => blob is Blob & {
|
|
13
13
|
type: ValueOf<typeof IMAGE_MIME_TYPES>;
|
|
14
14
|
};
|
|
15
|
+
export declare const isSupportedVideoFile: (blob: Blob | null | undefined) => blob is Blob & {
|
|
16
|
+
type: ValueOf<typeof VIDEO_MIME_TYPES>;
|
|
17
|
+
};
|
|
15
18
|
export declare const loadSceneOrLibraryFromBlob: (blob: Blob | File,
|
|
16
19
|
/** @see restore.localAppState */
|
|
17
20
|
localAppState: AppState | null, localElements: readonly ExcalidrawElement[] | null,
|
|
@@ -8,16 +8,20 @@ import "./css/styles.scss";
|
|
|
8
8
|
import "./fonts/fonts.css";
|
|
9
9
|
import "./css/tailwind.generated.css";
|
|
10
10
|
import type { ExcalidrawProps } from "./types";
|
|
11
|
+
export { StockImagePanel } from "./components/StockImagePanel";
|
|
12
|
+
export type { StockImagePanelProps, StockImagePhoto, StockImageSearchResult, LibraryImage, LibraryImageResult, LibraryImageFilter, } from "./components/StockImagePanel";
|
|
11
13
|
export declare const Excalidraw: React.MemoExoticComponent<(props: ExcalidrawProps) => import("react/jsx-runtime").JSX.Element>;
|
|
12
14
|
export { getSceneVersion, hashElementsVersion, hashString, getNonDeletedElements, } from "@orangecatai/element";
|
|
13
15
|
export { getTextFromElements } from "@orangecatai/element";
|
|
14
16
|
export { isInvisiblySmallElement } from "@orangecatai/element";
|
|
17
|
+
export { newImageElement, newVideoElement, newTextElement, newFrameElement, } from "@orangecatai/element";
|
|
18
|
+
export { isVideoElement } from "@orangecatai/element";
|
|
15
19
|
export { defaultLang, useI18n, languages } from "./i18n";
|
|
16
20
|
export { restoreAppState, restoreElement, restoreElements, restoreLibraryItems, } from "./data/restore";
|
|
17
21
|
export { reconcileElements } from "./data/reconcile";
|
|
18
22
|
export { exportToCanvas, exportToBlob, exportToSvg, exportToClipboard, } from "@orangecatai/utils/export";
|
|
19
23
|
export { serializeAsJSON, serializeLibraryAsJSON } from "./data/json";
|
|
20
|
-
export { loadFromBlob, loadSceneOrLibraryFromBlob, loadLibraryFromBlob, } from "./data/blob";
|
|
24
|
+
export { loadFromBlob, loadSceneOrLibraryFromBlob, loadLibraryFromBlob, isSupportedVideoFile, } from "./data/blob";
|
|
21
25
|
export { mergeLibraryItems, getLibraryItemsHash } from "./data/library";
|
|
22
26
|
export { isLinearElement } from "@orangecatai/element";
|
|
23
27
|
export { FONT_FAMILY, THEME, MIME_TYPES, ROUNDNESS, DEFAULT_LASER_COLOR, UserIdleState, normalizeLink, sceneCoordsToViewportCoords, viewportCoordsToSceneCoords, getFormFactor, } from "@orangecatai/common";
|
|
@@ -50,7 +54,7 @@ export { AIChatPanel } from "./components/AIChatPanel";
|
|
|
50
54
|
export type { AIChatPanelProps, AIChatPanelRef, ChatMessage, ChatSession, } from "./components/AIChatPanel";
|
|
51
55
|
export type { ExcalidrawImperativeAPI } from "./types";
|
|
52
56
|
export type { AppState, BinaryFiles, BinaryFileData, ExcalidrawProps, ExcalidrawInitialDataState, LibraryItem, LibraryItems, SceneData, UnsubscribeCallback, } from "./types";
|
|
53
|
-
export type { ExcalidrawElement, NonDeletedExcalidrawElement, NonDeleted, OrderedExcalidrawElement, ExcalidrawElementType, } from "@orangecatai/element/types";
|
|
57
|
+
export type { ExcalidrawElement, NonDeletedExcalidrawElement, NonDeleted, OrderedExcalidrawElement, ExcalidrawElementType, ExcalidrawVideoElement, } from "@orangecatai/element/types";
|
|
54
58
|
export type { ImageEditToolbarCallbacks } from "./components/ImageEditToolbar";
|
|
55
59
|
export type { CustomFontSpec, BrandContext } from "./types";
|
|
56
60
|
export type { ReviewerFeedback, ReviewIssue, } from "./components/ai-chat/reviewerAgent";
|