From dfc5b0b8037a04fffeb051dd6c52e82671b0bc6c Mon Sep 17 00:00:00 2001 From: Bradley Axen Date: Tue, 21 Apr 2026 09:19:20 -0700 Subject: [PATCH] consolidate provider ACP methods onto inventory (#8710) Signed-off-by: Bradley Axen --- crates/goose-acp/acp-meta.json | 10 - crates/goose-acp/acp-schema.json | 280 +++++------------- crates/goose-acp/src/server.rs | 113 +++---- .../goose-acp/tests/custom_requests_test.rs | 31 +- crates/goose-sdk/src/custom_requests.rs | 75 +---- crates/goose/src/providers/inventory/mod.rs | 22 +- .../src/features/providers/api/inventory.ts | 2 +- ui/goose2/src/shared/api/acpApi.ts | 23 +- ui/goose2/tests/e2e/fixtures/tauri-mock.ts | 2 - ui/sdk/src/generated/client.gen.ts | 22 -- ui/sdk/src/generated/index.ts | 12 +- ui/sdk/src/generated/types.gen.ts | 100 +++---- ui/sdk/src/generated/zod.gen.ts | 65 +--- ui/text/src/configure.tsx | 43 +-- ui/text/src/onboarding.tsx | 48 +-- 15 files changed, 275 insertions(+), 573 deletions(-) diff --git a/crates/goose-acp/acp-meta.json b/crates/goose-acp/acp-meta.json index 8a2e7fe4..769136c5 100644 --- a/crates/goose-acp/acp-meta.json +++ b/crates/goose-acp/acp-meta.json @@ -45,16 +45,6 @@ "requestType": "ListProvidersRequest", "responseType": "ListProvidersResponse" }, - { - "method": "_goose/providers/details", - "requestType": "GetProviderDetailsRequest", - "responseType": "GetProviderDetailsResponse" - }, - { - "method": "_goose/providers/inventory", - "requestType": "GetProviderInventoryRequest", - "responseType": "GetProviderInventoryResponse" - }, { "method": "_goose/providers/inventory/refresh", "requestType": "RefreshProviderInventoryRequest", diff --git a/crates/goose-acp/acp-schema.json b/crates/goose-acp/acp-schema.json index 8fe12e00..c44738c2 100644 --- a/crates/goose-acp/acp-schema.json +++ b/crates/goose-acp/acp-schema.json @@ -196,173 +196,6 @@ "x-method": "_goose/session/extensions" }, "ListProvidersRequest": { - "type": "object", - "description": "List providers available through goose, including the config-default sentinel.", - "x-side": "agent", - "x-method": "_goose/providers/list" - }, - "ListProvidersResponse": { - "type": "object", - "properties": { - "providers": { - "type": "array", - "items": { - "$ref": "#/$defs/ProviderListEntry" - } - } - }, - "required": [ - "providers" - ], - "description": "Provider list response.", - "x-side": "agent", - "x-method": "_goose/providers/list" - }, - "ProviderListEntry": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "label": { - "type": "string" - } - }, - "required": [ - "id", - "label" - ] - }, - "GetProviderDetailsRequest": { - "type": "object", - "description": "List providers with full metadata (config keys, setup steps, etc.).", - "x-side": "agent", - "x-method": "_goose/providers/details" - }, - "GetProviderDetailsResponse": { - "type": "object", - "properties": { - "providers": { - "type": "array", - "items": { - "$ref": "#/$defs/ProviderDetailEntry" - } - } - }, - "required": [ - "providers" - ], - "description": "Provider details response.", - "x-side": "agent", - "x-method": "_goose/providers/details" - }, - "ProviderDetailEntry": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "displayName": { - "type": "string" - }, - "description": { - "type": "string" - }, - "defaultModel": { - "type": "string" - }, - "isConfigured": { - "type": "boolean" - }, - "providerType": { - "type": "string" - }, - "configKeys": { - "type": "array", - "items": { - "$ref": "#/$defs/ProviderConfigKey" - } - }, - "setupSteps": { - "type": "array", - "items": { - "type": "string" - }, - "default": [] - }, - "knownModels": { - "type": "array", - "items": { - "$ref": "#/$defs/ModelEntry" - }, - "default": [] - } - }, - "required": [ - "name", - "displayName", - "description", - "defaultModel", - "isConfigured", - "providerType", - "configKeys" - ] - }, - "ProviderConfigKey": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "required": { - "type": "boolean" - }, - "secret": { - "type": "boolean" - }, - "default": { - "type": [ - "string", - "null" - ], - "default": null - }, - "oauthFlow": { - "type": "boolean", - "default": false - }, - "deviceCodeFlow": { - "type": "boolean", - "default": false - }, - "primary": { - "type": "boolean", - "default": false - } - }, - "required": [ - "name", - "required", - "secret" - ] - }, - "ModelEntry": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "contextLimit": { - "type": "integer", - "minimum": 0 - } - }, - "required": [ - "name", - "contextLimit" - ] - }, - "GetProviderInventoryRequest": { "type": "object", "properties": { "providerIds": { @@ -374,11 +207,11 @@ "default": [] } }, - "description": "Read per-provider inventory. Always returns immediately from stored state.", + "description": "List providers with setup metadata and the current model inventory snapshot.", "x-side": "agent", - "x-method": "_goose/providers/inventory" + "x-method": "_goose/providers/list" }, - "GetProviderInventoryResponse": { + "ListProvidersResponse": { "type": "object", "properties": { "entries": { @@ -391,9 +224,9 @@ "required": [ "entries" ], - "description": "Provider inventory response.", + "description": "Provider list response.", "x-side": "agent", - "x-method": "_goose/providers/inventory" + "x-method": "_goose/providers/list" }, "ProviderInventoryEntryDto": { "type": "object", @@ -406,10 +239,36 @@ "type": "string", "description": "Human-readable provider name." }, + "description": { + "type": "string", + "description": "Description of the provider's capabilities." + }, + "defaultModel": { + "type": "string", + "description": "The default/recommended model for this provider." + }, "configured": { "type": "boolean", "description": "Whether Goose has enough configuration to use this provider." }, + "providerType": { + "type": "string", + "description": "Provider classification such as `Preferred`, `Builtin`, `Declarative`, or `Custom`." + }, + "configKeys": { + "type": "array", + "items": { + "$ref": "#/$defs/ProviderConfigKey" + }, + "description": "Required configuration keys and setup metadata." + }, + "setupSteps": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Step-by-step setup instructions, when present." + }, "supportsRefresh": { "type": "boolean", "description": "Whether this provider supports background inventory refresh." @@ -461,7 +320,12 @@ "required": [ "providerId", "providerName", + "description", + "defaultModel", "configured", + "providerType", + "configKeys", + "setupSteps", "supportsRefresh", "refreshing", "models", @@ -469,6 +333,44 @@ ], "description": "Provider inventory entry." }, + "ProviderConfigKey": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "secret": { + "type": "boolean" + }, + "default": { + "type": [ + "string", + "null" + ], + "default": null + }, + "oauthFlow": { + "type": "boolean", + "default": false + }, + "deviceCodeFlow": { + "type": "boolean", + "default": false + }, + "primary": { + "type": "boolean", + "default": false + } + }, + "required": [ + "name", + "required", + "secret" + ] + }, "ProviderInventoryModelDto": { "type": "object", "properties": { @@ -1504,24 +1406,6 @@ "description": "Params for _goose/providers/list", "title": "ListProvidersRequest" }, - { - "allOf": [ - { - "$ref": "#/$defs/GetProviderDetailsRequest" - } - ], - "description": "Params for _goose/providers/details", - "title": "GetProviderDetailsRequest" - }, - { - "allOf": [ - { - "$ref": "#/$defs/GetProviderInventoryRequest" - } - ], - "description": "Params for _goose/providers/inventory", - "title": "GetProviderInventoryRequest" - }, { "allOf": [ { @@ -1825,22 +1709,6 @@ ], "title": "ListProvidersResponse" }, - { - "allOf": [ - { - "$ref": "#/$defs/GetProviderDetailsResponse" - } - ], - "title": "GetProviderDetailsResponse" - }, - { - "allOf": [ - { - "$ref": "#/$defs/GetProviderInventoryResponse" - } - ], - "title": "GetProviderInventoryResponse" - }, { "allOf": [ { diff --git a/crates/goose-acp/src/server.rs b/crates/goose-acp/src/server.rs index 09d483a2..2c62d17e 100644 --- a/crates/goose-acp/src/server.rs +++ b/crates/goose-acp/src/server.rs @@ -426,7 +426,16 @@ fn inventory_entry_to_dto(entry: ProviderInventoryEntry) -> ProviderInventoryEnt ProviderInventoryEntryDto { provider_id: entry.provider_id, provider_name: entry.provider_name, + description: entry.description, + default_model: entry.default_model, configured: entry.configured, + provider_type: format!("{:?}", entry.provider_type), + config_keys: entry + .config_keys + .into_iter() + .map(provider_config_key_to_dto) + .collect(), + setup_steps: entry.setup_steps, supports_refresh: entry.supports_refresh, refreshing: entry.refreshing, models: entry @@ -449,6 +458,18 @@ fn inventory_entry_to_dto(entry: ProviderInventoryEntry) -> ProviderInventoryEnt } } +fn provider_config_key_to_dto(key: goose::providers::base::ConfigKey) -> ProviderConfigKey { + ProviderConfigKey { + name: key.name, + required: key.required, + secret: key.secret, + default: key.default, + oauth_flow: key.oauth_flow, + device_code_flow: key.device_code_flow, + primary: key.primary, + } +} + fn build_model_state(current_model: &str, inventory: &ProviderInventoryEntry) -> SessionModelState { let mut available_models = inventory .models @@ -467,11 +488,16 @@ fn build_model_state(current_model: &str, inventory: &ProviderInventoryEntry) -> SessionModelState::new(ModelId::new(current_model), available_models) } -async fn list_provider_entries(current_provider: Option<&str>) -> Vec { +struct ProviderOptionEntry { + id: String, + label: String, +} + +async fn list_provider_entries(current_provider: Option<&str>) -> Vec { let mut providers = goose::providers::providers() .await .into_iter() - .map(|(metadata, _)| ProviderListEntry { + .map(|(metadata, _)| ProviderOptionEntry { id: metadata.name, label: metadata.display_name, }) @@ -485,7 +511,7 @@ async fn list_provider_entries(current_provider: Option<&str>) -> Vec) -> Vec Result { - Ok(ListProvidersResponse { - providers: list_provider_entries(None).await, - }) - } - - #[custom_method(GetProviderDetailsRequest)] - async fn on_get_provider_details( - &self, - _req: GetProviderDetailsRequest, - ) -> Result { - let config = self.load_config().ok(); - let all = goose::providers::providers().await; - let entries = all - .into_iter() - .map(|(metadata, provider_type)| { - let is_configured = config - .as_ref() - .map(|c| { - metadata.config_keys.iter().all(|k| { - if !k.required { - return true; - } - if k.secret { - c.get_secret::(&k.name).is_ok() - } else { - c.get_param::(&k.name).is_ok() - } - }) - }) - .unwrap_or(false); - ProviderDetailEntry { - name: metadata.name.clone(), - display_name: metadata.display_name.clone(), - description: metadata.description.clone(), - default_model: metadata.default_model.clone(), - is_configured, - provider_type: format!("{:?}", provider_type), - config_keys: metadata - .config_keys - .iter() - .map(|k| ProviderConfigKey { - name: k.name.clone(), - required: k.required, - secret: k.secret, - default: k.default.clone(), - oauth_flow: k.oauth_flow, - device_code_flow: k.device_code_flow, - primary: k.primary, - }) - .collect(), - setup_steps: metadata.setup_steps.clone(), - known_models: metadata - .known_models - .iter() - .map(|m| ModelEntry { - name: m.name.clone(), - context_limit: m.context_limit, - }) - .collect(), - } - }) - .collect(); - Ok(GetProviderDetailsResponse { providers: entries }) - } - - #[custom_method(GetProviderInventoryRequest)] - async fn on_get_provider_inventory( - &self, - req: GetProviderInventoryRequest, - ) -> Result { let entries = self .provider_inventory .entries(&req.provider_ids) .await .map_err(|e| sacp::Error::internal_error().data(e.to_string()))?; - Ok(GetProviderInventoryResponse { + Ok(ListProvidersResponse { entries: entries.into_iter().map(inventory_entry_to_dto).collect(), }) } @@ -4150,7 +4106,12 @@ print(\"hello, world\") let inventory = ProviderInventoryEntry { provider_id: "mock".to_string(), provider_name: "Mock".to_string(), + description: "Mock".to_string(), + default_model: "unused".to_string(), configured: true, + provider_type: goose::providers::base::ProviderType::Builtin, + config_keys: vec![], + setup_steps: vec![], supports_refresh: true, refreshing: false, models: models diff --git a/crates/goose-acp/tests/custom_requests_test.rs b/crates/goose-acp/tests/custom_requests_test.rs index 06c970f6..c4fe430f 100644 --- a/crates/goose-acp/tests/custom_requests_test.rs +++ b/crates/goose-acp/tests/custom_requests_test.rs @@ -112,32 +112,29 @@ fn test_custom_get_extensions() { } #[test] -fn test_custom_list_providers() { +fn test_custom_provider_inventory_includes_metadata() { run_test(async { let openai = OpenAiFixture::new(vec![], Arc::new(EnforceSessionId::default())).await; let conn = AcpServerConnection::new(TestConnectionConfig::default(), openai).await; let response = send_custom(conn.cx(), "_goose/providers/list", serde_json::json!({})) .await - .expect("provider list should succeed"); + .expect("provider inventory should succeed"); let providers = response - .get("providers") + .get("entries") .and_then(|value| value.as_array()) - .expect("missing providers array"); + .expect("missing entries array"); + let openai = providers + .iter() + .find(|provider| provider.get("providerId") == Some(&serde_json::json!("openai"))) + .expect("expected openai inventory entry"); - assert!( - providers.iter().any(|provider| { - provider.get("id") == Some(&serde_json::json!("goose")) - && provider.get("label") == Some(&serde_json::json!("Goose (Default)")) - }), - "expected Goose default provider sentinel" - ); - assert!( - providers - .iter() - .any(|provider| provider.get("id") == Some(&serde_json::json!("openai"))), - "expected at least one concrete provider from the goose registry" - ); + assert!(openai.get("providerName").is_some(), "missing providerName"); + assert!(openai.get("description").is_some(), "missing description"); + assert!(openai.get("defaultModel").is_some(), "missing defaultModel"); + assert!(openai.get("providerType").is_some(), "missing providerType"); + assert!(openai.get("configKeys").is_some(), "missing configKeys"); + assert!(openai.get("setupSteps").is_some(), "missing setupSteps"); }); } diff --git a/crates/goose-sdk/src/custom_requests.rs b/crates/goose-sdk/src/custom_requests.rs index 2906b7aa..223a92ac 100644 --- a/crates/goose-sdk/src/custom_requests.rs +++ b/crates/goose-sdk/src/custom_requests.rs @@ -181,24 +181,6 @@ pub struct RemoveSecretRequest { pub key: String, } -/// List providers available through goose, including the config-default sentinel. -#[derive(Debug, Default, Clone, Serialize, Deserialize, JsonSchema, JsonRpcRequest)] -#[request(method = "_goose/providers/list", response = ListProvidersResponse)] -pub struct ListProvidersRequest {} - -#[derive(Debug, Default, Clone, Serialize, Deserialize, JsonSchema)] -#[serde(rename_all = "camelCase")] -pub struct ProviderListEntry { - pub id: String, - pub label: String, -} - -/// Provider list response. -#[derive(Debug, Default, Clone, Serialize, Deserialize, JsonSchema, JsonRpcResponse)] -pub struct ListProvidersResponse { - pub providers: Vec, -} - /// Archive a session (soft delete). #[derive(Debug, Default, Clone, Serialize, Deserialize, JsonSchema, JsonRpcRequest)] #[request(method = "_goose/session/archive", response = EmptyResponse)] @@ -246,40 +228,6 @@ pub struct ImportSessionResponse { pub message_count: u64, } -/// List providers with full metadata (config keys, setup steps, etc.). -#[derive(Debug, Default, Clone, Serialize, Deserialize, JsonSchema, JsonRpcRequest)] -#[request(method = "_goose/providers/details", response = GetProviderDetailsResponse)] -pub struct GetProviderDetailsRequest {} - -/// Provider details response. -#[derive(Debug, Default, Clone, Serialize, Deserialize, JsonSchema, JsonRpcResponse)] -pub struct GetProviderDetailsResponse { - pub providers: Vec, -} - -#[derive(Debug, Default, Clone, Serialize, Deserialize, JsonSchema)] -#[serde(rename_all = "camelCase")] -pub struct ProviderDetailEntry { - pub name: String, - pub display_name: String, - pub description: String, - pub default_model: String, - pub is_configured: bool, - pub provider_type: String, - pub config_keys: Vec, - #[serde(default)] - pub setup_steps: Vec, - #[serde(default)] - pub known_models: Vec, -} - -#[derive(Debug, Default, Clone, Serialize, Deserialize, JsonSchema)] -#[serde(rename_all = "camelCase")] -pub struct ModelEntry { - pub name: String, - pub context_limit: usize, -} - #[derive(Debug, Default, Clone, Serialize, Deserialize, JsonSchema)] #[serde(rename_all = "camelCase")] pub struct ProviderConfigKey { @@ -494,22 +442,19 @@ pub struct DictationConfigResponse { pub providers: HashMap, } -/// Read per-provider inventory. Always returns immediately from stored state. +/// List providers with setup metadata and the current model inventory snapshot. #[derive(Debug, Default, Clone, Serialize, Deserialize, JsonSchema, JsonRpcRequest)] -#[request( - method = "_goose/providers/inventory", - response = GetProviderInventoryResponse -)] +#[request(method = "_goose/providers/list", response = ListProvidersResponse)] #[serde(rename_all = "camelCase")] -pub struct GetProviderInventoryRequest { +pub struct ListProvidersRequest { /// Only return entries for these providers. Empty means all. #[serde(default)] pub provider_ids: Vec, } -/// Provider inventory response. +/// Provider list response. #[derive(Debug, Default, Clone, Serialize, Deserialize, JsonSchema, JsonRpcResponse)] -pub struct GetProviderInventoryResponse { +pub struct ListProvidersResponse { pub entries: Vec, } @@ -584,8 +529,18 @@ pub struct ProviderInventoryEntryDto { pub provider_id: String, /// Human-readable provider name. pub provider_name: String, + /// Description of the provider's capabilities. + pub description: String, + /// The default/recommended model for this provider. + pub default_model: String, /// Whether Goose has enough configuration to use this provider. pub configured: bool, + /// Provider classification such as `Preferred`, `Builtin`, `Declarative`, or `Custom`. + pub provider_type: String, + /// Required configuration keys and setup metadata. + pub config_keys: Vec, + /// Step-by-step setup instructions, when present. + pub setup_steps: Vec, /// Whether this provider supports background inventory refresh. pub supports_refresh: bool, /// Whether a refresh is currently in flight. diff --git a/crates/goose/src/providers/inventory/mod.rs b/crates/goose/src/providers/inventory/mod.rs index 0a0eb9dc..7db08a06 100644 --- a/crates/goose/src/providers/inventory/mod.rs +++ b/crates/goose/src/providers/inventory/mod.rs @@ -1,4 +1,4 @@ -use super::base::{ConfigKey, ModelInfo}; +use super::base::{ConfigKey, ModelInfo, ProviderType}; use super::canonical::{map_provider_name, map_to_canonical_model, CanonicalModelRegistry}; use crate::config::declarative_providers::{DeclarativeProviderConfig, ProviderEngine}; use crate::config::Config; @@ -19,7 +19,12 @@ const STALE_AFTER_HOURS: i64 = 24; pub struct ProviderInventoryEntry { pub provider_id: String, pub provider_name: String, + pub description: String, + pub default_model: String, pub configured: bool, + pub provider_type: ProviderType, + pub config_keys: Vec, + pub setup_steps: Vec, pub supports_refresh: bool, pub refreshing: bool, pub models: Vec, @@ -162,8 +167,13 @@ struct InventorySnapshot { struct ProviderDescriptor { provider_id: String, provider_name: String, + description: String, + default_model: String, identity: InventoryIdentity, configured: bool, + provider_type: ProviderType, + config_keys: Vec, + setup_steps: Vec, supports_refresh: bool, static_models: Vec, model_selection_hint: Option, @@ -199,7 +209,12 @@ impl ProviderInventoryService { Ok(Some(ProviderInventoryEntry { provider_id: descriptor.provider_id, provider_name: descriptor.provider_name, + description: descriptor.description, + default_model: descriptor.default_model, configured: descriptor.configured, + provider_type: descriptor.provider_type, + config_keys: descriptor.config_keys, + setup_steps: descriptor.setup_steps, supports_refresh: descriptor.supports_refresh, refreshing, models, @@ -419,8 +434,13 @@ impl ProviderInventoryService { Ok(Some(ProviderDescriptor { provider_id: metadata.name.clone(), provider_name: metadata.display_name.clone(), + description: metadata.description.clone(), + default_model: metadata.default_model.clone(), identity, configured: entry.inventory_configured(), + provider_type: entry.provider_type(), + config_keys: metadata.config_keys.clone(), + setup_steps: metadata.setup_steps.clone(), supports_refresh: entry.supports_inventory_refresh(), static_models: metadata.known_models, model_selection_hint: metadata.model_selection_hint, diff --git a/ui/goose2/src/features/providers/api/inventory.ts b/ui/goose2/src/features/providers/api/inventory.ts index ef3f52c2..74d10129 100644 --- a/ui/goose2/src/features/providers/api/inventory.ts +++ b/ui/goose2/src/features/providers/api/inventory.ts @@ -10,7 +10,7 @@ export async function getProviderInventory( ): Promise { const client = await getClient(); const t0 = performance.now(); - const response = await client.goose.GooseProvidersInventory({ providerIds }); + const response = await client.goose.GooseProvidersList({ providerIds }); perfLog( `[perf:inventory] getProviderInventory done in ${(performance.now() - t0).toFixed(1)}ms (n=${response.entries.length})`, ); diff --git a/ui/goose2/src/shared/api/acpApi.ts b/ui/goose2/src/shared/api/acpApi.ts index f5bf7060..4ae88d56 100644 --- a/ui/goose2/src/shared/api/acpApi.ts +++ b/ui/goose2/src/shared/api/acpApi.ts @@ -20,16 +20,25 @@ export interface AcpSessionInfo { } const DEPRECATED_PROVIDER_IDS = new Set(["claude-code", "codex", "gemini-cli"]); +const DEFAULT_PROVIDER: AcpProvider = { + id: "goose", + label: "Goose (Default)", +}; export async function listProviders(): Promise { const client = await getClient(); - const result = await client.goose.GooseProvidersList({}); - // biome-ignore lint/suspicious/noExplicitAny: ACP SDK types don't expose providers field - return (result as any).providers - .filter( - (p: { id: string; label: string }) => !DEPRECATED_PROVIDER_IDS.has(p.id), - ) - .map((p: { id: string; label: string }) => ({ id: p.id, label: p.label })); + const result = await client.goose.GooseProvidersList({ + providerIds: [], + }); + + const providers = result.entries + .filter((entry) => !DEPRECATED_PROVIDER_IDS.has(entry.providerId)) + .map((entry) => ({ + id: entry.providerId, + label: entry.providerName, + })); + + return [DEFAULT_PROVIDER, ...providers]; } export async function listSessions(): Promise { diff --git a/ui/goose2/tests/e2e/fixtures/tauri-mock.ts b/ui/goose2/tests/e2e/fixtures/tauri-mock.ts index e7788208..57d73369 100644 --- a/ui/goose2/tests/e2e/fixtures/tauri-mock.ts +++ b/ui/goose2/tests/e2e/fixtures/tauri-mock.ts @@ -126,8 +126,6 @@ export function buildInitScript(options?: { return jsonRpcResult(message.id, { stopReason: "end_turn" }); } case "_goose/providers/list": - return jsonRpcResult(message.id, { providers: [] }); - case "_goose/providers/inventory": return jsonRpcResult(message.id, { entries: [] }); case "_goose/providers/inventory/refresh": return jsonRpcResult(message.id, { started: [], skipped: [] }); diff --git a/ui/sdk/src/generated/client.gen.ts b/ui/sdk/src/generated/client.gen.ts index dc49801e..d482ca2b 100644 --- a/ui/sdk/src/generated/client.gen.ts +++ b/ui/sdk/src/generated/client.gen.ts @@ -34,10 +34,6 @@ import type { ExportSourceResponse, GetExtensionsRequest, GetExtensionsResponse, - GetProviderDetailsRequest, - GetProviderDetailsResponse, - GetProviderInventoryRequest, - GetProviderInventoryResponse, GetSessionExtensionsRequest, GetSessionExtensionsResponse, GetToolsRequest, @@ -76,8 +72,6 @@ import { zExportSessionResponse, zExportSourceResponse, zGetExtensionsResponse, - zGetProviderDetailsResponse, - zGetProviderInventoryResponse, zGetSessionExtensionsResponse, zGetToolsResponse, zImportSessionResponse, @@ -144,22 +138,6 @@ export class GooseExtClient { return zListProvidersResponse.parse(raw) as ListProvidersResponse; } - async GooseProvidersDetails( - params: GetProviderDetailsRequest, - ): Promise { - const raw = await this.conn.extMethod("_goose/providers/details", params); - return zGetProviderDetailsResponse.parse(raw) as GetProviderDetailsResponse; - } - - async GooseProvidersInventory( - params: GetProviderInventoryRequest, - ): Promise { - const raw = await this.conn.extMethod("_goose/providers/inventory", params); - return zGetProviderInventoryResponse.parse( - raw, - ) as GetProviderInventoryResponse; - } - async GooseProvidersInventoryRefresh( params: RefreshProviderInventoryRequest, ): Promise { diff --git a/ui/sdk/src/generated/index.ts b/ui/sdk/src/generated/index.ts index 201d8f1c..42ffa4b1 100644 --- a/ui/sdk/src/generated/index.ts +++ b/ui/sdk/src/generated/index.ts @@ -1,6 +1,6 @@ // This file is auto-generated by @hey-api/openapi-ts -export type { AddExtensionRequest, ArchiveSessionRequest, CheckSecretRequest, CheckSecretResponse, CreateSourceRequest, CreateSourceResponse, DeleteSessionRequest, DeleteSourceRequest, DictationConfigRequest, DictationConfigResponse, DictationDownloadProgress, DictationLocalModelStatus, DictationModelCancelRequest, DictationModelDeleteRequest, DictationModelDownloadProgressRequest, DictationModelDownloadProgressResponse, DictationModelDownloadRequest, DictationModelOption, DictationModelSelectRequest, DictationModelsListRequest, DictationModelsListResponse, DictationProviderStatusEntry, DictationTranscribeRequest, DictationTranscribeResponse, EmptyResponse, ExportSessionRequest, ExportSessionResponse, ExportSourceRequest, ExportSourceResponse, ExtRequest, ExtResponse, GetExtensionsRequest, GetExtensionsResponse, GetProviderDetailsRequest, GetProviderDetailsResponse, GetProviderInventoryRequest, GetProviderInventoryResponse, GetSessionExtensionsRequest, GetSessionExtensionsResponse, GetToolsRequest, GetToolsResponse, ImportSessionRequest, ImportSessionResponse, ImportSourcesRequest, ImportSourcesResponse, ListProvidersRequest, ListProvidersResponse, ListSourcesRequest, ListSourcesResponse, ModelEntry, ProviderConfigKey, ProviderDetailEntry, ProviderInventoryEntryDto, ProviderInventoryModelDto, ProviderListEntry, ReadConfigRequest, ReadConfigResponse, ReadResourceRequest, ReadResourceResponse, RefreshProviderInventoryRequest, RefreshProviderInventoryResponse, RefreshProviderInventorySkipDto, RefreshProviderInventorySkipReasonDto, RemoveConfigRequest, RemoveExtensionRequest, RemoveSecretRequest, SourceEntry, SourceType, UnarchiveSessionRequest, UpdateSourceRequest, UpdateSourceResponse, UpdateWorkingDirRequest, UpsertConfigRequest, UpsertSecretRequest } from './types.gen.js'; +export type { AddExtensionRequest, ArchiveSessionRequest, CheckSecretRequest, CheckSecretResponse, CreateSourceRequest, CreateSourceResponse, DeleteSessionRequest, DeleteSourceRequest, DictationConfigRequest, DictationConfigResponse, DictationDownloadProgress, DictationLocalModelStatus, DictationModelCancelRequest, DictationModelDeleteRequest, DictationModelDownloadProgressRequest, DictationModelDownloadProgressResponse, DictationModelDownloadRequest, DictationModelOption, DictationModelSelectRequest, DictationModelsListRequest, DictationModelsListResponse, DictationProviderStatusEntry, DictationTranscribeRequest, DictationTranscribeResponse, EmptyResponse, ExportSessionRequest, ExportSessionResponse, ExportSourceRequest, ExportSourceResponse, ExtRequest, ExtResponse, GetExtensionsRequest, GetExtensionsResponse, GetSessionExtensionsRequest, GetSessionExtensionsResponse, GetToolsRequest, GetToolsResponse, ImportSessionRequest, ImportSessionResponse, ImportSourcesRequest, ImportSourcesResponse, ListProvidersRequest, ListProvidersResponse, ListSourcesRequest, ListSourcesResponse, ProviderConfigKey, ProviderInventoryEntryDto, ProviderInventoryModelDto, ReadConfigRequest, ReadConfigResponse, ReadResourceRequest, ReadResourceResponse, RefreshProviderInventoryRequest, RefreshProviderInventoryResponse, RefreshProviderInventorySkipDto, RefreshProviderInventorySkipReasonDto, RemoveConfigRequest, RemoveExtensionRequest, RemoveSecretRequest, SourceEntry, SourceType, UnarchiveSessionRequest, UpdateSourceRequest, UpdateSourceResponse, UpdateWorkingDirRequest, UpsertConfigRequest, UpsertSecretRequest } from './types.gen.js'; export const GOOSE_EXT_METHODS = [ { @@ -48,16 +48,6 @@ export const GOOSE_EXT_METHODS = [ requestType: "ListProvidersRequest", responseType: "ListProvidersResponse", }, - { - method: "_goose/providers/details", - requestType: "GetProviderDetailsRequest", - responseType: "GetProviderDetailsResponse", - }, - { - method: "_goose/providers/inventory", - requestType: "GetProviderInventoryRequest", - responseType: "GetProviderInventoryResponse", - }, { method: "_goose/providers/inventory/refresh", requestType: "RefreshProviderInventoryRequest", diff --git a/ui/sdk/src/generated/types.gen.ts b/ui/sdk/src/generated/types.gen.ts index 74fec01a..4335c158 100644 --- a/ui/sdk/src/generated/types.gen.ts +++ b/ui/sdk/src/generated/types.gen.ts @@ -105,69 +105,9 @@ export type GetSessionExtensionsResponse = { }; /** - * List providers available through goose, including the config-default sentinel. + * List providers with setup metadata and the current model inventory snapshot. */ export type ListProvidersRequest = { - [key: string]: unknown; -}; - -/** - * Provider list response. - */ -export type ListProvidersResponse = { - providers: Array; -}; - -export type ProviderListEntry = { - id: string; - label: string; -}; - -/** - * List providers with full metadata (config keys, setup steps, etc.). - */ -export type GetProviderDetailsRequest = { - [key: string]: unknown; -}; - -/** - * Provider details response. - */ -export type GetProviderDetailsResponse = { - providers: Array; -}; - -export type ProviderDetailEntry = { - name: string; - displayName: string; - description: string; - defaultModel: string; - isConfigured: boolean; - providerType: string; - configKeys: Array; - setupSteps?: Array; - knownModels?: Array; -}; - -export type ProviderConfigKey = { - name: string; - required: boolean; - secret: boolean; - default?: string | null; - oauthFlow?: boolean; - deviceCodeFlow?: boolean; - primary?: boolean; -}; - -export type ModelEntry = { - name: string; - contextLimit: number; -}; - -/** - * Read per-provider inventory. Always returns immediately from stored state. - */ -export type GetProviderInventoryRequest = { /** * Only return entries for these providers. Empty means all. */ @@ -175,9 +115,9 @@ export type GetProviderInventoryRequest = { }; /** - * Provider inventory response. + * Provider list response. */ -export type GetProviderInventoryResponse = { +export type ListProvidersResponse = { entries: Array; }; @@ -193,10 +133,30 @@ export type ProviderInventoryEntryDto = { * Human-readable provider name. */ providerName: string; + /** + * Description of the provider's capabilities. + */ + description: string; + /** + * The default/recommended model for this provider. + */ + defaultModel: string; /** * Whether Goose has enough configuration to use this provider. */ configured: boolean; + /** + * Provider classification such as `Preferred`, `Builtin`, `Declarative`, or `Custom`. + */ + providerType: string; + /** + * Required configuration keys and setup metadata. + */ + configKeys: Array; + /** + * Step-by-step setup instructions, when present. + */ + setupSteps: Array; /** * Whether this provider supports background inventory refresh. */ @@ -231,6 +191,16 @@ export type ProviderInventoryEntryDto = { modelSelectionHint?: string | null; }; +export type ProviderConfigKey = { + name: string; + required: boolean; + secret: boolean; + default?: string | null; + oauthFlow?: boolean; + deviceCodeFlow?: boolean; + primary?: boolean; +}; + /** * A single model in provider inventory. */ @@ -648,14 +618,14 @@ export type DictationModelSelectRequest = { export type ExtRequest = { id: string; method: string; - params?: AddExtensionRequest | RemoveExtensionRequest | GetToolsRequest | ReadResourceRequest | UpdateWorkingDirRequest | DeleteSessionRequest | GetExtensionsRequest | GetSessionExtensionsRequest | ListProvidersRequest | GetProviderDetailsRequest | GetProviderInventoryRequest | RefreshProviderInventoryRequest | ReadConfigRequest | UpsertConfigRequest | RemoveConfigRequest | CheckSecretRequest | UpsertSecretRequest | RemoveSecretRequest | ExportSessionRequest | ImportSessionRequest | ArchiveSessionRequest | UnarchiveSessionRequest | CreateSourceRequest | ListSourcesRequest | UpdateSourceRequest | DeleteSourceRequest | ExportSourceRequest | ImportSourcesRequest | DictationTranscribeRequest | DictationConfigRequest | DictationModelsListRequest | DictationModelDownloadRequest | DictationModelDownloadProgressRequest | DictationModelCancelRequest | DictationModelDeleteRequest | DictationModelSelectRequest | { + params?: AddExtensionRequest | RemoveExtensionRequest | GetToolsRequest | ReadResourceRequest | UpdateWorkingDirRequest | DeleteSessionRequest | GetExtensionsRequest | GetSessionExtensionsRequest | ListProvidersRequest | RefreshProviderInventoryRequest | ReadConfigRequest | UpsertConfigRequest | RemoveConfigRequest | CheckSecretRequest | UpsertSecretRequest | RemoveSecretRequest | ExportSessionRequest | ImportSessionRequest | ArchiveSessionRequest | UnarchiveSessionRequest | CreateSourceRequest | ListSourcesRequest | UpdateSourceRequest | DeleteSourceRequest | ExportSourceRequest | ImportSourcesRequest | DictationTranscribeRequest | DictationConfigRequest | DictationModelsListRequest | DictationModelDownloadRequest | DictationModelDownloadProgressRequest | DictationModelCancelRequest | DictationModelDeleteRequest | DictationModelSelectRequest | { [key: string]: unknown; } | null; }; export type ExtResponse = { id: string; - result?: EmptyResponse | GetToolsResponse | ReadResourceResponse | GetExtensionsResponse | GetSessionExtensionsResponse | ListProvidersResponse | GetProviderDetailsResponse | GetProviderInventoryResponse | RefreshProviderInventoryResponse | ReadConfigResponse | CheckSecretResponse | ExportSessionResponse | ImportSessionResponse | CreateSourceResponse | ListSourcesResponse | UpdateSourceResponse | ExportSourceResponse | ImportSourcesResponse | DictationTranscribeResponse | DictationConfigResponse | DictationModelsListResponse | DictationModelDownloadProgressResponse | unknown; + result?: EmptyResponse | GetToolsResponse | ReadResourceResponse | GetExtensionsResponse | GetSessionExtensionsResponse | ListProvidersResponse | RefreshProviderInventoryResponse | ReadConfigResponse | CheckSecretResponse | ExportSessionResponse | ImportSessionResponse | CreateSourceResponse | ListSourcesResponse | UpdateSourceResponse | ExportSourceResponse | ImportSourcesResponse | DictationTranscribeResponse | DictationConfigResponse | DictationModelsListResponse | DictationModelDownloadProgressResponse | unknown; } | { error: { code: number; diff --git a/ui/sdk/src/generated/zod.gen.ts b/ui/sdk/src/generated/zod.gen.ts index 27e4ab08..6a1c364e 100644 --- a/ui/sdk/src/generated/zod.gen.ts +++ b/ui/sdk/src/generated/zod.gen.ts @@ -90,27 +90,12 @@ export const zGetSessionExtensionsResponse = z.object({ }); /** - * List providers available through goose, including the config-default sentinel. + * List providers with setup metadata and the current model inventory snapshot. */ -export const zListProvidersRequest = z.record(z.unknown()); - -export const zProviderListEntry = z.object({ - id: z.string(), - label: z.string() +export const zListProvidersRequest = z.object({ + providerIds: z.array(z.string()).optional().default([]) }); -/** - * Provider list response. - */ -export const zListProvidersResponse = z.object({ - providers: z.array(zProviderListEntry) -}); - -/** - * List providers with full metadata (config keys, setup steps, etc.). - */ -export const zGetProviderDetailsRequest = z.record(z.unknown()); - export const zProviderConfigKey = z.object({ name: z.string(), required: z.boolean(), @@ -124,37 +109,6 @@ export const zProviderConfigKey = z.object({ primary: z.boolean().optional().default(false) }); -export const zModelEntry = z.object({ - name: z.string(), - contextLimit: z.number().int().gte(0) -}); - -export const zProviderDetailEntry = z.object({ - name: z.string(), - displayName: z.string(), - description: z.string(), - defaultModel: z.string(), - isConfigured: z.boolean(), - providerType: z.string(), - configKeys: z.array(zProviderConfigKey), - setupSteps: z.array(z.string()).optional().default([]), - knownModels: z.array(zModelEntry).optional().default([]) -}); - -/** - * Provider details response. - */ -export const zGetProviderDetailsResponse = z.object({ - providers: z.array(zProviderDetailEntry) -}); - -/** - * Read per-provider inventory. Always returns immediately from stored state. - */ -export const zGetProviderInventoryRequest = z.object({ - providerIds: z.array(z.string()).optional().default([]) -}); - /** * A single model in provider inventory. */ @@ -182,7 +136,12 @@ export const zProviderInventoryModelDto = z.object({ export const zProviderInventoryEntryDto = z.object({ providerId: z.string(), providerName: z.string(), + description: z.string(), + defaultModel: z.string(), configured: z.boolean(), + providerType: z.string(), + configKeys: z.array(zProviderConfigKey), + setupSteps: z.array(z.string()), supportsRefresh: z.boolean(), refreshing: z.boolean(), models: z.array(zProviderInventoryModelDto), @@ -206,9 +165,9 @@ export const zProviderInventoryEntryDto = z.object({ }); /** - * Provider inventory response. + * Provider list response. */ -export const zGetProviderInventoryResponse = z.object({ +export const zListProvidersResponse = z.object({ entries: z.array(zProviderInventoryEntryDto) }); @@ -626,8 +585,6 @@ export const zExtRequest = z.object({ zGetExtensionsRequest, zGetSessionExtensionsRequest, zListProvidersRequest, - zGetProviderDetailsRequest, - zGetProviderInventoryRequest, zRefreshProviderInventoryRequest, zReadConfigRequest, zUpsertConfigRequest, @@ -672,8 +629,6 @@ export const zExtResponse = z.union([ zGetExtensionsResponse, zGetSessionExtensionsResponse, zListProvidersResponse, - zGetProviderDetailsResponse, - zGetProviderInventoryResponse, zRefreshProviderInventoryResponse, zReadConfigResponse, zCheckSecretResponse, diff --git a/ui/text/src/configure.tsx b/ui/text/src/configure.tsx index 5e2d0b36..2312ee36 100644 --- a/ui/text/src/configure.tsx +++ b/ui/text/src/configure.tsx @@ -1,6 +1,6 @@ import React, { useState, useEffect, useCallback } from "react"; import { Box, Text, useInput, useStdout } from "ink"; -import type { GooseClient, ProviderDetailEntry } from "@aaif/goose-sdk"; +import type { GooseClient, ProviderInventoryEntryDto } from "@aaif/goose-sdk"; import { CRANBERRY, TEAL, @@ -38,7 +38,7 @@ interface ConfigureProps { interface ModelSelectorProps { client: GooseClient; - provider: ProviderDetailEntry; + provider: ProviderInventoryEntryDto; height: number; onSelect: (model: string) => void; onBack: () => void; @@ -74,7 +74,7 @@ const ModelSelector = React.memo(function ModelSelector({ setLoading(true); setError(null); const resp = await client.goose.GooseProvidersModels({ - providerName: provider.name, + providerName: provider.providerId, }); if (!cancelled) { setModels(resp.models); @@ -96,7 +96,7 @@ const ModelSelector = React.memo(function ModelSelector({ cancelled = true; clearTimeout(timeoutId); }; - }, [client, provider.name, provider.defaultModel]); + }, [client, provider.providerId, provider.defaultModel]); const filtered = (() => { if (!searchQuery) return models; @@ -190,7 +190,7 @@ const ModelSelector = React.memo(function ModelSelector({ ◆ Select model ◆ - Loading models for {provider.displayName}… + Loading models for {provider.providerName}… @@ -235,7 +235,7 @@ const ModelSelector = React.memo(function ModelSelector({ ◆ Enter model name ◆ - Type a model identifier for {provider.displayName} + Type a model identifier for {provider.providerName} @@ -270,7 +270,7 @@ const ModelSelector = React.memo(function ModelSelector({ ◆ Select model ◆ - Choose a model for {provider.displayName} + Choose a model for {provider.providerName} {/* Search Bar */} @@ -359,8 +359,8 @@ export default function ConfigureScreen({ initialIntent, }: ConfigureProps) { const [phase, setPhase] = useState("loading"); - const [providers, setProviders] = useState([]); - const [selectedProvider, setSelectedProvider] = useState(null); + const [providers, setProviders] = useState([]); + const [selectedProvider, setSelectedProvider] = useState(null); const [errorMsg, setErrorMsg] = useState(""); const [spinIdx, setSpinIdx] = useState(0); const [fetchKey, setFetchKey] = useState(0); @@ -378,13 +378,13 @@ export default function ConfigureScreen({ (async () => { try { - const resp = await client.goose.GooseProvidersDetails({}); + const resp = await client.goose.GooseProvidersList({ providerIds: [] }); if (cancelled) return; - const sorted = [...resp.providers].sort((a, b) => { + const sorted = [...resp.entries].sort((a, b) => { const aP = a.providerType === "Preferred" ? 0 : 1; const bP = b.providerType === "Preferred" ? 0 : 1; if (aP !== bP) return aP - bP; - return a.displayName.localeCompare(b.displayName); + return a.providerName.localeCompare(b.providerName); }); setProviders(sorted); @@ -392,7 +392,7 @@ export default function ConfigureScreen({ try { const cfg = await client.goose.GooseConfigRead({ key: "GOOSE_PROVIDER" }); if (cancelled) return; - const current = sorted.find((p) => p.name === cfg.value); + const current = sorted.find((p) => p.providerId === cfg.value); if (current) { setSelectedProvider(current); setPendingConfigValues({}); @@ -419,7 +419,11 @@ export default function ConfigureScreen({ }, [client, fetchKey, initialIntent]); const applyProviderModel = useCallback( - async (provider: ProviderDetailEntry, model: string, configValues: Record) => { + async ( + provider: ProviderInventoryEntryDto, + model: string, + configValues: Record, + ) => { setPhase("saving"); try { for (const [key, value] of Object.entries(configValues)) { @@ -430,11 +434,14 @@ export default function ConfigureScreen({ await client.goose.GooseConfigUpsert({ key, value }); } } - await client.goose.GooseConfigUpsert({ key: "GOOSE_PROVIDER", value: provider.name }); + await client.goose.GooseConfigUpsert({ + key: "GOOSE_PROVIDER", + value: provider.providerId, + }); await client.goose.GooseConfigUpsert({ key: "GOOSE_MODEL", value: model }); await client.goose.GooseSessionProviderUpdate({ sessionId, - provider: provider.name, + provider: provider.providerId, model, }); onComplete(); @@ -449,12 +456,12 @@ export default function ConfigureScreen({ const [pendingConfigValues, setPendingConfigValues] = useState>({}); const handleProviderSelected = useCallback( - (provider: ProviderDetailEntry) => { + (provider: ProviderInventoryEntryDto) => { const keys = provider.configKeys.filter( (k) => k.required && !k.oauthFlow && !k.deviceCodeFlow, ); setSelectedProvider(provider); - if (keys.length > 0 && !provider.isConfigured) { + if (keys.length > 0 && !provider.configured) { setPhase("configure"); } else { setPendingConfigValues({}); diff --git a/ui/text/src/onboarding.tsx b/ui/text/src/onboarding.tsx index 28db370b..8c6c6093 100644 --- a/ui/text/src/onboarding.tsx +++ b/ui/text/src/onboarding.tsx @@ -1,7 +1,7 @@ import React, { useState, useEffect, useCallback } from "react"; import { Box, Text, useInput, useStdout } from "ink"; import { TextInput, PasswordInput } from '@inkjs/ui'; -import type { GooseClient, ProviderDetailEntry } from "@aaif/goose-sdk"; +import type { GooseClient, ProviderInventoryEntryDto } from "@aaif/goose-sdk"; import { CRANBERRY, TEAL, @@ -30,9 +30,9 @@ interface OnboardingProps { } export interface ProviderSelectorProps { - providers: ProviderDetailEntry[]; + providers: ProviderInventoryEntryDto[]; height: number; - onSelect: (provider: ProviderDetailEntry) => void; + onSelect: (provider: ProviderInventoryEntryDto) => void; title?: string; subtitle?: string; onBack?: () => void; @@ -49,8 +49,8 @@ export const ProviderSelector = React.memo(function ProviderSelector({ providers const q = searchQuery.toLowerCase(); return providers.filter( (p) => - p.displayName.toLowerCase().includes(q) || - p.name.toLowerCase().includes(q), + p.providerName.toLowerCase().includes(q) || + p.providerId.toLowerCase().includes(q), ); })(); @@ -151,7 +151,11 @@ export const ProviderSelector = React.memo(function ProviderSelector({ providers }); // Create grid of provider cards - const renderProviderCard = (provider: ProviderDetailEntry, _index: number, isSelected: boolean) => { + const renderProviderCard = ( + provider: ProviderInventoryEntryDto, + _index: number, + isSelected: boolean, + ) => { const cardBorder = isSelected ? "double" : "single"; const cardBorderColor = isSelected ? GOLD : RULE_COLOR; const textColor = isSelected ? TEXT_PRIMARY : TEXT_SECONDARY; @@ -166,7 +170,7 @@ export const ProviderSelector = React.memo(function ProviderSelector({ providers return ( - {provider.displayName} + {provider.providerName} {provider.providerType === "Preferred" && ( )} - {provider.isConfigured && ( + {provider.configured && ( )} @@ -194,7 +198,7 @@ export const ProviderSelector = React.memo(function ProviderSelector({ providers - {provider.name} + {provider.providerId} {provider.description && ( @@ -306,7 +310,7 @@ export const ProviderSelector = React.memo(function ProviderSelector({ providers }); export interface ProviderConfiguratorProps { - provider: ProviderDetailEntry; + provider: ProviderInventoryEntryDto; height: number; onComplete: (values: Record) => void; onBack: () => void; @@ -383,7 +387,7 @@ export const ProviderConfigurator = React.memo(function ProviderConfigurator({ p {/* Header */} - ◆ Configure {provider.displayName} ◆ + ◆ Configure {provider.providerName} ◆ {provider.description && ( @@ -473,7 +477,7 @@ export const ProviderConfigurator = React.memo(function ProviderConfigurator({ p }); interface SuccessScreenProps { - provider: ProviderDetailEntry | null; + provider: ProviderInventoryEntryDto | null; height: number; } @@ -501,7 +505,7 @@ const SuccessScreen = React.memo(function SuccessScreen({ provider, height }: Su {provider && ( - Connected to {provider.displayName} + Connected to {provider.providerName} )} @@ -517,9 +521,9 @@ export default function Onboarding({ onComplete, }: OnboardingProps) { const [phase, setPhase] = useState("loading"); - const [providers, setProviders] = useState([]); + const [providers, setProviders] = useState([]); const [selectedProvider, setSelectedProvider] = - useState(null); + useState(null); const [errorMsg, setErrorMsg] = useState(""); const [spinIdx, setSpinIdx] = useState(0); const [fetchKey, setFetchKey] = useState(0); @@ -535,12 +539,12 @@ export default function Onboarding({ useEffect(() => { (async () => { try { - const resp = await client.goose.GooseProvidersDetails({}); - const sorted = [...resp.providers].sort((a, b) => { + const resp = await client.goose.GooseProvidersList({ providerIds: [] }); + const sorted = [...resp.entries].sort((a, b) => { const aP = a.providerType === "Preferred" ? 0 : 1; const bP = b.providerType === "Preferred" ? 0 : 1; if (aP !== bP) return aP - bP; - return a.displayName.localeCompare(b.displayName); + return a.providerName.localeCompare(b.providerName); }); setProviders(sorted); setPhase("select_provider"); @@ -552,7 +556,7 @@ export default function Onboarding({ }, [client, fetchKey]); const saveProvider = useCallback( - async (provider: ProviderDetailEntry, values: Record) => { + async (provider: ProviderInventoryEntryDto, values: Record) => { setPhase("saving"); try { for (const [key, value] of Object.entries(values)) { @@ -565,7 +569,7 @@ export default function Onboarding({ } await client.goose.GooseConfigUpsert({ key: "GOOSE_PROVIDER", - value: provider.name, + value: provider.providerId, }); await client.goose.GooseConfigUpsert({ key: "GOOSE_MODEL", @@ -582,7 +586,7 @@ export default function Onboarding({ ); const confirmProvider = useCallback( - (provider: ProviderDetailEntry) => { + (provider: ProviderInventoryEntryDto) => { const keys = provider.configKeys.filter( (k) => k.required && !k.oauthFlow && !k.deviceCodeFlow, );