@kinvolk/headlamp-plugin
Version:
The needed infrastructure for building Headlamp plugins.
215 lines (185 loc) • 6.26 kB
text/typescript
/**
* Utility functions for managing AI provider configurations
*/
export interface StoredProviderConfig {
providerId: string;
displayName?: string;
config: Record<string, any>;
}
export interface SavedConfigurations {
providers?: StoredProviderConfig[];
defaultProviderIndex?: number;
termsAccepted?: boolean;
}
/**
* Gets saved provider configurations from plugin data
*/
export function getSavedConfigurations(data: any): SavedConfigurations {
if (!data) {
return { providers: [] };
}
// Check for new format storage
if (data.providers && Array.isArray(data.providers)) {
return {
providers: data.providers,
defaultProviderIndex: data.defaultProviderIndex,
termsAccepted: data.termsAccepted || false,
};
}
// Create empty configuration if nothing is found
const providers: StoredProviderConfig[] = [];
return {
providers,
termsAccepted: false,
};
}
/**
* Gets the active configuration based on the default config
*/
export function getActiveConfig(
savedConfigs: SavedConfigurations | null | undefined
): StoredProviderConfig | null {
if (!savedConfigs?.providers || savedConfigs.providers.length === 0) {
return null;
}
const defaultConfig = savedConfigs?.providers[savedConfigs.defaultProviderIndex || 0];
if (defaultConfig) return defaultConfig;
// Otherwise return the first one
return savedConfigs?.providers[0];
}
/**
* Saves or updates a provider configuration
*/
export function saveProviderConfig(
savedConfigs: SavedConfigurations | null | undefined,
providerId: string,
config: Record<string, any>,
makeDefault: boolean = false,
displayName?: string
): SavedConfigurations {
// Ensure we have a valid savedConfigs object
const safeConfigs: SavedConfigurations = savedConfigs || { providers: [] };
// Create new array to avoid modifying the original
const providers: StoredProviderConfig[] =
safeConfigs?.providers?.map(p => ({
...p,
})) ?? [];
// Check if this exact configuration already exists (by comparing display name or key fields)
const existingIndex = providers.findIndex(p => {
// If displayName is provided, use that as primary matching criteria
if (displayName && p.displayName === displayName && p.providerId === providerId) {
return true;
}
// Must match provider ID
if (p.providerId !== providerId) return false;
// If either config doesn't have API key or other identifying fields, they're not matching
if ((!p.config.apiKey && config.apiKey) || (p.config.apiKey && !config.apiKey)) {
return false;
}
// If API keys exist and match, consider a match (same account)
if (p.config.apiKey && config.apiKey && p.config.apiKey === config.apiKey) {
// But if models or deployment names differ, they're different configs
if (p.config.model && config.model && p.config.model !== config.model) {
return false;
}
if (
p.config.deploymentName &&
config.deploymentName &&
p.config.deploymentName !== config.deploymentName
) {
return false;
}
// If we got here with matching API keys and no conflicting models/deployments,
// consider it the same configuration
return true;
}
// If baseURLs exist and match, consider a potential match
if (p.config.baseUrl && config.baseUrl && p.config.baseUrl === config.baseUrl) {
// For base URLs, we also need matching models to consider them the same config
if (p.config.model && config.model && p.config.model === config.model) {
return true;
}
}
// Otherwise, consider it a different configuration
return false;
});
// Create new config object
const updatedConfig: StoredProviderConfig = {
providerId,
displayName:
displayName || (existingIndex >= 0 ? providers[existingIndex]?.displayName : undefined),
config: { ...config },
};
// Update or add the configuration
if (existingIndex >= 0) {
providers[existingIndex] = updatedConfig;
} else {
// This is a new configuration, add it to the list
providers.push(updatedConfig);
}
// Set defaultProviderIndex if makeDefault is true
let defaultProviderIndex = safeConfigs.defaultProviderIndex;
if (makeDefault) {
// If we're updating an existing provider
if (existingIndex >= 0) {
defaultProviderIndex = existingIndex;
} else {
// If we're adding a new provider
defaultProviderIndex = providers.length - 1;
}
}
// Return updated configurations
return {
providers,
defaultProviderIndex,
termsAccepted: safeConfigs.termsAccepted || false,
};
}
/**
* Deletes a provider configuration
*/
export function deleteProviderConfig(
savedConfigs: SavedConfigurations | null | undefined,
providerId: string,
config: Record<string, any>
): SavedConfigurations {
// Ensure we have a valid savedConfigs object
const safeConfigs: SavedConfigurations = savedConfigs || { providers: [] };
// Create new array without the deleted config
const providers = Array.isArray(safeConfigs?.providers)
? safeConfigs?.providers.filter(p => {
if (p.providerId !== providerId) return true;
if (p.config.apiKey && config.apiKey) {
return p.config.apiKey !== config.apiKey;
}
if (p.config.baseUrl && config.baseUrl) {
return p.config.baseUrl !== config.baseUrl;
}
return JSON.stringify(p.config) !== JSON.stringify(config);
})
: [];
// If we deleted the default provider and have others left, make the first one the default
const defaultProviderIndex =
providers.length > 0
? safeConfigs.defaultProviderIndex !== undefined
? Math.min(safeConfigs.defaultProviderIndex, providers.length - 1)
: 0
: undefined;
return {
providers,
defaultProviderIndex,
termsAccepted: safeConfigs.termsAccepted || false,
};
}
/**
* Saves the terms acceptance status
*/
export function saveTermsAcceptance(
savedConfigs: SavedConfigurations | null | undefined
): SavedConfigurations {
const safeConfigs = savedConfigs || { providers: [] };
return {
...safeConfigs,
termsAccepted: true,
};
}