mirror of
https://github.com/microsoft/vscode.git
synced 2026-09-29 17:07:50 +08:00
Avoid dash placeholder in agent host URIs
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -260,7 +260,7 @@ export abstract class AHPFileSystemProvider extends Disposable implements IFileS
|
||||
* client side. Registered under the `vscode-agent-host` scheme.
|
||||
*
|
||||
* ```
|
||||
* vscode-agent-host://[connectionAuthority]/[originalScheme]/[originalAuthority]/[originalPath]
|
||||
* vscode-agent-host://[connectionAuthority]/[originalScheme]/[originalAuthority][originalPath]
|
||||
* ```
|
||||
*/
|
||||
export class AgentHostFileSystemProvider extends AHPFileSystemProvider {
|
||||
|
||||
@@ -15,7 +15,7 @@ import type { ResourceLabelFormatter } from '../../label/common/label.js';
|
||||
* remote resource can be represented without assuming `file://`:
|
||||
*
|
||||
* ```
|
||||
* vscode-agent-host://[connectionAuthority]/[originalScheme]/[originalAuthority]/[originalPath]
|
||||
* vscode-agent-host://[connectionAuthority]/[originalScheme]/[originalAuthority][originalPath]
|
||||
* ```
|
||||
*
|
||||
* For example, `file:///home/user/foo.ts` on remote `my-server` becomes:
|
||||
@@ -39,12 +39,12 @@ export function toAgentHostUri(originalUri: URI, connectionAuthority: string): U
|
||||
return originalUri;
|
||||
}
|
||||
|
||||
// Path format: /[originalScheme]/[originalAuthority]/[originalPath]
|
||||
// Path format: /[originalScheme]/[originalAuthority][originalPath]
|
||||
const originalAuthority = originalUri.authority || '';
|
||||
return URI.from({
|
||||
scheme: AGENT_HOST_SCHEME,
|
||||
authority: connectionAuthority,
|
||||
path: `/${originalUri.scheme}/${originalAuthority || '-'}${originalUri.path}`,
|
||||
path: `/${originalUri.scheme}/${originalAuthority}${originalUri.path}`,
|
||||
query: originalUri.query,
|
||||
fragment: originalUri.fragment,
|
||||
});
|
||||
@@ -60,7 +60,7 @@ export function fromAgentHostUri(agentHostUri: URI): URI {
|
||||
return agentHostUri;
|
||||
}
|
||||
|
||||
// Path: /[originalScheme]/[originalAuthority]/[rest of original path]
|
||||
// Path: /[originalScheme]/[originalAuthority][rest of original path]
|
||||
const path = agentHostUri.path;
|
||||
|
||||
// Find first segment boundary after leading /
|
||||
|
||||
@@ -124,7 +124,7 @@ suite('toAgentHostUri / fromAgentHostUri', () => {
|
||||
test('round-trips query and fragment for synthetic content URIs', () => {
|
||||
const original = URI.from({
|
||||
scheme: 'git-blob',
|
||||
path: '/src/app.ts',
|
||||
path: '/hello_count.txt',
|
||||
query: JSON.stringify({ sessionUri: 'copilot:/abc', sha: 'cafe1234' }),
|
||||
fragment: 'L1',
|
||||
});
|
||||
@@ -143,6 +143,34 @@ suite('toAgentHostUri / fromAgentHostUri', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('wraps empty original authority without a dash placeholder', () => {
|
||||
const original = URI.from({ scheme: 'git-blob', path: '/hello_count.txt', query: JSON.stringify({ sessionUri: 'copilot:/abc', sha: 'cafe1234' }) });
|
||||
const wrapped = toAgentHostUri(original, 'local');
|
||||
|
||||
assert.deepStrictEqual({
|
||||
path: wrapped.path,
|
||||
unwrapped: fromAgentHostUri(wrapped).toString(),
|
||||
}, {
|
||||
path: '/git-blob//hello_count.txt',
|
||||
unwrapped: original.toString(),
|
||||
});
|
||||
});
|
||||
|
||||
test('unwraps legacy dash placeholder for empty original authority', () => {
|
||||
const legacy = URI.from({
|
||||
scheme: AGENT_HOST_SCHEME,
|
||||
authority: 'local',
|
||||
path: '/git-blob/-/hello_count.txt',
|
||||
query: JSON.stringify({ sessionUri: 'copilot:/abc', sha: 'cafe1234' }),
|
||||
});
|
||||
|
||||
assert.strictEqual(fromAgentHostUri(legacy).toString(), URI.from({
|
||||
scheme: 'git-blob',
|
||||
path: '/hello_count.txt',
|
||||
query: legacy.query,
|
||||
}).toString());
|
||||
});
|
||||
|
||||
test('local authority returns original URI unchanged', () => {
|
||||
const original = URI.file('/workspace/test.ts');
|
||||
const result = toAgentHostUri(original, 'local');
|
||||
@@ -204,16 +232,16 @@ suite('AGENT_HOST_LABEL_FORMATTER', () => {
|
||||
assert.strictEqual(stripped, '/snap/before');
|
||||
});
|
||||
|
||||
test('stripPathSegments preserves label-friendly git-blob paths', () => {
|
||||
test('stripPathSegments preserves label-friendly root git-blob paths', () => {
|
||||
const originalUri = URI.from({
|
||||
scheme: 'git-blob',
|
||||
path: '/src/app.ts',
|
||||
path: '/hello_count.txt',
|
||||
query: JSON.stringify({ sessionUri: 'copilot:/abc', sha: 'cafe1234' }),
|
||||
});
|
||||
const encodedUri = toAgentHostUri(originalUri, 'remote-host');
|
||||
const encodedUri = toAgentHostUri(originalUri, 'local');
|
||||
|
||||
const stripped = stripPath(encodedUri.path, AGENT_HOST_LABEL_FORMATTER.formatting.stripPathSegments!);
|
||||
assert.strictEqual(stripped, '/src/app.ts');
|
||||
assert.deepStrictEqual({ path: encodedUri.path, stripped }, { path: '/git-blob//hello_count.txt', stripped: '/hello_count.txt' });
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -85,7 +85,7 @@ suite('SimpleFileDialog - scoped path prefix', () => {
|
||||
const displayPath = labelFormatterDisplay(uri.path, AGENT_HOST_LABEL_FORMATTER.formatting.stripPathSegments!);
|
||||
const prefix = computeScopedPathPrefix(uri, displayPath);
|
||||
|
||||
assert.strictEqual(prefix, '/file/-');
|
||||
assert.strictEqual(prefix, '/file/');
|
||||
assert.strictEqual(displayPath, '/Users/roblou/code');
|
||||
});
|
||||
|
||||
@@ -115,7 +115,7 @@ suite('SimpleFileDialog - scoped path prefix', () => {
|
||||
test('pathFromUri strips prefix to show clean path', () => {
|
||||
const authority = agentHostAuthority('localhost:8089');
|
||||
const uri = agentHostUri(authority, '/Users/roblou/code');
|
||||
const prefix = '/file/-';
|
||||
const prefix = '/file/';
|
||||
|
||||
assert.strictEqual(pathFromUri(uri, prefix), '/Users/roblou/code');
|
||||
});
|
||||
@@ -123,7 +123,7 @@ suite('SimpleFileDialog - scoped path prefix', () => {
|
||||
test('pathFromUri with trailing separator', () => {
|
||||
const authority = agentHostAuthority('localhost:8089');
|
||||
const uri = agentHostUri(authority, '/Users/roblou/code');
|
||||
const prefix = '/file/-';
|
||||
const prefix = '/file/';
|
||||
|
||||
assert.strictEqual(pathFromUri(uri, prefix, true), '/Users/roblou/code/');
|
||||
});
|
||||
@@ -135,14 +135,14 @@ suite('SimpleFileDialog - scoped path prefix', () => {
|
||||
|
||||
test('remoteUriFrom re-adds prefix to reconstruct encoded URI', () => {
|
||||
const authority = agentHostAuthority('localhost:8089');
|
||||
const prefix = '/file/-';
|
||||
const prefix = '/file/';
|
||||
const cleanPath = '/Users/roblou/code';
|
||||
|
||||
const result = remoteUriFrom(cleanPath, AGENT_HOST_SCHEME, authority, prefix);
|
||||
|
||||
assert.strictEqual(result.scheme, AGENT_HOST_SCHEME);
|
||||
assert.strictEqual(result.authority, authority);
|
||||
assert.strictEqual(result.path, '/file/-/Users/roblou/code');
|
||||
assert.strictEqual(result.path, '/file//Users/roblou/code');
|
||||
});
|
||||
|
||||
test('full round-trip: URI -> pathFromUri -> remoteUriFrom -> same URI', () => {
|
||||
@@ -167,7 +167,7 @@ suite('SimpleFileDialog - scoped path prefix', () => {
|
||||
|
||||
test('createBackItem root detection with prefix', () => {
|
||||
const authority = agentHostAuthority('localhost:8089');
|
||||
const prefix = '/file/-';
|
||||
const prefix = '/file/';
|
||||
|
||||
// Simulate root folder: path = prefix + '/'
|
||||
const rootUri = URI.from({ scheme: AGENT_HOST_SCHEME, authority, path: prefix + '/' });
|
||||
|
||||
Reference in New Issue
Block a user