diff --git a/apps/sim/app/api/tools/execute-command/run/route.ts b/apps/sim/app/api/tools/execute-command/run/route.ts index e00dea0c5f..5d5216ae13 100644 --- a/apps/sim/app/api/tools/execute-command/run/route.ts +++ b/apps/sim/app/api/tools/execute-command/run/route.ts @@ -4,6 +4,7 @@ import { type NextRequest, NextResponse } from 'next/server' import { checkInternalAuth } from '@/lib/auth/hybrid' import { isExecuteCommandEnabled } from '@/lib/core/config/feature-flags' import { generateRequestId } from '@/lib/core/utils/request' +import { DEFAULT_EXECUTION_TIMEOUT_MS } from '@/lib/execution/constants' import { normalizeName, REFERENCE, SPECIAL_REFERENCE_PREFIXES } from '@/executor/constants' import { type OutputSchema, resolveBlockReference } from '@/executor/utils/block-reference' import { @@ -151,7 +152,7 @@ function collectTagReplacements( blockOutputSchemas: Record ): Replacement[] { const tagPattern = new RegExp( - `${REFERENCE.START}([^${REFERENCE.START}${REFERENCE.END}]+)${REFERENCE.END}`, + `${REFERENCE.START}(\\S[^${REFERENCE.START}${REFERENCE.END}]*)${REFERENCE.END}`, 'g' ) @@ -217,6 +218,16 @@ function resolveCommandVariables( allReplacements.sort((a, b) => a.index - b.index) + for (let i = 1; i < allReplacements.length; i++) { + const prev = allReplacements[i - 1] + const curr = allReplacements[i] + if (curr.index < prev.index + prev.length) { + throw new Error( + `Overlapping variable references detected at positions ${prev.index} and ${curr.index}` + ) + } + } + let resolved = command for (let i = allReplacements.length - 1; i >= 0; i--) { const { index, length, value } = allReplacements[i] @@ -310,7 +321,6 @@ export async function POST(req: NextRequest) { } const body = await req.json() - const { DEFAULT_EXECUTION_TIMEOUT_MS } = await import('@/lib/execution/constants') const { command, diff --git a/apps/sim/blocks/blocks/execute-command.ts b/apps/sim/blocks/blocks/execute-command.ts index 28d7ac3bef..cd7b65fcf7 100644 --- a/apps/sim/blocks/blocks/execute-command.ts +++ b/apps/sim/blocks/blocks/execute-command.ts @@ -1,5 +1,6 @@ import { TerminalIcon } from '@/components/icons' import { isTruthy } from '@/lib/core/config/env' +import { DEFAULT_EXECUTION_TIMEOUT_MS } from '@/lib/execution/constants' import type { BlockConfig } from '@/blocks/types' import type { ExecuteCommandOutput } from '@/tools/execute-command/types' @@ -59,6 +60,13 @@ IMPORTANT FORMATTING RULES: required: false, placeholder: '/path/to/directory', }, + { + id: 'timeout', + title: 'Timeout (ms)', + type: 'short-input', + required: false, + placeholder: String(DEFAULT_EXECUTION_TIMEOUT_MS), + }, ], tools: { access: ['execute_command_run'], @@ -66,6 +74,7 @@ IMPORTANT FORMATTING RULES: inputs: { command: { type: 'string', description: 'Shell command to execute' }, workingDirectory: { type: 'string', description: 'Working directory for the command' }, + timeout: { type: 'number', description: 'Execution timeout in milliseconds' }, }, outputs: { stdout: { type: 'string', description: 'Standard output from the command' }, diff --git a/apps/sim/tools/execute-command/execute.ts b/apps/sim/tools/execute-command/execute.ts index 5c39429233..11e28f34ab 100644 --- a/apps/sim/tools/execute-command/execute.ts +++ b/apps/sim/tools/execute-command/execute.ts @@ -19,7 +19,7 @@ export const executeCommandRunTool: ToolConfig