Skip to content

Commit d487453

Browse files
stephentoubCopilot
andcommitted
Serve /copilot_internal/user before proxy init guard
The CLI authenticates and calls /copilot_internal/user at startup, which can race ahead of the per-test POST /config. The Go e2e harness spawns the CLI (ctx.NewClient) at the parent-test level, before any subtest's ConfigureForTest posts /config, so the user call reached the proxy while state was still nil and hit the 'not yet initialized' guard. That blocked the CLI's MCP enablement check and caused the macOS MCP e2e subtests to time out at 60s. Move the /copilot_internal/user read handler above the state guard, mirroring its write-side counterpart (/copilot-user-config). The handler only depends on the copilotUserByToken map, which is populated at NewTestContext independently of state, so this is safe and consistent. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 9d696d2 commit d487453

1 file changed

Lines changed: 33 additions & 28 deletions

File tree

test/harness/replayingCapiProxy.ts

Lines changed: 33 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -241,34 +241,12 @@ export class ReplayingCapiProxy extends CapturingHttpProxy {
241241
return;
242242
}
243243

244-
const state = this.state;
245-
if (!state) {
246-
throw new Error(
247-
"ReplayingCapiProxy not yet initialized. Either pass filePath and workDir to the constructor, " +
248-
"or post configuration to /config before making other HTTP requests.",
249-
);
250-
}
251-
252-
// Handle /models endpoint
253-
// Use stored models if available, otherwise use default model
254-
if (options.requestOptions.path === "/models") {
255-
const models =
256-
state.storedData?.models && state.storedData.models.length > 0
257-
? state.storedData.models
258-
: [defaultModel];
259-
const modelsResponse = createGetModelsResponse(models);
260-
const body = JSON.stringify(modelsResponse);
261-
const headers = {
262-
"content-type": "application/json",
263-
...commonResponseHeaders,
264-
};
265-
options.onResponseStart(200, headers);
266-
options.onData(Buffer.from(body));
267-
options.onResponseEnd();
268-
return;
269-
}
270-
271-
// Handle /copilot_internal/user endpoint for per-session auth
244+
// Handle /copilot_internal/user endpoint for per-session auth.
245+
// This must run before the state guard below: the CLI authenticates and
246+
// calls /copilot_internal/user at startup, which can race ahead of the
247+
// per-test POST /config (e.g. the Go harness spawns the CLI before the
248+
// first ConfigureForTest). The response only depends on the token map,
249+
// which is populated independently of `state`.
272250
if (options.requestOptions.path === "/copilot_internal/user") {
273251
const headers = options.requestOptions.headers;
274252
const headerMap = headers as
@@ -310,6 +288,33 @@ export class ReplayingCapiProxy extends CapturingHttpProxy {
310288
return;
311289
}
312290

291+
const state = this.state;
292+
if (!state) {
293+
throw new Error(
294+
"ReplayingCapiProxy not yet initialized. Either pass filePath and workDir to the constructor, " +
295+
"or post configuration to /config before making other HTTP requests.",
296+
);
297+
}
298+
299+
// Handle /models endpoint
300+
// Use stored models if available, otherwise use default model
301+
if (options.requestOptions.path === "/models") {
302+
const models =
303+
state.storedData?.models && state.storedData.models.length > 0
304+
? state.storedData.models
305+
: [defaultModel];
306+
const modelsResponse = createGetModelsResponse(models);
307+
const body = JSON.stringify(modelsResponse);
308+
const headers = {
309+
"content-type": "application/json",
310+
...commonResponseHeaders,
311+
};
312+
options.onResponseStart(200, headers);
313+
options.onData(Buffer.from(body));
314+
options.onResponseEnd();
315+
return;
316+
}
317+
313318
// Handle memory endpoints - return stub responses in tests
314319
// Matches: /agents/*/memory/*/enabled, /agents/*/memory/*/recent, etc.
315320
if (options.requestOptions.path?.match(/\/agents\/.*\/memory\//)) {

0 commit comments

Comments
 (0)