@builder.io/ai-utils 0.59.0 → 0.60.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/src/codegen.js CHANGED
@@ -1,8 +1,1516 @@
1
1
  import { z } from "zod";
2
+ import { AttachmentSchema, ContentMessageItemToolResultSchema, } from "./messages";
3
+ import { UserContextSchema } from "./mapping";
4
+ import { SetupDependencySchema } from "./projects";
5
+ export const GitSnapshotSchema = z.string().meta({
6
+ title: "GitSnapshot",
7
+ description: "Multi-repo git snapshot. Format: 'folder:hash,folder:hash' " +
8
+ "with URL-encoded folder names. Legacy single-hash form " +
9
+ "('abc123') is also accepted. Empty string means no commits.",
10
+ });
11
+ // Define the import type as a union of literal types.
12
+ export const ImportTypeSchema = z
13
+ .enum(["named", "default"])
14
+ .meta({ title: "ImportType" });
15
+ export const ProjectFileSchema = z
16
+ .object({
17
+ filePath: z.string(),
18
+ content: z.string().optional(),
19
+ importance: z.number().optional(),
20
+ dropReason: z.string().optional(),
21
+ wasIncluded: z.boolean().optional(),
22
+ virtual: z.boolean().optional(),
23
+ })
24
+ .meta({ title: "ProjectFile" });
25
+ export const CustomInstructionSchema = z
26
+ .object({
27
+ id: z.string(),
28
+ name: z.string(),
29
+ content: z.string(),
30
+ type: z.enum(["always", "agent-mode"]).optional(),
31
+ filePath: z.string().optional(),
32
+ glob: z.string().optional(),
33
+ description: z.string().optional(),
34
+ allowedTools: z.array(z.string()).optional(),
35
+ hideUI: z.boolean().optional(),
36
+ isSkill: z.boolean().optional(),
37
+ disableModelInvocation: z.boolean().optional(),
38
+ userInvocable: z.boolean().optional(),
39
+ /**
40
+ * Where this instruction was discovered. Drives precedence on name
41
+ * collision: `project` > `user` > `plugin`. Set by the discovery loader,
42
+ * not by the parsed file itself.
43
+ */
44
+ scope: z.enum(["project", "user", "plugin"]).optional(),
45
+ /**
46
+ * Name of the plugin that contributed this instruction, if any. Set by
47
+ * the plugin loader (Phase 2); always `undefined` for project-level and
48
+ * user-level standalone files (Phase 1).
49
+ */
50
+ pluginName: z.string().optional(),
51
+ })
52
+ .meta({ title: "CustomInstruction" });
2
53
  /** Reasoning effort level for LLM completions. */
3
54
  export const ReasoningEffortSchema = z
4
55
  .enum(["auto", "none", "minimal", "low", "medium", "high", "xhigh", "max"])
5
56
  .meta({ title: "ReasoningEffort" });
57
+ export const CustomAgentInfoSchema = z
58
+ .object({
59
+ name: z.string(),
60
+ description: z.string().optional(),
61
+ })
62
+ .meta({ title: "CustomAgentInfo" });
63
+ /** Per-agent model overrides. String = fixed model, string[] = round-robin. */
64
+ export const AgentModelOverridesSchema = z
65
+ .record(z.string(), z.union([z.string(), z.array(z.string())]))
66
+ .meta({ title: "AgentModelOverrides" });
67
+ export const CodeGenFrameworkSchema = z
68
+ .enum([
69
+ "react",
70
+ "html",
71
+ "mitosis",
72
+ "react-native",
73
+ "angular",
74
+ "vue",
75
+ "svelte",
76
+ "qwik",
77
+ "solid",
78
+ "marko",
79
+ "swiftui",
80
+ "jetpack-compose",
81
+ "flutter",
82
+ ])
83
+ .meta({ title: "CodeGenFramework" });
84
+ export const CodeGenStyleLibrarySchema = z
85
+ .enum([
86
+ "tailwind",
87
+ "tailwind-precise",
88
+ "emotion",
89
+ "styled-components",
90
+ "styled-jsx",
91
+ "react-native",
92
+ ])
93
+ .meta({ title: "CodeGenStyleLibrary" });
94
+ export const CompletionStopReasonSchema = z
95
+ .enum([
96
+ "max_tokens",
97
+ "stop_sequence",
98
+ "tool_use",
99
+ "end_turn",
100
+ "content_filter",
101
+ "error",
102
+ "aborted",
103
+ "pause_turn",
104
+ "refusal",
105
+ "compaction",
106
+ "model_context_window_exceeded",
107
+ ])
108
+ .nullable()
109
+ .meta({ title: "CompletionStopReason" });
110
+ export const FILE_PATH_DESCRIPTION = "The path of the file. Accepts a path relative to the project working directory, an absolute path (`/Users/.../skill.md`), or a tilde path (`~/.builder/skills/.../SKILL.md`). User-level Builder state under `~/.builder/**` is allowed by default for plugin operations; other absolute paths require an explicit ACL policy.";
111
+ export const ReadToolInputSchema = z
112
+ .object({
113
+ file_path: z.string().meta({ description: FILE_PATH_DESCRIPTION }),
114
+ offset: z.number().nullish().meta({
115
+ description: "The line number to start reading from.",
116
+ }),
117
+ limit: z.number().nullish().meta({
118
+ description: "The number of lines to read.",
119
+ }),
120
+ })
121
+ .meta({ title: "ReadToolInput" });
122
+ export const GlobSearchToolInputSchema = z
123
+ .object({
124
+ pattern: z.string().meta({ description: "The pattern to search for" }),
125
+ })
126
+ .meta({ title: "GlobSearchToolInput" });
127
+ export const GrepSearchToolInputSchema = z
128
+ .object({
129
+ query: z.string().meta({
130
+ description: 'A string literal or a JavaScript-flavored regex to search for in all project files. Only escape special characters such as {} and () in string literals to avoid confusion with regex patterns (e.g. "import \\{ foo \\}"). Avoid over-escaping as that will cause errors. Do NOT use inline regex flags like (?i) or (?s) — they are not supported. The search is case-insensitive by default; use the case_sensitive parameter to control this.',
131
+ }),
132
+ include_glob: z.string().nullish().meta({
133
+ description: "An optional single glob pattern to include only specific files (e.g. '**/*.(ts|tsx)' for all TypeScript files)",
134
+ }),
135
+ exclude_glob: z.string().nullish().meta({
136
+ description: "Optional glob pattern to exclude specific files or directories",
137
+ }),
138
+ case_sensitive: z.boolean().nullish().meta({
139
+ description: "Whether the search should be case-sensitive. Defaults to false (case-insensitive). Set to true for case-sensitive search.",
140
+ }),
141
+ })
142
+ .meta({ title: "GrepSearchToolInput" });
143
+ export const SkillToolInputSchema = z
144
+ .object({
145
+ skill: z.string().meta({
146
+ description: "The name of a skill from the available-skills list. Do not guess names.",
147
+ }),
148
+ args: z.string().nullish().meta({
149
+ description: "Optional invocation arguments; forwarded with the skill body in the tool result.",
150
+ }),
151
+ })
152
+ .meta({ title: "SkillToolInput" });
153
+ export const GetRuleToolInputSchema = z
154
+ .object({
155
+ name: z.string().meta({ description: "The name of the rule to get" }),
156
+ })
157
+ .meta({ title: "GetRuleToolInput" });
158
+ export const GetStyleInspirationToolInputSchema = z
159
+ .object({
160
+ url: z.string().meta({
161
+ description: "The URL of the website to analyze and mimic the style of, for example 'https://airbnb.com' or 'https://instagram.com'",
162
+ }),
163
+ })
164
+ .meta({ title: "GetStyleInspirationToolInput" });
165
+ export const GetBuildOutputToolInputSchema = z
166
+ .object({})
167
+ .meta({ title: "GetBuildOutputToolInput" });
168
+ export const DevServerControlInputSchema = z
169
+ .object({
170
+ restart: z.boolean().nullish().meta({
171
+ description: "Whether to restart the dev server, it will also return the initial logs coming from the dev server. This tool can be very slow, only use as last resort, most of the times file changes do not require a restart.",
172
+ }),
173
+ set_dev_command: z.string().nullish().meta({
174
+ description: "Use to set the command of the dev server, for example 'npm run dev' or 'cd packages/frontend && yarn dev'. When updating the command, the dev server will be automatically restarted. After changing a command, the proxy port might change, so you need to use the 'set_proxy_port' tool to update the proxy port. Only use if there are explicit issues",
175
+ }),
176
+ set_proxy_port: z.number().nullish().meta({
177
+ description: "Used to configure the proxy port of the dev server. For example, if `npm run dev` open a port in 8392, but current proxy server listens 3000, you can use this tool to update the proxy port. Only use if there are explicit issues.",
178
+ }),
179
+ get_logs: z.boolean().nullish().meta({
180
+ description: "When used standalone, the tool will return logs of the dev server and other status. But don't change or restart anything. It's a read-only operation.",
181
+ }),
182
+ set_env_variable: z.tuple([z.string(), z.string()]).nullish().meta({
183
+ description: "Tuple of two strings, the first string is the name of the environment variable, the second string is the value of the environment variable. For example, ['DB_API_KEY', '___PRIVATE_KEY___']",
184
+ }),
185
+ set_and_run_setup_command: z.string().nullish().meta({
186
+ description: "Use to set the command of the setup command, for example 'npm install' or 'yarn'. Only use if there are explicit issues.",
187
+ }),
188
+ })
189
+ .meta({ title: "DevServerControlInput" });
190
+ export const DevServerLogsInputSchema = z
191
+ .object({})
192
+ .meta({ title: "DevServerLogsInput" });
193
+ export const DevServerRestartInputSchema = z.object({}).meta({
194
+ title: "DevServerRestartInput",
195
+ description: "Restarts the dev server with current configuration.",
196
+ });
197
+ export const BashToolInputSchema = z
198
+ .object({
199
+ description: z.string().meta({
200
+ description: "A human readable description of the command to run, for example 'install dependencies' or 'run tests'. This description will be used to explain the command to the user.",
201
+ }),
202
+ command: z.string().meta({
203
+ description: "The shell command to run, for example 'npm install --save uuid', 'yarn test' or 'npm run build'...",
204
+ }),
205
+ timeout: z.number().nullish().meta({
206
+ description: "Optional timeout in milliseconds (max/default 600000)",
207
+ }),
208
+ })
209
+ .meta({ title: "BashToolInput" });
210
+ export const PowerShellToolInputSchema = z
211
+ .object({
212
+ command: z.string().nullish().meta({
213
+ description: "The PowerShell command to run, for example 'npm install' or 'yarn test'",
214
+ }),
215
+ timeout: z.number().nullish().meta({
216
+ description: "The timeout in milliseconds for the command to run. Choose an appropriate timeout based on the command",
217
+ }),
218
+ description: z.string().nullish().meta({
219
+ description: "A human readable description of the command to run, for example 'install dependencies' or 'run tests'. This description will be used to explain the command to the user.",
220
+ }),
221
+ })
222
+ .meta({ title: "PowerShellToolInput" });
223
+ export const WebSearchToolInputSchema = z
224
+ .object({
225
+ query: z.string().meta({
226
+ description: "The question to search on the internet, be specific and concise.",
227
+ }),
228
+ })
229
+ .meta({ title: "WebSearchToolInput" });
230
+ export const WriteFileInputSchema = z
231
+ .object({
232
+ title: z.string().meta({
233
+ description: "Human readable description of the change or generated code, it's mandatory",
234
+ }),
235
+ file_path: z.string().meta({ description: FILE_PATH_DESCRIPTION }),
236
+ content: z.string().meta({
237
+ description: "Actual content to write into the file, use an empty string to remove the file",
238
+ }),
239
+ })
240
+ .meta({ title: "WriteFileInput" });
241
+ export const SearchReplaceInputSchema = z
242
+ .object({
243
+ title: z.string().meta({
244
+ description: "Human readable description of the change or generated code, it's mandatory",
245
+ }),
246
+ file_path: z.string().meta({
247
+ description: `${FILE_PATH_DESCRIPTION} The content of this path must be previously known.`,
248
+ }),
249
+ old_str: z.string().meta({ description: "The text to replace" }),
250
+ new_str: z.string().meta({
251
+ description: "The text to replace it with (must be different from old_str)",
252
+ }),
253
+ replace_all: z.boolean().optional().meta({
254
+ description: "Replace all occurences of old_str (default false)",
255
+ }),
256
+ apply_with_error: z.boolean().optional(),
257
+ })
258
+ .meta({ title: "SearchReplaceInput" });
259
+ export const MultiSearchReplaceInputSchema = z
260
+ .object({
261
+ title: z.string().meta({
262
+ description: "Human readable description of the change or generated code, it's mandatory",
263
+ }),
264
+ file_path: z.string().meta({
265
+ description: `${FILE_PATH_DESCRIPTION} The content of this path must be previously known.`,
266
+ }),
267
+ edits: z
268
+ .array(z.object({
269
+ old_str: z.string().meta({
270
+ description: "The text to replace (must match the file contents exactly, including all whitespace and indentation)",
271
+ }),
272
+ new_str: z.string().meta({
273
+ description: "The edited text to replace the old_str",
274
+ }),
275
+ replace_all: z.boolean().optional().meta({
276
+ description: "Replace all occurrences of old_str. This parameter is optional and defaults to false.",
277
+ }),
278
+ }))
279
+ .meta({
280
+ description: "An array of edit operations to perform, where each edit contains: old_str, new_str, replace_all",
281
+ }),
282
+ apply_with_error: z.boolean().nullish(),
283
+ })
284
+ .meta({ title: "MultiSearchReplaceInput" });
285
+ export const FindMediaToolInputSchema = z
286
+ .object({
287
+ query: z.string(),
288
+ type: z.enum(["image", "video"]),
289
+ orientation: z.enum(["landscape", "portrait", "square"]).nullish(),
290
+ hex_color: z.string().nullish(),
291
+ })
292
+ .meta({ title: "FindMediaToolInput" });
293
+ export const MediaToolInputSchema = z
294
+ .object({
295
+ query: z.string().meta({
296
+ description: "The text prompt describing the media to find or generate",
297
+ }),
298
+ type: z.enum(["image", "video", "gen-image"]).meta({
299
+ description: "The type of media: 'image' to search images, 'video' to search videos, or 'gen-image' to generate an AI image",
300
+ }),
301
+ orientation: z.enum(["landscape", "portrait", "square"]).nullish().meta({
302
+ description: "The orientation/aspect ratio of the media (landscape=wide, portrait=tall, square=1:1)",
303
+ }),
304
+ hex_color: z.string().nullish().meta({
305
+ description: "Optionally use to find images with the predominant specified hex color, for example '#000000' or '#FFFFFF'",
306
+ }),
307
+ input_image_urls: z.array(z.string()).nullish().meta({
308
+ description: 'Reference image URLs for AI image generation (only used with type: "gen-image")',
309
+ }),
310
+ })
311
+ .meta({ title: "MediaToolInput" });
312
+ export const MemoryToolInputSchema = z
313
+ .object({
314
+ content: z.string().meta({
315
+ description: "Markdown content of the memory, keep it factual and to the point. Avoid using line numbers, code snippets as they are likely to change.",
316
+ }),
317
+ when: z.string().meta({
318
+ description: "The semantic search query that will be used to retrieve this memory later. Describe the situation, task, or context when this memory should be surfaced.",
319
+ }),
320
+ category: z
321
+ .union([
322
+ z.literal("architecture").meta({
323
+ description: "System structure, layers, and responsibilities",
324
+ }),
325
+ z.literal("data-and-sync").meta({
326
+ description: "Data storage, persistence, synchronization, IPC, and state flow",
327
+ }),
328
+ z.literal("patterns-and-standards").meta({
329
+ description: "Canonical ways of doing things in this codebase",
330
+ }),
331
+ z.literal("coupling-and-duplication").meta({
332
+ description: "Cross-file, cross-surface, or duplicated logic that must stay aligned",
333
+ }),
334
+ z.literal("ui-and-ux-contracts").meta({
335
+ description: "User-visible behavior, UX guarantees, and UI rules",
336
+ }),
337
+ z.literal("concurrency-and-lifecycle").meta({
338
+ description: "Async behavior, ordering, lifecycle, and race prevention",
339
+ }),
340
+ z
341
+ .literal("invariants")
342
+ .meta({ description: "Hard rules that must always remain true" }),
343
+ z
344
+ .literal("security-and-trust")
345
+ .meta({ description: "Security, permissions, and trust boundaries" }),
346
+ z.literal("gotchas").meta({
347
+ description: "Known sharp edges that will break things if ignored",
348
+ }),
349
+ z.literal("constraints-and-limits").meta({
350
+ description: "System limits, assumptions, and non-obvious constraints",
351
+ }),
352
+ z.literal("rationale-and-history").meta({
353
+ description: "Why something is the way it is (tradeoffs, history, intent)",
354
+ }),
355
+ ])
356
+ .meta({ description: "The general category that this memory fits into" }),
357
+ glob: z.string().optional().meta({
358
+ description: "Glob pattern for file-based memory retrieval. Use specific paths (e.g., 'src/components/Button.tsx', 'lib/api/**/*.ts') rather than broad patterns (e.g., '*.tsx'). When files matching this glob are read, this memory will be suggested.",
359
+ }),
360
+ importance: z.number().optional(),
361
+ glob_auto_include: z.boolean().optional().meta({
362
+ description: "Whenever the memory should be included whenever the glob is matched.",
363
+ }),
364
+ })
365
+ .meta({ title: "MemoryToolInput" });
366
+ export const SearchMemoriesToolInputSchema = z
367
+ .object({
368
+ query: z.string(),
369
+ limit: z.number().optional(),
370
+ minSimilarity: z.number().optional(),
371
+ })
372
+ .meta({ title: "SearchMemoriesToolInput" });
373
+ export const ScoreMemoriesToolInputSchema = z
374
+ .object({
375
+ outcome: z.enum(["worked", "failed", "partial", "unknown"]),
376
+ memory_scores: z.record(z.string(), z.enum(["worked", "failed", "partial", "unknown"])),
377
+ })
378
+ .meta({ title: "ScoreMemoriesToolInput" });
379
+ /**
380
+ * Reusable `{ label, description }` option shape used by AskUserQuestion,
381
+ * ExitToolInput, ProposedConfig, ProposeConfigParams, etc.
382
+ */
383
+ export const LabelOptionSchema = z
384
+ .object({
385
+ label: z.string(),
386
+ description: z.string(),
387
+ })
388
+ .meta({ title: "LabelOption" });
389
+ export const AskUserQuestionOptionSchema = z
390
+ .strictObject({
391
+ label: z.string().meta({
392
+ description: "The display text for this option that the user will see and select. Should be concise (1-5 words) and clearly describe the choice.",
393
+ }),
394
+ description: z.string().meta({
395
+ description: "Explanation of what this option means or what will happen if chosen. Useful for providing context about trade-offs or implications.",
396
+ }),
397
+ preview: z.string().nullish().meta({
398
+ description: "Optional preview content rendered when this option is focused. Use for mockups, code snippets, or visual comparisons that help users compare options. See the tool description for the expected content format.",
399
+ }),
400
+ })
401
+ .meta({ title: "AskUserQuestionOption" });
402
+ export const AskUserQuestionSchema = z
403
+ .strictObject({
404
+ question: z.string().meta({
405
+ description: 'The complete question to ask the user. Should be clear, specific, and end with a question mark. Example: "Which library should we use for date formatting?" If multiSelect is true, phrase it accordingly, e.g. "Which features do you want to enable?"',
406
+ }),
407
+ header: z.string().meta({
408
+ description: 'Very short label displayed as a chip/tag (max 12 chars). Examples: "Auth method", "Library", "Approach".',
409
+ }),
410
+ options: z.array(AskUserQuestionOptionSchema).min(2).max(4).meta({
411
+ description: "The available choices for this question. Must have 2-4 options. Each option should be a distinct, mutually exclusive choice (unless multiSelect is enabled). There should be no 'Other' option, that will be provided automatically.",
412
+ }),
413
+ multiSelect: z.boolean().optional().meta({
414
+ description: "Set to true to allow the user to select multiple options instead of just one. Use when choices are not mutually exclusive.",
415
+ }),
416
+ })
417
+ .meta({ title: "AskUserQuestion" });
418
+ export const AskUserQuestionToolInputSchema = z
419
+ .strictObject({
420
+ questions: z
421
+ .array(AskUserQuestionSchema)
422
+ .min(1, "Must have at least 1 question")
423
+ .max(4)
424
+ .meta({ description: "Questions to ask the user (1-4 questions)" }),
425
+ answers: z
426
+ .record(z.string(), z.union([z.string(), z.array(z.string())]))
427
+ .optional(),
428
+ })
429
+ .meta({ title: "AskUserQuestionToolInput" });
430
+ export const AgentToolInputSchema = z
431
+ .object({
432
+ description: z
433
+ .string()
434
+ .meta({ description: "A short (3-5 word) description of the task" }),
435
+ prompt: z
436
+ .string()
437
+ .meta({ description: "The task for the agent to perform" }),
438
+ subagent_type: z.string().optional().meta({
439
+ description: "The type of specialized agent to use for this task",
440
+ }),
441
+ resume: z
442
+ .string()
443
+ .optional()
444
+ .meta({ description: "Optional agent ID to resume from" }),
445
+ origin_channel_id: z.string().optional().meta({
446
+ description: "The original user's channel_id that triggered this work. When provided, it will be included in the worker report so you can route the response back to the correct channel. Always pass this when spawning agents on behalf of a user request.",
447
+ }),
448
+ attachmentUrls: z.array(z.string()).optional().meta({
449
+ description: "URLs of images or files to attach to the agent's context. Useful for providing visual context like screenshots, designs, or reference images.",
450
+ }),
451
+ })
452
+ .meta({ title: "AgentToolInput" });
453
+ export const RevertToolInputSchema = z
454
+ .object({
455
+ checkpoint_id: z.string().meta({
456
+ description: "The checkpoint ID to revert back to. All changes from this checkpoint to HEAD will be reverted.",
457
+ }),
458
+ })
459
+ .meta({ title: "RevertToolInput" });
460
+ export const TodoReadToolInputSchema = z
461
+ .object({})
462
+ .meta({ title: "TodoReadToolInput" });
463
+ export const RunningAgentsToolInputSchema = z
464
+ .object({})
465
+ .meta({ title: "RunningAgentsToolInput" });
466
+ export const TodoWriteToolInputSchema = z
467
+ .object({
468
+ mode: z.enum(["replace", "patch"]).meta({
469
+ description: "Determine how the new todos update the current list: 'patch' means existing items will remain and only the provided items will be updated. The same 'id' must be provided for items you want to update. 'replace' means all existing items will be replaced with the new array of todos.",
470
+ }),
471
+ todos: z.array(z.object({
472
+ content: z.string().meta({
473
+ description: "The imperative form describing what needs to be done",
474
+ }),
475
+ status: z.enum(["pending", "in_progress", "completed"]),
476
+ id: z.string(),
477
+ })),
478
+ })
479
+ .meta({ title: "TodoWriteToolInput" });
480
+ export const TaskCreateToolInputSchema = z
481
+ .object({
482
+ subject: z.string().meta({ description: "A brief title for the task" }),
483
+ description: z.string().meta({ description: "What needs to be done" }),
484
+ metadata: z.record(z.string(), z.unknown()).optional(),
485
+ })
486
+ .meta({ title: "TaskCreateToolInput" });
487
+ export const TaskUpdateToolInputSchema = z
488
+ .object({
489
+ taskId: z.string().meta({ description: "The ID of the task to update" }),
490
+ subject: z.string().optional().meta({
491
+ description: "New subject for the task",
492
+ }),
493
+ description: z.string().optional().meta({
494
+ description: "New description for the task",
495
+ }),
496
+ status: z
497
+ .enum(["pending", "in_progress", "completed", "deleted"])
498
+ .optional()
499
+ .meta({ description: "New status for the task" }),
500
+ owner: z.string().optional().meta({
501
+ description: "New owner for the task",
502
+ }),
503
+ addBlocks: z.array(z.string()).optional().meta({
504
+ description: "Task IDs that this task blocks",
505
+ }),
506
+ addBlockedBy: z.array(z.string()).optional().meta({
507
+ description: "Task IDs that block this task",
508
+ }),
509
+ metadata: z.record(z.string(), z.unknown()).optional(),
510
+ })
511
+ .meta({ title: "TaskUpdateToolInput" });
512
+ export const TaskListToolInputSchema = z
513
+ .object({})
514
+ .meta({ title: "TaskListToolInput" });
515
+ export const BuilderEditToolInputSchema = z
516
+ .object({
517
+ filePath: z.string().meta({
518
+ description: "The path of the Mitosis file to edit (e.g., index.lite.tsx)",
519
+ }),
520
+ old_str: z.string().meta({
521
+ description: "Content to be replaced, this substring should appear verbatim in the selected file_path",
522
+ }),
523
+ new_str: z.string().meta({
524
+ description: "New content to replace the old content with",
525
+ }),
526
+ })
527
+ .meta({ title: "BuilderEditToolInput" });
528
+ export const GetScreenshotToolInputSchema = z
529
+ .object({
530
+ href: z.string().optional(),
531
+ selector: z.string().optional(),
532
+ width: z.number().optional(),
533
+ height: z.number().optional(),
534
+ })
535
+ .meta({ title: "GetScreenshotToolInput" });
536
+ export const NavigatePreviewToolInputSchema = z
537
+ .object({
538
+ href: z.string().meta({
539
+ description: "The URL or relative path to navigate the preview to (e.g., '/about' or 'https://example.com')",
540
+ }),
541
+ })
542
+ .meta({ title: "NavigatePreviewToolInput" });
543
+ export const WebFetchToolInputSchema = z
544
+ .object({
545
+ url: z.string().meta({ description: "The URL to fetch content from" }),
546
+ prompt: z.string().optional().meta({
547
+ description: "Optional prompt to describe the content you want to extract from the URL. Leave it blank to fetch images.",
548
+ }),
549
+ include_styles: z.boolean().optional().meta({
550
+ description: "If true, the computed styles of the page will be extracted, as well as a screenshot. Prompt must be provided",
551
+ }),
552
+ })
553
+ .meta({ title: "WebFetchToolInput" });
554
+ export const ExplorationMetadataToolInputSchema = z
555
+ .object({
556
+ category: z
557
+ .enum(["reusable_knowledge", "one_off", "bad_quality"])
558
+ .optional(),
559
+ gif_id: z.string().optional(),
560
+ timeline_id: z.string().optional(),
561
+ recording_id: z.string().optional(),
562
+ important_files: z.array(z.object({
563
+ file_path: z.string().meta({
564
+ description: "The relative path of the file to read",
565
+ }),
566
+ relevance: z.enum(["high", "medium", "low"]).optional().meta({
567
+ description: "The relevance of the file based on the initial user_prompt",
568
+ }),
569
+ offset: z.number().optional().meta({
570
+ description: "The offset of the file to read, in lines",
571
+ }),
572
+ limit: z.number().optional().meta({
573
+ description: "The limit of the file to read, in lines",
574
+ }),
575
+ })),
576
+ })
577
+ .meta({ title: "ExplorationMetadataToolInput" });
578
+ export const EnterPlanModeToolInputSchema = z
579
+ .object({})
580
+ .meta({ title: "EnterPlanModeToolInput" });
581
+ export const ExitPlanModeToolInputSchema = z
582
+ .object({
583
+ plan: z.string().meta({
584
+ description: "The plan you came up with, that you want to run by the user for approval. Supports markdown. The plan should be pretty concise. Do not include follow up questions in the plan.",
585
+ }),
586
+ handled: z.boolean().optional(),
587
+ })
588
+ .meta({ title: "ExitPlanModeToolInput" });
589
+ export const ReadMcpResourceToolInputSchema = z
590
+ .object({
591
+ uri: z.string().meta({
592
+ description: "The URI of the resource to read, matching a resource template pattern (e.g., 'file:///path/to/file')",
593
+ }),
594
+ serverName: z.string().optional().meta({
595
+ description: "Optional name of the MCP server to use. If not provided, will auto-detect based on URI.",
596
+ }),
597
+ })
598
+ .meta({ title: "ReadMcpResourceToolInput" });
599
+ export const TimelineEventCategorySchema = z
600
+ .enum([
601
+ "navigation",
602
+ "interaction",
603
+ "assertion",
604
+ "error",
605
+ "milestone",
606
+ "code-change",
607
+ "observation",
608
+ ])
609
+ .meta({ title: "TimelineEventCategory" });
610
+ export const TestOutcomeSchema = z
611
+ .enum(["succeeded", "couldnt_verify", "failed", "other"])
612
+ .meta({ title: "TestOutcome" });
613
+ export const TestCaseFailureCategorySchema = z
614
+ .enum([
615
+ "env_issue",
616
+ "creds_missing",
617
+ "needs_user_input",
618
+ "server_not_ready",
619
+ "feature_not_reachable",
620
+ "timeout",
621
+ "assertion_failed",
622
+ "unexpected_error",
623
+ "not_applicable",
624
+ "escalated",
625
+ ])
626
+ .meta({ title: "TestCaseFailureCategory" });
627
+ export const RecordFrameToolInputSchema = z
628
+ .object({
629
+ title: z.string().meta({
630
+ description: "A descriptive title for this frame (e.g., 'Login page loaded', 'Form submitted successfully')",
631
+ }),
632
+ frame: z.literal("last-image").meta({
633
+ description: "The frame source. Use 'last-image' to record the most recent screenshot.",
634
+ }),
635
+ category: TimelineEventCategorySchema.optional().meta({
636
+ description: "Category of this frame for timeline organization. Default: 'milestone'",
637
+ }),
638
+ description: z.string().optional().meta({
639
+ description: "Optional longer description providing context about what this frame shows.",
640
+ }),
641
+ })
642
+ .meta({ title: "RecordFrameToolInput" });
643
+ export const ReportTestOutcomeToolInputSchema = z
644
+ .object({
645
+ outcome: TestOutcomeSchema.meta({
646
+ description: "The structured test outcome",
647
+ }),
648
+ summary: z.string().meta({
649
+ description: "A concise 1–2 sentence summary explaining the test outcome",
650
+ }),
651
+ details: z.string().optional().meta({
652
+ description: "Optional additional context: error messages, steps attempted, etc.",
653
+ }),
654
+ test_case_id: z.string().optional().meta({
655
+ description: "Links to a test case ID (e.g., 'TC-01'). If present, this is a per-case report. If absent, this is the session-level summary.",
656
+ }),
657
+ evidence_frame_count: z.number().optional().meta({
658
+ description: "Number of RecordFrame calls made for this test case. Should be >= 1 for per-case reports.",
659
+ }),
660
+ failure_category: TestCaseFailureCategorySchema.optional().meta({
661
+ description: "Structured failure reason. Required when outcome is failed or couldnt_verify.",
662
+ }),
663
+ failure_detail: z.string().optional().meta({
664
+ description: "Human-readable failure explanation. E.g., 'Login page returned 403 — test account may have been disabled'",
665
+ }),
666
+ console_errors: z.string().optional(),
667
+ network_failures: z.string().optional(),
668
+ steps_attempted: z.string().optional(),
669
+ urls_tested: z.array(z.string()).optional(),
670
+ })
671
+ .meta({ title: "ReportTestOutcomeToolInput" });
672
+ /**
673
+ * Configuration values proposed by the setup analyzer agent
674
+ */
675
+ export const SetupAnalysisValuesSchema = z
676
+ .object({
677
+ projectOverview: z.object({
678
+ framework: z.string().nullable(),
679
+ packageManager: z.enum(["npm", "yarn", "pnpm", "bun"]).nullable(),
680
+ isMonorepo: z.boolean(),
681
+ detectedLanguage: z.enum(["typescript", "javascript"]).nullable(),
682
+ }),
683
+ rootDirectory: z
684
+ .object({
685
+ path: z.string(),
686
+ reason: z.string(),
687
+ })
688
+ .nullable(),
689
+ installCommand: z
690
+ .object({
691
+ command: z.string(),
692
+ reason: z.string(),
693
+ })
694
+ .nullable(),
695
+ runtimeDependencies: z.array(z.object({
696
+ tool: z.string(),
697
+ version: z.string(),
698
+ source: z.string(),
699
+ })),
700
+ devServer: z
701
+ .object({
702
+ command: z.string(),
703
+ url: z.string(),
704
+ port: z.number(),
705
+ reason: z.string(),
706
+ })
707
+ .nullable(),
708
+ environmentVariables: z.array(z.object({
709
+ key: z.string(),
710
+ description: z.string(),
711
+ isRequired: z.boolean(),
712
+ isSecret: z.boolean(),
713
+ defaultValue: z.string().nullable(),
714
+ source: z.string(),
715
+ })),
716
+ validationScript: z
717
+ .object({
718
+ command: z.string(),
719
+ reason: z.string(),
720
+ })
721
+ .nullable(),
722
+ npmrcContents: z.string().nullable(),
723
+ hasHotModuleReload: z
724
+ .object({
725
+ value: z.boolean(),
726
+ reason: z.string(),
727
+ })
728
+ .nullable(),
729
+ })
730
+ .meta({ title: "SetupAnalysisValues" });
731
+ export const ProposeConfigToolInputSchema = z
732
+ .object({
733
+ config: SetupAnalysisValuesSchema,
734
+ message: z.string().optional(),
735
+ })
736
+ .meta({ title: "ProposeConfigToolInput" });
737
+ // Field types for single-value setup updates
738
+ export const SetupValueFieldSchema = z
739
+ .enum([
740
+ "installCommand",
741
+ "devServer",
742
+ "validationScript",
743
+ "environmentVariables",
744
+ ])
745
+ .meta({ title: "SetupValueField" });
746
+ export const UpdateSetupValueToolInputSchema = z
747
+ .object({
748
+ field: SetupValueFieldSchema.meta({ description: "Which field to update" }),
749
+ value: z.object({
750
+ command: z.string().optional().meta({
751
+ description: "The command to run (for installCommand, devServer, validationScript)",
752
+ }),
753
+ url: z.string().optional().meta({
754
+ description: "Dev server URL (only for devServer)",
755
+ }),
756
+ port: z.number().optional().meta({
757
+ description: "Dev server port (only for devServer)",
758
+ }),
759
+ environmentVariables: z
760
+ .array(z.object({
761
+ key: z.string().meta({ description: "Variable name" }),
762
+ description: z.string().optional().meta({
763
+ description: "What this variable is for",
764
+ }),
765
+ isRequired: z.boolean().optional().meta({
766
+ description: "Whether this variable is required",
767
+ }),
768
+ isSecret: z.boolean().optional().meta({
769
+ description: "Whether this is a secret/credential",
770
+ }),
771
+ defaultValue: z.string().nullish(),
772
+ }))
773
+ .optional(),
774
+ }),
775
+ reason: z.string(),
776
+ })
777
+ .meta({ title: "UpdateSetupValueToolInput" });
778
+ export const ExitStateSchema = z
779
+ .enum([
780
+ "verified",
781
+ "no-frontend",
782
+ "empty-project",
783
+ "mobile-project",
784
+ "user-question",
785
+ "code-change-required",
786
+ "other",
787
+ "started",
788
+ "failed",
789
+ ])
790
+ .meta({
791
+ title: "ExitState",
792
+ description: "Current state: verified (all done), no-frontend (project has no dev server), empty-project (project has almost no code), mobile-project (mobile app e.g. Expo/React Native — recommend desktop local mode), user-question (need input), code-change-required (repo has code issues user must fix), other (other problem), started (Session started but Exit tool was never called (orphaned session)), failed (Session failed before reaching the agent (e.g. branch/container creation failed))",
793
+ });
794
+ export const ExitToolInputSchema = z
795
+ .object({
796
+ state: ExitStateSchema.meta({
797
+ description: "Current state: verified (all done), no-frontend (project has no dev server), empty-project (project has almost no code), mobile-project (mobile app e.g. Expo/React Native), user-question (need input), code-change-required (repo has code issues user must fix), other (other problem)",
798
+ }),
799
+ summary: z.string().meta({
800
+ description: "Brief summary of configuration outcome (what succeeded or what's needed)",
801
+ }),
802
+ questions: z
803
+ .array(z.object({
804
+ question: z.string().meta({ description: "Full question text" }),
805
+ context: z.string().meta({
806
+ description: "Why this information is needed",
807
+ }),
808
+ header: z.string().optional().meta({
809
+ description: 'Short label (e.g., "API Key", "Database URL")',
810
+ }),
811
+ type: z.enum(["select", "multi-select", "text"]).optional().meta({
812
+ description: 'Question type: "select" for single-choice, "multi-select" for multiple choices, "text" for free-form input. Defaults to "select" if options are present, "text" if not.',
813
+ }),
814
+ placeholder: z.string().optional().meta({
815
+ description: "Placeholder/hint text for 'text' type questions (e.g., 'Enter your API key', 'https://localhost:3000')",
816
+ }),
817
+ options: z.array(LabelOptionSchema).optional().meta({
818
+ description: "Suggested answer choices (for 'select' and 'multi-select' types). User can always choose 'Other'.",
819
+ }),
820
+ }))
821
+ .optional()
822
+ .meta({
823
+ description: "Questions for user (only when state is 'user-question'). Include suggested options when possible.",
824
+ }),
825
+ isMonorepo: z
826
+ .boolean()
827
+ .optional()
828
+ .meta({ description: "Repository contains multiple packages/apps" }),
829
+ isMicrofrontend: z.boolean().optional().meta({
830
+ description: "Frontend code served over multiple ports/servers",
831
+ }),
832
+ setupNeedsCredentials: z.boolean().optional().meta({
833
+ description: "Setup requires credentials (e.g., NPM_TOKEN for private packages)",
834
+ }),
835
+ devServerNeedsCredentials: z.boolean().optional().meta({
836
+ description: "Dev server needs special environment variables to run",
837
+ }),
838
+ needsVPN: z
839
+ .boolean()
840
+ .optional()
841
+ .meta({ description: "Setup requires a VPN connection" }),
842
+ autoReload: z.boolean().optional().meta({
843
+ description: "The dev server is able to reload the page automatically when the code changes, either through HMR or full page reload. Usually vite, webpack etc support this.",
844
+ }),
845
+ usesBuilderCms: z.boolean().optional().meta({
846
+ description: "The connected app uses Builder CMS (detected via @builder.io/react or @builder.io/sdk-* dependencies, a builder-registry file, or Builder CMS API keys such as BUILDER_PUBLIC_KEY)",
847
+ }),
848
+ stack: z.array(z.string()).optional().meta({
849
+ description: 'Technologies used by the connected application (not monorepo-wide). Include specific, high-confidence signals only, e.g. ["React", "Next.js", "Postgres", "Drizzle", "Tailwind CSS", "Clerk"]. Omit vague or uncertain entries.',
850
+ }),
851
+ projectDescription: z.string().optional().meta({
852
+ description: "A human-readable description of what this project is about — focus on purpose and domain, not technical stack. This helps route user requests to the right project (e.g., 'Company blog and content management', 'E-commerce storefront for selling shoes', 'Internal admin dashboard for managing users').",
853
+ }),
854
+ })
855
+ .meta({ title: "ExitToolInput" });
856
+ /**
857
+ * Configuration proposed by the configuration agent, stored in Firebase
858
+ */
859
+ const DevCommandStateValues = [
860
+ "running",
861
+ "stopped",
862
+ "starting",
863
+ "failed",
864
+ "unset",
865
+ ];
866
+ const SetupCommandStateValues = [
867
+ "not-installed",
868
+ "installing",
869
+ "installed",
870
+ "install-failed",
871
+ "install-aborted",
872
+ ];
873
+ const HttpServerStateValues = [
874
+ "ok-2xx",
875
+ "error-4xx",
876
+ "error-5xx",
877
+ "error-fetch",
878
+ "stopped",
879
+ "connecting",
880
+ ];
881
+ const ValidateCommandStateValues = [
882
+ "unset",
883
+ "running",
884
+ "stopped",
885
+ "success",
886
+ "failure",
887
+ ];
888
+ const ProposedQuestionSchema = z.object({
889
+ question: z.string(),
890
+ context: z.string(),
891
+ whatYouTried: z.string().optional(),
892
+ header: z
893
+ .string()
894
+ .optional()
895
+ .meta({ description: "Short label (e.g., 'API Key', 'Database URL')" }),
896
+ type: z.enum(["select", "multi-select", "text"]).optional().meta({
897
+ description: 'Question type: "select" for single-choice, "multi-select" for multiple choices, "text" for free-form input',
898
+ }),
899
+ placeholder: z
900
+ .string()
901
+ .optional()
902
+ .meta({ description: "Placeholder text for text-type questions" }),
903
+ options: z.array(LabelOptionSchema).optional(),
904
+ });
905
+ export const EnvironmentVariableSchema = z
906
+ .object({
907
+ key: z.string(),
908
+ value: z.string(),
909
+ isSecret: z.boolean(),
910
+ placeholder: z.boolean().optional().meta({
911
+ description: "If true, indicates this is a placeholder value that needs user replacement",
912
+ }),
913
+ explanation: z.string().optional().meta({
914
+ description: "Explanation of why this env var is needed and what value the user should provide",
915
+ }),
916
+ })
917
+ .meta({ title: "EnvironmentVariable" });
918
+ const ProposedConfigurationSchema = z.object({
919
+ setupCommand: z.object({
920
+ value: z.string().optional(),
921
+ verified: z
922
+ .boolean()
923
+ .meta({ description: "Based on setupState === 'installed'" }),
924
+ elapsed: z
925
+ .number()
926
+ .optional()
927
+ .meta({ description: "Time taken in milliseconds (if verified)" }),
928
+ }),
929
+ setupDependencies: z.object({
930
+ value: z.array(SetupDependencySchema).optional(),
931
+ verified: z
932
+ .boolean()
933
+ .meta({ description: "Based on setupState === 'installed'" }),
934
+ }),
935
+ devCommand: z.object({
936
+ value: z.string().optional(),
937
+ verified: z
938
+ .boolean()
939
+ .meta({ description: "Based on devState === 'running'" }),
940
+ elapsed: z
941
+ .number()
942
+ .optional()
943
+ .meta({ description: "Time taken in milliseconds (if verified)" }),
944
+ }),
945
+ devServer: z.object({
946
+ value: z.string().optional(),
947
+ verified: z
948
+ .boolean()
949
+ .meta({ description: "Based on httpServerState === 'ok-2xx'" }),
950
+ elapsed: z.number().optional().meta({
951
+ description: "Time taken in milliseconds waiting for the server to respond",
952
+ }),
953
+ }),
954
+ validateCommand: z.object({
955
+ value: z.string().optional(),
956
+ verified: z
957
+ .boolean()
958
+ .meta({ description: "Based on validateState === 'success'" }),
959
+ elapsed: z
960
+ .number()
961
+ .optional()
962
+ .meta({ description: "Time taken in milliseconds (if verified)" }),
963
+ }),
964
+ appOrigin: z.object({
965
+ value: z.string().optional(),
966
+ verified: z
967
+ .boolean()
968
+ .meta({ description: "Based on httpServerState === 'ok-2xx'" }),
969
+ }),
970
+ defaultOrigin: z.object({
971
+ value: z.string().optional(),
972
+ verified: z.boolean().meta({
973
+ description: "Always true if set (used with wildcard appOrigin)",
974
+ }),
975
+ }),
976
+ environmentVariables: z.object({
977
+ value: z.array(EnvironmentVariableSchema).optional(),
978
+ verified: z
979
+ .boolean()
980
+ .meta({ description: "Based on devState === 'running'" }),
981
+ }),
982
+ autoDetectDevServer: z.object({
983
+ value: z.boolean().optional(),
984
+ verified: z.boolean().meta({ description: "Always true if set" }),
985
+ }),
986
+ autoDetectDevServerPatterns: z.object({
987
+ value: z.array(z.string()).optional(),
988
+ verified: z.boolean().meta({ description: "Always true if set" }),
989
+ }),
990
+ hasHotModuleReload: z.object({
991
+ value: z.boolean().optional(),
992
+ reason: z
993
+ .string()
994
+ .optional()
995
+ .meta({ description: "Detection-only, not auto-applied" }),
996
+ }),
997
+ });
998
+ const ProposedOrchestratorStatesSchema = z.object({
999
+ setupState: z.enum(SetupCommandStateValues),
1000
+ devState: z.enum(DevCommandStateValues),
1001
+ httpServerState: z.enum(HttpServerStateValues),
1002
+ validateState: z.enum(ValidateCommandStateValues),
1003
+ });
1004
+ export const ProposedConfigSchema = z
1005
+ .object({
1006
+ id: z.string().meta({ description: "Auto-generated document ID" }),
1007
+ projectId: z.string(),
1008
+ branchName: z.string(),
1009
+ createdAt: z.number(),
1010
+ updatedAt: z.number(),
1011
+ ownerId: z.string(),
1012
+ state: ExitStateSchema.meta({
1013
+ description: "Configuration state from Exit tool",
1014
+ }),
1015
+ summary: z.string().meta({ description: "Summary from Exit tool" }),
1016
+ questions: z.array(ProposedQuestionSchema).optional(),
1017
+ configuration: ProposedConfigurationSchema,
1018
+ // Metadata
1019
+ sessionId: z.string(),
1020
+ orchestratorStates: ProposedOrchestratorStatesSchema,
1021
+ // Resource usage tracking
1022
+ peakDiskUsage: z
1023
+ .number()
1024
+ .optional()
1025
+ .meta({ description: "Peak disk usage in bytes" }),
1026
+ peakMemoryUsage: z
1027
+ .number()
1028
+ .optional()
1029
+ .meta({ description: "Peak memory usage in bytes" }),
1030
+ screenshotUrl: z.string().optional().meta({
1031
+ description: "Screenshot URL from verification (e.g., error page screenshot)",
1032
+ }),
1033
+ // Repository metadata and classifications
1034
+ isMonorepo: z.boolean().optional(),
1035
+ isMicrofrontend: z.boolean().optional(),
1036
+ setupNeedsCredentials: z.boolean().optional(),
1037
+ devServerNeedsCredentials: z.boolean().optional(),
1038
+ projectDescription: z.string().optional(),
1039
+ cost: z.number().optional(),
1040
+ durationMs: z.number().optional(),
1041
+ needsVPN: z.boolean().optional(),
1042
+ autoReload: z.boolean().optional(),
1043
+ usesBuilderCms: z.boolean().optional(),
1044
+ stack: z.array(z.string()).optional(),
1045
+ })
1046
+ .meta({
1047
+ title: "ProposedConfig",
1048
+ description: "Configuration proposed by the configuration agent, stored in Firebase",
1049
+ });
1050
+ /**
1051
+ * Parameters for proposing a configuration to the backend
1052
+ */
1053
+ export const ProposeConfigParamsSchema = z
1054
+ .object({
1055
+ projectId: z.string(),
1056
+ branchName: z.string(),
1057
+ state: ExitStateSchema,
1058
+ summary: z.string(),
1059
+ questions: z
1060
+ .array(z.object({
1061
+ question: z.string(),
1062
+ context: z.string(),
1063
+ whatYouTried: z.string().optional(),
1064
+ header: z.string().optional(),
1065
+ options: z.array(LabelOptionSchema).optional(),
1066
+ multiSelect: z.boolean().optional(),
1067
+ }))
1068
+ .optional(),
1069
+ configuration: ProposedConfigurationSchema,
1070
+ sessionId: z.string(),
1071
+ orchestratorStates: ProposedOrchestratorStatesSchema,
1072
+ peakDiskUsage: z.number().optional(),
1073
+ peakMemoryUsage: z.number().optional(),
1074
+ screenshotUrl: z.string().optional(),
1075
+ isMonorepo: z.boolean().optional(),
1076
+ isMicrofrontend: z.boolean().optional(),
1077
+ setupNeedsCredentials: z.boolean().optional(),
1078
+ devServerNeedsCredentials: z.boolean().optional(),
1079
+ needsVPN: z.boolean().optional(),
1080
+ projectDescription: z.string().optional(),
1081
+ autoReload: z.boolean().optional(),
1082
+ usesBuilderCms: z.boolean().optional(),
1083
+ stack: z.array(z.string()).optional(),
1084
+ })
1085
+ .meta({ title: "ProposeConfigParams" });
1086
+ // Verification tool inputs for project-configuration agent
1087
+ export const VerifySetupCommandToolInputSchema = z
1088
+ .object({
1089
+ command: z.string().meta({
1090
+ description: "The install command to run (e.g., 'npm install', 'yarn', 'pnpm install'). It can be a multi-line command too, just like a shell script.",
1091
+ }),
1092
+ dependencies: z
1093
+ .array(z.object({
1094
+ tool: z.string().meta({
1095
+ description: "The tool/binary to verify (e.g., 'node', 'npm', 'git')",
1096
+ }),
1097
+ version: z.string().optional().meta({
1098
+ description: "Optional version requirement (e.g., '>=18.0.0', '20.x')",
1099
+ }),
1100
+ }))
1101
+ .optional(),
1102
+ })
1103
+ .meta({ title: "VerifySetupCommandToolInput" });
1104
+ export const VerifyDevCommandToolInputSchema = z
1105
+ .object({
1106
+ command: z.string().meta({
1107
+ description: "The dev server command to run (e.g., 'npm run dev', 'cd packages/frontend && yarn dev')",
1108
+ }),
1109
+ })
1110
+ .meta({ title: "VerifyDevCommandToolInput" });
1111
+ export const VerifyDevServerToolInputSchema = z
1112
+ .object({
1113
+ autoDetect: z.boolean().meta({
1114
+ description: "Whether to automatically detect the dev server URL from terminal output",
1115
+ }),
1116
+ autoDetectPattern: z.string().optional().meta({
1117
+ description: "Pattern to match and extract URL from terminal output when multiple URLs are present (e.g., 'Local:.*http://localhost:\\\\d+')",
1118
+ }),
1119
+ hardcodedUrl: z.string().optional().meta({
1120
+ description: "The hardcoded dev server URL to use when autoDetect is false (e.g., 'http://localhost:3000')",
1121
+ }),
1122
+ appOrigin: z.string().meta({
1123
+ description: "The origin where the app should be accessed (e.g., 'https://acme.com', 'https://*.acme.com'). Can be a pattern with wildcard.",
1124
+ }),
1125
+ defaultOrigin: z.string().optional().meta({
1126
+ description: "Default origin to use when appOrigin is a pattern (e.g., 'https://dev.acme.com'). Required if appOrigin contains a wildcard.",
1127
+ }),
1128
+ })
1129
+ .meta({ title: "VerifyDevServerToolInput" });
1130
+ export const VerifyValidateCommandToolInputSchema = z
1131
+ .object({
1132
+ command: z.string(),
1133
+ timeout: z.number().optional().meta({
1134
+ description: "Default: 300000 (5 minutes)",
1135
+ }),
1136
+ })
1137
+ .meta({ title: "VerifyValidateCommandToolInput" });
1138
+ export const ProposeEnvVariableToolInputSchema = z
1139
+ .object({
1140
+ key: z.string().meta({
1141
+ description: "The environment variable name (e.g., 'NODE_ENV', 'API_KEY')",
1142
+ }),
1143
+ value: z.string().meta({
1144
+ description: "The environment variable value. Must be a concrete value, not a placeholder.",
1145
+ }),
1146
+ secret: z.boolean().optional().meta({
1147
+ description: "Whether this is a secret value (will be masked in logs). Default: false",
1148
+ }),
1149
+ })
1150
+ .meta({ title: "ProposeEnvVariableToolInput" });
1151
+ export const SetEnvVariableToolInputSchema = z
1152
+ .object({
1153
+ key: z.string().meta({
1154
+ description: "The environment variable name (e.g., 'NODE_ENV', 'API_KEY')",
1155
+ }),
1156
+ value: z.string().meta({
1157
+ description: "The environment variable value. Use clear placeholder like 'PLACEHOLDER_DATABASE_URL' if actual value is unknown.",
1158
+ }),
1159
+ secret: z.boolean().optional().meta({
1160
+ description: "Whether this is a secret value (will be masked in logs). Default: false",
1161
+ }),
1162
+ placeholder: z.boolean().optional().meta({
1163
+ description: "If true, indicates this is a placeholder value that needs user replacement",
1164
+ }),
1165
+ explanation: z.string().optional().meta({
1166
+ description: "Explanation of why this env var is needed and what value the user should provide",
1167
+ }),
1168
+ })
1169
+ .meta({ title: "SetEnvVariableToolInput" });
1170
+ export const SetFileOverrideToolInputSchema = z
1171
+ .object({
1172
+ path: z.string().meta({
1173
+ description: 'Path where the file should be written. Supports absolute paths ("/app/.npmrc"), tilde ("~/.npmrc") and paths relative to the project working directory ("./.npmrc"). Use this tool ONLY for configuration-only files that should NOT be committed to the repo (e.g. `.npmrc` with auth tokens, machine-local env files) — never to patch source code or fix software issues.',
1174
+ }),
1175
+ content: z.string().optional().meta({
1176
+ description: "Plain text content to write to the file. Mutually exclusive with `base64`.",
1177
+ }),
1178
+ base64: z.string().optional().meta({
1179
+ description: "Base64-encoded binary content to write to the file. Mutually exclusive with `content`. Use only when the file is genuinely binary.",
1180
+ }),
1181
+ })
1182
+ .meta({ title: "SetFileOverrideToolInput" });
1183
+ export const SendMessageToolInputSchema = z
1184
+ .object({
1185
+ channel_id: z.string().meta({
1186
+ description: "The channel identifier in URI format (see supported formats in the tool description)",
1187
+ }),
1188
+ markdown: z.string().meta({
1189
+ description: "The message content to send in markdown format",
1190
+ }),
1191
+ status: z.enum([
1192
+ "starting",
1193
+ "question",
1194
+ "will-follow-up",
1195
+ "done:success",
1196
+ "done:error",
1197
+ ]),
1198
+ loading_message: z.string().optional().meta({
1199
+ description: "Loading message displayed in the Slack thread while the agent is working (only used when status is 'starting').",
1200
+ }),
1201
+ voice_response: z.boolean().optional().meta({
1202
+ description: "When true, send the response as a voice message using text-to-speech. Only supported for Telegram channels. Only set to true when the user's original message was a voice/audio message (look for '[Voice message transcription]' or '[Audio' markers), the channel is Telegram, and the response is short and conversational with no URLs, code, lists, or other content that doesn't translate to audio. Default to false (text) for all text-originated messages.",
1203
+ }),
1204
+ from_user_id: z.string().optional().meta({
1205
+ description: "Builder.io user ID this message is from / should be attributed to. Only allowed when channel_id is 'builder/branch/{project_id}/{branch_name}'. When set, the message is delivered to the target branch as coming from this user (role 'user') instead of from the agent. Use whenever the message represents user feedback/intent that should be assigned to someone — even if it was composed, summarized, or merged from multiple people.",
1206
+ }),
1207
+ })
1208
+ .meta({ title: "SendMessageToolInput" });
1209
+ export const SpawnBranchToolInputSchema = z
1210
+ .object({
1211
+ project_id: z.string().meta({
1212
+ description: "The project ID to create the branch in",
1213
+ }),
1214
+ message: z.string().meta({
1215
+ description: "The initial message or task description for the branch. Do NOT include instructions to open or create a PR unless the user's original request explicitly asked for a PR.",
1216
+ }),
1217
+ builder_user_id: z.string().optional().meta({
1218
+ description: "Builder.io user ID to act as. When provided, the branch will be created as if this user created it.",
1219
+ }),
1220
+ hidden: z.boolean().optional().meta({
1221
+ description: "Whether to hide the branch from the user. Useful for exploratory branches not intended to ever get merged back to main. Default: false.",
1222
+ }),
1223
+ origin_channel_id: z.string().optional().meta({
1224
+ description: "The channel identifier that originally triggered this work. Used for tracking purposes and coming back to the original slack thread with updates.",
1225
+ }),
1226
+ session_mode: z.enum(["normal", "planning", "deep-research"]).optional(),
1227
+ model: z.enum(["auto", "opus", "sonnet", "haiku"]).optional(),
1228
+ attachment_urls: z.array(z.string()).optional(),
1229
+ git_base_branch: z.string().optional(),
1230
+ auto_archive_on_idle: z.boolean().optional(),
1231
+ })
1232
+ .meta({ title: "SpawnBranchToolInput" });
1233
+ export const CreateProjectToolInputSchema = z
1234
+ .object({
1235
+ repo_url: z.string().meta({
1236
+ description: "Repository URL (regular Git URL or template:// URL)",
1237
+ }),
1238
+ name: z.string().optional().meta({
1239
+ description: "Human-readable name for the project. If not provided, a name will be generated from the repo name.",
1240
+ }),
1241
+ builder_user_id: z.string().meta({
1242
+ description: "Builder.io user ID to act as. The project and branch will be created as if this user created them, and their git credentials will be validated before creation.",
1243
+ }),
1244
+ origin_channel_id: z.string().optional().meta({
1245
+ description: "The channel_id identifier that originally triggered this work. Used for routing status updates back to the user.",
1246
+ }),
1247
+ initial_message: z.string().optional().meta({
1248
+ description: "Only valid for template:// URLs — creates a branch with this message",
1249
+ }),
1250
+ })
1251
+ .meta({ title: "CreateProjectToolInput" });
1252
+ export const GetAvailableReposToolInputSchema = z
1253
+ .object({})
1254
+ .meta({ title: "GetAvailableReposToolInput" });
1255
+ export const ReadBranchToolInputSchema = z
1256
+ .object({
1257
+ project_id: z.string().meta({
1258
+ description: "The project ID containing the branch",
1259
+ }),
1260
+ branch_name: z.string().meta({
1261
+ description: "The name of the branch to read",
1262
+ }),
1263
+ })
1264
+ .meta({ title: "ReadBranchToolInput" });
1265
+ export const ArchiveBranchToolInputSchema = z
1266
+ .object({
1267
+ project_id: z.string().meta({
1268
+ description: "The project ID containing the branch",
1269
+ }),
1270
+ branch_name: z.string().meta({
1271
+ description: "The name of the branch to archive",
1272
+ }),
1273
+ builder_user_id: z.string().meta({
1274
+ description: "The Builder.io user ID of the person requesting the archive. This is used to attribute the archive action to a specific user.",
1275
+ }),
1276
+ reason: z.string().optional().meta({
1277
+ description: "The reason for archiving this branch (max 500 chars). Examples: 'Work completed and merged', 'No longer needed', 'Superseded by branch X'.",
1278
+ }),
1279
+ })
1280
+ .meta({ title: "ArchiveBranchToolInput" });
1281
+ export const ReviewSeveritySchema = z
1282
+ .enum(["high", "medium", "low"])
1283
+ .meta({ title: "ReviewSeverity" });
1284
+ /** Comment for PR review - used by SubmitPRReview */
1285
+ export const PRReviewCommentSchema = z
1286
+ .object({
1287
+ file_path: z.string().meta({
1288
+ description: "Relative file path - MUST be a file that appears in the PR diff",
1289
+ }),
1290
+ line: z.number().meta({
1291
+ description: "Line number in the file (end line for multi-line). MUST be a line within the PR diff",
1292
+ }),
1293
+ start_line: z.number().optional().meta({
1294
+ description: "For multi-line comments (optional)",
1295
+ }),
1296
+ side: z.enum(["LEFT", "RIGHT"]).optional().meta({
1297
+ description: "Diff side. RIGHT (default) = NEW file (added/context). LEFT = OLD file (removed/context). Use LEFT only when commenting on deleted code with no semantically related new-side anchor.",
1298
+ }),
1299
+ title: z.string().meta({
1300
+ description: "Brief plain-text issue title. MUST NOT start with severity emojis",
1301
+ }),
1302
+ body: z.string().meta({ description: "Review comment (1-2 sentences)" }),
1303
+ severity: ReviewSeveritySchema.meta({
1304
+ description: "Issue severity: high (blocking), medium (should fix), or low (minor observation)",
1305
+ }),
1306
+ debugInfo: z.string().optional(),
1307
+ gif_id: z.string().optional().meta({
1308
+ description: "Per-comment GIF (optional)",
1309
+ }),
1310
+ })
1311
+ .meta({ title: "PRReviewComment" });
1312
+ export const ReviewVerdictSchema = z
1313
+ .enum(["looks_good", "has_findings", "blocking"])
1314
+ .meta({ title: "ReviewVerdict" });
1315
+ /** SubmitPRReview - Fast code review without recording */
1316
+ export const SubmitPRReviewToolInputSchema = z
1317
+ .object({
1318
+ summary: z.string().meta({
1319
+ description: "Your detailed analysis of the changes (displayed in a collapsible 'Review Details' section)",
1320
+ }),
1321
+ comments: z.array(PRReviewCommentSchema).optional(),
1322
+ risk_level: ReviewSeveritySchema.optional(),
1323
+ verdict: ReviewVerdictSchema.optional(),
1324
+ })
1325
+ .meta({ title: "SubmitPRReviewToolInput" });
1326
+ export const ResolveQACommentsToolInputSchema = z
1327
+ .object({
1328
+ thread_node_ids: z.array(z.string()).meta({
1329
+ description: "GraphQL thread node_ids (PRRT_...) from previous review response",
1330
+ }),
1331
+ })
1332
+ .meta({ title: "ResolveQACommentsToolInput" });
1333
+ export const ReportUIIssueToolInputSchema = z
1334
+ .object({
1335
+ title: z.string().meta({
1336
+ description: "Brief summary of the issue (e.g., 'Button click has no effect')",
1337
+ }),
1338
+ description: z.string().meta({
1339
+ description: "Detailed description of what went wrong, what was expected, and what actually happened",
1340
+ }),
1341
+ debugInfo: z.string().optional().meta({
1342
+ description: "Optional console errors, stack traces, or other diagnostic information",
1343
+ }),
1344
+ })
1345
+ .meta({ title: "ReportUIIssueToolInput" });
1346
+ export const ReportIssueToolInputSchema = z
1347
+ .object({
1348
+ file_path: z.string().meta({
1349
+ description: "File path where the issue occurs (e.g., 'packages/api/src/auth.ts')",
1350
+ }),
1351
+ line: z.number().meta({
1352
+ description: "End line number of the issue range (or single line if no start_line)",
1353
+ }),
1354
+ start_line: z.number().optional().meta({
1355
+ description: "Optional start line for multi-line issues. When provided, the comment spans from start_line to line",
1356
+ }),
1357
+ title: z.string().meta({
1358
+ description: "Short, descriptive title (one line, no markdown)",
1359
+ }),
1360
+ severity: ReviewSeveritySchema.meta({
1361
+ description: "Issue severity: high for critical bugs, medium for should-fix, low for minor observations",
1362
+ }),
1363
+ body: z.string().meta({
1364
+ description: "Detailed explanation in markdown format. Should include: What the issue is, Why it's problematic, Impact, How to fix it, Evidence",
1365
+ }),
1366
+ })
1367
+ .meta({ title: "ReportIssueToolInput" });
1368
+ export const EscalateToPlannerSchema = z
1369
+ .object({
1370
+ issue: z.string().meta({ description: "What's blocking execution" }),
1371
+ steps_attempted: z
1372
+ .string()
1373
+ .meta({ description: "What was tried before escalating" }),
1374
+ current_url: z.string().meta({ description: "Current browser URL" }),
1375
+ test_case_id: z
1376
+ .string()
1377
+ .meta({ description: "Which test case is blocked" }),
1378
+ })
1379
+ .meta({ title: "EscalateToPlanner" });
1380
+ export const GetLastBrowserTestToolInputSchema = z
1381
+ .object({})
1382
+ .meta({ title: "GetLastBrowserTestToolInput" });
1383
+ export const IDEDiagnosticsToolInputSchema = z
1384
+ .object({
1385
+ file_path: z.string().optional().meta({
1386
+ description: "Optional relative or absolute path to filter diagnostics to a single file. Omit to retrieve diagnostics for the entire workspace.",
1387
+ }),
1388
+ })
1389
+ .meta({ title: "IDEDiagnosticsToolInput" });
1390
+ export const PullPrototypeToolInputSchema = z
1391
+ .object({
1392
+ url: z.string().meta({
1393
+ description: "The prototype URL (e.g., https://builder.io/app/projects/<projectId>/<branchName>)",
1394
+ }),
1395
+ project_id: z.string().optional().meta({
1396
+ description: "The project ID (optional, parsed from URL if not provided)",
1397
+ }),
1398
+ branch_name: z.string().optional().meta({
1399
+ description: "The branch name (optional, parsed from URL if not provided)",
1400
+ }),
1401
+ })
1402
+ .meta({ title: "PullPrototypeToolInput" });
1403
+ export const EnsurePRToolInputSchema = z
1404
+ .object({
1405
+ project_id: z.string().meta({
1406
+ description: "The Builder.io project ID containing the branch",
1407
+ }),
1408
+ branch_name: z.string().meta({
1409
+ description: "The Fusion branch name to push and open a PR for",
1410
+ }),
1411
+ builder_user_id: z.string().optional().meta({
1412
+ description: "Builder.io user ID to attribute the PR to. When provided, the PR body will credit this user and the user must be a member of the organization. Highly recommended when the PR is being opened on behalf of a specific user.",
1413
+ }),
1414
+ draft: z.boolean().optional().meta({
1415
+ description: 'Whether to create the PR as a draft. When omitted, defaults to the branch\'s configured commitMode: true for "draft-prs" branches, false for "prs" branches.',
1416
+ }),
1417
+ })
1418
+ .meta({ title: "EnsurePRToolInput" });
1419
+ export const ConnectMCPToolInputSchema = z
1420
+ .object({
1421
+ name: z.string().meta({
1422
+ description: 'Human-readable name of the service to connect, e.g. "Jira", "Linear", "Sentry"',
1423
+ }),
1424
+ url: z.string().optional().meta({
1425
+ description: "Remote MCP endpoint URL (e.g. https://mcp.linear.app/mcp). When omitted, the tool discovers known URLs for the named service instead.",
1426
+ }),
1427
+ })
1428
+ .meta({ title: "ConnectMCPToolInput" });
1429
+ export const CodeGenToolMapSchema = z.object({
1430
+ Read: ReadToolInputSchema,
1431
+ Write: WriteFileInputSchema,
1432
+ Edit: SearchReplaceInputSchema,
1433
+ ReadRule: GetRuleToolInputSchema,
1434
+ Skill: SkillToolInputSchema,
1435
+ GetStyleInspiration: GetStyleInspirationToolInputSchema,
1436
+ GetScreenshot: GetScreenshotToolInputSchema,
1437
+ NavigatePreview: NavigatePreviewToolInputSchema,
1438
+ MultiEdit: MultiSearchReplaceInputSchema,
1439
+ FindMedia: FindMediaToolInputSchema,
1440
+ Media: MediaToolInputSchema,
1441
+ AddMemory: MemoryToolInputSchema,
1442
+ SearchMemories: SearchMemoriesToolInputSchema,
1443
+ ScoreMemories: ScoreMemoriesToolInputSchema,
1444
+ Bash: BashToolInputSchema,
1445
+ PowerShell: PowerShellToolInputSchema,
1446
+ WebSearch: WebSearchToolInputSchema,
1447
+ AskUserQuestion: AskUserQuestionToolInputSchema,
1448
+ Agent: AgentToolInputSchema,
1449
+ Grep: GrepSearchToolInputSchema,
1450
+ Glob: GlobSearchToolInputSchema,
1451
+ DevServerControl: DevServerControlInputSchema,
1452
+ DevServerLogs: DevServerLogsInputSchema,
1453
+ DevServerRestart: DevServerRestartInputSchema,
1454
+ Revert: RevertToolInputSchema,
1455
+ TodoRead: TodoReadToolInputSchema,
1456
+ TodoWrite: TodoWriteToolInputSchema,
1457
+ TaskCreate: TaskCreateToolInputSchema,
1458
+ TaskUpdate: TaskUpdateToolInputSchema,
1459
+ TaskList: TaskListToolInputSchema,
1460
+ BuilderEdit: BuilderEditToolInputSchema,
1461
+ WebFetch: WebFetchToolInputSchema,
1462
+ ExplorationMetadata: ExplorationMetadataToolInputSchema,
1463
+ EnterPlanMode: EnterPlanModeToolInputSchema,
1464
+ ExitPlanMode: ExitPlanModeToolInputSchema,
1465
+ ReadMcpResource: ReadMcpResourceToolInputSchema,
1466
+ RecordFrame: RecordFrameToolInputSchema,
1467
+ SubmitPRReview: SubmitPRReviewToolInputSchema,
1468
+ ProposeConfig: ProposeConfigToolInputSchema,
1469
+ UpdateSetupValue: UpdateSetupValueToolInputSchema,
1470
+ Exit: ExitToolInputSchema,
1471
+ ResolveQAComments: ResolveQACommentsToolInputSchema,
1472
+ GetLastBrowserTest: GetLastBrowserTestToolInputSchema,
1473
+ ReportUIIssue: ReportUIIssueToolInputSchema,
1474
+ ReportIssue: ReportIssueToolInputSchema,
1475
+ ReportTestOutcome: ReportTestOutcomeToolInputSchema,
1476
+ VerifySetupCommand: VerifySetupCommandToolInputSchema,
1477
+ VerifyDevCommand: VerifyDevCommandToolInputSchema,
1478
+ VerifyDevServer: VerifyDevServerToolInputSchema,
1479
+ VerifyValidateCommand: VerifyValidateCommandToolInputSchema,
1480
+ ProposeEnvVariable: ProposeEnvVariableToolInputSchema,
1481
+ SetEnvVariable: SetEnvVariableToolInputSchema,
1482
+ SetFileOverride: SetFileOverrideToolInputSchema,
1483
+ SendMessage: SendMessageToolInputSchema,
1484
+ SpawnBranch: SpawnBranchToolInputSchema,
1485
+ CreateProject: CreateProjectToolInputSchema,
1486
+ GetAvailableRepos: GetAvailableReposToolInputSchema,
1487
+ ReadBranch: ReadBranchToolInputSchema,
1488
+ ArchiveBranch: ArchiveBranchToolInputSchema,
1489
+ RunningAgents: RunningAgentsToolInputSchema,
1490
+ IDEDiagnostics: IDEDiagnosticsToolInputSchema,
1491
+ EscalateToPlanner: EscalateToPlannerSchema,
1492
+ PullPrototype: PullPrototypeToolInputSchema,
1493
+ ConnectMCP: ConnectMCPToolInputSchema,
1494
+ EnsurePR: EnsurePRToolInputSchema,
1495
+ });
1496
+ export const CodeGenToolsSchema = CodeGenToolMapSchema.keyof().meta({
1497
+ title: "CodeGenTools",
1498
+ });
1499
+ export const SessionModeSchema = z
1500
+ .enum(["planning", "normal", "auto-planning", "deep-research"])
1501
+ .meta({ title: "SessionMode" });
1502
+ export const CodeGenModeSchema = z
1503
+ .enum([
1504
+ "quality",
1505
+ "quality-v4",
1506
+ /**
1507
+ * @deprecated Use `quality-v4` instead. Kept for backwards compatibility
1508
+ * with older dev-tools clients in the wild that may still request this mode
1509
+ * for sub-agents. New code should not produce this value.
1510
+ */
1511
+ "quality-v4-agent",
1512
+ ])
1513
+ .meta({ title: "CodeGenMode" });
6
1514
  export const DEFAULT_QUEUE_BEHAVIOR = {
7
1515
  schedule: "next-turn",
8
1516
  coalesce: "merge",
@@ -47,3 +1555,378 @@ export const BASE_CODEGEN_POSITIONS = [
47
1555
  "design-system-indexer",
48
1556
  "builder-publish-integration",
49
1557
  ];
1558
+ export const BaseCodeGenPositionSchema = z
1559
+ .enum(BASE_CODEGEN_POSITIONS)
1560
+ .meta({ title: "BaseCodeGenPosition" });
1561
+ export const CodeGenPositionSchema = z
1562
+ .union([
1563
+ BaseCodeGenPositionSchema,
1564
+ z.templateLiteral([BaseCodeGenPositionSchema, "-agent"]),
1565
+ ])
1566
+ .meta({ title: "CodeGenPosition" });
1567
+ export const RepoIndexingConfigSchema = z
1568
+ .object({
1569
+ designSystems: z.array(z.string()),
1570
+ })
1571
+ .meta({ title: "RepoIndexingConfig" });
1572
+ export const LocalMCPToolsSchema = z
1573
+ .object({
1574
+ name: z.string(),
1575
+ description: z.string().optional(),
1576
+ inputSchema: z.any().optional(),
1577
+ serverName: z.string(),
1578
+ })
1579
+ .meta({ title: "LocalMCPTools" });
1580
+ export const CodeGenCategorySchema = z
1581
+ .union([
1582
+ z.templateLiteral(["repair-", z.string()]),
1583
+ z.literal("user-normal"),
1584
+ z.literal("user-figma"),
1585
+ z.literal("user-pdf"),
1586
+ z.literal("user-image"),
1587
+ z.literal("setup-agent"),
1588
+ z.templateLiteral(["background-", z.string()]),
1589
+ z.templateLiteral(["indexing-", z.string()]),
1590
+ ])
1591
+ .meta({ title: "CodeGenCategory" });
1592
+ export const UserSourcePermissionSchema = z
1593
+ .enum([
1594
+ "editCode",
1595
+ "modifyMcpServers",
1596
+ "modifyProjectSettings",
1597
+ "createBranches",
1598
+ "sendPullRequests",
1599
+ "view",
1600
+ ])
1601
+ .meta({ title: "UserSourcePermission" });
1602
+ const userSourceBaseShape = {
1603
+ role: z.enum(["user", "agent"]),
1604
+ principals: z
1605
+ .array(z.string())
1606
+ .optional()
1607
+ .meta({ description: "teams/roles like ['developer', 'admin']" }),
1608
+ jobs: z.array(z.string()).optional().meta({
1609
+ description: "job titles like ['designer', 'developer'] - used for role-aware communication instead of principals when available",
1610
+ }),
1611
+ permissions: z.array(UserSourcePermissionSchema).optional(),
1612
+ channelId: z.string().optional(),
1613
+ };
1614
+ export const UserSourceBaseSchema = z
1615
+ .object(userSourceBaseShape)
1616
+ .meta({ title: "UserSourceBase" });
1617
+ /** All integration sources: Slack, Teams, Jira, Linear, and git providers (GitHub, GitLab, Azure, Bitbucket). */
1618
+ export const UserSourceOtherSchema = z
1619
+ .object({
1620
+ ...userSourceBaseShape,
1621
+ source: z.enum([
1622
+ "slack",
1623
+ "telegram",
1624
+ "whatsapp",
1625
+ "teams",
1626
+ "jira",
1627
+ "linear",
1628
+ "github",
1629
+ "gitlab",
1630
+ "azure",
1631
+ "bitbucket",
1632
+ ]),
1633
+ userId: z.string().optional().meta({
1634
+ description: "User ID from the external platform (Slack user ID, GitHub user id, etc.)",
1635
+ }),
1636
+ userName: z.string().optional(),
1637
+ userEmail: z.string().optional(),
1638
+ photoURL: z.string().optional(),
1639
+ builderUserId: z.string().optional().meta({
1640
+ description: "Resolved Builder user ID for attribution/credits",
1641
+ }),
1642
+ link: z.string().optional().meta({
1643
+ description: "Optional link (e.g. comment/PR URL) for git provider sources",
1644
+ }),
1645
+ })
1646
+ .meta({ title: "UserSourceOther" });
1647
+ export const UserSourceBuilderSchema = z
1648
+ .object({
1649
+ ...userSourceBaseShape,
1650
+ source: z.literal("builder.io"),
1651
+ userId: z.string().optional(),
1652
+ userName: z.string().optional(),
1653
+ userEmail: z.string().optional(),
1654
+ photoURL: z.string().optional(),
1655
+ })
1656
+ .meta({ title: "UserSourceBuilder" });
1657
+ export const UserSourceAgentSchema = z
1658
+ .object({
1659
+ ...userSourceBaseShape,
1660
+ source: z.literal("agent"),
1661
+ userId: z.string().optional(),
1662
+ userName: z.string().optional(),
1663
+ userEmail: z.string().optional(),
1664
+ })
1665
+ .meta({ title: "UserSourceAgent" });
1666
+ export const UserSourceSchema = z
1667
+ .discriminatedUnion("source", [
1668
+ UserSourceOtherSchema,
1669
+ UserSourceBuilderSchema,
1670
+ UserSourceAgentSchema,
1671
+ ])
1672
+ .meta({ title: "UserSource" });
1673
+ export const PermissionSchema = z
1674
+ .enum(["read", "write", "list"])
1675
+ .meta({ title: "Permission" });
1676
+ // One ACL rule
1677
+ export const AclEntrySchema = z
1678
+ .object({
1679
+ action: z
1680
+ .enum(["allow", "deny"])
1681
+ .meta({ description: "whether this rule allows or denies access" }),
1682
+ resource: z
1683
+ .string()
1684
+ .meta({ description: "what — supports glob patterns like /files/*.txt" }),
1685
+ permissions: z
1686
+ .array(PermissionSchema)
1687
+ .meta({ description: "actions this rule applies to" }),
1688
+ description: z.string().optional().meta({
1689
+ description: "custom message, in deny case, this is the error message. This will override denyDescription on AclPolicy if defined.",
1690
+ }),
1691
+ principals: z.array(z.string()).optional().meta({
1692
+ description: "array of teams/roles this rule applies to (e.g., ['developer', 'admin'])",
1693
+ }),
1694
+ })
1695
+ .meta({ title: "AclEntry" });
1696
+ // A full ACL policy is just a list of rules
1697
+ export const AclPolicySchema = z
1698
+ .object({
1699
+ secrets: z.array(z.string()).optional(),
1700
+ entries: z.array(AclEntrySchema).optional(),
1701
+ denyDescription: z.string().optional().meta({
1702
+ description: "Default message to use when a resource is denied access",
1703
+ }),
1704
+ })
1705
+ .meta({ title: "AclPolicy" });
1706
+ export const SystemReminderObjSchema = z
1707
+ .object({
1708
+ text: z.string(),
1709
+ tag: z.string().optional(),
1710
+ ephemeral: z.boolean().optional(),
1711
+ })
1712
+ .meta({ title: "SystemReminderObj" });
1713
+ export const SystemReminderSchema = z
1714
+ .union([z.string(), SystemReminderObjSchema])
1715
+ .meta({ title: "SystemReminder" });
1716
+ // Schema for CodeGenInputOptions. This is `z.looseObject` so unknown / forward-compat
1717
+ // fields pass through. Fields marked `@internal` (function values, middleware-set
1718
+ // markers) are excluded from the schema and added back via TypeScript intersection
1719
+ // in the `CodeGenInputOptions` type below.
1720
+ //
1721
+ // BuilderContent and PrettierOptions are declared in other modules.
1722
+ // For those we use `z.custom<T>()` as a forward-reference: the inferred TS type is correct,
1723
+ // runtime validation is identity-only.
1724
+ export const CodeGenInputOptionsSchema = z
1725
+ .looseObject({
1726
+ position: CodeGenPositionSchema,
1727
+ eventName: z.string().optional(),
1728
+ sessionId: z.string(),
1729
+ codeGenMode: CodeGenModeSchema.optional(),
1730
+ sessionMode: SessionModeSchema.optional(),
1731
+ url: z.string().optional(),
1732
+ diffActions: z.boolean().optional(),
1733
+ planningPrompt: z.boolean().optional(),
1734
+ customInstructions: z.array(CustomInstructionSchema).optional(),
1735
+ customAgents: z.array(CustomAgentInfoSchema).optional(),
1736
+ systemPromptOverride: z.union([z.string(), z.array(z.string())]).optional(),
1737
+ userPrompt: z.string().optional(),
1738
+ systemReminders: z.array(SystemReminderSchema).optional(),
1739
+ ephemeralUserPrompt: z.string().optional(),
1740
+ uiContextPrompt: z.string().optional(),
1741
+ displayUserPrompt: z.string().optional(),
1742
+ files: z.array(ProjectFileSchema).optional(),
1743
+ rerankFiles: z.number().optional(),
1744
+ toolResults: z.array(ContentMessageItemToolResultSchema).optional(),
1745
+ attachments: z.array(AttachmentSchema).optional(),
1746
+ beforeCommit: GitSnapshotSchema.optional(),
1747
+ workingDirectory: z.string().optional(),
1748
+ includeRelevantMemories: z.boolean().optional(),
1749
+ encryptKey: z.string().optional(),
1750
+ modelOverride: z.string().optional(),
1751
+ errorIfHadCompaction: z.boolean().optional(),
1752
+ softContextWindow: z.number().optional(),
1753
+ promptVersion: z.enum(["v1", "v2", "v3"]).optional(),
1754
+ reasoning: ReasoningEffortSchema.optional(),
1755
+ redactUserMessages: z.boolean().optional(),
1756
+ redactLLMMessages: z.boolean().optional(),
1757
+ environmentVariables: z.array(EnvironmentVariableSchema).optional(),
1758
+ skipCommandSecurity: z.boolean().optional(),
1759
+ // Code options
1760
+ builderContent: z.custom().optional(),
1761
+ framework: CodeGenFrameworkSchema.optional(),
1762
+ styleLibrary: CodeGenStyleLibrarySchema.optional(),
1763
+ typescript: z.boolean().optional(),
1764
+ userContext: UserContextSchema.optional(),
1765
+ aclPolicy: AclPolicySchema.optional(),
1766
+ repoIndexingConfig: RepoIndexingConfigSchema.optional(),
1767
+ recommendedRoot: z.string().optional(),
1768
+ enabledTools: z.array(CodeGenToolsSchema).optional(),
1769
+ enabledMCPs: z.array(z.string()).optional(),
1770
+ skipFileDiff: z.boolean().optional(),
1771
+ interruptActiveTask: z.boolean().optional().meta({
1772
+ description: "When true, the agent should interrupt its current task to handle this message immediately, rather than finishing the current task first.",
1773
+ }),
1774
+ localMCPTools: z.array(LocalMCPToolsSchema).optional().meta({
1775
+ description: "Local MCP tool definitions from stdio servers (CLI-side only). These tools will be executed on the client side and passed through from the server.",
1776
+ }),
1777
+ isLocal: z.boolean().optional().meta({
1778
+ description: "Indicates whether the codegen is running in local mode (local filesystem) vs cloud/container mode. Used to determine git auto-commit behavior.",
1779
+ }),
1780
+ maxAgentLoops: z.number().optional(),
1781
+ maxAgentTiming: z.number().optional(),
1782
+ maxTokens: z.number().optional().meta({
1783
+ description: "Maximum output tokens allowed in the LLM response. This will set the maximum token output for the LLM.",
1784
+ }),
1785
+ maxPages: z.number().optional(),
1786
+ autoContinue: z.number().optional(),
1787
+ isManualContinue: z.boolean().optional(),
1788
+ llmSuggestions: z.boolean().optional(),
1789
+ conclusionText: z.boolean().optional(),
1790
+ mcpServers: z.boolean().optional(),
1791
+ pingEvents: z.boolean().optional(),
1792
+ forceCompact: z.boolean().optional(),
1793
+ hadPagination: z.boolean().optional(),
1794
+ category: CodeGenCategorySchema.optional(),
1795
+ metadata: z.record(z.string(), z.any()).optional(),
1796
+ searchResponse: z.any().nullish(),
1797
+ prettierConfig: z.custom().optional(),
1798
+ // Role
1799
+ role: z.enum(["user", "agent"]).optional(),
1800
+ user: UserSourceSchema.optional(),
1801
+ // Context
1802
+ projectId: z.string().optional(),
1803
+ branchName: z.string().optional(),
1804
+ repoHash: z.string().optional(),
1805
+ repoBranch: z.string().optional(),
1806
+ parentSessionId: z.string().optional().meta({
1807
+ description: "Immediate parent session id when this completion runs inside a sub-agent.",
1808
+ }),
1809
+ mainSessionId: z.string().optional().meta({
1810
+ description: "Root session of the agent tree. Sub-agents inherit this from their parent so cost rolls up to the root in one hop, regardless of nesting depth.",
1811
+ }),
1812
+ /** @deprecated */
1813
+ prevId: z.string().optional(),
1814
+ /** @deprecated */
1815
+ vcpId: z.string().optional(),
1816
+ /** @deprecated */
1817
+ repair: z.boolean().optional(),
1818
+ /** @deprecated */
1819
+ systemReminderPrompt: z.string().optional(),
1820
+ })
1821
+ .meta({ title: "CodeGenInputOptions" });
1822
+ export const AutoPushModeSchema = z
1823
+ .enum(["force-push", "merge-push", "ff-push", "safe-push", "none"])
1824
+ .meta({ title: "AutoPushMode" });
1825
+ export const SyncChangesFromRemoteSchema = z
1826
+ .object({
1827
+ remoteBranches: z.enum(["both", "main", "ai"]).optional(),
1828
+ fastForward: z.enum(["never", "required", "auto"]).optional(),
1829
+ canPush: z.boolean().optional(),
1830
+ uncommittedChanges: z.enum(["stash", "commit", "fail"]).optional(),
1831
+ requestRefresh: z.boolean().optional(),
1832
+ allowUnrelatedHistory: z.boolean().optional(),
1833
+ resetToBase: z.boolean().optional().meta({
1834
+ description: "When true, reset the AI branch hard to the remote feature/base branch instead of merging. This gives a clean slate that exactly matches the checked-out feature branch on remote, avoiding any merge-style conflicts or divergence. Fails clearly if the feature/base branch cannot be determined or is absent from the remote.",
1835
+ }),
1836
+ updateLastCommits: z.boolean().optional().meta({
1837
+ description: "Whether to update the internal 'last AI commits' baseline after the sync completes. Defaults to `true` for backwards compatibility. Set to `false` when the caller wants `getChangesReport()` to keep diffing from the pre-sync baseline (e.g. so a downstream prompt can see exactly what changed since the last reset/sync)",
1838
+ }),
1839
+ })
1840
+ .meta({ title: "SyncChangesFromRemote" });
1841
+ export const GenerateUserMessageSchema = z
1842
+ .object({
1843
+ idempotencyKey: z.string().optional(),
1844
+ user: UserSourceSchema.optional(),
1845
+ userPrompt: z.string(),
1846
+ uiContextPrompt: z.string().optional(),
1847
+ ephemeralUserPrompt: z.string().optional(),
1848
+ displayPrompt: z.string().optional(),
1849
+ files: z.array(z.string()).optional(),
1850
+ systemReminders: z.array(SystemReminderObjSchema).optional(),
1851
+ includeBaseFiles: z.boolean().optional(),
1852
+ attachments: z.array(AttachmentSchema).optional(),
1853
+ logsCheckpoint: z.boolean().optional(),
1854
+ dropAbortedPrompt: z.boolean().optional(),
1855
+ runValidateCommand: z.boolean().optional(),
1856
+ modelOverride: z.string().optional(),
1857
+ agentModelOverrides: AgentModelOverridesSchema.optional(),
1858
+ softContextWindow: z.number().optional(),
1859
+ maxCompletions: z.number().optional(),
1860
+ isManualContinue: z.boolean().optional(),
1861
+ includeRelevantMemories: z.boolean().optional(),
1862
+ category: CodeGenCategorySchema.optional(),
1863
+ metadata: z.record(z.string(), z.any()).optional(),
1864
+ autoPush: AutoPushModeSchema.optional(),
1865
+ syncChanges: SyncChangesFromRemoteSchema.optional(),
1866
+ enabledMCPs: z.array(z.string()).optional(),
1867
+ sessionMode: SessionModeSchema.optional(),
1868
+ queue: z.boolean().optional(),
1869
+ agentType: z.string().optional().meta({
1870
+ description: "Custom agent type to use for this message",
1871
+ }),
1872
+ enableQAReviewTool: z.boolean().optional().meta({
1873
+ description: "Enable AddQAReview tool for QA PR review branches",
1874
+ }),
1875
+ reasoning: ReasoningEffortSchema.optional().meta({
1876
+ description: "Per-message reasoning effort override",
1877
+ }),
1878
+ /** @deprecated */
1879
+ repair: z.boolean().optional(),
1880
+ forceCompact: z.boolean().optional().meta({
1881
+ description: "Force compaction of the conversation before generating the next completion",
1882
+ }),
1883
+ })
1884
+ .meta({ title: "GenerateUserMessage" });
1885
+ /**
1886
+ * Request for generating a commit message via LLM
1887
+ */
1888
+ export const CommitMessageRequestSchema = z
1889
+ .object({
1890
+ diff: z.string().meta({ description: "Git diff from previous commit" }),
1891
+ userMessages: z
1892
+ .array(z.string())
1893
+ .meta({ description: "User messages sent during AI work" }),
1894
+ recentCommits: z.array(z.string()).meta({
1895
+ description: "Last 10 commits from main branch for style reference",
1896
+ }),
1897
+ longCommit: z
1898
+ .boolean()
1899
+ .optional()
1900
+ .meta({ description: "Whether to generate a long commit message" }),
1901
+ projectId: z.string().optional().meta({
1902
+ description: "Project ID for fetching project-specific commit instructions",
1903
+ }),
1904
+ })
1905
+ .meta({ title: "CommitMessageRequest" });
1906
+ /**
1907
+ * Response from commit message generation
1908
+ */
1909
+ export const CommitMessageResponseSchema = z
1910
+ .object({
1911
+ message: z.string().meta({ description: "Full commit message" }),
1912
+ title: z
1913
+ .string()
1914
+ .meta({ description: "First line (50-72 chars) - the commit title" }),
1915
+ body: z
1916
+ .string()
1917
+ .optional()
1918
+ .meta({ description: "Optional extended description" }),
1919
+ })
1920
+ .meta({ title: "CommitMessageResponse" });
1921
+ /**
1922
+ * Request body for `POST /codegen/model-permission-response`. Sent by the
1923
+ * frontend to approve or deny a model permission prompt.
1924
+ */
1925
+ export const ModelPermissionResponseRequestSchema = z
1926
+ .object({
1927
+ sessionId: z.string(),
1928
+ toolId: z.string(),
1929
+ approved: z.boolean(),
1930
+ reason: z.string().optional(),
1931
+ })
1932
+ .meta({ title: "ModelPermissionResponseRequest" });