Skip to content

Commit 2b5e130

Browse files
feat: add dynamic OAuth prompt system with conditional fields
- Add PromptFieldSchema supporting text and select input types - Support conditional prompt visibility based on previous inputs - Add inputs parameter to OAuth authorize request - Update OAuth dialogs to render dynamic prompts - Add OPENCODE_PUBLIC_URL config for OAuth callback URLs - Remove redundant OAuthMethod enum in favor of backend schema
1 parent 9d94c33 commit 2b5e130

12 files changed

Lines changed: 371 additions & 78 deletions

File tree

backend/src/routes/oauth.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ export function createOAuthRoutes() {
1818
const body = await c.req.json()
1919
const validated = OAuthAuthorizeRequestSchema.parse(body)
2020

21-
// Proxy to OpenCode server
21+
// Proxy to OpenCode server - only method and inputs are supported
2222
const response = await proxyRequest(
2323
new Request(
2424
`${OPENCODE_SERVER_URL}/provider/${providerId}/oauth/authorize`,

backend/src/services/opencode-single-server.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import { patchOpenCodeConfig } from './proxy'
2323

2424
const OPENCODE_SERVER_PORT = ENV.OPENCODE.PORT
2525
const OPENCODE_SERVER_HOST = ENV.OPENCODE.HOST
26+
const OPENCODE_SERVER_PUBLIC_URL = ENV.OPENCODE.PUBLIC_URL
2627
const MIN_OPENCODE_VERSION = '1.0.137'
2728
const MAX_STDERR_SIZE = 10240
2829

@@ -247,6 +248,7 @@ class OpenCodeServerManager {
247248
GIT_SSH_COMMAND: gitSshCommand,
248249
XDG_DATA_HOME: path.join(openCodeServerDirectory, '.opencode/state'),
249250
XDG_CONFIG_HOME: path.join(openCodeServerDirectory, '.config'),
251+
...(OPENCODE_SERVER_PUBLIC_URL ? { OPENCODE_PUBLIC_URL: OPENCODE_SERVER_PUBLIC_URL } : {}),
250252
OPENCODE_CONFIG: openCodeConfigPath,
251253
}
252254
}

frontend/src/api/oauth.ts

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,14 @@
11
import { API_BASE_URL } from "@/config"
2+
import type { components, operations } from "./opencode-types"
23
import { fetchWrapper, FetchError } from "./fetchWrapper"
34

4-
export interface OAuthAuthorizeResponse {
5-
url: string
6-
method: "code"
7-
instructions: string
8-
}
5+
type OpenCodeAuthorizeRequest = NonNullable<operations["provider.oauth.authorize"]["requestBody"]>["content"]["application/json"]
96

10-
export interface OAuthCallbackRequest {
11-
method: number
12-
code?: string
13-
}
7+
export type OAuthAuthorizeResponse = components["schemas"]["ProviderAuthAuthorization"]
148

15-
export interface ProviderAuthMethod {
16-
type: "oauth" | "api"
17-
label: string
18-
}
9+
export type OAuthCallbackRequest = NonNullable<operations["provider.oauth.callback"]["requestBody"]>["content"]["application/json"]
10+
11+
export type ProviderAuthMethod = components["schemas"]["ProviderAuthMethod"]
1912

2013
export interface ProviderAuthMethods {
2114
[providerId: string]: ProviderAuthMethod[]
@@ -29,12 +22,12 @@ function handleApiError(error: unknown, context: string): never {
2922
}
3023

3124
export const oauthApi = {
32-
authorize: async (providerId: string, method: number): Promise<OAuthAuthorizeResponse> => {
25+
authorize: async (providerId: string, method: number, inputs?: OpenCodeAuthorizeRequest["inputs"]): Promise<OAuthAuthorizeResponse> => {
3326
try {
3427
return await fetchWrapper(`${API_BASE_URL}/api/oauth/${providerId}/oauth/authorize`, {
3528
method: 'POST',
3629
headers: { 'Content-Type': 'application/json' },
37-
body: JSON.stringify({ method }),
30+
body: JSON.stringify({ method, inputs }),
3831
})
3932
} catch (error) {
4033
handleApiError(error, "OAuth authorization failed")

frontend/src/api/opencode-spec.json

Lines changed: 101 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3552,16 +3552,22 @@
35523552
"requestBody": {
35533553
"content": {
35543554
"application/json": {
3555-
"schema": {
3556-
"type": "object",
3557-
"properties": {
3558-
"method": {
3559-
"description": "Auth method index",
3560-
"type": "number"
3561-
}
3562-
},
3563-
"required": [
3564-
"method"
3555+
"schema": {
3556+
"type": "object",
3557+
"properties": {
3558+
"method": {
3559+
"description": "Auth method index",
3560+
"type": "number"
3561+
},
3562+
"inputs": {
3563+
"type": "object",
3564+
"additionalProperties": {
3565+
"type": "string"
3566+
}
3567+
}
3568+
},
3569+
"required": [
3570+
"method"
35653571
]
35663572
}
35673573
}
@@ -10399,6 +10405,90 @@
1039910405
},
1040010406
"label": {
1040110407
"type": "string"
10408+
},
10409+
"prompts": {
10410+
"type": "array",
10411+
"items": {
10412+
"anyOf": [
10413+
{
10414+
"type": "object",
10415+
"properties": {
10416+
"type": {
10417+
"type": "string",
10418+
"const": "text"
10419+
},
10420+
"key": {
10421+
"type": "string"
10422+
},
10423+
"message": {
10424+
"type": "string"
10425+
},
10426+
"placeholder": {
10427+
"type": "string"
10428+
}
10429+
},
10430+
"required": [
10431+
"type",
10432+
"key",
10433+
"message"
10434+
]
10435+
},
10436+
{
10437+
"type": "object",
10438+
"properties": {
10439+
"type": {
10440+
"type": "string",
10441+
"const": "select"
10442+
},
10443+
"key": {
10444+
"type": "string"
10445+
},
10446+
"message": {
10447+
"type": "string"
10448+
},
10449+
"options": {
10450+
"type": "array",
10451+
"items": {
10452+
"type": "object",
10453+
"properties": {
10454+
"label": {
10455+
"type": "string"
10456+
},
10457+
"value": {
10458+
"type": "string"
10459+
}
10460+
},
10461+
"required": [
10462+
"label",
10463+
"value"
10464+
]
10465+
}
10466+
},
10467+
"when": {
10468+
"type": "object",
10469+
"properties": {
10470+
"key": {
10471+
"type": "string"
10472+
},
10473+
"value": {
10474+
"type": "string"
10475+
}
10476+
},
10477+
"required": [
10478+
"key",
10479+
"value"
10480+
]
10481+
}
10482+
},
10483+
"required": [
10484+
"type",
10485+
"key",
10486+
"message",
10487+
"options"
10488+
]
10489+
}
10490+
]
10491+
}
1040210492
}
1040310493
},
1040410494
"required": [
@@ -10932,4 +11022,4 @@
1093211022
}
1093311023
}
1093411024
}
10935-
}
11025+
}

frontend/src/api/opencode-types.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3379,6 +3379,24 @@ export interface components {
33793379
ProviderAuthMethod: {
33803380
type: "oauth" | "api";
33813381
label: string;
3382+
prompts?: ({
3383+
type: "text";
3384+
key: string;
3385+
message: string;
3386+
placeholder?: string;
3387+
} | {
3388+
type: "select";
3389+
key: string;
3390+
message: string;
3391+
options: {
3392+
label: string;
3393+
value: string;
3394+
}[];
3395+
when?: {
3396+
key: string;
3397+
value: string;
3398+
};
3399+
})[];
33823400
};
33833401
ProviderAuthAuthorization: {
33843402
url: string;
@@ -5698,6 +5716,9 @@ export interface operations {
56985716
"application/json": {
56995717
/** @description Auth method index */
57005718
method: number;
5719+
inputs?: {
5720+
[key: string]: string;
5721+
};
57015722
};
57025723
};
57035724
};

0 commit comments

Comments
 (0)