fix: V2 settings carry extensions over during model change (#1944)
This commit is contained in:
+6
-27
@@ -28,14 +28,8 @@ import ProviderSettings from './components/settings_v2/providers/ProviderSetting
|
|||||||
import { useChat } from './hooks/useChat';
|
import { useChat } from './hooks/useChat';
|
||||||
|
|
||||||
import 'react-toastify/dist/ReactToastify.css';
|
import 'react-toastify/dist/ReactToastify.css';
|
||||||
import { FixedExtensionEntry, useConfig } from './components/ConfigContext';
|
import { useConfig } from './components/ConfigContext';
|
||||||
import {
|
import { addExtensionFromDeepLink as addExtensionFromDeepLinkV2 } from './components/settings_v2/extensions';
|
||||||
initializeBuiltInExtensions,
|
|
||||||
syncBuiltInExtensions,
|
|
||||||
addExtensionFromDeepLink as addExtensionFromDeepLinkV2,
|
|
||||||
addToAgentOnStartup,
|
|
||||||
} from './components/settings_v2/extensions';
|
|
||||||
import { extractExtensionConfig } from './components/settings_v2/extensions/utils';
|
|
||||||
|
|
||||||
// Views and their options
|
// Views and their options
|
||||||
export type View =
|
export type View =
|
||||||
@@ -105,25 +99,10 @@ export default function App() {
|
|||||||
setView('chat');
|
setView('chat');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await initializeSystem(provider, model);
|
await initializeSystem(provider, model, {
|
||||||
|
getExtensions,
|
||||||
// Initialize or sync built-in extensions into config.yaml
|
addExtension,
|
||||||
let refreshedExtensions = await getExtensions(true);
|
});
|
||||||
|
|
||||||
if (refreshedExtensions.length === 0) {
|
|
||||||
await initializeBuiltInExtensions(addExtension);
|
|
||||||
refreshedExtensions = await getExtensions(true);
|
|
||||||
} else {
|
|
||||||
await syncBuiltInExtensions(refreshedExtensions, addExtension);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add enabled extensions to agent
|
|
||||||
for (const extensionEntry of refreshedExtensions) {
|
|
||||||
if (extensionEntry.enabled) {
|
|
||||||
const extensionConfig = extractExtensionConfig(extensionEntry);
|
|
||||||
await addToAgentOnStartup({ addToConfig: addExtension, extensionConfig });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error in alpha initialization:', error);
|
console.error('Error in alpha initialization:', error);
|
||||||
setFatalError(`System initialization error: ${error.message || 'Unknown error'}`);
|
setFatalError(`System initialization error: ${error.message || 'Unknown error'}`);
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ import type {
|
|||||||
} from '../api/types.gen';
|
} from '../api/types.gen';
|
||||||
import { removeShims } from './settings_v2/extensions/utils';
|
import { removeShims } from './settings_v2/extensions/utils';
|
||||||
|
|
||||||
|
export type { ExtensionConfig } from '../api/types.gen';
|
||||||
|
|
||||||
// Define a local version that matches the structure of the imported one
|
// Define a local version that matches the structure of the imported one
|
||||||
export type FixedExtensionEntry = ExtensionConfig & {
|
export type FixedExtensionEntry = ExtensionConfig & {
|
||||||
enabled: boolean;
|
enabled: boolean;
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import { initializeAgent } from '../../../agent/index';
|
import { initializeSystem } from '../../../utils/providerUtils';
|
||||||
import { toastError, toastSuccess } from '../../../toasts';
|
import { toastError, toastSuccess } from '../../../toasts';
|
||||||
import { ProviderDetails } from '@/src/api';
|
import { ProviderDetails } from '@/src/api';
|
||||||
import { getProviderMetadata } from './modelInterface';
|
import { getProviderMetadata } from './modelInterface';
|
||||||
import { ProviderMetadata } from '../../../api';
|
import { ProviderMetadata } from '../../../api';
|
||||||
|
import type { ExtensionConfig, FixedExtensionEntry } from '../../ConfigContext';
|
||||||
|
|
||||||
// titles
|
// titles
|
||||||
const CHANGE_MODEL_TOAST_TITLE = 'Model selected';
|
const CHANGE_MODEL_TOAST_TITLE = 'Model selected';
|
||||||
@@ -23,12 +24,23 @@ interface changeModelProps {
|
|||||||
model: string;
|
model: string;
|
||||||
provider: string;
|
provider: string;
|
||||||
writeToConfig: (key: string, value: unknown, is_secret: boolean) => Promise<void>;
|
writeToConfig: (key: string, value: unknown, is_secret: boolean) => Promise<void>;
|
||||||
|
getExtensions?: (b: boolean) => Promise<FixedExtensionEntry[]>;
|
||||||
|
addExtension?: (name: string, config: ExtensionConfig, enabled: boolean) => Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: error handling
|
// TODO: error handling
|
||||||
export async function changeModel({ model, provider, writeToConfig }: changeModelProps) {
|
export async function changeModel({
|
||||||
|
model,
|
||||||
|
provider,
|
||||||
|
writeToConfig,
|
||||||
|
getExtensions,
|
||||||
|
addExtension,
|
||||||
|
}: changeModelProps) {
|
||||||
try {
|
try {
|
||||||
await initializeAgent({ model: model, provider: provider });
|
await initializeSystem(provider, model, {
|
||||||
|
getExtensions,
|
||||||
|
addExtension,
|
||||||
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`Failed to change model at agent step -- ${model} ${provider}`);
|
console.error(`Failed to change model at agent step -- ${model} ${provider}`);
|
||||||
toastError({
|
toastError({
|
||||||
@@ -61,49 +73,6 @@ export async function changeModel({ model, provider, writeToConfig }: changeMode
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface startAgentFromConfigProps {
|
|
||||||
readFromConfig: (key: string, is_secret: boolean) => Promise<unknown>;
|
|
||||||
}
|
|
||||||
|
|
||||||
// starts agent with the values for GOOSE_PROVIDER and GOOSE_MODEL that are in the config
|
|
||||||
export async function startAgentFromConfig({ readFromConfig }: startAgentFromConfigProps) {
|
|
||||||
let modelProvider: { model: string; provider: string };
|
|
||||||
|
|
||||||
// read from config
|
|
||||||
try {
|
|
||||||
modelProvider = await getCurrentModelAndProvider({ readFromConfig: readFromConfig });
|
|
||||||
} catch (error) {
|
|
||||||
toastError({
|
|
||||||
title: START_AGENT_TITLE,
|
|
||||||
msg: CONFIG_READ_MODEL_ERROR_MSG,
|
|
||||||
traceback: error,
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const model = modelProvider.model;
|
|
||||||
const provider = modelProvider.provider;
|
|
||||||
|
|
||||||
console.log(`Starting agent with GOOSE_MODEL=${model} and GOOSE_PROVIDER=${provider}`);
|
|
||||||
|
|
||||||
try {
|
|
||||||
await initializeAgent({ model: model, provider: provider });
|
|
||||||
} catch (error) {
|
|
||||||
console.error(`Failed to change model at agent step -- ${model} ${provider}`);
|
|
||||||
toastError({
|
|
||||||
title: CHANGE_MODEL_TOAST_TITLE,
|
|
||||||
msg: SWITCH_MODEL_AGENT_ERROR_MSG,
|
|
||||||
traceback: error,
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
} finally {
|
|
||||||
toastSuccess({
|
|
||||||
title: CHANGE_MODEL_TOAST_TITLE,
|
|
||||||
msg: `${INITIALIZE_SYSTEM_WITH_MODEL_SUCCESS_MSG} with ${model} from ${provider}`,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
interface getCurrentModelAndProviderProps {
|
interface getCurrentModelAndProviderProps {
|
||||||
readFromConfig: (key: string, is_secret: boolean) => Promise<unknown>;
|
readFromConfig: (key: string, is_secret: boolean) => Promise<unknown>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import { QUICKSTART_GUIDE_URL } from '../../providers/modal/constants';
|
|||||||
import { Input } from '../../../ui/input';
|
import { Input } from '../../../ui/input';
|
||||||
import { Select } from '../../../ui/Select';
|
import { Select } from '../../../ui/Select';
|
||||||
import { useConfig } from '../../../ConfigContext';
|
import { useConfig } from '../../../ConfigContext';
|
||||||
import { changeModel as switchModel } from '../index';
|
import { changeModel } from '../index';
|
||||||
import type { View } from '../../../../App';
|
import type { View } from '../../../../App';
|
||||||
|
|
||||||
const ModalButtons = ({ onSubmit, onCancel, isValid, validationErrors }) => (
|
const ModalButtons = ({ onSubmit, onCancel, isValid, validationErrors }) => (
|
||||||
@@ -36,7 +36,7 @@ type AddModelModalProps = {
|
|||||||
setView: (view: View) => void;
|
setView: (view: View) => void;
|
||||||
};
|
};
|
||||||
export const AddModelModal = ({ onClose, setView }: AddModelModalProps) => {
|
export const AddModelModal = ({ onClose, setView }: AddModelModalProps) => {
|
||||||
const { getProviders, upsert } = useConfig();
|
const { getProviders, upsert, getExtensions, addExtension } = useConfig();
|
||||||
const [providerOptions, setProviderOptions] = useState([]);
|
const [providerOptions, setProviderOptions] = useState([]);
|
||||||
const [modelOptions, setModelOptions] = useState([]);
|
const [modelOptions, setModelOptions] = useState([]);
|
||||||
const [provider, setProvider] = useState<string | null>(null);
|
const [provider, setProvider] = useState<string | null>(null);
|
||||||
@@ -72,12 +72,18 @@ export const AddModelModal = ({ onClose, setView }: AddModelModalProps) => {
|
|||||||
return formIsValid;
|
return formIsValid;
|
||||||
};
|
};
|
||||||
|
|
||||||
const changeModel = async () => {
|
const onSubmit = async () => {
|
||||||
setAttemptedSubmit(true);
|
setAttemptedSubmit(true);
|
||||||
const isFormValid = validateForm();
|
const isFormValid = validateForm();
|
||||||
|
|
||||||
if (isFormValid) {
|
if (isFormValid) {
|
||||||
await switchModel({ model: model, provider: provider, writeToConfig: upsert });
|
await changeModel({
|
||||||
|
model: model,
|
||||||
|
provider: provider,
|
||||||
|
writeToConfig: upsert,
|
||||||
|
getExtensions,
|
||||||
|
addExtension,
|
||||||
|
});
|
||||||
onClose();
|
onClose();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -159,7 +165,7 @@ export const AddModelModal = ({ onClose, setView }: AddModelModalProps) => {
|
|||||||
onClose={onClose}
|
onClose={onClose}
|
||||||
footer={
|
footer={
|
||||||
<ModalButtons
|
<ModalButtons
|
||||||
onSubmit={changeModel}
|
onSubmit={onSubmit}
|
||||||
onCancel={onClose}
|
onCancel={onClose}
|
||||||
isValid={isValid}
|
isValid={isValid}
|
||||||
validationErrors={validationErrors}
|
validationErrors={validationErrors}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import BackButton from '../../ui/BackButton';
|
|||||||
import ProviderGrid from './ProviderGrid';
|
import ProviderGrid from './ProviderGrid';
|
||||||
import { useConfig } from '../../ConfigContext';
|
import { useConfig } from '../../ConfigContext';
|
||||||
import { ProviderDetails } from '../../../api/types.gen';
|
import { ProviderDetails } from '../../../api/types.gen';
|
||||||
import { initializeAgent } from '../../../agent/';
|
import { initializeSystem } from '../../../utils/providerUtils';
|
||||||
import WelcomeGooseLogo from '../../WelcomeGooseLogo';
|
import WelcomeGooseLogo from '../../WelcomeGooseLogo';
|
||||||
|
|
||||||
interface ProviderSettingsProps {
|
interface ProviderSettingsProps {
|
||||||
@@ -13,7 +13,7 @@ interface ProviderSettingsProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default function ProviderSettings({ onClose, isOnboarding }: ProviderSettingsProps) {
|
export default function ProviderSettings({ onClose, isOnboarding }: ProviderSettingsProps) {
|
||||||
const { getProviders, upsert } = useConfig();
|
const { getProviders, upsert, getExtensions, addExtension } = useConfig();
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
const [providers, setProviders] = useState<ProviderDetails[]>([]);
|
const [providers, setProviders] = useState<ProviderDetails[]>([]);
|
||||||
const initialLoadDone = useRef(false);
|
const initialLoadDone = useRef(false);
|
||||||
@@ -69,13 +69,16 @@ export default function ProviderSettings({ onClose, isOnboarding }: ProviderSett
|
|||||||
);
|
);
|
||||||
|
|
||||||
// initialize agent
|
// initialize agent
|
||||||
await initializeAgent({ provider: provider.name, model });
|
await initializeSystem(provider.name, model, {
|
||||||
|
getExtensions,
|
||||||
|
addExtension,
|
||||||
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`Failed to initialize with provider ${provider_name}:`, error);
|
console.error(`Failed to initialize with provider ${provider_name}:`, error);
|
||||||
}
|
}
|
||||||
onClose();
|
onClose();
|
||||||
},
|
},
|
||||||
[initializeAgent, onClose, upsert]
|
[onClose, upsert]
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -4,6 +4,13 @@ import { GOOSE_PROVIDER, GOOSE_MODEL } from '../env_vars';
|
|||||||
import { Model } from '../components/settings/models/ModelContext';
|
import { Model } from '../components/settings/models/ModelContext';
|
||||||
import { gooseModels } from '../components/settings/models/GooseModels';
|
import { gooseModels } from '../components/settings/models/GooseModels';
|
||||||
import { initializeAgent } from '../agent';
|
import { initializeAgent } from '../agent';
|
||||||
|
import {
|
||||||
|
initializeBuiltInExtensions,
|
||||||
|
syncBuiltInExtensions,
|
||||||
|
addToAgentOnStartup,
|
||||||
|
} from '../components/settings_v2/extensions';
|
||||||
|
import { extractExtensionConfig } from '../components/settings_v2/extensions/utils';
|
||||||
|
import type { ExtensionConfig, FixedExtensionEntry } from '../components/ConfigContext';
|
||||||
|
|
||||||
export function getStoredProvider(config: any): string | null {
|
export function getStoredProvider(config: any): string | null {
|
||||||
return config.GOOSE_PROVIDER || localStorage.getItem(GOOSE_PROVIDER);
|
return config.GOOSE_PROVIDER || localStorage.getItem(GOOSE_PROVIDER);
|
||||||
@@ -65,7 +72,14 @@ You can also validate your output after you have generated it to ensure it meets
|
|||||||
There may be (but not always) some tools mentioned in the instructions which you can check are available to this instance of goose (and try to help the user if they are not or find alternatives).
|
There may be (but not always) some tools mentioned in the instructions which you can check are available to this instance of goose (and try to help the user if they are not or find alternatives).
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const initializeSystem = async (provider: string, model: string) => {
|
export const initializeSystem = async (
|
||||||
|
provider: string,
|
||||||
|
model: string,
|
||||||
|
options?: {
|
||||||
|
getExtensions?: (b: boolean) => Promise<FixedExtensionEntry[]>;
|
||||||
|
addExtension?: (name: string, config: ExtensionConfig, enabled: boolean) => Promise<void>;
|
||||||
|
}
|
||||||
|
) => {
|
||||||
try {
|
try {
|
||||||
console.log('initializing agent with provider', provider, 'model', model);
|
console.log('initializing agent with provider', provider, 'model', model);
|
||||||
await initializeAgent({ provider, model });
|
await initializeAgent({ provider, model });
|
||||||
@@ -104,11 +118,30 @@ export const initializeSystem = async (provider: string, model: string) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This will go away after the release of settings v2 as we now handle this via
|
if (process.env.ALPHA) {
|
||||||
//
|
if (!options?.getExtensions || !options?.addExtension) {
|
||||||
// initializeBuiltInExtensions
|
console.warn('Extension helpers not provided in alpha mode');
|
||||||
// syncBuiltInExtensions
|
return;
|
||||||
if (!process.env.ALPHA) {
|
}
|
||||||
|
|
||||||
|
// Initialize or sync built-in extensions into config.yaml
|
||||||
|
let refreshedExtensions = await options.getExtensions(false);
|
||||||
|
|
||||||
|
if (refreshedExtensions.length === 0) {
|
||||||
|
await initializeBuiltInExtensions(options.addExtension);
|
||||||
|
refreshedExtensions = await options.getExtensions(false);
|
||||||
|
} else {
|
||||||
|
await syncBuiltInExtensions(refreshedExtensions, options.addExtension);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add enabled extensions to agent
|
||||||
|
for (const extensionEntry of refreshedExtensions) {
|
||||||
|
if (extensionEntry.enabled) {
|
||||||
|
const extensionConfig = extractExtensionConfig(extensionEntry);
|
||||||
|
await addToAgentOnStartup({ addToConfig: options.addExtension, extensionConfig });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
loadAndAddStoredExtensions().catch((error) => {
|
loadAndAddStoredExtensions().catch((error) => {
|
||||||
console.error('Failed to load and add stored extension configs:', error);
|
console.error('Failed to load and add stored extension configs:', error);
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user