Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions crates/goose-server/src/routes/config_management.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ pub struct UpsertConfigQuery {
pub is_secret: bool,
}

#[derive(Deserialize, ToSchema)]
#[derive(Deserialize, Serialize, ToSchema)]
pub struct ConfigKeyQuery {
pub key: String,
pub is_secret: bool,
Expand Down Expand Up @@ -123,9 +123,9 @@ pub async fn remove_config(
}

#[utoipa::path(
get,
post, // Change from get to post
path = "/config/read",
request_body = ConfigKeyQuery,
request_body = ConfigKeyQuery, // Switch back to request_body
responses(
(status = 200, description = "Configuration value retrieved successfully", body = Value),
(status = 404, description = "Configuration key not found")
Expand Down
2 changes: 1 addition & 1 deletion ui/desktop/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@
}
},
"/config/read": {
"get": {
"post": {
"tags": [
"super::routes::config_management"
],
Expand Down
2 changes: 1 addition & 1 deletion ui/desktop/src/api/sdk.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ export const providers = <ThrowOnError extends boolean = false>(options?: Option
};

export const readConfig = <ThrowOnError extends boolean = false>(options: Options<ReadConfigData, ThrowOnError>) => {
return (options.client ?? _heyApiClient).get<unknown, unknown, ThrowOnError>({
return (options.client ?? _heyApiClient).post<unknown, unknown, ThrowOnError>({
url: '/config/read',
...options,
headers: {
Expand Down
1 change: 0 additions & 1 deletion ui/desktop/src/components/ConfigContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,6 @@ export const ConfigProvider: React.FC<ConfigProviderProps> = ({ children }) => {
};

const upsert = async (key: string, value: unknown, isSecret: boolean = false) => {
console.log('trying to upsert', key, value, isSecret);
const query: UpsertConfigQuery = {
key: key,
value: value,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React, { useEffect, useMemo } from 'react';
import React, { useEffect, useMemo, useState } from 'react';
import { Input } from '../../../../../ui/input';
import { useConfig } from '../../../../../ConfigContext'; // Adjust this import path as needed

interface DefaultProviderSetupFormProps {
configValues: Record<string, any>;
Expand All @@ -13,29 +14,59 @@ export default function DefaultProviderSetupForm({
provider,
}: DefaultProviderSetupFormProps) {
const parameters = provider.metadata.config_keys || [];
const [isLoading, setIsLoading] = useState(true);
const { read } = useConfig();

// Initialize default values when the component mounts or provider changes
// Initialize values when the component mounts or provider changes
useEffect(() => {
const defaultValues = {};
parameters.forEach((parameter) => {
if (
parameter.required &&
parameter.default !== undefined &&
parameter.default !== null &&
!configValues[parameter.name]
) {
defaultValues[parameter.name] = parameter.default;
const loadConfigValues = async () => {
setIsLoading(true);
const newValues = { ...configValues };

// Try to load actual values from config for each parameter that is not secret
for (const parameter of parameters) {
if (parameter.required && !parameter.secret) {
try {
// Check if there's a stored value in the config system
const configKey = `${parameter.name}`;
const configResponse = await read(configKey, parameter.secret || false);
console.log('configResponse', configResponse);

if (configResponse) {
// Use the value from the config provider
newValues[parameter.name] = configResponse;
} else if (
parameter.default !== undefined &&
parameter.default !== null &&
!configValues[parameter.name]
) {
// Fall back to default value if no config value exists
newValues[parameter.name] = parameter.default;
}
} catch (error) {
console.error(`Failed to load config for ${parameter.name}:`, error);
// Fall back to default if read operation fails
if (
parameter.default !== undefined &&
parameter.default !== null &&
!configValues[parameter.name]
) {
newValues[parameter.name] = parameter.default;
}
}
}
}
});

// Only update if there are default values to add
if (Object.keys(defaultValues).length > 0) {
// Update state with loaded values
setConfigValues((prev) => ({
...prev,
...defaultValues,
...newValues,
}));
}
}, [provider.name, parameters, setConfigValues, configValues]);
setIsLoading(false);
};

loadConfigValues();
}, [provider.name, parameters, setConfigValues, read]);

// Filter parameters to only show required ones
const requiredParameters = useMemo(() => {
Expand All @@ -53,6 +84,10 @@ export default function DefaultProviderSetupForm({
return parameter.name.toUpperCase();
};

if (isLoading) {
return <div className="text-center py-4">Loading configuration values...</div>;
}

return (
<div className="mt-4 space-y-4">
{requiredParameters.length === 0 ? (
Expand Down
Loading