@drawcall/design 0.8.0 → 0.9.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.
@@ -0,0 +1,17 @@
1
+ import { getCliClient } from "../cli-client.js";
2
+ import { apiOption } from "../options.js";
3
+ import { designIdSchema } from "../v1/schemas.js";
4
+ export function clientFor(command) {
5
+ return getCliClient(apiOption(command));
6
+ }
7
+ export function projectId(command) {
8
+ const value = command.optsWithGlobals().project;
9
+ if (typeof value !== "string") {
10
+ throw new Error("Select a project with -p, --project <project-id>.");
11
+ }
12
+ return designIdSchema.parse(value);
13
+ }
14
+ export function requireConfirmation(confirmed) {
15
+ if (!confirmed)
16
+ throw new Error("Destructive commands require --yes.");
17
+ }
@@ -0,0 +1,2 @@
1
+ import type { Command } from "commander";
2
+ export declare function registerFilesystemCommands(program: Command): void;
@@ -0,0 +1,80 @@
1
+ import { clientFor, projectId, requireConfirmation } from "./context.js";
2
+ export function registerFilesystemCommands(program) {
3
+ program
4
+ .command("ls")
5
+ .description("List paths in the selected project filesystem")
6
+ .argument("[path]", "Absolute directory path", "/")
7
+ .action(async (path, _options, command) => {
8
+ const client = await clientFor(command);
9
+ const result = await client.filesystem.list({
10
+ project: projectId(command),
11
+ path,
12
+ });
13
+ for (const item of result.paths)
14
+ console.log(item);
15
+ });
16
+ program
17
+ .command("read")
18
+ .description("Read a project file")
19
+ .argument("<path>", "Absolute project path")
20
+ .action(async (path, _options, command) => {
21
+ const client = await clientFor(command);
22
+ const file = await client.filesystem.read({
23
+ project: projectId(command),
24
+ path,
25
+ });
26
+ if (file.type === "text") {
27
+ process.stdout.write(file.text);
28
+ return;
29
+ }
30
+ console.log(file.url);
31
+ });
32
+ program
33
+ .command("write")
34
+ .description("Create or overwrite a text project file")
35
+ .argument("<path>", "Absolute project path")
36
+ .argument("[text]", "Inline text; omit or use - to read stdin")
37
+ .action(async (path, text, _options, command) => {
38
+ const client = await clientFor(command);
39
+ await client.filesystem.write({
40
+ project: projectId(command),
41
+ path,
42
+ text: text === undefined || text === "-" ? await readStdin() : text,
43
+ });
44
+ console.log(`Wrote ${path}.`);
45
+ });
46
+ program
47
+ .command("edit")
48
+ .description("Replace text that occurs exactly once in a project file")
49
+ .argument("<path>", "Absolute project path")
50
+ .argument("<old-text>", "Text that must occur exactly once")
51
+ .argument("<new-text>", "Replacement text")
52
+ .action(async (path, oldText, newText, _options, command) => {
53
+ const client = await clientFor(command);
54
+ await client.filesystem.edit({
55
+ project: projectId(command),
56
+ path,
57
+ oldText,
58
+ newText,
59
+ });
60
+ console.log(`Edited ${path}.`);
61
+ });
62
+ program
63
+ .command("delete")
64
+ .description("Delete a project file")
65
+ .argument("<path>", "Absolute project path")
66
+ .option("-y, --yes", "Confirm deletion", false)
67
+ .action(async (path, options, command) => {
68
+ requireConfirmation(options.yes);
69
+ const client = await clientFor(command);
70
+ await client.filesystem.delete({ project: projectId(command), path });
71
+ console.log(`Deleted ${path}.`);
72
+ });
73
+ }
74
+ async function readStdin() {
75
+ const chunks = [];
76
+ for await (const chunk of process.stdin) {
77
+ chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
78
+ }
79
+ return Buffer.concat(chunks).toString("utf8");
80
+ }
@@ -0,0 +1,2 @@
1
+ import type { Command } from "commander";
2
+ export declare function registerFrameCommands(program: Command): void;
@@ -0,0 +1,127 @@
1
+ import { readImageInput } from "../image.js";
2
+ import { parseFrameSize } from "../target.js";
3
+ import { designIdSchema, marketAssetSchema, } from "../v1/schemas.js";
4
+ import { clientFor, projectId, requireConfirmation } from "./context.js";
5
+ import { registerImageCommands } from "./image.js";
6
+ export function registerFrameCommands(program) {
7
+ const frame = program.command("frame").description("Manage frames");
8
+ frame
9
+ .command("list")
10
+ .description("List frames in the selected project")
11
+ .action(async (_options, command) => {
12
+ const client = await clientFor(command);
13
+ const frames = await client.frame.list({ project: projectId(command) });
14
+ if (frames.length === 0) {
15
+ console.log("No frames.");
16
+ return;
17
+ }
18
+ for (const item of frames) {
19
+ console.log(`${item.id}\t${item.name}\t${item.type}\t${item.width}x${item.height}`);
20
+ }
21
+ });
22
+ frame
23
+ .command("create")
24
+ .description("Create a GLTS, image, or pinned Market frame")
25
+ .argument("<name>", "Frame name")
26
+ .requiredOption("-t, --type <type>", "glts, image, or market")
27
+ .option("-s, --size <width>x<height>", "GLTS viewport size")
28
+ .option("--image <url-or-path>", "Image URL or local PNG, JPEG, or WebP")
29
+ .option("--asset <name@version>", "Exact public Market asset version")
30
+ .action(async (name, options, command) => {
31
+ const project = projectId(command);
32
+ const input = await createFrameInput(project, name, options);
33
+ const client = await clientFor(command);
34
+ const created = await client.frame.create(input);
35
+ console.log(`Created ${created.id}\t${created.name}\t${created.type}`);
36
+ console.log(`Path /${created.id}/`);
37
+ });
38
+ frame
39
+ .command("rename")
40
+ .description("Rename a frame")
41
+ .argument("<frame-id>", "Frame ID")
42
+ .argument("<name>", "New frame name")
43
+ .action(async (frameId, name, _options, command) => {
44
+ const id = designIdSchema.parse(frameId);
45
+ const client = await clientFor(command);
46
+ const renamed = await client.frame.rename({
47
+ project: projectId(command),
48
+ frame: id,
49
+ name,
50
+ });
51
+ console.log(`Renamed ${renamed.id}\t${renamed.name}.`);
52
+ });
53
+ frame
54
+ .command("delete")
55
+ .description("Delete frames")
56
+ .argument("<frame-id...>", "Frame IDs")
57
+ .option("-y, --yes", "Confirm deletion", false)
58
+ .action(async (frameIds, options, command) => {
59
+ requireConfirmation(options.yes);
60
+ const project = projectId(command);
61
+ const client = await clientFor(command);
62
+ for (const frameId of frameIds) {
63
+ const id = designIdSchema.parse(frameId);
64
+ await client.frame.delete({ project, frame: id });
65
+ console.log(`Deleted ${id}.`);
66
+ }
67
+ });
68
+ frame
69
+ .command("screenshot")
70
+ .description("Render frames and print their screenshot URLs")
71
+ .argument("<frame-id...>", "Frame IDs")
72
+ .action(async (frameIds, _options, command) => {
73
+ const project = projectId(command);
74
+ const client = await clientFor(command);
75
+ for (const frameId of frameIds) {
76
+ const id = designIdSchema.parse(frameId);
77
+ const result = await client.frame.screenshot({ project, frame: id });
78
+ console.log(`${id}\t${result.url}`);
79
+ }
80
+ });
81
+ registerImageCommands(frame);
82
+ }
83
+ async function createFrameInput(project, name, options) {
84
+ if (options.type === "glts") {
85
+ if (options.image !== undefined || options.asset !== undefined) {
86
+ throw new Error("GLTS frames do not accept --image or --asset");
87
+ }
88
+ if (options.size === undefined) {
89
+ throw new Error("GLTS frames require --size <width>x<height>");
90
+ }
91
+ return {
92
+ project,
93
+ name,
94
+ type: "glts",
95
+ ...parseFrameSize(options.size),
96
+ };
97
+ }
98
+ if (options.type === "image") {
99
+ if (options.size !== undefined || options.asset !== undefined) {
100
+ throw new Error("Image frames do not accept --size or --asset");
101
+ }
102
+ if (options.image === undefined) {
103
+ throw new Error("Image frames require --image");
104
+ }
105
+ return {
106
+ project,
107
+ name,
108
+ type: "image",
109
+ image: await readImageInput(options.image),
110
+ };
111
+ }
112
+ if (options.type === "market") {
113
+ if (options.size !== undefined || options.image !== undefined) {
114
+ throw new Error("Market frames do not accept --size or --image");
115
+ }
116
+ if (options.asset === undefined) {
117
+ throw new Error("Market frames require --asset");
118
+ }
119
+ return {
120
+ project,
121
+ name,
122
+ type: "market",
123
+ asset: marketAssetSchema.parse(options.asset),
124
+ };
125
+ }
126
+ throw new Error("--type must be glts, image, or market");
127
+ }
@@ -0,0 +1,2 @@
1
+ import { Command } from "commander";
2
+ export declare function registerImageCommands(frame: Command): void;
@@ -0,0 +1,69 @@
1
+ import { Command, Option } from "commander";
2
+ import { readImageInput } from "../image.js";
3
+ import { designIdSchema, generateImageSchema, } from "../v1/schemas.js";
4
+ import { clientFor, projectId } from "./context.js";
5
+ export function registerImageCommands(frame) {
6
+ frame
7
+ .command("generate-image")
8
+ .description("Generate a new image frame")
9
+ .argument("<name>", "New frame name")
10
+ .requiredOption("--prompt <text>", "Image generation prompt")
11
+ .option("--reference <url-or-path>", "Reference image URL or local PNG, JPEG, or WebP; repeat to preserve order", collect, [])
12
+ .action(async (name, options, command) => {
13
+ const input = await resolveImageReferences({
14
+ project: projectId(command),
15
+ operation: "generate",
16
+ prompt: options.prompt,
17
+ references: options.reference,
18
+ result: "new",
19
+ name,
20
+ });
21
+ const client = await clientFor(command);
22
+ printGeneratedFrame(await client.frame.generateImage(input));
23
+ });
24
+ frame
25
+ .command("edit-image")
26
+ .description("Edit an image frame")
27
+ .argument("<target>", "Image frame ID")
28
+ .requiredOption("--prompt <text>", "Image edit prompt")
29
+ .addOption(new Option("--replace", "Replace the target image frame").conflicts("name"))
30
+ .addOption(new Option("--name <new>", "Create the edit as a new image frame").conflicts("replace"))
31
+ .option("--reference <url-or-path>", "Additional image URL or local PNG, JPEG, or WebP; repeat to preserve order", collect, [])
32
+ .action(async (target, options, command) => {
33
+ const input = await resolveImageReferences({
34
+ project: projectId(command),
35
+ operation: "edit",
36
+ prompt: options.prompt,
37
+ target: designIdSchema.parse(target),
38
+ references: options.reference,
39
+ ...editOutput(options),
40
+ });
41
+ const client = await clientFor(command);
42
+ printGeneratedFrame(await client.frame.generateImage(input));
43
+ });
44
+ }
45
+ async function resolveImageReferences(input) {
46
+ const maximum = input.operation === "edit" ? 3 : 4;
47
+ if (input.references.length > maximum) {
48
+ throw new Error(`${input.operation === "edit" ? "Image editing" : "Image generation"} supports at most ${maximum} --reference values.`);
49
+ }
50
+ return generateImageSchema.parse({
51
+ ...input,
52
+ references: await Promise.all(input.references.map(readImageInput)),
53
+ });
54
+ }
55
+ function editOutput(options) {
56
+ if (options.replace)
57
+ return { result: "replace" };
58
+ if (options.name !== undefined) {
59
+ return { result: "new", name: options.name };
60
+ }
61
+ throw new Error("Choose exactly one of --replace or --name <new>.");
62
+ }
63
+ function collect(value, previous) {
64
+ return [...previous, value];
65
+ }
66
+ function printGeneratedFrame(frame) {
67
+ console.log(`Generated ${frame.id}\t${frame.name}\timage`);
68
+ console.log(`Path /${frame.id}/`);
69
+ }
@@ -0,0 +1,2 @@
1
+ import type { Command } from "commander";
2
+ export declare function registerProjectCommands(program: Command): void;
@@ -0,0 +1,39 @@
1
+ import { designIdSchema } from "../v1/schemas.js";
2
+ import { clientFor, requireConfirmation } from "./context.js";
3
+ export function registerProjectCommands(program) {
4
+ const project = program.command("project").description("Manage projects");
5
+ project
6
+ .command("list")
7
+ .description("List projects")
8
+ .action(async (_options, command) => {
9
+ const client = await clientFor(command);
10
+ const projects = await client.project.list();
11
+ if (projects.length === 0) {
12
+ console.log("No projects.");
13
+ return;
14
+ }
15
+ for (const item of projects)
16
+ console.log(`${item.id}\t${item.name}`);
17
+ });
18
+ project
19
+ .command("create")
20
+ .description("Create a project")
21
+ .argument("<name>", "Project name")
22
+ .action(async (name, _options, command) => {
23
+ const client = await clientFor(command);
24
+ const created = await client.project.create({ name });
25
+ console.log(`Created ${created.id}\t${created.name}`);
26
+ });
27
+ project
28
+ .command("delete")
29
+ .description("Delete a project")
30
+ .argument("<project-id>", "Project ID")
31
+ .option("-y, --yes", "Confirm deletion", false)
32
+ .action(async (projectId, options, command) => {
33
+ requireConfirmation(options.yes);
34
+ const id = designIdSchema.parse(projectId);
35
+ const client = await clientFor(command);
36
+ await client.project.delete({ project: id });
37
+ console.log(`Deleted ${id}.`);
38
+ });
39
+ }
package/dist/command.js CHANGED
@@ -1,11 +1,9 @@
1
1
  import { createRequire } from "node:module";
2
2
  import { Command, Option } from "commander";
3
- import { getCliClient } from "./cli-client.js";
4
- import { readImageInput } from "./image.js";
5
- import { apiOption } from "./options.js";
3
+ import { registerFilesystemCommands } from "./command/filesystem.js";
4
+ import { registerFrameCommands } from "./command/frame.js";
5
+ import { registerProjectCommands } from "./command/project.js";
6
6
  import { cliDesignSkill } from "./skill.generated.js";
7
- import { parseFrameSize } from "./target.js";
8
- import { designIdSchema, marketAssetSchema } from "./v1/schemas.js";
9
7
  export function createDesignCommand(options = {}) {
10
8
  const program = new Command()
11
9
  .name(options.name ?? "design")
@@ -19,251 +17,11 @@ export function createDesignCommand(options = {}) {
19
17
  .action(() => {
20
18
  process.stdout.write(cliDesignSkill);
21
19
  });
22
- const project = program.command("project").description("Manage projects");
23
- project
24
- .command("list")
25
- .description("List projects")
26
- .action(async (_options, command) => {
27
- const client = await clientFor(command);
28
- const projects = await client.project.list();
29
- if (projects.length === 0) {
30
- console.log("No projects.");
31
- return;
32
- }
33
- for (const item of projects)
34
- console.log(`${item.id}\t${item.name}`);
35
- });
36
- project
37
- .command("create")
38
- .description("Create a project")
39
- .argument("<name>", "Project name")
40
- .action(async (name, _options, command) => {
41
- const client = await clientFor(command);
42
- const created = await client.project.create({ name });
43
- console.log(`Created ${created.id}\t${created.name}`);
44
- });
45
- project
46
- .command("delete")
47
- .description("Delete a project")
48
- .argument("<project-id>", "Project ID")
49
- .option("-y, --yes", "Confirm deletion", false)
50
- .action(async (projectId, options, command) => {
51
- requireConfirmation(options.yes);
52
- const id = designIdSchema.parse(projectId);
53
- const client = await clientFor(command);
54
- await client.project.delete({ project: id });
55
- console.log(`Deleted ${id}.`);
56
- });
57
- const frame = program.command("frame").description("Manage frames");
58
- frame
59
- .command("list")
60
- .description("List frames in the selected project")
61
- .action(async (_options, command) => {
62
- const client = await clientFor(command);
63
- const frames = await client.frame.list({ project: projectId(command) });
64
- if (frames.length === 0) {
65
- console.log("No frames.");
66
- return;
67
- }
68
- for (const item of frames) {
69
- console.log(`${item.id}\t${item.name}\t${item.type}\t${item.width}x${item.height}`);
70
- }
71
- });
72
- frame
73
- .command("create")
74
- .description("Create a GLTS, image, or pinned Market frame")
75
- .argument("<name>", "Frame name")
76
- .requiredOption("-t, --type <type>", "glts, image, or market")
77
- .option("-s, --size <width>x<height>", "GLTS viewport size")
78
- .option("--image <url-or-path>", "Image URL or local PNG, JPEG, or WebP")
79
- .option("--asset <name@version>", "Exact public Market asset version")
80
- .action(async (name, options, command) => {
81
- const project = projectId(command);
82
- const input = await createFrameInput(project, name, options);
83
- const client = await clientFor(command);
84
- const created = await client.frame.create(input);
85
- console.log(`Created ${created.id}\t${created.name}\t${created.type}`);
86
- console.log(`Path /${created.id}/`);
87
- });
88
- frame
89
- .command("rename")
90
- .description("Rename a frame")
91
- .argument("<frame-id>", "Frame ID")
92
- .argument("<name>", "New frame name")
93
- .action(async (frameId, name, _options, command) => {
94
- const id = designIdSchema.parse(frameId);
95
- const client = await clientFor(command);
96
- const renamed = await client.frame.rename({
97
- project: projectId(command),
98
- frame: id,
99
- name,
100
- });
101
- console.log(`Renamed ${renamed.id}\t${renamed.name}.`);
102
- });
103
- frame
104
- .command("delete")
105
- .description("Delete frames")
106
- .argument("<frame-id...>", "Frame IDs")
107
- .option("-y, --yes", "Confirm deletion", false)
108
- .action(async (frameIds, options, command) => {
109
- requireConfirmation(options.yes);
110
- const project = projectId(command);
111
- const client = await clientFor(command);
112
- for (const frameId of frameIds) {
113
- const id = designIdSchema.parse(frameId);
114
- await client.frame.delete({ project, frame: id });
115
- console.log(`Deleted ${id}.`);
116
- }
117
- });
118
- frame
119
- .command("screenshot")
120
- .description("Render frames and print their screenshot URLs")
121
- .argument("<frame-id...>", "Frame IDs")
122
- .action(async (frameIds, _options, command) => {
123
- const project = projectId(command);
124
- const client = await clientFor(command);
125
- for (const frameId of frameIds) {
126
- const id = designIdSchema.parse(frameId);
127
- const result = await client.frame.screenshot({ project, frame: id });
128
- console.log(`${id}\t${result.url}`);
129
- }
130
- });
131
- program
132
- .command("ls")
133
- .description("List paths in the selected project filesystem")
134
- .argument("[path]", "Absolute directory path", "/")
135
- .action(async (path, _options, command) => {
136
- const client = await clientFor(command);
137
- const result = await client.filesystem.list({
138
- project: projectId(command),
139
- path,
140
- });
141
- for (const item of result.paths)
142
- console.log(item);
143
- });
144
- program
145
- .command("read")
146
- .description("Read a project file")
147
- .argument("<path>", "Absolute project path")
148
- .action(async (path, _options, command) => {
149
- const client = await clientFor(command);
150
- const file = await client.filesystem.read({
151
- project: projectId(command),
152
- path,
153
- });
154
- if (file.type === "text") {
155
- process.stdout.write(file.text);
156
- return;
157
- }
158
- console.log(file.url);
159
- });
160
- program
161
- .command("write")
162
- .description("Create or overwrite a text project file")
163
- .argument("<path>", "Absolute project path")
164
- .argument("[text]", "Inline text; omit or use - to read stdin")
165
- .action(async (path, text, _options, command) => {
166
- const client = await clientFor(command);
167
- await client.filesystem.write({
168
- project: projectId(command),
169
- path,
170
- text: text === undefined || text === "-" ? await readStdin() : text,
171
- });
172
- console.log(`Wrote ${path}.`);
173
- });
174
- program
175
- .command("edit")
176
- .description("Replace text that occurs exactly once in a project file")
177
- .argument("<path>", "Absolute project path")
178
- .argument("<old-text>", "Text that must occur exactly once")
179
- .argument("<new-text>", "Replacement text")
180
- .action(async (path, oldText, newText, _options, command) => {
181
- const client = await clientFor(command);
182
- await client.filesystem.edit({
183
- project: projectId(command),
184
- path,
185
- oldText,
186
- newText,
187
- });
188
- console.log(`Edited ${path}.`);
189
- });
190
- program
191
- .command("delete")
192
- .description("Delete a project file")
193
- .argument("<path>", "Absolute project path")
194
- .option("-y, --yes", "Confirm deletion", false)
195
- .action(async (path, options, command) => {
196
- requireConfirmation(options.yes);
197
- const client = await clientFor(command);
198
- await client.filesystem.delete({ project: projectId(command), path });
199
- console.log(`Deleted ${path}.`);
200
- });
20
+ registerProjectCommands(program);
21
+ registerFrameCommands(program);
22
+ registerFilesystemCommands(program);
201
23
  return program;
202
24
  }
203
- async function createFrameInput(project, name, options) {
204
- if (options.type === "glts") {
205
- if (options.image !== undefined || options.asset !== undefined) {
206
- throw new Error("GLTS frames do not accept --image or --asset");
207
- }
208
- if (options.size === undefined) {
209
- throw new Error("GLTS frames require --size <width>x<height>");
210
- }
211
- return {
212
- project,
213
- name,
214
- type: "glts",
215
- ...parseFrameSize(options.size),
216
- };
217
- }
218
- if (options.type === "image") {
219
- if (options.size !== undefined || options.asset !== undefined) {
220
- throw new Error("Image frames do not accept --size or --asset");
221
- }
222
- if (options.image === undefined)
223
- throw new Error("Image frames require --image");
224
- return {
225
- project,
226
- name,
227
- type: "image",
228
- image: await readImageInput(options.image),
229
- };
230
- }
231
- if (options.type === "market") {
232
- if (options.size !== undefined || options.image !== undefined) {
233
- throw new Error("Market frames do not accept --size or --image");
234
- }
235
- if (options.asset === undefined)
236
- throw new Error("Market frames require --asset");
237
- return {
238
- project,
239
- name,
240
- type: "market",
241
- asset: marketAssetSchema.parse(options.asset),
242
- };
243
- }
244
- throw new Error("--type must be glts, image, or market");
245
- }
246
- async function clientFor(command) {
247
- return getCliClient(apiOption(command));
248
- }
249
- function projectId(command) {
250
- const value = command.optsWithGlobals().project;
251
- if (typeof value !== "string") {
252
- throw new Error("Select a project with -p, --project <project-id>.");
253
- }
254
- return designIdSchema.parse(value);
255
- }
256
- function requireConfirmation(confirmed) {
257
- if (!confirmed)
258
- throw new Error("Destructive commands require --yes.");
259
- }
260
- async function readStdin() {
261
- const chunks = [];
262
- for await (const chunk of process.stdin) {
263
- chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
264
- }
265
- return Buffer.concat(chunks).toString("utf8");
266
- }
267
25
  function readPackageVersion() {
268
26
  const manifest = createRequire(import.meta.url)("../package.json");
269
27
  if (!manifest ||
@@ -0,0 +1 @@
1
+ export declare function frameImageUrl(viewUrl: string, frameId: string): string;
@@ -0,0 +1,6 @@
1
+ import { designIdSchema, httpUrlSchema } from "./v1/schemas.js";
2
+ export function frameImageUrl(viewUrl, frameId) {
3
+ const view = new URL(httpUrlSchema.parse(viewUrl));
4
+ const id = designIdSchema.parse(frameId);
5
+ return new URL(`/${id}.webp`, view.origin).href;
6
+ }
package/dist/image.d.ts CHANGED
@@ -1 +1,2 @@
1
- export declare function readImageInput(value: string): Promise<File | string>;
1
+ import { type ImageInput } from "./v1/schemas.js";
2
+ export declare function readImageInput(value: string): Promise<ImageInput>;
package/dist/image.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { readFile } from "node:fs/promises";
2
2
  import { basename, extname } from "node:path";
3
- import { imageUrlSchema } from "./v1/schemas.js";
3
+ import { imageInputSchema, imageUrlSchema, } from "./v1/schemas.js";
4
4
  export async function readImageInput(value) {
5
5
  if (/^https?:/i.test(value) || value.includes("://")) {
6
6
  return imageUrlSchema.parse(value);
@@ -10,9 +10,7 @@ export async function readImageInput(value) {
10
10
  if (mediaType === undefined) {
11
11
  throw new Error("Local images must be PNG, JPEG, or WebP files");
12
12
  }
13
- return new File([await readFile(value)], basename(value), {
14
- type: mediaType,
15
- });
13
+ return imageInputSchema.parse(new File([await readFile(value)], basename(value), { type: mediaType }));
16
14
  }
17
15
  function mediaTypeForExtension(extension) {
18
16
  if (extension === ".jpeg" || extension === ".jpg")