@drawcall/design 0.3.0 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  export * as v1 from "./v1/index.js";
2
2
  export { designSkill } from "./skill.generated.js";
3
3
  export { frameCreationCapabilities, type FrameCreationCapability, type FrameCreationCapabilityId, type FrameCreationInput, } from "./v1/capabilities.js";
4
+ export { IMAGE_GENERATION_MODEL, IMAGE_GENERATION_PROVIDER, } from "./v1/schemas.js";
4
5
  export { parseFrameSize } from "./target.js";
5
6
  export { acknowledgesInspection, inspectionCommandSchema, inspectionFrameMessageSchema, inspectionMessageTypes, projectSyncMaps, projectSyncUrl, type InspectionAppliedMessage, type InspectionCommand, type InspectionFrameMessage, } from "./protocol.js";
6
- export type { BinaryFile, CreateFrame, CreateProjectFromBrief, CreateGltsFrame, CreateImageFrame, CreateMarketFrame, DesignFile, FileList, FileMutation, Frame, GltsFrame, ImageFrame, MarketFrame, Project, ProjectDerivationStatus, Screenshot, TextFile, User, } from "./v1/schemas.js";
7
+ export type { BinaryFile, CreateFrame, CreateProjectFromBrief, CreateGltsFrame, CreateImageFrame, CreateMarketFrame, GenerateImageFrame, DesignFile, FileList, FileMutation, Frame, GltsFrame, ImageFrame, ImageGenerationOperation, ImageGenerationProvenance, ImageGenerationResult, MarketFrame, Project, ProjectDerivationStatus, Screenshot, TextFile, User, } from "./v1/schemas.js";
package/dist/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  export * as v1 from "./v1/index.js";
2
2
  export { designSkill } from "./skill.generated.js";
3
3
  export { frameCreationCapabilities, } from "./v1/capabilities.js";
4
+ export { IMAGE_GENERATION_MODEL, IMAGE_GENERATION_PROVIDER, } from "./v1/schemas.js";
4
5
  export { parseFrameSize } from "./target.js";
5
6
  export { acknowledgesInspection, inspectionCommandSchema, inspectionFrameMessageSchema, inspectionMessageTypes, projectSyncMaps, projectSyncUrl, } from "./protocol.js";
@@ -1,5 +1,6 @@
1
1
  import { z } from "zod";
2
2
  export declare const projectSyncMaps: {
3
+ readonly frameContentRevisions: "frame-content-revisions";
3
4
  readonly filesystemRevision: "filesystem-revision";
4
5
  readonly frameRecords: "frame-records";
5
6
  };
package/dist/protocol.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { z } from "zod";
2
2
  export const projectSyncMaps = {
3
+ frameContentRevisions: "frame-content-revisions",
3
4
  filesystemRevision: "filesystem-revision",
4
5
  frameRecords: "frame-records",
5
6
  };
@@ -1,5 +1,5 @@
1
- export type FrameCreationCapabilityId = "add-image" | "create-glts" | "search-assets";
2
- export type FrameCreationInput = "asset" | "height" | "image" | "name" | "width";
1
+ export type FrameCreationCapabilityId = "add-image" | "create-glts" | "generate-image" | "search-assets";
2
+ export type FrameCreationInput = "asset" | "height" | "image" | "name" | "prompt" | "references" | "width";
3
3
  export interface FrameCreationCapability {
4
4
  id: FrameCreationCapabilityId;
5
5
  frameType: "glts" | "image" | "market";
@@ -13,6 +13,13 @@ export const frameCreationCapabilities = [
13
13
  description: "Create an empty programmable 3D frame",
14
14
  inputs: ["name", "width", "height"],
15
15
  },
16
+ {
17
+ id: "generate-image",
18
+ frameType: "image",
19
+ label: "Generate image",
20
+ description: "Create or edit an image with optional frame references",
21
+ inputs: ["name", "prompt", "references"],
22
+ },
16
23
  {
17
24
  id: "search-assets",
18
25
  frameType: "market",
@@ -76,6 +76,24 @@ export declare const contract: {
76
76
  createdAt: z.ZodString;
77
77
  updatedAt: z.ZodString;
78
78
  }, z.core.$strip>, Record<never, never>, Record<never, never>>;
79
+ rename: import("@orpc/contract").ContractProcedureBuilderWithInputOutput<z.ZodObject<{
80
+ project: z.ZodString;
81
+ name: z.ZodString;
82
+ }, z.core.$strip>, z.ZodObject<{
83
+ id: z.ZodString;
84
+ name: z.ZodString;
85
+ sourceBrief: z.ZodNullable<z.ZodString>;
86
+ title: z.ZodNullable<z.ZodString>;
87
+ summary: z.ZodNullable<z.ZodString>;
88
+ derivationStatus: z.ZodEnum<{
89
+ not_requested: "not_requested";
90
+ pending: "pending";
91
+ failed: "failed";
92
+ complete: "complete";
93
+ }>;
94
+ createdAt: z.ZodString;
95
+ updatedAt: z.ZodString;
96
+ }, z.core.$strip>, Record<never, never>, Record<never, never>>;
79
97
  delete: import("@orpc/contract").ContractProcedureBuilderWithInputOutput<z.ZodObject<{
80
98
  project: z.ZodString;
81
99
  }, z.core.$strip>, z.ZodObject<{
@@ -110,6 +128,41 @@ export declare const contract: {
110
128
  updatedAt: z.ZodString;
111
129
  type: z.ZodLiteral<"image">;
112
130
  file: z.ZodString;
131
+ provenance: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
132
+ kind: z.ZodLiteral<"generated">;
133
+ operation: z.ZodEnum<{
134
+ generate: "generate";
135
+ edit: "edit";
136
+ }>;
137
+ prompt: z.ZodString;
138
+ references: z.ZodArray<z.ZodObject<{
139
+ frameId: z.ZodString;
140
+ frameUpdatedAt: z.ZodString;
141
+ }, z.core.$strip>>;
142
+ result: z.ZodEnum<{
143
+ replace: "replace";
144
+ new: "new";
145
+ }>;
146
+ provider: z.ZodLiteral<"fal-ai">;
147
+ model: z.ZodLiteral<"openai/gpt-image-2">;
148
+ }, z.core.$strip>, z.ZodObject<{
149
+ kind: z.ZodLiteral<"generated">;
150
+ operation: z.ZodEnum<{
151
+ generate: "generate";
152
+ edit: "edit";
153
+ }>;
154
+ prompt: z.ZodString;
155
+ references: z.ZodArray<z.ZodObject<{
156
+ frameId: z.ZodString;
157
+ frameUpdatedAt: z.ZodString;
158
+ }, z.core.$strip>>;
159
+ result: z.ZodEnum<{
160
+ replace: "replace";
161
+ new: "new";
162
+ }>;
163
+ provider: z.ZodLiteral<"cloudflare-workers-ai">;
164
+ model: z.ZodLiteral<"@cf/black-forest-labs/flux-2-klein-4b">;
165
+ }, z.core.$strip>], "provider">>;
113
166
  }, z.core.$strip>, z.ZodObject<{
114
167
  id: z.ZodString;
115
168
  projectId: z.ZodString;
@@ -171,6 +224,131 @@ export declare const contract: {
171
224
  updatedAt: z.ZodString;
172
225
  type: z.ZodLiteral<"image">;
173
226
  file: z.ZodString;
227
+ provenance: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
228
+ kind: z.ZodLiteral<"generated">;
229
+ operation: z.ZodEnum<{
230
+ generate: "generate";
231
+ edit: "edit";
232
+ }>;
233
+ prompt: z.ZodString;
234
+ references: z.ZodArray<z.ZodObject<{
235
+ frameId: z.ZodString;
236
+ frameUpdatedAt: z.ZodString;
237
+ }, z.core.$strip>>;
238
+ result: z.ZodEnum<{
239
+ replace: "replace";
240
+ new: "new";
241
+ }>;
242
+ provider: z.ZodLiteral<"fal-ai">;
243
+ model: z.ZodLiteral<"openai/gpt-image-2">;
244
+ }, z.core.$strip>, z.ZodObject<{
245
+ kind: z.ZodLiteral<"generated">;
246
+ operation: z.ZodEnum<{
247
+ generate: "generate";
248
+ edit: "edit";
249
+ }>;
250
+ prompt: z.ZodString;
251
+ references: z.ZodArray<z.ZodObject<{
252
+ frameId: z.ZodString;
253
+ frameUpdatedAt: z.ZodString;
254
+ }, z.core.$strip>>;
255
+ result: z.ZodEnum<{
256
+ replace: "replace";
257
+ new: "new";
258
+ }>;
259
+ provider: z.ZodLiteral<"cloudflare-workers-ai">;
260
+ model: z.ZodLiteral<"@cf/black-forest-labs/flux-2-klein-4b">;
261
+ }, z.core.$strip>], "provider">>;
262
+ }, z.core.$strip>, z.ZodObject<{
263
+ id: z.ZodString;
264
+ projectId: z.ZodString;
265
+ name: z.ZodString;
266
+ x: z.ZodNumber;
267
+ y: z.ZodNumber;
268
+ width: z.ZodNumber;
269
+ height: z.ZodNumber;
270
+ viewUrl: z.ZodString;
271
+ createdAt: z.ZodString;
272
+ updatedAt: z.ZodString;
273
+ type: z.ZodLiteral<"market">;
274
+ asset: z.ZodString;
275
+ }, z.core.$strip>], "type">, Record<never, never>, Record<never, never>>;
276
+ generateImage: import("@orpc/contract").ContractProcedureBuilderWithInputOutput<z.ZodObject<{
277
+ project: z.ZodString;
278
+ operation: z.ZodEnum<{
279
+ generate: "generate";
280
+ edit: "edit";
281
+ }>;
282
+ prompt: z.ZodString;
283
+ target: z.ZodOptional<z.ZodString>;
284
+ references: z.ZodDefault<z.ZodArray<z.ZodString>>;
285
+ result: z.ZodEnum<{
286
+ replace: "replace";
287
+ new: "new";
288
+ }>;
289
+ name: z.ZodOptional<z.ZodString>;
290
+ x: z.ZodOptional<z.ZodNumber>;
291
+ y: z.ZodOptional<z.ZodNumber>;
292
+ }, z.core.$strict>, z.ZodDiscriminatedUnion<[z.ZodObject<{
293
+ id: z.ZodString;
294
+ projectId: z.ZodString;
295
+ name: z.ZodString;
296
+ x: z.ZodNumber;
297
+ y: z.ZodNumber;
298
+ width: z.ZodNumber;
299
+ height: z.ZodNumber;
300
+ viewUrl: z.ZodString;
301
+ createdAt: z.ZodString;
302
+ updatedAt: z.ZodString;
303
+ type: z.ZodLiteral<"glts">;
304
+ }, z.core.$strip>, z.ZodObject<{
305
+ id: z.ZodString;
306
+ projectId: z.ZodString;
307
+ name: z.ZodString;
308
+ x: z.ZodNumber;
309
+ y: z.ZodNumber;
310
+ width: z.ZodNumber;
311
+ height: z.ZodNumber;
312
+ viewUrl: z.ZodString;
313
+ createdAt: z.ZodString;
314
+ updatedAt: z.ZodString;
315
+ type: z.ZodLiteral<"image">;
316
+ file: z.ZodString;
317
+ provenance: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
318
+ kind: z.ZodLiteral<"generated">;
319
+ operation: z.ZodEnum<{
320
+ generate: "generate";
321
+ edit: "edit";
322
+ }>;
323
+ prompt: z.ZodString;
324
+ references: z.ZodArray<z.ZodObject<{
325
+ frameId: z.ZodString;
326
+ frameUpdatedAt: z.ZodString;
327
+ }, z.core.$strip>>;
328
+ result: z.ZodEnum<{
329
+ replace: "replace";
330
+ new: "new";
331
+ }>;
332
+ provider: z.ZodLiteral<"fal-ai">;
333
+ model: z.ZodLiteral<"openai/gpt-image-2">;
334
+ }, z.core.$strip>, z.ZodObject<{
335
+ kind: z.ZodLiteral<"generated">;
336
+ operation: z.ZodEnum<{
337
+ generate: "generate";
338
+ edit: "edit";
339
+ }>;
340
+ prompt: z.ZodString;
341
+ references: z.ZodArray<z.ZodObject<{
342
+ frameId: z.ZodString;
343
+ frameUpdatedAt: z.ZodString;
344
+ }, z.core.$strip>>;
345
+ result: z.ZodEnum<{
346
+ replace: "replace";
347
+ new: "new";
348
+ }>;
349
+ provider: z.ZodLiteral<"cloudflare-workers-ai">;
350
+ model: z.ZodLiteral<"@cf/black-forest-labs/flux-2-klein-4b">;
351
+ }, z.core.$strip>], "provider">>;
174
352
  }, z.core.$strip>, z.ZodObject<{
175
353
  id: z.ZodString;
176
354
  projectId: z.ZodString;
@@ -214,6 +392,41 @@ export declare const contract: {
214
392
  updatedAt: z.ZodString;
215
393
  type: z.ZodLiteral<"image">;
216
394
  file: z.ZodString;
395
+ provenance: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
396
+ kind: z.ZodLiteral<"generated">;
397
+ operation: z.ZodEnum<{
398
+ generate: "generate";
399
+ edit: "edit";
400
+ }>;
401
+ prompt: z.ZodString;
402
+ references: z.ZodArray<z.ZodObject<{
403
+ frameId: z.ZodString;
404
+ frameUpdatedAt: z.ZodString;
405
+ }, z.core.$strip>>;
406
+ result: z.ZodEnum<{
407
+ replace: "replace";
408
+ new: "new";
409
+ }>;
410
+ provider: z.ZodLiteral<"fal-ai">;
411
+ model: z.ZodLiteral<"openai/gpt-image-2">;
412
+ }, z.core.$strip>, z.ZodObject<{
413
+ kind: z.ZodLiteral<"generated">;
414
+ operation: z.ZodEnum<{
415
+ generate: "generate";
416
+ edit: "edit";
417
+ }>;
418
+ prompt: z.ZodString;
419
+ references: z.ZodArray<z.ZodObject<{
420
+ frameId: z.ZodString;
421
+ frameUpdatedAt: z.ZodString;
422
+ }, z.core.$strip>>;
423
+ result: z.ZodEnum<{
424
+ replace: "replace";
425
+ new: "new";
426
+ }>;
427
+ provider: z.ZodLiteral<"cloudflare-workers-ai">;
428
+ model: z.ZodLiteral<"@cf/black-forest-labs/flux-2-klein-4b">;
429
+ }, z.core.$strip>], "provider">>;
217
430
  }, z.core.$strip>, z.ZodObject<{
218
431
  id: z.ZodString;
219
432
  projectId: z.ZodString;
@@ -1,6 +1,6 @@
1
1
  import { oc } from "@orpc/contract";
2
2
  import { z } from "zod";
3
- import { createFrameSchema, createProjectFromBriefSchema, designIdSchema, fileListSchema, fileMutationSchema, fileSchema, fileTextSchema, frameNameSchema, frameSchema, projectDirectoryPathSchema, projectNameSchema, projectPathSchema, projectSchema, screenshotSchema, userSchema, } from "./schemas.js";
3
+ import { createFrameSchema, createProjectFromBriefSchema, designIdSchema, fileListSchema, fileMutationSchema, fileSchema, fileTextSchema, frameNameSchema, frameSchema, generateImageFrameSchema, projectDirectoryPathSchema, projectNameSchema, projectPathSchema, projectSchema, screenshotSchema, userSchema, } from "./schemas.js";
4
4
  const projectInputSchema = z.object({ project: designIdSchema });
5
5
  const frameInputSchema = projectInputSchema.extend({ frame: designIdSchema });
6
6
  const fileInputSchema = projectInputSchema.extend({ path: projectPathSchema });
@@ -28,6 +28,10 @@ export const contract = {
28
28
  })
29
29
  .input(projectInputSchema)
30
30
  .output(projectSchema),
31
+ rename: oc
32
+ .route({ method: "PATCH", path: "/projects/{project}" })
33
+ .input(projectInputSchema.extend({ name: projectNameSchema }))
34
+ .output(projectSchema),
31
35
  delete: oc
32
36
  .route({ method: "DELETE", path: "/projects/{project}" })
33
37
  .input(projectInputSchema)
@@ -42,6 +46,13 @@ export const contract = {
42
46
  .route({ method: "POST", path: "/projects/{project}/frames" })
43
47
  .input(createFrameSchema)
44
48
  .output(frameSchema),
49
+ generateImage: oc
50
+ .route({
51
+ method: "POST",
52
+ path: "/projects/{project}/images/generations",
53
+ })
54
+ .input(generateImageFrameSchema)
55
+ .output(frameSchema),
45
56
  rename: oc
46
57
  .route({ method: "PATCH", path: "/projects/{project}/frames/{frame}" })
47
58
  .input(frameInputSchema.extend({ name: frameNameSchema }))
@@ -1,6 +1,8 @@
1
1
  import { z } from "zod";
2
2
  export declare const MAX_FRAME_DIMENSION = 4096;
3
3
  export declare const MAX_FILE_LENGTH = 512000;
4
+ export declare const MAX_IMAGE_GENERATION_PROMPT_LENGTH = 2048;
5
+ export declare const MAX_IMAGE_GENERATION_REFERENCES = 4;
4
6
  export declare const designIdSchema: z.ZodString;
5
7
  export declare const projectNameSchema: z.ZodString;
6
8
  export declare const projectBriefSchema: z.ZodString;
@@ -62,6 +64,57 @@ export declare const gltsFrameSchema: z.ZodObject<{
62
64
  updatedAt: z.ZodString;
63
65
  type: z.ZodLiteral<"glts">;
64
66
  }, z.core.$strip>;
67
+ export declare const imageGenerationOperationSchema: z.ZodEnum<{
68
+ generate: "generate";
69
+ edit: "edit";
70
+ }>;
71
+ export declare const imageGenerationResultSchema: z.ZodEnum<{
72
+ replace: "replace";
73
+ new: "new";
74
+ }>;
75
+ export declare const imageGenerationReferenceSchema: z.ZodObject<{
76
+ frameId: z.ZodString;
77
+ frameUpdatedAt: z.ZodString;
78
+ }, z.core.$strip>;
79
+ export declare const IMAGE_GENERATION_PROVIDER = "fal-ai";
80
+ export declare const IMAGE_GENERATION_MODEL = "openai/gpt-image-2";
81
+ export declare const LEGACY_IMAGE_GENERATION_PROVIDER = "cloudflare-workers-ai";
82
+ export declare const LEGACY_IMAGE_GENERATION_MODEL = "@cf/black-forest-labs/flux-2-klein-4b";
83
+ export declare const imageGenerationProvenanceSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
84
+ kind: z.ZodLiteral<"generated">;
85
+ operation: z.ZodEnum<{
86
+ generate: "generate";
87
+ edit: "edit";
88
+ }>;
89
+ prompt: z.ZodString;
90
+ references: z.ZodArray<z.ZodObject<{
91
+ frameId: z.ZodString;
92
+ frameUpdatedAt: z.ZodString;
93
+ }, z.core.$strip>>;
94
+ result: z.ZodEnum<{
95
+ replace: "replace";
96
+ new: "new";
97
+ }>;
98
+ provider: z.ZodLiteral<"fal-ai">;
99
+ model: z.ZodLiteral<"openai/gpt-image-2">;
100
+ }, z.core.$strip>, z.ZodObject<{
101
+ kind: z.ZodLiteral<"generated">;
102
+ operation: z.ZodEnum<{
103
+ generate: "generate";
104
+ edit: "edit";
105
+ }>;
106
+ prompt: z.ZodString;
107
+ references: z.ZodArray<z.ZodObject<{
108
+ frameId: z.ZodString;
109
+ frameUpdatedAt: z.ZodString;
110
+ }, z.core.$strip>>;
111
+ result: z.ZodEnum<{
112
+ replace: "replace";
113
+ new: "new";
114
+ }>;
115
+ provider: z.ZodLiteral<"cloudflare-workers-ai">;
116
+ model: z.ZodLiteral<"@cf/black-forest-labs/flux-2-klein-4b">;
117
+ }, z.core.$strip>], "provider">;
65
118
  export declare const imageFrameSchema: z.ZodObject<{
66
119
  id: z.ZodString;
67
120
  projectId: z.ZodString;
@@ -75,6 +128,41 @@ export declare const imageFrameSchema: z.ZodObject<{
75
128
  updatedAt: z.ZodString;
76
129
  type: z.ZodLiteral<"image">;
77
130
  file: z.ZodString;
131
+ provenance: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
132
+ kind: z.ZodLiteral<"generated">;
133
+ operation: z.ZodEnum<{
134
+ generate: "generate";
135
+ edit: "edit";
136
+ }>;
137
+ prompt: z.ZodString;
138
+ references: z.ZodArray<z.ZodObject<{
139
+ frameId: z.ZodString;
140
+ frameUpdatedAt: z.ZodString;
141
+ }, z.core.$strip>>;
142
+ result: z.ZodEnum<{
143
+ replace: "replace";
144
+ new: "new";
145
+ }>;
146
+ provider: z.ZodLiteral<"fal-ai">;
147
+ model: z.ZodLiteral<"openai/gpt-image-2">;
148
+ }, z.core.$strip>, z.ZodObject<{
149
+ kind: z.ZodLiteral<"generated">;
150
+ operation: z.ZodEnum<{
151
+ generate: "generate";
152
+ edit: "edit";
153
+ }>;
154
+ prompt: z.ZodString;
155
+ references: z.ZodArray<z.ZodObject<{
156
+ frameId: z.ZodString;
157
+ frameUpdatedAt: z.ZodString;
158
+ }, z.core.$strip>>;
159
+ result: z.ZodEnum<{
160
+ replace: "replace";
161
+ new: "new";
162
+ }>;
163
+ provider: z.ZodLiteral<"cloudflare-workers-ai">;
164
+ model: z.ZodLiteral<"@cf/black-forest-labs/flux-2-klein-4b">;
165
+ }, z.core.$strip>], "provider">>;
78
166
  }, z.core.$strip>;
79
167
  export declare const marketFrameSchema: z.ZodObject<{
80
168
  id: z.ZodString;
@@ -115,6 +203,41 @@ export declare const frameSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
115
203
  updatedAt: z.ZodString;
116
204
  type: z.ZodLiteral<"image">;
117
205
  file: z.ZodString;
206
+ provenance: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
207
+ kind: z.ZodLiteral<"generated">;
208
+ operation: z.ZodEnum<{
209
+ generate: "generate";
210
+ edit: "edit";
211
+ }>;
212
+ prompt: z.ZodString;
213
+ references: z.ZodArray<z.ZodObject<{
214
+ frameId: z.ZodString;
215
+ frameUpdatedAt: z.ZodString;
216
+ }, z.core.$strip>>;
217
+ result: z.ZodEnum<{
218
+ replace: "replace";
219
+ new: "new";
220
+ }>;
221
+ provider: z.ZodLiteral<"fal-ai">;
222
+ model: z.ZodLiteral<"openai/gpt-image-2">;
223
+ }, z.core.$strip>, z.ZodObject<{
224
+ kind: z.ZodLiteral<"generated">;
225
+ operation: z.ZodEnum<{
226
+ generate: "generate";
227
+ edit: "edit";
228
+ }>;
229
+ prompt: z.ZodString;
230
+ references: z.ZodArray<z.ZodObject<{
231
+ frameId: z.ZodString;
232
+ frameUpdatedAt: z.ZodString;
233
+ }, z.core.$strip>>;
234
+ result: z.ZodEnum<{
235
+ replace: "replace";
236
+ new: "new";
237
+ }>;
238
+ provider: z.ZodLiteral<"cloudflare-workers-ai">;
239
+ model: z.ZodLiteral<"@cf/black-forest-labs/flux-2-klein-4b">;
240
+ }, z.core.$strip>], "provider">>;
118
241
  }, z.core.$strip>, z.ZodObject<{
119
242
  id: z.ZodString;
120
243
  projectId: z.ZodString;
@@ -177,6 +300,23 @@ export declare const createFrameSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
177
300
  type: z.ZodLiteral<"market">;
178
301
  asset: z.ZodString;
179
302
  }, z.core.$strict>], "type">;
303
+ export declare const generateImageFrameSchema: z.ZodObject<{
304
+ project: z.ZodString;
305
+ operation: z.ZodEnum<{
306
+ generate: "generate";
307
+ edit: "edit";
308
+ }>;
309
+ prompt: z.ZodString;
310
+ target: z.ZodOptional<z.ZodString>;
311
+ references: z.ZodDefault<z.ZodArray<z.ZodString>>;
312
+ result: z.ZodEnum<{
313
+ replace: "replace";
314
+ new: "new";
315
+ }>;
316
+ name: z.ZodOptional<z.ZodString>;
317
+ x: z.ZodOptional<z.ZodNumber>;
318
+ y: z.ZodOptional<z.ZodNumber>;
319
+ }, z.core.$strict>;
180
320
  export declare const fileListSchema: z.ZodObject<{
181
321
  paths: z.ZodArray<z.ZodString>;
182
322
  }, z.core.$strip>;
@@ -218,12 +358,16 @@ export type CreateProjectFromBrief = z.infer<typeof createProjectFromBriefSchema
218
358
  export type ProjectDerivationStatus = z.infer<typeof projectDerivationStatusSchema>;
219
359
  export type GltsFrame = z.infer<typeof gltsFrameSchema>;
220
360
  export type ImageFrame = z.infer<typeof imageFrameSchema>;
361
+ export type ImageGenerationOperation = z.infer<typeof imageGenerationOperationSchema>;
362
+ export type ImageGenerationResult = z.infer<typeof imageGenerationResultSchema>;
363
+ export type ImageGenerationProvenance = z.infer<typeof imageGenerationProvenanceSchema>;
221
364
  export type MarketFrame = z.infer<typeof marketFrameSchema>;
222
365
  export type Frame = z.infer<typeof frameSchema>;
223
366
  export type CreateGltsFrame = z.infer<typeof createGltsFrameSchema>;
224
367
  export type CreateImageFrame = z.infer<typeof createImageFrameSchema>;
225
368
  export type CreateMarketFrame = z.infer<typeof createMarketFrameSchema>;
226
369
  export type CreateFrame = z.infer<typeof createFrameSchema>;
370
+ export type GenerateImageFrame = z.infer<typeof generateImageFrameSchema>;
227
371
  export type FileList = z.infer<typeof fileListSchema>;
228
372
  export type TextFile = z.infer<typeof textFileSchema>;
229
373
  export type BinaryFile = z.infer<typeof binaryFileSchema>;
@@ -1,6 +1,8 @@
1
1
  import { z } from "zod";
2
2
  export const MAX_FRAME_DIMENSION = 4_096;
3
3
  export const MAX_FILE_LENGTH = 512_000;
4
+ export const MAX_IMAGE_GENERATION_PROMPT_LENGTH = 2_048;
5
+ export const MAX_IMAGE_GENERATION_REFERENCES = 4;
4
6
  export const designIdSchema = z
5
7
  .string()
6
8
  .regex(/^[a-z0-9]{14}$/, "IDs are 14 lowercase alphanumeric characters");
@@ -91,9 +93,39 @@ const frameBaseSchema = z.object({
91
93
  export const gltsFrameSchema = frameBaseSchema.extend({
92
94
  type: z.literal("glts"),
93
95
  });
96
+ export const imageGenerationOperationSchema = z.enum(["generate", "edit"]);
97
+ export const imageGenerationResultSchema = z.enum(["new", "replace"]);
98
+ export const imageGenerationReferenceSchema = z.object({
99
+ frameId: designIdSchema,
100
+ frameUpdatedAt: z.string().datetime(),
101
+ });
102
+ export const IMAGE_GENERATION_PROVIDER = "fal-ai";
103
+ export const IMAGE_GENERATION_MODEL = "openai/gpt-image-2";
104
+ export const LEGACY_IMAGE_GENERATION_PROVIDER = "cloudflare-workers-ai";
105
+ export const LEGACY_IMAGE_GENERATION_MODEL = "@cf/black-forest-labs/flux-2-klein-4b";
106
+ const imageGenerationProvenanceBaseSchema = z.object({
107
+ kind: z.literal("generated"),
108
+ operation: imageGenerationOperationSchema,
109
+ prompt: z.string().min(1).max(MAX_IMAGE_GENERATION_PROMPT_LENGTH),
110
+ references: z
111
+ .array(imageGenerationReferenceSchema)
112
+ .max(MAX_IMAGE_GENERATION_REFERENCES),
113
+ result: imageGenerationResultSchema,
114
+ });
115
+ export const imageGenerationProvenanceSchema = z.discriminatedUnion("provider", [
116
+ imageGenerationProvenanceBaseSchema.extend({
117
+ provider: z.literal(IMAGE_GENERATION_PROVIDER),
118
+ model: z.literal(IMAGE_GENERATION_MODEL),
119
+ }),
120
+ imageGenerationProvenanceBaseSchema.extend({
121
+ provider: z.literal(LEGACY_IMAGE_GENERATION_PROVIDER),
122
+ model: z.literal(LEGACY_IMAGE_GENERATION_MODEL),
123
+ }),
124
+ ]);
94
125
  export const imageFrameSchema = frameBaseSchema.extend({
95
126
  type: z.literal("image"),
96
127
  file: projectPathSchema,
128
+ provenance: imageGenerationProvenanceSchema.optional(),
97
129
  });
98
130
  export const marketFrameSchema = frameBaseSchema.extend({
99
131
  type: z.literal("market"),
@@ -137,6 +169,85 @@ export const createFrameSchema = z.discriminatedUnion("type", [
137
169
  createImageFrameSchema,
138
170
  createMarketFrameSchema,
139
171
  ]);
172
+ export const generateImageFrameSchema = z
173
+ .object({
174
+ project: designIdSchema,
175
+ operation: imageGenerationOperationSchema,
176
+ prompt: z.string().trim().min(1).max(MAX_IMAGE_GENERATION_PROMPT_LENGTH),
177
+ target: designIdSchema.optional(),
178
+ references: z
179
+ .array(designIdSchema)
180
+ .max(MAX_IMAGE_GENERATION_REFERENCES)
181
+ .default([]),
182
+ result: imageGenerationResultSchema,
183
+ name: frameNameSchema.optional(),
184
+ x: framePositionSchema.optional(),
185
+ y: framePositionSchema.optional(),
186
+ })
187
+ .strict()
188
+ .superRefine((input, context) => {
189
+ const orderedReferences = [
190
+ ...(input.target ? [input.target] : []),
191
+ ...input.references,
192
+ ];
193
+ if (new Set(orderedReferences).size !== orderedReferences.length) {
194
+ context.addIssue({
195
+ code: "custom",
196
+ path: ["references"],
197
+ message: "Image references must be unique",
198
+ });
199
+ }
200
+ if (orderedReferences.length > MAX_IMAGE_GENERATION_REFERENCES) {
201
+ context.addIssue({
202
+ code: "custom",
203
+ path: ["references"],
204
+ message: `Image generation supports at most ${MAX_IMAGE_GENERATION_REFERENCES} references`,
205
+ });
206
+ }
207
+ if (input.operation === "generate" && input.target) {
208
+ context.addIssue({
209
+ code: "custom",
210
+ path: ["target"],
211
+ message: "A generation request cannot have an edit target",
212
+ });
213
+ }
214
+ if (input.operation === "edit" && !input.target) {
215
+ context.addIssue({
216
+ code: "custom",
217
+ path: ["target"],
218
+ message: "An edit request requires an image target",
219
+ });
220
+ }
221
+ if (input.result === "replace" && input.operation !== "edit") {
222
+ context.addIssue({
223
+ code: "custom",
224
+ path: ["result"],
225
+ message: "Only an image edit can replace a frame",
226
+ });
227
+ }
228
+ if (input.result === "new" && !input.name) {
229
+ context.addIssue({
230
+ code: "custom",
231
+ path: ["name"],
232
+ message: "A new generated frame requires a name",
233
+ });
234
+ }
235
+ if (input.result === "replace" && input.name) {
236
+ context.addIssue({
237
+ code: "custom",
238
+ path: ["name"],
239
+ message: "A replacement keeps the target frame name",
240
+ });
241
+ }
242
+ if (input.result === "replace" &&
243
+ (input.x !== undefined || input.y !== undefined)) {
244
+ context.addIssue({
245
+ code: "custom",
246
+ path: [input.x !== undefined ? "x" : "y"],
247
+ message: "A replacement keeps the target frame position",
248
+ });
249
+ }
250
+ });
140
251
  export const fileListSchema = z.object({
141
252
  paths: z.array(projectPathSchema),
142
253
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drawcall/design",
3
- "version": "0.3.0",
3
+ "version": "0.4.1",
4
4
  "description": "Typed API and remote CLI for Drawcall Design",
5
5
  "repository": {
6
6
  "type": "git",