Skip to content

improving file attachement handling#2757

Merged
azizmejri1 merged 17 commits intodyad-sh:mainfrom
azizmejri1:improve-file-handling
Feb 25, 2026
Merged

improving file attachement handling#2757
azizmejri1 merged 17 commits intodyad-sh:mainfrom
azizmejri1:improve-file-handling

Conversation

@azizmejri1
Copy link
Copy Markdown
Collaborator

@azizmejri1 azizmejri1 commented Feb 20, 2026

closes #2576


Open with Devin

@wwwillchen
Copy link
Copy Markdown
Collaborator

@BugBot run

@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello @azizmejri1, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly refactors the way file attachments are handled within the system. It transitions from an indirect, ID-based resolution system to a more direct and secure file copying mechanism. The change aims to improve clarity for the AI by providing direct temporary file paths and enhances security by validating source paths for copy operations. This also introduces a dedicated UI component for better user feedback on file copy actions.

Highlights

  • New File Copy Mechanism: Introduced a new copy_file tool for the local agent and a corresponding <dyad-copy> custom tag. This new mechanism allows the AI to directly copy files from temporary paths (where attachments are initially stored) into the codebase, replacing the previous write_file tool with DYAD_ATTACHMENT_X IDs.
  • Deprecation of Old Attachment Handling: The DYAD_ATTACHMENT_X ID system and the FileUploadsState utility have been removed. The write_file tool no longer resolves attachment IDs, streamlining the file handling process.
  • Enhanced Security for File Operations: Implemented security checks for the copy_file tool and dyad-copy tag processing. Absolute source paths are now strictly validated to ensure they originate only from the designated temporary attachments directory, preventing unauthorized file access.
  • Updated AI Prompting and UI: The system prompt for the AI has been updated to guide it towards using the new copy_file tool or <dyad-copy> tag with temporary file paths. A new DyadCopy React component was added to visually represent these file copy operations in the chat interface.
Changelog
  • e2e-tests/fixtures/engine/local-agent/upload-to-codebase.ts
    • Updated fixture to use the new copy_file tool instead of write_file for uploading files to the codebase.
    • Modified the content argument to from and DYAD_ATTACHMENT_0 to a temporary file path, reflecting the new attachment handling.
  • e2e-tests/local_agent_file_upload.spec.ts
    • Updated comments to reflect the change from write_file and file IDs to copy_file and temporary file paths.
  • src/components/chat/DyadCopy.tsx
    • Added new React component DyadCopy to render <dyad-copy> custom tags in the chat UI, displaying 'From' and 'To' paths.
  • src/components/chat/DyadMarkdownParser.tsx
    • Imported the new DyadCopy component.
    • Added dyad-copy to the list of DYAD_CUSTOM_TAGS.
    • Implemented rendering logic for dyad-copy tags using the DyadCopy component.
  • src/ipc/handlers/chat_stream_handlers.ts
    • Removed import and usage of FileUploadsState.
    • Modified attachment handling to provide temporary file paths directly to the AI for 'upload-to-codebase' and 'chat-context' attachments.
    • Updated system prompts to instruct the AI to use the copy_file tool or <dyad-copy> tag with temporary paths.
  • src/ipc/processors/response_processor.ts
    • Imported getDyadCopyTags and os module.
    • Defined TEMP_DIR for secure temporary file handling.
    • Removed FileUploadsState instantiation and related file upload ID resolution logic.
    • Added new logic to process <dyad-copy> tags, including security checks for source paths, file copying, and Git integration.
  • src/ipc/utils/dyad_tag_parser.ts
    • Added getDyadCopyTags function to parse <dyad-copy> XML tags from AI responses.
  • src/ipc/utils/file_uploads_state.ts
    • Removed the FileUploadsState utility file, deprecating the old file attachment ID management.
  • src/pro/main/ipc/handlers/local_agent/tool_definitions.ts
    • Imported the new copyFileTool.
    • Added copyFileTool to the list of available TOOL_DEFINITIONS.
  • src/pro/main/ipc/handlers/local_agent/tools/copy_file.ts
    • Added new copy_file tool definition for the local agent.
    • Implemented file copying logic with security checks for source paths and Git integration.
    • Included XML tag building for <dyad-copy>.
  • src/pro/main/ipc/handlers/local_agent/tools/file_upload_utils.ts
    • Removed the file_upload_utils file, as its functionality for resolving attachment IDs is no longer needed.
  • src/pro/main/ipc/handlers/local_agent/tools/write_file.ts
    • Removed import of resolveFileUploadContent.
    • Removed logic that resolved file upload IDs before writing content, simplifying the write_file tool.
  • testing/fake-llm-server/chatCompletionHandler.ts
    • Updated the fake LLM server to respond with the new <dyad-copy> tag format for image uploads, extracting the temporary path from the user message.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with πŸ‘ and πŸ‘Ž on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution. ↩

@wwwillchen
Copy link
Copy Markdown
Collaborator

@BugBot run

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

The pull request refactors the file attachment handling mechanism. It replaces the write_file tool with a new copy_file tool for uploading files to the codebase. This change involves removing the FileUploadsState utility and directly providing temporary file paths to the AI for copying. A new DyadCopy component and associated parsing logic have been added to the frontend to display these copy operations. The changes improve the clarity and security of file handling by explicitly using a copy operation from a temporary, controlled directory. One comment's rule reference was removed as it incorrectly linked to a prompt injection rule for a path traversal issue.

I am having trouble creating individual review comments. Click here to see my feedback.

src/pro/main/ipc/handlers/local_agent/tools/copy_file.ts (44-60)

critical

This block handles the resolution of the from path, allowing both absolute paths (with a critical security check) and relative paths. The security check ensures that absolute paths are confined to ALLOWED_TEMP_DIR, preventing path traversal attacks.

src/ipc/processors/response_processor.ts (423-435)

critical

This security check is crucial. It ensures that if an absolute path is provided for the from argument in a dyad-copy tag, it must reside within the designated TEMP_DIR. This prevents malicious actors from using the copy_file tool to access or copy arbitrary files on the system, which could lead to information disclosure or system compromise. This directly addresses a potential path traversal vulnerability.

src/ipc/processors/response_processor.ts (417-465)

high

This new block of code processes dyad-copy tags. It includes important security checks to ensure that absolute from paths are restricted to the TEMP_DIR, preventing arbitrary file access. It also handles file existence checks, directory creation, file copying, and Git staging. This is a critical new piece of functionality.

src/pro/main/ipc/handlers/local_agent/tools/copy_file.ts (1-81)

high

This new file defines the copyFileTool, which is a core part of the new file attachment handling. It includes schema validation, consent preview, XML building, and the execution logic for copying files. The security check for absolute paths within ALLOWED_TEMP_DIR is a critical aspect of this tool.

src/ipc/handlers/chat_stream_handlers.ts (772-779)

medium

The system prompt for local-agent mode is updated to guide the AI to use the copy_file tool with from and to paths. This replaces the old write_file and DYAD_ATTACHMENT_0 instructions, ensuring the AI uses the new, more secure method.

When files are attached for upload to the codebase, use the `copy_file` tool to copy them from their temporary path into the project.\n\nExample:\n```\ncopy_file(from="/tmp/dyad-attachments/abc123.png", to="src/assets/logo.png", description="Copy uploaded image into project")\n```\n\nThe temporary file paths are provided in the attachment information above.\n`;

src/ipc/processors/response_processor.ts (113-115)

medium

The removal of FileUploadsState instantiation and related methods (getFileUploadsForChat, clear) from processFullResponseActions confirms that the old file ID resolution logic is entirely removed from the backend processing. This simplifies the code and removes a layer of indirection.

src/ipc/handlers/chat_stream_handlers.ts (784-789)

medium

Similarly, the system prompt for non-local-agent mode (when hasUploadedAttachments is true) is updated to use the dyad-copy tag with from and to attributes. This ensures consistency across different modes for file copying.

When files are attached for upload to the codebase, copy them into the project using this format:\n\n<dyad-copy from="/tmp/dyad-attachments/abc123.png" to="src/assets/logo.png" description="Copy uploaded file"></dyad-copy>\n\nThe temporary file paths are provided in the attachment information above.\n`;

e2e-tests/fixtures/engine/local-agent/upload-to-codebase.ts (5-7)

medium

The comment here is slightly misleading. The AI receives a temp file path and uses the copy_file tool to copy it. The original description mentioned write_file and resolving an attachment ID, which is no longer the case. The updated description is more accurate.

src/ipc/processors/response_processor.ts (422-452)

medium

The removal of the fileUploadsMap and the logic to resolve DYAD_ATTACHMENT_0 from dyadWriteTags processing is a direct consequence of the new copy_file approach. This simplifies the write_file tool's responsibility to just writing content, while copy_file handles the transfer of uploaded files.

src/ipc/utils/file_uploads_state.ts (1-75)

medium

The file_uploads_state.ts file and its FileUploadsState class have been completely removed. This is a significant change, as the previous mechanism of mapping file IDs to uploaded content is no longer used. The new approach directly passes temporary file paths, making this state management obsolete.

src/ipc/handlers/chat_stream_handlers.ts (314-315)

medium

The prompt for upload-to-codebase attachments is updated to instruct the AI to use the copy_file tool and provides the temporary file path directly. This is a crucial change that aligns with the new file handling strategy.

            attachmentInfo += `\n\nFile to upload to codebase: "${attachment.name}" (temp path: ${filePath})\nUse the copy_file tool (or <dyad-copy> tag) to copy this file into the codebase at the appropriate location.\n`;

e2e-tests/fixtures/engine/local-agent/upload-to-codebase.ts (16-20)

medium

The write_file tool has been replaced with copy_file. The arguments have also changed from path and content to from and to, reflecting the new copy operation. This is a significant change in how file uploads are handled.

          name: "copy_file",
          args: {
            from: "/tmp/dyad-attachments/abc123.png",
            to: "assets/uploaded-file.png",
            description: "Copy uploaded file to codebase",
          },

src/pro/main/ipc/handlers/local_agent/tools/file_upload_utils.ts (1-75)

medium

The file_upload_utils.ts file has been removed, along with its resolveFileUploadContent function. This is consistent with the new approach where file IDs are no longer used, and temporary file paths are directly provided for copying.

src/pro/main/ipc/handlers/local_agent/tools/write_file.ts (53)

medium

The logic to resolve file upload IDs has been removed from writeFileTool.execute. The write_file tool now directly writes the provided args.content, as the responsibility for handling uploaded files has shifted to the copy_file tool.

    fs.writeFileSync(fullFilePath, args.content);

github-actions[bot]

This comment was marked as resolved.

@github-actions
Copy link
Copy Markdown
Contributor

πŸ” Dyadbot Code Review Summary

Verdict: πŸ€” NOT SURE - Potential issues

Reviewed by 3 independent agents: Correctness Expert, Code Health Expert, UX Wizard.

Issues Summary

Severity File Issue
πŸ”΄ HIGH e2e-tests/fixtures/engine/local-agent/upload-to-codebase.ts:17 E2E test fixture uses hardcoded temp path that won't exist at runtime
πŸ”΄ HIGH e2e-tests/snapshots/*.aria.yml E2E snapshots still reference old DYAD_ATTACHMENT_0 format (confirmed in 2 snapshot files)
🟑 MEDIUM src/ipc/processors/response_processor.ts:417 Security validation logic duplicated between response_processor and copy_file tool
🟑 MEDIUM src/components/chat/DyadCopy.tsx:36 Raw temp file path (e.g. /tmp/dyad-attachments/a1b2c3.png) exposed to users in 'From' field
🟑 MEDIUM src/components/chat/DyadCopy.tsx:27 DyadCopy card lacks pending/aborted state indicators (inconsistent with DyadWrite)
🟑 MEDIUM src/ipc/handlers/chat_stream_handlers.ts:318 Chat-context attachments now expose temp paths to AI without guidance, may trigger unwanted copies
🟑 MEDIUM src/ipc/processors/response_processor.ts:461 Copy operations missing isSharedServerModule / Supabase deployment checks
🟑 MEDIUM src/ipc/processors/response_processor.ts Proposal handler likely not updated for dyad-copy β€” copy operations may not appear in the approval preview
🟒 Low Priority Notes (5 items)
  • Path check allows temp directory itself as source β€” resolvedFrom === resolvedTempDir permits the directory itself; copyFileSync would throw EISDIR but the check is semantically wrong (response_processor.ts:428, copy_file.ts:51)
  • TEMP_DIR constant defined in 3 separate files β€” "dyad-attachments" string duplicated in response_processor.ts, chat_stream_handlers.ts, and copy_file.ts
  • Self-closing <dyad-copy ... /> tags not matched by regex β€” dyad_tag_parser.ts:75 regex requires explicit closing tag; LLMs may produce self-closing variant
  • Security error messages expose internal system paths β€” response_processor.ts:430 pushes raw path in error message that may surface to users
  • Unused regex capture group β€” dyad_tag_parser.ts:75 captures body content (group 2) but never uses it
🚫 Dropped False Positives (2 items)
  • DyadCopy doesn't accept direct props like DyadRename β€” Dropped: The node.properties pattern is how it's actually called from DyadMarkdownParser; direct props aren't needed
  • Path traversal via symlinks β€” Dropped: Node's path.resolve normalizes paths; safeJoin provides additional protection

Generated by Dyadbot multi-agent code review

@github-actions github-actions bot added the needs-human:review-issue ai agent flagged an issue that requires human review label Feb 20, 2026
@wwwillchen
Copy link
Copy Markdown
Collaborator

@BugBot run

github-actions[bot]

This comment was marked as resolved.

@github-actions
Copy link
Copy Markdown
Contributor

πŸ” Dyadbot Code Review Summary

Verdict: β›” NO - Do NOT merge

Reviewed by 3 independent agents: Correctness Expert, Code Health Expert, UX Wizard.

Issues Summary

Severity File Issue
πŸ”΄ HIGH src/ipc/handlers/shell_handler.ts:36 open-file-path handler has no path validation β€” allows arbitrary file execution
🟑 MEDIUM src/ipc/handlers/chat_stream_handlers.ts:332 Attachment attributes not escaped β€” filenames with quotes break tag parsing
🟑 MEDIUM src/main.ts:128 URL hostname normalization may break paths with uppercase/special characters
🟑 MEDIUM src/components/chat/DyadAttachment.tsx:60 Image thumbnail not keyboard-accessible
🟑 MEDIUM src/components/chat/DyadAttachment.tsx:70 Lightbox modal lacks keyboard dismiss and focus trapping
🟑 MEDIUM src/components/chat/ChatMessage.tsx:145 Attachment-only user messages show floating thumbnails with no container
🟑 MEDIUM src/ipc/handlers/chat_stream_handlers.ts:660 Duplicate message history replacement loop (identical to implementPlanDisplayPrompt block)
🟒 Low Priority Notes (3 items)
  • Long filenames truncate without tooltip β€” src/components/chat/DyadAttachment.tsx:112 β€” Non-image file cards use truncate but don't set title={name} for hover, unlike the image thumbnail
  • dyad-media directory may be committed to git β€” src/ipc/handlers/chat_stream_handlers.ts:299 β€” The dyad-media/ directory is created inside the user's project but not added to .gitignore
  • No loading state for image thumbnails β€” src/components/chat/DyadAttachment.tsx:50 β€” No placeholder/skeleton while images load from the dyad-media:// protocol
🚫 Dropped False Positives (8 items)
  • Text file content no longer read for chat-context β€” Dropped: The text file reading code is still present in the chat-context branch (unchanged in the diff)
  • resolvedFrom === resolvedTempDir allows copying the directory itself β€” Dropped: fs.copyFileSync would throw EISDIR, caught by the try/catch block
  • extractAttachments regex /g flag fragile pattern β€” Dropped: Code is currently correct; inner while runs to null which resets lastIndex
  • No WHY comment for dual-write strategy β€” Dropped: Existing comments adequately explain each write's purpose
  • attribute-type vs attachmentType naming inconsistency β€” Dropped: Standard HTML convention (kebab-case attributes, camelCase in JS)
  • readFile import is dead code β€” Dropped: Still used in two places in the file
  • Temp dir constant defined in 3 places β€” Dropped: Already covered by existing comment Infinite Loop: Checking Node.js setup...Β #2
  • Attachment tag parsing duplicated between ChatMessage and DyadMarkdownParser β€” Dropped: Different use cases (user message extraction vs. markdown rendering)

Generated by Dyadbot multi-agent code review

@wwwillchen
Copy link
Copy Markdown
Collaborator

@BugBot run

@azizmejri1
Copy link
Copy Markdown
Collaborator Author

πŸ€– Claude Code Review Summary

PR Confidence: 4/5

All code review issues addressed except one E2E fixture concern that requires a design decision about the test infrastructure.

Unresolved Threads

Thread Rationale Link
E2E fixture hardcoded temp path LocalAgentFixture format uses static args; cannot adapt to dynamic temp paths. Requires design decision on fixture format or test setup. Principles #3 and #4 don't address test infrastructure. View

Resolved Threads

Issue Rationale Link
Security validation logic duplicated Extracted shared DYAD_ATTACHMENTS_DIR constant and isWithinTempAttachmentsDir() utility used by both response_processor and copy_file tool View
Raw temp path exposed to users in DyadCopy Per Principle #4: Transparent Over Magical, hid cryptic hash paths for temp attachments (absolute paths) while keeping relative paths visible View
DyadCopy lacks pending/aborted state indicators Added DyadStateIndicator for pending ("Copying...") and aborted ("Did not finish") states, consistent with DyadWrite View
Chat-context attachments expose temp paths to AI Removed temp paths from chat-context attachment descriptions to prevent AI from auto-copying reference files View
Copy operations missing sharedModulesChanged checks Added isSharedServerModule and isServerFunction checks with Supabase function deployment, consistent with write/rename/search-replace blocks View
open-file-path handler has no path validation (HIGH) Added path validation restricting shell.openPath to files within the dyad-apps directory View
Attachment attributes not escaped in display tag Applied escapeXmlAttr() to all interpolated values in <dyad-attachment> tag; added unescapeXmlAttr on the parsing side View
URL hostname normalization breaks paths Changed URL format to dyad-media://media/{path} with backward-compatible protocol handler supporting both old and new formats View
Image thumbnail not keyboard-accessible, Lightbox lacks keyboard dismiss Added role="button", tabIndex, onKeyDown (Enter/Space) to thumbnail; added role="dialog", aria-modal, Escape key handler, and aria-label to lightbox View
Attachment-only messages show floating thumbnails Now showing message container for attachment-only user messages View
Duplicate message history replacement loop Combined implementPlanDisplayPrompt and displayUserPrompt conditions into a single loop View
Product Principle Suggestions

The following suggestions could improve rules/product-principles.md to help resolve ambiguous cases in the future:

  • Principle Does it work for Intel Macs?Β #4: Transparent Over Magical: "Add guidance on when to show vs. hide internal implementation details (like temp file paths) in the UI. Showing system paths to users is not transparency - it's information overload. Transparency means showing relevant information the user can act on."

πŸ€– Generated by Claude Code

@github-actions
Copy link
Copy Markdown
Contributor

πŸ” Dyadbot Code Review Summary

Verdict: πŸ€” NOT SURE - Potential issues

Reviewed by 3 independent agents: Correctness Expert, Code Health Expert, UX Wizard.

Issues Summary

Severity File Issue
🟑 MEDIUM src/main.ts:149 Unescaped file path in file:// URL
🟑 MEDIUM src/ipc/utils/dyad_tag_parser.ts:75 Self-closing <dyad-copy/> tags silently ignored
🟑 MEDIUM src/components/chat/ChatMessage.tsx:33 Attachment tag parsing duplicated with DyadMarkdownParser
🟑 MEDIUM src/components/chat/DyadAttachment.tsx:86 Lightbox modal doesn't trap focus or lock scroll
🟒 Low Priority Notes (4 items)
  • Attachment-only messages show empty bubble β€” src/components/chat/ChatMessage.tsx: When user sends only attachments (no text), the message bubble renders empty since VanillaMarkdownParser gets an empty string, producing a visual gap above the attachment thumbnails.
  • implementPlan + displayUserPrompt conflation β€” src/ipc/handlers/chat_stream_handlers.ts:466: When both implementPlanDisplayPrompt and displayUserPrompt are set, attachment display tags are discarded from the DB-stored message due to the ?? chain priority.
  • Windows path detection in DyadCopy β€” src/components/chat/DyadCopy.tsx:28: from.startsWith("/") to detect temp paths won't work on Windows (where temp paths start with C:\...), showing cryptic hash filenames to the user.
  • No image loading state β€” src/components/chat/DyadAttachment.tsx:79: Image thumbnails show empty containers while loading from the dyad-media:// protocol with no skeleton/placeholder.
🚫 Dropped False Positives (5 items)
  • attrRegex g flag skips attributes on subsequent tags β€” Dropped: JavaScript regex resets lastIndex to 0 when exec() returns null, so the inner while loop correctly resets for each outer tag match.
  • isWithinTempAttachmentsDir allows directory itself β€” Dropped: fs.copyFileSync would throw on a directory argument anyway; no actual security risk.
  • Temp files deleted before copy_file executes β€” Dropped: The 30-minute cleanup timeout runs after stream completion (including all tool executions in the agent loop). Persistent copies in dyad-media/ serve as long-term storage.
  • AI can copy sensitive files via relative from paths β€” Dropped: The AI already has full read/write access to the app directory via existing write_file/delete_file tools; copy_file doesn't expand the attack surface.
  • Copy button exposes raw attachment tags β€” Dropped: The copy button only appears on assistant messages, and user messages (which contain <dyad-attachment> tags) don't have a copy button.

Generated by Dyadbot multi-agent code review

github-actions[bot]

This comment was marked as resolved.

github-actions[bot]

This comment was marked as resolved.

github-actions[bot]

This comment was marked as resolved.

github-actions[bot]

This comment was marked as resolved.

@wwwillchen
Copy link
Copy Markdown
Collaborator

@BugBot run

@azizmejri1
Copy link
Copy Markdown
Collaborator Author

Claude Code Review Summary

PR Confidence: 4/5

All actionable review threads have been addressed; one E2E test fixture thread remains open for human decision on test infrastructure design.

Unresolved Threads

Thread Rationale Link
E2E test fixture hardcoded temp path Already flagged for human review by azizmejri1 - requires decision on test infrastructure design (dynamic arg substitution vs pre-creating files). Principles #3 and #4 do not address test infrastructure design. View

Resolved Threads

Issue Rationale Link
Unescaped file path in file:// URL (main.ts) Fixed by using pathToFileURL from Node.js url module for proper encoding View
Self-closing dyad-copy tags silently ignored (dyad_tag_parser.ts) Fixed regex to also match self-closing tags View
Lightbox focus trap and body scroll lock (DyadAttachment.tsx) Added body scroll lock, auto-focus on close button, and onKeyDown Escape handler on the dialog View
Attachment tag parsing duplication (ChatMessage.tsx) Resolved with explanation: the two parsers serve different purposes and consolidation is a reasonable follow-up View
Product Principle Suggestions

The following suggestions could improve rules/product-principles.md to help resolve ambiguous cases in the future:

  • Principle Does it work for Intel Macs?Β #4: Transparent Over Magical: Add guidance on test infrastructure design decisions, specifically whether test fixtures should use dynamic substitution or static pre-created data when testing features that involve dynamically generated paths.

Generated by Claude Code

@azizmejri1
Copy link
Copy Markdown
Collaborator Author

i took a quick look and overall, this PR looks good!

i'm curious why you decided to put it in dyad-media vs. doing something like .dyad/media? not sure if one is better than the other but curious about your reaosning.

I was thinking saving the attachments to dyad-media will allow the users to see their attached files in the file explorer ,unlike using a hidden folder like .dyad/media (this argument may become invalid after shipping the media library)

@wwwillchen
Copy link
Copy Markdown
Collaborator

@azizmejri1 got it. I think we should do .dyad/media for now because this feels more like an implementation detail. for example, we might want to garbage collect things inside the media folder if it becomes too much space. i worry a bit that garbage collecting (aka deleting files) in a more public folder location may surprise users.

Copy link
Copy Markdown
Collaborator

@wwwillchen wwwillchen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. before merging, let's do the .dyad/media change from the earlier comment.

after this PR, let's do a clean-up routine similar to what we do for aimessagesjson:

cleanupOldAiMessagesJson();

e.g. delete media files in .dyad/media more than 30 days old

@wwwillchen
Copy link
Copy Markdown
Collaborator

@BugBot run

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

πŸ’‘ Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 098f1d7311

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with πŸ‘.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

attachmentInfo += `\n\nFile to upload to codebase: ${attachment.name} (file id: ${fileId})\n`;
if (attachment.attachmentType === "upload-to-codebase") {
// Provide the .dyad/media path so the AI can copy it into the codebase
attachmentInfo += `\n\nFile to upload to codebase: "${attachment.name}" (path: ${persistentPath})\nUse the copy_file tool (or <dyad-copy> tag) to copy this file into the codebase at the appropriate location.\n`;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Stop exposing absolute attachment paths in model prompts

For upload-to-codebase attachments, this inserts persistentPath (an absolute local filesystem path) into attachmentInfo, and that text is later appended to userPrompt and sent to the model. In hosted-model sessions this leaks user-specific path data (for example usernames/home directory structure) to third-party providers and unnecessarily expands the privacy surface compared to the previous opaque IDs; use an app-relative path like .dyad/media/<hash> for model-facing instructions instead.

Useful? React with πŸ‘Β / πŸ‘Ž.

Comment on lines +296 to +298
fs.mkdirSync(mediaDir, { recursive: true });
}
await ensureDyadGitignored(appPath);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Fall back when app path is not writable for attachments

Attachment handling now unconditionally creates ${appPath}/.dyad/media and updates .gitignore before processing the request; if an app was imported from a non-writable location (for example skipCopy imports on read-only paths), mkdirSync/ensureDyadGitignored will throw and the whole chat request fails even for chat-context-only uploads. A fallback to temp storage (or deferring writes until a code-modifying action) is needed to avoid breaking attachment usage in those environments.

Useful? React with πŸ‘Β / πŸ‘Ž.

@github-actions
Copy link
Copy Markdown
Contributor

πŸ” Dyadbot Code Review Summary

Verdict: βœ… YES - Ready to merge

Reviewed by 3 independent agents: Correctness Expert, Code Health Expert, UX Wizard.

This PR already has extensive review coverage (~50+ existing comments). After cross-referencing, only one new MEDIUM issue was found that hasn't been previously flagged.

Issues Summary

Severity File Issue
🟑 MEDIUM src/components/chat/DyadAttachment.tsx:75 Image thumbnails have no loading placeholder
🟒 Low Priority Notes (10 items)
  • Self-closing <dyad-attachment> regex won't match - src/components/chat/ChatMessage.tsx:40 β€” Tags are always generated in explicit close form, but the regex should handle self-closing for robustness
  • Gitignore matching ignores comments and negation - src/ipc/handlers/gitignoreUtils.ts:21 β€” A commented-out # .dyad/ or negated !.dyad/ line would be treated as already present
  • Dead typeof content === "string" guard - src/ipc/processors/response_processor.ts:475 β€” After removing FileUploadsState, content is always a string; the check is dead code
  • Long single-line template literal - src/ipc/handlers/chat_stream_handlers.ts:327 β€” The <dyad-attachment> tag builder is very long; consider multi-line for readability
  • ensureGitignored array param only used with single entry - src/ipc/handlers/gitignoreUtils.ts:8 β€” Mild premature generalization vs the original single-entry version
  • node prop typed as any - src/components/chat/DyadCopy.tsx:17 β€” Inconsistent with DyadAttachment's explicit typing
  • Search-replace block missing supabaseProjectId guard - src/ipc/processors/response_processor.ts:395 β€” Pre-existing but exposed by PR fixing adjacent blocks
  • Array index as React key for attachments - src/components/chat/ChatMessage.tsx:243 β€” Could cause stale state if list changes; use att.path || att.url instead
  • Lightbox opens/closes with no transition - src/components/chat/DyadAttachment.tsx:96 β€” Abrupt appearance; a ~150ms fade would feel smoother
  • DyadCopy card is not clickable - src/components/chat/DyadCopy.tsx:32 β€” Unlike DyadWrite, copy cards have no click interaction to view the destination file
🚫 Dropped False Positives (11 items)
  • MD5 hash non-determinism β€” Already covered by existing comments at lines 307 (hash collision) and 316 (file accumulation)
  • URL encoding edge cases β€” Already covered by existing URL encoding comments
  • Historical messages with dyad-attachment tags β€” Directly overlaps with existing comment at line 633
  • Protocol handler subdirectory handling β€” Overlaps with existing path traversal comments on main.ts
  • XML parsing duplication in ChatMessage β€” Extensively discussed in existing comments at lines 48, 56
  • Inline type defined twice β€” Covered by existing comment at line 48
  • Dump prettifier overlapping regexes β€” Covered by existing comment at line 35
  • Attachment-only floating thumbnails β€” Directly overlaps with existing comments at lines 142, 146
  • DyadCopy path label styling β€” Overlaps with existing DyadCopy path comments
  • Copy git-add failure handling β€” Error is correctly caught and reported; minor residual state is acceptable
  • Orphaned comment at line 134 β€” Unverified from diff context, low impact

Generated by Dyadbot multi-agent code review

Comment on lines +75 to +89
<div
className={`relative ${SIZE_CLASSES[size]} rounded-lg overflow-hidden border border-border/60 cursor-pointer hover:brightness-90 transition-all`}
onClick={() => setIsExpanded(true)}
onKeyDown={(e) => {
if (e.key === "Enter" || e.key === " ") {
e.preventDefault();
setIsExpanded(true);
}
}}
role="button"
tabIndex={0}
aria-label={`Expand image: ${name}`}
title={name}
>
<img
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟑 MEDIUM | visual-feedback

Image thumbnails have no loading placeholder

When an image attachment renders, there's no placeholder or skeleton shown while the image loads from the dyad-media:// protocol. Users see an empty bordered box that suddenly pops in with the image, causing a perceived layout shift or flash of empty content. This is especially noticeable for larger images or slower disk reads.

πŸ’‘ Suggestion: Add a lightweight loading skeleton or a subtle Image icon placeholder inside the thumbnail container that shows until the image's onLoad event fires. A simple approach:

const [imageLoaded, setImageLoaded] = useState(false);

// In the thumbnail:
{!imageLoaded && (
  <div className="absolute inset-0 flex items-center justify-center bg-muted animate-pulse">
    <Image size={20} className="text-muted-foreground" />
  </div>
)}
<img ... onLoad={() => setImageLoaded(true)} />

@github-actions
Copy link
Copy Markdown
Contributor

🎭 Playwright Test Results

❌ Some tests failed

OS Passed Failed Flaky Skipped
🍎 macOS 356 4 3 112
πŸͺŸ Windows 359 0 6 112

Summary: 715 passed, 4 failed, 9 flaky, 224 skipped

Failed Tests

🍎 macOS

  • capacitor.spec.ts > capacitor upgrade and sync works
    • Error: expect(locator).toBeVisible() failed
  • concurrent_chat.spec.ts > concurrent chat
    • Error: expect(locator).toBeVisible() failed
  • context_manage.spec.ts > manage context - exclude paths with smart context
    • Error: expect(locator).toMatchAriaSnapshot(expected) failed
  • setup_flow.spec.ts > Setup Flow > node.js install flow
    • TimeoutError: locator.click: Timeout 30000ms exceeded.

πŸ“‹ Re-run Failing Tests (macOS)

Copy and paste to re-run all failing spec files locally:

npm run e2e \
  e2e-tests/capacitor.spec.ts \
  e2e-tests/concurrent_chat.spec.ts \
  e2e-tests/context_manage.spec.ts \
  e2e-tests/setup_flow.spec.ts

⚠️ Flaky Tests

🍎 macOS

  • context_manage.spec.ts > manage context - smart context (passed after 1 retry)
  • logs_server.spec.ts > system messages UI shows server logs with correct type (passed after 1 retry)
  • setup_flow.spec.ts > Setup Flow > setup banner shows correct state when node.js is installed (passed after 1 retry)

πŸͺŸ Windows

  • attach_image.spec.ts > attach image - chat - upload to codebase (passed after 1 retry)
  • chat_input.spec.ts > send button disabled during pending proposal (passed after 1 retry)
  • chat_tabs.spec.ts > right-click context menu: Close tabs to the right (passed after 2 retries)
  • edit_code.spec.ts > edit code (passed after 1 retry)
  • setup_flow.spec.ts > Setup Flow > setup banner shows correct state when node.js is installed (passed after 1 retry)
  • setup_flow.spec.ts > Setup Flow > node.js install flow (passed after 1 retry)

πŸ“Š View full report

@github-actions
Copy link
Copy Markdown
Contributor

🎭 Playwright Test Results

❌ Some tests failed

OS Passed Failed Flaky Skipped
🍎 macOS 359 1 2 112
πŸͺŸ Windows 363 0 6 112

Summary: 722 passed, 1 failed, 8 flaky, 224 skipped

Failed Tests

🍎 macOS

  • setup_flow.spec.ts > Setup Flow > node.js install flow
    • TimeoutError: locator.click: Timeout 30000ms exceeded.

πŸ“‹ Re-run Failing Tests (macOS)

Copy and paste to re-run all failing spec files locally:

npm run e2e \
  e2e-tests/setup_flow.spec.ts

⚠️ Flaky Tests

🍎 macOS

  • logs_server.spec.ts > system messages UI shows server logs with correct type (passed after 1 retry)
  • setup_flow.spec.ts > Setup Flow > setup banner shows correct state when node.js is installed (passed after 1 retry)

πŸͺŸ Windows

  • attach_image.spec.ts > attach image - chat - upload to codebase (passed after 1 retry)
  • chat_input.spec.ts > send button disabled during pending proposal (passed after 1 retry)
  • chat_tabs.spec.ts > right-click context menu: Close tabs to the right (passed after 2 retries)
  • edit_code.spec.ts > edit code (passed after 1 retry)
  • setup_flow.spec.ts > Setup Flow > setup banner shows correct state when node.js is installed (passed after 1 retry)
  • setup_flow.spec.ts > Setup Flow > node.js install flow (passed after 1 retry)

πŸ“Š View full report

@github-actions github-actions bot added needs-human:final-check ai agent thinks everything looks good - needs final review from human and removed needs-human:review-issue ai agent flagged an issue that requires human review labels Feb 24, 2026
@github-actions
Copy link
Copy Markdown
Contributor

🎭 Playwright Test Results

βœ… All tests passed!

OS Passed Flaky Skipped
🍎 macOS 360 2 112
πŸͺŸ Windows 364 6 112

Total: 724 tests passed (8 flaky) (224 skipped)

⚠️ Flaky Tests

🍎 macOS

  • logs_server.spec.ts > system messages UI shows server logs with correct type (passed after 1 retry)
  • setup_flow.spec.ts > Setup Flow > setup banner shows correct state when node.js is installed (passed after 1 retry)

πŸͺŸ Windows

  • attach_image.spec.ts > attach image - chat - upload to codebase (passed after 1 retry)
  • chat_input.spec.ts > send button disabled during pending proposal (passed after 1 retry)
  • chat_tabs.spec.ts > right-click context menu: Close tabs to the right (passed after 2 retries)
  • edit_code.spec.ts > edit code (passed after 1 retry)
  • setup_flow.spec.ts > Setup Flow > setup banner shows correct state when node.js is installed (passed after 1 retry)
  • setup_flow.spec.ts > Setup Flow > node.js install flow (passed after 1 retry)

πŸ“Š View full report

@wwwillchen
Copy link
Copy Markdown
Collaborator

@BugBot run

@github-actions
Copy link
Copy Markdown
Contributor

πŸ” Dyadbot Code Review Summary

Verdict: βœ… YES - Ready to merge

Reviewed by 3 independent agents: Correctness Expert, Code Health Expert, UX Wizard.

This PR already has extensive review coverage (~60+ existing comments across many rounds). After cross-referencing, three new MEDIUM findings below.

Issues Summary

Severity File Issue
🟑 MEDIUM src/ipc/processors/response_processor.ts:419 Copy operations execute before writes, breaking write-then-copy sequences
🟑 MEDIUM src/ipc/utils/media_path_utils.ts:12 Two similar validation functions lack guidance on when to use which
🟑 MEDIUM src/components/chat/DyadCopy.tsx:3 Clipboard 'Copy' icon semantically misleading for file copy operation
🟒 Low Priority Notes (1 item)
  • Lightbox has no open/close transition - src/components/chat/DyadAttachment.tsx:96 - The lightbox overlay appears/disappears instantly with no fade or scale animation, which feels jarring compared to typical modal patterns.
🚫 Dropped False Positives (7 items)
  • base64 extraction with no delimiter validation - Dropped: Input format is controlled by browser FileReader API which always produces valid data:...;base64,... URLs
  • Media URL %2F encoding fragility - Dropped: Electron's URL class correctly preserves %2F in pathname; custom protocol handling is well-established
  • Relative from path allows copying sensitive files - Dropped: AI already has full file read/write access via write_file tool, so copy_file doesn't expand the attack surface
  • extractAttachments utility in React component file - Dropped: Already discussed in existing comments; justified by different parsing purposes (metadata extraction vs tag rendering)
  • State indicator three-way conditional verbose - Dropped: Matches patterns in other DyadCard components, consistency is more important than brevity
  • Sync vs async filesystem mix - Dropped: Consistent with existing patterns in write_file and other utilities throughout the codebase
  • Self-closing dyad-attachment tags not matched - Dropped: Already covered by existing comment about self-closing dyad-copy tags; same pattern

Generated by Dyadbot multi-agent code review

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

πŸ’‘ Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c666281a2e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with πŸ‘.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

to: string;
description?: string;
}[] {
const dyadCopyRegex = /<dyad-copy([^>]*?)(?:>([\s\S]*?)<\/dyad-copy>|\/>)/gi;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Align dyad-copy parsing with renderer tag format

getDyadCopyTags now executes self-closing copy tags (<dyad-copy ... />), but the renderer path (parseCustomTags in src/components/chat/DyadMarkdownParser.tsx) only recognizes paired tags (<dyad-copy>...</dyad-copy>). When a provider emits the self-closing form, the copy still runs in processFullResponseActions, but no DyadCopy card/state is rendered, so users lose visibility into a state-changing action.

Useful? React with πŸ‘Β / πŸ‘Ž.

Comment on lines +294 to +298
const mediaDir = path.join(appPath, DYAD_MEDIA_DIR_NAME);
if (!fs.existsSync(mediaDir)) {
fs.mkdirSync(mediaDir, { recursive: true });
}
await ensureDyadGitignored(appPath);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Avoid hard failure when attachment storage is unwritable

Attachment processing now always writes into {appPath}/.dyad/media and updates .gitignore before streaming starts. In read-only or permission-restricted projects, this throws in chat:stream before any model call, so even chat-context attachments cannot be used. This is a regression from temp-dir-backed handling because it turns a normal user action into a hard request failure in those environments.

Useful? React with πŸ‘Β / πŸ‘Ž.

Copy link
Copy Markdown
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Multi-agent review: 3 new issue(s) found

}

// Process all file copies
const dyadCopyTags = getDyadCopyTags(fullResponse);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟑 MEDIUM | ordering

Copy operations execute before writes, breaking write-then-copy sequences

Copy tags are processed here (lines 419-450) before write tags (lines 452+). If an AI response contains a <dyad-write> to create a file followed by a <dyad-copy> that references that newly-written file as its source, the copy will fail with "Source file does not exist" because copies execute first.

While the primary use case is copying from .dyad/media/ (pre-existing files), the copy_file tool description says it can "copy files within the codebase," which enables this write-then-copy pattern.

πŸ’‘ Suggestion: Either move copy processing to after write processing, or document that copies from files created in the same response are not supported.

* ".dyad" + "media" path segments with at least one segment (filename) after,
* then confirms the resolved path doesn't escape via ".." traversal.
*/
export function isFileWithinAnyDyadMediaDir(absPath: string): boolean {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟑 MEDIUM | missing-why-comment

Two similar validation functions lack guidance on when to use which

isWithinDyadMediaDir(absPath, appPath) (line 12) and isFileWithinAnyDyadMediaDir(absPath) (line 30) serve overlapping purposes with different trade-offs. The first is precise but requires a known app path; the second uses heuristic segment matching for contexts where the app path isn't available (e.g., shell_handler.ts). However, there's no comment explaining this distinction, and a future maintainer could easily use the wrong one or attempt to consolidate them.

πŸ’‘ Suggestion: Add a brief doc comment above each: e.g., /** Use when app path is available (preferred - more precise). */ and /** Use when app path is unknown (e.g., generic IPC handlers). Less precise but safe. */

@@ -0,0 +1,58 @@
import type React from "react";
import type { ReactNode } from "react";
import { Copy } from "lucide-react";
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟑 MEDIUM | icon-semantics

Clipboard 'Copy' icon is semantically misleading for a file copy operation

The Copy icon from lucide-react is a clipboard/document-copy icon (two overlapping rectangles), universally associated with "copy to clipboard." Combined with the "Copy" badge text, users may mistake this card for a clipboard action rather than a file duplication operation. Other file-operation cards use semantically appropriate icons: DyadWrite uses Pencil, DyadRename uses FileEdit, DyadDelete uses a trash icon.

πŸ’‘ Suggestion: Use a file-oriented icon like Files (two file icons), CopyPlus, or FileOutput from lucide-react to clearly convey "file copy."

@github-actions github-actions bot added needs-human:review-issue ai agent flagged an issue that requires human review and removed needs-human:final-check ai agent thinks everything looks good - needs final review from human labels Feb 25, 2026
@github-actions
Copy link
Copy Markdown
Contributor

🎭 Playwright Test Results

❌ Some tests failed

OS Passed Failed Flaky Skipped
🍎 macOS 354 5 4 115
πŸͺŸ Windows 356 0 6 115

Summary: 710 passed, 5 failed, 10 flaky, 230 skipped

Failed Tests

🍎 macOS

  • mcp.spec.ts > mcp - call calculator via http
    • Error: expect(locator).toBeVisible() failed
  • problems.spec.ts > problems auto-fix - enabled
    • Error: expect(locator).toBeVisible() failed
  • problems.spec.ts > problems auto-fix - complex delete-rename-write
    • Error: expect(locator).toBeVisible() failed
  • problems.spec.ts > problems - fix all
    • Error: expect(locator).toBeVisible() failed
  • problems.spec.ts > problems - select specific problems and fix
    • Error: expect(locator).toBeVisible() failed

πŸ“‹ Re-run Failing Tests (macOS)

Copy and paste to re-run all failing spec files locally:

npm run e2e \
  e2e-tests/mcp.spec.ts \
  e2e-tests/problems.spec.ts

⚠️ Flaky Tests

🍎 macOS

  • concurrent_chat.spec.ts > concurrent chat (passed after 1 retry)
  • free_agent_quota.spec.ts > free agent quota - quota resets after 24 hours (passed after 1 retry)
  • problems.spec.ts > problems - manual edit (react/vite) (passed after 2 retries)
  • setup_flow.spec.ts > Setup Flow > setup banner shows correct state when node.js is installed (passed after 1 retry)

πŸͺŸ Windows

  • attach_image.spec.ts > attach image - chat - upload to codebase (passed after 1 retry)
  • context_limit_banner.spec.ts > context limit banner shows 'running out' when near context limit (passed after 1 retry)
  • edit_code.spec.ts > edit code (passed after 1 retry)
  • edit_code.spec.ts > edit code edits the right file (passed after 2 retries)
  • reject.spec.ts > reject (passed after 1 retry)
  • setup_flow.spec.ts > Setup Flow > setup banner shows correct state when node.js is installed (passed after 1 retry)

πŸ“Š View full report

@github-actions github-actions bot added needs-human:final-check ai agent thinks everything looks good - needs final review from human and removed needs-human:review-issue ai agent flagged an issue that requires human review labels Feb 25, 2026
@github-actions
Copy link
Copy Markdown
Contributor

🎭 Playwright Test Results

βœ… All tests passed!

OS Passed Flaky Skipped
🍎 macOS 359 3 115
πŸͺŸ Windows 362 6 115

Total: 721 tests passed (9 flaky) (230 skipped)

⚠️ Flaky Tests

🍎 macOS

  • concurrent_chat.spec.ts > concurrent chat (passed after 1 retry)
  • free_agent_quota.spec.ts > free agent quota - quota resets after 24 hours (passed after 1 retry)
  • setup_flow.spec.ts > Setup Flow > setup banner shows correct state when node.js is installed (passed after 1 retry)

πŸͺŸ Windows

  • attach_image.spec.ts > attach image - chat - upload to codebase (passed after 1 retry)
  • context_limit_banner.spec.ts > context limit banner shows 'running out' when near context limit (passed after 1 retry)
  • edit_code.spec.ts > edit code (passed after 1 retry)
  • edit_code.spec.ts > edit code edits the right file (passed after 2 retries)
  • reject.spec.ts > reject (passed after 1 retry)
  • setup_flow.spec.ts > Setup Flow > setup banner shows correct state when node.js is installed (passed after 1 retry)

πŸ“Š View full report

@azizmejri1 azizmejri1 merged commit 26c65ed into dyad-sh:main Feb 25, 2026
28 of 29 checks passed
@github-actions
Copy link
Copy Markdown
Contributor

🎭 Playwright Test Results

❌ Some tests failed

OS Passed Failed Flaky Skipped
🍎 macOS 359 0 2 115
πŸͺŸ Windows 361 2 4 115

Summary: 720 passed, 2 failed, 6 flaky, 230 skipped

Failed Tests

πŸͺŸ Windows

  • github.spec.ts > create and sync to new repo - custom branch
    • TimeoutError: locator.click: Timeout 30000ms exceeded.
  • setup_flow.spec.ts > Setup Flow > node.js install flow
    • Error: expect(locator).toBeVisible() failed

⚠️ Flaky Tests

🍎 macOS

  • setup_flow.spec.ts > Setup Flow > setup banner shows correct state when node.js is installed (passed after 1 retry)
  • setup_flow.spec.ts > Setup Flow > node.js install flow (passed after 1 retry)

πŸͺŸ Windows

  • attach_image.spec.ts > attach image - chat - upload to codebase (passed after 1 retry)
  • concurrent_chat.spec.ts > concurrent chat (passed after 2 retries)
  • setup_flow.spec.ts > Setup Flow > setup banner shows correct state when node.js is installed (passed after 1 retry)
  • template-create-nextjs.spec.ts > create next.js app (passed after 1 retry)

πŸ“Š View full report

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-human:final-check ai agent thinks everything looks good - needs final review from human

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Improve attachment file handling

2 participants