fix: specify extension env vars only by name (#2249)
Co-authored-by: Lily Delalande <ldelalande@block.xyz>
This commit is contained in:
@@ -2,6 +2,8 @@ import { ExtensionConfig } from '../../../api/types.gen';
|
|||||||
import { getApiUrl, getSecretKey } from '../../../config';
|
import { getApiUrl, getSecretKey } from '../../../config';
|
||||||
import { toastService, ToastServiceOptions } from '../../../toasts';
|
import { toastService, ToastServiceOptions } from '../../../toasts';
|
||||||
import { replaceWithShims } from './utils';
|
import { replaceWithShims } from './utils';
|
||||||
|
import { saveEnvVarsToKeyring } from './extension-manager';
|
||||||
|
import type { AgentExtensionConfig } from './extension-manager';
|
||||||
|
|
||||||
interface ApiResponse {
|
interface ApiResponse {
|
||||||
error?: boolean;
|
error?: boolean;
|
||||||
@@ -141,13 +143,17 @@ export async function addToAgent(
|
|||||||
options: ToastServiceOptions = {}
|
options: ToastServiceOptions = {}
|
||||||
): Promise<Response> {
|
): Promise<Response> {
|
||||||
try {
|
try {
|
||||||
if (extension.type === 'stdio') {
|
await saveEnvVarsToKeyring(extension);
|
||||||
extension.cmd = await replaceWithShims(extension.cmd);
|
|
||||||
|
const ext = toAgentExtensionConfig(extension);
|
||||||
|
|
||||||
|
if (ext.type === 'stdio') {
|
||||||
|
ext.cmd = await replaceWithShims(ext.cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
extension.name = sanitizeName(extension.name);
|
ext.name = sanitizeName(ext.name);
|
||||||
|
|
||||||
return await extensionApiCall('/extensions/add', extension, options);
|
return await extensionApiCall('/extensions/add', ext, options);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// Check if this is a 428 error and make the message more descriptive
|
// Check if this is a 428 error and make the message more descriptive
|
||||||
if (error.message && error.message.includes('428')) {
|
if (error.message && error.message.includes('428')) {
|
||||||
@@ -179,3 +185,32 @@ export async function removeFromAgent(
|
|||||||
function sanitizeName(name: string) {
|
function sanitizeName(name: string) {
|
||||||
return name.toLowerCase().replace(/-/g, '').replace(/_/g, '').replace(/\s/g, '');
|
return name.toLowerCase().replace(/-/g, '').replace(/_/g, '').replace(/\s/g, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function toAgentExtensionConfig(config: ExtensionConfig): AgentExtensionConfig {
|
||||||
|
// Use type narrowing to handle different variants of the union type
|
||||||
|
if ('type' in config) {
|
||||||
|
switch (config.type) {
|
||||||
|
case 'sse': {
|
||||||
|
const { envs, ...rest } = config;
|
||||||
|
return {
|
||||||
|
...rest,
|
||||||
|
env_keys: envs ? Object.keys(envs) : undefined,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
case 'stdio': {
|
||||||
|
const { envs, ...rest } = config;
|
||||||
|
return {
|
||||||
|
...rest,
|
||||||
|
env_keys: envs ? Object.keys(envs) : undefined,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
case 'builtin':
|
||||||
|
case 'frontend':
|
||||||
|
// These types don't have envs field, so just return as is
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This should never happen due to the union type constraint
|
||||||
|
throw new Error('Invalid extension configuration type');
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,12 @@
|
|||||||
import type { ExtensionConfig } from '../../../api/types.gen';
|
import type { ExtensionConfig } from '../../../api/types.gen';
|
||||||
import { toastService, ToastServiceOptions } from '../../../toasts';
|
import { toastService, ToastServiceOptions } from '../../../toasts';
|
||||||
import { addToAgent, removeFromAgent } from './agent-api';
|
import { addToAgent, removeFromAgent } from './agent-api';
|
||||||
|
import { upsertConfig } from '../../../api';
|
||||||
|
|
||||||
|
// TODO: unify config.yaml and the agent /extensions/add API's notion of env vars
|
||||||
|
export type AgentExtensionConfig = ExtensionConfig & {
|
||||||
|
env_keys?: string[];
|
||||||
|
};
|
||||||
|
|
||||||
interface ActivateExtensionProps {
|
interface ActivateExtensionProps {
|
||||||
addToConfig: (name: string, extensionConfig: ExtensionConfig, enabled: boolean) => Promise<void>;
|
addToConfig: (name: string, extensionConfig: ExtensionConfig, enabled: boolean) => Promise<void>;
|
||||||
@@ -283,3 +289,11 @@ export async function deleteExtension({ name, removeFromConfig }: DeleteExtensio
|
|||||||
throw agentRemoveError;
|
throw agentRemoveError;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function saveEnvVarsToKeyring(extension: ExtensionConfig) {
|
||||||
|
if (extension.type === 'stdio' || extension.type === 'sse') {
|
||||||
|
for (const [key, value] of Object.entries(extension.envs || {})) {
|
||||||
|
await upsertConfig({ body: { key, value, is_secret: true } });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user