feat(web): insert path mentions for non-image file drops and pastes - #5543

Closed
kristjaningi wants to merge 12 commits into
pingdotgg:mainfrom
kristjaningi:feat/composer-file-drop-path-mentions
Closed

feat(web): insert path mentions for non-image file drops and pastes#5543
kristjaningi wants to merge 12 commits into
pingdotgg:mainfrom
kristjaningi:feat/composer-file-drop-path-mentions

Conversation

@kristjaningi

@kristjaningikristjaningi commented Aug 6, 2026

Copy link
Copy Markdown

What

Dropping or pasting a non-image file into the composer currently fails with "Unsupported file type ... Please attach image files only." This PR turns those files into file mention chips instead, so the agent can read them where they already live:

  • Drop: non-image files (and folders) become mentions - workspace-relative when inside the repo, absolute otherwise. Images keep the exact existing attachment flow; mixed drops attach the images and mention the rest.
  • Paste: non-image clipboard files become mention chips at the cursor.
  • Desktop bridge: exposes webUtils.getPathForFile as an optional DesktopBridge method (Electron >= 32 removed File.path). Browser tabs have no OS path access; they keep the image-only flow with a clearer error.
  • Path mentions are only offered when the selected environment is the primary same-host backend; SSH/relay/remote/WSL environments have different filesystems and get the same image-only error.
  • Bonus: thread title seeds now render file links as their basename instead of raw [name](path) markup (also fixes titles for existing file-tree drag mentions).

Why this shape

Mentions are plain prompt text, so there are zero contract or server protocol changes. I'm aware of the orchestration V2 rework (#2829) that closed#4058 - this deliberately stays out of that layer entirely, and follows @juliusmarminge's suggestion there to just provide the path where the agent can find the file. Complementary to the attachment work in #3927.

Fixes#2126

Before Screenshots ⛔

image

After Screenshots ✅

CleanShot 2026-08-06 at 18 52 48@2xCleanShot 2026-08-06 at 18 53 46@2xCleanShot 2026-08-06 at 18 54 24@2x

Verification

  • New pure-logic tests for the drop partition, path relativization, and title basenames; typecheck clean across web, desktop, contracts, and shared.
  • Manually tested in the desktop app - screenshots and video coming shortly.

Note

Insert path mentions for non-image file drops and pastes in the chat composer

  • Dropping or pasting non-image files into the chat composer now inserts file-mention chips (workspace-relative when inside the project, absolute otherwise) instead of plain text; images continue to be attached as before.
  • Adds composerFileDrop.ts with platform-aware path resolution, file partitioning, and error composition utilities used by ChatComposer.
  • Exposes getPathForFile on window.desktopBridge via preload.ts so the renderer can resolve on-disk paths for dropped files.
  • Thread titles seeded from prompts containing file-mention links now use basenames via replaceComposerFileLinksWithBasenames instead of raw markdown.
  • Risk: unresolvable non-image file pastes are consumed (no plain-text fallback) and show a thread error instead.

Macroscope summarized 4683aee.


Note

Low Risk
Composer UX and prompt text only; no server protocol changes. Path gating limits wrong-filesystem mentions; extensive unit tests cover edge cases.

Overview
Non-image OS files dropped or pasted into the chat composer become file path mention chips (workspace-relative when inside the project, absolute otherwise) instead of failing as unsupported attachments. Images still use the existing attachment flow; mixed clipboard/drops attach images and mention the rest.

The desktop bridge adds optional getPathForFile via Electron webUtils so the renderer can resolve dropped file paths. Mentions are only offered for the primary same-host environment, with Windows vs POSIX path-style checks (e.g. WSL-only) so bad paths are not sent to the agent; browser/remote/SSH cases keep image-only behavior with clearer thread errors.

Lexical paste handling inserts mention chips for pasted non-image files; drop handling partitions files and appends serialized link text. Shared token/serialization logic now treats POSIX filenames with backslashes correctly. New thread titles seed from basenames via replaceComposerFileLinksWithBasenames instead of raw [name](path) markup. User docs add a composer page describing images, mentions, and limits.

Reviewed by Cursor Bugbot for commit 4683aee. Bugbot is set up for automated code reviews on this repo. Configure here.

Dropping or pasting a non-image file into the composer previously failed
with "Unsupported file type ... Please attach image files only." Referencing
a file by dragging it into the prompt is a standard workflow in comparable
tools, so non-image files now become file mention chips instead:
- Drop: non-image files are partitioned away from the image-attachment flow
and inserted as mentions at the end of the prompt, workspace-relative when
the file lives inside the repo, absolute otherwise. Directories (empty MIME
type) work the same way. Mixed drops attach the images and mention the rest.
- Paste: the editor's paste command inserts mention chips at the cursor for
non-image clipboard files, leaving images to the existing attachment path.
- Desktop bridge: expose webUtils.getPathForFile as an optional
DesktopBridge.getPathForFile, since Electron >= 32 removed File.path and
the renderer cannot learn a dropped file's location otherwise. Browser
tabs have no OS path access and keep the previous behavior.
- Thread titles: seed titles now render file links as their basename instead
of raw "[name](path)" markup. This also fixes titles for existing
file-tree drag mentions.
No contract or server protocol changes: mentions are plain prompt text, so
remote environments and every provider handle them unchanged.
@coderabbitai

coderabbitaiBot commented Aug 6, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: e8ddd24d-8b9b-4807-b4ad-241c8ce581a7

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Comment threadapps/web/src/components/chat/composerFileDrop.ts
Backslash is a valid filename character on POSIX, so normalizing it to "/"
turned a dropped /repo/a\b.txt into a mention for a/b.txt, a different or
nonexistent file. Separator normalization (and the case-insensitive
compare) now applies only when both sides are Windows paths.
Comment threadapps/web/src/components/chat/composerFileDrop.ts
Comment threadapps/web/src/components/chat/composerFileDrop.ts Outdated
Two workspaceRelativeDropPath fixes:
- A POSIX workspace root of "/" trimmed to an empty string and bailed, so
files under a filesystem-root workspace were mentioned by absolute path.
The empty-root guard now checks the original input, and the separator
appended for the prefix check restores the trimmed root.
- The relative slice offset came from the lowercased comparable prefix,
whose length can differ from the original for some Unicode (e.g. "İ"
lowercases to two code points), truncating the result. Slice by the
original root's length instead, and require the boundary character to be
the separator so any residual misalignment falls back to the absolute
path rather than a wrong relative one.
@kristjaningi
kristjaningi marked this pull request as ready for review August 6, 2026 19:07

@chatgpt-codex-connectorchatgpt-codex-connectorBot left a comment

Copy link
Copy Markdown

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:ded9627d13

ℹ️ 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".

Comment threadapps/web/src/components/chat/composerFileDrop.ts
Comment threadapps/web/src/components/composerInlineTokenPaste.ts Outdated
In desktop WSL-only mode the WSL server occupies the primary backend slot,
so the connection-target gate passed while webUtils.getPathForFile returned
Windows host paths the Linux-side agent cannot read. Dropped files were
mentioned as C:/... paths pointing nowhere.
The resolver now also compares the resolved path's style against the
selected environment's platform.os and treats mismatches as unresolvable,
surfacing the existing per-environment error instead. Mismatches are
rejected rather than translated because WSL mount roots are configurable
and a guessed /mnt/c/... path would silently point at a nonexistent file.
A paste can land while a chip is node-selected, so $getSelection() is not a
range selection and $insertPastedFileMentions bailed without inserting.
Nothing downstream recovers: the default paste cannot turn files into
mentions and the composer's paste handler prevents it while only reporting
unresolvable files, so resolvable files vanished with no chip and no error.
Fall back to a range selection at the end of the prompt instead of bailing.
@macroscopeapp

macroscopeappBot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This PR adds a new feature (non-image file drop/paste to path mentions) with substantial new logic for cross-platform path resolution and desktop bridge integration. There is also an unresolved comment identifying a potential bug in error handling for mixed image/file drops.

You can customize Macroscope's approvability policy. Learn more.

@github-actionsgithub-actionsBot added the vouch:unvouched PR author is not yet trusted in the VOUCHED list. label Aug 6, 2026
@github-actionsgithub-actionsBot added the size:L 100-499 changed lines (additions + deletions). label Aug 8, 2026

@chatgpt-codex-connectorchatgpt-codex-connectorBot left a comment

Copy link
Copy Markdown

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:00bf04e0c2

ℹ️ 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".

Comment threadapps/web/src/components/chat/composerFileDrop.ts Outdated
Comment threadapps/web/src/components/composerInlineTokenPaste.ts
kdcokenny added a commit to kdcokenny/t3code that referenced this pull request Aug 8, 2026
Ported from pingdotgg#5543.
Co-authored-by: Kristján Ingi <k.geirsson@gmail.com>

@chatgpt-codex-connectorchatgpt-codex-connectorBot left a comment

Copy link
Copy Markdown

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:dcf162b71b

ℹ️ 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".

Comment threadapps/web/src/components/chat/ChatComposer.tsx

@chatgpt-codex-connectorchatgpt-codex-connectorBot left a comment

Copy link
Copy Markdown

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:61f56a001e

ℹ️ 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".

Comment threadapps/web/src/components/chat/composerFileDrop.ts
Comment threadapps/web/src/components/chat/ChatComposer.tsx
serializeComposerFileLink treated every backslash as a directory
separator, so a POSIX file named a\b.txt became a chip labeled b.txt.
Basename handling is now platform-aware, and token parsing still
accepts older Windows mentions that used a backslash as a separator.
addComposerImages clears the thread error on successful validation, so
writing the mention-unavailable message after it hid a real attachment
count error. Mixed drops now compose both messages in one write.
Non-image drops and pastes now insert path mentions on desktop, with
different fallbacks in the browser and on remote or WSL-only
environments. That is user-visible behavior and belongs in shipped docs.

@cursorcursorBot left a comment

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.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 4683aee. Configure here.

const addComposerImages = async (
files: File[],
options?: { fallbackThreadError?: string | null },
) => {

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.

Mention error dropped on plan prompts

Medium Severity

Moving unresolved-file errors into addComposerImages via fallbackThreadError skips that path when plan questions are pending. The helper returns early after the image toast and never applies the fallback, and paste/drop only call setThreadError in the no-images branch, so a mixed image plus unresolved file no longer surfaces the mention error.

Additional Locations (2)
Fix in CursorFix in Web

Reviewed by Cursor Bugbot for commit 4683aee. Configure here.

@chatgpt-codex-connectorchatgpt-codex-connectorBot left a comment

Copy link
Copy Markdown

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:4683aeefd0

ℹ️ 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".

Comment on lines +2332 to +2335
setThreadError(
threadId,
composeComposerFileDropThreadError(error, options?.fallbackThreadError ?? null),
);

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 Preserve mention errors after image compression fails

When a mixed paste/drop contains an unavailable non-image file—for example, in a browser or remote environment—and an image that passes initial validation but later fails compression, the mention error is combined only here; the later setThreadError(threadId, compressionError) overwrites it. The non-image file is therefore omitted without explanation, so retain or merge fallbackThreadError when reporting asynchronous compression failures as well.

AGENTS.md reference: AGENTS.md:L74-L74

Useful? React with 👍 / 👎.

@t3dotgg

Copy link
Copy Markdown
Member

Note

🤖 GPT-5.6 Sol responding on behalf of Theo

We're closing this PR as we clean up the T3 Code backlog. Thank you for taking the time to put this together.

#6203 keeps the useful drop and paste behavior in a much smaller patch. This branch also changes inline-token paste rules and thread-title seeds, and its extra folder support does not justify that added scope.

If you believe we closed this in error, please reopen the PR and leave a comment explaining what we missed.

@t3dotggt3dotgg closed this Aug 28, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L100-499 changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: Any non-image file attachment support

2 participants

@kristjaningi@t3dotgg
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

feat(web): insert path mentions for non-image file drops and pastes - #5543

Closed
kristjaningi wants to merge 12 commits into
pingdotgg:mainfrom
kristjaningi:feat/composer-file-drop-path-mentions
Closed

feat(web): insert path mentions for non-image file drops and pastes#5543
kristjaningi wants to merge 12 commits into
pingdotgg:mainfrom
kristjaningi:feat/composer-file-drop-path-mentions

Conversation

@kristjaningi

@kristjaningikristjaningi commented Aug 6, 2026

Copy link
Copy Markdown

What

Dropping or pasting a non-image file into the composer currently fails with "Unsupported file type ... Please attach image files only." This PR turns those files into file mention chips instead, so the agent can read them where they already live:

  • Drop: non-image files (and folders) become mentions - workspace-relative when inside the repo, absolute otherwise. Images keep the exact existing attachment flow; mixed drops attach the images and mention the rest.
  • Paste: non-image clipboard files become mention chips at the cursor.
  • Desktop bridge: exposes webUtils.getPathForFile as an optional DesktopBridge method (Electron >= 32 removed File.path). Browser tabs have no OS path access; they keep the image-only flow with a clearer error.
  • Path mentions are only offered when the selected environment is the primary same-host backend; SSH/relay/remote/WSL environments have different filesystems and get the same image-only error.
  • Bonus: thread title seeds now render file links as their basename instead of raw [name](path) markup (also fixes titles for existing file-tree drag mentions).

Why this shape

Mentions are plain prompt text, so there are zero contract or server protocol changes. I'm aware of the orchestration V2 rework (#2829) that closed#4058 - this deliberately stays out of that layer entirely, and follows @juliusmarminge's suggestion there to just provide the path where the agent can find the file. Complementary to the attachment work in #3927.

Fixes#2126

Before Screenshots ⛔

image

After Screenshots ✅

CleanShot 2026-08-06 at 18 52 48@2xCleanShot 2026-08-06 at 18 53 46@2xCleanShot 2026-08-06 at 18 54 24@2x

Verification

  • New pure-logic tests for the drop partition, path relativization, and title basenames; typecheck clean across web, desktop, contracts, and shared.
  • Manually tested in the desktop app - screenshots and video coming shortly.

Note

Insert path mentions for non-image file drops and pastes in the chat composer

  • Dropping or pasting non-image files into the chat composer now inserts file-mention chips (workspace-relative when inside the project, absolute otherwise) instead of plain text; images continue to be attached as before.
  • Adds composerFileDrop.ts with platform-aware path resolution, file partitioning, and error composition utilities used by ChatComposer.
  • Exposes getPathForFile on window.desktopBridge via preload.ts so the renderer can resolve on-disk paths for dropped files.
  • Thread titles seeded from prompts containing file-mention links now use basenames via replaceComposerFileLinksWithBasenames instead of raw markdown.
  • Risk: unresolvable non-image file pastes are consumed (no plain-text fallback) and show a thread error instead.

Macroscope summarized 4683aee.


Note

Low Risk
Composer UX and prompt text only; no server protocol changes. Path gating limits wrong-filesystem mentions; extensive unit tests cover edge cases.

Overview
Non-image OS files dropped or pasted into the chat composer become file path mention chips (workspace-relative when inside the project, absolute otherwise) instead of failing as unsupported attachments. Images still use the existing attachment flow; mixed clipboard/drops attach images and mention the rest.

The desktop bridge adds optional getPathForFile via Electron webUtils so the renderer can resolve dropped file paths. Mentions are only offered for the primary same-host environment, with Windows vs POSIX path-style checks (e.g. WSL-only) so bad paths are not sent to the agent; browser/remote/SSH cases keep image-only behavior with clearer thread errors.

Lexical paste handling inserts mention chips for pasted non-image files; drop handling partitions files and appends serialized link text. Shared token/serialization logic now treats POSIX filenames with backslashes correctly. New thread titles seed from basenames via replaceComposerFileLinksWithBasenames instead of raw [name](path) markup. User docs add a composer page describing images, mentions, and limits.

Reviewed by Cursor Bugbot for commit 4683aee. Bugbot is set up for automated code reviews on this repo. Configure here.

Dropping or pasting a non-image file into the composer previously failed
with "Unsupported file type ... Please attach image files only." Referencing
a file by dragging it into the prompt is a standard workflow in comparable
tools, so non-image files now become file mention chips instead:
- Drop: non-image files are partitioned away from the image-attachment flow
and inserted as mentions at the end of the prompt, workspace-relative when
the file lives inside the repo, absolute otherwise. Directories (empty MIME
type) work the same way. Mixed drops attach the images and mention the rest.
- Paste: the editor's paste command inserts mention chips at the cursor for
non-image clipboard files, leaving images to the existing attachment path.
- Desktop bridge: expose webUtils.getPathForFile as an optional
DesktopBridge.getPathForFile, since Electron >= 32 removed File.path and
the renderer cannot learn a dropped file's location otherwise. Browser
tabs have no OS path access and keep the previous behavior.
- Thread titles: seed titles now render file links as their basename instead
of raw "[name](path)" markup. This also fixes titles for existing
file-tree drag mentions.
No contract or server protocol changes: mentions are plain prompt text, so
remote environments and every provider handle them unchanged.
@coderabbitai

coderabbitaiBot commented Aug 6, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: e8ddd24d-8b9b-4807-b4ad-241c8ce581a7

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Comment threadapps/web/src/components/chat/composerFileDrop.ts
Backslash is a valid filename character on POSIX, so normalizing it to "/"
turned a dropped /repo/a\b.txt into a mention for a/b.txt, a different or
nonexistent file. Separator normalization (and the case-insensitive
compare) now applies only when both sides are Windows paths.
Comment threadapps/web/src/components/chat/composerFileDrop.ts
Comment threadapps/web/src/components/chat/composerFileDrop.ts Outdated
Two workspaceRelativeDropPath fixes:
- A POSIX workspace root of "/" trimmed to an empty string and bailed, so
files under a filesystem-root workspace were mentioned by absolute path.
The empty-root guard now checks the original input, and the separator
appended for the prefix check restores the trimmed root.
- The relative slice offset came from the lowercased comparable prefix,
whose length can differ from the original for some Unicode (e.g. "İ"
lowercases to two code points), truncating the result. Slice by the
original root's length instead, and require the boundary character to be
the separator so any residual misalignment falls back to the absolute
path rather than a wrong relative one.
@kristjaningi
kristjaningi marked this pull request as ready for review August 6, 2026 19:07

@chatgpt-codex-connectorchatgpt-codex-connectorBot left a comment

Copy link
Copy Markdown

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:ded9627d13

ℹ️ 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".

Comment threadapps/web/src/components/chat/composerFileDrop.ts
Comment threadapps/web/src/components/composerInlineTokenPaste.ts Outdated
In desktop WSL-only mode the WSL server occupies the primary backend slot,
so the connection-target gate passed while webUtils.getPathForFile returned
Windows host paths the Linux-side agent cannot read. Dropped files were
mentioned as C:/... paths pointing nowhere.
The resolver now also compares the resolved path's style against the
selected environment's platform.os and treats mismatches as unresolvable,
surfacing the existing per-environment error instead. Mismatches are
rejected rather than translated because WSL mount roots are configurable
and a guessed /mnt/c/... path would silently point at a nonexistent file.
A paste can land while a chip is node-selected, so $getSelection() is not a
range selection and $insertPastedFileMentions bailed without inserting.
Nothing downstream recovers: the default paste cannot turn files into
mentions and the composer's paste handler prevents it while only reporting
unresolvable files, so resolvable files vanished with no chip and no error.
Fall back to a range selection at the end of the prompt instead of bailing.
@macroscopeapp

macroscopeappBot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This PR adds a new feature (non-image file drop/paste to path mentions) with substantial new logic for cross-platform path resolution and desktop bridge integration. There is also an unresolved comment identifying a potential bug in error handling for mixed image/file drops.

You can customize Macroscope's approvability policy. Learn more.

@github-actionsgithub-actionsBot added the vouch:unvouched PR author is not yet trusted in the VOUCHED list. label Aug 6, 2026
@github-actionsgithub-actionsBot added the size:L 100-499 changed lines (additions + deletions). label Aug 8, 2026

@chatgpt-codex-connectorchatgpt-codex-connectorBot left a comment

Copy link
Copy Markdown

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:00bf04e0c2

ℹ️ 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".

Comment threadapps/web/src/components/chat/composerFileDrop.ts Outdated
Comment threadapps/web/src/components/composerInlineTokenPaste.ts
kdcokenny added a commit to kdcokenny/t3code that referenced this pull request Aug 8, 2026
Ported from pingdotgg#5543.
Co-authored-by: Kristján Ingi <k.geirsson@gmail.com>

@chatgpt-codex-connectorchatgpt-codex-connectorBot left a comment

Copy link
Copy Markdown

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:dcf162b71b

ℹ️ 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".

Comment threadapps/web/src/components/chat/ChatComposer.tsx

@chatgpt-codex-connectorchatgpt-codex-connectorBot left a comment

Copy link
Copy Markdown

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:61f56a001e

ℹ️ 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".

Comment threadapps/web/src/components/chat/composerFileDrop.ts
Comment threadapps/web/src/components/chat/ChatComposer.tsx
serializeComposerFileLink treated every backslash as a directory
separator, so a POSIX file named a\b.txt became a chip labeled b.txt.
Basename handling is now platform-aware, and token parsing still
accepts older Windows mentions that used a backslash as a separator.
addComposerImages clears the thread error on successful validation, so
writing the mention-unavailable message after it hid a real attachment
count error. Mixed drops now compose both messages in one write.
Non-image drops and pastes now insert path mentions on desktop, with
different fallbacks in the browser and on remote or WSL-only
environments. That is user-visible behavior and belongs in shipped docs.

@cursorcursorBot left a comment

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.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 4683aee. Configure here.

const addComposerImages = async (
files: File[],
options?: { fallbackThreadError?: string | null },
) => {

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.

Mention error dropped on plan prompts

Medium Severity

Moving unresolved-file errors into addComposerImages via fallbackThreadError skips that path when plan questions are pending. The helper returns early after the image toast and never applies the fallback, and paste/drop only call setThreadError in the no-images branch, so a mixed image plus unresolved file no longer surfaces the mention error.

Additional Locations (2)
Fix in CursorFix in Web

Reviewed by Cursor Bugbot for commit 4683aee. Configure here.

@chatgpt-codex-connectorchatgpt-codex-connectorBot left a comment

Copy link
Copy Markdown

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:4683aeefd0

ℹ️ 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".

Comment on lines +2332 to +2335
setThreadError(
threadId,
composeComposerFileDropThreadError(error, options?.fallbackThreadError ?? null),
);

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 Preserve mention errors after image compression fails

When a mixed paste/drop contains an unavailable non-image file—for example, in a browser or remote environment—and an image that passes initial validation but later fails compression, the mention error is combined only here; the later setThreadError(threadId, compressionError) overwrites it. The non-image file is therefore omitted without explanation, so retain or merge fallbackThreadError when reporting asynchronous compression failures as well.

AGENTS.md reference: AGENTS.md:L74-L74

Useful? React with 👍 / 👎.

@t3dotgg

Copy link
Copy Markdown
Member

Note

🤖 GPT-5.6 Sol responding on behalf of Theo

We're closing this PR as we clean up the T3 Code backlog. Thank you for taking the time to put this together.

#6203 keeps the useful drop and paste behavior in a much smaller patch. This branch also changes inline-token paste rules and thread-title seeds, and its extra folder support does not justify that added scope.

If you believe we closed this in error, please reopen the PR and leave a comment explaining what we missed.

@t3dotggt3dotgg closed this Aug 28, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L100-499 changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: Any non-image file attachment support

2 participants

@kristjaningi@t3dotgg
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(web): insert path mentions for non-image file drops and pastes - #5543

Closed
kristjaningi wants to merge 12 commits into
pingdotgg:mainfrom
kristjaningi:feat/composer-file-drop-path-mentions
Closed

feat(web): insert path mentions for non-image file drops and pastes#5543
kristjaningi wants to merge 12 commits into
pingdotgg:mainfrom
kristjaningi:feat/composer-file-drop-path-mentions

Conversation

@kristjaningi

@kristjaningikristjaningi commented Aug 6, 2026

Copy link
Copy Markdown

What

Dropping or pasting a non-image file into the composer currently fails with "Unsupported file type ... Please attach image files only." This PR turns those files into file mention chips instead, so the agent can read them where they already live:

  • Drop: non-image files (and folders) become mentions - workspace-relative when inside the repo, absolute otherwise. Images keep the exact existing attachment flow; mixed drops attach the images and mention the rest.
  • Paste: non-image clipboard files become mention chips at the cursor.
  • Desktop bridge: exposes webUtils.getPathForFile as an optional DesktopBridge method (Electron >= 32 removed File.path). Browser tabs have no OS path access; they keep the image-only flow with a clearer error.
  • Path mentions are only offered when the selected environment is the primary same-host backend; SSH/relay/remote/WSL environments have different filesystems and get the same image-only error.
  • Bonus: thread title seeds now render file links as their basename instead of raw [name](path) markup (also fixes titles for existing file-tree drag mentions).

Why this shape

Mentions are plain prompt text, so there are zero contract or server protocol changes. I'm aware of the orchestration V2 rework (#2829) that closed#4058 - this deliberately stays out of that layer entirely, and follows @juliusmarminge's suggestion there to just provide the path where the agent can find the file. Complementary to the attachment work in #3927.

Fixes#2126

Before Screenshots ⛔

image

After Screenshots ✅

CleanShot 2026-08-06 at 18 52 48@2xCleanShot 2026-08-06 at 18 53 46@2xCleanShot 2026-08-06 at 18 54 24@2x

Verification

  • New pure-logic tests for the drop partition, path relativization, and title basenames; typecheck clean across web, desktop, contracts, and shared.
  • Manually tested in the desktop app - screenshots and video coming shortly.

Note

Insert path mentions for non-image file drops and pastes in the chat composer

  • Dropping or pasting non-image files into the chat composer now inserts file-mention chips (workspace-relative when inside the project, absolute otherwise) instead of plain text; images continue to be attached as before.
  • Adds composerFileDrop.ts with platform-aware path resolution, file partitioning, and error composition utilities used by ChatComposer.
  • Exposes getPathForFile on window.desktopBridge via preload.ts so the renderer can resolve on-disk paths for dropped files.
  • Thread titles seeded from prompts containing file-mention links now use basenames via replaceComposerFileLinksWithBasenames instead of raw markdown.
  • Risk: unresolvable non-image file pastes are consumed (no plain-text fallback) and show a thread error instead.

Macroscope summarized 4683aee.


Note

Low Risk
Composer UX and prompt text only; no server protocol changes. Path gating limits wrong-filesystem mentions; extensive unit tests cover edge cases.

Overview
Non-image OS files dropped or pasted into the chat composer become file path mention chips (workspace-relative when inside the project, absolute otherwise) instead of failing as unsupported attachments. Images still use the existing attachment flow; mixed clipboard/drops attach images and mention the rest.

The desktop bridge adds optional getPathForFile via Electron webUtils so the renderer can resolve dropped file paths. Mentions are only offered for the primary same-host environment, with Windows vs POSIX path-style checks (e.g. WSL-only) so bad paths are not sent to the agent; browser/remote/SSH cases keep image-only behavior with clearer thread errors.

Lexical paste handling inserts mention chips for pasted non-image files; drop handling partitions files and appends serialized link text. Shared token/serialization logic now treats POSIX filenames with backslashes correctly. New thread titles seed from basenames via replaceComposerFileLinksWithBasenames instead of raw [name](path) markup. User docs add a composer page describing images, mentions, and limits.

Reviewed by Cursor Bugbot for commit 4683aee. Bugbot is set up for automated code reviews on this repo. Configure here.

Dropping or pasting a non-image file into the composer previously failed
with "Unsupported file type ... Please attach image files only." Referencing
a file by dragging it into the prompt is a standard workflow in comparable
tools, so non-image files now become file mention chips instead:
- Drop: non-image files are partitioned away from the image-attachment flow
and inserted as mentions at the end of the prompt, workspace-relative when
the file lives inside the repo, absolute otherwise. Directories (empty MIME
type) work the same way. Mixed drops attach the images and mention the rest.
- Paste: the editor's paste command inserts mention chips at the cursor for
non-image clipboard files, leaving images to the existing attachment path.
- Desktop bridge: expose webUtils.getPathForFile as an optional
DesktopBridge.getPathForFile, since Electron >= 32 removed File.path and
the renderer cannot learn a dropped file's location otherwise. Browser
tabs have no OS path access and keep the previous behavior.
- Thread titles: seed titles now render file links as their basename instead
of raw "[name](path)" markup. This also fixes titles for existing
file-tree drag mentions.
No contract or server protocol changes: mentions are plain prompt text, so
remote environments and every provider handle them unchanged.
@coderabbitai

coderabbitaiBot commented Aug 6, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: e8ddd24d-8b9b-4807-b4ad-241c8ce581a7

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Comment threadapps/web/src/components/chat/composerFileDrop.ts
Backslash is a valid filename character on POSIX, so normalizing it to "/"
turned a dropped /repo/a\b.txt into a mention for a/b.txt, a different or
nonexistent file. Separator normalization (and the case-insensitive
compare) now applies only when both sides are Windows paths.
Comment threadapps/web/src/components/chat/composerFileDrop.ts
Comment threadapps/web/src/components/chat/composerFileDrop.ts Outdated
Two workspaceRelativeDropPath fixes:
- A POSIX workspace root of "/" trimmed to an empty string and bailed, so
files under a filesystem-root workspace were mentioned by absolute path.
The empty-root guard now checks the original input, and the separator
appended for the prefix check restores the trimmed root.
- The relative slice offset came from the lowercased comparable prefix,
whose length can differ from the original for some Unicode (e.g. "İ"
lowercases to two code points), truncating the result. Slice by the
original root's length instead, and require the boundary character to be
the separator so any residual misalignment falls back to the absolute
path rather than a wrong relative one.
@kristjaningi
kristjaningi marked this pull request as ready for review August 6, 2026 19:07

@chatgpt-codex-connectorchatgpt-codex-connectorBot left a comment

Copy link
Copy Markdown

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:ded9627d13

ℹ️ 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".

Comment threadapps/web/src/components/chat/composerFileDrop.ts
Comment threadapps/web/src/components/composerInlineTokenPaste.ts Outdated
In desktop WSL-only mode the WSL server occupies the primary backend slot,
so the connection-target gate passed while webUtils.getPathForFile returned
Windows host paths the Linux-side agent cannot read. Dropped files were
mentioned as C:/... paths pointing nowhere.
The resolver now also compares the resolved path's style against the
selected environment's platform.os and treats mismatches as unresolvable,
surfacing the existing per-environment error instead. Mismatches are
rejected rather than translated because WSL mount roots are configurable
and a guessed /mnt/c/... path would silently point at a nonexistent file.
A paste can land while a chip is node-selected, so $getSelection() is not a
range selection and $insertPastedFileMentions bailed without inserting.
Nothing downstream recovers: the default paste cannot turn files into
mentions and the composer's paste handler prevents it while only reporting
unresolvable files, so resolvable files vanished with no chip and no error.
Fall back to a range selection at the end of the prompt instead of bailing.
@macroscopeapp

macroscopeappBot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This PR adds a new feature (non-image file drop/paste to path mentions) with substantial new logic for cross-platform path resolution and desktop bridge integration. There is also an unresolved comment identifying a potential bug in error handling for mixed image/file drops.

You can customize Macroscope's approvability policy. Learn more.

@github-actionsgithub-actionsBot added the vouch:unvouched PR author is not yet trusted in the VOUCHED list. label Aug 6, 2026
@github-actionsgithub-actionsBot added the size:L 100-499 changed lines (additions + deletions). label Aug 8, 2026

@chatgpt-codex-connectorchatgpt-codex-connectorBot left a comment

Copy link
Copy Markdown

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:00bf04e0c2

ℹ️ 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".

Comment threadapps/web/src/components/chat/composerFileDrop.ts Outdated
Comment threadapps/web/src/components/composerInlineTokenPaste.ts
kdcokenny added a commit to kdcokenny/t3code that referenced this pull request Aug 8, 2026
Ported from pingdotgg#5543.
Co-authored-by: Kristján Ingi <k.geirsson@gmail.com>

@chatgpt-codex-connectorchatgpt-codex-connectorBot left a comment

Copy link
Copy Markdown

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:dcf162b71b

ℹ️ 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".

Comment threadapps/web/src/components/chat/ChatComposer.tsx

@chatgpt-codex-connectorchatgpt-codex-connectorBot left a comment

Copy link
Copy Markdown

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:61f56a001e

ℹ️ 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".

Comment threadapps/web/src/components/chat/composerFileDrop.ts
Comment threadapps/web/src/components/chat/ChatComposer.tsx
serializeComposerFileLink treated every backslash as a directory
separator, so a POSIX file named a\b.txt became a chip labeled b.txt.
Basename handling is now platform-aware, and token parsing still
accepts older Windows mentions that used a backslash as a separator.
addComposerImages clears the thread error on successful validation, so
writing the mention-unavailable message after it hid a real attachment
count error. Mixed drops now compose both messages in one write.
Non-image drops and pastes now insert path mentions on desktop, with
different fallbacks in the browser and on remote or WSL-only
environments. That is user-visible behavior and belongs in shipped docs.

@cursorcursorBot left a comment

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.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 4683aee. Configure here.

const addComposerImages = async (
files: File[],
options?: { fallbackThreadError?: string | null },
) => {

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.

Mention error dropped on plan prompts

Medium Severity

Moving unresolved-file errors into addComposerImages via fallbackThreadError skips that path when plan questions are pending. The helper returns early after the image toast and never applies the fallback, and paste/drop only call setThreadError in the no-images branch, so a mixed image plus unresolved file no longer surfaces the mention error.

Additional Locations (2)
Fix in CursorFix in Web

Reviewed by Cursor Bugbot for commit 4683aee. Configure here.

@chatgpt-codex-connectorchatgpt-codex-connectorBot left a comment

Copy link
Copy Markdown

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:4683aeefd0

ℹ️ 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".

Comment on lines +2332 to +2335
setThreadError(
threadId,
composeComposerFileDropThreadError(error, options?.fallbackThreadError ?? null),
);

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 Preserve mention errors after image compression fails

When a mixed paste/drop contains an unavailable non-image file—for example, in a browser or remote environment—and an image that passes initial validation but later fails compression, the mention error is combined only here; the later setThreadError(threadId, compressionError) overwrites it. The non-image file is therefore omitted without explanation, so retain or merge fallbackThreadError when reporting asynchronous compression failures as well.

AGENTS.md reference: AGENTS.md:L74-L74

Useful? React with 👍 / 👎.

@t3dotgg

Copy link
Copy Markdown
Member

Note

🤖 GPT-5.6 Sol responding on behalf of Theo

We're closing this PR as we clean up the T3 Code backlog. Thank you for taking the time to put this together.

#6203 keeps the useful drop and paste behavior in a much smaller patch. This branch also changes inline-token paste rules and thread-title seeds, and its extra folder support does not justify that added scope.

If you believe we closed this in error, please reopen the PR and leave a comment explaining what we missed.

@t3dotggt3dotgg closed this Aug 28, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L100-499 changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: Any non-image file attachment support

2 participants

@kristjaningi@t3dotgg
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(web): insert path mentions for non-image file drops and pastes - #5543

Closed
kristjaningi wants to merge 12 commits into
pingdotgg:mainfrom
kristjaningi:feat/composer-file-drop-path-mentions
Closed

feat(web): insert path mentions for non-image file drops and pastes#5543
kristjaningi wants to merge 12 commits into
pingdotgg:mainfrom
kristjaningi:feat/composer-file-drop-path-mentions

Conversation

@kristjaningi

@kristjaningikristjaningi commented Aug 6, 2026

Copy link
Copy Markdown

What

Dropping or pasting a non-image file into the composer currently fails with "Unsupported file type ... Please attach image files only." This PR turns those files into file mention chips instead, so the agent can read them where they already live:

  • Drop: non-image files (and folders) become mentions - workspace-relative when inside the repo, absolute otherwise. Images keep the exact existing attachment flow; mixed drops attach the images and mention the rest.
  • Paste: non-image clipboard files become mention chips at the cursor.
  • Desktop bridge: exposes webUtils.getPathForFile as an optional DesktopBridge method (Electron >= 32 removed File.path). Browser tabs have no OS path access; they keep the image-only flow with a clearer error.
  • Path mentions are only offered when the selected environment is the primary same-host backend; SSH/relay/remote/WSL environments have different filesystems and get the same image-only error.
  • Bonus: thread title seeds now render file links as their basename instead of raw [name](path) markup (also fixes titles for existing file-tree drag mentions).

Why this shape

Mentions are plain prompt text, so there are zero contract or server protocol changes. I'm aware of the orchestration V2 rework (#2829) that closed#4058 - this deliberately stays out of that layer entirely, and follows @juliusmarminge's suggestion there to just provide the path where the agent can find the file. Complementary to the attachment work in #3927.

Fixes#2126

Before Screenshots ⛔

image

After Screenshots ✅

CleanShot 2026-08-06 at 18 52 48@2xCleanShot 2026-08-06 at 18 53 46@2xCleanShot 2026-08-06 at 18 54 24@2x

Verification

  • New pure-logic tests for the drop partition, path relativization, and title basenames; typecheck clean across web, desktop, contracts, and shared.
  • Manually tested in the desktop app - screenshots and video coming shortly.

Note

Insert path mentions for non-image file drops and pastes in the chat composer

  • Dropping or pasting non-image files into the chat composer now inserts file-mention chips (workspace-relative when inside the project, absolute otherwise) instead of plain text; images continue to be attached as before.
  • Adds composerFileDrop.ts with platform-aware path resolution, file partitioning, and error composition utilities used by ChatComposer.
  • Exposes getPathForFile on window.desktopBridge via preload.ts so the renderer can resolve on-disk paths for dropped files.
  • Thread titles seeded from prompts containing file-mention links now use basenames via replaceComposerFileLinksWithBasenames instead of raw markdown.
  • Risk: unresolvable non-image file pastes are consumed (no plain-text fallback) and show a thread error instead.

Macroscope summarized 4683aee.


Note

Low Risk
Composer UX and prompt text only; no server protocol changes. Path gating limits wrong-filesystem mentions; extensive unit tests cover edge cases.

Overview
Non-image OS files dropped or pasted into the chat composer become file path mention chips (workspace-relative when inside the project, absolute otherwise) instead of failing as unsupported attachments. Images still use the existing attachment flow; mixed clipboard/drops attach images and mention the rest.

The desktop bridge adds optional getPathForFile via Electron webUtils so the renderer can resolve dropped file paths. Mentions are only offered for the primary same-host environment, with Windows vs POSIX path-style checks (e.g. WSL-only) so bad paths are not sent to the agent; browser/remote/SSH cases keep image-only behavior with clearer thread errors.

Lexical paste handling inserts mention chips for pasted non-image files; drop handling partitions files and appends serialized link text. Shared token/serialization logic now treats POSIX filenames with backslashes correctly. New thread titles seed from basenames via replaceComposerFileLinksWithBasenames instead of raw [name](path) markup. User docs add a composer page describing images, mentions, and limits.

Reviewed by Cursor Bugbot for commit 4683aee. Bugbot is set up for automated code reviews on this repo. Configure here.

Dropping or pasting a non-image file into the composer previously failed
with "Unsupported file type ... Please attach image files only." Referencing
a file by dragging it into the prompt is a standard workflow in comparable
tools, so non-image files now become file mention chips instead:
- Drop: non-image files are partitioned away from the image-attachment flow
and inserted as mentions at the end of the prompt, workspace-relative when
the file lives inside the repo, absolute otherwise. Directories (empty MIME
type) work the same way. Mixed drops attach the images and mention the rest.
- Paste: the editor's paste command inserts mention chips at the cursor for
non-image clipboard files, leaving images to the existing attachment path.
- Desktop bridge: expose webUtils.getPathForFile as an optional
DesktopBridge.getPathForFile, since Electron >= 32 removed File.path and
the renderer cannot learn a dropped file's location otherwise. Browser
tabs have no OS path access and keep the previous behavior.
- Thread titles: seed titles now render file links as their basename instead
of raw "[name](path)" markup. This also fixes titles for existing
file-tree drag mentions.
No contract or server protocol changes: mentions are plain prompt text, so
remote environments and every provider handle them unchanged.
@coderabbitai

coderabbitaiBot commented Aug 6, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: e8ddd24d-8b9b-4807-b4ad-241c8ce581a7

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Comment threadapps/web/src/components/chat/composerFileDrop.ts
Backslash is a valid filename character on POSIX, so normalizing it to "/"
turned a dropped /repo/a\b.txt into a mention for a/b.txt, a different or
nonexistent file. Separator normalization (and the case-insensitive
compare) now applies only when both sides are Windows paths.
Comment threadapps/web/src/components/chat/composerFileDrop.ts
Comment threadapps/web/src/components/chat/composerFileDrop.ts Outdated
Two workspaceRelativeDropPath fixes:
- A POSIX workspace root of "/" trimmed to an empty string and bailed, so
files under a filesystem-root workspace were mentioned by absolute path.
The empty-root guard now checks the original input, and the separator
appended for the prefix check restores the trimmed root.
- The relative slice offset came from the lowercased comparable prefix,
whose length can differ from the original for some Unicode (e.g. "İ"
lowercases to two code points), truncating the result. Slice by the
original root's length instead, and require the boundary character to be
the separator so any residual misalignment falls back to the absolute
path rather than a wrong relative one.
@kristjaningi
kristjaningi marked this pull request as ready for review August 6, 2026 19:07

@chatgpt-codex-connectorchatgpt-codex-connectorBot left a comment

Copy link
Copy Markdown

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:ded9627d13

ℹ️ 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".

Comment threadapps/web/src/components/chat/composerFileDrop.ts
Comment threadapps/web/src/components/composerInlineTokenPaste.ts Outdated
In desktop WSL-only mode the WSL server occupies the primary backend slot,
so the connection-target gate passed while webUtils.getPathForFile returned
Windows host paths the Linux-side agent cannot read. Dropped files were
mentioned as C:/... paths pointing nowhere.
The resolver now also compares the resolved path's style against the
selected environment's platform.os and treats mismatches as unresolvable,
surfacing the existing per-environment error instead. Mismatches are
rejected rather than translated because WSL mount roots are configurable
and a guessed /mnt/c/... path would silently point at a nonexistent file.
A paste can land while a chip is node-selected, so $getSelection() is not a
range selection and $insertPastedFileMentions bailed without inserting.
Nothing downstream recovers: the default paste cannot turn files into
mentions and the composer's paste handler prevents it while only reporting
unresolvable files, so resolvable files vanished with no chip and no error.
Fall back to a range selection at the end of the prompt instead of bailing.
@macroscopeapp

macroscopeappBot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This PR adds a new feature (non-image file drop/paste to path mentions) with substantial new logic for cross-platform path resolution and desktop bridge integration. There is also an unresolved comment identifying a potential bug in error handling for mixed image/file drops.

You can customize Macroscope's approvability policy. Learn more.

@github-actionsgithub-actionsBot added the vouch:unvouched PR author is not yet trusted in the VOUCHED list. label Aug 6, 2026
@github-actionsgithub-actionsBot added the size:L 100-499 changed lines (additions + deletions). label Aug 8, 2026

@chatgpt-codex-connectorchatgpt-codex-connectorBot left a comment

Copy link
Copy Markdown

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:00bf04e0c2

ℹ️ 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".

Comment threadapps/web/src/components/chat/composerFileDrop.ts Outdated
Comment threadapps/web/src/components/composerInlineTokenPaste.ts
kdcokenny added a commit to kdcokenny/t3code that referenced this pull request Aug 8, 2026
Ported from pingdotgg#5543.
Co-authored-by: Kristján Ingi <k.geirsson@gmail.com>

@chatgpt-codex-connectorchatgpt-codex-connectorBot left a comment

Copy link
Copy Markdown

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:dcf162b71b

ℹ️ 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".

Comment threadapps/web/src/components/chat/ChatComposer.tsx

@chatgpt-codex-connectorchatgpt-codex-connectorBot left a comment

Copy link
Copy Markdown

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:61f56a001e

ℹ️ 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".

Comment threadapps/web/src/components/chat/composerFileDrop.ts
Comment threadapps/web/src/components/chat/ChatComposer.tsx
serializeComposerFileLink treated every backslash as a directory
separator, so a POSIX file named a\b.txt became a chip labeled b.txt.
Basename handling is now platform-aware, and token parsing still
accepts older Windows mentions that used a backslash as a separator.
addComposerImages clears the thread error on successful validation, so
writing the mention-unavailable message after it hid a real attachment
count error. Mixed drops now compose both messages in one write.
Non-image drops and pastes now insert path mentions on desktop, with
different fallbacks in the browser and on remote or WSL-only
environments. That is user-visible behavior and belongs in shipped docs.

@cursorcursorBot left a comment

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.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 4683aee. Configure here.

const addComposerImages = async (
files: File[],
options?: { fallbackThreadError?: string | null },
) => {

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.

Mention error dropped on plan prompts

Medium Severity

Moving unresolved-file errors into addComposerImages via fallbackThreadError skips that path when plan questions are pending. The helper returns early after the image toast and never applies the fallback, and paste/drop only call setThreadError in the no-images branch, so a mixed image plus unresolved file no longer surfaces the mention error.

Additional Locations (2)
Fix in CursorFix in Web

Reviewed by Cursor Bugbot for commit 4683aee. Configure here.

@chatgpt-codex-connectorchatgpt-codex-connectorBot left a comment

Copy link
Copy Markdown

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:4683aeefd0

ℹ️ 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".

Comment on lines +2332 to +2335
setThreadError(
threadId,
composeComposerFileDropThreadError(error, options?.fallbackThreadError ?? null),
);

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 Preserve mention errors after image compression fails

When a mixed paste/drop contains an unavailable non-image file—for example, in a browser or remote environment—and an image that passes initial validation but later fails compression, the mention error is combined only here; the later setThreadError(threadId, compressionError) overwrites it. The non-image file is therefore omitted without explanation, so retain or merge fallbackThreadError when reporting asynchronous compression failures as well.

AGENTS.md reference: AGENTS.md:L74-L74

Useful? React with 👍 / 👎.

@t3dotgg

Copy link
Copy Markdown
Member

Note

🤖 GPT-5.6 Sol responding on behalf of Theo

We're closing this PR as we clean up the T3 Code backlog. Thank you for taking the time to put this together.

#6203 keeps the useful drop and paste behavior in a much smaller patch. This branch also changes inline-token paste rules and thread-title seeds, and its extra folder support does not justify that added scope.

If you believe we closed this in error, please reopen the PR and leave a comment explaining what we missed.

@t3dotggt3dotgg closed this Aug 28, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L100-499 changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: Any non-image file attachment support

2 participants

@kristjaningi@t3dotgg
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

feat(web): insert path mentions for non-image file drops and pastes - #5543

Closed
kristjaningi wants to merge 12 commits into
pingdotgg:mainfrom
kristjaningi:feat/composer-file-drop-path-mentions
Closed

feat(web): insert path mentions for non-image file drops and pastes#5543
kristjaningi wants to merge 12 commits into
pingdotgg:mainfrom
kristjaningi:feat/composer-file-drop-path-mentions

Conversation

@kristjaningi

@kristjaningikristjaningi commented Aug 6, 2026

Copy link
Copy Markdown

What

Dropping or pasting a non-image file into the composer currently fails with "Unsupported file type ... Please attach image files only." This PR turns those files into file mention chips instead, so the agent can read them where they already live:

  • Drop: non-image files (and folders) become mentions - workspace-relative when inside the repo, absolute otherwise. Images keep the exact existing attachment flow; mixed drops attach the images and mention the rest.
  • Paste: non-image clipboard files become mention chips at the cursor.
  • Desktop bridge: exposes webUtils.getPathForFile as an optional DesktopBridge method (Electron >= 32 removed File.path). Browser tabs have no OS path access; they keep the image-only flow with a clearer error.
  • Path mentions are only offered when the selected environment is the primary same-host backend; SSH/relay/remote/WSL environments have different filesystems and get the same image-only error.
  • Bonus: thread title seeds now render file links as their basename instead of raw [name](path) markup (also fixes titles for existing file-tree drag mentions).

Why this shape

Mentions are plain prompt text, so there are zero contract or server protocol changes. I'm aware of the orchestration V2 rework (#2829) that closed#4058 - this deliberately stays out of that layer entirely, and follows @juliusmarminge's suggestion there to just provide the path where the agent can find the file. Complementary to the attachment work in #3927.

Fixes#2126

Before Screenshots ⛔

image

After Screenshots ✅

CleanShot 2026-08-06 at 18 52 48@2xCleanShot 2026-08-06 at 18 53 46@2xCleanShot 2026-08-06 at 18 54 24@2x

Verification

  • New pure-logic tests for the drop partition, path relativization, and title basenames; typecheck clean across web, desktop, contracts, and shared.
  • Manually tested in the desktop app - screenshots and video coming shortly.

Note

Insert path mentions for non-image file drops and pastes in the chat composer

  • Dropping or pasting non-image files into the chat composer now inserts file-mention chips (workspace-relative when inside the project, absolute otherwise) instead of plain text; images continue to be attached as before.
  • Adds composerFileDrop.ts with platform-aware path resolution, file partitioning, and error composition utilities used by ChatComposer.
  • Exposes getPathForFile on window.desktopBridge via preload.ts so the renderer can resolve on-disk paths for dropped files.
  • Thread titles seeded from prompts containing file-mention links now use basenames via replaceComposerFileLinksWithBasenames instead of raw markdown.
  • Risk: unresolvable non-image file pastes are consumed (no plain-text fallback) and show a thread error instead.

Macroscope summarized 4683aee.


Note

Low Risk
Composer UX and prompt text only; no server protocol changes. Path gating limits wrong-filesystem mentions; extensive unit tests cover edge cases.

Overview
Non-image OS files dropped or pasted into the chat composer become file path mention chips (workspace-relative when inside the project, absolute otherwise) instead of failing as unsupported attachments. Images still use the existing attachment flow; mixed clipboard/drops attach images and mention the rest.

The desktop bridge adds optional getPathForFile via Electron webUtils so the renderer can resolve dropped file paths. Mentions are only offered for the primary same-host environment, with Windows vs POSIX path-style checks (e.g. WSL-only) so bad paths are not sent to the agent; browser/remote/SSH cases keep image-only behavior with clearer thread errors.

Lexical paste handling inserts mention chips for pasted non-image files; drop handling partitions files and appends serialized link text. Shared token/serialization logic now treats POSIX filenames with backslashes correctly. New thread titles seed from basenames via replaceComposerFileLinksWithBasenames instead of raw [name](path) markup. User docs add a composer page describing images, mentions, and limits.

Reviewed by Cursor Bugbot for commit 4683aee. Bugbot is set up for automated code reviews on this repo. Configure here.

Dropping or pasting a non-image file into the composer previously failed
with "Unsupported file type ... Please attach image files only." Referencing
a file by dragging it into the prompt is a standard workflow in comparable
tools, so non-image files now become file mention chips instead:
- Drop: non-image files are partitioned away from the image-attachment flow
and inserted as mentions at the end of the prompt, workspace-relative when
the file lives inside the repo, absolute otherwise. Directories (empty MIME
type) work the same way. Mixed drops attach the images and mention the rest.
- Paste: the editor's paste command inserts mention chips at the cursor for
non-image clipboard files, leaving images to the existing attachment path.
- Desktop bridge: expose webUtils.getPathForFile as an optional
DesktopBridge.getPathForFile, since Electron >= 32 removed File.path and
the renderer cannot learn a dropped file's location otherwise. Browser
tabs have no OS path access and keep the previous behavior.
- Thread titles: seed titles now render file links as their basename instead
of raw "[name](path)" markup. This also fixes titles for existing
file-tree drag mentions.
No contract or server protocol changes: mentions are plain prompt text, so
remote environments and every provider handle them unchanged.
@coderabbitai

coderabbitaiBot commented Aug 6, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: e8ddd24d-8b9b-4807-b4ad-241c8ce581a7

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Comment threadapps/web/src/components/chat/composerFileDrop.ts
Backslash is a valid filename character on POSIX, so normalizing it to "/"
turned a dropped /repo/a\b.txt into a mention for a/b.txt, a different or
nonexistent file. Separator normalization (and the case-insensitive
compare) now applies only when both sides are Windows paths.
Comment threadapps/web/src/components/chat/composerFileDrop.ts
Comment threadapps/web/src/components/chat/composerFileDrop.ts Outdated
Two workspaceRelativeDropPath fixes:
- A POSIX workspace root of "/" trimmed to an empty string and bailed, so
files under a filesystem-root workspace were mentioned by absolute path.
The empty-root guard now checks the original input, and the separator
appended for the prefix check restores the trimmed root.
- The relative slice offset came from the lowercased comparable prefix,
whose length can differ from the original for some Unicode (e.g. "İ"
lowercases to two code points), truncating the result. Slice by the
original root's length instead, and require the boundary character to be
the separator so any residual misalignment falls back to the absolute
path rather than a wrong relative one.
@kristjaningi
kristjaningi marked this pull request as ready for review August 6, 2026 19:07

@chatgpt-codex-connectorchatgpt-codex-connectorBot left a comment

Copy link
Copy Markdown

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:ded9627d13

ℹ️ 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".

Comment threadapps/web/src/components/chat/composerFileDrop.ts
Comment threadapps/web/src/components/composerInlineTokenPaste.ts Outdated
In desktop WSL-only mode the WSL server occupies the primary backend slot,
so the connection-target gate passed while webUtils.getPathForFile returned
Windows host paths the Linux-side agent cannot read. Dropped files were
mentioned as C:/... paths pointing nowhere.
The resolver now also compares the resolved path's style against the
selected environment's platform.os and treats mismatches as unresolvable,
surfacing the existing per-environment error instead. Mismatches are
rejected rather than translated because WSL mount roots are configurable
and a guessed /mnt/c/... path would silently point at a nonexistent file.
A paste can land while a chip is node-selected, so $getSelection() is not a
range selection and $insertPastedFileMentions bailed without inserting.
Nothing downstream recovers: the default paste cannot turn files into
mentions and the composer's paste handler prevents it while only reporting
unresolvable files, so resolvable files vanished with no chip and no error.
Fall back to a range selection at the end of the prompt instead of bailing.
@macroscopeapp

macroscopeappBot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This PR adds a new feature (non-image file drop/paste to path mentions) with substantial new logic for cross-platform path resolution and desktop bridge integration. There is also an unresolved comment identifying a potential bug in error handling for mixed image/file drops.

You can customize Macroscope's approvability policy. Learn more.

@github-actionsgithub-actionsBot added the vouch:unvouched PR author is not yet trusted in the VOUCHED list. label Aug 6, 2026
@github-actionsgithub-actionsBot added the size:L 100-499 changed lines (additions + deletions). label Aug 8, 2026

@chatgpt-codex-connectorchatgpt-codex-connectorBot left a comment

Copy link
Copy Markdown

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:00bf04e0c2

ℹ️ 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".

Comment threadapps/web/src/components/chat/composerFileDrop.ts Outdated
Comment threadapps/web/src/components/composerInlineTokenPaste.ts
kdcokenny added a commit to kdcokenny/t3code that referenced this pull request Aug 8, 2026
Ported from pingdotgg#5543.
Co-authored-by: Kristján Ingi <k.geirsson@gmail.com>

@chatgpt-codex-connectorchatgpt-codex-connectorBot left a comment

Copy link
Copy Markdown

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:dcf162b71b

ℹ️ 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".

Comment threadapps/web/src/components/chat/ChatComposer.tsx

@chatgpt-codex-connectorchatgpt-codex-connectorBot left a comment

Copy link
Copy Markdown

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:61f56a001e

ℹ️ 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".

Comment threadapps/web/src/components/chat/composerFileDrop.ts
Comment threadapps/web/src/components/chat/ChatComposer.tsx
serializeComposerFileLink treated every backslash as a directory
separator, so a POSIX file named a\b.txt became a chip labeled b.txt.
Basename handling is now platform-aware, and token parsing still
accepts older Windows mentions that used a backslash as a separator.
addComposerImages clears the thread error on successful validation, so
writing the mention-unavailable message after it hid a real attachment
count error. Mixed drops now compose both messages in one write.
Non-image drops and pastes now insert path mentions on desktop, with
different fallbacks in the browser and on remote or WSL-only
environments. That is user-visible behavior and belongs in shipped docs.

@cursorcursorBot left a comment

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.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 4683aee. Configure here.

const addComposerImages = async (
files: File[],
options?: { fallbackThreadError?: string | null },
) => {

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.

Mention error dropped on plan prompts

Medium Severity

Moving unresolved-file errors into addComposerImages via fallbackThreadError skips that path when plan questions are pending. The helper returns early after the image toast and never applies the fallback, and paste/drop only call setThreadError in the no-images branch, so a mixed image plus unresolved file no longer surfaces the mention error.

Additional Locations (2)
Fix in CursorFix in Web

Reviewed by Cursor Bugbot for commit 4683aee. Configure here.

@chatgpt-codex-connectorchatgpt-codex-connectorBot left a comment

Copy link
Copy Markdown

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:4683aeefd0

ℹ️ 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".

Comment on lines +2332 to +2335
setThreadError(
threadId,
composeComposerFileDropThreadError(error, options?.fallbackThreadError ?? null),
);

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 Preserve mention errors after image compression fails

When a mixed paste/drop contains an unavailable non-image file—for example, in a browser or remote environment—and an image that passes initial validation but later fails compression, the mention error is combined only here; the later setThreadError(threadId, compressionError) overwrites it. The non-image file is therefore omitted without explanation, so retain or merge fallbackThreadError when reporting asynchronous compression failures as well.

AGENTS.md reference: AGENTS.md:L74-L74

Useful? React with 👍 / 👎.

@t3dotgg

Copy link
Copy Markdown
Member

Note

🤖 GPT-5.6 Sol responding on behalf of Theo

We're closing this PR as we clean up the T3 Code backlog. Thank you for taking the time to put this together.

#6203 keeps the useful drop and paste behavior in a much smaller patch. This branch also changes inline-token paste rules and thread-title seeds, and its extra folder support does not justify that added scope.

If you believe we closed this in error, please reopen the PR and leave a comment explaining what we missed.

@t3dotggt3dotgg closed this Aug 28, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L100-499 changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: Any non-image file attachment support

2 participants

@kristjaningi@t3dotgg
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(web): insert path mentions for non-image file drops and pastes - #5543

Closed
kristjaningi wants to merge 12 commits into
pingdotgg:mainfrom
kristjaningi:feat/composer-file-drop-path-mentions
Closed

feat(web): insert path mentions for non-image file drops and pastes#5543
kristjaningi wants to merge 12 commits into
pingdotgg:mainfrom
kristjaningi:feat/composer-file-drop-path-mentions

Conversation

@kristjaningi

@kristjaningikristjaningi commented Aug 6, 2026

Copy link
Copy Markdown

What

Dropping or pasting a non-image file into the composer currently fails with "Unsupported file type ... Please attach image files only." This PR turns those files into file mention chips instead, so the agent can read them where they already live:

  • Drop: non-image files (and folders) become mentions - workspace-relative when inside the repo, absolute otherwise. Images keep the exact existing attachment flow; mixed drops attach the images and mention the rest.
  • Paste: non-image clipboard files become mention chips at the cursor.
  • Desktop bridge: exposes webUtils.getPathForFile as an optional DesktopBridge method (Electron >= 32 removed File.path). Browser tabs have no OS path access; they keep the image-only flow with a clearer error.
  • Path mentions are only offered when the selected environment is the primary same-host backend; SSH/relay/remote/WSL environments have different filesystems and get the same image-only error.
  • Bonus: thread title seeds now render file links as their basename instead of raw [name](path) markup (also fixes titles for existing file-tree drag mentions).

Why this shape

Mentions are plain prompt text, so there are zero contract or server protocol changes. I'm aware of the orchestration V2 rework (#2829) that closed#4058 - this deliberately stays out of that layer entirely, and follows @juliusmarminge's suggestion there to just provide the path where the agent can find the file. Complementary to the attachment work in #3927.

Fixes#2126

Before Screenshots ⛔

image

After Screenshots ✅

CleanShot 2026-08-06 at 18 52 48@2xCleanShot 2026-08-06 at 18 53 46@2xCleanShot 2026-08-06 at 18 54 24@2x

Verification

  • New pure-logic tests for the drop partition, path relativization, and title basenames; typecheck clean across web, desktop, contracts, and shared.
  • Manually tested in the desktop app - screenshots and video coming shortly.

Note

Insert path mentions for non-image file drops and pastes in the chat composer

  • Dropping or pasting non-image files into the chat composer now inserts file-mention chips (workspace-relative when inside the project, absolute otherwise) instead of plain text; images continue to be attached as before.
  • Adds composerFileDrop.ts with platform-aware path resolution, file partitioning, and error composition utilities used by ChatComposer.
  • Exposes getPathForFile on window.desktopBridge via preload.ts so the renderer can resolve on-disk paths for dropped files.
  • Thread titles seeded from prompts containing file-mention links now use basenames via replaceComposerFileLinksWithBasenames instead of raw markdown.
  • Risk: unresolvable non-image file pastes are consumed (no plain-text fallback) and show a thread error instead.

Macroscope summarized 4683aee.


Note

Low Risk
Composer UX and prompt text only; no server protocol changes. Path gating limits wrong-filesystem mentions; extensive unit tests cover edge cases.

Overview
Non-image OS files dropped or pasted into the chat composer become file path mention chips (workspace-relative when inside the project, absolute otherwise) instead of failing as unsupported attachments. Images still use the existing attachment flow; mixed clipboard/drops attach images and mention the rest.

The desktop bridge adds optional getPathForFile via Electron webUtils so the renderer can resolve dropped file paths. Mentions are only offered for the primary same-host environment, with Windows vs POSIX path-style checks (e.g. WSL-only) so bad paths are not sent to the agent; browser/remote/SSH cases keep image-only behavior with clearer thread errors.

Lexical paste handling inserts mention chips for pasted non-image files; drop handling partitions files and appends serialized link text. Shared token/serialization logic now treats POSIX filenames with backslashes correctly. New thread titles seed from basenames via replaceComposerFileLinksWithBasenames instead of raw [name](path) markup. User docs add a composer page describing images, mentions, and limits.

Reviewed by Cursor Bugbot for commit 4683aee. Bugbot is set up for automated code reviews on this repo. Configure here.

Dropping or pasting a non-image file into the composer previously failed
with "Unsupported file type ... Please attach image files only." Referencing
a file by dragging it into the prompt is a standard workflow in comparable
tools, so non-image files now become file mention chips instead:
- Drop: non-image files are partitioned away from the image-attachment flow
and inserted as mentions at the end of the prompt, workspace-relative when
the file lives inside the repo, absolute otherwise. Directories (empty MIME
type) work the same way. Mixed drops attach the images and mention the rest.
- Paste: the editor's paste command inserts mention chips at the cursor for
non-image clipboard files, leaving images to the existing attachment path.
- Desktop bridge: expose webUtils.getPathForFile as an optional
DesktopBridge.getPathForFile, since Electron >= 32 removed File.path and
the renderer cannot learn a dropped file's location otherwise. Browser
tabs have no OS path access and keep the previous behavior.
- Thread titles: seed titles now render file links as their basename instead
of raw "[name](path)" markup. This also fixes titles for existing
file-tree drag mentions.
No contract or server protocol changes: mentions are plain prompt text, so
remote environments and every provider handle them unchanged.
@coderabbitai

coderabbitaiBot commented Aug 6, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: e8ddd24d-8b9b-4807-b4ad-241c8ce581a7

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Comment threadapps/web/src/components/chat/composerFileDrop.ts
Backslash is a valid filename character on POSIX, so normalizing it to "/"
turned a dropped /repo/a\b.txt into a mention for a/b.txt, a different or
nonexistent file. Separator normalization (and the case-insensitive
compare) now applies only when both sides are Windows paths.
Comment threadapps/web/src/components/chat/composerFileDrop.ts
Comment threadapps/web/src/components/chat/composerFileDrop.ts Outdated
Two workspaceRelativeDropPath fixes:
- A POSIX workspace root of "/" trimmed to an empty string and bailed, so
files under a filesystem-root workspace were mentioned by absolute path.
The empty-root guard now checks the original input, and the separator
appended for the prefix check restores the trimmed root.
- The relative slice offset came from the lowercased comparable prefix,
whose length can differ from the original for some Unicode (e.g. "İ"
lowercases to two code points), truncating the result. Slice by the
original root's length instead, and require the boundary character to be
the separator so any residual misalignment falls back to the absolute
path rather than a wrong relative one.
@kristjaningi
kristjaningi marked this pull request as ready for review August 6, 2026 19:07

@chatgpt-codex-connectorchatgpt-codex-connectorBot left a comment

Copy link
Copy Markdown

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:ded9627d13

ℹ️ 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".

Comment threadapps/web/src/components/chat/composerFileDrop.ts
Comment threadapps/web/src/components/composerInlineTokenPaste.ts Outdated
In desktop WSL-only mode the WSL server occupies the primary backend slot,
so the connection-target gate passed while webUtils.getPathForFile returned
Windows host paths the Linux-side agent cannot read. Dropped files were
mentioned as C:/... paths pointing nowhere.
The resolver now also compares the resolved path's style against the
selected environment's platform.os and treats mismatches as unresolvable,
surfacing the existing per-environment error instead. Mismatches are
rejected rather than translated because WSL mount roots are configurable
and a guessed /mnt/c/... path would silently point at a nonexistent file.
A paste can land while a chip is node-selected, so $getSelection() is not a
range selection and $insertPastedFileMentions bailed without inserting.
Nothing downstream recovers: the default paste cannot turn files into
mentions and the composer's paste handler prevents it while only reporting
unresolvable files, so resolvable files vanished with no chip and no error.
Fall back to a range selection at the end of the prompt instead of bailing.
@macroscopeapp

macroscopeappBot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This PR adds a new feature (non-image file drop/paste to path mentions) with substantial new logic for cross-platform path resolution and desktop bridge integration. There is also an unresolved comment identifying a potential bug in error handling for mixed image/file drops.

You can customize Macroscope's approvability policy. Learn more.

@github-actionsgithub-actionsBot added the vouch:unvouched PR author is not yet trusted in the VOUCHED list. label Aug 6, 2026
@github-actionsgithub-actionsBot added the size:L 100-499 changed lines (additions + deletions). label Aug 8, 2026

@chatgpt-codex-connectorchatgpt-codex-connectorBot left a comment

Copy link
Copy Markdown

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:00bf04e0c2

ℹ️ 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".

Comment threadapps/web/src/components/chat/composerFileDrop.ts Outdated
Comment threadapps/web/src/components/composerInlineTokenPaste.ts
kdcokenny added a commit to kdcokenny/t3code that referenced this pull request Aug 8, 2026
Ported from pingdotgg#5543.
Co-authored-by: Kristján Ingi <k.geirsson@gmail.com>

@chatgpt-codex-connectorchatgpt-codex-connectorBot left a comment

Copy link
Copy Markdown

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:dcf162b71b

ℹ️ 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".

Comment threadapps/web/src/components/chat/ChatComposer.tsx

@chatgpt-codex-connectorchatgpt-codex-connectorBot left a comment

Copy link
Copy Markdown

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:61f56a001e

ℹ️ 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".

Comment threadapps/web/src/components/chat/composerFileDrop.ts
Comment threadapps/web/src/components/chat/ChatComposer.tsx
serializeComposerFileLink treated every backslash as a directory
separator, so a POSIX file named a\b.txt became a chip labeled b.txt.
Basename handling is now platform-aware, and token parsing still
accepts older Windows mentions that used a backslash as a separator.
addComposerImages clears the thread error on successful validation, so
writing the mention-unavailable message after it hid a real attachment
count error. Mixed drops now compose both messages in one write.
Non-image drops and pastes now insert path mentions on desktop, with
different fallbacks in the browser and on remote or WSL-only
environments. That is user-visible behavior and belongs in shipped docs.

@cursorcursorBot left a comment

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.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 4683aee. Configure here.

const addComposerImages = async (
files: File[],
options?: { fallbackThreadError?: string | null },
) => {

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.

Mention error dropped on plan prompts

Medium Severity

Moving unresolved-file errors into addComposerImages via fallbackThreadError skips that path when plan questions are pending. The helper returns early after the image toast and never applies the fallback, and paste/drop only call setThreadError in the no-images branch, so a mixed image plus unresolved file no longer surfaces the mention error.

Additional Locations (2)
Fix in CursorFix in Web

Reviewed by Cursor Bugbot for commit 4683aee. Configure here.

@chatgpt-codex-connectorchatgpt-codex-connectorBot left a comment

Copy link
Copy Markdown

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:4683aeefd0

ℹ️ 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".

Comment on lines +2332 to +2335
setThreadError(
threadId,
composeComposerFileDropThreadError(error, options?.fallbackThreadError ?? null),
);

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 Preserve mention errors after image compression fails

When a mixed paste/drop contains an unavailable non-image file—for example, in a browser or remote environment—and an image that passes initial validation but later fails compression, the mention error is combined only here; the later setThreadError(threadId, compressionError) overwrites it. The non-image file is therefore omitted without explanation, so retain or merge fallbackThreadError when reporting asynchronous compression failures as well.

AGENTS.md reference: AGENTS.md:L74-L74

Useful? React with 👍 / 👎.

@t3dotgg

Copy link
Copy Markdown
Member

Note

🤖 GPT-5.6 Sol responding on behalf of Theo

We're closing this PR as we clean up the T3 Code backlog. Thank you for taking the time to put this together.

#6203 keeps the useful drop and paste behavior in a much smaller patch. This branch also changes inline-token paste rules and thread-title seeds, and its extra folder support does not justify that added scope.

If you believe we closed this in error, please reopen the PR and leave a comment explaining what we missed.

@t3dotggt3dotgg closed this Aug 28, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L100-499 changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: Any non-image file attachment support

2 participants

@kristjaningi@t3dotgg
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(web): insert path mentions for non-image file drops and pastes - #5543

Closed
kristjaningi wants to merge 12 commits into
pingdotgg:mainfrom
kristjaningi:feat/composer-file-drop-path-mentions
Closed

feat(web): insert path mentions for non-image file drops and pastes#5543
kristjaningi wants to merge 12 commits into
pingdotgg:mainfrom
kristjaningi:feat/composer-file-drop-path-mentions

Conversation

@kristjaningi

@kristjaningikristjaningi commented Aug 6, 2026

Copy link
Copy Markdown

What

Dropping or pasting a non-image file into the composer currently fails with "Unsupported file type ... Please attach image files only." This PR turns those files into file mention chips instead, so the agent can read them where they already live:

  • Drop: non-image files (and folders) become mentions - workspace-relative when inside the repo, absolute otherwise. Images keep the exact existing attachment flow; mixed drops attach the images and mention the rest.
  • Paste: non-image clipboard files become mention chips at the cursor.
  • Desktop bridge: exposes webUtils.getPathForFile as an optional DesktopBridge method (Electron >= 32 removed File.path). Browser tabs have no OS path access; they keep the image-only flow with a clearer error.
  • Path mentions are only offered when the selected environment is the primary same-host backend; SSH/relay/remote/WSL environments have different filesystems and get the same image-only error.
  • Bonus: thread title seeds now render file links as their basename instead of raw [name](path) markup (also fixes titles for existing file-tree drag mentions).

Why this shape

Mentions are plain prompt text, so there are zero contract or server protocol changes. I'm aware of the orchestration V2 rework (#2829) that closed#4058 - this deliberately stays out of that layer entirely, and follows @juliusmarminge's suggestion there to just provide the path where the agent can find the file. Complementary to the attachment work in #3927.

Fixes#2126

Before Screenshots ⛔

image

After Screenshots ✅

CleanShot 2026-08-06 at 18 52 48@2xCleanShot 2026-08-06 at 18 53 46@2xCleanShot 2026-08-06 at 18 54 24@2x

Verification

  • New pure-logic tests for the drop partition, path relativization, and title basenames; typecheck clean across web, desktop, contracts, and shared.
  • Manually tested in the desktop app - screenshots and video coming shortly.

Note

Insert path mentions for non-image file drops and pastes in the chat composer

  • Dropping or pasting non-image files into the chat composer now inserts file-mention chips (workspace-relative when inside the project, absolute otherwise) instead of plain text; images continue to be attached as before.
  • Adds composerFileDrop.ts with platform-aware path resolution, file partitioning, and error composition utilities used by ChatComposer.
  • Exposes getPathForFile on window.desktopBridge via preload.ts so the renderer can resolve on-disk paths for dropped files.
  • Thread titles seeded from prompts containing file-mention links now use basenames via replaceComposerFileLinksWithBasenames instead of raw markdown.
  • Risk: unresolvable non-image file pastes are consumed (no plain-text fallback) and show a thread error instead.

Macroscope summarized 4683aee.


Note

Low Risk
Composer UX and prompt text only; no server protocol changes. Path gating limits wrong-filesystem mentions; extensive unit tests cover edge cases.

Overview
Non-image OS files dropped or pasted into the chat composer become file path mention chips (workspace-relative when inside the project, absolute otherwise) instead of failing as unsupported attachments. Images still use the existing attachment flow; mixed clipboard/drops attach images and mention the rest.

The desktop bridge adds optional getPathForFile via Electron webUtils so the renderer can resolve dropped file paths. Mentions are only offered for the primary same-host environment, with Windows vs POSIX path-style checks (e.g. WSL-only) so bad paths are not sent to the agent; browser/remote/SSH cases keep image-only behavior with clearer thread errors.

Lexical paste handling inserts mention chips for pasted non-image files; drop handling partitions files and appends serialized link text. Shared token/serialization logic now treats POSIX filenames with backslashes correctly. New thread titles seed from basenames via replaceComposerFileLinksWithBasenames instead of raw [name](path) markup. User docs add a composer page describing images, mentions, and limits.

Reviewed by Cursor Bugbot for commit 4683aee. Bugbot is set up for automated code reviews on this repo. Configure here.

Dropping or pasting a non-image file into the composer previously failed
with "Unsupported file type ... Please attach image files only." Referencing
a file by dragging it into the prompt is a standard workflow in comparable
tools, so non-image files now become file mention chips instead:
- Drop: non-image files are partitioned away from the image-attachment flow
and inserted as mentions at the end of the prompt, workspace-relative when
the file lives inside the repo, absolute otherwise. Directories (empty MIME
type) work the same way. Mixed drops attach the images and mention the rest.
- Paste: the editor's paste command inserts mention chips at the cursor for
non-image clipboard files, leaving images to the existing attachment path.
- Desktop bridge: expose webUtils.getPathForFile as an optional
DesktopBridge.getPathForFile, since Electron >= 32 removed File.path and
the renderer cannot learn a dropped file's location otherwise. Browser
tabs have no OS path access and keep the previous behavior.
- Thread titles: seed titles now render file links as their basename instead
of raw "[name](path)" markup. This also fixes titles for existing
file-tree drag mentions.
No contract or server protocol changes: mentions are plain prompt text, so
remote environments and every provider handle them unchanged.
@coderabbitai

coderabbitaiBot commented Aug 6, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: e8ddd24d-8b9b-4807-b4ad-241c8ce581a7

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Comment threadapps/web/src/components/chat/composerFileDrop.ts
Backslash is a valid filename character on POSIX, so normalizing it to "/"
turned a dropped /repo/a\b.txt into a mention for a/b.txt, a different or
nonexistent file. Separator normalization (and the case-insensitive
compare) now applies only when both sides are Windows paths.
Comment threadapps/web/src/components/chat/composerFileDrop.ts
Comment threadapps/web/src/components/chat/composerFileDrop.ts Outdated
Two workspaceRelativeDropPath fixes:
- A POSIX workspace root of "/" trimmed to an empty string and bailed, so
files under a filesystem-root workspace were mentioned by absolute path.
The empty-root guard now checks the original input, and the separator
appended for the prefix check restores the trimmed root.
- The relative slice offset came from the lowercased comparable prefix,
whose length can differ from the original for some Unicode (e.g. "İ"
lowercases to two code points), truncating the result. Slice by the
original root's length instead, and require the boundary character to be
the separator so any residual misalignment falls back to the absolute
path rather than a wrong relative one.
@kristjaningi
kristjaningi marked this pull request as ready for review August 6, 2026 19:07

@chatgpt-codex-connectorchatgpt-codex-connectorBot left a comment

Copy link
Copy Markdown

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:ded9627d13

ℹ️ 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".

Comment threadapps/web/src/components/chat/composerFileDrop.ts
Comment threadapps/web/src/components/composerInlineTokenPaste.ts Outdated
In desktop WSL-only mode the WSL server occupies the primary backend slot,
so the connection-target gate passed while webUtils.getPathForFile returned
Windows host paths the Linux-side agent cannot read. Dropped files were
mentioned as C:/... paths pointing nowhere.
The resolver now also compares the resolved path's style against the
selected environment's platform.os and treats mismatches as unresolvable,
surfacing the existing per-environment error instead. Mismatches are
rejected rather than translated because WSL mount roots are configurable
and a guessed /mnt/c/... path would silently point at a nonexistent file.
A paste can land while a chip is node-selected, so $getSelection() is not a
range selection and $insertPastedFileMentions bailed without inserting.
Nothing downstream recovers: the default paste cannot turn files into
mentions and the composer's paste handler prevents it while only reporting
unresolvable files, so resolvable files vanished with no chip and no error.
Fall back to a range selection at the end of the prompt instead of bailing.
@macroscopeapp

macroscopeappBot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This PR adds a new feature (non-image file drop/paste to path mentions) with substantial new logic for cross-platform path resolution and desktop bridge integration. There is also an unresolved comment identifying a potential bug in error handling for mixed image/file drops.

You can customize Macroscope's approvability policy. Learn more.

@github-actionsgithub-actionsBot added the vouch:unvouched PR author is not yet trusted in the VOUCHED list. label Aug 6, 2026
@github-actionsgithub-actionsBot added the size:L 100-499 changed lines (additions + deletions). label Aug 8, 2026

@chatgpt-codex-connectorchatgpt-codex-connectorBot left a comment

Copy link
Copy Markdown

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:00bf04e0c2

ℹ️ 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".

Comment threadapps/web/src/components/chat/composerFileDrop.ts Outdated
Comment threadapps/web/src/components/composerInlineTokenPaste.ts
kdcokenny added a commit to kdcokenny/t3code that referenced this pull request Aug 8, 2026
Ported from pingdotgg#5543.
Co-authored-by: Kristján Ingi <k.geirsson@gmail.com>

@chatgpt-codex-connectorchatgpt-codex-connectorBot left a comment

Copy link
Copy Markdown

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:dcf162b71b

ℹ️ 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".

Comment threadapps/web/src/components/chat/ChatComposer.tsx

@chatgpt-codex-connectorchatgpt-codex-connectorBot left a comment

Copy link
Copy Markdown

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:61f56a001e

ℹ️ 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".

Comment threadapps/web/src/components/chat/composerFileDrop.ts
Comment threadapps/web/src/components/chat/ChatComposer.tsx
serializeComposerFileLink treated every backslash as a directory
separator, so a POSIX file named a\b.txt became a chip labeled b.txt.
Basename handling is now platform-aware, and token parsing still
accepts older Windows mentions that used a backslash as a separator.
addComposerImages clears the thread error on successful validation, so
writing the mention-unavailable message after it hid a real attachment
count error. Mixed drops now compose both messages in one write.
Non-image drops and pastes now insert path mentions on desktop, with
different fallbacks in the browser and on remote or WSL-only
environments. That is user-visible behavior and belongs in shipped docs.

@cursorcursorBot left a comment

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.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 4683aee. Configure here.

const addComposerImages = async (
files: File[],
options?: { fallbackThreadError?: string | null },
) => {

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.

Mention error dropped on plan prompts

Medium Severity

Moving unresolved-file errors into addComposerImages via fallbackThreadError skips that path when plan questions are pending. The helper returns early after the image toast and never applies the fallback, and paste/drop only call setThreadError in the no-images branch, so a mixed image plus unresolved file no longer surfaces the mention error.

Additional Locations (2)
Fix in CursorFix in Web

Reviewed by Cursor Bugbot for commit 4683aee. Configure here.

@chatgpt-codex-connectorchatgpt-codex-connectorBot left a comment

Copy link
Copy Markdown

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:4683aeefd0

ℹ️ 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".

Comment on lines +2332 to +2335
setThreadError(
threadId,
composeComposerFileDropThreadError(error, options?.fallbackThreadError ?? null),
);

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 Preserve mention errors after image compression fails

When a mixed paste/drop contains an unavailable non-image file—for example, in a browser or remote environment—and an image that passes initial validation but later fails compression, the mention error is combined only here; the later setThreadError(threadId, compressionError) overwrites it. The non-image file is therefore omitted without explanation, so retain or merge fallbackThreadError when reporting asynchronous compression failures as well.

AGENTS.md reference: AGENTS.md:L74-L74

Useful? React with 👍 / 👎.

@t3dotgg

Copy link
Copy Markdown
Member

Note

🤖 GPT-5.6 Sol responding on behalf of Theo

We're closing this PR as we clean up the T3 Code backlog. Thank you for taking the time to put this together.

#6203 keeps the useful drop and paste behavior in a much smaller patch. This branch also changes inline-token paste rules and thread-title seeds, and its extra folder support does not justify that added scope.

If you believe we closed this in error, please reopen the PR and leave a comment explaining what we missed.

@t3dotggt3dotgg closed this Aug 28, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L100-499 changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: Any non-image file attachment support

2 participants

@kristjaningi@t3dotgg
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

feat(web): insert path mentions for non-image file drops and pastes - #5543

Closed
kristjaningi wants to merge 12 commits into
pingdotgg:mainfrom
kristjaningi:feat/composer-file-drop-path-mentions
Closed

feat(web): insert path mentions for non-image file drops and pastes#5543
kristjaningi wants to merge 12 commits into
pingdotgg:mainfrom
kristjaningi:feat/composer-file-drop-path-mentions

Conversation

@kristjaningi

@kristjaningikristjaningi commented Aug 6, 2026

Copy link
Copy Markdown

What

Dropping or pasting a non-image file into the composer currently fails with "Unsupported file type ... Please attach image files only." This PR turns those files into file mention chips instead, so the agent can read them where they already live:

  • Drop: non-image files (and folders) become mentions - workspace-relative when inside the repo, absolute otherwise. Images keep the exact existing attachment flow; mixed drops attach the images and mention the rest.
  • Paste: non-image clipboard files become mention chips at the cursor.
  • Desktop bridge: exposes webUtils.getPathForFile as an optional DesktopBridge method (Electron >= 32 removed File.path). Browser tabs have no OS path access; they keep the image-only flow with a clearer error.
  • Path mentions are only offered when the selected environment is the primary same-host backend; SSH/relay/remote/WSL environments have different filesystems and get the same image-only error.
  • Bonus: thread title seeds now render file links as their basename instead of raw [name](path) markup (also fixes titles for existing file-tree drag mentions).

Why this shape

Mentions are plain prompt text, so there are zero contract or server protocol changes. I'm aware of the orchestration V2 rework (#2829) that closed#4058 - this deliberately stays out of that layer entirely, and follows @juliusmarminge's suggestion there to just provide the path where the agent can find the file. Complementary to the attachment work in #3927.

Fixes#2126

Before Screenshots ⛔

image

After Screenshots ✅

CleanShot 2026-08-06 at 18 52 48@2xCleanShot 2026-08-06 at 18 53 46@2xCleanShot 2026-08-06 at 18 54 24@2x

Verification

  • New pure-logic tests for the drop partition, path relativization, and title basenames; typecheck clean across web, desktop, contracts, and shared.
  • Manually tested in the desktop app - screenshots and video coming shortly.

Note

Insert path mentions for non-image file drops and pastes in the chat composer

  • Dropping or pasting non-image files into the chat composer now inserts file-mention chips (workspace-relative when inside the project, absolute otherwise) instead of plain text; images continue to be attached as before.
  • Adds composerFileDrop.ts with platform-aware path resolution, file partitioning, and error composition utilities used by ChatComposer.
  • Exposes getPathForFile on window.desktopBridge via preload.ts so the renderer can resolve on-disk paths for dropped files.
  • Thread titles seeded from prompts containing file-mention links now use basenames via replaceComposerFileLinksWithBasenames instead of raw markdown.
  • Risk: unresolvable non-image file pastes are consumed (no plain-text fallback) and show a thread error instead.

Macroscope summarized 4683aee.


Note

Low Risk
Composer UX and prompt text only; no server protocol changes. Path gating limits wrong-filesystem mentions; extensive unit tests cover edge cases.

Overview
Non-image OS files dropped or pasted into the chat composer become file path mention chips (workspace-relative when inside the project, absolute otherwise) instead of failing as unsupported attachments. Images still use the existing attachment flow; mixed clipboard/drops attach images and mention the rest.

The desktop bridge adds optional getPathForFile via Electron webUtils so the renderer can resolve dropped file paths. Mentions are only offered for the primary same-host environment, with Windows vs POSIX path-style checks (e.g. WSL-only) so bad paths are not sent to the agent; browser/remote/SSH cases keep image-only behavior with clearer thread errors.

Lexical paste handling inserts mention chips for pasted non-image files; drop handling partitions files and appends serialized link text. Shared token/serialization logic now treats POSIX filenames with backslashes correctly. New thread titles seed from basenames via replaceComposerFileLinksWithBasenames instead of raw [name](path) markup. User docs add a composer page describing images, mentions, and limits.

Reviewed by Cursor Bugbot for commit 4683aee. Bugbot is set up for automated code reviews on this repo. Configure here.

Dropping or pasting a non-image file into the composer previously failed
with "Unsupported file type ... Please attach image files only." Referencing
a file by dragging it into the prompt is a standard workflow in comparable
tools, so non-image files now become file mention chips instead:
- Drop: non-image files are partitioned away from the image-attachment flow
and inserted as mentions at the end of the prompt, workspace-relative when
the file lives inside the repo, absolute otherwise. Directories (empty MIME
type) work the same way. Mixed drops attach the images and mention the rest.
- Paste: the editor's paste command inserts mention chips at the cursor for
non-image clipboard files, leaving images to the existing attachment path.
- Desktop bridge: expose webUtils.getPathForFile as an optional
DesktopBridge.getPathForFile, since Electron >= 32 removed File.path and
the renderer cannot learn a dropped file's location otherwise. Browser
tabs have no OS path access and keep the previous behavior.
- Thread titles: seed titles now render file links as their basename instead
of raw "[name](path)" markup. This also fixes titles for existing
file-tree drag mentions.
No contract or server protocol changes: mentions are plain prompt text, so
remote environments and every provider handle them unchanged.
@coderabbitai

coderabbitaiBot commented Aug 6, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: e8ddd24d-8b9b-4807-b4ad-241c8ce581a7

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Comment threadapps/web/src/components/chat/composerFileDrop.ts
Backslash is a valid filename character on POSIX, so normalizing it to "/"
turned a dropped /repo/a\b.txt into a mention for a/b.txt, a different or
nonexistent file. Separator normalization (and the case-insensitive
compare) now applies only when both sides are Windows paths.
Comment threadapps/web/src/components/chat/composerFileDrop.ts
Comment threadapps/web/src/components/chat/composerFileDrop.ts Outdated
Two workspaceRelativeDropPath fixes:
- A POSIX workspace root of "/" trimmed to an empty string and bailed, so
files under a filesystem-root workspace were mentioned by absolute path.
The empty-root guard now checks the original input, and the separator
appended for the prefix check restores the trimmed root.
- The relative slice offset came from the lowercased comparable prefix,
whose length can differ from the original for some Unicode (e.g. "İ"
lowercases to two code points), truncating the result. Slice by the
original root's length instead, and require the boundary character to be
the separator so any residual misalignment falls back to the absolute
path rather than a wrong relative one.
@kristjaningi
kristjaningi marked this pull request as ready for review August 6, 2026 19:07

@chatgpt-codex-connectorchatgpt-codex-connectorBot left a comment

Copy link
Copy Markdown

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:ded9627d13

ℹ️ 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".

Comment threadapps/web/src/components/chat/composerFileDrop.ts
Comment threadapps/web/src/components/composerInlineTokenPaste.ts Outdated
In desktop WSL-only mode the WSL server occupies the primary backend slot,
so the connection-target gate passed while webUtils.getPathForFile returned
Windows host paths the Linux-side agent cannot read. Dropped files were
mentioned as C:/... paths pointing nowhere.
The resolver now also compares the resolved path's style against the
selected environment's platform.os and treats mismatches as unresolvable,
surfacing the existing per-environment error instead. Mismatches are
rejected rather than translated because WSL mount roots are configurable
and a guessed /mnt/c/... path would silently point at a nonexistent file.
A paste can land while a chip is node-selected, so $getSelection() is not a
range selection and $insertPastedFileMentions bailed without inserting.
Nothing downstream recovers: the default paste cannot turn files into
mentions and the composer's paste handler prevents it while only reporting
unresolvable files, so resolvable files vanished with no chip and no error.
Fall back to a range selection at the end of the prompt instead of bailing.
@macroscopeapp

macroscopeappBot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This PR adds a new feature (non-image file drop/paste to path mentions) with substantial new logic for cross-platform path resolution and desktop bridge integration. There is also an unresolved comment identifying a potential bug in error handling for mixed image/file drops.

You can customize Macroscope's approvability policy. Learn more.

@github-actionsgithub-actionsBot added the vouch:unvouched PR author is not yet trusted in the VOUCHED list. label Aug 6, 2026
@github-actionsgithub-actionsBot added the size:L 100-499 changed lines (additions + deletions). label Aug 8, 2026

@chatgpt-codex-connectorchatgpt-codex-connectorBot left a comment

Copy link
Copy Markdown

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:00bf04e0c2

ℹ️ 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".

Comment threadapps/web/src/components/chat/composerFileDrop.ts Outdated
Comment threadapps/web/src/components/composerInlineTokenPaste.ts
kdcokenny added a commit to kdcokenny/t3code that referenced this pull request Aug 8, 2026
Ported from pingdotgg#5543.
Co-authored-by: Kristján Ingi <k.geirsson@gmail.com>

@chatgpt-codex-connectorchatgpt-codex-connectorBot left a comment

Copy link
Copy Markdown

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:dcf162b71b

ℹ️ 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".

Comment threadapps/web/src/components/chat/ChatComposer.tsx

@chatgpt-codex-connectorchatgpt-codex-connectorBot left a comment

Copy link
Copy Markdown

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:61f56a001e

ℹ️ 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".

Comment threadapps/web/src/components/chat/composerFileDrop.ts
Comment threadapps/web/src/components/chat/ChatComposer.tsx
serializeComposerFileLink treated every backslash as a directory
separator, so a POSIX file named a\b.txt became a chip labeled b.txt.
Basename handling is now platform-aware, and token parsing still
accepts older Windows mentions that used a backslash as a separator.
addComposerImages clears the thread error on successful validation, so
writing the mention-unavailable message after it hid a real attachment
count error. Mixed drops now compose both messages in one write.
Non-image drops and pastes now insert path mentions on desktop, with
different fallbacks in the browser and on remote or WSL-only
environments. That is user-visible behavior and belongs in shipped docs.

@cursorcursorBot left a comment

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.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 4683aee. Configure here.

const addComposerImages = async (
files: File[],
options?: { fallbackThreadError?: string | null },
) => {

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.

Mention error dropped on plan prompts

Medium Severity

Moving unresolved-file errors into addComposerImages via fallbackThreadError skips that path when plan questions are pending. The helper returns early after the image toast and never applies the fallback, and paste/drop only call setThreadError in the no-images branch, so a mixed image plus unresolved file no longer surfaces the mention error.

Additional Locations (2)
Fix in CursorFix in Web

Reviewed by Cursor Bugbot for commit 4683aee. Configure here.

@chatgpt-codex-connectorchatgpt-codex-connectorBot left a comment

Copy link
Copy Markdown

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:4683aeefd0

ℹ️ 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".

Comment on lines +2332 to +2335
setThreadError(
threadId,
composeComposerFileDropThreadError(error, options?.fallbackThreadError ?? null),
);

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 Preserve mention errors after image compression fails

When a mixed paste/drop contains an unavailable non-image file—for example, in a browser or remote environment—and an image that passes initial validation but later fails compression, the mention error is combined only here; the later setThreadError(threadId, compressionError) overwrites it. The non-image file is therefore omitted without explanation, so retain or merge fallbackThreadError when reporting asynchronous compression failures as well.

AGENTS.md reference: AGENTS.md:L74-L74

Useful? React with 👍 / 👎.

@t3dotgg

Copy link
Copy Markdown
Member

Note

🤖 GPT-5.6 Sol responding on behalf of Theo

We're closing this PR as we clean up the T3 Code backlog. Thank you for taking the time to put this together.

#6203 keeps the useful drop and paste behavior in a much smaller patch. This branch also changes inline-token paste rules and thread-title seeds, and its extra folder support does not justify that added scope.

If you believe we closed this in error, please reopen the PR and leave a comment explaining what we missed.

@t3dotggt3dotgg closed this Aug 28, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L100-499 changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: Any non-image file attachment support

2 participants

@kristjaningi@t3dotgg