Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/platform/agentHost/common/tunnelAgentHost.ts
13394 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 { Event } from '../../../base/common/event.js';
7
import { createDecorator } from '../../instantiation/common/instantiation.js';
8
import type { IAgentHostSocketInfo } from './agentService.js';
9
10
export const ITunnelAgentHostService = createDecorator<ITunnelAgentHostService>('tunnelAgentHostService');
11
12
/**
13
* IPC channel name for the shared-process tunnel service.
14
*/
15
export const TUNNEL_AGENT_HOST_CHANNEL = 'tunnelAgentHost';
16
17
/** Configuration key for the list of manually configured tunnel names. */
18
export const TunnelAgentHostsSettingId = 'chat.remoteAgentTunnels';
19
20
/** Minimum protocol version required for agent host connections. */
21
export const TUNNEL_MIN_PROTOCOL_VERSION = 5;
22
23
/** Well-known port for the agent host on tunnel machines. */
24
export const TUNNEL_AGENT_HOST_PORT = 31546;
25
26
/** Label used to identify VS Code server launcher tunnels. */
27
export const TUNNEL_LAUNCHER_LABEL = 'vscode-server-launcher';
28
29
/** Address prefix for tunnel-backed connections (e.g. `tunnel:myTunnelId`). */
30
export const TUNNEL_ADDRESS_PREFIX = 'tunnel:';
31
32
/** Prefix for protocol version tags. */
33
export const PROTOCOL_VERSION_TAG_PREFIX = 'protocolv';
34
35
/**
36
* Parse tunnel tags to extract display name and protocol version.
37
* Follows the convention from the vscode-remote-tunnels SDK: the
38
* first label that is not `vscode-server-launcher`, does not start
39
* with `_`, and is not a `protocolvN` tag is the display name.
40
*/
41
export class TunnelTags {
42
public readonly protocolVersion: number = 2;
43
public readonly name: string | undefined;
44
45
constructor(readonly value: readonly string[] | undefined) {
46
if (value) {
47
let protocolVersion: number | undefined;
48
let name: string | undefined;
49
for (const tag of value) {
50
if (tag.startsWith(PROTOCOL_VERSION_TAG_PREFIX)) {
51
const parsed = Number(tag.slice(PROTOCOL_VERSION_TAG_PREFIX.length));
52
if (!isNaN(parsed)) {
53
protocolVersion = parsed;
54
}
55
} else if (!tag.startsWith('_') && tag !== TUNNEL_LAUNCHER_LABEL && !name) {
56
name = tag;
57
}
58
}
59
if (protocolVersion !== undefined) {
60
this.protocolVersion = protocolVersion;
61
}
62
if (name !== undefined) {
63
this.name = name;
64
}
65
}
66
}
67
}
68
69
/** A recently used tunnel cached in storage. */
70
export interface ICachedTunnel {
71
readonly tunnelId: string;
72
readonly clusterId: string;
73
readonly name: string;
74
readonly authProvider?: 'github' | 'microsoft';
75
}
76
77
/** Information about a discovered dev tunnel with an agent host. */
78
export interface ITunnelInfo {
79
/** The tunnel's unique identifier. */
80
readonly tunnelId: string;
81
/** The cluster region where the tunnel is hosted. */
82
readonly clusterId: string;
83
/** Display name derived from tunnel tags or tunnel name. */
84
readonly name: string;
85
/** All tags/labels on the tunnel. */
86
readonly tags: readonly string[];
87
/** Parsed protocol version from tags. */
88
readonly protocolVersion: number;
89
/** Number of hosts currently accepting connections (0 = offline). */
90
readonly hostConnectionCount: number;
91
}
92
93
/**
94
* Serializable result from a successful tunnel connect operation.
95
* Returned over IPC from the shared process.
96
*/
97
export interface ITunnelConnectResult {
98
/** Unique identifier for this connection's relay channel. */
99
readonly connectionId: string;
100
/** Display-friendly address (e.g. "tunnel:myTunnel"). */
101
readonly address: string;
102
/** Display name for the tunnel. */
103
readonly name: string;
104
/** Connection token derived from the tunnel ID. */
105
readonly connectionToken: string;
106
}
107
108
/**
109
* A message relayed from a remote agent host through the tunnel.
110
* The shared process acts as a WebSocket proxy, forwarding JSON
111
* messages bidirectionally between the tunnel and the renderer via IPC.
112
*/
113
export interface ITunnelRelayMessage {
114
readonly connectionId: string;
115
readonly data: string;
116
}
117
118
/**
119
* Main-process (shared process) service that manages dev tunnel
120
* connections. The renderer calls this over IPC and handles registration
121
* with {@link IRemoteAgentHostService} locally.
122
*/
123
export const ITunnelAgentHostMainService = createDecorator<ITunnelAgentHostMainService>('tunnelAgentHostMainService');
124
125
export interface ITunnelAgentHostMainService {
126
readonly _serviceBrand: undefined;
127
128
/** Fires when a message is received from a remote agent host via the tunnel relay. */
129
readonly onDidRelayMessage: Event<ITunnelRelayMessage>;
130
131
/** Fires when a relay connection to a remote agent host closes. */
132
readonly onDidRelayClose: Event<string /* connectionId */>;
133
134
/**
135
* List dev tunnels associated with the user's account that have
136
* the `vscode-server-launcher` label and a protocol version tag
137
* of at least {@link TUNNEL_MIN_PROTOCOL_VERSION}.
138
*
139
* @param token The user's access token (GitHub or Microsoft).
140
* @param authProvider The auth provider that issued the token.
141
* @param additionalTunnelNames Optional tunnel names to look up
142
* in addition to the account-wide enumeration.
143
*/
144
listTunnels(token: string, authProvider: 'github' | 'microsoft', additionalTunnelNames?: string[]): Promise<ITunnelInfo[]>;
145
146
/**
147
* Connect to a tunnel's agent host via the dev tunnels relay and
148
* begin relaying WebSocket messages through IPC.
149
*
150
* @param token The user's access token (GitHub or Microsoft).
151
* @param authProvider The auth provider that issued the token.
152
* @param tunnelId The tunnel ID to connect to.
153
* @param clusterId The cluster region of the tunnel.
154
*/
155
connect(token: string, authProvider: 'github' | 'microsoft', tunnelId: string, clusterId: string): Promise<ITunnelConnectResult>;
156
157
/**
158
* Send a message to a remote agent host through the tunnel relay.
159
*/
160
relaySend(connectionId: string, message: string): Promise<void>;
161
162
/**
163
* Disconnect a tunnel relay connection.
164
*/
165
disconnect(connectionId: string): Promise<void>;
166
}
167
168
/**
169
* Renderer-side service that manages dev tunnel agent host connections.
170
* Uses the shared-process {@link ITunnelAgentHostMainService} for
171
* actual tunnel SDK operations and registers connections with
172
* {@link IRemoteAgentHostService}.
173
*/
174
export interface ITunnelAgentHostService {
175
readonly _serviceBrand: undefined;
176
177
/** Fires when the set of available tunnels changes. */
178
readonly onDidChangeTunnels: Event<void>;
179
180
/**
181
* Enumerate available dev tunnels with agent host support.
182
* When {@link options.silent} is `true`, uses cached tokens without
183
* prompting the user. Returns an empty array if no cached token.
184
*/
185
listTunnels(options?: { silent?: boolean }): Promise<ITunnelInfo[]>;
186
187
/**
188
* Connect to a tunnel's agent host and register the connection
189
* with {@link IRemoteAgentHostService}.
190
*
191
* @param tunnel The tunnel to connect to.
192
* @param authProvider Optional auth provider to use. If omitted, uses cached/last known.
193
*/
194
connect(tunnel: ITunnelInfo, authProvider?: 'github' | 'microsoft'): Promise<void>;
195
196
/**
197
* Disconnect from a tunnel agent host.
198
*/
199
disconnect(address: string): Promise<void>;
200
201
/** Get the list of recently used (cached) tunnels. */
202
getCachedTunnels(): ICachedTunnel[];
203
204
/** Cache a tunnel as recently used. */
205
cacheTunnel(tunnel: ITunnelInfo, authProvider?: 'github' | 'microsoft'): void;
206
207
/** Remove a tunnel from the cache. */
208
removeCachedTunnel(tunnelId: string): void;
209
210
/**
211
* Determine which auth provider has an existing cached session.
212
* When {@link silent} is true, does not prompt the user.
213
* Returns `undefined` if no cached session is available.
214
*/
215
getAuthProvider(options?: { silent?: boolean }): Promise<'github' | 'microsoft' | undefined>;
216
}
217
218
// ---- Tunnel hosting (exposing the local agent host to remote clients) --------
219
220
/** IPC channel name for the tunnel host service. */
221
export const TUNNEL_HOST_CHANNEL = 'tunnelHost';
222
223
/** Output channel ID for the tunnel host logs. */
224
export const TUNNEL_HOST_LOG_ID = 'tunnelHostService';
225
226
/** Information about an actively hosted tunnel. */
227
export interface ITunnelHostInfo {
228
readonly tunnelName: string;
229
readonly tunnelId: string;
230
readonly clusterId: string;
231
readonly domain: string;
232
}
233
234
/** Status of the tunnel host. */
235
export type TunnelHostStatus =
236
| { readonly active: false }
237
| { readonly active: true; readonly info: ITunnelHostInfo };
238
239
/**
240
* Shared-process service that hosts a dev tunnel using `TunnelRelayTunnelHost`
241
* and pipes incoming connections to the local agent host.
242
*/
243
export const ITunnelAgentHostHostingService = createDecorator<ITunnelAgentHostHostingService>('tunnelAgentHostHostingService');
244
245
export interface ITunnelAgentHostHostingService {
246
readonly _serviceBrand: undefined;
247
248
/** Fires when the hosting status changes. */
249
readonly onDidChangeStatus: Event<TunnelHostStatus>;
250
251
/**
252
* Start hosting a dev tunnel that forwards connections to the local
253
* agent host. Creates a tunnel with the appropriate labels and port
254
* configuration, then connects a `TunnelRelayTunnelHost`.
255
*
256
* @param token The user's access token.
257
* @param authProvider The auth provider that issued the token.
258
* @param socketInfo Socket path for the local agent host.
259
*/
260
startHosting(token: string, authProvider: 'github' | 'microsoft', socketInfo: IAgentHostSocketInfo): Promise<ITunnelHostInfo>;
261
262
/** Stop hosting and clean up the tunnel. */
263
stopHosting(): Promise<void>;
264
265
/** Get the current hosting status. */
266
getStatus(): Promise<TunnelHostStatus>;
267
}
268
269