From 9d061cd7f79ef7e533c4a28446b8f23535da700f Mon Sep 17 00:00:00 2001 From: Tobiloba Adedeji Date: Thu, 13 Mar 2025 01:22:35 +0100 Subject: [PATCH 1/2] docs: add api docs fetching to docs --- .../AgentsAPIViewer/APIViewer.astro | 278 ++++++++++++++++++ .../docs/ai-agents/Agents-APIs/index.mdx | 10 + 2 files changed, 288 insertions(+) create mode 100644 src/components/AgentsAPIViewer/APIViewer.astro diff --git a/src/components/AgentsAPIViewer/APIViewer.astro b/src/components/AgentsAPIViewer/APIViewer.astro new file mode 100644 index 000000000..93843a2b9 --- /dev/null +++ b/src/components/AgentsAPIViewer/APIViewer.astro @@ -0,0 +1,278 @@ +--- +interface OpenAPIInfo { + title: string; + description: string; +} + +interface OpenAPIParameter { + name: string; + in: string; + description: string; + required: boolean; + schema?: any; + example?: any; +} + +interface OpenAPIExample { + summary: string; + value: any; +} + +interface OpenAPIContent { + schema?: any; + examples?: Record; +} + +interface OpenAPIResponse { + description: string; + content?: Record; +} + +interface OpenAPIRequestBody { + required?: boolean; + content?: Record; +} + +interface OpenAPIMethod { + summary: string; + description: string; + parameters?: OpenAPIParameter[]; + requestBody?: OpenAPIRequestBody; + responses: Record; +} + +interface OpenAPIData { + openapi: string; + info: OpenAPIInfo; + paths: Record>; + components: any; + tags: Array<{ name: string }>; +} + +// Fetch the OpenAPI spec at build time +let apiData: OpenAPIData | null = null; +let error: string | null = null; + +try { + const response = await fetch('https://api.fleek.xyz/api/openapi.json'); + if (!response.ok) { + throw new Error( + `Failed to fetch API spec: ${response.status} ${response.statusText}`, + ); + } + + const fullData = await response.json(); + + const aiAgentsPaths: Record> = {}; + + for (const [path, methods] of Object.entries(fullData.paths)) { + if (path.includes('ai-agents')) { + aiAgentsPaths[path] = methods as Record; + } + } + + apiData = { + openapi: fullData.openapi, + info: fullData.info, + paths: aiAgentsPaths, + components: fullData.components, + tags: fullData.tags.filter( + (tag: { name: string }) => tag.name === 'AI Agents', + ), + }; +} catch (err) { + console.error('Error fetching or parsing OpenAPI spec:', err); + error = 'Failed to load API documentation. Please try again later.'; +} + +function getMethodColor(method: string): string { + switch (method.toLowerCase()) { + case 'get': + return 'bg-blue-500'; + case 'post': + return 'bg-green-500'; + case 'put': + return 'bg-yellow-dark-8'; + case 'delete': + return 'bg-red-dark-8'; + default: + return 'bg-gray-500'; + } +} + +function formatJSON(obj: any): string { + return JSON.stringify(obj, null, 2); +} +--- + +{ + error ? ( +
{error}
+ ) : apiData ? ( +
+
+ {Object.entries(apiData.paths).map(([path, methods]) => ( +
+

{path}

+ +
+ {Object.entries(methods).map(([method, details]) => ( +
+
+ + {method} + + {details.summary} +
+ +
+ {details.description} +
+ + {details.parameters && details.parameters.length > 0 && ( +
+

Parameters:

+
    + {details.parameters.map((param) => ( +
  • + {param.name} + {param.required && ( + * + )} + ({param.in}) - + {param.description} + {param.example && ( +
    + + Example:{' '} + + + {param.example.toString()} + +
    + )} +
  • + ))} +
+
+ )} + + {details.requestBody && ( +
+

Request Body:

+
+ {details.requestBody.required && ( + Required. + )} + {details.requestBody.content && + Object.entries(details.requestBody.content).map( + ([contentType, content]) => ( +
+
+ + {contentType} + +
+ + {/* Request Body Examples */} + {content.examples && + Object.keys(content.examples).length > 0 && ( +
+
+ Examples: +
+
+ {Object.entries(content.examples).map( + ([exampleName, example]) => ( +
+ + {example.summary || exampleName} + + + {formatJSON(example.value)} + +
+ ), + )} +
+
+ )} +
+ ), + )} +
+
+ )} + +
+

Responses:

+
+ {Object.entries(details.responses).map( + ([status, response]) => ( +
+
Status: {status}
+
+ {response.description} +
+ + {/* Response Examples */} + {response.content && + Object.entries(response.content).map( + ([contentType, content]) => ( +
+
+ {contentType} +
+ + {content.examples && + Object.keys(content.examples).length > + 0 && ( +
+
+ + View Example + +
+ {Object.entries( + content.examples, + ).map( + ([exampleName, example]) => ( +
+ {example.summary && ( +
+ {example.summary} +
+ )} + + {formatJSON( + example.value, + )} + +
+ ), + )} +
+
+
+ )} +
+ ), + )} +
+ ), + )} +
+
+
+ ))} +
+
+ ))} +
+
+ ) : ( +
Loading API documentation...
+ ) +} diff --git a/src/content/docs/ai-agents/Agents-APIs/index.mdx b/src/content/docs/ai-agents/Agents-APIs/index.mdx index 81d247b93..c3c586b14 100644 --- a/src/content/docs/ai-agents/Agents-APIs/index.mdx +++ b/src/content/docs/ai-agents/Agents-APIs/index.mdx @@ -5,6 +5,8 @@ date: 2025-01-24 desc: AI agent APIs from Fleek. --- +import AIAgentsAPIViewer from '../../../../components/AgentsAPIViewer/APIViewer.astro'; + # Fleek AI Agent APIs :::info @@ -103,3 +105,11 @@ fetch('https://api.fleek.xyz/api/v1/ai-agents/12345/api/message', { ``` For more details, check the full API docs . + +## Agent API endpoints + +:::note +Each request to the Fleek AI agent API must include the `X-Api-Key` header with the API key you generated. +::: + + From a4120f64bae70343a92679a1e116eca38eb5c78f Mon Sep 17 00:00:00 2001 From: Bruno Camarneiro Date: Thu, 13 Mar 2025 10:04:08 +0100 Subject: [PATCH 2/2] use react compoenent instead of astro file --- .../AgentsAPIViewer/APIViewer.astro | 278 ----------------- src/components/AgentsAPIViewer/APIViewer.tsx | 294 ++++++++++++++++++ .../docs/ai-agents/Agents-APIs/index.mdx | 4 +- 3 files changed, 296 insertions(+), 280 deletions(-) delete mode 100644 src/components/AgentsAPIViewer/APIViewer.astro create mode 100644 src/components/AgentsAPIViewer/APIViewer.tsx diff --git a/src/components/AgentsAPIViewer/APIViewer.astro b/src/components/AgentsAPIViewer/APIViewer.astro deleted file mode 100644 index 93843a2b9..000000000 --- a/src/components/AgentsAPIViewer/APIViewer.astro +++ /dev/null @@ -1,278 +0,0 @@ ---- -interface OpenAPIInfo { - title: string; - description: string; -} - -interface OpenAPIParameter { - name: string; - in: string; - description: string; - required: boolean; - schema?: any; - example?: any; -} - -interface OpenAPIExample { - summary: string; - value: any; -} - -interface OpenAPIContent { - schema?: any; - examples?: Record; -} - -interface OpenAPIResponse { - description: string; - content?: Record; -} - -interface OpenAPIRequestBody { - required?: boolean; - content?: Record; -} - -interface OpenAPIMethod { - summary: string; - description: string; - parameters?: OpenAPIParameter[]; - requestBody?: OpenAPIRequestBody; - responses: Record; -} - -interface OpenAPIData { - openapi: string; - info: OpenAPIInfo; - paths: Record>; - components: any; - tags: Array<{ name: string }>; -} - -// Fetch the OpenAPI spec at build time -let apiData: OpenAPIData | null = null; -let error: string | null = null; - -try { - const response = await fetch('https://api.fleek.xyz/api/openapi.json'); - if (!response.ok) { - throw new Error( - `Failed to fetch API spec: ${response.status} ${response.statusText}`, - ); - } - - const fullData = await response.json(); - - const aiAgentsPaths: Record> = {}; - - for (const [path, methods] of Object.entries(fullData.paths)) { - if (path.includes('ai-agents')) { - aiAgentsPaths[path] = methods as Record; - } - } - - apiData = { - openapi: fullData.openapi, - info: fullData.info, - paths: aiAgentsPaths, - components: fullData.components, - tags: fullData.tags.filter( - (tag: { name: string }) => tag.name === 'AI Agents', - ), - }; -} catch (err) { - console.error('Error fetching or parsing OpenAPI spec:', err); - error = 'Failed to load API documentation. Please try again later.'; -} - -function getMethodColor(method: string): string { - switch (method.toLowerCase()) { - case 'get': - return 'bg-blue-500'; - case 'post': - return 'bg-green-500'; - case 'put': - return 'bg-yellow-dark-8'; - case 'delete': - return 'bg-red-dark-8'; - default: - return 'bg-gray-500'; - } -} - -function formatJSON(obj: any): string { - return JSON.stringify(obj, null, 2); -} ---- - -{ - error ? ( -
{error}
- ) : apiData ? ( -
-
- {Object.entries(apiData.paths).map(([path, methods]) => ( -
-

{path}

- -
- {Object.entries(methods).map(([method, details]) => ( -
-
- - {method} - - {details.summary} -
- -
- {details.description} -
- - {details.parameters && details.parameters.length > 0 && ( -
-

Parameters:

-
    - {details.parameters.map((param) => ( -
  • - {param.name} - {param.required && ( - * - )} - ({param.in}) - - {param.description} - {param.example && ( -
    - - Example:{' '} - - - {param.example.toString()} - -
    - )} -
  • - ))} -
-
- )} - - {details.requestBody && ( -
-

Request Body:

-
- {details.requestBody.required && ( - Required. - )} - {details.requestBody.content && - Object.entries(details.requestBody.content).map( - ([contentType, content]) => ( -
-
- - {contentType} - -
- - {/* Request Body Examples */} - {content.examples && - Object.keys(content.examples).length > 0 && ( -
-
- Examples: -
-
- {Object.entries(content.examples).map( - ([exampleName, example]) => ( -
- - {example.summary || exampleName} - - - {formatJSON(example.value)} - -
- ), - )} -
-
- )} -
- ), - )} -
-
- )} - -
-

Responses:

-
- {Object.entries(details.responses).map( - ([status, response]) => ( -
-
Status: {status}
-
- {response.description} -
- - {/* Response Examples */} - {response.content && - Object.entries(response.content).map( - ([contentType, content]) => ( -
-
- {contentType} -
- - {content.examples && - Object.keys(content.examples).length > - 0 && ( -
-
- - View Example - -
- {Object.entries( - content.examples, - ).map( - ([exampleName, example]) => ( -
- {example.summary && ( -
- {example.summary} -
- )} - - {formatJSON( - example.value, - )} - -
- ), - )} -
-
-
- )} -
- ), - )} -
- ), - )} -
-
-
- ))} -
-
- ))} -
-
- ) : ( -
Loading API documentation...
- ) -} diff --git a/src/components/AgentsAPIViewer/APIViewer.tsx b/src/components/AgentsAPIViewer/APIViewer.tsx new file mode 100644 index 000000000..987017da6 --- /dev/null +++ b/src/components/AgentsAPIViewer/APIViewer.tsx @@ -0,0 +1,294 @@ +import { useCallback, useEffect, useState } from "react"; + +interface OpenAPIInfo { + title: string; + description: string; +} + +interface OpenAPIParameter { + name: string; + in: string; + description: string; + required: boolean; + schema?: any; + example?: any; +} + +interface OpenAPIExample { + summary: string; + value: any; +} + +interface OpenAPIContent { + schema?: any; + examples?: Record; +} + +interface OpenAPIResponse { + description: string; + content?: Record; +} + +interface OpenAPIRequestBody { + required?: boolean; + content?: Record; +} + +interface OpenAPIMethod { + summary: string; + description: string; + parameters?: OpenAPIParameter[]; + requestBody?: OpenAPIRequestBody; + responses: Record; +} + +interface OpenAPIData { + openapi: string; + info: OpenAPIInfo; + paths: Record>; + components: any; + tags: Array<{ name: string }>; +} + +const APIViewer = () => { + // Fetch the OpenAPI spec at build time + const [apiData, setApiData] = useState(); + const [error, setError] = useState(); + + const fetchData = useCallback(async () => { + try { + const response = await fetch("https://api.fleek.xyz/api/openapi.json"); + if (!response.ok) { + throw new Error( + `Failed to fetch API spec: ${response.status} ${response.statusText}`, + ); + } + + const fullData = await response.json(); + + const aiAgentsPaths: Record> = {}; + + for (const [path, methods] of Object.entries(fullData.paths)) { + if (path.includes("ai-agents")) { + aiAgentsPaths[path] = methods as Record; + } + } + + setApiData({ + openapi: fullData.openapi, + info: fullData.info, + paths: aiAgentsPaths, + components: fullData.components, + tags: fullData.tags.filter( + (tag: { name: string }) => tag.name === "AI Agents", + ), + }); + } catch (err) { + console.error("Error fetching or parsing OpenAPI spec:", err); + setError("Failed to load API documentation. Please try again later."); + } + }, []); + + useEffect(() => { + fetchData(); + }, [fetchData]); + + function getMethodColor(method: string): string { + switch (method.toLowerCase()) { + case "get": + return "bg-blue-500"; + case "post": + return "bg-green-500"; + case "put": + return "bg-yellow-dark-8"; + case "delete": + return "bg-red-dark-8"; + default: + return "bg-gray-500"; + } + } + + function formatJSON(obj: any): string { + return JSON.stringify(obj, null, 2); + } + + if (error) { + return
{error}
; + } + + if (!apiData) { + return
Loading API documentation...
; + } + + return ( +
+
+ {Object.entries(apiData.paths).map(([path, methods]) => ( +
+

{path}

+ +
+ {Object.entries(methods).map(([method, details]) => ( +
+
+ + {method} + + {details.summary} +
+ +
+ {details.description} +
+ + {details.parameters && details.parameters.length > 0 && ( +
+

+ Parameters: +

+
    + {details.parameters.map((param) => ( +
  • + {param.name} + {param.required && ( + * + )} + ({param.in}) - + {param.description} + {param.example && ( +
    + + Example:{" "} + + + {param.example.toString()} + +
    + )} +
  • + ))} +
+
+ )} + + {details.requestBody && ( +
+

+ Request Body: +

+
+ {details.requestBody.required && ( + Required. + )} + {details.requestBody.content && + Object.entries(details.requestBody.content).map( + ([contentType, content]) => ( +
+
+ + {contentType} + +
+ + {/* Request Body Examples */} + {content.examples && + Object.keys(content.examples).length > 0 && ( +
+
+ Examples: +
+
+ {Object.entries(content.examples).map( + ([exampleName, example]) => ( +
+ + {example.summary || exampleName} + + + {formatJSON(example.value)} + +
+ ), + )} +
+
+ )} +
+ ), + )} +
+
+ )} + +
+

Responses:

+
+ {Object.entries(details.responses).map( + ([status, response]) => ( +
+
Status: {status}
+
+ {response.description} +
+ + {/* Response Examples */} + {response.content && + Object.entries(response.content).map( + ([contentType, content]) => ( +
+
+ {contentType} +
+ + {content.examples && + Object.keys(content.examples).length > + 0 && ( +
+
+ + View Example + +
+ {Object.entries( + content.examples, + ).map( + ([exampleName, example]) => ( +
+ {example.summary && ( +
+ {example.summary} +
+ )} + + {formatJSON( + example.value, + )} + +
+ ), + )} +
+
+
+ )} +
+ ), + )} +
+ ), + )} +
+
+
+ ))} +
+
+ ))} +
+
+ ); +}; + +export default APIViewer; diff --git a/src/content/docs/ai-agents/Agents-APIs/index.mdx b/src/content/docs/ai-agents/Agents-APIs/index.mdx index c3c586b14..5f68a05ef 100644 --- a/src/content/docs/ai-agents/Agents-APIs/index.mdx +++ b/src/content/docs/ai-agents/Agents-APIs/index.mdx @@ -5,7 +5,7 @@ date: 2025-01-24 desc: AI agent APIs from Fleek. --- -import AIAgentsAPIViewer from '../../../../components/AgentsAPIViewer/APIViewer.astro'; +import AIAgentsAPIViewer from '@base/components/AgentsAPIViewer/APIViewer.tsx'; # Fleek AI Agent APIs @@ -112,4 +112,4 @@ For more details, check the +