fix: accept auth code in chutes oauth manual flow

This commit is contained in:
Peter Steinberger 2026-02-15 02:52:36 +00:00
parent 981d572132
commit 6c0dca30b8
2 changed files with 32 additions and 26 deletions

View File

@ -20,14 +20,6 @@ const IOS_NODE = {
connected: true,
} as const;
function getFirstRuntimeLogLine(): string {
const value = runtime.log.mock.calls[0]?.[0];
if (typeof value !== "string") {
throw new Error(`expected runtime.log first arg to be string, got ${typeof value}`);
}
return value;
}
function mockCameraGateway(
command: "camera.snap" | "camera.clip",
payload: Record<string, unknown>,

View File

@ -15,6 +15,34 @@ type OAuthPrompt = {
placeholder?: string;
};
function parseManualOAuthInput(
input: string,
expectedState: string,
): { code: string; state: string } {
const trimmed = String(input ?? "").trim();
if (!trimmed) {
throw new Error("Missing OAuth redirect URL or authorization code.");
}
// Support pasting either:
// - Full redirect URL (preferred; validates state)
// - Raw authorization code (legacy/manual copy flows)
const looksLikeRedirect =
/^https?:\/\//i.test(trimmed) || trimmed.includes("://") || trimmed.includes("?");
if (!looksLikeRedirect) {
return { code: trimmed, state: expectedState };
}
const parsed = parseOAuthCallbackInput(trimmed, expectedState);
if ("error" in parsed) {
throw new Error(parsed.error);
}
if (parsed.state !== expectedState) {
throw new Error("Invalid OAuth state");
}
return parsed;
}
function buildAuthorizeUrl(params: {
clientId: string;
redirectUri: string;
@ -156,17 +184,10 @@ export async function loginChutes(params: {
await params.onAuth({ url });
params.onProgress?.("Waiting for redirect URL…");
const input = await params.onPrompt({
message: "Paste the redirect URL",
message: "Paste the redirect URL (or authorization code)",
placeholder: `${params.app.redirectUri}?code=...&state=...`,
});
const parsed = parseOAuthCallbackInput(String(input), state);
if ("error" in parsed) {
throw new Error(parsed.error);
}
if (parsed.state !== state) {
throw new Error("Invalid OAuth state");
}
codeAndState = parsed;
codeAndState = parseManualOAuthInput(input, state);
} else {
const callback = waitForLocalCallback({
redirectUri: params.app.redirectUri,
@ -176,17 +197,10 @@ export async function loginChutes(params: {
}).catch(async () => {
params.onProgress?.("OAuth callback not detected; paste redirect URL…");
const input = await params.onPrompt({
message: "Paste the redirect URL",
message: "Paste the redirect URL (or authorization code)",
placeholder: `${params.app.redirectUri}?code=...&state=...`,
});
const parsed = parseOAuthCallbackInput(String(input), state);
if ("error" in parsed) {
throw new Error(parsed.error);
}
if (parsed.state !== state) {
throw new Error("Invalid OAuth state");
}
return parsed;
return parseManualOAuthInput(input, state);
});
await params.onAuth({ url });