@orangecatai/adgen-canvas 0.0.39 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. package/dist/dev/chunk-2K6ZAAHB.js +1535 -0
  2. package/dist/dev/chunk-2K6ZAAHB.js.map +7 -0
  3. package/dist/dev/{chunk-E7VZGEUJ.js → chunk-2Q5Z4UTF.js} +2 -2
  4. package/dist/dev/{chunk-E7VZGEUJ.js.map → chunk-2Q5Z4UTF.js.map} +1 -1
  5. package/dist/dev/{chunk-LIELFD5T.js → chunk-3WIRZ6S7.js} +6 -1
  6. package/dist/dev/chunk-3WIRZ6S7.js.map +7 -0
  7. package/dist/dev/{chunk-5XP2WJAQ.js → chunk-7XZBXIDZ.js} +1300 -1252
  8. package/dist/dev/chunk-7XZBXIDZ.js.map +7 -0
  9. package/dist/dev/chunk-AKA4GZ3R.js +62 -0
  10. package/dist/dev/chunk-AKA4GZ3R.js.map +7 -0
  11. package/dist/dev/chunk-LWUV2KR2.js +27 -0
  12. package/dist/dev/chunk-LWUV2KR2.js.map +7 -0
  13. package/dist/dev/chunk-T57LHRZV.js +2167 -0
  14. package/dist/dev/chunk-T57LHRZV.js.map +7 -0
  15. package/dist/dev/components/auto-resize/nativeResizeAgent-5XWJJ74W.js +1074 -0
  16. package/dist/dev/components/auto-resize/nativeResizeAgent-5XWJJ74W.js.map +7 -0
  17. package/dist/dev/data/{image-PUPXCX7M.js → image-MTDE3WXB.js} +4 -3
  18. package/dist/dev/index.css +618 -27
  19. package/dist/dev/index.css.map +3 -3
  20. package/dist/dev/index.js +6769 -8217
  21. package/dist/dev/index.js.map +4 -4
  22. package/dist/dev/locales/{en-VCZQBJ2N.js → en-3S2H3QGO.js} +2 -2
  23. package/dist/dev/model-capabilities.js +47 -0
  24. package/dist/dev/model-capabilities.js.map +7 -0
  25. package/dist/dev/subset-shared.chunk.js +1 -1
  26. package/dist/dev/subset-worker.chunk.js +1 -1
  27. package/dist/prod/chunk-6YYSQB5E.js +1 -0
  28. package/dist/prod/{chunk-CLQPYXMS.js → chunk-PIM2DC2L.js} +3 -3
  29. package/dist/prod/chunk-POCDVKZK.js +142 -0
  30. package/dist/prod/chunk-PWBUVPCU.js +1 -0
  31. package/dist/prod/{chunk-WBFDC4WN.js → chunk-R4DNAEVN.js} +1 -1
  32. package/dist/prod/chunk-U2I2OXQ7.js +4 -0
  33. package/dist/prod/chunk-UR7GPHHO.js +1 -0
  34. package/dist/prod/components/auto-resize/nativeResizeAgent-45UNA3LO.js +5 -0
  35. package/dist/prod/data/image-U4RMOYQQ.js +1 -0
  36. package/dist/prod/index.css +1 -1
  37. package/dist/prod/index.js +67 -298
  38. package/dist/prod/locales/{en-ZZURI326.js → en-Z3CKUL4S.js} +1 -1
  39. package/dist/prod/model-capabilities.js +1 -0
  40. package/dist/prod/subset-shared.chunk.js +1 -1
  41. package/dist/prod/subset-worker.chunk.js +1 -1
  42. package/dist/types/common/src/utils.d.ts +4 -1
  43. package/dist/types/element/src/index.d.ts +3 -0
  44. package/dist/types/element/src/newElement.d.ts +2 -1
  45. package/dist/types/element/src/textHtml.d.ts +14 -0
  46. package/dist/types/element/src/textLayout.d.ts +97 -0
  47. package/dist/types/element/src/textStyleRanges.d.ts +62 -0
  48. package/dist/types/element/src/textWrapping.d.ts +27 -0
  49. package/dist/types/element/src/types.d.ts +35 -0
  50. package/dist/types/excalidraw/actions/actionFrame.d.ts +1 -0
  51. package/dist/types/excalidraw/actions/actionLinearEditor.d.ts +1 -0
  52. package/dist/types/excalidraw/actions/actionProperties.d.ts +50 -0
  53. package/dist/types/excalidraw/actions/index.d.ts +1 -1
  54. package/dist/types/excalidraw/actions/types.d.ts +1 -1
  55. package/dist/types/excalidraw/components/AIChatPanel.d.ts +18 -2
  56. package/dist/types/excalidraw/components/App.d.ts +6 -0
  57. package/dist/types/excalidraw/components/FontSizeInput.d.ts +19 -0
  58. package/dist/types/excalidraw/components/ImageGeneratorPanel.d.ts +946 -45
  59. package/dist/types/excalidraw/components/VideoGeneratorPanel.d.ts +67 -53
  60. package/dist/types/excalidraw/components/ai-chat/ActivityTimeline.d.ts +18 -0
  61. package/dist/types/excalidraw/components/ai-chat/activitySteps.d.ts +106 -0
  62. package/dist/types/excalidraw/components/ai-chat/agentLoop.d.ts +66 -3
  63. package/dist/types/excalidraw/components/ai-chat/canvasTools.d.ts +23 -8
  64. package/dist/types/excalidraw/components/ai-chat/htmlToExcalidraw.d.ts +3 -0
  65. package/dist/types/excalidraw/components/ai-chat/openRouterStream.d.ts +13 -0
  66. package/dist/types/excalidraw/components/auto-resize/ResizeActivityCard.d.ts +7 -0
  67. package/dist/types/excalidraw/components/auto-resize/autoResizeEngine.d.ts +5 -2
  68. package/dist/types/excalidraw/components/auto-resize/autoResizeStore.d.ts +23 -0
  69. package/dist/types/excalidraw/components/auto-resize/imageBounds.d.ts +11 -0
  70. package/dist/types/excalidraw/components/auto-resize/nativeResizeAgent.d.ts +5 -0
  71. package/dist/types/excalidraw/components/auto-resize/resizeFitting.d.ts +7 -0
  72. package/dist/types/excalidraw/components/auto-resize/resizeLayout.d.ts +33 -0
  73. package/dist/types/excalidraw/components/icons.d.ts +6 -0
  74. package/dist/types/excalidraw/components/template-builder/TemplateBuilderTray.d.ts +1 -0
  75. package/dist/types/excalidraw/index.d.ts +9 -0
  76. package/dist/types/excalidraw/modelCapabilities/index.d.ts +17 -0
  77. package/dist/types/excalidraw/modelCapabilities/registry.image.d.ts +2 -0
  78. package/dist/types/excalidraw/modelCapabilities/registry.video.d.ts +2 -0
  79. package/dist/types/excalidraw/modelCapabilities/shared.d.ts +24 -0
  80. package/dist/types/excalidraw/modelCapabilities/types.d.ts +276 -0
  81. package/dist/types/excalidraw/modelCapabilities/validate.d.ts +48 -0
  82. package/dist/types/excalidraw/types.d.ts +4 -4
  83. package/dist/types/excalidraw/utils/imageApi.d.ts +3 -0
  84. package/dist/types/excalidraw/utils/referenceBudget.d.ts +12 -23
  85. package/dist/types/excalidraw/utils/videoApi.d.ts +21 -1
  86. package/dist/types/excalidraw/wysiwyg/richTextEditable.d.ts +36 -0
  87. package/dist/types/excalidraw/wysiwyg/textSelectionStyles.d.ts +32 -0
  88. package/dist/types/excalidraw/wysiwyg/textWysiwyg.d.ts +6 -2
  89. package/package.json +10 -4
  90. package/dist/dev/chunk-5XP2WJAQ.js.map +0 -7
  91. package/dist/dev/chunk-LIELFD5T.js.map +0 -7
  92. package/dist/prod/chunk-T3ZLBHX4.js +0 -4
  93. package/dist/prod/data/image-AG3CTRSJ.js +0 -1
  94. /package/dist/dev/data/{image-PUPXCX7M.js.map → image-MTDE3WXB.js.map} +0 -0
  95. /package/dist/dev/locales/{en-VCZQBJ2N.js.map → en-3S2H3QGO.js.map} +0 -0
@@ -0,0 +1,33 @@
1
+ import type { ImageBounds } from "./imageBounds";
2
+ import type { ExcalidrawElement } from "@orangecatai/element/types";
3
+ export declare const RESIZE_MODEL = "x-ai/grok-4.6";
4
+ export declare const MAX_RESIZE_RETRIES = 2;
5
+ export declare class LayoutContractError extends Error {
6
+ }
7
+ export type LayerMetadata = {
8
+ id: string;
9
+ role: "background" | "headline" | "body" | "legal" | "logo" | "product" | "cta" | "decoration";
10
+ label: string;
11
+ relatedTo: string[];
12
+ };
13
+ export type LayoutPatch = {
14
+ id: string;
15
+ x?: number;
16
+ y?: number;
17
+ width?: number;
18
+ height?: number;
19
+ fontSize?: number;
20
+ };
21
+ export declare function parseMetadata(value: unknown, layers: readonly ExcalidrawElement[]): LayerMetadata[];
22
+ export declare function parsePatches(value: unknown, layers: readonly ExcalidrawElement[]): LayoutPatch[];
23
+ export declare function applyPatches(layers: readonly ExcalidrawElement[], patches: LayoutPatch[]): ExcalidrawElement[];
24
+ export declare function reuseLayout(layers: readonly ExcalidrawElement[], sourceW: number, sourceH: number, targetW: number, targetH: number): ExcalidrawElement[] | null;
25
+ export declare function scaleLayout(layers: readonly ExcalidrawElement[], sourceW: number, sourceH: number, targetW: number, targetH: number): ExcalidrawElement[];
26
+ export declare function validateLayout(layers: readonly ExcalidrawElement[], metadata: LayerMetadata[], width: number, height: number, imageBounds?: Record<string, ImageBounds>): string[];
27
+ /** One initial candidate plus at most two repairs. Every returned candidate is verified. */
28
+ export declare function runVerifiedLayout<T>(opts: {
29
+ initial: T;
30
+ propose: (previous: T, issues: string[], attempt: number) => Promise<T>;
31
+ inspect: (candidate: T, attempt: number) => Promise<string[]>;
32
+ signal?: AbortSignal;
33
+ }): Promise<T>;
@@ -10,6 +10,7 @@ export declare const createIcon: (d: string | React.ReactNode, opts?: number | O
10
10
  export declare const PlusPromoIcon: import("react/jsx-runtime").JSX.Element;
11
11
  export declare const LibraryIcon: import("react/jsx-runtime").JSX.Element;
12
12
  export declare const PlusIcon: import("react/jsx-runtime").JSX.Element;
13
+ export declare const MinusIcon: import("react/jsx-runtime").JSX.Element;
13
14
  export declare const DotsIcon: import("react/jsx-runtime").JSX.Element;
14
15
  export declare const DotsHorizontalIcon: import("react/jsx-runtime").JSX.Element;
15
16
  export declare const PinIcon: import("react/jsx-runtime").JSX.Element;
@@ -107,6 +108,11 @@ export declare const FillSolidIcon: import("react/jsx-runtime").JSX.Element;
107
108
  export declare const StrokeWidthBaseIcon: import("react/jsx-runtime").JSX.Element;
108
109
  export declare const StrokeWidthBoldIcon: import("react/jsx-runtime").JSX.Element;
109
110
  export declare const StrokeWidthExtraBoldIcon: import("react/jsx-runtime").JSX.Element;
111
+ export declare const TextBoldIcon: import("react/jsx-runtime").JSX.Element;
112
+ export declare const TextItalicIcon: import("react/jsx-runtime").JSX.Element;
113
+ export declare const TextUnderlineIcon: import("react/jsx-runtime").JSX.Element;
114
+ export declare const TextStrikethroughIcon: import("react/jsx-runtime").JSX.Element;
115
+ export declare const TextHighlightIcon: import("react/jsx-runtime").JSX.Element;
110
116
  export declare const StrokeStyleSolidIcon: React.MemoExoticComponent<({ theme }: {
111
117
  theme: Theme;
112
118
  }) => import("react/jsx-runtime").JSX.Element>;
@@ -439,6 +439,7 @@ export declare const getTemplateBuilderFrame: (elements: readonly SceneElement[]
439
439
  lineHeight: number & {
440
440
  _brand: "unitlessLineHeight";
441
441
  };
442
+ styleRanges?: readonly import("@orangecatai/element/types").TextStyleRange[];
442
443
  }> & {
443
444
  index: import("@orangecatai/element/types").FractionalIndex;
444
445
  }) | (Readonly<{
@@ -49,13 +49,22 @@ export { DiagramToCodePlugin } from "./components/DiagramToCodePlugin/DiagramToC
49
49
  export { getDataURL } from "./data/blob";
50
50
  export { isElementLink } from "@orangecatai/element";
51
51
  export { setCustomTextMetricsProvider } from "@orangecatai/element";
52
+ export type { TextRunStyle, TextStyleRange } from "@orangecatai/element/types";
53
+ export { applyStyleToRange, getCommonStyleInRange, getStyleAtOffset, normalizeStyleRanges, splitTextIntoRuns, parseHtmlToStyledText, styledTextToHtml, } from "@orangecatai/element";
52
54
  export { CommandPalette } from "./components/CommandPalette/CommandPalette";
53
55
  export { AIChatPanel } from "./components/AIChatPanel";
54
56
  export type { AIChatPanelProps, AIChatPanelRef, ChatMessage, ChatSession, } from "./components/AIChatPanel";
55
57
  export type { ExcalidrawImperativeAPI } from "./types";
58
+ export { ActivityTimeline } from "./components/ai-chat/ActivityTimeline";
59
+ export type { ActivityTimelineProps } from "./components/ai-chat/ActivityTimeline";
60
+ export { applyAgentUpdate, createReducerContext, finalizeSteps, humanizeToolLabel, stepsFromLegacyToolActions, summarizeSteps, upsertStep, } from "./components/ai-chat/activitySteps";
61
+ export type { ActivityStep, ActivityStepStatus, ActivityReducerContext, } from "./components/ai-chat/activitySteps";
62
+ export type { AgentUpdate, ToolAction, AgentResult, } from "./components/ai-chat/agentLoop";
56
63
  export type { AppState, BinaryFiles, BinaryFileData, ExcalidrawProps, ExcalidrawInitialDataState, LibraryItem, LibraryItems, SceneData, UnsubscribeCallback, } from "./types";
57
64
  export type { ExcalidrawElement, NonDeletedExcalidrawElement, NonDeleted, OrderedExcalidrawElement, ExcalidrawElementType, ExcalidrawVideoElement, } from "@orangecatai/element/types";
58
65
  export type { ImageEditToolbarCallbacks } from "./components/ImageEditToolbar";
59
66
  export type { CustomFontSpec, BrandContext } from "./types";
60
67
  export type { CampaignSummary, AddToCampaignPayload } from "./types";
61
68
  export type { ReviewerFeedback, ReviewIssue, } from "./components/ai-chat/reviewerAgent";
69
+ export { ALL_MODEL_CAPABILITIES, AUTO_DURATION, IMAGE_MODEL_CAPABILITIES, VIDEO_MODEL_CAPABILITIES, effectiveUserReferenceLimit, getCapabilities, groupImages, normalizeInputs, registeredModelIds, validateInputs, } from "./modelCapabilities";
70
+ export type { AspectRatioMode, AssetCapabilities, AudioMode, CapabilityConstraint, ControlCapabilities, FrameCapabilities, InputAsset, InputCapabilityError, InputCapabilityErrorCode, ModelInputCapabilities, NormalizedGenerationInputs, RawGenerationInputs, ReferenceCapabilities, ReferenceGroup, ReferenceGrouping, RequestedControls, } from "./modelCapabilities";
@@ -0,0 +1,17 @@
1
+ import type { ModelInputCapabilities } from "./types";
2
+ export * from "./types";
3
+ export * from "./validate";
4
+ export { IMAGE_MODEL_CAPABILITIES } from "./registry.image";
5
+ export { VIDEO_MODEL_CAPABILITIES } from "./registry.video";
6
+ export declare const ALL_MODEL_CAPABILITIES: readonly ModelInputCapabilities[];
7
+ /**
8
+ * Resolve the capability record for a model id, or null when the model is not
9
+ * registered. The host MUST resolve through this rather than trusting any
10
+ * capability values sent by the client.
11
+ *
12
+ * OpenRouter's web-search variant appends ":online" to a model id; strip it
13
+ * before looking up, mirroring `isModelAllowed` on the host.
14
+ */
15
+ export declare function getCapabilities(modelId: string | null | undefined): ModelInputCapabilities | null;
16
+ /** Every registered model id, for allowlist parity checks. */
17
+ export declare function registeredModelIds(): string[];
@@ -0,0 +1,2 @@
1
+ import type { ModelInputCapabilities } from "./types";
2
+ export declare const IMAGE_MODEL_CAPABILITIES: readonly ModelInputCapabilities[];
@@ -0,0 +1,2 @@
1
+ import type { ModelInputCapabilities } from "./types";
2
+ export declare const VIDEO_MODEL_CAPABILITIES: readonly ModelInputCapabilities[];
@@ -0,0 +1,24 @@
1
+ import type { AssetCapabilities, FrameCapabilities } from "./types";
2
+ export declare const MB: number;
3
+ /** Image models have no frame slots at all. */
4
+ export declare const NO_FRAMES: FrameCapabilities;
5
+ /**
6
+ * Per-asset dimension/size fields left UNCHECKED because the provider does not
7
+ * document them.
8
+ *
9
+ * Conservative defaults cut two different ways, and the distinction matters:
10
+ *
11
+ * - For COUNTS and COMBINATIONS, the safest default is restrictive. Sending
12
+ * one reference too many, or an unsupported refs+frames mix, means a paid
13
+ * request that fails upstream. So an undocumented cap becomes the tightest
14
+ * documented-adjacent value (MAI Image -> 1 image; Veo refs+frames -> not
15
+ * allowed).
16
+ *
17
+ * - For per-asset DIMENSION bounds, the safest default is no check at all.
18
+ * Inventing a ceiling would reject images the provider would have accepted,
19
+ * turning a missing doc into a broken feature. The transport guard
20
+ * (REFERENCE_WIRE_BUDGET_BYTES) still bounds the payload.
21
+ *
22
+ * Every field defaulted this way is listed in the record's `unknownFields`.
23
+ */
24
+ export declare const unchecked: Pick<AssetCapabilities, "maxImageBytes" | "minEdgePx" | "maxEdgePx" | "inputPixels" | "inputAspectRatioRange">;
@@ -0,0 +1,276 @@
1
+ /**
2
+ * Hard cap on user-supplied reference images per generation. Six covers every
3
+ * realistic ad brief. This is a product/transport decision, NOT a provider
4
+ * limit — `ModelInputCapabilities.references.maxImages` carries those.
5
+ */
6
+ export declare const MAX_USER_REFERENCE_IMAGES = 6;
7
+ /**
8
+ * Ceiling on total attached references across all tiers.
9
+ * 6 user + 1 source + 1 logo + 2 brand assets + 2 ad references.
10
+ */
11
+ export declare const MAX_REFERENCE_IMAGES = 12;
12
+ /**
13
+ * Wire-byte budget for the attached images alone. Vercel rejects at 4.5 MB;
14
+ * this leaves headroom for the prompt, brand context and JSON envelope.
15
+ */
16
+ export declare const REFERENCE_WIRE_BUDGET_BYTES: number;
17
+ /**
18
+ * What the SDK assumes a host-injected brand asset costs on the wire, and the
19
+ * ceiling the host compresses each one to before injecting it.
20
+ */
21
+ export declare const HOST_ASSET_BYTE_RESERVATION: number;
22
+ export type CapabilityCondition = {
23
+ kind: "hasReferences";
24
+ } | {
25
+ kind: "hasStartFrame";
26
+ } | {
27
+ kind: "hasEndFrame";
28
+ } | {
29
+ kind: "hasAnyFrame";
30
+ } | {
31
+ kind: "resolutionIn";
32
+ values: readonly string[];
33
+ };
34
+ export type CapabilityRequirement = {
35
+ kind: "durationMustBe";
36
+ seconds: number;
37
+ } | {
38
+ kind: "resolutionAtMost";
39
+ value: string;
40
+ } | {
41
+ kind: "aspectRatioMustBe";
42
+ value: string;
43
+ };
44
+ export interface CapabilityConstraint {
45
+ /** Fires when ANY of these conditions holds. */
46
+ whenAny: readonly CapabilityCondition[];
47
+ requires: CapabilityRequirement;
48
+ /** User-readable explanation, quoting the provider rule where possible. */
49
+ message: string;
50
+ }
51
+ /**
52
+ * Ordering used by `resolutionAtMost`. Lower rank = smaller output.
53
+ * Keys are compared case-insensitively.
54
+ */
55
+ export declare const RESOLUTION_RANK: Readonly<Record<string, number>>;
56
+ export type Modality = "image" | "video";
57
+ /**
58
+ * How a model groups reference images.
59
+ *
60
+ * `flat` — a plain list of images (Seedream, Seedance, Wan, Grok, Veo).
61
+ * `elements` — nested subjects, each built from several views of one subject.
62
+ * Kling 3.0 only: max 3 Elements, each 1 frontal image plus 1-3
63
+ * additional angles. A flat count cannot express this.
64
+ */
65
+ export type ReferenceGrouping = "flat" | "elements";
66
+ export interface ReferenceCapabilities {
67
+ supported: boolean;
68
+ grouping: ReferenceGrouping;
69
+ /** Max reference IMAGES. For `elements`, the total across all groups. */
70
+ maxImages: number;
71
+ /** `elements` only: max number of subjects. */
72
+ maxGroups?: number;
73
+ /** `elements` only: images permitted per subject, frontal image included. */
74
+ imagesPerGroup?: {
75
+ min: number;
76
+ max: number;
77
+ };
78
+ maxVideos: number;
79
+ maxAudios: number;
80
+ /** Provider-side ceiling across every reference asset type, when documented. */
81
+ maxTotalAssets?: number;
82
+ acceptsImageAndVideoReferences: boolean;
83
+ /**
84
+ * Whether references may accompany a start/end frame. This is the field the
85
+ * providers disagree on most sharply: ByteDance and Alibaba forbid the
86
+ * combination outright, xAI explicitly permits it, and Google documents
87
+ * neither (so Veo takes the conservative `false`).
88
+ */
89
+ canCombineWithStartFrame: boolean;
90
+ canCombineWithEndFrame: boolean;
91
+ }
92
+ export interface FrameSlotCapability {
93
+ supported: boolean;
94
+ maxImages: 0 | 1;
95
+ }
96
+ export interface FrameCapabilities {
97
+ start: FrameSlotCapability;
98
+ end: FrameSlotCapability;
99
+ allowsStartAndEndTogether: boolean;
100
+ /**
101
+ * True when an end frame is only accepted alongside a start frame.
102
+ * Veo 3.1: `lastFrame` "must be used in combination with the image
103
+ * parameter". Kling 3.0: "last-frame-only video generation is not
104
+ * supported".
105
+ */
106
+ endFrameRequiresStartFrame: boolean;
107
+ }
108
+ export interface AssetCapabilities {
109
+ /** Lower-case MIME types the provider documents for input images. */
110
+ imageMimeTypes: readonly string[];
111
+ maxImageBytes: number | null;
112
+ minEdgePx: number | null;
113
+ maxEdgePx: number | null;
114
+ /**
115
+ * Permitted total pixel count (width x height) of an INPUT image. Several
116
+ * providers bound the product rather than either edge -- Seedream allows
117
+ * [196, 36,000,000] regardless of how the pixels are distributed.
118
+ */
119
+ inputPixels: {
120
+ min: number;
121
+ max: number;
122
+ } | null;
123
+ /** Permitted width/height ratio of an INPUT image, as [min, max]. */
124
+ inputAspectRatioRange: readonly [number, number] | null;
125
+ /** Provider cap on the whole request body. */
126
+ maxRequestBytes: number | null;
127
+ }
128
+ /**
129
+ * How the provider treats an explicit output aspect ratio.
130
+ *
131
+ * `settable` — accepts an explicit value in every mode.
132
+ * `forcedAdaptiveWithFrames` — accepts a value for text-to-video, but requires
133
+ * `adaptive` once a frame is attached, deriving the
134
+ * ratio from the first frame (Seedance 2.x).
135
+ * `notApplicableWithFrames` — the image-to-video endpoint has no aspect-ratio
136
+ * parameter at all, though text-to-video does
137
+ * (Kling 3.0).
138
+ * `notApplicable` — no aspect-ratio parameter in any mode.
139
+ */
140
+ export type AspectRatioMode = "settable" | "forcedAdaptiveWithFrames" | "notApplicableWithFrames" | "notApplicable";
141
+ /** The value providers use to mean "derive the ratio from the input media". */
142
+ export declare const ADAPTIVE_ASPECT_RATIO = "adaptive";
143
+ export type AudioMode = "always-on" | "toggle-default-on" | "toggle-default-off" | "none";
144
+ export interface ControlCapabilities {
145
+ aspectRatioMode: AspectRatioMode;
146
+ aspectRatios: readonly string[];
147
+ resolutions: readonly string[];
148
+ /** Discrete allowed durations. Mutually exclusive with min/max. */
149
+ durationsSeconds?: readonly number[];
150
+ minDurationSeconds?: number;
151
+ maxDurationSeconds?: number;
152
+ /** Whether the provider accepts `-1` / auto duration. */
153
+ supportsAutoDuration?: boolean;
154
+ audio: AudioMode;
155
+ supportsNegativePrompt: boolean;
156
+ supportsSeed: boolean;
157
+ /** Output pixel envelope, where the provider documents one. */
158
+ outputPixels?: {
159
+ min: number;
160
+ max: number;
161
+ };
162
+ /** Output edge constraints, where documented. */
163
+ outputEdge?: {
164
+ min?: number;
165
+ max?: number;
166
+ multipleOf?: number;
167
+ };
168
+ /** Max ratio of longer edge to shorter edge for the OUTPUT. */
169
+ maxOutputEdgeRatio?: number;
170
+ }
171
+ export interface VerificationRecord {
172
+ /** First-party doc URL(s) the values were transcribed from. */
173
+ sources: readonly string[];
174
+ /** ISO date the transcription was checked. */
175
+ checkedOn: string;
176
+ }
177
+ export interface ModelInputCapabilities {
178
+ modelId: string;
179
+ modality: Modality;
180
+ verified: VerificationRecord;
181
+ /**
182
+ * Dotted paths of fields holding a CONSERVATIVE DEFAULT because the
183
+ * first-party docs do not state the value. Never empty-by-omission: a field
184
+ * absent from this list is a transcribed, verified value.
185
+ */
186
+ unknownFields: readonly string[];
187
+ /** Why each unknown field defaults the way it does, keyed by the same path. */
188
+ unknownNotes?: Readonly<Record<string, string>>;
189
+ references: ReferenceCapabilities;
190
+ frames: FrameCapabilities;
191
+ assets: AssetCapabilities;
192
+ controls: ControlCapabilities;
193
+ constraints: readonly CapabilityConstraint[];
194
+ /** Provider rules we cannot check client-side, surfaced for messaging. */
195
+ providerCaveats?: readonly string[];
196
+ }
197
+ export interface InputAsset {
198
+ /** Data URL or remote URL. Empty string marks a host-filled placeholder. */
199
+ dataUrl: string;
200
+ mimeType?: string;
201
+ bytes?: number;
202
+ widthPx?: number;
203
+ heightPx?: number;
204
+ label?: string;
205
+ }
206
+ /**
207
+ * A reference "subject" for `elements` grouping: one frontal view plus
208
+ * additional angles of the same subject.
209
+ */
210
+ export interface ReferenceGroup {
211
+ frontal: InputAsset;
212
+ additional: InputAsset[];
213
+ label?: string;
214
+ }
215
+ /**
216
+ * Every request is normalized into explicit slots before validation. The
217
+ * validator must keep these categories distinct: a start frame is not an
218
+ * ordinary reference image unless the provider docs say it is counted as one,
219
+ * and the same holds for an end frame and a Quick Edit source image.
220
+ */
221
+ export interface NormalizedGenerationInputs {
222
+ startFrame: InputAsset | null;
223
+ endFrame: InputAsset | null;
224
+ /**
225
+ * How many images the caller actually supplied for each frame slot. Every
226
+ * registered model accepts at most one, so anything above that is reported
227
+ * rather than silently truncated.
228
+ */
229
+ startFrameCount: number;
230
+ endFrameCount: number;
231
+ referenceImages: InputAsset[];
232
+ referenceVideos: InputAsset[];
233
+ referenceAudios: InputAsset[];
234
+ /** `elements` grouping only. */
235
+ referenceGroups: ReferenceGroup[];
236
+ sourceImage: InputAsset | null;
237
+ brandLogo: InputAsset | null;
238
+ /** Host-injected brand/ad references the SDK only reserves room for. */
239
+ hostReferences: InputAsset[];
240
+ }
241
+ /**
242
+ * What callers hand to `normalizeInputs`. Every field is optional, and the
243
+ * frame slots accept either a single asset or an array so an over-supply is
244
+ * visible to the validator.
245
+ */
246
+ export interface RawGenerationInputs {
247
+ startFrame?: InputAsset | InputAsset[] | null;
248
+ endFrame?: InputAsset | InputAsset[] | null;
249
+ referenceImages?: InputAsset[];
250
+ referenceVideos?: InputAsset[];
251
+ referenceAudios?: InputAsset[];
252
+ referenceGroups?: ReferenceGroup[];
253
+ sourceImage?: InputAsset | null;
254
+ brandLogo?: InputAsset | null;
255
+ hostReferences?: InputAsset[];
256
+ }
257
+ /** The control values accompanying a request, for constraint evaluation. */
258
+ export interface RequestedControls {
259
+ aspectRatio?: string;
260
+ resolution?: string;
261
+ durationSeconds?: number;
262
+ audio?: boolean;
263
+ seed?: number;
264
+ negativePrompt?: string;
265
+ }
266
+ export type InputCapabilityErrorCode = "UNKNOWN_MODEL_CAPABILITIES" | "START_FRAME_NOT_SUPPORTED" | "END_FRAME_NOT_SUPPORTED" | "TOO_MANY_START_FRAMES" | "TOO_MANY_END_FRAMES" | "END_FRAME_REQUIRES_START_FRAME" | "START_AND_END_FRAME_NOT_SUPPORTED_TOGETHER" | "FRAME_REFERENCE_COMBINATION_NOT_SUPPORTED" | "REFERENCE_FRAME_COMBINATION_UNVERIFIED" | "REFERENCES_NOT_SUPPORTED" | "TOO_MANY_REFERENCE_IMAGES" | "TOO_MANY_REFERENCE_VIDEOS" | "TOO_MANY_REFERENCE_AUDIOS" | "TOO_MANY_REFERENCE_ASSETS" | "TOO_MANY_REFERENCE_GROUPS" | "INVALID_REFERENCE_GROUP_SIZE" | "UNSUPPORTED_MEDIA_TYPE" | "UNSUPPORTED_DIMENSIONS" | "REQUEST_TOO_LARGE" | "UNSUPPORTED_CONTROL" | "CONTROL_CONSTRAINT_VIOLATED";
267
+ export interface InputCapabilityError {
268
+ code: InputCapabilityErrorCode;
269
+ message: string;
270
+ modelId: string;
271
+ /** Which input category or control caused the rejection. */
272
+ field?: string;
273
+ /** The permitted value, count, or set of values. */
274
+ allowed?: number | string | readonly string[];
275
+ received?: number | string;
276
+ }
@@ -0,0 +1,48 @@
1
+ import type { InputAsset, InputCapabilityError, ModelInputCapabilities, NormalizedGenerationInputs, RawGenerationInputs, ReferenceGroup, RequestedControls } from "./types";
2
+ /** The sentinel providers use for "pick a duration for me". */
3
+ export declare const AUTO_DURATION = -1;
4
+ /**
5
+ * Normalize a request into explicit slots. The categories stay distinct: a
6
+ * start frame is never folded into the reference list, and neither is a Quick
7
+ * Edit source image, because providers count them separately.
8
+ */
9
+ export declare function normalizeInputs(raw: RawGenerationInputs): NormalizedGenerationInputs;
10
+ /** Every image in a reference group, frontal view first. */
11
+ export declare function groupImages(group: ReferenceGroup): InputAsset[];
12
+ /**
13
+ * How many user-supplied reference images this model can actually take.
14
+ *
15
+ * The transport guard and the provider limit are different things and either
16
+ * may bind: most providers accept far more than we ever send (Seedance allows
17
+ * 30), while two accept fewer (MAI Image 1, Grok Imagine Image 5).
18
+ *
19
+ * `reserved` is the number of provider-counted inputs already spoken for — a
20
+ * Quick Edit source image, a logo, a host-injected brand asset.
21
+ */
22
+ export declare function effectiveUserReferenceLimit(caps: ModelInputCapabilities, reserved: number, globalLimit?: number): number;
23
+ /**
24
+ * The duration a model's own constraints force for this request, or null when
25
+ * nothing is forced.
26
+ *
27
+ * Veo 3.1 is the case that matters: reference images, 1080p and 4K each
28
+ * require an 8 second duration. The UI needs this to pick a valid default and
29
+ * to coerce the duration when the user changes resolution, rather than
30
+ * letting the two controls drift into a combination the provider rejects.
31
+ */
32
+ export declare function requiredDurationFor(caps: ModelInputCapabilities | null | undefined, inputs: NormalizedGenerationInputs, controls: RequestedControls): number | null;
33
+ /**
34
+ * The highest resolution this request may use, given the model's constraints,
35
+ * or null when nothing is capped. Grok Imagine Video caps reference-to-video
36
+ * at 720p even though the model itself supports 1080p.
37
+ */
38
+ export declare function maxResolutionFor(caps: ModelInputCapabilities | null | undefined, inputs: NormalizedGenerationInputs, controls: RequestedControls): string | null;
39
+ /** Resolutions from `caps` that are usable for this request. */
40
+ export declare function allowedResolutionsFor(caps: ModelInputCapabilities | null | undefined, inputs: NormalizedGenerationInputs, controls: RequestedControls): readonly string[];
41
+ /**
42
+ * Validate a normalized request against a capability record.
43
+ *
44
+ * `caps` is nullable on purpose: an unregistered model must be rejected, not
45
+ * waved through, and the host resolves the record itself rather than trusting
46
+ * anything the client sent.
47
+ */
48
+ export declare function validateInputs(caps: ModelInputCapabilities | null | undefined, inputs: NormalizedGenerationInputs, controls: RequestedControls): InputCapabilityError[];
@@ -761,8 +761,8 @@ export interface ExcalidrawProps {
761
761
  * background regeneration and the agent chat `generate_image` tool.
762
762
  * Pass the same value here and to `AIChatPanel.agentImageModel` to keep
763
763
  * both surfaces on the same model with a single configuration.
764
- * @default "openai/gpt-image-2"
765
- * @example "google/gemini-3.1-flash-image-preview"
764
+ * @default "openai/gpt-image-2.5-flare"
765
+ * @example "google/gemini-3.1-flash-lite-image"
766
766
  */
767
767
  agentImageModel?: string;
768
768
  /**
@@ -787,9 +787,9 @@ export interface ExcalidrawProps {
787
787
  * model at all.
788
788
  *
789
789
  * Must support extreme aspect ratios (4:1, 1:4, 8:1, 1:8) and be callable
790
- * from `chat/completions`. `openai/gpt-image-2` satisfies NEITHER — it is
790
+ * from `chat/completions`. GPT Image models satisfy neither — they are
791
791
  * generation-only on OpenRouter and its ratio enum stops at 3:1 / 1:3.
792
- * @default "google/gemini-3.1-flash-image-preview"
792
+ * @default "google/gemini-3.1-flash-lite-image"
793
793
  */
794
794
  outpaintModel?: string;
795
795
  /**
@@ -102,4 +102,7 @@ aspectRatio: string | null, imageSize: string | null, textOutput: boolean, image
102
102
  */
103
103
  hostBrandAssetSlots?: number;
104
104
  hostAdReferenceSlots?: number;
105
+ quality?: "auto" | "low" | "medium" | "high" | "xhigh" | "max";
106
+ background?: "auto" | "opaque" | "transparent";
107
+ outputFormat?: "png" | "webp";
105
108
  }): Promise<string>;
@@ -42,6 +42,7 @@
42
42
  * downscales everything, then escalates compression on the largest offenders,
43
43
  * and only starts shedding slots if the payload is *still* over budget.
44
44
  */
45
+ import { HOST_ASSET_BYTE_RESERVATION, MAX_REFERENCE_IMAGES, MAX_USER_REFERENCE_IMAGES, REFERENCE_WIRE_BUDGET_BYTES } from "../modelCapabilities/types";
45
46
  /** Reference tiers in descending priority. Index === priority rank. */
46
47
  export declare const REFERENCE_TIERS: readonly ["user", "source", "logo", "brandAsset", "adReference"];
47
48
  export type ReferenceTier = typeof REFERENCE_TIERS[number];
@@ -64,31 +65,19 @@ export interface DroppedSlot {
64
65
  reason: "count" | "bytes";
65
66
  }
66
67
  /**
67
- * Hard cap on user-supplied reference images per generation. Six covers every
68
- * realistic ad brief and keeps the request inside the limits of the models we
69
- * route to.
70
- */
71
- export declare const MAX_USER_REFERENCE_IMAGES = 6;
72
- /**
73
- * Ceiling on total attached references. 6 user + 1 source + 1 logo + 2 brand
74
- * assets + 2 ad references. Comfortably under the ~20 images-per-request cap
75
- * observed on OpenRouter.
76
- */
77
- export declare const MAX_REFERENCE_IMAGES = 12;
78
- /**
79
- * Wire-byte budget for the attached images alone.
68
+ * These four are TRANSPORT guards — our own limits, not any provider's — and
69
+ * they now live alongside the capability contract so both enforcement layers
70
+ * read the same numbers. Re-exported here because this module has been their
71
+ * import site for a long time.
80
72
  *
81
- * Vercel rejects at 4.5 MB. This leaves ~1.3 MB of headroom for the prompt,
82
- * the brand context block, and the JSON envelope — all of which the caller can
83
- * further reserve against via `reservedBytes`.
84
- */
85
- export declare const REFERENCE_WIRE_BUDGET_BYTES: number;
86
- /**
87
- * What the SDK assumes a host-injected brand asset costs on the wire, and the
88
- * ceiling the host compresses each one down to before injecting it. Keeping
89
- * both sides on the same number is what makes the SDK's reservation honest.
73
+ * A transport guard and a provider limit are different things and either may
74
+ * bind. Most providers accept far more than we send (Seedance allows 30
75
+ * references and a 64 MB body), but two accept fewer — MAI Image takes one
76
+ * input image, Grok Imagine Image five — so a count that clears these guards
77
+ * can still be invalid. Use `effectiveUserReferenceLimit` from
78
+ * ../modelCapabilities, which takes the smaller of the two.
90
79
  */
91
- export declare const HOST_ASSET_BYTE_RESERVATION: number;
80
+ export { HOST_ASSET_BYTE_RESERVATION, MAX_REFERENCE_IMAGES, MAX_USER_REFERENCE_IMAGES, REFERENCE_WIRE_BUDGET_BYTES, };
92
81
  /** Sort into priority order, stable within a tier. */
93
82
  export declare function orderByPriority(slots: ReferenceSlot[]): ReferenceSlot[];
94
83
  /**
@@ -1,14 +1,34 @@
1
+ /**
2
+ * One reference SUBJECT for models whose references are nested rather than a
3
+ * flat list. Kling 3.0 calls these "Elements": each is built from one frontal
4
+ * reference image plus 1-3 other angles or close-ups of the same subject.
5
+ *
6
+ * See ELEMENTS_TRANSPORT_ENABLED in VideoGeneratorPanel for why this is not
7
+ * yet sent on the wire.
8
+ */
9
+ export interface VideoReferenceSubject {
10
+ frontalDataUrl: string;
11
+ additionalDataUrls: string[];
12
+ }
1
13
  export interface VideoJobParams {
2
14
  model: string;
3
15
  prompt: string;
4
- aspectRatio: string;
16
+ /**
17
+ * Omitted entirely for models whose image-to-video endpoint has no
18
+ * aspect-ratio parameter (Kling 3.0), and sent as "adaptive" where the
19
+ * provider requires the ratio to follow the first frame (Seedance 2.x).
20
+ */
21
+ aspectRatio?: string;
5
22
  duration?: number;
6
23
  resolution?: string;
7
24
  firstFrameDataUrl?: string;
8
25
  lastFrameDataUrl?: string;
9
26
  audio?: boolean;
10
27
  negativePrompt?: string;
28
+ /** Flat reference images, for providers that take a plain list. */
11
29
  inputReferences?: string[];
30
+ /** Nested reference subjects, for providers that group them (Kling). */
31
+ referenceSubjects?: VideoReferenceSubject[];
12
32
  seed?: number;
13
33
  }
14
34
  export interface VideoJobResult {
@@ -0,0 +1,36 @@
1
+ import { getCommonStyleInRange } from "@orangecatai/element";
2
+ import type { ExcalidrawTextElement, TextRunStyle, TextStyleRange } from "@orangecatai/element/types";
3
+ /**
4
+ * The WYSIWYG text editor surface.
5
+ *
6
+ * It's a `contenteditable` (a textarea can't show mixed formatting) that
7
+ * exposes the slice of the `HTMLTextAreaElement` API the editor was written
8
+ * against — `value`, `selectionStart`, `selectionEnd`, `select()` — so that
9
+ * indent/outdent, paste, submit and blur handling keep working unchanged, and
10
+ * so host code that pokes at `.excalidraw-wysiwyg` doesn't have to care.
11
+ *
12
+ * On top of that it owns the per-range styles: the DOM is rendered from
13
+ * `{ value, styleRanges }` and re-read back after every edit, which is what
14
+ * keeps style offsets correct across typing, deleting and pasting without any
15
+ * manual index bookkeeping.
16
+ */
17
+ export type RichTextEditable = HTMLDivElement & {
18
+ value: string;
19
+ selectionStart: number;
20
+ selectionEnd: number;
21
+ select: () => void;
22
+ setSelectionRange: (start: number, end: number) => void;
23
+ /** per-range styles, indexed against `value` */
24
+ styleRanges: readonly TextStyleRange[] | undefined;
25
+ /** applies a style patch to the current selection (no-op if collapsed) */
26
+ applyStyleToSelection: (patch: TextRunStyle) => void;
27
+ /** the style shared by the current selection, for the properties panel */
28
+ getSelectionStyle: () => ReturnType<typeof getCommonStyleInRange>;
29
+ /** replaces the selection with styled text (used by paste) */
30
+ insertStyledText: (text: string, ranges?: readonly TextStyleRange[]) => void;
31
+ /** re-renders the DOM, e.g. after the element's base style changed */
32
+ refresh: () => void;
33
+ };
34
+ /** base (element-level) style the runs are layered on top of */
35
+ export type RichTextBaseStyle = Pick<ExcalidrawTextElement, "fontSize" | "fontFamily" | "strokeColor">;
36
+ export declare const createRichTextEditable: (getBaseStyle: () => RichTextBaseStyle) => RichTextEditable;
@@ -0,0 +1,32 @@
1
+ import type { TextRunStyle } from "@orangecatai/element/types";
2
+ import type { RichTextEditable } from "./richTextEditable";
3
+ /**
4
+ * Bridge between the properties panel and the open text editor.
5
+ *
6
+ * When text is being edited and part of it is highlighted, style changes from
7
+ * the panel apply to that range only (Canva/Docs behaviour) instead of to the
8
+ * whole element. The editor owns the text and its style ranges while it's
9
+ * open, so panel changes are routed through it — the resulting `input` event
10
+ * persists them onto the element the same way typing does.
11
+ */
12
+ export declare const getActiveTextEditor: () => RichTextEditable | null;
13
+ /** the highlighted range in the open editor, if any */
14
+ export declare const getActiveTextSelection: () => {
15
+ editor: RichTextEditable;
16
+ start: number;
17
+ end: number;
18
+ } | null;
19
+ /**
20
+ * Applies a style patch to the highlighted text, returning whether it did.
21
+ * A `false` return means the caller should fall back to changing the property
22
+ * on the whole element.
23
+ */
24
+ export declare const applyStyleToActiveTextSelection: (patch: TextRunStyle) => boolean;
25
+ /**
26
+ * The style shared by the highlighted text, for rendering the panel's own
27
+ * state (a field that differs across the range comes back in `mixed`).
28
+ */
29
+ export declare const getActiveTextSelectionStyle: () => {
30
+ style: TextRunStyle;
31
+ mixed: import("@orangecatai/element").TextRunStyleKey[];
32
+ } | null;