From 66bc887a2d0b58b9b61aa741f7fb5bae3f8ec028 Mon Sep 17 00:00:00 2001 From: Piotr Karwatka Date: Fri, 20 Dec 2024 06:43:20 +0100 Subject: [PATCH] feat: http request tool + example checking on the latest `fabrice` issues (#139) Related to #74 TODO: add `bdd` tests after merging #137 in --- example/src/fabrice_latest_issues.ts | 46 ++++++++++++++++++++++++ packages/tools/src/http.ts | 53 ++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+) create mode 100644 example/src/fabrice_latest_issues.ts create mode 100644 packages/tools/src/http.ts diff --git a/example/src/fabrice_latest_issues.ts b/example/src/fabrice_latest_issues.ts new file mode 100644 index 0000000..6181761 --- /dev/null +++ b/example/src/fabrice_latest_issues.ts @@ -0,0 +1,46 @@ +import 'dotenv/config' + +import { httpTool } from '@fabrice-ai/tools/http' +import { agent } from 'fabrice-ai/agent' +import { solution } from 'fabrice-ai/solution' +import { teamwork } from 'fabrice-ai/teamwork' +import { logger } from 'fabrice-ai/telemetry' +import { workflow } from 'fabrice-ai/workflow' + +const browser = agent({ + description: ` + You are skilled at browsing Web with specified URLs, + methods, params etc. + You are using "httpTool" to get the data from the API and/or Web pages. + `, + tools: { + httpTool, + }, +}) + +const wrapupRedactor = agent({ + description: ` + Your role is to check Github project details and check for latest issues. + `, +}) + +const checkupGithubProject = workflow({ + team: { browser, wrapupRedactor }, + description: ` + Check the project details for "fabrice-ai" using the following API URL: + "https://api.github.com/repos/callstackincubator/fabrice-ai". + + From the data received get the number of stars and the URL for the listing the issues. + List last top 3 issues and the number of star gazers for the project. + `, + output: ` + Comprehensive markdown report for fabrice-ai project: + - Include top 3 new issues. + - Include the actual number of star gazers. + `, + snapshot: logger, +}) + +const result = await teamwork(checkupGithubProject) + +console.log(solution(result)) diff --git a/packages/tools/src/http.ts b/packages/tools/src/http.ts new file mode 100644 index 0000000..ed54f4c --- /dev/null +++ b/packages/tools/src/http.ts @@ -0,0 +1,53 @@ +import axios from 'axios' +import { tool } from 'fabrice-ai/tool' +import { z } from 'zod' + +async function makeHttpRequest({ + url, + method, + headers, + body, +}: { + url: string + method: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' + headers?: Record + body?: any +}): Promise { + try { + const response = await axios({ + url, + method, + headers, + data: body, + }) + + if (typeof response.data === 'object') { + return JSON.stringify(response.data) + } else return response.data as string + } catch (error) { + if (axios.isAxiosError(error)) { + throw new Error( + `HTTP error ${error.response?.status}: ${error.response?.data || error.message}` + ) + } else { + throw new Error(`Unknown error: ${error}`) + } + } +} + +export const httpTool = tool({ + description: 'Makes HTTP requests to specified URLs with configurable method, headers, and body.', + parameters: z.object({ + url: z.string().describe('The URL to make the request to.'), + method: z.enum(['GET', 'POST', 'PUT', 'DELETE', 'PATCH']).describe('The HTTP method to use.'), + headers: z.record(z.string()).optional().describe('Headers to include in the HTTP request.'), + body: z + .string() + .describe( + 'The body of the HTTP request. For GET requests, this should typically be empty string. For other requests it could be JSON or other formats.' + ), + }), + execute: async ({ url, method, headers, body }) => { + return makeHttpRequest({ url, method, headers, body }) + }, +})