fix(native-chat): resolve /D:/ chat file links to the drive in Windows workspaces (#34367)

In a drive-letter workspace, strip the leading slash from URL-style
/X:/ file hrefs before resolving, so links like /D:/Temp/report.txt
open D:/Temp/report.txt. POSIX, WSL UNC, and UNC hrefs are unchanged.

Fixes #34310
This commit is contained in:
BingZ
2026-10-27 09:48:32 -07:00
committed by GitHub
parent 1aada40c24
commit efd0a09f69
3 changed files with 42 additions and 3 deletions
@@ -299,4 +299,25 @@ describe('resolveNativeChatFileLink', () => {
it('ignores http links so normal markdown navigation can handle them', () => {
expect(resolveNativeChatFileLink('https://example.com/docs/guide.md', context)).toBeNull()
})
it('reads URL-style /D:/ targets as the drive only in a Windows workspace', () => {
const windowsContext = { ...context, worktreePath: 'D:/repo' }
for (const href of ['/D:/Temp/report.txt', createNativeChatFileHref('/D:/Temp/report.txt')]) {
expect(resolveNativeChatFileLink(href, windowsContext)?.absolutePath).toBe(
'D:/Temp/report.txt'
)
}
expect(
resolveNativeChatFileLink(
createNativeChatFileHref('/D:/Temp/report.txt', 'literal'),
windowsContext
)?.absolutePath
).toBe('D:/Temp/report.txt')
expect(
resolveNativeChatFileLink('//server/share/report.txt', windowsContext)?.absolutePath
).toBe('//server/share/report.txt')
expect(resolveNativeChatFileLink('/D:/Temp/report.txt', context)?.absolutePath).toBe(
'/D:/Temp/report.txt'
)
})
})
@@ -1,5 +1,10 @@
import { chatWorkspaceByTabId } from '@/lib/structured-chat-tab-index'
import { routeNativeChatHref } from '../../../../shared/native-chat-href-routing'
import {
routeNativeChatHref,
type NativeChatHrefRoute
} from '../../../../shared/native-chat-href-routing'
import { WINDOWS_DRIVE_PATH_PREFIX } from '../../../../shared/file-uri-path'
import { normalizeAbsolutePath } from '../../../../shared/terminal-path-normalization'
import {
parseExplicitFileLinkTarget,
resolveExplicitFileLinkTarget,
@@ -130,6 +135,19 @@ function resolvePathText(
}
}
// Chats open a drive-letter workspace as native Windows (no WSL mapping), so URL-style /D:/… there is D:.
function routeNativeChatFileHref(
href: string | undefined,
worktreePath: string
): NativeChatHrefRoute {
const route = routeNativeChatHref(href)
return route.kind === 'file' &&
WINDOWS_DRIVE_PATH_PREFIX.test(route.pathText) &&
normalizeAbsolutePath(worktreePath)?.rootKind === 'windows'
? { ...route, pathText: route.pathText.slice(1) }
: route
}
export function resolveNativeChatFileLink(
href: string | undefined,
context: NativeChatFileLinkContext | null
@@ -137,7 +155,7 @@ export function resolveNativeChatFileLink(
if (!context) {
return null
}
const route = routeNativeChatHref(href)
const route = routeNativeChatFileHref(href, context.worktreePath)
if (route.kind !== 'file') {
return null
}
+1 -1
View File
@@ -1,4 +1,4 @@
const WINDOWS_DRIVE_PATH_PREFIX = /^\/[A-Za-z]:\//
export const WINDOWS_DRIVE_PATH_PREFIX = /^\/[A-Za-z]:\//
const UNC_PATH_PREFIX = /^(?:\\\\|\/\/)([^\\/]+)[\\/]+([^\\/]+)(?:[\\/](.*))?$/
function encodePathSegments(path: string): string {