Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/platform/agentHost/common/agentHostUri.ts
13395 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import { encodeBase64, VSBuffer } from '../../../base/common/buffer.js';
7
import { Schemas } from '../../../base/common/network.js';
8
import { URI } from '../../../base/common/uri.js';
9
import type { ResourceLabelFormatter } from '../../label/common/label.js';
10
11
/**
12
* The URI scheme for accessing files on a remote agent host.
13
*
14
* URIs encode the original scheme, authority, and path so that any
15
* remote resource can be represented without assuming `file://`:
16
*
17
* ```
18
* vscode-agent-host://[connectionAuthority]/[originalScheme]/[originalAuthority]/[originalPath]
19
* ```
20
*
21
* For example, `file:///home/user/foo.ts` on remote `my-server` becomes:
22
* ```
23
* vscode-agent-host://my-server/file//home/user/foo.ts
24
* ```
25
*/
26
export const AGENT_HOST_SCHEME = 'vscode-agent-host';
27
28
/**
29
* Wraps a remote URI into a {@link AGENT_HOST_SCHEME} URI that can be
30
* resolved through the agent host filesystem provider.
31
*
32
* @param originalUri The URI on the remote (e.g. `file:///path` or
33
* `agenthost-content:///sessionId/...`)
34
* @param connectionAuthority The sanitized connection identifier used as
35
* the URI authority (from {@link agentHostAuthority}).
36
*/
37
export function toAgentHostUri(originalUri: URI, connectionAuthority: string): URI {
38
if (connectionAuthority === 'local' && originalUri.scheme === Schemas.file) {
39
return originalUri;
40
}
41
42
// Path format: /[originalScheme]/[originalAuthority]/[originalPath]
43
const originalAuthority = originalUri.authority || '';
44
return URI.from({
45
scheme: AGENT_HOST_SCHEME,
46
authority: connectionAuthority,
47
path: `/${originalUri.scheme}/${originalAuthority || '-'}${originalUri.path}`,
48
});
49
}
50
51
/**
52
* Extracts the original URI from a {@link AGENT_HOST_SCHEME} URI.
53
*
54
* The inverse of {@link toAgentHostUri}.
55
*/
56
export function fromAgentHostUri(agentHostUri: URI): URI {
57
// Path: /[originalScheme]/[originalAuthority]/[rest of original path]
58
const path = agentHostUri.path;
59
60
// Find first segment boundary after leading /
61
const schemeEnd = path.indexOf('/', 1);
62
if (schemeEnd === -1) {
63
// Malformed — treat whole path as file scheme
64
return URI.from({ scheme: 'file', path });
65
}
66
67
const originalScheme = path.substring(1, schemeEnd);
68
69
// Find second segment boundary (authority/path split)
70
const authorityEnd = path.indexOf('/', schemeEnd + 1);
71
if (authorityEnd === -1) {
72
// No path after authority
73
const originalAuthority = path.substring(schemeEnd + 1);
74
return URI.from({ scheme: originalScheme, authority: originalAuthority, path: '/' });
75
}
76
77
let originalAuthority = path.substring(schemeEnd + 1, authorityEnd);
78
if (originalAuthority === '-') {
79
originalAuthority = '';
80
}
81
82
const originalPath = path.substring(authorityEnd);
83
84
return URI.from({
85
scheme: originalScheme,
86
authority: originalAuthority || undefined,
87
path: originalPath,
88
});
89
}
90
91
/**
92
* Strips the redundant `ws://` scheme from an address. The transport layer
93
* already defaults to `ws://`, so only `wss://` needs to be preserved.
94
*/
95
export function normalizeRemoteAgentHostAddress(address: string): string {
96
if (address.startsWith('ws://')) {
97
return address.slice('ws://'.length);
98
}
99
return address;
100
}
101
102
/**
103
* Encode a remote address into an identifier that is safe for use in
104
* both URI schemes and URI authorities, and is collision-free.
105
*
106
* Three tiers:
107
* 1. Purely alphanumeric addresses are returned as-is.
108
* 2. "Normal" addresses containing only `[a-zA-Z0-9.:-]` get colons
109
* replaced with `__` (double underscore) for human readability.
110
* Addresses containing `_` skip this tier to keep the encoding
111
* collision-free (`__` can only appear from colon replacement).
112
* 3. Everything else is url-safe base64-encoded with a `b64-` prefix.
113
*/
114
export function agentHostAuthority(address: string): string {
115
const normalized = normalizeRemoteAgentHostAddress(address);
116
if (/^[a-zA-Z0-9]+$/.test(normalized)) {
117
return normalized;
118
}
119
if (/^[a-zA-Z0-9.:\-]+$/.test(normalized)) {
120
return normalized.replaceAll(':', '__');
121
}
122
return 'b64-' + encodeBase64(VSBuffer.fromString(normalized), false, true);
123
}
124
125
/**
126
* Label formatter for {@link AGENT_HOST_SCHEME} URIs. Strips the two
127
* leading path segments (`/scheme/authority`) to display the original
128
* file path.
129
*/
130
export const AGENT_HOST_LABEL_FORMATTER: ResourceLabelFormatter = {
131
scheme: AGENT_HOST_SCHEME,
132
formatting: {
133
label: '${path}',
134
separator: '/',
135
stripPathSegments: 2,
136
},
137
};
138
139