mirror of
https://github.com/aljazceru/goose.git
synced 2025-12-20 07:34:27 +01:00
ui: turn on extensions at startup (#1861)
This commit is contained in:
@@ -24,12 +24,14 @@ 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 { useConfig } from './components/ConfigContext';
|
import { FixedExtensionEntry, useConfig } from './components/ConfigContext';
|
||||||
import {
|
import {
|
||||||
initializeBuiltInExtensions,
|
initializeBuiltInExtensions,
|
||||||
syncBuiltInExtensions,
|
syncBuiltInExtensions,
|
||||||
addExtensionFromDeepLink as addExtensionFromDeepLinkV2,
|
addExtensionFromDeepLink as addExtensionFromDeepLinkV2,
|
||||||
|
addToAgentOnStartup,
|
||||||
} from './components/settings_v2/extensions';
|
} 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 =
|
||||||
@@ -74,6 +76,8 @@ export default function App() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// this is all settings v2 stuff
|
// this is all settings v2 stuff
|
||||||
|
// Modified version of the alpha initialization flow for App.tsx
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// Skip if feature flag is not enabled
|
// Skip if feature flag is not enabled
|
||||||
if (!process.env.ALPHA) {
|
if (!process.env.ALPHA) {
|
||||||
@@ -82,24 +86,68 @@ export default function App() {
|
|||||||
|
|
||||||
console.log('Alpha flow initializing...');
|
console.log('Alpha flow initializing...');
|
||||||
|
|
||||||
const setupExtensions = async () => {
|
// First quickly check if we have model and provider to set chat view
|
||||||
|
const checkRequiredConfig = async () => {
|
||||||
try {
|
try {
|
||||||
console.log('Setting up extensions...');
|
console.log('Reading GOOSE_PROVIDER and GOOSE_MODEL from config...');
|
||||||
|
const provider = (await read('GOOSE_PROVIDER', false)) as string;
|
||||||
|
const model = (await read('GOOSE_MODEL', false)) as string;
|
||||||
|
|
||||||
// Set the ref immediately to prevent duplicate runs
|
if (provider && model) {
|
||||||
initAttemptedRef.current = true;
|
// We have all needed configuration, set chat view immediately
|
||||||
console.log('Set initAttemptedRef to prevent duplicate runs');
|
console.log(`Found provider: ${provider}, model: ${model}, setting chat view`);
|
||||||
|
setView('chat');
|
||||||
|
|
||||||
|
// Initialize the system in background
|
||||||
|
initializeSystem(provider, model)
|
||||||
|
.then(() => console.log('System initialization successful'))
|
||||||
|
.catch((error) => {
|
||||||
|
console.error('Error initializing system:', error);
|
||||||
|
setFatalError(`System initialization error: ${error.message || 'Unknown error'}`);
|
||||||
|
setView('welcome');
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// Missing configuration, show onboarding
|
||||||
|
console.log('Missing configuration, showing onboarding');
|
||||||
|
if (!provider) console.log('Missing provider');
|
||||||
|
if (!model) console.log('Missing model');
|
||||||
|
setView('welcome');
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error checking configuration:', error);
|
||||||
|
setFatalError(`Configuration check error: ${error.message || 'Unknown error'}`);
|
||||||
|
setView('welcome');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Setup extensions in parallel
|
||||||
|
const setupExtensions = async () => {
|
||||||
|
// Set the ref immediately to prevent duplicate runs
|
||||||
|
initAttemptedRef.current = true;
|
||||||
|
|
||||||
|
let refreshedExtensions: FixedExtensionEntry[] = [];
|
||||||
|
try {
|
||||||
// Force refresh extensions from the backend to ensure we have the latest
|
// Force refresh extensions from the backend to ensure we have the latest
|
||||||
console.log('Getting extensions from backend...');
|
console.log('Getting extensions from backend...');
|
||||||
const refreshedExtensions = await getExtensions(true);
|
refreshedExtensions = await getExtensions(true);
|
||||||
console.log(`Retrieved ${refreshedExtensions.length} extensions`);
|
console.log(`Retrieved ${refreshedExtensions.length} extensions`);
|
||||||
|
} catch (error) {
|
||||||
|
console.log('Error getting extensions list');
|
||||||
|
return; // Exit early if we can't get the extensions list
|
||||||
|
}
|
||||||
|
|
||||||
|
// built-in extensions block -- just adds them to config if missing
|
||||||
|
try {
|
||||||
|
console.log('Setting up built-in extensions...');
|
||||||
|
|
||||||
if (refreshedExtensions.length === 0) {
|
if (refreshedExtensions.length === 0) {
|
||||||
// If we still have no extensions, this is truly a first-time setup
|
// If we still have no extensions, this is truly a first-time setup
|
||||||
console.log('First-time setup: Adding all built-in extensions...');
|
console.log('First-time setup: Adding all built-in extensions...');
|
||||||
await initializeBuiltInExtensions(addExtension);
|
await initializeBuiltInExtensions(addExtension);
|
||||||
console.log('Built-in extensions initialization complete');
|
console.log('Built-in extensions initialization complete');
|
||||||
|
|
||||||
|
// Refresh the extensions list after initialization
|
||||||
|
refreshedExtensions = await getExtensions(true);
|
||||||
} else {
|
} else {
|
||||||
// Extensions exist, check for any missing built-ins
|
// Extensions exist, check for any missing built-ins
|
||||||
console.log('Checking for missing built-in extensions...');
|
console.log('Checking for missing built-in extensions...');
|
||||||
@@ -109,69 +157,37 @@ export default function App() {
|
|||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error setting up extensions:', error);
|
console.error('Error setting up extensions:', error);
|
||||||
console.error('Extension setup error details:', {
|
|
||||||
message: error.message,
|
|
||||||
stack: error.stack,
|
|
||||||
name: error.name,
|
|
||||||
});
|
|
||||||
// We don't set fatal error here since the app might still work without extensions
|
// We don't set fatal error here since the app might still work without extensions
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
const initializeApp = async () => {
|
// now try to add to agent
|
||||||
try {
|
console.log('Adding enabled extensions to agent...');
|
||||||
console.log('Initializing alpha app...');
|
for (const extensionEntry of refreshedExtensions) {
|
||||||
|
if (extensionEntry.enabled) {
|
||||||
// Check if we have the required configuration
|
console.log(`Adding extension to agent: ${extensionEntry.name}`);
|
||||||
console.log('Reading GOOSE_PROVIDER from config...');
|
// need to convert to config because that's what the endpoint expects
|
||||||
const provider = (await read('GOOSE_PROVIDER', false)) as string;
|
const extensionConfig = extractExtensionConfig(extensionEntry);
|
||||||
console.log('Provider from config:', provider);
|
// will handle toasts and also set failures to enabled = false
|
||||||
|
await addToAgentOnStartup({ addToConfig: addExtension, extensionConfig });
|
||||||
console.log('Reading GOOSE_MODEL from config...');
|
|
||||||
const model = (await read('GOOSE_MODEL', false)) as string;
|
|
||||||
console.log('Model from config:', model);
|
|
||||||
|
|
||||||
if (provider && model) {
|
|
||||||
// We have all needed configuration, initialize the system
|
|
||||||
console.log(`Initializing system with provider: ${provider}, model: ${model}`);
|
|
||||||
await initializeSystem(provider, model);
|
|
||||||
console.log('System initialization successful');
|
|
||||||
setView('chat');
|
|
||||||
} else {
|
} else {
|
||||||
// Missing configuration, show onboarding
|
console.log(`Skipping disabled extension: ${extensionEntry.name}`);
|
||||||
console.log('Missing configuration, showing onboarding');
|
|
||||||
if (!provider) console.log('Missing provider');
|
|
||||||
if (!model) console.log('Missing model');
|
|
||||||
setView('welcome');
|
|
||||||
}
|
}
|
||||||
} catch (error) {
|
|
||||||
console.error('Error initializing app:', error);
|
|
||||||
console.error('App initialization error details:', {
|
|
||||||
message: error.message,
|
|
||||||
stack: error.stack,
|
|
||||||
name: error.name,
|
|
||||||
});
|
|
||||||
setFatalError(`Alpha initialization error: ${error.message || 'Unknown error'}`);
|
|
||||||
setView('welcome');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log('Extensions setup complete');
|
||||||
};
|
};
|
||||||
|
|
||||||
// Execute with better promise handling
|
// Execute the two flows in parallel for speed
|
||||||
initializeApp()
|
checkRequiredConfig().catch((error) => {
|
||||||
.then(() => console.log('Alpha app initialization complete'))
|
console.error('Unhandled error in checkRequiredConfig:', error);
|
||||||
.catch((error) => {
|
setFatalError(`Config check error: ${error.message || 'Unknown error'}`);
|
||||||
console.error('Unhandled error in initializeApp:', error);
|
});
|
||||||
setFatalError(`Unhandled alpha app error: ${error.message || 'Unknown error'}`);
|
|
||||||
});
|
|
||||||
|
|
||||||
setupExtensions()
|
setupExtensions().catch((error) => {
|
||||||
.then(() => console.log('Extensions setup complete'))
|
console.error('Unhandled error in setupExtensions:', error);
|
||||||
.catch((error) => {
|
// Not setting fatal error here since extensions are optional
|
||||||
console.error('Unhandled error in setupExtensions:', error);
|
});
|
||||||
// Not setting fatal error here since extensions are optional
|
|
||||||
});
|
|
||||||
}, []); // Empty dependency array since we're using initAttemptedRef
|
}, []); // Empty dependency array since we're using initAttemptedRef
|
||||||
|
|
||||||
const setView = (view: View, viewOptions: Record<any, any> = {}) => {
|
const setView = (view: View, viewOptions: Record<any, any> = {}) => {
|
||||||
console.log(`Setting view to: ${view}`, viewOptions);
|
console.log(`Setting view to: ${view}`, viewOptions);
|
||||||
setInternalView({ view, viewOptions });
|
setInternalView({ view, viewOptions });
|
||||||
|
|||||||
@@ -20,10 +20,6 @@ export default function SettingsView({
|
|||||||
setView: (view: View) => void;
|
setView: (view: View) => void;
|
||||||
viewOptions: SettingsViewOptions;
|
viewOptions: SettingsViewOptions;
|
||||||
}) {
|
}) {
|
||||||
const { config } = useConfig();
|
|
||||||
|
|
||||||
console.log(config);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="h-screen w-full">
|
<div className="h-screen w-full">
|
||||||
<div className="relative flex items-center h-[36px] w-full bg-bgSubtle"></div>
|
<div className="relative flex items-center h-[36px] w-full bg-bgSubtle"></div>
|
||||||
|
|||||||
@@ -78,21 +78,51 @@ export async function activateExtension({
|
|||||||
// AddToAgent
|
// AddToAgent
|
||||||
await AddToAgent(extensionConfig);
|
await AddToAgent(extensionConfig);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
console.error('Failed to add extension to agent:', error);
|
||||||
// add to config with enabled = false
|
// add to config with enabled = false
|
||||||
await addToConfig(extensionConfig.name, extensionConfig, false);
|
await addToConfig(extensionConfig.name, extensionConfig, false);
|
||||||
// show user the error, return
|
// Rethrow the error to inform the caller
|
||||||
console.log('error', error);
|
throw error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Then add to config
|
// Then add to config
|
||||||
try {
|
try {
|
||||||
await addToConfig(extensionConfig.name, extensionConfig, true);
|
await addToConfig(extensionConfig.name, extensionConfig, true);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
console.error('Failed to add extension to config:', error);
|
||||||
// remove from Agent
|
// remove from Agent
|
||||||
await RemoveFromAgent(extensionConfig.name);
|
try {
|
||||||
// config error workflow
|
await RemoveFromAgent(extensionConfig.name);
|
||||||
console.log('error', error);
|
} catch (removeError) {
|
||||||
|
console.error('Failed to remove extension from agent after config failure:', removeError);
|
||||||
|
}
|
||||||
|
// Rethrow the error to inform the caller
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface addToAgentOnStartupProps {
|
||||||
|
addToConfig: (name: string, extensionConfig: ExtensionConfig, enabled: boolean) => Promise<void>;
|
||||||
|
extensionConfig: ExtensionConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function addToAgentOnStartup({
|
||||||
|
addToConfig,
|
||||||
|
extensionConfig,
|
||||||
|
}: addToAgentOnStartupProps): Promise<void> {
|
||||||
|
try {
|
||||||
|
// AddToAgent
|
||||||
|
await AddToAgent(extensionConfig);
|
||||||
|
} catch (error) {
|
||||||
|
console.log('got error trying to add to agent in addAgentOnStartUp', error);
|
||||||
|
// update config with enabled = false
|
||||||
|
try {
|
||||||
|
await toggleExtension({ toggle: 'toggleOff', extensionConfig, addToConfig });
|
||||||
|
} catch (toggleError) {
|
||||||
|
console.error('Failed to toggle extension off after agent error:', toggleError);
|
||||||
|
}
|
||||||
|
// Rethrow the error to inform the caller
|
||||||
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,26 +143,24 @@ export async function updateExtension({
|
|||||||
// AddToAgent
|
// AddToAgent
|
||||||
await AddToAgent(extensionConfig);
|
await AddToAgent(extensionConfig);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// i think only error that gets thrown here is when it's not from the response... rest are handled by agent
|
console.error('Failed to add extension to agent during update:', error);
|
||||||
console.log('error', error);
|
// Failed to add to agent -- show that error to user and do not update the config file
|
||||||
// failed to add to agent -- show that error to user and do not update the config file
|
throw error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Then add to config
|
// Then add to config
|
||||||
try {
|
try {
|
||||||
await addToConfig(extensionConfig.name, extensionConfig, enabled);
|
await addToConfig(extensionConfig.name, extensionConfig, enabled);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// config error workflow
|
console.error('Failed to update extension in config:', error);
|
||||||
console.log('error', error);
|
throw error;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
await addToConfig(extensionConfig.name, extensionConfig, enabled);
|
await addToConfig(extensionConfig.name, extensionConfig, enabled);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// TODO: Add to agent with previous configuration and raise error
|
console.error('Failed to update disabled extension in config:', error);
|
||||||
// for now just log error
|
throw error;
|
||||||
console.log('error', error);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -141,7 +169,6 @@ interface toggleExtensionProps {
|
|||||||
toggle: 'toggleOn' | 'toggleOff';
|
toggle: 'toggleOn' | 'toggleOff';
|
||||||
extensionConfig: ExtensionConfig;
|
extensionConfig: ExtensionConfig;
|
||||||
addToConfig: (name: string, extensionConfig: ExtensionConfig, enabled: boolean) => Promise<void>;
|
addToConfig: (name: string, extensionConfig: ExtensionConfig, enabled: boolean) => Promise<void>;
|
||||||
removeFromConfig: (name: string) => Promise<void>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function toggleExtension({
|
export async function toggleExtension({
|
||||||
@@ -155,33 +182,50 @@ export async function toggleExtension({
|
|||||||
// add to agent
|
// add to agent
|
||||||
await AddToAgent(extensionConfig);
|
await AddToAgent(extensionConfig);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// do nothing raise error
|
console.error('Error adding extension to agent. Will try to toggle back off. Error:', error);
|
||||||
// show user error
|
try {
|
||||||
console.log('Error adding extension to agent. Error:', error);
|
await toggleExtension({ toggle: 'toggleOff', extensionConfig, addToConfig });
|
||||||
return;
|
} catch (toggleError) {
|
||||||
|
console.error('Failed to toggle extension off after agent error:', toggleError);
|
||||||
|
}
|
||||||
|
throw error;
|
||||||
}
|
}
|
||||||
|
|
||||||
// update the config
|
// update the config
|
||||||
try {
|
try {
|
||||||
await addToConfig(extensionConfig.name, extensionConfig, true);
|
await addToConfig(extensionConfig.name, extensionConfig, true);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// remove from agent?
|
console.error('Failed to update config after enabling extension:', error);
|
||||||
await RemoveFromAgent(extensionConfig.name);
|
// remove from agent
|
||||||
|
try {
|
||||||
|
await RemoveFromAgent(extensionConfig.name);
|
||||||
|
} catch (removeError) {
|
||||||
|
console.error('Failed to remove extension from agent after config failure:', removeError);
|
||||||
|
}
|
||||||
|
throw error;
|
||||||
}
|
}
|
||||||
} else if (toggle == 'toggleOff') {
|
} else if (toggle == 'toggleOff') {
|
||||||
// enabled to disabled
|
// enabled to disabled
|
||||||
|
let agentRemoveError = null;
|
||||||
try {
|
try {
|
||||||
await RemoveFromAgent(extensionConfig.name);
|
await RemoveFromAgent(extensionConfig.name);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// note there was an error, but remove from config anyway
|
// note there was an error, but attempt to remove from config anyway
|
||||||
console.error('Error removing extension from agent', extensionConfig.name, error);
|
console.error('Error removing extension from agent', extensionConfig.name, error);
|
||||||
|
agentRemoveError = error;
|
||||||
}
|
}
|
||||||
|
|
||||||
// update the config
|
// update the config
|
||||||
try {
|
try {
|
||||||
await addToConfig(extensionConfig.name, extensionConfig, false);
|
await addToConfig(extensionConfig.name, extensionConfig, false);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// TODO: Add to agent with previous configuration
|
console.error('Error removing extension from config', extensionConfig.name, 'Error:', error);
|
||||||
console.log('Error removing extension from config', extensionConfig.name, 'Error:', error);
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we had an error removing from agent but succeeded updating config, still throw the original error
|
||||||
|
if (agentRemoveError) {
|
||||||
|
throw agentRemoveError;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -193,15 +237,29 @@ interface deleteExtensionProps {
|
|||||||
|
|
||||||
export async function deleteExtension({ name, removeFromConfig }: deleteExtensionProps) {
|
export async function deleteExtension({ name, removeFromConfig }: deleteExtensionProps) {
|
||||||
// remove from agent
|
// remove from agent
|
||||||
await RemoveFromAgent(name);
|
let agentRemoveError = null;
|
||||||
|
try {
|
||||||
|
await RemoveFromAgent(name);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to remove extension from agent during deletion:', error);
|
||||||
|
agentRemoveError = error;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await removeFromConfig(name);
|
await removeFromConfig(name);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log('Failed to remove extension from config after removing from agent. Error:', error);
|
console.error(
|
||||||
// TODO: tell user to restart goose and try again to remove (will still be present in settings but not on agent until restart)
|
'Failed to remove extension from config after removing from agent. Error:',
|
||||||
|
error
|
||||||
|
);
|
||||||
|
// If we also had an agent remove error, log it but throw the config error as it's more critical
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we had an error removing from agent but succeeded removing from config, still throw the original error
|
||||||
|
if (agentRemoveError) {
|
||||||
|
throw agentRemoveError;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -292,7 +350,12 @@ export async function addExtensionFromDeepLink(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If no env vars are required, proceed with adding the extension
|
// If no env vars are required, proceed with adding the extension
|
||||||
await activateExtension({ extensionConfig: config, addToConfig: addExtensionFn });
|
try {
|
||||||
|
await activateExtension({ extensionConfig: config, addToConfig: addExtensionFn });
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to activate extension from deeplink:', error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -340,8 +403,13 @@ export async function syncBuiltInExtensions(
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Add the extension with its default enabled state
|
// Add the extension with its default enabled state
|
||||||
await addExtensionFn(nameToKey(builtinExt.name), extConfig, builtinExt.enabled);
|
try {
|
||||||
addedCount++;
|
await addExtensionFn(nameToKey(builtinExt.name), extConfig, builtinExt.enabled);
|
||||||
|
addedCount++;
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Failed to add built-in extension ${builtinExt.name}:`, error);
|
||||||
|
// Continue with other extensions even if one fails
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -415,7 +483,7 @@ async function extensionApiCall<T>(
|
|||||||
msg: 'Agent is not initialized. Please initialize the agent first.',
|
msg: 'Agent is not initialized. Please initialize the agent first.',
|
||||||
traceback: errorMsg,
|
traceback: errorMsg,
|
||||||
});
|
});
|
||||||
return response;
|
throw new Error('Agent is not initialized. Please initialize the agent first.');
|
||||||
}
|
}
|
||||||
|
|
||||||
const msg = `Failed to ${actionType === 'adding' ? 'add' : 'remove'} ${extensionName} extension: ${errorMsg}`;
|
const msg = `Failed to ${actionType === 'adding' ? 'add' : 'remove'} ${extensionName} extension: ${errorMsg}`;
|
||||||
@@ -427,7 +495,7 @@ async function extensionApiCall<T>(
|
|||||||
msg: msg,
|
msg: msg,
|
||||||
traceback: errorMsg,
|
traceback: errorMsg,
|
||||||
});
|
});
|
||||||
return response;
|
throw new Error(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse response JSON safely
|
// Parse response JSON safely
|
||||||
@@ -435,40 +503,54 @@ async function extensionApiCall<T>(
|
|||||||
try {
|
try {
|
||||||
const text = await response.text();
|
const text = await response.text();
|
||||||
data = text ? JSON.parse(text) : { error: false };
|
data = text ? JSON.parse(text) : { error: false };
|
||||||
} catch (error) {
|
} catch (parseError) {
|
||||||
console.warn('Could not parse response as JSON, assuming success', error);
|
console.warn('Could not parse response as JSON, assuming success', parseError);
|
||||||
data = { error: false };
|
data = { error: false };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!data.error) {
|
if (!data.error) {
|
||||||
if (toastId) toast.dismiss(toastId);
|
if (toastId) toast.dismiss(toastId);
|
||||||
ToastSuccess({ title: extensionName, msg: 'Successfully enabled extension' });
|
ToastSuccess({ title: extensionName, msg: `Successfully ${pastVerb} extension` });
|
||||||
|
return response;
|
||||||
} else {
|
} else {
|
||||||
const errorMessage = `Error adding extension -- parsing data`;
|
const errorMessage = `Error ${actionType} extension -- parsing data: ${data.message || 'Unknown error'}`;
|
||||||
console.error(errorMessage);
|
console.error(errorMessage);
|
||||||
if (toastId) toast.dismiss(toastId);
|
if (toastId) toast.dismiss(toastId);
|
||||||
ToastError({
|
ToastError({
|
||||||
title: extensionName,
|
title: extensionName,
|
||||||
msg: errorMessage,
|
msg: errorMessage,
|
||||||
traceback: data.message, // why data.message not data.error?
|
traceback: data.message || 'Unknown error', // why data.message not data.error?
|
||||||
});
|
});
|
||||||
|
throw new Error(errorMessage);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
//
|
if (toastId) toast.dismiss(toastId);
|
||||||
|
console.error(`Error in extensionApiCall for ${extensionName}:`, error);
|
||||||
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Public functions
|
// Public functions
|
||||||
export async function AddToAgent(extension: ExtensionConfig): Promise<Response> {
|
export async function AddToAgent(extension: ExtensionConfig): Promise<Response> {
|
||||||
if (extension.type === 'stdio') {
|
try {
|
||||||
console.log('extension command', extension.cmd);
|
if (extension.type === 'stdio') {
|
||||||
extension.cmd = await replaceWithShims(extension.cmd);
|
console.log('extension command', extension.cmd);
|
||||||
console.log('next ext command', extension.cmd);
|
extension.cmd = await replaceWithShims(extension.cmd);
|
||||||
}
|
console.log('next ext command', extension.cmd);
|
||||||
|
}
|
||||||
|
|
||||||
return extensionApiCall('/extensions/add', extension, 'adding', extension.name);
|
return await extensionApiCall('/extensions/add', extension, 'adding', extension.name);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Failed to add extension ${extension.name} to agent:`, error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function RemoveFromAgent(name: string): Promise<Response> {
|
export async function RemoveFromAgent(name: string): Promise<Response> {
|
||||||
return extensionApiCall('/extensions/remove', name, 'removing', name);
|
try {
|
||||||
|
return await extensionApiCall('/extensions/remove', name, 'removing', name);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Failed to remove extension ${name} from agent:`, error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user