mirror of
https://github.com/microsoft/vscode.git
synced 2026-07-11 17:18:13 +01:00
address Copilot review: auth-pending unstick, upstream cache eviction, spawn-port bridge fallback, resolver mutex
This commit is contained in:
@@ -159,6 +159,21 @@ export function activate(context: vscode.ExtensionContext) {
|
||||
commandArgs.push('--connection-token', connectionToken);
|
||||
|
||||
const agentHostPort = getConfiguration('agentHostPort');
|
||||
const agentHostBridgePort = getConfiguration('agentHostBridgePort');
|
||||
if (
|
||||
typeof agentHostPort === 'number' && agentHostPort > 0 &&
|
||||
typeof agentHostBridgePort === 'number' && agentHostBridgePort > 0
|
||||
) {
|
||||
// `agentHostPort` spawns an agent host inside the server;
|
||||
// `agentHostBridgePort` bridges the renderer to an
|
||||
// externally-running one. They contradict each other —
|
||||
// reject up front so the user notices instead of getting
|
||||
// two agent hosts and silently confusing failure modes.
|
||||
throw new Error(
|
||||
`testResolver: 'agentHostPort' and 'agentHostBridgePort' are mutually exclusive. ` +
|
||||
`Configure at most one (got port=${agentHostPort}, bridge=${agentHostBridgePort}).`
|
||||
);
|
||||
}
|
||||
if (typeof agentHostPort === 'number' && agentHostPort > 0) {
|
||||
commandArgs.push('--agent-host-port', String(agentHostPort));
|
||||
}
|
||||
@@ -166,7 +181,6 @@ export function activate(context: vscode.ExtensionContext) {
|
||||
// Bridge to an externally-running agent host (e.g. one started
|
||||
// by `code agent host`). Mutually exclusive with `agentHostPort`
|
||||
// — that one spawns its own agent host.
|
||||
const agentHostBridgePort = getConfiguration('agentHostBridgePort');
|
||||
if (typeof agentHostBridgePort === 'number' && agentHostBridgePort > 0) {
|
||||
commandArgs.push('--agent-host-bridge-port', String(agentHostBridgePort));
|
||||
}
|
||||
|
||||
@@ -256,6 +256,16 @@ export class AgentHostChannel<TContext> extends Disposable implements IServerCha
|
||||
if (!conn) {
|
||||
conn = this._upstreamFactory(this._endpoint);
|
||||
this._perCtx.set(ctx, conn);
|
||||
// If the upstream closes on its own (e.g. agent host restart or
|
||||
// connection drop), evict it from the cache so the next
|
||||
// `connect()` call creates a fresh upstream rather than
|
||||
// returning the stuck-closed one.
|
||||
const sub = conn.onClose(() => {
|
||||
sub.dispose();
|
||||
if (this._perCtx.get(ctx) === conn) {
|
||||
this._perCtx.delete(ctx);
|
||||
}
|
||||
});
|
||||
}
|
||||
return conn;
|
||||
}
|
||||
|
||||
@@ -270,17 +270,25 @@ export async function setupServerServices(connectionToken: ServerConnectionToken
|
||||
disposables.add(instantiationService.createInstance(ServerAgentHostManager, agentHostStarter));
|
||||
}
|
||||
|
||||
// The bridge requires an explicit upstream — we do NOT fall back to
|
||||
// the spawn port. When `--agent-host-port=0` is used the OS picks a
|
||||
// port at runtime that this server has no way of learning; in the
|
||||
// `code tunnel` flow the CLI captures that port from the AH's
|
||||
// readiness line and passes it back as `--agent-host-bridge-port` on
|
||||
// the renderer-serving servers. The manager-spawned AH itself never
|
||||
// serves renderer connections directly, so it doesn't need a bridge.
|
||||
const bridgePort = args['agent-host-bridge-port'];
|
||||
const bridgePath = args['agent-host-bridge-path'];
|
||||
// The bridge upstream defaults to the agent host this server just
|
||||
// spawned, but ONLY when that endpoint is dialable at configuration
|
||||
// time — i.e. an explicit non-zero port or a socket path. When
|
||||
// `--agent-host-port=0` is used the OS picks a port at runtime that
|
||||
// this server has no way of learning, so we refuse to register a
|
||||
// bridge against a placeholder `0`; in that case the caller (the CLI
|
||||
// `code tunnel` flow) is expected to capture the bound port from the
|
||||
// AH's readiness line and pass it back as `--agent-host-bridge-port`
|
||||
// on the renderer-serving servers. Explicit `--agent-host-bridge-*`
|
||||
// always wins over the spawn fallback.
|
||||
const spawnPortNumber = spawnPort ? parseInt(spawnPort, 10) : NaN;
|
||||
const hasUsableSpawnPort = Number.isFinite(spawnPortNumber) && spawnPortNumber > 0;
|
||||
const bridgePort = args['agent-host-bridge-port'] ?? (hasUsableSpawnPort ? spawnPort : undefined);
|
||||
const bridgePath = args['agent-host-bridge-path'] ?? spawnPath;
|
||||
const bridgeHost = args['agent-host-bridge-host'] ?? args.host ?? 'localhost';
|
||||
const bridgeToken = args['agent-host-bridge-connection-token'];
|
||||
const bridgeToken = args['agent-host-bridge-connection-token']
|
||||
?? ((bridgePort || bridgePath) && spawnAgentHost && connectionToken.type === ServerConnectionTokenType.Mandatory
|
||||
? connectionToken.value
|
||||
: undefined);
|
||||
if (bridgePort || bridgePath) {
|
||||
const agentHostBridge = disposables.add(new AgentHostChannel<RemoteAgentConnectionContext>(
|
||||
socketServer,
|
||||
|
||||
@@ -67,10 +67,12 @@ export class EditorRemoteAgentHostServiceClient extends Disposable implements IA
|
||||
|
||||
if (!enabled) {
|
||||
this._logService.info(`${LOG_PREFIX} Disabled via "${AgentHostEnabledSettingId}". Not connecting.`);
|
||||
this.setAuthenticationPending(false);
|
||||
return;
|
||||
}
|
||||
if (!connection) {
|
||||
this._logService.warn(`${LOG_PREFIX} No remote agent connection available. Not connecting.`);
|
||||
this.setAuthenticationPending(false);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user