-
Notifications
You must be signed in to change notification settings - Fork 2.4k
alexhancock/remove-settings-v1 #2744
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
f19cafc
cleanup: remove settings v1
alexhancock 38f491e
cleanup: move settings_v2 -> settings
alexhancock 2fa7062
fix react electron property not recognized
zanesq 5f3e32e
fix e2e tests after upstream ui changes and lint check
zanesq ced612d
task: addressing PR feedback
alexhancock d508ed5
feat: react context provider for model and provider
alexhancock 7a45e70
fix: adjust ModelsBottomBar to not need a useEffect with no deps to g…
alexhancock File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,190 @@ | ||
| import React, { createContext, useContext, useState, useEffect, useMemo, useCallback } from 'react'; | ||
| import { initializeAgent } from '../agent'; | ||
| import { toastError, toastSuccess } from '../toasts'; | ||
| import Model, { getProviderMetadata } from './settings/models/modelInterface'; | ||
| import { ProviderMetadata } from '../api'; | ||
| import { useConfig } from './ConfigContext'; | ||
|
|
||
| // titles | ||
| export const UNKNOWN_PROVIDER_TITLE = 'Provider name lookup'; | ||
|
|
||
| // errors | ||
| const CHANGE_MODEL_ERROR_TITLE = 'Change failed'; | ||
| const SWITCH_MODEL_AGENT_ERROR_MSG = | ||
| 'Failed to start agent with selected model -- please try again'; | ||
| const CONFIG_UPDATE_ERROR_MSG = 'Failed to update configuration settings -- please try again'; | ||
| export const UNKNOWN_PROVIDER_MSG = 'Unknown provider in config -- please inspect your config.yaml'; | ||
|
|
||
| // success | ||
| const CHANGE_MODEL_TOAST_TITLE = 'Model changed'; | ||
| const SWITCH_MODEL_SUCCESS_MSG = 'Successfully switched models'; | ||
|
|
||
| interface ModelAndProviderContextType { | ||
| currentModel: string | null; | ||
| currentProvider: string | null; | ||
| changeModel: (model: Model) => Promise<void>; | ||
| getCurrentModelAndProvider: () => Promise<{ model: string; provider: string }>; | ||
| getFallbackModelAndProvider: () => Promise<{ model: string; provider: string }>; | ||
| getCurrentModelAndProviderForDisplay: () => Promise<{ model: string; provider: string }>; | ||
| refreshCurrentModelAndProvider: () => Promise<void>; | ||
| } | ||
|
|
||
| interface ModelAndProviderProviderProps { | ||
| children: React.ReactNode; | ||
| } | ||
|
|
||
| const ModelAndProviderContext = createContext<ModelAndProviderContextType | undefined>(undefined); | ||
|
|
||
| export const ModelAndProviderProvider: React.FC<ModelAndProviderProviderProps> = ({ children }) => { | ||
| const [currentModel, setCurrentModel] = useState<string | null>(null); | ||
| const [currentProvider, setCurrentProvider] = useState<string | null>(null); | ||
| const { read, upsert, getProviders } = useConfig(); | ||
|
|
||
| const changeModel = useCallback( | ||
| async (model: Model) => { | ||
| const modelName = model.name; | ||
| const providerName = model.provider; | ||
| try { | ||
| await initializeAgent({ | ||
| model: model.name, | ||
| provider: model.provider, | ||
| }); | ||
| } catch (error) { | ||
| console.error(`Failed to change model at agent step -- ${modelName} ${providerName}`); | ||
| toastError({ | ||
| title: CHANGE_MODEL_ERROR_TITLE, | ||
| msg: SWITCH_MODEL_AGENT_ERROR_MSG, | ||
| traceback: error instanceof Error ? error.message : String(error), | ||
| }); | ||
| // don't write to config | ||
| return; | ||
| } | ||
|
|
||
| try { | ||
| await upsert('GOOSE_PROVIDER', providerName, false); | ||
| await upsert('GOOSE_MODEL', modelName, false); | ||
|
|
||
| // Update local state | ||
| setCurrentProvider(providerName); | ||
| setCurrentModel(modelName); | ||
| } catch (error) { | ||
| console.error(`Failed to change model at config step -- ${modelName} ${providerName}}`); | ||
| toastError({ | ||
| title: CHANGE_MODEL_ERROR_TITLE, | ||
| msg: CONFIG_UPDATE_ERROR_MSG, | ||
| traceback: error instanceof Error ? error.message : String(error), | ||
| }); | ||
| // agent and config will be out of sync at this point | ||
| // TODO: reset agent to use current config settings | ||
| } finally { | ||
| // show toast | ||
| toastSuccess({ | ||
| title: CHANGE_MODEL_TOAST_TITLE, | ||
| msg: `${SWITCH_MODEL_SUCCESS_MSG} -- using ${model.alias ?? modelName} from ${model.subtext ?? providerName}`, | ||
| }); | ||
| } | ||
| }, | ||
| [upsert] | ||
| ); | ||
|
|
||
| const getFallbackModelAndProvider = useCallback(async () => { | ||
| const provider = window.appConfig.get('GOOSE_DEFAULT_PROVIDER') as string; | ||
| const model = window.appConfig.get('GOOSE_DEFAULT_MODEL') as string; | ||
| if (provider && model) { | ||
| try { | ||
| await upsert('GOOSE_MODEL', model, false); | ||
| await upsert('GOOSE_PROVIDER', provider, false); | ||
| } catch (error) { | ||
| console.error('[getFallbackModelAndProvider] Failed to write to config', error); | ||
| } | ||
| } | ||
| return { model: model, provider: provider }; | ||
| }, [upsert]); | ||
|
|
||
| const getCurrentModelAndProvider = useCallback(async () => { | ||
| let model: string; | ||
| let provider: string; | ||
|
|
||
| // read from config | ||
| try { | ||
| model = (await read('GOOSE_MODEL', false)) as string; | ||
| provider = (await read('GOOSE_PROVIDER', false)) as string; | ||
| } catch (error) { | ||
| console.error(`Failed to read GOOSE_MODEL or GOOSE_PROVIDER from config`); | ||
| throw error; | ||
| } | ||
| if (!model || !provider) { | ||
| console.log('[getCurrentModelAndProvider] Checking app environment as fallback'); | ||
| return getFallbackModelAndProvider(); | ||
| } | ||
| return { model: model, provider: provider }; | ||
| }, [read, getFallbackModelAndProvider]); | ||
|
|
||
| const getCurrentModelAndProviderForDisplay = useCallback(async () => { | ||
| const modelProvider = await getCurrentModelAndProvider(); | ||
| const gooseModel = modelProvider.model; | ||
| const gooseProvider = modelProvider.provider; | ||
|
|
||
| // lookup display name | ||
| let metadata: ProviderMetadata; | ||
|
|
||
| try { | ||
| metadata = await getProviderMetadata(String(gooseProvider), getProviders); | ||
| } catch (error) { | ||
| return { model: gooseModel, provider: gooseProvider }; | ||
| } | ||
| const providerDisplayName = metadata.display_name; | ||
|
|
||
| return { model: gooseModel, provider: providerDisplayName }; | ||
| }, [getCurrentModelAndProvider, getProviders]); | ||
|
|
||
| const refreshCurrentModelAndProvider = useCallback(async () => { | ||
| try { | ||
| const { model, provider } = await getCurrentModelAndProvider(); | ||
| setCurrentModel(model); | ||
| setCurrentProvider(provider); | ||
| } catch (error) { | ||
| console.error('Failed to refresh current model and provider:', error); | ||
| } | ||
| }, [getCurrentModelAndProvider]); | ||
|
|
||
| // Load initial model and provider on mount | ||
| useEffect(() => { | ||
| refreshCurrentModelAndProvider(); | ||
| }, [refreshCurrentModelAndProvider]); | ||
|
|
||
| const contextValue = useMemo( | ||
| () => ({ | ||
| currentModel, | ||
| currentProvider, | ||
| changeModel, | ||
| getCurrentModelAndProvider, | ||
| getFallbackModelAndProvider, | ||
| getCurrentModelAndProviderForDisplay, | ||
| refreshCurrentModelAndProvider, | ||
| }), | ||
| [ | ||
| currentModel, | ||
| currentProvider, | ||
| changeModel, | ||
| getCurrentModelAndProvider, | ||
| getFallbackModelAndProvider, | ||
| getCurrentModelAndProviderForDisplay, | ||
| refreshCurrentModelAndProvider, | ||
| ] | ||
| ); | ||
|
|
||
| return ( | ||
| <ModelAndProviderContext.Provider value={contextValue}> | ||
| {children} | ||
| </ModelAndProviderContext.Provider> | ||
| ); | ||
| }; | ||
|
|
||
| export const useModelAndProvider = () => { | ||
| const context = useContext(ModelAndProviderContext); | ||
| if (context === undefined) { | ||
| throw new Error('useModelAndProvider must be used within a ModelAndProviderProvider'); | ||
| } | ||
| return context; | ||
| }; |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we not need these anymore?