fix(mcp): preserve existing manual login waits

This commit is contained in:
danzaio
2026-06-09 14:15:17 -03:00
committed by can1357
parent 8e6f6c13e5
commit 314cea633a
3 changed files with 30 additions and 2 deletions
@@ -597,6 +597,11 @@ export class MCPCommandController {
const resolvedClientSecret = clientSecret.trim() || undefined;
const manualInput = this.ctx.oauthManualInput;
if (manualInput.hasPending() && manualInput.pendingProviderId !== MCP_MANUAL_INPUT_PROVIDER_ID) {
throw new Error(
`OAuth login already in progress for ${manualInput.pendingProviderId}. Complete or cancel it before starting MCP OAuth.`,
);
}
const oauthTimeout = new AbortController();
try {
// Create OAuth flow
@@ -652,8 +657,15 @@ export class MCPCommandController {
onProgress: (message: string) => {
this.ctx.present([new Spacer(1), new Text(theme.fg("muted", message), 1, 0)]);
},
onManualCodeInput: () => manualInput.waitForInput(MCP_MANUAL_INPUT_PROVIDER_ID),
signal: oauthTimeout.signal,
onManualCodeInput: () => {
const pendingInput = manualInput.tryWaitForInput(MCP_MANUAL_INPUT_PROVIDER_ID);
if (!pendingInput) {
throw new Error(
`OAuth login already in progress for ${manualInput.pendingProviderId}. Complete or cancel it before starting MCP OAuth.`,
);
}
return pendingInput;
},
},
);
@@ -17,6 +17,11 @@ export class OAuthManualInputManager {
return promise;
}
tryWaitForInput(providerId: string): Promise<string> | undefined {
if (this.#pending) return undefined;
return this.waitForInput(providerId);
}
submit(input: string): boolean {
if (!this.#pending) return false;
const { resolve } = this.#pending;
@@ -13,6 +13,17 @@ describe("OAuthManualInputManager", () => {
expect(manager.hasPending()).toBe(false);
});
it("does not replace pending input when using tryWaitForInput", async () => {
const manager = new OAuthManualInputManager();
const first = manager.waitForInput("openai-codex");
expect(manager.tryWaitForInput("mcp")).toBeUndefined();
expect(manager.pendingProviderId).toBe("openai-codex");
expect(manager.submit("callback-url")).toBe(true);
expect(await first).toBe("callback-url");
});
it("returns false when no pending input", () => {
const manager = new OAuthManualInputManager();