mirror of
https://github.com/simstudioai/sim.git
synced 2026-01-10 15:38:00 -05:00
fix: env vars process only on api key and openai fallback removed
This commit is contained in:
@@ -234,7 +234,7 @@ export class AgentBlockHandler implements BlockHandler {
|
||||
tools: formattedTools.length > 0 ? formattedTools : undefined,
|
||||
temperature: inputs.temperature,
|
||||
maxTokens: inputs.maxTokens,
|
||||
apiKey: inputs.apiKey || context.environmentVariables?.OPENAI_API_KEY,
|
||||
apiKey: inputs.apiKey,
|
||||
responseFormat,
|
||||
}
|
||||
|
||||
|
||||
@@ -62,8 +62,13 @@ export class InputResolver {
|
||||
// Resolve block references
|
||||
let resolvedValue = this.resolveBlockReferences(value, context, block)
|
||||
|
||||
// Check if this is an API key field
|
||||
const isApiKey = key.toLowerCase().includes('apikey') ||
|
||||
key.toLowerCase().includes('secret') ||
|
||||
key.toLowerCase().includes('token')
|
||||
|
||||
// Resolve environment variables
|
||||
resolvedValue = this.resolveEnvVariables(resolvedValue)
|
||||
resolvedValue = this.resolveEnvVariables(resolvedValue, isApiKey)
|
||||
|
||||
// Convert JSON strings to objects if possible
|
||||
try {
|
||||
@@ -239,40 +244,89 @@ export class InputResolver {
|
||||
return resolvedValue
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if a string contains a properly formatted environment variable reference.
|
||||
* Valid references are either:
|
||||
* 1. A standalone env var (entire string is just {{ENV_VAR}})
|
||||
* 2. An explicit env var with clear boundaries (usually within a URL or similar)
|
||||
*
|
||||
* @param value - The string to check
|
||||
* @returns Whether this contains a properly formatted env var reference
|
||||
*/
|
||||
private containsProperEnvVarReference(value: string): boolean {
|
||||
if (!value || typeof value !== 'string') return false
|
||||
|
||||
// Case 1: String is just a single environment variable
|
||||
if (value.trim().match(/^\{\{[^{}]+\}\}$/)) {
|
||||
return true
|
||||
}
|
||||
|
||||
// Case 2: Check for environment variables in specific contexts
|
||||
// For example, in URLs, bearer tokens, etc.
|
||||
const properContextPatterns = [
|
||||
// Auth header patterns
|
||||
/Bearer\s+\{\{[^{}]+\}\}/i,
|
||||
/Authorization:\s+Bearer\s+\{\{[^{}]+\}\}/i,
|
||||
/Authorization:\s+\{\{[^{}]+\}\}/i,
|
||||
|
||||
// API key in URL patterns
|
||||
/[?&]api[_-]?key=\{\{[^{}]+\}\}/i,
|
||||
/[?&]key=\{\{[^{}]+\}\}/i,
|
||||
/[?&]token=\{\{[^{}]+\}\}/i,
|
||||
|
||||
// API key in header patterns
|
||||
/X-API-Key:\s+\{\{[^{}]+\}\}/i,
|
||||
/api[_-]?key:\s+\{\{[^{}]+\}\}/i
|
||||
]
|
||||
|
||||
return properContextPatterns.some(pattern => pattern.test(value))
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves environment variables in any value ({{ENV_VAR}}).
|
||||
* Only processes environment variables in apiKey fields or when explicitly needed.
|
||||
*
|
||||
* @param value - Value that may contain environment variable references
|
||||
* @param isApiKey - Whether this is an API key field (requires special env var handling)
|
||||
* @returns Value with environment variables resolved
|
||||
* @throws Error if referenced environment variable is not found
|
||||
*/
|
||||
resolveEnvVariables(value: any): any {
|
||||
resolveEnvVariables(value: any, isApiKey: boolean = false): any {
|
||||
if (typeof value === 'string') {
|
||||
const envMatches = value.match(/\{\{([^}]+)\}\}/g)
|
||||
if (envMatches) {
|
||||
let resolvedValue = value
|
||||
for (const match of envMatches) {
|
||||
const envKey = match.slice(2, -2)
|
||||
const envValue = this.environmentVariables[envKey]
|
||||
// Only process environment variables if:
|
||||
// 1. This is an API key field
|
||||
// 2. String is a complete environment variable reference ({{ENV_VAR}})
|
||||
// 3. String contains environment variable references in proper contexts (auth headers, URLs)
|
||||
const isExplicitEnvVar = value.trim().startsWith('{{') && value.trim().endsWith('}}')
|
||||
const hasProperEnvVarReferences = this.containsProperEnvVarReference(value)
|
||||
|
||||
if (isApiKey || isExplicitEnvVar || hasProperEnvVarReferences) {
|
||||
const envMatches = value.match(/\{\{([^}]+)\}\}/g)
|
||||
if (envMatches) {
|
||||
let resolvedValue = value
|
||||
for (const match of envMatches) {
|
||||
const envKey = match.slice(2, -2)
|
||||
const envValue = this.environmentVariables[envKey]
|
||||
|
||||
if (envValue === undefined) {
|
||||
throw new Error(`Environment variable "${envKey}" was not found.`)
|
||||
if (envValue === undefined) {
|
||||
throw new Error(`Environment variable "${envKey}" was not found.`)
|
||||
}
|
||||
|
||||
resolvedValue = resolvedValue.replace(match, envValue)
|
||||
}
|
||||
|
||||
resolvedValue = resolvedValue.replace(match, envValue)
|
||||
return resolvedValue
|
||||
}
|
||||
return resolvedValue
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
if (Array.isArray(value)) {
|
||||
return value.map((item) => this.resolveEnvVariables(item))
|
||||
return value.map((item) => this.resolveEnvVariables(item, isApiKey))
|
||||
}
|
||||
|
||||
if (value && typeof value === 'object') {
|
||||
return Object.entries(value).reduce(
|
||||
(acc, [k, v]) => ({ ...acc, [k]: this.resolveEnvVariables(v) }),
|
||||
(acc, [k, v]) => ({ ...acc, [k]: this.resolveEnvVariables(v, k.toLowerCase() === 'apikey') }),
|
||||
{}
|
||||
)
|
||||
}
|
||||
@@ -303,8 +357,12 @@ export class InputResolver {
|
||||
if (typeof value === 'string') {
|
||||
// First resolve block references
|
||||
const resolvedReferences = this.resolveBlockReferences(value, context, currentBlock)
|
||||
// Then resolve environment variables
|
||||
return this.resolveEnvVariables(resolvedReferences)
|
||||
|
||||
// Check if this is an API key field
|
||||
const isApiKey = this.isApiKeyField(currentBlock, value)
|
||||
|
||||
// Then resolve environment variables with the API key flag
|
||||
return this.resolveEnvVariables(resolvedReferences, isApiKey)
|
||||
}
|
||||
|
||||
// Handle arrays
|
||||
@@ -316,6 +374,7 @@ export class InputResolver {
|
||||
if (typeof value === 'object') {
|
||||
const result: Record<string, any> = {}
|
||||
for (const [k, v] of Object.entries(value)) {
|
||||
const isApiKey = k.toLowerCase() === 'apikey'
|
||||
result[k] = this.resolveNestedStructure(v, context, currentBlock)
|
||||
}
|
||||
return result
|
||||
@@ -325,6 +384,38 @@ export class InputResolver {
|
||||
return value
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if a given field in a block is an API key field.
|
||||
*
|
||||
* @param block - Block containing the field
|
||||
* @param value - Value to check
|
||||
* @returns Whether this appears to be an API key field
|
||||
*/
|
||||
private isApiKeyField(block: SerializedBlock, value: string): boolean {
|
||||
// Check if the block is an API or agent block (which typically have API keys)
|
||||
const blockType = block.metadata?.id
|
||||
if (blockType !== 'api' && blockType !== 'agent') {
|
||||
return false
|
||||
}
|
||||
|
||||
// Look for the value in the block params
|
||||
for (const [key, paramValue] of Object.entries(block.config.params)) {
|
||||
if (paramValue === value) {
|
||||
// Check if key name suggests it's an API key
|
||||
const normalizedKey = key.toLowerCase().replace(/[_\-\s]/g, '')
|
||||
return (
|
||||
normalizedKey === 'apikey' ||
|
||||
normalizedKey.includes('apikey') ||
|
||||
normalizedKey.includes('secretkey') ||
|
||||
normalizedKey.includes('accesskey') ||
|
||||
normalizedKey.includes('token')
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats a value for use in condition blocks.
|
||||
* Handles strings, null, undefined, and objects appropriately.
|
||||
|
||||
@@ -54,7 +54,19 @@ export function ShortInput({
|
||||
const normalizedTitle = config?.title?.replace(/\s+/g, '').toLowerCase() || ''
|
||||
|
||||
// Check for common API key naming patterns
|
||||
const apiKeyPatterns = ['apikey', 'api_key', 'api-key', 'secretkey', 'secret_key', 'secret-key']
|
||||
const apiKeyPatterns = [
|
||||
'apikey',
|
||||
'api_key',
|
||||
'api-key',
|
||||
'secretkey',
|
||||
'secret_key',
|
||||
'secret-key',
|
||||
'token',
|
||||
'access_token',
|
||||
'auth_token',
|
||||
'secret',
|
||||
'password',
|
||||
]
|
||||
|
||||
return apiKeyPatterns.some(
|
||||
(pattern) =>
|
||||
@@ -240,8 +252,13 @@ export function ShortInput({
|
||||
const displayValue =
|
||||
password && !isFocused ? '•'.repeat(value?.toString().length ?? 0) : (value?.toString() ?? '')
|
||||
|
||||
// Modify the EnvVarDropdown to use the correct setter
|
||||
// Explicitly mark environment variable references with '{{' and '}}' when inserting
|
||||
const handleEnvVarSelect = (newValue: string) => {
|
||||
// For API keys, ensure we're using the full value with {{ }} format
|
||||
if (isApiKeyField && !newValue.startsWith('{{')) {
|
||||
newValue = `{{${newValue}}}`
|
||||
}
|
||||
|
||||
if (onChange) {
|
||||
onChange(newValue)
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user