diff --git a/crates/rhema-claw/src/backends.rs b/crates/rhema-claw/src/backends.rs index f2125f7..2d3272e 100644 --- a/crates/rhema-claw/src/backends.rs +++ b/crates/rhema-claw/src/backends.rs @@ -320,6 +320,7 @@ fn env_vars_for(kind: &str) -> &'static [&'static str] { "zai" => &["ZAI_API_KEY", "Z_AI_API_KEY"], "opencode" => &["OPENCODE_API_KEY"], "copilot" => &["GITHUB_COPILOT_TOKEN"], + "chatgpt" => &["CHATGPT_ACCESS_TOKEN"], _ => &[], } } @@ -366,6 +367,7 @@ pub struct ProviderParams { pub fn addable_kinds() -> &'static [&'static str] { &[ "anthropic", + "chatgpt", "copilot", "deepseek", "google", @@ -542,6 +544,7 @@ pub fn discover( "zai", "opencode", "copilot", + "chatgpt", ] { let stored_of_kind = rows.iter().any(|(_, params)| params.kind == kind); let params = if kind == "llama-cpp" { diff --git a/deploy/docker/claw.Dockerfile b/deploy/docker/claw.Dockerfile index 5e8029c..1609412 100644 --- a/deploy/docker/claw.Dockerfile +++ b/deploy/docker/claw.Dockerfile @@ -26,6 +26,7 @@ COPY crates/rhema-memory/Cargo.toml crates/rhema-memory/Cargo.toml COPY crates/rhema-mcp/Cargo.toml crates/rhema-mcp/Cargo.toml COPY crates/rhema-provider/Cargo.toml crates/rhema-provider/Cargo.toml COPY crates/rhema-provider-anthropic/Cargo.toml crates/rhema-provider-anthropic/Cargo.toml +COPY crates/rhema-provider-chatgpt/Cargo.toml crates/rhema-provider-chatgpt/Cargo.toml COPY crates/rhema-provider-copilot/Cargo.toml crates/rhema-provider-copilot/Cargo.toml COPY crates/rhema-provider-google/Cargo.toml crates/rhema-provider-google/Cargo.toml COPY crates/rhema-provider-llama-cpp/Cargo.toml crates/rhema-provider-llama-cpp/Cargo.toml diff --git a/deploy/docker/sandboxd.Dockerfile b/deploy/docker/sandboxd.Dockerfile index fd5a323..afa9857 100644 --- a/deploy/docker/sandboxd.Dockerfile +++ b/deploy/docker/sandboxd.Dockerfile @@ -28,6 +28,7 @@ COPY crates/rhema-memory/Cargo.toml crates/rhema-memory/Cargo.toml COPY crates/rhema-mcp/Cargo.toml crates/rhema-mcp/Cargo.toml COPY crates/rhema-provider/Cargo.toml crates/rhema-provider/Cargo.toml COPY crates/rhema-provider-anthropic/Cargo.toml crates/rhema-provider-anthropic/Cargo.toml +COPY crates/rhema-provider-chatgpt/Cargo.toml crates/rhema-provider-chatgpt/Cargo.toml COPY crates/rhema-provider-copilot/Cargo.toml crates/rhema-provider-copilot/Cargo.toml COPY crates/rhema-provider-google/Cargo.toml crates/rhema-provider-google/Cargo.toml COPY crates/rhema-provider-llama-cpp/Cargo.toml crates/rhema-provider-llama-cpp/Cargo.toml diff --git a/web/claw/app/components/settings/ProvidersPage.vue b/web/claw/app/components/settings/ProvidersPage.vue index 63266a3..212ea1c 100644 --- a/web/claw/app/components/settings/ProvidersPage.vue +++ b/web/claw/app/components/settings/ProvidersPage.vue @@ -98,6 +98,7 @@ function save(): void { // --- the login form --------------------------------------------------- const KIND_LABELS: Record = { anthropic: 'Anthropic', + chatgpt: 'ChatGPT (subscription)', copilot: 'GitHub Copilot', deepseek: 'DeepSeek', google: 'Google Gemini', @@ -111,10 +112,14 @@ function kindLabel(kind: string): string { return KIND_LABELS[kind] ?? kind } -/** The key field's voice: copilot logs in with a GitHub token. */ -const keyLabel = computed(() => - addKind.value === 'copilot' ? 'GitHub token' : 'API key', -) +/** The key field's voice: copilot logs in with a GitHub token, and a + * ChatGPT login takes the browser flow's credential JSON (or a bare + * access token). */ +const keyLabel = computed(() => { + if (addKind.value === 'copilot') return 'GitHub token' + if (addKind.value === 'chatgpt') return 'ChatGPT credential (JSON or access token)' + return 'API key' +}) /** A field the daemon does not demand reads as optional, not hidden. */ function label(name: string, base: string): string { diff --git a/web/claw/app/composables/useClaw.ts b/web/claw/app/composables/useClaw.ts index d1ddad9..ae8ab42 100644 --- a/web/claw/app/composables/useClaw.ts +++ b/web/claw/app/composables/useClaw.ts @@ -204,7 +204,8 @@ export type AgentImageKind = 'avatar' | 'logo' /** The credentials a provider login carries: the instance name (the * kind when omitted), the kind (required on an id's first login), an - * API key (a GitHub token for copilot), and a server URL for + * API key (a GitHub token for copilot, the sign-in JSON for chatgpt), + * and a server URL for * llama.cpp. Empty optionals are omitted, never sent as "" strings. */ export interface ProviderCredentials { name?: string