* Execute a tool request directly * Internal routes (/api/...) use regular fetch * External URLs use SSRF-protected fetch with DNS validation and IP pinning
( toolId: string, tool: ToolConfig, params: Record<string, any>, signal?: AbortSignal )
| 1524 | * External URLs use SSRF-protected fetch with DNS validation and IP pinning |
| 1525 | */ |
| 1526 | async function executeToolRequest( |
| 1527 | toolId: string, |
| 1528 | tool: ToolConfig, |
| 1529 | params: Record<string, any>, |
| 1530 | signal?: AbortSignal |
| 1531 | ): Promise<ToolResponse> { |
| 1532 | const requestId = generateRequestId() |
| 1533 | |
| 1534 | const requestParams = formatRequestParams(tool, params) |
| 1535 | |
| 1536 | try { |
| 1537 | const endpointUrl = |
| 1538 | typeof tool.request.url === 'function' ? tool.request.url(params) : tool.request.url |
| 1539 | const isInternalRoute = endpointUrl.startsWith('/api/') |
| 1540 | const baseUrl = isInternalRoute ? getInternalApiBaseUrl() : getBaseUrl() |
| 1541 | |
| 1542 | const fullUrlObj = new URL(endpointUrl, baseUrl) |
| 1543 | |
| 1544 | if (isInternalRoute) { |
| 1545 | const workflowId = params._context?.workflowId |
| 1546 | if (workflowId) { |
| 1547 | fullUrlObj.searchParams.set('workflowId', workflowId) |
| 1548 | } |
| 1549 | const userId = params._context?.userId |
| 1550 | if (userId) { |
| 1551 | fullUrlObj.searchParams.set('userId', userId) |
| 1552 | } |
| 1553 | } |
| 1554 | |
| 1555 | const fullUrl = fullUrlObj.toString() |
| 1556 | |
| 1557 | if (isCustomTool(toolId) && tool.request.body) { |
| 1558 | const requestBody = tool.request.body(params) |
| 1559 | if ( |
| 1560 | typeof requestBody === 'object' && |
| 1561 | requestBody !== null && |
| 1562 | 'schema' in requestBody && |
| 1563 | 'params' in requestBody |
| 1564 | ) { |
| 1565 | try { |
| 1566 | validateClientSideParams( |
| 1567 | requestBody.params as Record<string, any>, |
| 1568 | requestBody.schema as { |
| 1569 | type: string |
| 1570 | properties: Record<string, any> |
| 1571 | required?: string[] |
| 1572 | } |
| 1573 | ) |
| 1574 | } catch (validationError) { |
| 1575 | logger.error(`[${requestId}] Custom tool validation failed for ${toolId}:`, { |
| 1576 | error: toError(validationError).message, |
| 1577 | }) |
| 1578 | throw validationError |
| 1579 | } |
| 1580 | } |
| 1581 | } |
| 1582 | |
| 1583 | const headers = new Headers(requestParams.headers) |
no test coverage detected