@drawcall/design 0.5.11 → 0.6.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.
package/README.md CHANGED
@@ -40,23 +40,19 @@ The Commander implementation is available for aggregate CLIs:
40
40
  ```ts
41
41
  import { createDesignCommand } from "@drawcall/design";
42
42
 
43
- program.addCommand(createDesignCommand({ includeAuthCommands: false }));
43
+ program.addCommand(createDesignCommand());
44
44
  ```
45
45
 
46
46
  The MCP tools can be mounted into a server owned by another package:
47
47
 
48
48
  ```ts
49
- import {
50
- createDesignMcpOperations,
51
- registerDesignTools,
52
- v1,
53
- } from "@drawcall/design";
49
+ import { registerDesignTools, v1 } from "@drawcall/design";
54
50
  import { McpServer } from "@modelcontextprotocol/server";
55
51
 
56
52
  const client = v1.createClient({ authToken: process.env.DRAWCALL_AUTH_TOKEN });
57
53
  const server = new McpServer({ name: "mcp.drawcall.ai", version: "1.0.0" });
58
54
 
59
- registerDesignTools(server, createDesignMcpOperations(client));
55
+ registerDesignTools(server, client);
60
56
  ```
61
57
 
62
58
  The host owns the server identity, authentication, and transport. The MCP SDK
package/dist/auth.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ export declare function createLoginCommand(): Command;
3
+ export declare function createLogoutCommand(): Command;
package/dist/auth.js ADDED
@@ -0,0 +1,29 @@
1
+ import { getConfigPath as getAuthConfigPath, runDeviceLogin, saveAuthToken, signOut, } from "@drawcall/auth";
2
+ import { Command } from "commander";
3
+ import { clearConfig, saveConfig } from "./config.js";
4
+ import { apiOption } from "./options.js";
5
+ import { createClient, DEFAULT_BASE_URL } from "./v1/client.js";
6
+ export function createLoginCommand() {
7
+ return new Command("login")
8
+ .description("Sign in with your Drawcall account")
9
+ .action(async (_options, command) => {
10
+ const baseUrlOverride = apiOption(command);
11
+ const baseUrl = baseUrlOverride ?? DEFAULT_BASE_URL;
12
+ const token = await runDeviceLogin();
13
+ const client = createClient({ baseUrl, authToken: token });
14
+ const user = await client.user.me();
15
+ if (baseUrlOverride)
16
+ await saveConfig({ baseUrl });
17
+ else
18
+ await clearConfig();
19
+ await saveAuthToken(token);
20
+ console.log(`Signed in as ${user.email}. Credentials saved to ${getAuthConfigPath()}.`);
21
+ });
22
+ }
23
+ export function createLogoutCommand() {
24
+ return new Command("logout").description("Sign out").action(async () => {
25
+ const authExisted = await signOut();
26
+ const configExisted = await clearConfig();
27
+ console.log(authExisted || configExisted ? "Signed out." : "Already signed out.");
28
+ });
29
+ }
package/dist/browser.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  export * as v1 from "./v1/index.js";
2
- export { createDesignMcpOperations, registerDesignTools, type DesignMcpOperationRunner, type DesignMcpOperations, type DesignMcpServer, type DesignMcpScreenshot, type DesignMcpToolResult, } from "./mcp/index.js";
2
+ export { registerDesignTools, type DesignMcpOptions, type DesignMcpServer, type DesignMcpToolResult, } from "./mcp/index.js";
3
3
  export { cliDesignSkill, mcpDesignSkill } from "./skill.generated.js";
4
4
  export { frameCreationCapabilities, type FrameCreationCapability, type FrameCreationCapabilityId, type FrameCreationInput, } from "./v1/capabilities.js";
5
5
  export { cameraPoseSchema, IMAGE_GENERATION_MODEL, IMAGE_GENERATION_PROVIDER, } from "./v1/schemas.js";
package/dist/browser.js CHANGED
@@ -1,5 +1,5 @@
1
1
  export * as v1 from "./v1/index.js";
2
- export { createDesignMcpOperations, registerDesignTools, } from "./mcp/index.js";
2
+ export { registerDesignTools, } from "./mcp/index.js";
3
3
  export { cliDesignSkill, mcpDesignSkill } from "./skill.generated.js";
4
4
  export { frameCreationCapabilities, } from "./v1/capabilities.js";
5
5
  export { cameraPoseSchema, IMAGE_GENERATION_MODEL, IMAGE_GENERATION_PROVIDER, } from "./v1/schemas.js";
package/dist/cli.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
- import { createDesignCommand } from "./command.js";
3
- const program = createDesignCommand();
2
+ import { createDesignCli } from "./standalone.js";
3
+ const program = createDesignCli();
4
4
  if (process.argv.length <= 2) {
5
5
  program.outputHelp();
6
6
  }
package/dist/command.d.ts CHANGED
@@ -2,6 +2,5 @@ import { Command } from "commander";
2
2
  export interface DesignCommandOptions {
3
3
  name?: string;
4
4
  version?: string;
5
- includeAuthCommands?: boolean;
6
5
  }
7
6
  export declare function createDesignCommand(options?: DesignCommandOptions): Command;
package/dist/command.js CHANGED
@@ -1,12 +1,10 @@
1
1
  import { createRequire } from "node:module";
2
- import { getConfigPath as getAuthConfigPath, runDeviceLogin, saveAuthToken, signOut, } from "@drawcall/auth";
3
2
  import { Command, Option } from "commander";
4
- import { clearConfig, saveConfig } from "./config.js";
5
3
  import { getCliClient } from "./cli-client.js";
6
4
  import { readImageInput } from "./image.js";
5
+ import { apiOption } from "./options.js";
7
6
  import { cliDesignSkill } from "./skill.generated.js";
8
7
  import { parseFrameSize } from "./target.js";
9
- import { createClient, DEFAULT_BASE_URL } from "./v1/client.js";
10
8
  import { designIdSchema, marketAssetSchema } from "./v1/schemas.js";
11
9
  export function createDesignCommand(options = {}) {
12
10
  const program = new Command()
@@ -21,8 +19,6 @@ export function createDesignCommand(options = {}) {
21
19
  .action(() => {
22
20
  process.stdout.write(cliDesignSkill);
23
21
  });
24
- if (options.includeAuthCommands ?? true)
25
- addAuthCommands(program);
26
22
  const project = program.command("project").description("Manage projects");
27
23
  project
28
24
  .command("list")
@@ -204,32 +200,6 @@ export function createDesignCommand(options = {}) {
204
200
  });
205
201
  return program;
206
202
  }
207
- function addAuthCommands(program) {
208
- program
209
- .command("login")
210
- .description("Sign in with your Drawcall account")
211
- .action(async (_options, command) => {
212
- const baseUrlOverride = apiOption(command);
213
- const baseUrl = baseUrlOverride ?? DEFAULT_BASE_URL;
214
- const token = await runDeviceLogin();
215
- const client = createClient({ baseUrl, authToken: token });
216
- const user = await client.user.me();
217
- if (baseUrlOverride)
218
- await saveConfig({ baseUrl });
219
- else
220
- await clearConfig();
221
- await saveAuthToken(token);
222
- console.log(`Signed in as ${user.email}. Credentials saved to ${getAuthConfigPath()}.`);
223
- });
224
- program
225
- .command("logout")
226
- .description("Sign out")
227
- .action(async () => {
228
- const authExisted = await signOut();
229
- const configExisted = await clearConfig();
230
- console.log(authExisted || configExisted ? "Signed out." : "Already signed out.");
231
- });
232
- }
233
203
  async function createFrameInput(project, name, options) {
234
204
  if (options.type === "glts") {
235
205
  if (options.image !== undefined || options.asset !== undefined) {
@@ -276,10 +246,6 @@ async function createFrameInput(project, name, options) {
276
246
  async function clientFor(command) {
277
247
  return getCliClient(apiOption(command));
278
248
  }
279
- function apiOption(command) {
280
- const value = command.optsWithGlobals().api;
281
- return typeof value === "string" ? value : undefined;
282
- }
283
249
  function projectId(command) {
284
250
  const value = command.optsWithGlobals().project;
285
251
  if (typeof value !== "string") {
@@ -1,2 +1,3 @@
1
- import type { DesignMcpOperationRunner, DesignMcpOperations, DesignMcpServer } from "./types.js";
2
- export declare function registerFileTools(server: DesignMcpServer, design: DesignMcpOperations, run: DesignMcpOperationRunner): void;
1
+ import type { DesignV1Client } from "../v1/client.js";
2
+ import type { DesignMcpServer } from "./types.js";
3
+ export declare function registerFileTools(server: DesignMcpServer, client: DesignV1Client): void;
package/dist/mcp/file.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { fileTextSchema } from "../v1/schemas.js";
2
2
  import { fileResult, result } from "./result.js";
3
3
  import { directoryPathSchema, fileInput, projectInput } from "./schema.js";
4
- export function registerFileTools(server, design, run) {
4
+ export function registerFileTools(server, client) {
5
5
  server.registerTool("list_files", {
6
6
  description: "Return canonical project-absolute paths. Omit path to list the entire project; otherwise use /<frame-id> without a trailing slash. Pass returned file paths unchanged to file tools.",
7
7
  inputSchema: projectInput.extend({
@@ -13,7 +13,10 @@ export function registerFileTools(server, design, run) {
13
13
  openWorldHint: false,
14
14
  idempotentHint: true,
15
15
  },
16
- }, async ({ project, path }) => result(await run("list_files", () => design.listFiles(project, path))));
16
+ }, async ({ project, path }) => result(await client.filesystem.list({
17
+ project,
18
+ ...(path === undefined ? {} : { path }),
19
+ })));
17
20
  server.registerTool("read_file", {
18
21
  description: "Read one canonical project-absolute path returned by list_files. The path includes the frame ID; this tool does not accept a frame argument. Binary files return their hosted URL and media type.",
19
22
  inputSchema: fileInput,
@@ -24,7 +27,7 @@ export function registerFileTools(server, design, run) {
24
27
  idempotentHint: true,
25
28
  },
26
29
  }, async ({ project, path }) => {
27
- const file = await run("read_file", () => design.readFile(project, path));
30
+ const file = await client.filesystem.read({ project, path });
28
31
  return file.type === "text" ? fileResult(file) : result(file);
29
32
  });
30
33
  server.registerTool("write_file", {
@@ -35,7 +38,7 @@ export function registerFileTools(server, design, run) {
35
38
  destructiveHint: true,
36
39
  openWorldHint: true,
37
40
  },
38
- }, async ({ project, path, text }) => result(await run("write_file", () => design.writeFile(project, path, text))));
41
+ }, async ({ project, path, text }) => result(await client.filesystem.write({ project, path, text })));
39
42
  server.registerTool("edit_file", {
40
43
  description: "Replace oldText when it occurs exactly once at a canonical project-absolute .glts path. The path includes the frame ID; this tool does not accept a frame argument.",
41
44
  inputSchema: fileInput.extend({
@@ -47,7 +50,7 @@ export function registerFileTools(server, design, run) {
47
50
  destructiveHint: true,
48
51
  openWorldHint: true,
49
52
  },
50
- }, async ({ project, path, oldText, newText }) => result(await run("edit_file", () => design.editFile(project, path, oldText, newText))));
53
+ }, async ({ project, path, oldText, newText }) => result(await client.filesystem.edit({ project, path, oldText, newText })));
51
54
  server.registerTool("delete_file", {
52
55
  description: "Permanently delete one .glts file at a canonical project-absolute path. The path includes the frame ID; this tool does not accept a frame argument.",
53
56
  inputSchema: fileInput,
@@ -56,5 +59,5 @@ export function registerFileTools(server, design, run) {
56
59
  destructiveHint: true,
57
60
  openWorldHint: true,
58
61
  },
59
- }, async ({ project, path }) => result(await run("delete_file", () => design.deleteFile(project, path))));
62
+ }, async ({ project, path }) => result(await client.filesystem.delete({ project, path })));
60
63
  }
@@ -1,2 +1,3 @@
1
- import type { DesignMcpOperationRunner, DesignMcpOperations, DesignMcpServer } from "./types.js";
2
- export declare function registerFrameTools(server: DesignMcpServer, design: DesignMcpOperations, run: DesignMcpOperationRunner): void;
1
+ import type { DesignV1Client } from "../v1/client.js";
2
+ import type { DesignMcpServer } from "./types.js";
3
+ export declare function registerFrameTools(server: DesignMcpServer, client: DesignV1Client, fetcher: typeof globalThis.fetch): void;
package/dist/mcp/frame.js CHANGED
@@ -1,7 +1,7 @@
1
- import { frameNameSchema, generateImageFrameSchema } from "../v1/schemas.js";
1
+ import { frameNameSchema, generateImageFrameSchema, } from "../v1/schemas.js";
2
2
  import { base64, result } from "./result.js";
3
3
  import { createFrameSchema, frameCreationInput, frameInput, projectInput, } from "./schema.js";
4
- export function registerFrameTools(server, design, run) {
4
+ export function registerFrameTools(server, client, fetcher) {
5
5
  server.registerTool("list_frames", {
6
6
  description: "List frames. Use their immutable ids for frame commands and filesystem paths.",
7
7
  inputSchema: projectInput,
@@ -11,9 +11,7 @@ export function registerFrameTools(server, design, run) {
11
11
  openWorldHint: false,
12
12
  idempotentHint: true,
13
13
  },
14
- }, async ({ project }) => result({
15
- frames: await run("list_frames", () => design.listFrames(project)),
16
- }));
14
+ }, async ({ project }) => result({ frames: await client.frame.list({ project }) }));
17
15
  server.registerTool("create_frame", {
18
16
  description: "Create a frame in a Drawcall Design project. Use type=glts for reusable 3D objects and scenes, then write its source with write_file. Use type=image only for an existing public image URL and type=market only for an exact public Market asset.",
19
17
  inputSchema: createFrameSchema,
@@ -24,7 +22,7 @@ export function registerFrameTools(server, design, run) {
24
22
  idempotentHint: false,
25
23
  },
26
24
  }, async (input) => result({
27
- frame: await run("create_frame", () => design.createFrame(frameCreationInput(input))),
25
+ frame: await client.frame.create(frameCreationInput(input)),
28
26
  }));
29
27
  server.registerTool("generate_image", {
30
28
  description: "Generate a 2D image or reference frame from text and up to four same-project image frame references. Use only when the user asks for a 2D image, picture, concept, or reference; do not use for 3D objects, scenes, or reusable GLTS assets. For edit, target is reference 0. New frames are the default; result=replace explicitly replaces the target image while preserving its frame ID, name, and layout.",
@@ -36,7 +34,7 @@ export function registerFrameTools(server, design, run) {
36
34
  idempotentHint: false,
37
35
  },
38
36
  }, async (input) => result({
39
- frame: await run("generate_image", () => design.generateImage(input)),
37
+ frame: await client.frame.generateImage(input),
40
38
  }));
41
39
  server.registerTool("rename_frame", {
42
40
  description: "Rename a frame. Its immutable frame id does not change.",
@@ -47,7 +45,7 @@ export function registerFrameTools(server, design, run) {
47
45
  openWorldHint: false,
48
46
  },
49
47
  }, async ({ project, frame, name }) => result({
50
- frame: await run("rename_frame", () => design.renameFrame(project, frame, name)),
48
+ frame: await client.frame.rename({ project, frame, name }),
51
49
  }));
52
50
  server.registerTool("delete_frame", {
53
51
  description: "Permanently delete a frame.",
@@ -58,7 +56,7 @@ export function registerFrameTools(server, design, run) {
58
56
  openWorldHint: true,
59
57
  idempotentHint: false,
60
58
  },
61
- }, async ({ project, frame }) => result(await run("delete_frame", () => design.deleteFrame(project, frame))));
59
+ }, async ({ project, frame }) => result(await client.frame.delete({ project, frame })));
62
60
  server.registerTool("get_frame_screenshot", {
63
61
  description: "Render a DPR-1 PNG screenshot of a frame.",
64
62
  inputSchema: frameInput,
@@ -69,7 +67,8 @@ export function registerFrameTools(server, design, run) {
69
67
  idempotentHint: true,
70
68
  },
71
69
  }, async ({ project, frame }) => {
72
- const screenshot = await run("get_frame_screenshot", () => design.screenshot(project, frame));
70
+ const screenshot = await client.frame.screenshot({ project, frame });
71
+ const png = await screenshotBytes(screenshot, fetcher);
73
72
  const structuredContent = {
74
73
  url: screenshot.url,
75
74
  width: screenshot.width,
@@ -80,7 +79,7 @@ export function registerFrameTools(server, design, run) {
80
79
  content: [
81
80
  {
82
81
  type: "image",
83
- data: base64(screenshot.png),
82
+ data: base64(png),
84
83
  mimeType: screenshot.mediaType,
85
84
  },
86
85
  ],
@@ -88,3 +87,17 @@ export function registerFrameTools(server, design, run) {
88
87
  };
89
88
  });
90
89
  }
90
+ async function screenshotBytes(screenshot, fetcher) {
91
+ const response = await fetcher(screenshot.url);
92
+ if (!response.ok) {
93
+ throw new Error(`Could not read screenshot ${screenshot.url}: ${response.status} ${response.statusText}`);
94
+ }
95
+ const mediaType = response.headers
96
+ .get("content-type")
97
+ ?.split(";", 1)[0]
98
+ ?.trim();
99
+ if (mediaType !== screenshot.mediaType) {
100
+ throw new Error(`Screenshot ${screenshot.url} returned ${mediaType ?? "no media type"}; expected ${screenshot.mediaType}`);
101
+ }
102
+ return new Uint8Array(await response.arrayBuffer());
103
+ }
@@ -1,3 +1,2 @@
1
- export { createDesignMcpOperations } from "./client.js";
2
1
  export { registerDesignTools } from "./register.js";
3
- export type { DesignMcpOperationRunner, DesignMcpOperations, DesignMcpServer, DesignMcpScreenshot, DesignMcpToolResult, } from "./types.js";
2
+ export type { DesignMcpOptions, DesignMcpServer, DesignMcpToolResult, } from "./types.js";
package/dist/mcp/index.js CHANGED
@@ -1,2 +1 @@
1
- export { createDesignMcpOperations } from "./client.js";
2
1
  export { registerDesignTools } from "./register.js";
@@ -1,2 +1,3 @@
1
- import type { DesignMcpOperationRunner, DesignMcpOperations, DesignMcpServer } from "./types.js";
2
- export declare function registerProjectTools(server: DesignMcpServer, design: DesignMcpOperations, run: DesignMcpOperationRunner): void;
1
+ import type { DesignV1Client } from "../v1/client.js";
2
+ import type { DesignMcpServer } from "./types.js";
3
+ export declare function registerProjectTools(server: DesignMcpServer, client: DesignV1Client): void;
@@ -2,7 +2,7 @@ import { z } from "zod";
2
2
  import { projectNameSchema } from "../v1/schemas.js";
3
3
  import { result } from "./result.js";
4
4
  import { projectInput } from "./schema.js";
5
- export function registerProjectTools(server, design, run) {
5
+ export function registerProjectTools(server, client) {
6
6
  server.registerTool("list_projects", {
7
7
  description: "List projects available to the current Drawcall account.",
8
8
  annotations: {
@@ -11,9 +11,7 @@ export function registerProjectTools(server, design, run) {
11
11
  openWorldHint: false,
12
12
  idempotentHint: true,
13
13
  },
14
- }, async () => result({
15
- projects: await run("list_projects", () => design.listProjects()),
16
- }));
14
+ }, async () => result({ projects: await client.project.list() }));
17
15
  server.registerTool("create_project", {
18
16
  description: "Create a project. Use its returned immutable id in every later call.",
19
17
  inputSchema: z.object({ name: projectNameSchema }).strict(),
@@ -23,9 +21,7 @@ export function registerProjectTools(server, design, run) {
23
21
  openWorldHint: false,
24
22
  idempotentHint: false,
25
23
  },
26
- }, async ({ name }) => result({
27
- project: await run("create_project", () => design.createProject(name)),
28
- }));
24
+ }, async ({ name }) => result({ project: await client.project.create({ name }) }));
29
25
  server.registerTool("delete_project", {
30
26
  description: "Permanently delete a project and its frames.",
31
27
  inputSchema: projectInput,
@@ -35,5 +31,5 @@ export function registerProjectTools(server, design, run) {
35
31
  openWorldHint: true,
36
32
  idempotentHint: false,
37
33
  },
38
- }, async ({ project }) => result(await run("delete_project", () => design.deleteProject(project))));
34
+ }, async ({ project }) => result(await client.project.delete({ project })));
39
35
  }
@@ -1,2 +1,3 @@
1
- import type { DesignMcpOperationRunner, DesignMcpOperations, DesignMcpServer } from "./types.js";
2
- export declare function registerDesignTools(server: DesignMcpServer, design: DesignMcpOperations, run?: DesignMcpOperationRunner): void;
1
+ import type { DesignV1Client } from "../v1/client.js";
2
+ import type { DesignMcpOptions, DesignMcpServer } from "./types.js";
3
+ export declare function registerDesignTools(server: DesignMcpServer, client: DesignV1Client, options?: DesignMcpOptions): void;
@@ -2,12 +2,9 @@ import { registerFileTools } from "./file.js";
2
2
  import { registerFrameTools } from "./frame.js";
3
3
  import { registerProjectTools } from "./project.js";
4
4
  import { registerSkillTool } from "./skill.js";
5
- export function registerDesignTools(server, design, run = runOperation) {
5
+ export function registerDesignTools(server, client, options = {}) {
6
6
  registerSkillTool(server);
7
- registerProjectTools(server, design, run);
8
- registerFrameTools(server, design, run);
9
- registerFileTools(server, design, run);
10
- }
11
- function runOperation(_name, operation) {
12
- return operation();
7
+ registerProjectTools(server, client);
8
+ registerFrameTools(server, client, options.fetch ?? globalThis.fetch);
9
+ registerFileTools(server, client);
13
10
  }
@@ -1,4 +1,3 @@
1
- import type { CreateFrame, DesignFile, FileList, FileMutation, Frame, GenerateImageFrame, Project, Screenshot } from "../v1/schemas.js";
2
1
  import type { z } from "zod";
3
2
  export interface DesignMcpToolResult {
4
3
  [key: string]: unknown;
@@ -27,28 +26,7 @@ type DesignMcpToolHandler<Input extends z.ZodType | undefined> = Input extends z
27
26
  export interface DesignMcpServer {
28
27
  registerTool<Input extends z.ZodType | undefined = undefined>(name: string, config: DesignMcpToolConfig<Input>, handler: DesignMcpToolHandler<Input>): unknown;
29
28
  }
30
- export interface DesignMcpScreenshot extends Screenshot {
31
- png: Uint8Array;
32
- }
33
- export type DesignMcpOperationRunner = <Result>(name: string, operation: () => Promise<Result>) => Promise<Result>;
34
- export interface DesignMcpOperations {
35
- listProjects(): Promise<Project[]>;
36
- createProject(name: string): Promise<Project>;
37
- deleteProject(project: string): Promise<{
38
- id: string;
39
- }>;
40
- listFrames(project: string): Promise<Frame[]>;
41
- createFrame(input: CreateFrame): Promise<Frame>;
42
- generateImage(input: GenerateImageFrame): Promise<Frame>;
43
- renameFrame(project: string, frame: string, name: string): Promise<Frame>;
44
- deleteFrame(project: string, frame: string): Promise<{
45
- id: string;
46
- }>;
47
- listFiles(project: string, path?: string): Promise<FileList>;
48
- readFile(project: string, path: string): Promise<DesignFile>;
49
- writeFile(project: string, path: string, text: string): Promise<FileMutation>;
50
- editFile(project: string, path: string, oldText: string, newText: string): Promise<FileMutation>;
51
- deleteFile(project: string, path: string): Promise<FileMutation>;
52
- screenshot(project: string, frame: string): Promise<DesignMcpScreenshot>;
29
+ export interface DesignMcpOptions {
30
+ fetch?: typeof globalThis.fetch;
53
31
  }
54
32
  export {};
@@ -0,0 +1,2 @@
1
+ import type { Command } from "commander";
2
+ export declare function apiOption(command: Command): string | undefined;
@@ -0,0 +1,4 @@
1
+ export function apiOption(command) {
2
+ const value = command.optsWithGlobals().api;
3
+ return typeof value === "string" ? value : undefined;
4
+ }
@@ -65,8 +65,8 @@ export declare const projectImageFrameRecordSchema: z.ZodObject<{
65
65
  frameUpdatedAt: z.ZodString;
66
66
  }, z.core.$strip>>;
67
67
  result: z.ZodEnum<{
68
- new: "new";
69
68
  replace: "replace";
69
+ new: "new";
70
70
  }>;
71
71
  provider: z.ZodLiteral<"fal-ai">;
72
72
  model: z.ZodLiteral<"openai/gpt-image-2">;
@@ -82,8 +82,8 @@ export declare const projectImageFrameRecordSchema: z.ZodObject<{
82
82
  frameUpdatedAt: z.ZodString;
83
83
  }, z.core.$strip>>;
84
84
  result: z.ZodEnum<{
85
- new: "new";
86
85
  replace: "replace";
86
+ new: "new";
87
87
  }>;
88
88
  provider: z.ZodLiteral<"cloudflare-workers-ai">;
89
89
  model: z.ZodLiteral<"@cf/black-forest-labs/flux-2-klein-4b">;
@@ -177,8 +177,8 @@ export declare const projectFrameRecordSchema: z.ZodDiscriminatedUnion<[z.ZodObj
177
177
  frameUpdatedAt: z.ZodString;
178
178
  }, z.core.$strip>>;
179
179
  result: z.ZodEnum<{
180
- new: "new";
181
180
  replace: "replace";
181
+ new: "new";
182
182
  }>;
183
183
  provider: z.ZodLiteral<"fal-ai">;
184
184
  model: z.ZodLiteral<"openai/gpt-image-2">;
@@ -194,8 +194,8 @@ export declare const projectFrameRecordSchema: z.ZodDiscriminatedUnion<[z.ZodObj
194
194
  frameUpdatedAt: z.ZodString;
195
195
  }, z.core.$strip>>;
196
196
  result: z.ZodEnum<{
197
- new: "new";
198
197
  replace: "replace";
198
+ new: "new";
199
199
  }>;
200
200
  provider: z.ZodLiteral<"cloudflare-workers-ai">;
201
201
  model: z.ZodLiteral<"@cf/black-forest-labs/flux-2-klein-4b">;
@@ -287,8 +287,8 @@ export declare const projectStateSchema: z.ZodObject<{
287
287
  frameUpdatedAt: z.ZodString;
288
288
  }, z.core.$strip>>;
289
289
  result: z.ZodEnum<{
290
- new: "new";
291
290
  replace: "replace";
291
+ new: "new";
292
292
  }>;
293
293
  provider: z.ZodLiteral<"fal-ai">;
294
294
  model: z.ZodLiteral<"openai/gpt-image-2">;
@@ -304,8 +304,8 @@ export declare const projectStateSchema: z.ZodObject<{
304
304
  frameUpdatedAt: z.ZodString;
305
305
  }, z.core.$strip>>;
306
306
  result: z.ZodEnum<{
307
- new: "new";
308
307
  replace: "replace";
308
+ new: "new";
309
309
  }>;
310
310
  provider: z.ZodLiteral<"cloudflare-workers-ai">;
311
311
  model: z.ZodLiteral<"@cf/black-forest-labs/flux-2-klein-4b">;
@@ -0,0 +1,3 @@
1
+ import type { Command } from "commander";
2
+ import { type DesignCommandOptions } from "./command.js";
3
+ export declare function createDesignCli(options?: DesignCommandOptions): Command;
@@ -0,0 +1,7 @@
1
+ import { createLoginCommand, createLogoutCommand } from "./auth.js";
2
+ import { createDesignCommand } from "./command.js";
3
+ export function createDesignCli(options = {}) {
4
+ return createDesignCommand(options)
5
+ .addCommand(createLoginCommand())
6
+ .addCommand(createLogoutCommand());
7
+ }
@@ -154,8 +154,8 @@ export declare const contract: {
154
154
  frameUpdatedAt: z.ZodString;
155
155
  }, z.core.$strip>>;
156
156
  result: z.ZodEnum<{
157
- new: "new";
158
157
  replace: "replace";
158
+ new: "new";
159
159
  }>;
160
160
  provider: z.ZodLiteral<"fal-ai">;
161
161
  model: z.ZodLiteral<"openai/gpt-image-2">;
@@ -171,8 +171,8 @@ export declare const contract: {
171
171
  frameUpdatedAt: z.ZodString;
172
172
  }, z.core.$strip>>;
173
173
  result: z.ZodEnum<{
174
- new: "new";
175
174
  replace: "replace";
175
+ new: "new";
176
176
  }>;
177
177
  provider: z.ZodLiteral<"cloudflare-workers-ai">;
178
178
  model: z.ZodLiteral<"@cf/black-forest-labs/flux-2-klein-4b">;
@@ -264,8 +264,8 @@ export declare const contract: {
264
264
  frameUpdatedAt: z.ZodString;
265
265
  }, z.core.$strip>>;
266
266
  result: z.ZodEnum<{
267
- new: "new";
268
267
  replace: "replace";
268
+ new: "new";
269
269
  }>;
270
270
  provider: z.ZodLiteral<"fal-ai">;
271
271
  model: z.ZodLiteral<"openai/gpt-image-2">;
@@ -281,8 +281,8 @@ export declare const contract: {
281
281
  frameUpdatedAt: z.ZodString;
282
282
  }, z.core.$strip>>;
283
283
  result: z.ZodEnum<{
284
- new: "new";
285
284
  replace: "replace";
285
+ new: "new";
286
286
  }>;
287
287
  provider: z.ZodLiteral<"cloudflare-workers-ai">;
288
288
  model: z.ZodLiteral<"@cf/black-forest-labs/flux-2-klein-4b">;
@@ -311,8 +311,8 @@ export declare const contract: {
311
311
  target: z.ZodOptional<z.ZodString>;
312
312
  references: z.ZodDefault<z.ZodArray<z.ZodString>>;
313
313
  result: z.ZodEnum<{
314
- new: "new";
315
314
  replace: "replace";
315
+ new: "new";
316
316
  }>;
317
317
  name: z.ZodOptional<z.ZodString>;
318
318
  x: z.ZodOptional<z.ZodNumber>;
@@ -368,8 +368,8 @@ export declare const contract: {
368
368
  frameUpdatedAt: z.ZodString;
369
369
  }, z.core.$strip>>;
370
370
  result: z.ZodEnum<{
371
- new: "new";
372
371
  replace: "replace";
372
+ new: "new";
373
373
  }>;
374
374
  provider: z.ZodLiteral<"fal-ai">;
375
375
  model: z.ZodLiteral<"openai/gpt-image-2">;
@@ -385,8 +385,8 @@ export declare const contract: {
385
385
  frameUpdatedAt: z.ZodString;
386
386
  }, z.core.$strip>>;
387
387
  result: z.ZodEnum<{
388
- new: "new";
389
388
  replace: "replace";
389
+ new: "new";
390
390
  }>;
391
391
  provider: z.ZodLiteral<"cloudflare-workers-ai">;
392
392
  model: z.ZodLiteral<"@cf/black-forest-labs/flux-2-klein-4b">;
@@ -460,8 +460,8 @@ export declare const contract: {
460
460
  frameUpdatedAt: z.ZodString;
461
461
  }, z.core.$strip>>;
462
462
  result: z.ZodEnum<{
463
- new: "new";
464
463
  replace: "replace";
464
+ new: "new";
465
465
  }>;
466
466
  provider: z.ZodLiteral<"fal-ai">;
467
467
  model: z.ZodLiteral<"openai/gpt-image-2">;
@@ -477,8 +477,8 @@ export declare const contract: {
477
477
  frameUpdatedAt: z.ZodString;
478
478
  }, z.core.$strip>>;
479
479
  result: z.ZodEnum<{
480
- new: "new";
481
480
  replace: "replace";
481
+ new: "new";
482
482
  }>;
483
483
  provider: z.ZodLiteral<"cloudflare-workers-ai">;
484
484
  model: z.ZodLiteral<"@cf/black-forest-labs/flux-2-klein-4b">;
@@ -566,8 +566,8 @@ export declare const contract: {
566
566
  frameUpdatedAt: z.ZodString;
567
567
  }, z.core.$strip>>;
568
568
  result: z.ZodEnum<{
569
- new: "new";
570
569
  replace: "replace";
570
+ new: "new";
571
571
  }>;
572
572
  provider: z.ZodLiteral<"fal-ai">;
573
573
  model: z.ZodLiteral<"openai/gpt-image-2">;
@@ -583,8 +583,8 @@ export declare const contract: {
583
583
  frameUpdatedAt: z.ZodString;
584
584
  }, z.core.$strip>>;
585
585
  result: z.ZodEnum<{
586
- new: "new";
587
586
  replace: "replace";
587
+ new: "new";
588
588
  }>;
589
589
  provider: z.ZodLiteral<"cloudflare-workers-ai">;
590
590
  model: z.ZodLiteral<"@cf/black-forest-labs/flux-2-klein-4b">;
@@ -661,8 +661,8 @@ export declare const contract: {
661
661
  frameUpdatedAt: z.ZodString;
662
662
  }, z.core.$strip>>;
663
663
  result: z.ZodEnum<{
664
- new: "new";
665
664
  replace: "replace";
665
+ new: "new";
666
666
  }>;
667
667
  provider: z.ZodLiteral<"fal-ai">;
668
668
  model: z.ZodLiteral<"openai/gpt-image-2">;
@@ -678,8 +678,8 @@ export declare const contract: {
678
678
  frameUpdatedAt: z.ZodString;
679
679
  }, z.core.$strip>>;
680
680
  result: z.ZodEnum<{
681
- new: "new";
682
681
  replace: "replace";
682
+ new: "new";
683
683
  }>;
684
684
  provider: z.ZodLiteral<"cloudflare-workers-ai">;
685
685
  model: z.ZodLiteral<"@cf/black-forest-labs/flux-2-klein-4b">;
@@ -97,8 +97,8 @@ export declare const imageGenerationOperationSchema: z.ZodEnum<{
97
97
  edit: "edit";
98
98
  }>;
99
99
  export declare const imageGenerationResultSchema: z.ZodEnum<{
100
- new: "new";
101
100
  replace: "replace";
101
+ new: "new";
102
102
  }>;
103
103
  export declare const imageGenerationReferenceSchema: z.ZodObject<{
104
104
  frameId: z.ZodString;
@@ -120,8 +120,8 @@ export declare const imageGenerationProvenanceSchema: z.ZodDiscriminatedUnion<[z
120
120
  frameUpdatedAt: z.ZodString;
121
121
  }, z.core.$strip>>;
122
122
  result: z.ZodEnum<{
123
- new: "new";
124
123
  replace: "replace";
124
+ new: "new";
125
125
  }>;
126
126
  provider: z.ZodLiteral<"fal-ai">;
127
127
  model: z.ZodLiteral<"openai/gpt-image-2">;
@@ -137,8 +137,8 @@ export declare const imageGenerationProvenanceSchema: z.ZodDiscriminatedUnion<[z
137
137
  frameUpdatedAt: z.ZodString;
138
138
  }, z.core.$strip>>;
139
139
  result: z.ZodEnum<{
140
- new: "new";
141
140
  replace: "replace";
141
+ new: "new";
142
142
  }>;
143
143
  provider: z.ZodLiteral<"cloudflare-workers-ai">;
144
144
  model: z.ZodLiteral<"@cf/black-forest-labs/flux-2-klein-4b">;
@@ -168,8 +168,8 @@ export declare const imageFrameSchema: z.ZodObject<{
168
168
  frameUpdatedAt: z.ZodString;
169
169
  }, z.core.$strip>>;
170
170
  result: z.ZodEnum<{
171
- new: "new";
172
171
  replace: "replace";
172
+ new: "new";
173
173
  }>;
174
174
  provider: z.ZodLiteral<"fal-ai">;
175
175
  model: z.ZodLiteral<"openai/gpt-image-2">;
@@ -185,8 +185,8 @@ export declare const imageFrameSchema: z.ZodObject<{
185
185
  frameUpdatedAt: z.ZodString;
186
186
  }, z.core.$strip>>;
187
187
  result: z.ZodEnum<{
188
- new: "new";
189
188
  replace: "replace";
189
+ new: "new";
190
190
  }>;
191
191
  provider: z.ZodLiteral<"cloudflare-workers-ai">;
192
192
  model: z.ZodLiteral<"@cf/black-forest-labs/flux-2-klein-4b">;
@@ -257,8 +257,8 @@ export declare const frameSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
257
257
  frameUpdatedAt: z.ZodString;
258
258
  }, z.core.$strip>>;
259
259
  result: z.ZodEnum<{
260
- new: "new";
261
260
  replace: "replace";
261
+ new: "new";
262
262
  }>;
263
263
  provider: z.ZodLiteral<"fal-ai">;
264
264
  model: z.ZodLiteral<"openai/gpt-image-2">;
@@ -274,8 +274,8 @@ export declare const frameSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
274
274
  frameUpdatedAt: z.ZodString;
275
275
  }, z.core.$strip>>;
276
276
  result: z.ZodEnum<{
277
- new: "new";
278
277
  replace: "replace";
278
+ new: "new";
279
279
  }>;
280
280
  provider: z.ZodLiteral<"cloudflare-workers-ai">;
281
281
  model: z.ZodLiteral<"@cf/black-forest-labs/flux-2-klein-4b">;
@@ -352,8 +352,8 @@ export declare const generateImageFrameSchema: z.ZodObject<{
352
352
  target: z.ZodOptional<z.ZodString>;
353
353
  references: z.ZodDefault<z.ZodArray<z.ZodString>>;
354
354
  result: z.ZodEnum<{
355
- new: "new";
356
355
  replace: "replace";
356
+ new: "new";
357
357
  }>;
358
358
  name: z.ZodOptional<z.ZodString>;
359
359
  x: z.ZodOptional<z.ZodNumber>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drawcall/design",
3
- "version": "0.5.11",
3
+ "version": "0.6.0",
4
4
  "description": "Typed API and remote CLI for Drawcall Design",
5
5
  "repository": {
6
6
  "type": "git",
@@ -16,7 +16,7 @@
16
16
  "skills"
17
17
  ],
18
18
  "bin": {
19
- "design": "./dist/cli.js"
19
+ "design": "dist/cli.js"
20
20
  },
21
21
  "scripts": {
22
22
  "generate": "node scripts/generate-skill.mjs",
@@ -1,3 +0,0 @@
1
- import type { DesignV1Client } from "../v1/client.js";
2
- import type { DesignMcpOperations } from "./types.js";
3
- export declare function createDesignMcpOperations(client: DesignV1Client, fetcher?: typeof globalThis.fetch): DesignMcpOperations;
@@ -1,38 +0,0 @@
1
- export function createDesignMcpOperations(client, fetcher = globalThis.fetch) {
2
- return {
3
- listProjects: () => client.project.list(),
4
- createProject: (name) => client.project.create({ name }),
5
- deleteProject: (project) => client.project.delete({ project }),
6
- listFrames: (project) => client.frame.list({ project }),
7
- createFrame: (input) => client.frame.create(input),
8
- generateImage: (input) => client.frame.generateImage(input),
9
- renameFrame: (project, frame, name) => client.frame.rename({ project, frame, name }),
10
- deleteFrame: (project, frame) => client.frame.delete({ project, frame }),
11
- listFiles: (project, path) => client.filesystem.list({
12
- project,
13
- ...(path === undefined ? {} : { path }),
14
- }),
15
- readFile: (project, path) => client.filesystem.read({ project, path }),
16
- writeFile: (project, path, text) => client.filesystem.write({ project, path, text }),
17
- editFile: (project, path, oldText, newText) => client.filesystem.edit({ project, path, oldText, newText }),
18
- deleteFile: (project, path) => client.filesystem.delete({ project, path }),
19
- screenshot: async (project, frame) => {
20
- const screenshot = await client.frame.screenshot({ project, frame });
21
- const response = await fetcher(screenshot.url);
22
- if (!response.ok) {
23
- throw new Error(`Could not read screenshot ${screenshot.url}: ${response.status} ${response.statusText}`);
24
- }
25
- const mediaType = response.headers
26
- .get("content-type")
27
- ?.split(";", 1)[0]
28
- ?.trim();
29
- if (mediaType !== screenshot.mediaType) {
30
- throw new Error(`Screenshot ${screenshot.url} returned ${mediaType ?? "no media type"}; expected ${screenshot.mediaType}`);
31
- }
32
- return {
33
- ...screenshot,
34
- png: new Uint8Array(await response.arrayBuffer()),
35
- };
36
- },
37
- };
38
- }