feat(paseo-agent): add browser OAuth start mode

Default daemon-run OAuth to browser mode while keeping device-code explicit for remote-safe setup.
This commit is contained in:
Mohamed Boudra
2026-07-02 14:51:26 +02:00
parent 269aa53c27
commit 6a2b5ea5ea
15 changed files with 575 additions and 120 deletions
+19 -9
View File
@@ -20,7 +20,10 @@ interface RecordingClientInput {
providerType: string;
options: { apiKey?: string; models?: Array<{ id: string }> };
}) => Promise<unknown>;
startOAuth?: (name: string) => Promise<unknown>;
startOAuth?: (
name: string,
options?: { mode?: string; requestId?: string } | string,
) => Promise<unknown>;
completeOAuth?: (name: string) => Promise<unknown>;
storeCredential?: (input: { name: string; credential: unknown }) => Promise<unknown>;
}
@@ -59,8 +62,11 @@ function createClient(input: RecordingClientInput) {
error: null,
};
},
startPaseoAgentOAuth: async (name: string) =>
input.startOAuth?.(name) ?? {
startPaseoAgentOAuth: async (
name: string,
options?: { mode?: string; requestId?: string } | string,
) =>
input.startOAuth?.(name, options) ?? {
requestId: "oauth-start-1",
success: true,
name,
@@ -443,8 +449,10 @@ describe("provider add", () => {
connectDaemon: async () =>
createClient({
catalog: [oauthEntry()],
startOAuth: async (name) => {
oauthCalls.push(`start:${name}`);
startOAuth: async (name, options) => {
oauthCalls.push(
`start:${name}:${typeof options === "string" ? options : options?.mode}`,
);
return {
requestId: "start-1",
success: true,
@@ -471,7 +479,7 @@ describe("provider add", () => {
}),
});
expect(oauthCalls).toEqual(["start:beta-oauth", "complete:beta-oauth"]);
expect(oauthCalls).toEqual(["start:beta-oauth:device_code", "complete:beta-oauth"]);
expect(output.join("\n")).toContain("ABCD-EFGH");
expect(output.join("\n")).toContain("https://auth.example.test/device");
expect(result.data.auth).toBe("Connected");
@@ -500,8 +508,10 @@ describe("provider add", () => {
connectDaemon: async () =>
createClient({
catalog: [oauthEntry()],
startOAuth: async (name) => {
oauthCalls.push(`start:${name}`);
startOAuth: async (name, options) => {
oauthCalls.push(
`start:${name}:${typeof options === "string" ? options : options?.mode}`,
);
return {
requestId: "start-1",
success: true,
@@ -527,7 +537,7 @@ describe("provider add", () => {
}),
});
expect(oauthCalls).toEqual(["start:beta-oauth", "complete:beta-oauth"]);
expect(oauthCalls).toEqual(["start:beta-oauth:device_code", "complete:beta-oauth"]);
expect(output.join("\n")).toContain("Browser could not be opened");
expect(output.join("\n")).toContain("WXYZ-1234");
});
+1 -1
View File
@@ -351,7 +351,7 @@ async function runDaemonOAuth(
name: string,
dependencies: ProviderAddDependencies,
): Promise<PaseoAgentProviderAuthState | undefined> {
const started = await client.startPaseoAgentOAuth(name);
const started = await client.startPaseoAgentOAuth(name, { mode: "device_code" });
if (!started.success) {
throw {
code: "OAUTH_START_FAILED",