MCPcopy Index your code
hub / github.com/simstudioai/sim / executeToolWithWatchdog

Function executeToolWithWatchdog

apps/sim/lib/copilot/request/tools/executor.ts:266–292  ·  view source on GitHub ↗

* Execute a tool with a hard settlement guarantee. If the handler neither * resolves nor rejects within the tool's watchdog cap, throw a timeout error * so the standard failure path (persist failed row, publish terminal * confirmation, resume Go with an error result) runs and the chat never * we

(toolCall: ToolCallState, execContext: ExecutionContext)

Source from the content-addressed store, hash-verified

264 * eventual settlement is ignored.
265 */
266async function executeToolWithWatchdog(toolCall: ToolCallState, execContext: ExecutionContext) {
267 const timeoutMs = toolWatchdogTimeoutMs(toolCall.name)
268 // Thread the invoking subagent's channel id per call (execContext is shared
269 // across the whole turn, so the channel id can't live on it) — server tools
270 // use it to scope the workspace_file -> edit_content intent handoff.
271 const toolContext = toolCall.parentToolCallId
272 ? { ...execContext, parentToolCallId: toolCall.parentToolCallId }
273 : execContext
274 const execution = executeTool(toolCall.name, toolCall.params || {}, toolContext)
275 let timer: ReturnType<typeof setTimeout> | undefined
276 try {
277 return await Promise.race([
278 execution,
279 new Promise<never>((_, reject) => {
280 timer = setTimeout(
281 () => reject(new ToolExecutionTimeoutError(toolCall.name, timeoutMs)),
282 timeoutMs
283 )
284 }),
285 ])
286 } finally {
287 if (timer) clearTimeout(timer)
288 // Swallow the abandoned promise's eventual rejection so it can't surface
289 // as an unhandled rejection after a watchdog loss.
290 execution.catch(() => {})
291 }
292}
293
294/**
295 * Last-resort settlement for a tool whose promise never settled (a hang the

Callers 1

Calls 2

executeToolFunction · 0.90
toolWatchdogTimeoutMsFunction · 0.85

Tested by

no test coverage detected