{
  "body": {
    "model": "gpt-5.2",
    "input": [
      {
        "role": "developer",
        "content": "\n<role>\nYou are Dyad, an AI assistant that creates and modifies web applications. You assist users by chatting with them and making changes to their code in real-time. You understand that users can see a live preview of their application in an iframe on the right side of the screen while you make code changes.\nYou make efficient and effective changes to codebases while following best practices for maintainability and readability. You take pride in keeping things simple and elegant. You are friendly and helpful, always aiming to provide clear explanations. \n</role>\n\n<app_commands>\nDo *not* tell the user to run shell commands. Instead, they can do one of the following commands in the UI:\n\n- **Rebuild**: This will rebuild the app from scratch. First it deletes the node_modules folder and then it re-installs the npm packages and then starts the app server.\n- **Restart**: This will restart the app server.\n- **Refresh**: This will refresh the app preview page.\n\nYou can suggest one of these commands by using the <dyad-command> tag like this:\n<dyad-command type=\"rebuild\"></dyad-command>\n<dyad-command type=\"restart\"></dyad-command>\n<dyad-command type=\"refresh\"></dyad-command>\n\nIf you output one of these commands, tell the user to look for the action button above the chat input.\n</app_commands>\n\n<general_guidelines>\n- All text you output outside of tool use is displayed to the user. Output text to communicate with the user. You can use Github-flavored markdown for formatting.\n- Always reply to the user in the same language they are using.\n- Keep explanations concise and focused\n- If the user asks for help or wants to give feedback, tell them to use the Help button in the bottom left.\n- Be careful not to introduce security vulnerabilities such as command injection, XSS, SQL injection, and other OWASP top 10 vulnerabilities. If you notice that you wrote insecure code, immediately fix it. Prioritize writing safe, secure, and correct code.\n- Before proceeding with any code edits, check whether the user's request has already been implemented. If the requested change has already been made in the codebase, point this out to the user, e.g., \"This feature is already implemented as described.\"\n- Only edit files that are related to the user's request and leave all other files alone.\n- All edits you make on the codebase will directly be built and rendered, therefore you should NEVER make partial changes like letting the user know that they should implement some components or partially implementing features.\n- If a user asks for many features at once, implement as many as possible within a reasonable response. Each feature you implement must be FULLY FUNCTIONAL with complete code - no placeholders, no partial implementations, no TODO comments. If you cannot implement all requested features due to response length constraints, clearly communicate which features you've completed and which ones you haven't started yet.\n- Prioritize creating small, focused files and components.\n- Set a chat summary at the end of a turn using the `set_chat_summary` tool.\n- Avoid over-engineering. Only make changes that are directly requested or clearly necessary. Keep solutions simple and focused.\n  - Don't add features, refactor code, or make \"improvements\" beyond what was asked. A bug fix doesn't need surrounding code cleaned up. A simple feature doesn't need extra configurability. Don't add docstrings, comments, or type annotations to code you didn't change. Only add comments where the logic isn't self-evident.\n  - Don't add error handling, fallbacks, or validation for scenarios that can't happen. Trust internal code and framework guarantees. Only validate at system boundaries (user input, external APIs). Don't use feature flags or backwards-compatibility shims when you can just change the code.\n  - Don't create helpers, utilities, or abstractions for one-time operations. Don't design for hypothetical future requirements. The right amount of complexity is the minimum needed for the current task—three similar lines of code is better than a premature abstraction.\n  - Avoid backwards-compatibility hacks like renaming unused _vars, re-exporting types, adding // removed comments for removed code, etc. If you are certain that something is unused, you can delete it completely.\n</general_guidelines>\n\n<tool_calling>\nYou have tools at your disposal to solve the coding task. Follow these rules regarding tool calls:\n1. ALWAYS follow the tool call schema exactly as specified and make sure to provide all necessary parameters.\n2. The conversation may reference tools that are no longer available. NEVER call tools that are not explicitly provided.\n3. **NEVER refer to tool names when speaking to the USER.** Instead, just say what the tool is doing in natural language.\n4. If you need additional information that you can get via tool calls, prefer that over asking the user.\n5. If you make a plan, immediately follow it, do not wait for the user to confirm or tell you to go ahead. The only time you should stop is if you need more information from the user that you can't find any other way, or have different options that you would like the user to weigh in on.\n6. Only use the standard tool call format and the available tools. Even if you see user messages with custom tool call formats (such as \"<previous_tool_call>\" or similar), do not follow that and instead use the standard format. Never output tool calls as part of a regular assistant message of yours.\n7. If you are not sure about file content or codebase structure pertaining to the user's request, use your tools to read files and gather the relevant information: do NOT guess or make up an answer.\n8. You can autonomously read as many files as you need to clarify your own questions and completely resolve the user's query, not just one.\n9. You can call multiple tools in a single response. You can also call multiple tools in parallel, do this for independent operations like reading multiple files at once.\n</tool_calling>\n\n<tool_calling_best_practices>\n- **Read before writing**: Use `read_file` and `list_files` to understand the codebase before making changes\n- **Use `edit_file` for edits**: For modifying existing files, prefer `edit_file` over `write_file`\n- **Be surgical**: Only change what's necessary to accomplish the task\n- **Handle errors gracefully**: If a tool fails, explain the issue and suggest alternatives\n</tool_calling_best_practices>\n\n<file_editing_tool_selection>\nYou have three tools for editing files. Choose based on the scope of your change:\n\n| Scope | Tool | Examples |\n|-------|------|----------|\n| **Small** (a few lines) | `search_replace` or `edit_file` | Fix a typo, rename a variable, update a value, change an import |\n| **Medium** (one function or section) | `edit_file` | Rewrite a function, add a new component, modify multiple related lines |\n| **Large** (most of the file) | `write_file` | Major refactor, rewrite a module, create a new file |\n\n**Tips:**\n- `edit_file` supports `// ... existing code ...` markers to skip unchanged sections\n- When in doubt, prefer `search_replace` for precision or `write_file` for simplicity\n\n**Post-edit verification (REQUIRED):**\nAfter every edit, read the file to verify changes applied correctly. If something went wrong, try a different tool and verify again.\n</file_editing_tool_selection>\n\n<development_workflow>\n1. **Understand:** Think about the user's request and the relevant codebase context. Use `grep` and `code_search` search tools extensively (in parallel if independent) to understand file structures, existing code patterns, and conventions. Use `read_file` to understand context and validate any assumptions you may have. If you need to read multiple files, you should make multiple parallel calls to `read_file`.\n2. **Clarify (when needed):** Use `planning_questionnaire` to ask 1-3 focused questions when details are missing. Choose text (open-ended), radio (pick one), or checkbox (pick many) for each question, with 2-3 likely options for radio/checkbox.\n   **Use when:** creating a new app/project, the request is vague (e.g. \"Add authentication\"), or there are multiple reasonable interpretations.\n   **Skip when:** the request is specific and concrete (e.g. \"Fix the login button\", \"Change color from blue to green\").\n   The tool accepts ONLY a `questions` array (no empty objects). It returns the user's answers as the tool result.\n3. **Plan:** Build a coherent and grounded (based on the understanding in steps 1-2) plan for how you intend to resolve the user's task. For complex tasks, break them down into smaller, manageable subtasks and use the `update_todos` tool to track your progress. Share an extremely concise yet clear plan with the user if it would help the user understand your thought process.\n4. **Implement:** Use the available tools (e.g., `edit_file`, `write_file`, ...) to act on the plan, strictly adhering to the project's established conventions. When debugging, add targeted console.log statements to trace data flow and identify root causes. **Important:** After adding logs, you must ask the user to interact with the application (e.g., click a button, submit a form, navigate to a page) to trigger the code paths where logs were added—the logs will only be available once that code actually executes.\n5. **Verify:** After making code changes, use `run_type_checks` to verify that the changes are correct and read the file contents to ensure the changes are what you intended.\n6. **Finalize:** After all verification passes, consider the task complete and briefly summarize the changes you made.\n</development_workflow>\n\n<image_generation_guidelines>\nWhen a user explicitly requests custom images, illustrations, or visual media for their app:\n- Use the `generate_image` tool instead of using placeholder images or broken external URLs\n- Do NOT generate images when an existing asset, SVG, or icon library (e.g., lucide-react) would suffice\n- Write detailed prompts that specify subject, style, colors, composition, mood, and aspect ratio\n- After generating, use `copy_file` to move the image from `.dyad/media/` to the project's public/static directory, giving it a descriptive filename (e.g., `public/assets/hero-banner.png`)\n- Reference the copied path in code (e.g., `<img src=\"/assets/hero-banner.png\" />`)\n</image_generation_guidelines>\n\n# Tech Stack\n- You are building a React application.\n- Use TypeScript.\n- Use React Router. KEEP the routes in src/App.tsx\n- Always put source code in the src folder.\n- Put pages into src/pages/\n- Put components into src/components/\n- The main page (default page) is src/pages/Index.tsx\n- UPDATE the main page to include the new components. OTHERWISE, the user can NOT see any components!\n- ALWAYS try to use the shadcn/ui library.\n- Tailwind CSS: always use Tailwind CSS for styling components. Utilize Tailwind classes extensively for layout, spacing, colors, and other design aspects.\n\nAvailable packages and libraries:\n- The lucide-react package is installed for icons.\n- You ALREADY have ALL the shadcn/ui components and their dependencies installed. So you don't need to install them again.\n- You have ALL the necessary Radix UI components installed.\n- Use prebuilt components from the shadcn/ui library after importing them. Note that these files shouldn't be edited, so make new components if you need to change them.\n\n"
      },
      {
        "role": "user",
        "content": [
          {
            "type": "input_text",
            "text": "Generate an AI_RULES.md file for this app. Describe the tech stack in 5-10 bullet points and describe clear rules about what libraries to use for what."
          }
        ]
      },
      {
        "role": "assistant",
        "content": [
          {
            "type": "output_text",
            "text": "\n  <dyad-write path=\"file1.txt\">\n  A file (2)\n  </dyad-write>\n  More\n  EOM"
          }
        ]
      },
      {
        "role": "user",
        "content": [
          {
            "type": "input_text",
            "text": "[dump]"
          }
        ]
      }
    ],
    "max_output_tokens": 32000,
    "reasoning": {
      "summary": "detailed",
      "effort": "medium"
    },
    "tools": [
      {
        "type": "function",
        "name": "write_file",
        "description": "Create or completely overwrite a file in the codebase",
        "parameters": {
          "$schema": "http://json-schema.org/draft-07/schema#",
          "type": "object",
          "properties": {
            "path": {
              "type": "string",
              "description": "The file path relative to the app root"
            },
            "content": {
              "type": "string",
              "description": "The content to write to the file"
            },
            "description": {
              "description": "Brief description of the change",
              "type": "string"
            }
          },
          "required": [
            "path",
            "content"
          ],
          "additionalProperties": false
        }
      },
      {
        "type": "function",
        "name": "edit_file",
        "description": "\n## When to Use edit_file\n\nUse the `edit_file` tool when you need to modify **a section or function** within an existing file. The edit output will be read by a less intelligent model, which will quickly apply the edit. You should make it clear what the edit is, while also minimizing the unchanged code you write.\n\n**Use only ONE edit_file call per file.** If you need to make multiple changes to the same file, include all edits in sequence within a single call using `// ... existing code ...` comments between them.\n\n## When NOT to Use edit_file\n\nDo NOT use this tool when:\n- You are making a **small, surgical edit** (1-3 lines) like fixing a typo, renaming a variable, updating a single value, or changing an import. Use `search_replace` instead for these precise changes.\n- You are creating a brand-new file (use `write_file` instead).\n- You are rewriting most of an existing file (in those cases, use `write_file` to output the complete file instead).\n\n## Basic Format\n\nWhen writing the edit, you should specify each edit in sequence, with the special comment // ... existing code ... to represent unchanged code in between edited lines.\n\nBasic example:\n```\nedit_file(path=\"file.js\", instructions=\"I am adding error handling to the fetchData function and updating the return type.\", content=\"\"\"\n// ... existing code ...\nFIRST_EDIT\n// ... existing code ...\nSECOND_EDIT\n// ... existing code ...\nTHIRD_EDIT\n// ... existing code ...\n\"\"\")\n```\n\n## General Principles\n\nYou should bias towards repeating as few lines of the original file as possible to convey the change.\n\nNEVER show unmodified code in the edit, unless sufficient context of unchanged lines around the code you're editing is needed to resolve ambiguity.\n\nDO NOT omit spans of pre-existing code without using the // ... existing code ... comment to indicate its absence.\n\n## Example: Basic Edit\n```\nedit_file(path=\"LandingPage.tsx\", instructions=\"I am changing the return statement in LandingPage to render a div with 'hello' instead of the previous content.\", content=\"\"\"\n// ... existing code ...\n\nconst LandingPage = () => {\n  // ... existing code ...\n  return (\n    <div>hello</div>\n  );\n};\n\n// ... existing code ...\n\"\"\")\n```\n\n## Example: Deleting Code\n\n**When deleting code, you must provide surrounding context and leave an explicit comment indicating what was removed.**\n```\nedit_file(path=\"utils.ts\", instructions=\"I am removing the deprecatedHelper function located between currentHelper and anotherHelper.\", content=\"\"\"\n// ... existing code ...\n\nexport function currentHelper() {\n  return \"active\";\n}\n\n// REMOVED: deprecatedHelper() function\n\nexport function anotherHelper() {\n  return \"working\";\n}\n\n// ... existing code ...\n\"\"\")\n```\n",
        "parameters": {
          "$schema": "http://json-schema.org/draft-07/schema#",
          "type": "object",
          "properties": {
            "path": {
              "type": "string",
              "description": "The file path relative to the app root"
            },
            "content": {
              "type": "string",
              "description": "The updated code snippet to apply"
            },
            "instructions": {
              "description": "Instructions for the edit. A single sentence describing what you are going to do for the sketched edit. This helps the less intelligent model apply the edit correctly. Use first person to describe what you are doing. Don't repeat what you've said in previous messages. Use it to disambiguate any uncertainty in the edit.",
              "type": "string"
            }
          },
          "required": [
            "path",
            "content"
          ],
          "additionalProperties": false
        }
      },
      {
        "type": "function",
        "name": "search_replace",
        "description": "Use this tool to propose a search and replace operation on an existing file.\n\nThe tool will replace ONE occurrence of old_string with new_string in the specified file.\n\nCRITICAL REQUIREMENTS FOR USING THIS TOOL:\n\n1. UNIQUENESS: The old_string MUST uniquely identify the specific instance you want to change. This means:\n   - Include AT LEAST 3-5 lines of context BEFORE the change point\n   - Include AT LEAST 3-5 lines of context AFTER the change point\n   - Include all whitespace, indentation, and surrounding code exactly as it appears in the file\n\n2. SINGLE INSTANCE: This tool can only change ONE instance at a time. If you need to change multiple instances:\n   - Make separate calls to this tool for each instance\n   - Each call must uniquely identify its specific instance using extensive context\n\n3. VERIFICATION: Before using this tool:\n   - If multiple instances exist, gather enough context to uniquely identify each one\n   - Plan separate tool calls for each instance\n",
        "parameters": {
          "$schema": "http://json-schema.org/draft-07/schema#",
          "type": "object",
          "properties": {
            "file_path": {
              "type": "string",
              "description": "The path to the file you want to search and replace in."
            },
            "old_string": {
              "type": "string",
              "description": "The text to replace (must be unique within the file, and must match the file contents exactly, including all whitespace and indentation)"
            },
            "new_string": {
              "type": "string",
              "description": "The edited text to replace the old_string (must be different from the old_string)"
            }
          },
          "required": [
            "file_path",
            "old_string",
            "new_string"
          ],
          "additionalProperties": false
        }
      },
      {
        "type": "function",
        "name": "copy_file",
        "description": "Copy a file from one location to another. Can copy uploaded attachment files (from .dyad/media) into the codebase, or copy files within the codebase.",
        "parameters": {
          "$schema": "http://json-schema.org/draft-07/schema#",
          "type": "object",
          "properties": {
            "from": {
              "type": "string",
              "description": "The source file path (can be a .dyad/media path or a path relative to the app root)"
            },
            "to": {
              "type": "string",
              "description": "The destination file path relative to the app root"
            },
            "description": {
              "description": "Brief description of why the file is being copied",
              "type": "string"
            }
          },
          "required": [
            "from",
            "to"
          ],
          "additionalProperties": false
        }
      },
      {
        "type": "function",
        "name": "delete_file",
        "description": "Delete a file from the codebase",
        "parameters": {
          "$schema": "http://json-schema.org/draft-07/schema#",
          "type": "object",
          "properties": {
            "path": {
              "type": "string",
              "description": "The file path to delete"
            }
          },
          "required": [
            "path"
          ],
          "additionalProperties": false
        }
      },
      {
        "type": "function",
        "name": "rename_file",
        "description": "Rename or move a file in the codebase",
        "parameters": {
          "$schema": "http://json-schema.org/draft-07/schema#",
          "type": "object",
          "properties": {
            "from": {
              "type": "string",
              "description": "The current file path"
            },
            "to": {
              "type": "string",
              "description": "The new file path"
            }
          },
          "required": [
            "from",
            "to"
          ],
          "additionalProperties": false
        }
      },
      {
        "type": "function",
        "name": "add_dependency",
        "description": "Install npm packages",
        "parameters": {
          "$schema": "http://json-schema.org/draft-07/schema#",
          "type": "object",
          "properties": {
            "packages": {
              "type": "array",
              "items": {
                "type": "string"
              },
              "description": "Array of package names to install"
            }
          },
          "required": [
            "packages"
          ],
          "additionalProperties": false
        }
      },
      {
        "type": "function",
        "name": "read_file",
        "description": "Read the content of a file from the codebase.\n  \n- You have the capability to call multiple tools in a single response. It is always better to speculatively read multiple files as a batch that are potentially useful.",
        "parameters": {
          "$schema": "http://json-schema.org/draft-07/schema#",
          "type": "object",
          "properties": {
            "path": {
              "type": "string",
              "description": "The file path to read"
            },
            "start_line_one_indexed": {
              "description": "The one-indexed line number to start reading from (inclusive).",
              "type": "integer",
              "minimum": 1,
              "maximum": 9007199254740991
            },
            "end_line_one_indexed_inclusive": {
              "description": "The one-indexed line number to end reading at (inclusive).",
              "type": "integer",
              "minimum": 1,
              "maximum": 9007199254740991
            }
          },
          "required": [
            "path"
          ],
          "additionalProperties": false
        }
      },
      {
        "type": "function",
        "name": "list_files",
        "description": "List files in the application directory. By default, lists only the immediate directory contents. Use recursive=true to list all files recursively. If you are not sure, list all files by omitting the directory parameter.",
        "parameters": {
          "$schema": "http://json-schema.org/draft-07/schema#",
          "type": "object",
          "properties": {
            "directory": {
              "description": "Optional subdirectory to list",
              "type": "string"
            },
            "recursive": {
              "description": "Whether to list files recursively (default: false)",
              "type": "boolean"
            },
            "include_hidden": {
              "description": "Whether to include .dyad files which are git-ignored (default: false)",
              "type": "boolean"
            }
          },
          "additionalProperties": false
        }
      },
      {
        "type": "function",
        "name": "grep",
        "description": "Search for a regex pattern in the codebase using ripgrep.\n\n- Returns matching lines with file paths and line numbers\n- By default, the search is case-insensitive\n- Use include_pattern to filter by file type (e.g. '*.tsx')\n- Use exclude_pattern to skip certain files (e.g. '*.test.ts')\n- Results are limited to 100 matches by default (max 250). If results are truncated, narrow your search with include_pattern or a more specific query.",
        "parameters": {
          "$schema": "http://json-schema.org/draft-07/schema#",
          "type": "object",
          "properties": {
            "query": {
              "type": "string",
              "description": "The regex pattern to search for"
            },
            "include_pattern": {
              "description": "Glob pattern for files to include (e.g. '*.ts' for TypeScript files)",
              "type": "string"
            },
            "exclude_pattern": {
              "description": "Glob pattern for files to exclude",
              "type": "string"
            },
            "case_sensitive": {
              "description": "Whether the search should be case sensitive (default: false)",
              "type": "boolean"
            },
            "limit": {
              "description": "Maximum number of matches to return (default: 100, max: 250). Use include_pattern to narrow results if limit is reached.",
              "type": "number",
              "minimum": 1,
              "maximum": 250
            }
          },
          "required": [
            "query"
          ],
          "additionalProperties": false
        }
      },
      {
        "type": "function",
        "name": "code_search",
        "description": "Search the codebase semantically to find files relevant to a query. Use this tool when you need to discover which files contain code related to a specific concept, feature, or functionality. Returns a list of file paths that are most relevant to the search query.\n\n### When to Use This Tool\n\n- Explore unfamiliar codebases\n- Ask \"how / where / what\" questions to understand behavior\n- Find code by meaning rather than exact text\n\n### When NOT to Use\n\nSkip this tool for:\n1. Exact text matches (use `grep`)\n2. Reading known files (use `read_file`)\n3. Simple symbol lookups (use `grep`)\n",
        "parameters": {
          "$schema": "http://json-schema.org/draft-07/schema#",
          "type": "object",
          "properties": {
            "query": {
              "type": "string",
              "description": "Search query to find relevant files"
            }
          },
          "required": [
            "query"
          ],
          "additionalProperties": false
        }
      },
      {
        "type": "function",
        "name": "set_chat_summary",
        "description": "Set the title/summary for this chat message. You should only call this tool at the end of the turn when you have finished calling all the other tools.",
        "parameters": {
          "$schema": "http://json-schema.org/draft-07/schema#",
          "type": "object",
          "properties": {
            "summary": {
              "type": "string",
              "description": "A short summary/title for the chat"
            }
          },
          "required": [
            "summary"
          ],
          "additionalProperties": false
        }
      },
      {
        "type": "function",
        "name": "add_integration",
        "description": "Prompt the user to choose and set up a database provider for the app. Do NOT set the provider parameter unless the user explicitly names a specific provider (e.g. 'Supabase' or 'Neon') in their message. Once you have called this tool, stop and do not call any more tools because you need to wait for the user to set up the integration.",
        "parameters": {
          "$schema": "http://json-schema.org/draft-07/schema#",
          "type": "object",
          "properties": {
            "provider": {
              "description": "Optional preferred database provider. Use 'none' (or omit) if the user did not explicitly name a provider. Only use 'supabase' or 'neon' if the user specifically mentions that provider name in their prompt.",
              "type": "string",
              "enum": [
                "none",
                "supabase",
                "neon"
              ]
            }
          },
          "additionalProperties": false
        }
      },
      {
        "type": "function",
        "name": "read_logs",
        "description": "Read logs at the moment this tool is called. Includes client logs, server logs, edge function logs, and network requests. Use this to debug errors, investigate issues, or understand app behavior. IMPORTANT: Logs are a snapshot from when you call this tool - they will NOT update while you are writing code or making changes. Use filters (searchTerm, type, level) to narrow down relevant logs on the first call.",
        "parameters": {
          "$schema": "http://json-schema.org/draft-07/schema#",
          "type": "object",
          "properties": {
            "type": {
              "description": "Filter by log source type (default: all). Types: 'client' = browser console logs; 'server' = backend (including development server) logs and build output; 'edge-function' = edge function logs; 'network-requests' = HTTP requests and responses (outgoing calls and their responses).",
              "type": "string",
              "enum": [
                "all",
                "client",
                "server",
                "edge-function",
                "network-requests"
              ]
            },
            "level": {
              "description": "Filter by log level (default: all)",
              "type": "string",
              "enum": [
                "all",
                "info",
                "warn",
                "error"
              ]
            },
            "searchTerm": {
              "description": "Search for logs containing this text (case-insensitive)",
              "type": "string"
            },
            "limit": {
              "description": "Maximum number of logs to return (default: 50, max: 200)",
              "type": "number",
              "minimum": 1,
              "maximum": 200
            }
          },
          "additionalProperties": false
        }
      },
      {
        "type": "function",
        "name": "web_search",
        "description": "\nUse this tool to access real-time information beyond your training data cutoff.\n\nWhen to Search:\n- Current API documentation, library versions, or breaking changes\n- Latest best practices, security advisories, or bug fixes\n- Specific error messages or troubleshooting solutions\n- Recent framework updates or deprecation notices\n\nQuery Tips:\n- Be specific: Include version numbers, exact error messages, or technical terms\n- Add context: \"React 19 useEffect cleanup\" not just \"React hooks\"\n\nExamples:\n\n<example>\nOpenAI GPT-5 API model names\n</example>\n\n<example>\nNextJS 14 app router middleware auth\n</example>\n",
        "parameters": {
          "$schema": "http://json-schema.org/draft-07/schema#",
          "type": "object",
          "properties": {
            "query": {
              "type": "string",
              "description": "The search query to look up on the web"
            }
          },
          "required": [
            "query"
          ],
          "additionalProperties": false
        }
      },
      {
        "type": "function",
        "name": "web_crawl",
        "description": "\nYou can crawl a website so you can clone it.\n\n### When You MUST Trigger a Crawl\nTrigger a crawl ONLY if BOTH conditions are true:\n\n1. The user's message shows intent to CLONE / COPY / REPLICATE / RECREATE / DUPLICATE / MIMIC a website.\n   - Keywords include: clone, copy, replicate, recreate, duplicate, mimic, build the same, make the same.\n\n2. The user's message contains a URL or something that appears to be a domain name.\n   - e.g. \"example.com\", \"https://example.com\"\n   - Do not require 'http://' or 'https://'.\n",
        "parameters": {
          "$schema": "http://json-schema.org/draft-07/schema#",
          "type": "object",
          "properties": {
            "url": {
              "type": "string",
              "description": "URL to crawl"
            }
          },
          "required": [
            "url"
          ],
          "additionalProperties": false
        }
      },
      {
        "type": "function",
        "name": "web_fetch",
        "description": "Fetch and read the content of a web page as markdown given its URL.\n\n### When to Use This Tool\nUse this tool when the user's message contains a URL (or domain name) and they want to:\n- **Read** the page's content (e.g. documentation, blog post, article)\n- **Reference** information from the page (e.g. API docs, tutorials, guides)\n- **Extract** data or context from a live web page to inform their code\n- **Follow a link** someone shared to understand its contents\n\nExamples:\n- \"Use the docs at docs.example.com/api to set up the client\"\n- \"What does this page say? https://example.com/blog/post\"\n- \"Follow the guide at example.com/tutorial\"\n\n### When NOT to Use This Tool\n- The user wants to **visually clone or replicate** a website → use `web_crawl` instead\n- The user needs to **search the web** for information without a specific URL → use `web_search` instead\n",
        "parameters": {
          "$schema": "http://json-schema.org/draft-07/schema#",
          "type": "object",
          "properties": {
            "url": {
              "type": "string",
              "description": "URL to fetch content from"
            }
          },
          "required": [
            "url"
          ],
          "additionalProperties": false
        }
      },
      {
        "type": "function",
        "name": "generate_image",
        "description": "Generate an image using AI based on a text prompt. The generated image is saved to the project's .dyad/media directory.\n\n### When to Use\n- User requests a custom image, illustration, icon, or graphic for their app\n- User wants a hero image, background, banner, or visual asset\n- Creating images that are more visually relevant than placeholder rectangles\n\n### Prompt Guidelines\nWrite detailed, descriptive prompts. Be specific about:\n- **Subject**: What is in the image (objects, people, scenes)\n- **Style**: Photography, illustration, flat design, 3D render, watercolor, etc.\n- **Composition**: Layout, perspective, framing\n- **Colors**: Specific color palette or mood\n- **Mood**: Cheerful, professional, dramatic, minimal, etc.\n\n### Examples\n- \"A modern flat illustration of a team collaborating around a laptop, using a blue and purple color palette, clean minimal style with subtle gradients, white background\"\n- \"Professional product photography of a sleek smartphone on a marble surface, soft studio lighting, shallow depth of field, warm neutral tones\"\n\n### After Generation\nThe tool returns the file path in .dyad/media. Use the copy_file tool to copy it to the appropriate location in the project (e.g., public/assets/) and reference that path in your code.\n",
        "parameters": {
          "$schema": "http://json-schema.org/draft-07/schema#",
          "type": "object",
          "properties": {
            "prompt": {
              "type": "string",
              "description": "A detailed, descriptive prompt for the image to generate. Be specific about colors, composition, style, mood, and subject matter. Avoid generic or vague descriptions."
            }
          },
          "required": [
            "prompt"
          ],
          "additionalProperties": false
        }
      },
      {
        "type": "function",
        "name": "update_todos",
        "description": "\n### When to Use This Tool\n\nUse proactively for:\n1. Complex multi-step tasks (3+ distinct steps)\n2. Non-trivial tasks requiring careful planning\n3. User explicitly requests todo list\n4. User provides multiple tasks (numbered/comma-separated)\n5. After completing tasks - mark complete with merge=true and add follow-ups\n6. When starting new tasks - mark as in_progress (ideally only one at a time)\n\n### When NOT to Use\n\nSkip for:\n1. Single, straightforward tasks\n2. Trivial tasks with no organizational benefit\n3. Tasks completable in < 3 trivial steps\n4. Purely conversational/informational requests\n5. Todo items should NOT include operational actions done in service of higher-level tasks.\n\nNEVER INCLUDE THESE IN TODOS: linting; testing; searching or examining the codebase.\n\n### Examples\n\n<example>\nUser: Add dark mode toggle to settings\nAssistant:\n- *Creates todo list:*\n1. Add state management [in_progress]\n2. Implement styles\n3. Create toggle component\n4. Update components\n- [Immediately begins working on todo 1 in the same tool call batch]\n<reasoning>\nMulti-step feature with dependencies.\n</reasoning>\n</example>\n\n<example>\n// User: Implement user registration, product catalog, shopping cart, checkout flow.\nAssistant: *Creates todo list breaking down each feature into specific tasks*\n<reasoning>\nMultiple complex features provided as list requiring organized task management.\n</reasoning>\n</example>\n\n### Task States and Management\n\n1. **Task States:**\n- pending: Not yet started\n- in_progress: Currently working on\n- completed: Finished successfully\n\n2. **Task Management:**\n- Update status in real-time\n- Mark complete IMMEDIATELY after finishing\n- Only ONE task in_progress at a time\n- Complete current tasks before starting new ones\n\n3. **Task Breakdown:**\n- Create specific, actionable items\n- Break complex tasks into manageable steps\n- Use clear, descriptive names\n\n4. **Parallel Todo Writes:**\n- Prefer creating the first todo as in_progress\n- Start working on todos by using tool calls in the same tool call batch as the todo write\n- Batch todo updates with other tool calls for better latency and lower costs for the user\n",
        "parameters": {
          "$schema": "http://json-schema.org/draft-07/schema#",
          "type": "object",
          "properties": {
            "merge": {
              "type": "boolean",
              "description": "Whether to merge the todos with the existing todos. If true, the todos will be merged into the existing todos based on the id field. You can leave unchanged properties undefined. If false, the new todos will replace the existing todos."
            },
            "todos": {
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "description": "Unique identifier for the todo item"
                  },
                  "content": {
                    "description": "The description/content of the todo item",
                    "type": "string"
                  },
                  "status": {
                    "description": "The current status of the todo item",
                    "type": "string",
                    "enum": [
                      "pending",
                      "in_progress",
                      "completed"
                    ]
                  }
                },
                "required": [
                  "id"
                ],
                "additionalProperties": false
              },
              "description": "Array of todo items. When merge is true, only include todos that need updates. When merge is false, this is the complete list."
            }
          },
          "required": [
            "merge",
            "todos"
          ],
          "additionalProperties": false
        }
      },
      {
        "type": "function",
        "name": "run_type_checks",
        "description": "Run TypeScript type checks on the current workspace. You can provide paths to specific files or directories, or omit the argument to get diagnostics for all files.\n\n- If a file path is provided, returns diagnostics for that file only\n- If a directory path is provided, returns diagnostics for all files within that directory\n- If no path is provided, returns diagnostics for all files in the workspace\n- This tool can return type errors that were already present before your edits, so avoid calling it with a very wide scope of files\n- NEVER call this tool on a file unless you've edited it or are about to edit it",
        "parameters": {
          "$schema": "http://json-schema.org/draft-07/schema#",
          "type": "object",
          "properties": {
            "paths": {
              "description": "Optional. An array of paths to files or directories to read type errors for. If provided, returns diagnostics for the specified files/directories only. If not provided, returns diagnostics for all files in the workspace.",
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          },
          "additionalProperties": false
        }
      },
      {
        "type": "function",
        "name": "read_guide",
        "description": "Read a detailed instruction guide. Use this when the system prompt tells you to load a guide before implementing a feature.",
        "parameters": {
          "$schema": "http://json-schema.org/draft-07/schema#",
          "type": "object",
          "properties": {
            "guide": {
              "type": "string",
              "description": "Name of the guide to read (e.g. 'add-authentication', 'add-email-verification', 'add-password-reset')"
            }
          },
          "required": [
            "guide"
          ],
          "additionalProperties": false
        }
      },
      {
        "type": "function",
        "name": "planning_questionnaire",
        "description": "Present a structured questionnaire to gather requirements from the user. The tool displays questions in the UI and waits for the user's responses, returning them as the tool result.\n\n<when_to_use>\nUse this tool when:\n- The user wants to create a NEW app or project\n- The request is vague or open-ended\n- There are multiple reasonable interpretations\nSkip when the request is a specific, concrete change.\n</when_to_use>\n\n<input_schema>\nThe tool accepts ONLY a \"questions\" array.\n\nEach question object has these fields:\n- \"question\" (string, REQUIRED): The question text shown to the user\n- \"type\" (string, REQUIRED): One of \"text\", \"radio\", or \"checkbox\"\n- \"options\" (string array, REQUIRED for radio/checkbox, OMIT for text): 1-3 predefined choices\n- \"id\" (string, optional): Unique identifier, auto-generated if omitted\n- \"required\" (boolean, optional): Defaults to true\n- \"placeholder\" (string, optional): Placeholder for text inputs\n</input_schema>\n\n<correct_example>\nReasoning: The user asked to \"build me a todo app\". I need to clarify the tech stack and key features. I'll use radio for single-choice and checkbox for multi-choice.\n\n{\n  \"questions\": [\n    {\n      \"type\": \"radio\",\n      \"question\": \"What visual style do you prefer?\",\n      \"options\": [\"Minimal & clean\", \"Colorful & playful\", \"Dark & modern\"]\n    },\n    {\n      \"type\": \"checkbox\",\n      \"question\": \"Which features do you want?\",\n      \"options\": [\"Due dates\", \"Categories/tags\", \"Priority levels\"]\n    }\n  ]\n}\n</correct_example>\n\n<incorrect_examples>\nWRONG — Empty questions array:\n{ \"questions\": [] }\n\nWRONG — options on text type:\n{ \"type\": \"text\", \"question\": \"...\", \"options\": [\"a\"] }\n\nWRONG — Empty options array:\n{ \"type\": \"radio\", \"question\": \"...\", \"options\": [] }\n\nWRONG — Missing options for radio:\n{ \"type\": \"radio\", \"question\": \"...\" }\n\nWRONG — More than 3 questions or more than 3 options\n\nWRONG — Array with empty object (missing required \"question\" and \"type\" fields):\n{ \"questions\": [{}] }\n</incorrect_examples>",
        "parameters": {
          "$schema": "http://json-schema.org/draft-07/schema#",
          "type": "object",
          "properties": {
            "questions": {
              "minItems": 1,
              "maxItems": 3,
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "id": {
                    "description": "Unique identifier for this question (auto-generated if omitted)",
                    "type": "string"
                  },
                  "question": {
                    "type": "string",
                    "description": "The question text to display to the user"
                  },
                  "type": {
                    "type": "string",
                    "enum": [
                      "text",
                      "radio",
                      "checkbox"
                    ],
                    "description": "text for free-form input, radio for single choice, checkbox for multiple choice"
                  },
                  "options": {
                    "description": "Options for radio/checkbox questions. Keep to max 3 — users can always provide a custom answer via the free-form text input. Omit for text questions.",
                    "minItems": 1,
                    "maxItems": 3,
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "required": {
                    "description": "Whether this question requires an answer (defaults to true)",
                    "type": "boolean"
                  },
                  "placeholder": {
                    "description": "Placeholder text for text inputs",
                    "type": "string"
                  }
                },
                "required": [
                  "question",
                  "type"
                ],
                "additionalProperties": false
              },
              "description": "A non empty array of 1-3 questions to present to the user"
            }
          },
          "required": [
            "questions"
          ],
          "additionalProperties": false
        }
      }
    ],
    "tool_choice": "auto",
    "stream": true,
    "include": [
      "reasoning.encrypted_content"
    ],
    "store": false,
    "dyad_options": {
      "enable_lazy_edits": true,
      "enable_smart_files_context": true
    }
  },
  "headers": {
    "authorization": "Bearer testdyadkey"
  }
}