import * as plugins from './plugins.js'; import * as interfaces from './smartagent.interfaces.js'; import { BaseToolWrapper } from './smartagent.tools.base.js'; /** * HTTP tool for making web requests * Wraps @push.rocks/smartrequest */ export class HttpTool extends BaseToolWrapper { public name = 'http'; public description = 'Make HTTP requests to web APIs and services'; public actions: interfaces.IToolAction[] = [ { name: 'get', description: 'Make a GET request', parameters: { type: 'object', properties: { url: { type: 'string', description: 'URL to request' }, headers: { type: 'object', description: 'Request headers (key-value pairs)' }, query: { type: 'object', description: 'Query parameters (key-value pairs)' }, timeout: { type: 'number', description: 'Timeout in milliseconds' }, }, required: ['url'], }, }, { name: 'post', description: 'Make a POST request with JSON body', parameters: { type: 'object', properties: { url: { type: 'string', description: 'URL to request' }, body: { type: 'object', description: 'JSON body to send' }, headers: { type: 'object', description: 'Request headers (key-value pairs)' }, query: { type: 'object', description: 'Query parameters (key-value pairs)' }, timeout: { type: 'number', description: 'Timeout in milliseconds' }, }, required: ['url'], }, }, { name: 'put', description: 'Make a PUT request with JSON body', parameters: { type: 'object', properties: { url: { type: 'string', description: 'URL to request' }, body: { type: 'object', description: 'JSON body to send' }, headers: { type: 'object', description: 'Request headers (key-value pairs)' }, timeout: { type: 'number', description: 'Timeout in milliseconds' }, }, required: ['url', 'body'], }, }, { name: 'patch', description: 'Make a PATCH request with JSON body', parameters: { type: 'object', properties: { url: { type: 'string', description: 'URL to request' }, body: { type: 'object', description: 'JSON body to send' }, headers: { type: 'object', description: 'Request headers (key-value pairs)' }, timeout: { type: 'number', description: 'Timeout in milliseconds' }, }, required: ['url', 'body'], }, }, { name: 'delete', description: 'Make a DELETE request', parameters: { type: 'object', properties: { url: { type: 'string', description: 'URL to request' }, headers: { type: 'object', description: 'Request headers (key-value pairs)' }, timeout: { type: 'number', description: 'Timeout in milliseconds' }, }, required: ['url'], }, }, ]; public async initialize(): Promise { // SmartRequest is stateless, no initialization needed this.isInitialized = true; } public async cleanup(): Promise { this.isInitialized = false; } public async execute( action: string, params: Record ): Promise { this.validateAction(action); this.ensureInitialized(); try { let request = plugins.smartrequest.SmartRequest.create().url(params.url as string); // Add headers if (params.headers && typeof params.headers === 'object') { for (const [key, value] of Object.entries(params.headers as Record)) { request = request.header(key, value); } } // Add query parameters if (params.query && typeof params.query === 'object') { request = request.query(params.query as Record); } // Add timeout if (params.timeout) { request = request.timeout(params.timeout as number); } // Add JSON body for POST, PUT, PATCH if (params.body && ['post', 'put', 'patch'].includes(action)) { request = request.json(params.body); } // Execute the request let response; switch (action) { case 'get': response = await request.get(); break; case 'post': response = await request.post(); break; case 'put': response = await request.put(); break; case 'patch': response = await request.patch(); break; case 'delete': response = await request.delete(); break; default: return { success: false, error: `Unknown action: ${action}` }; } // Parse response body let body: unknown; const contentType = response.headers?.['content-type'] || ''; try { if (contentType.includes('application/json')) { body = await response.json(); } else { body = await response.text(); } } catch { body = null; } return { success: response.ok, result: { url: params.url, method: action.toUpperCase(), status: response.status, statusText: response.statusText, ok: response.ok, headers: response.headers, body, }, }; } catch (error) { return { success: false, error: error instanceof Error ? error.message : String(error), }; } } public getCallSummary(action: string, params: Record): string { const method = action.toUpperCase(); let summary = `${method} request to "${params.url}"`; if (params.query && Object.keys(params.query as object).length > 0) { const queryStr = JSON.stringify(params.query); summary += ` with query: ${queryStr.length > 50 ? queryStr.substring(0, 50) + '...' : queryStr}`; } if (params.body) { const bodyStr = JSON.stringify(params.body); const preview = bodyStr.length > 100 ? bodyStr.substring(0, 100) + '...' : bodyStr; summary += ` with body: ${preview}`; } if (params.headers && Object.keys(params.headers as object).length > 0) { const headerKeys = Object.keys(params.headers as object).join(', '); summary += ` with headers: [${headerKeys}]`; } return summary; } }