Skip to content

Commit 2db6c82

Browse files
committed
fix: env vars process only on api key and openai fallback removed
1 parent 7cdf72b commit 2db6c82

File tree

3 files changed

+129
-21
lines changed

3 files changed

+129
-21
lines changed

sim/app/executor/handlers.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ export class AgentBlockHandler implements BlockHandler {
234234
tools: formattedTools.length > 0 ? formattedTools : undefined,
235235
temperature: inputs.temperature,
236236
maxTokens: inputs.maxTokens,
237-
apiKey: inputs.apiKey || context.environmentVariables?.OPENAI_API_KEY,
237+
apiKey: inputs.apiKey,
238238
responseFormat,
239239
}
240240

sim/app/executor/resolver.ts

Lines changed: 109 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,13 @@ export class InputResolver {
6262
// Resolve block references
6363
let resolvedValue = this.resolveBlockReferences(value, context, block)
6464

65+
// Check if this is an API key field
66+
const isApiKey = key.toLowerCase().includes('apikey') ||
67+
key.toLowerCase().includes('secret') ||
68+
key.toLowerCase().includes('token')
69+
6570
// Resolve environment variables
66-
resolvedValue = this.resolveEnvVariables(resolvedValue)
71+
resolvedValue = this.resolveEnvVariables(resolvedValue, isApiKey)
6772

6873
// Convert JSON strings to objects if possible
6974
try {
@@ -239,40 +244,89 @@ export class InputResolver {
239244
return resolvedValue
240245
}
241246

247+
/**
248+
* Determines if a string contains a properly formatted environment variable reference.
249+
* Valid references are either:
250+
* 1. A standalone env var (entire string is just {{ENV_VAR}})
251+
* 2. An explicit env var with clear boundaries (usually within a URL or similar)
252+
*
253+
* @param value - The string to check
254+
* @returns Whether this contains a properly formatted env var reference
255+
*/
256+
private containsProperEnvVarReference(value: string): boolean {
257+
if (!value || typeof value !== 'string') return false
258+
259+
// Case 1: String is just a single environment variable
260+
if (value.trim().match(/^\{\{[^{}]+\}\}$/)) {
261+
return true
262+
}
263+
264+
// Case 2: Check for environment variables in specific contexts
265+
// For example, in URLs, bearer tokens, etc.
266+
const properContextPatterns = [
267+
// Auth header patterns
268+
/Bearer\s+\{\{[^{}]+\}\}/i,
269+
/Authorization:\s+Bearer\s+\{\{[^{}]+\}\}/i,
270+
/Authorization:\s+\{\{[^{}]+\}\}/i,
271+
272+
// API key in URL patterns
273+
/[?&]api[_-]?key=\{\{[^{}]+\}\}/i,
274+
/[?&]key=\{\{[^{}]+\}\}/i,
275+
/[?&]token=\{\{[^{}]+\}\}/i,
276+
277+
// API key in header patterns
278+
/X-API-Key:\s+\{\{[^{}]+\}\}/i,
279+
/api[_-]?key:\s+\{\{[^{}]+\}\}/i
280+
]
281+
282+
return properContextPatterns.some(pattern => pattern.test(value))
283+
}
284+
242285
/**
243286
* Resolves environment variables in any value ({{ENV_VAR}}).
287+
* Only processes environment variables in apiKey fields or when explicitly needed.
244288
*
245289
* @param value - Value that may contain environment variable references
290+
* @param isApiKey - Whether this is an API key field (requires special env var handling)
246291
* @returns Value with environment variables resolved
247292
* @throws Error if referenced environment variable is not found
248293
*/
249-
resolveEnvVariables(value: any): any {
294+
resolveEnvVariables(value: any, isApiKey: boolean = false): any {
250295
if (typeof value === 'string') {
251-
const envMatches = value.match(/\{\{([^}]+)\}\}/g)
252-
if (envMatches) {
253-
let resolvedValue = value
254-
for (const match of envMatches) {
255-
const envKey = match.slice(2, -2)
256-
const envValue = this.environmentVariables[envKey]
257-
258-
if (envValue === undefined) {
259-
throw new Error(`Environment variable "${envKey}" was not found.`)
260-
}
296+
// Only process environment variables if:
297+
// 1. This is an API key field
298+
// 2. String is a complete environment variable reference ({{ENV_VAR}})
299+
// 3. String contains environment variable references in proper contexts (auth headers, URLs)
300+
const isExplicitEnvVar = value.trim().startsWith('{{') && value.trim().endsWith('}}')
301+
const hasProperEnvVarReferences = this.containsProperEnvVarReference(value)
302+
303+
if (isApiKey || isExplicitEnvVar || hasProperEnvVarReferences) {
304+
const envMatches = value.match(/\{\{([^}]+)\}\}/g)
305+
if (envMatches) {
306+
let resolvedValue = value
307+
for (const match of envMatches) {
308+
const envKey = match.slice(2, -2)
309+
const envValue = this.environmentVariables[envKey]
310+
311+
if (envValue === undefined) {
312+
throw new Error(`Environment variable "${envKey}" was not found.`)
313+
}
261314

262-
resolvedValue = resolvedValue.replace(match, envValue)
315+
resolvedValue = resolvedValue.replace(match, envValue)
316+
}
317+
return resolvedValue
263318
}
264-
return resolvedValue
265319
}
266320
return value
267321
}
268322

269323
if (Array.isArray(value)) {
270-
return value.map((item) => this.resolveEnvVariables(item))
324+
return value.map((item) => this.resolveEnvVariables(item, isApiKey))
271325
}
272326

273327
if (value && typeof value === 'object') {
274328
return Object.entries(value).reduce(
275-
(acc, [k, v]) => ({ ...acc, [k]: this.resolveEnvVariables(v) }),
329+
(acc, [k, v]) => ({ ...acc, [k]: this.resolveEnvVariables(v, k.toLowerCase() === 'apikey') }),
276330
{}
277331
)
278332
}
@@ -303,8 +357,12 @@ export class InputResolver {
303357
if (typeof value === 'string') {
304358
// First resolve block references
305359
const resolvedReferences = this.resolveBlockReferences(value, context, currentBlock)
306-
// Then resolve environment variables
307-
return this.resolveEnvVariables(resolvedReferences)
360+
361+
// Check if this is an API key field
362+
const isApiKey = this.isApiKeyField(currentBlock, value)
363+
364+
// Then resolve environment variables with the API key flag
365+
return this.resolveEnvVariables(resolvedReferences, isApiKey)
308366
}
309367

310368
// Handle arrays
@@ -316,6 +374,7 @@ export class InputResolver {
316374
if (typeof value === 'object') {
317375
const result: Record<string, any> = {}
318376
for (const [k, v] of Object.entries(value)) {
377+
const isApiKey = k.toLowerCase() === 'apikey'
319378
result[k] = this.resolveNestedStructure(v, context, currentBlock)
320379
}
321380
return result
@@ -325,6 +384,38 @@ export class InputResolver {
325384
return value
326385
}
327386

387+
/**
388+
* Determines if a given field in a block is an API key field.
389+
*
390+
* @param block - Block containing the field
391+
* @param value - Value to check
392+
* @returns Whether this appears to be an API key field
393+
*/
394+
private isApiKeyField(block: SerializedBlock, value: string): boolean {
395+
// Check if the block is an API or agent block (which typically have API keys)
396+
const blockType = block.metadata?.id
397+
if (blockType !== 'api' && blockType !== 'agent') {
398+
return false
399+
}
400+
401+
// Look for the value in the block params
402+
for (const [key, paramValue] of Object.entries(block.config.params)) {
403+
if (paramValue === value) {
404+
// Check if key name suggests it's an API key
405+
const normalizedKey = key.toLowerCase().replace(/[_\-\s]/g, '')
406+
return (
407+
normalizedKey === 'apikey' ||
408+
normalizedKey.includes('apikey') ||
409+
normalizedKey.includes('secretkey') ||
410+
normalizedKey.includes('accesskey') ||
411+
normalizedKey.includes('token')
412+
)
413+
}
414+
}
415+
416+
return false
417+
}
418+
328419
/**
329420
* Formats a value for use in condition blocks.
330421
* Handles strings, null, undefined, and objects appropriately.

sim/app/w/[id]/components/workflow-block/components/sub-block/components/short-input.tsx

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,19 @@ export function ShortInput({
5454
const normalizedTitle = config?.title?.replace(/\s+/g, '').toLowerCase() || ''
5555

5656
// Check for common API key naming patterns
57-
const apiKeyPatterns = ['apikey', 'api_key', 'api-key', 'secretkey', 'secret_key', 'secret-key']
57+
const apiKeyPatterns = [
58+
'apikey',
59+
'api_key',
60+
'api-key',
61+
'secretkey',
62+
'secret_key',
63+
'secret-key',
64+
'token',
65+
'access_token',
66+
'auth_token',
67+
'secret',
68+
'password',
69+
]
5870

5971
return apiKeyPatterns.some(
6072
(pattern) =>
@@ -240,8 +252,13 @@ export function ShortInput({
240252
const displayValue =
241253
password && !isFocused ? '•'.repeat(value?.toString().length ?? 0) : (value?.toString() ?? '')
242254

243-
// Modify the EnvVarDropdown to use the correct setter
255+
// Explicitly mark environment variable references with '{{' and '}}' when inserting
244256
const handleEnvVarSelect = (newValue: string) => {
257+
// For API keys, ensure we're using the full value with {{ }} format
258+
if (isApiKeyField && !newValue.startsWith('{{')) {
259+
newValue = `{{${newValue}}}`
260+
}
261+
245262
if (onChange) {
246263
onChange(newValue)
247264
} else {

0 commit comments

Comments
 (0)