Merge pull request #9 from sahiixx/cursor/update-ai-agent-api-reference-documentation-dfae

Update AI agent API reference documentation
This commit is contained in:
Sahiix@1 2025-10-02 09:02:27 +04:00 committed by GitHub
commit 5d913e5e0f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 1643 additions and 0 deletions

View File

@ -0,0 +1,47 @@
# Universal AI Agent Artifact Bundle
Contents:
- `openapi/openapi.yaml`: OpenAPI 3.0 spec
- `postman/UniversalAI.postman_collection.json`: Postman collection (variables: `baseUrl`, `token`)
- `clients/node`: Node client (ESM), SSE streaming, WebSocket sample, rate-limited fetch
- `clients/python`: Python client (`requests`), SSE streaming
- `utils`: Rate-limit-safe helpers (`rate_limit.js`, `rate_limit.py`)
- `scripts/curl.sh`: Handy cURL commands
Quickstart:
1) Postman
- Import `postman/UniversalAI.postman_collection.json`
- Set variables `baseUrl`, `token`
2) OpenAPI
- Load `openapi/openapi.yaml` into Swagger UI/Insomnia/Stoplight
3) Node client
```bash
cd clients/node
npm install
BASE_URL=https://your-domain.com TOKEN=YOUR_TOKEN npm start
# WebSocket sample
BASE_URL=https://your-domain.com TOKEN=YOUR_TOKEN npm run ws
```
4) Python client
```bash
cd clients/python
python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
BASE_URL=https://your-domain.com TOKEN=YOUR_TOKEN python examples.py
```
5) cURL
```bash
cd scripts
chmod +x curl.sh
BASE_URL=https://your-domain.com TOKEN=YOUR_TOKEN ./curl.sh chat "Hello"
```
Notes:
- Set `BASE_URL` and `TOKEN` environment variables for all samples.
- Streaming responses are SSE (Server-Sent Events) and parsed via `data: ...` lines.
- Retry/backoff on HTTP 429/5xx is implemented in the rate-limit helpers.

View File

@ -0,0 +1,14 @@
{
"name": "universal-ai-client",
"version": "0.1.0",
"private": true,
"type": "module",
"engines": { "node": ">=18" },
"dependencies": {
"ws": "^8.17.0"
},
"scripts": {
"start": "node src/examples.js",
"ws": "node src/ws_example.js"
}
}

View File

@ -0,0 +1,117 @@
import { rateLimitedFetch } from '../../utils/rate_limit.js';
export class UniversalAIClient {
constructor(baseUrl, token) {
this.baseUrl = (baseUrl || '').replace(/\/$/, '');
this.token = token;
}
_headers(json = true) {
const headers = { 'Authorization': `Bearer ${this.token}` };
if (json) headers['Content-Type'] = 'application/json';
return headers;
}
async chat(message, options = {}) {
const response = await rateLimitedFetch(fetch, `${this.baseUrl}/chat`, {
method: 'POST',
headers: this._headers(true),
body: JSON.stringify({ message, ...options })
});
return response.json();
}
async streamChat(message, onChunk, { optimizePrompt = true } = {}) {
const url = `${this.baseUrl}/stream?message=${encodeURIComponent(message)}&optimizePrompt=${optimizePrompt}`;
const response = await rateLimitedFetch(fetch, url, {
method: 'GET',
headers: { ...this._headers(false), 'Accept': 'text/event-stream' }
});
const reader = response.body.getReader();
const decoder = new TextDecoder();
while (true) {
const { done, value } = await reader.read();
if (done) break;
const chunk = decoder.decode(value);
for (const line of chunk.split('\n')) {
if (line.startsWith('data: ')) {
try {
const data = JSON.parse(line.slice(6));
if (onChunk) onChunk(data);
} catch (_) { /* ignore parse errors */ }
}
}
}
}
async getConversations({ limit = 50, offset = 0, userId } = {}) {
const url = new URL(`${this.baseUrl}/conversations`);
url.searchParams.set('limit', String(limit));
url.searchParams.set('offset', String(offset));
if (userId) url.searchParams.set('userId', userId);
const response = await rateLimitedFetch(fetch, url.toString(), {
method: 'GET',
headers: this._headers(false)
});
return response.json();
}
async ragIngest(documents, collection = 'knowledge_base') {
const response = await rateLimitedFetch(fetch, `${this.baseUrl}/rag/ingest`, {
method: 'POST',
headers: this._headers(true),
body: JSON.stringify({ documents, collection })
});
return response.json();
}
async ragSearch(query, { collection = 'knowledge_base', limit = 5, threshold } = {}) {
const payload = { query, collection, limit };
if (typeof threshold === 'number') payload.threshold = threshold;
const response = await rateLimitedFetch(fetch, `${this.baseUrl}/rag/search`, {
method: 'POST',
headers: this._headers(true),
body: JSON.stringify(payload)
});
return response.json();
}
async ragAnswer(question, { collection = 'knowledge_base', maxContext = 3, includeContext = true } = {}) {
const response = await rateLimitedFetch(fetch, `${this.baseUrl}/rag/answer`, {
method: 'POST',
headers: this._headers(true),
body: JSON.stringify({ question, collection, maxContext, includeContext })
});
return response.json();
}
async listPlugins() {
const response = await rateLimitedFetch(fetch, `${this.baseUrl}/plugins`, {
method: 'GET',
headers: this._headers(false)
});
return response.json();
}
async executePlugin(pluginName, action, parameters = {}) {
const response = await rateLimitedFetch(fetch, `${this.baseUrl}/plugins/${encodeURIComponent(pluginName)}/execute`, {
method: 'POST',
headers: this._headers(true),
body: JSON.stringify({ action, parameters })
});
return response.json();
}
async analyticsDashboard() {
const response = await rateLimitedFetch(fetch, `${this.baseUrl}/analytics/dashboard`, {
method: 'GET',
headers: this._headers(false)
});
return response.json();
}
}
export default UniversalAIClient;

View File

@ -0,0 +1,31 @@
import UniversalAIClient from './client.js';
const BASE_URL = process.env.BASE_URL || 'https://your-domain.com';
const TOKEN = process.env.TOKEN || 'YOUR_TOKEN';
const client = new UniversalAIClient(BASE_URL, TOKEN);
async function main() {
console.log('Chat:');
const chat = await client.chat('Hello, how are you?', { optimizePrompt: true });
console.log(chat);
console.log('\nStreaming:');
await client.streamChat('Tell me a short story.', (chunk) => {
if (chunk.type === 'chunk') process.stdout.write(chunk.content);
if (chunk.type === 'end') console.log('\n[stream end]', chunk.metadata);
});
console.log('\nRAG Search:');
const search = await client.ragSearch('machine learning algorithms', { collection: 'knowledge_base', limit: 3 });
console.log(search.results?.map(r => ({ id: r.id, score: r.score })));
console.log('\nPlugin Execute:');
const plugin = await client.executePlugin('web-scraper', 'scrape', { url: 'https://example.com', selector: '.content', format: 'text' });
console.log(plugin);
}
main().catch((err) => {
console.error(err);
process.exit(1);
});

View File

@ -0,0 +1,36 @@
import WebSocket from 'ws';
const BASE_URL = process.env.BASE_URL || 'https://your-domain.com';
const TOKEN = process.env.TOKEN || 'YOUR_TOKEN';
const WS_URL = process.env.WS_URL || BASE_URL.replace(/^http/, 'ws');
const ws = new WebSocket(WS_URL);
ws.on('open', () => {
console.log('WS connected, authenticating...');
ws.send(JSON.stringify({ type: 'auth', token: TOKEN }));
});
ws.on('message', (buf) => {
const msgText = buf.toString();
try {
const data = JSON.parse(msgText);
if (data.type === 'auth_success') {
console.log('Auth OK, sending stream_chat');
ws.send(JSON.stringify({ type: 'stream_chat', text: 'Tell me a story', optimizePrompt: true }));
} else if (data.type === 'stream_chunk') {
process.stdout.write(data.chunk);
} else if (data.type === 'chat_response') {
console.log('\n[chat_response]', data.message);
} else if (data.type === 'error') {
console.error('WS error:', data.message);
} else {
console.log('[WS]', data);
}
} catch (_) {
console.log('[RAW]', msgText);
}
});
ws.on('close', () => console.log('WS closed'));
ws.on('error', (err) => console.error('WS error', err));

View File

@ -0,0 +1,25 @@
from universal_ai_client import UniversalAIClient
import os
BASE_URL = os.environ.get('BASE_URL', 'https://your-domain.com')
TOKEN = os.environ.get('TOKEN', 'YOUR_TOKEN')
client = UniversalAIClient(BASE_URL, TOKEN)
print('Chat:')
print(client.chat('Hello, how are you?', optimizePrompt=True))
print('\nStreaming:')
for event in client.stream_chat('Tell me a short story.'):
if event.get('type') == 'chunk':
print(event.get('content', ''), end='', flush=True)
elif event.get('type') == 'end':
print('\n[stream end]', event.get('metadata'))
break
print('\nRAG Search:')
search = client.rag_search('machine learning algorithms', collection='knowledge_base', limit=3)
print([{'id': r['id'], 'score': r['score']} for r in search.get('results', [])])
print('\nPlugin Execute:')
print(client.execute_plugin('web-scraper', 'scrape', { 'url': 'https://example.com', 'selector': '.content', 'format': 'text' }))

View File

@ -0,0 +1 @@
requests>=2.31.0

View File

@ -0,0 +1,97 @@
from __future__ import annotations
import json
from typing import Any, Dict, Generator, Iterable, Optional
import requests
from utils.rate_limit import request_with_retries
class UniversalAIClient:
def __init__(self, base_url: str, token: str):
self.base_url = base_url.rstrip('/')
self.token = token
self.session = requests.Session()
self.session.headers.update({'Authorization': f'Bearer {token}'})
def _json(self, method: str, path: str, json_body: Optional[Dict[str, Any]] = None, stream: bool = False) -> requests.Response:
url = f"{self.base_url}{path}"
headers = {}
if not stream:
headers['Content-Type'] = 'application/json'
return request_with_retries(
self.session.request,
method=method,
url=url,
json=json_body,
headers=headers,
stream=stream,
)
def chat(self, message: str, **kwargs: Any) -> Dict[str, Any]:
resp = self._json('POST', '/chat', { 'message': message, **kwargs })
resp.raise_for_status()
return resp.json()
def stream_chat(self, message: str, optimize_prompt: bool = True) -> Generator[Dict[str, Any], None, None]:
params = {
'message': message,
'optimizePrompt': 'true' if optimize_prompt else 'false'
}
url = f"{self.base_url}/stream"
resp = request_with_retries(
self.session.get,
url=url,
headers={'Accept': 'text/event-stream'},
params=params,
stream=True,
)
resp.raise_for_status()
for line in resp.iter_lines(decode_unicode=True):
if not line:
continue
if line.startswith('data: '):
try:
yield json.loads(line[6:])
except json.JSONDecodeError:
continue
def get_conversations(self, limit: int = 50, offset: int = 0, user_id: Optional[str] = None) -> Dict[str, Any]:
params: Dict[str, Any] = { 'limit': limit, 'offset': offset }
if user_id:
params['userId'] = user_id
url = f"{self.base_url}/conversations"
resp = request_with_retries(self.session.get, url=url, params=params)
resp.raise_for_status()
return resp.json()
def rag_ingest(self, documents: Iterable[Dict[str, Any]], collection: str = 'knowledge_base') -> Dict[str, Any]:
payload = { 'documents': list(documents), 'collection': collection }
resp = self._json('POST', '/rag/ingest', payload)
resp.raise_for_status()
return resp.json()
def rag_search(self, query: str, collection: str = 'knowledge_base', limit: int = 5, threshold: Optional[float] = None) -> Dict[str, Any]:
payload: Dict[str, Any] = { 'query': query, 'collection': collection, 'limit': limit }
if threshold is not None:
payload['threshold'] = threshold
resp = self._json('POST', '/rag/search', payload)
resp.raise_for_status()
return resp.json()
def rag_answer(self, question: str, collection: str = 'knowledge_base', max_context: int = 3, include_context: bool = True) -> Dict[str, Any]:
payload = { 'question': question, 'collection': collection, 'maxContext': max_context, 'includeContext': include_context }
resp = self._json('POST', '/rag/answer', payload)
resp.raise_for_status()
return resp.json()
def list_plugins(self) -> Dict[str, Any]:
resp = request_with_retries(self.session.get, url=f"{self.base_url}/plugins")
resp.raise_for_status()
return resp.json()
def execute_plugin(self, plugin_name: str, action: str, parameters: Dict[str, Any]) -> Dict[str, Any]:
payload = { 'action': action, 'parameters': parameters }
resp = self._json('POST', f"/plugins/{plugin_name}/execute", payload)
resp.raise_for_status()
return resp.json()

View File

@ -0,0 +1,928 @@
openapi: 3.0.3
info:
title: Universal AI Agent API
version: "1.0.0"
description: |
OpenAPI 3.0 specification generated from the Universal AI Agent API reference.
servers:
- url: https://your-domain.com
description: Production server
security:
- bearerAuth: []
paths:
/health:
get:
summary: Health check
description: Returns service health and connected subsystems.
responses:
'200':
description: Health status
content:
application/json:
schema:
$ref: '#/components/schemas/HealthResponse'
/system/info:
get:
summary: System information
security:
- bearerAuth: []
responses:
'200':
description: System information
content:
application/json:
schema:
$ref: '#/components/schemas/SystemInfoResponse'
'401':
$ref: '#/components/responses/UnauthorizedError'
/auth/login:
post:
summary: Login and obtain JWT tokens
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/LoginRequest'
responses:
'200':
description: Login success
content:
application/json:
schema:
$ref: '#/components/schemas/LoginResponse'
'400':
$ref: '#/components/responses/ValidationError'
'401':
$ref: '#/components/responses/UnauthorizedError'
/chat:
post:
summary: Standard chat
security:
- bearerAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ChatRequest'
responses:
'200':
description: Chat response
content:
application/json:
schema:
$ref: '#/components/schemas/ChatResponse'
'400':
$ref: '#/components/responses/ValidationError'
'401':
$ref: '#/components/responses/UnauthorizedError'
/stream:
get:
summary: Streaming chat (SSE)
description: Server-Sent Events stream of chat tokens/chunks.
security:
- bearerAuth: []
parameters:
- in: query
name: message
required: true
schema:
type: string
- in: query
name: optimizePrompt
required: false
schema:
type: boolean
default: false
responses:
'200':
description: text/event-stream output
content:
text/event-stream:
schema:
type: string
description: Stream of SSE events with `data: {"type": "start|chunk|end", ...}`
'401':
$ref: '#/components/responses/UnauthorizedError'
/conversations:
get:
summary: List conversation history
security:
- bearerAuth: []
parameters:
- in: query
name: limit
schema: { type: integer, default: 50, minimum: 1 }
- in: query
name: offset
schema: { type: integer, default: 0, minimum: 0 }
- in: query
name: userId
schema: { type: string }
responses:
'200':
description: Conversation list
content:
application/json:
schema:
$ref: '#/components/schemas/ConversationsResponse'
'401':
$ref: '#/components/responses/UnauthorizedError'
/rag/ingest:
post:
summary: Ingest documents to the RAG collection
security:
- bearerAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/RagIngestRequest'
responses:
'200':
description: Ingest result
content:
application/json:
schema:
$ref: '#/components/schemas/RagIngestResponse'
'400':
$ref: '#/components/responses/ValidationError'
'401':
$ref: '#/components/responses/UnauthorizedError'
/rag/search:
post:
summary: Semantic search over RAG documents
security:
- bearerAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/RagSearchRequest'
responses:
'200':
description: Search results
content:
application/json:
schema:
$ref: '#/components/schemas/RagSearchResponse'
'400':
$ref: '#/components/responses/ValidationError'
'401':
$ref: '#/components/responses/UnauthorizedError'
/rag/answer:
post:
summary: RAG-enhanced answer generation
security:
- bearerAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/RagAnswerRequest'
responses:
'200':
description: Generated answer with sources and context
content:
application/json:
schema:
$ref: '#/components/schemas/RagAnswerResponse'
'400':
$ref: '#/components/responses/ValidationError'
'401':
$ref: '#/components/responses/UnauthorizedError'
/agents/execute:
post:
summary: Execute a multi-agent task
security:
- bearerAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/AgentsExecuteRequest'
responses:
'200':
description: Task execution results
content:
application/json:
schema:
$ref: '#/components/schemas/AgentsExecuteResponse'
'400':
$ref: '#/components/responses/ValidationError'
'401':
$ref: '#/components/responses/UnauthorizedError'
/agents/task/{taskId}:
get:
summary: Get multi-agent task status
security:
- bearerAuth: []
parameters:
- in: path
name: taskId
required: true
schema: { type: string }
responses:
'200':
description: Task status
content:
application/json:
schema:
$ref: '#/components/schemas/AgentTaskStatusResponse'
'401':
$ref: '#/components/responses/UnauthorizedError'
'404':
$ref: '#/components/responses/NotFoundError'
/voice/tts:
post:
summary: Text to speech
security:
- bearerAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/TTSRequest'
responses:
'200':
description: TTS result
content:
application/json:
schema:
$ref: '#/components/schemas/TTSResponse'
'400':
$ref: '#/components/responses/ValidationError'
'401':
$ref: '#/components/responses/UnauthorizedError'
/voice/command:
post:
summary: Process a voice command (text intent processing)
security:
- bearerAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/VoiceCommandRequest'
responses:
'200':
description: Intent and action
content:
application/json:
schema:
$ref: '#/components/schemas/VoiceCommandResponse'
'400':
$ref: '#/components/responses/ValidationError'
'401':
$ref: '#/components/responses/UnauthorizedError'
/voice/autopilot:
post:
summary: Control autopilot mode
security:
- bearerAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/VoiceAutopilotRequest'
responses:
'200':
description: Autopilot status
content:
application/json:
schema:
$ref: '#/components/schemas/VoiceAutopilotResponse'
'400':
$ref: '#/components/responses/ValidationError'
'401':
$ref: '#/components/responses/UnauthorizedError'
/plugins:
get:
summary: List available plugins
security:
- bearerAuth: []
responses:
'200':
description: Plugin list
content:
application/json:
schema:
$ref: '#/components/schemas/PluginsListResponse'
'401':
$ref: '#/components/responses/UnauthorizedError'
/plugins/{pluginName}/execute:
post:
summary: Execute a plugin action
security:
- bearerAuth: []
parameters:
- in: path
name: pluginName
required: true
schema: { type: string }
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/PluginExecuteRequest'
responses:
'200':
description: Plugin execution result
content:
application/json:
schema:
$ref: '#/components/schemas/PluginExecuteResponse'
'400':
$ref: '#/components/responses/ValidationError'
'401':
$ref: '#/components/responses/UnauthorizedError'
'404':
$ref: '#/components/responses/NotFoundError'
/plugins/install:
post:
summary: Install a plugin
security:
- bearerAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/PluginInstallRequest'
responses:
'200':
description: Installation result
content:
application/json:
schema:
$ref: '#/components/schemas/PluginInstallResponse'
'400':
$ref: '#/components/responses/ValidationError'
'401':
$ref: '#/components/responses/UnauthorizedError'
/analytics/dashboard:
get:
summary: Get dashboard analytics
security:
- bearerAuth: []
responses:
'200':
description: Dashboard data
content:
application/json:
schema:
$ref: '#/components/schemas/AnalyticsDashboardResponse'
'401':
$ref: '#/components/responses/UnauthorizedError'
/analytics/metrics:
get:
summary: Get system metrics timeseries
security:
- bearerAuth: []
parameters:
- in: query
name: timeRange
schema:
type: string
enum: ["1h", "24h", "7d", "30d"]
default: "24h"
- in: query
name: metric
schema:
type: string
enum: ["requests", "performance", "errors", "users"]
responses:
'200':
description: Metrics timeseries
content:
application/json:
schema:
$ref: '#/components/schemas/AnalyticsMetricsResponse'
'401':
$ref: '#/components/responses/UnauthorizedError'
/analytics/export:
get:
summary: Export analytics data
security:
- bearerAuth: []
parameters:
- in: query
name: format
schema:
type: string
enum: ["json", "csv"]
default: "json"
- in: query
name: timeRange
schema:
type: string
enum: ["1h", "24h", "7d", "30d"]
default: "24h"
responses:
'200':
description: File download
content:
application/octet-stream:
schema:
type: string
format: binary
'401':
$ref: '#/components/responses/UnauthorizedError'
components:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
responses:
UnauthorizedError:
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
NotFoundError:
description: Not found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
ValidationError:
description: Validation error
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
schemas:
ErrorResponse:
type: object
properties:
error:
type: boolean
example: true
message:
type: string
code:
type: string
timestamp:
type: string
format: date-time
requestId:
type: string
HealthResponse:
type: object
properties:
status:
type: string
example: healthy
uptime:
type: integer
memory:
type: string
connections:
type: object
additionalProperties: { type: string }
features:
type: object
properties:
rag: { type: boolean }
voice: { type: boolean }
plugins: { type: boolean }
multiAgent: { type: boolean }
SystemInfoResponse:
type: object
properties:
version: { type: string }
nodeVersion: { type: string }
platform: { type: string }
architecture: { type: string }
environment: { type: string }
features:
type: array
items: { type: string }
limits:
type: object
properties:
maxRequestSize: { type: string }
rateLimit:
type: object
properties:
window: { type: integer }
max: { type: integer }
LoginRequest:
type: object
required: [email, password]
properties:
email: { type: string, format: email }
password: { type: string }
mfaCode: { type: string, nullable: true }
LoginResponse:
type: object
properties:
success: { type: boolean }
accessToken: { type: string }
refreshToken: { type: string }
sessionId: { type: string }
user:
type: object
properties:
id: { type: string }
email: { type: string }
roles:
type: array
items: { type: string }
mfaEnabled: { type: boolean }
ChatRequest:
type: object
required: [message]
properties:
message: { type: string }
optimizePrompt: { type: boolean, default: false }
context: { type: string, nullable: true }
userId: { type: string, nullable: true }
ChatResponse:
type: object
properties:
response: { type: string }
metadata:
type: object
properties:
model: { type: string }
tokens: { type: integer }
responseTime: { type: integer }
optimized: { type: boolean }
conversationId: { type: string }
ConversationsResponse:
type: object
properties:
conversations:
type: array
items:
type: object
properties:
id: { type: string }
userId: { type: string }
messages:
type: array
items:
type: object
properties:
role: { type: string, enum: [user, assistant, system] }
content: { type: string }
timestamp: { type: string, format: date-time }
createdAt: { type: string, format: date-time }
updatedAt: { type: string, format: date-time }
total: { type: integer }
hasMore: { type: boolean }
RagIngestRequest:
type: object
required: [documents, collection]
properties:
documents:
type: array
items:
type: object
required: [id, content]
properties:
id: { type: string }
content: { type: string }
metadata:
type: object
additionalProperties: {}
collection: { type: string }
RagIngestResponse:
type: object
properties:
success: { type: boolean }
ingested: { type: integer }
failed: { type: integer }
collection: { type: string }
processingTime: { type: integer }
RagSearchRequest:
type: object
required: [query, collection]
properties:
query: { type: string }
collection: { type: string }
limit: { type: integer, default: 5 }
threshold: { type: number, format: float, nullable: true }
RagSearchResponse:
type: object
properties:
results:
type: array
items:
type: object
properties:
id: { type: string }
content: { type: string }
score: { type: number, format: float }
metadata:
type: object
additionalProperties: {}
query: { type: string }
totalResults: { type: integer }
searchTime: { type: integer }
RagAnswerRequest:
type: object
required: [question, collection]
properties:
question: { type: string }
collection: { type: string }
maxContext: { type: integer, default: 3 }
includeContext: { type: boolean, default: true }
RagAnswerResponse:
type: object
properties:
answer: { type: string }
sources:
type: array
items:
type: object
properties:
id: { type: string }
title: { type: string }
relevanceScore: { type: number, format: float }
context:
type: array
items:
type: object
properties:
content: { type: string }
source: { type: string }
confidence: { type: number, format: float }
AgentsExecuteRequest:
type: object
required: [task, agents]
properties:
task: { type: string }
agents:
type: array
items: { type: string }
parallel: { type: boolean, default: false }
maxIterations: { type: integer, default: 3 }
AgentsExecuteResponse:
type: object
properties:
success: { type: boolean }
taskId: { type: string }
results:
type: array
items:
type: object
properties:
agent: { type: string }
role: { type: string }
response: { type: string }
executionTime: { type: integer }
finalSynthesis: { type: string }
totalExecutionTime: { type: integer }
confidence: { type: number, format: float }
AgentTaskStatusResponse:
type: object
properties:
taskId: { type: string }
status: { type: string, enum: [queued, running, completed, failed] }
progress: { type: integer }
currentAgent: { type: string, nullable: true }
results:
type: array
items: { type: object }
startTime: { type: string, format: date-time }
endTime: { type: string, format: date-time, nullable: true }
TTSRequest:
type: object
required: [text, voice, language, voice, language]
properties:
text: { type: string }
voice: { type: string, example: neural }
language: { type: string, example: en-US }
speed: { type: number, default: 1.0 }
format: { type: string, enum: [mp3, wav, ogg], default: mp3 }
TTSResponse:
type: object
properties:
success: { type: boolean }
audioUrl: { type: string }
duration: { type: number }
format: { type: string }
size: { type: integer }
VoiceCommandRequest:
type: object
required: [command]
properties:
command: { type: string }
context: { type: string, nullable: true }
userId: { type: string, nullable: true }
VoiceCommandResponse:
type: object
properties:
success: { type: boolean }
command: { type: string }
intent: { type: string }
entities:
type: array
items: { type: string }
action: { type: string }
response: { type: string }
audioResponse: { type: string }
VoiceAutopilotRequest:
type: object
required: [mode]
properties:
mode:
type: string
enum: [start, stop, status]
context: { type: string, nullable: true }
preferences:
type: object
properties:
verbosity: { type: string, enum: [low, medium, high] }
autoExecute: { type: boolean }
VoiceAutopilotResponse:
type: object
properties:
success: { type: boolean }
mode: { type: string }
sessionId: { type: string }
status: { type: string }
capabilities:
type: array
items: { type: string }
PluginsListResponse:
type: object
properties:
plugins:
type: array
items:
type: object
properties:
name: { type: string }
version: { type: string }
description: { type: string }
category: { type: string }
status: { type: string }
permissions:
type: array
items: { type: string }
total: { type: integer }
PluginExecuteRequest:
type: object
required: [action, parameters]
properties:
action: { type: string }
parameters:
type: object
additionalProperties: {}
PluginExecuteResponse:
type: object
properties:
success: { type: boolean }
plugin: { type: string }
action: { type: string }
result:
type: object
additionalProperties: {}
executionTime: { type: integer }
PluginInstallRequest:
type: object
required: [source, package, version]
properties:
source: { type: string, enum: [npm, git, url] }
package: { type: string }
version: { type: string }
PluginInstallResponse:
type: object
properties:
success: { type: boolean }
plugin: { type: string }
version: { type: string }
status: { type: string }
message: { type: string }
AnalyticsDashboardResponse:
type: object
properties:
overview:
type: object
properties:
uptime: { type: integer }
totalRequests: { type: integer }
successRate: { type: string }
averageResponseTime: { type: integer }
activeUsers: { type: integer }
healthScore: { type: integer }
requests:
type: object
properties:
total: { type: integer }
successful: { type: integer }
failed: { type: integer }
byHour:
type: array
items: { type: integer }
topEndpoints:
type: array
items:
type: object
properties:
endpoint: { type: string }
requests: { type: integer }
averageTime: { type: integer }
errorRate: { type: number }
ai:
type: object
properties:
totalTokens: { type: integer }
totalCost: { type: number }
averageResponseTime: { type: integer }
topModels:
type: array
items:
type: object
properties:
model: { type: string }
requests: { type: integer }
tokens: { type: integer }
cost: { type: number }
AnalyticsMetricsResponse:
type: object
properties:
timeRange: { type: string }
metrics:
type: object
additionalProperties:
type: object
properties:
timestamps:
type: array
items: { type: string, format: date-time }
values:
type: array
items: { type: number }
x-websocket:
url: wss://your-domain.com
description: |
WebSocket API supports the following client messages: `auth`, `stream_chat`, `voice_command`, `plugin_execute`.
Server messages include: `auth_success`, `chat_response`, `stream_chunk`, `error`.

View File

@ -0,0 +1,205 @@
{
"info": {
"name": "Universal AI Agent API",
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
"_postman_id": "c0a1d6b2-1111-4a22-9c9e-abcde1234567"
},
"variable": [
{ "key": "baseUrl", "value": "https://your-domain.com", "type": "string" },
{ "key": "token", "value": "YOUR_TOKEN", "type": "string" }
],
"auth": {
"type": "bearer",
"bearer": [ { "key": "token", "value": "{{token}}", "type": "string" } ]
},
"item": [
{
"name": "Health",
"request": { "method": "GET", "url": "{{baseUrl}}/health" }
},
{
"name": "System Info",
"request": {
"method": "GET",
"header": [ { "key": "Authorization", "value": "Bearer {{token}}" } ],
"url": "{{baseUrl}}/system/info"
}
},
{
"name": "Auth Login",
"request": {
"method": "POST",
"header": [ { "key": "Content-Type", "value": "application/json" } ],
"url": "{{baseUrl}}/auth/login",
"body": {
"mode": "raw",
"raw": "{\n \"email\": \"user@example.com\",\n \"password\": \"secure_password\",\n \"mfaCode\": \"123456\"\n}"
}
}
},
{
"name": "Chat",
"request": {
"method": "POST",
"header": [
{ "key": "Authorization", "value": "Bearer {{token}}" },
{ "key": "Content-Type", "value": "application/json" }
],
"url": "{{baseUrl}}/chat",
"body": { "mode": "raw", "raw": "{\n \"message\": \"Hello, how can you help me?\",\n \"optimizePrompt\": true\n}" }
}
},
{
"name": "Conversations",
"request": {
"method": "GET",
"header": [ { "key": "Authorization", "value": "Bearer {{token}}" } ],
"url": {
"raw": "{{baseUrl}}/conversations?limit=50&offset=0",
"host": [ "{{baseUrl}}" ],
"path": [ "conversations" ],
"query": [
{ "key": "limit", "value": "50" },
{ "key": "offset", "value": "0" }
]
}
}
},
{
"name": "RAG Ingest",
"request": {
"method": "POST",
"header": [
{ "key": "Authorization", "value": "Bearer {{token}}" },
{ "key": "Content-Type", "value": "application/json" }
],
"url": "{{baseUrl}}/rag/ingest",
"body": { "mode": "raw", "raw": "{\n \"documents\": [\n {\n \"id\": \"doc1\",\n \"content\": \"This is a sample document content...\",\n \"metadata\": {\n \"title\": \"Sample Document\",\n \"author\": \"John Doe\",\n \"category\": \"technical\"\n }\n }\n ],\n \"collection\": \"knowledge_base\"\n}" }
}
},
{
"name": "RAG Search",
"request": {
"method": "POST",
"header": [
{ "key": "Authorization", "value": "Bearer {{token}}" },
{ "key": "Content-Type", "value": "application/json" }
],
"url": "{{baseUrl}}/rag/search",
"body": { "mode": "raw", "raw": "{\n \"query\": \"machine learning algorithms\",\n \"collection\": \"knowledge_base\",\n \"limit\": 5,\n \"threshold\": 0.7\n}" }
}
},
{
"name": "RAG Answer",
"request": {
"method": "POST",
"header": [
{ "key": "Authorization", "value": "Bearer {{token}}" },
{ "key": "Content-Type", "value": "application/json" }
],
"url": "{{baseUrl}}/rag/answer",
"body": { "mode": "raw", "raw": "{\n \"question\": \"What are the best machine learning algorithms?\",\n \"collection\": \"knowledge_base\",\n \"maxContext\": 3,\n \"includeContext\": true\n}" }
}
},
{
"name": "Agents Execute",
"request": {
"method": "POST",
"header": [
{ "key": "Authorization", "value": "Bearer {{token}}" },
{ "key": "Content-Type", "value": "application/json" }
],
"url": "{{baseUrl}}/agents/execute",
"body": { "mode": "raw", "raw": "{\n \"task\": \"Analyze the performance of our web application and suggest optimizations\",\n \"agents\": [\"planner\", \"critic\", \"executor\"],\n \"parallel\": false,\n \"maxIterations\": 3\n}" }
}
},
{
"name": "Agent Task Status",
"request": {
"method": "GET",
"header": [ { "key": "Authorization", "value": "Bearer {{token}}" } ],
"url": "{{baseUrl}}/agents/task/task_123"
}
},
{
"name": "Voice TTS",
"request": {
"method": "POST",
"header": [
{ "key": "Authorization", "value": "Bearer {{token}}" },
{ "key": "Content-Type", "value": "application/json" }
],
"url": "{{baseUrl}}/voice/tts",
"body": { "mode": "raw", "raw": "{\n \"text\": \"Hello, this is your AI assistant speaking.\",\n \"voice\": \"neural\",\n \"language\": \"en-US\",\n \"speed\": 1.0,\n \"format\": \"mp3\"\n}" }
}
},
{
"name": "Voice Command",
"request": {
"method": "POST",
"header": [
{ "key": "Authorization", "value": "Bearer {{token}}" },
{ "key": "Content-Type", "value": "application/json" }
],
"url": "{{baseUrl}}/voice/command",
"body": { "mode": "raw", "raw": "{\n \"command\": \"analyze the latest sales data\",\n \"context\": \"dashboard\",\n \"userId\": \"user123\"\n}" }
}
},
{
"name": "Voice Autopilot",
"request": {
"method": "POST",
"header": [
{ "key": "Authorization", "value": "Bearer {{token}}" },
{ "key": "Content-Type", "value": "application/json" }
],
"url": "{{baseUrl}}/voice/autopilot",
"body": { "mode": "raw", "raw": "{\n \"mode\": \"start\",\n \"context\": \"development\",\n \"preferences\": {\n \"verbosity\": \"medium\",\n \"autoExecute\": false\n }\n}" }
}
},
{
"name": "Plugins List",
"request": { "method": "GET", "header": [ { "key": "Authorization", "value": "Bearer {{token}}" } ], "url": "{{baseUrl}}/plugins" }
},
{
"name": "Plugin Execute",
"request": {
"method": "POST",
"header": [
{ "key": "Authorization", "value": "Bearer {{token}}" },
{ "key": "Content-Type", "value": "application/json" }
],
"url": "{{baseUrl}}/plugins/web-scraper/execute",
"body": { "mode": "raw", "raw": "{\n \"action\": \"scrape\",\n \"parameters\": {\n \"url\": \"https://example.com\",\n \"selector\": ".content",\n \"format\": \"text\"\n }\n}" }
}
},
{
"name": "Plugin Install",
"request": {
"method": "POST",
"header": [
{ "key": "Authorization", "value": "Bearer {{token}}" },
{ "key": "Content-Type", "value": "application/json" }
],
"url": "{{baseUrl}}/plugins/install",
"body": { "mode": "raw", "raw": "{\n \"source\": \"npm\",\n \"package\": \"@universal-ai/plugin-example\",\n \"version\": \"1.0.0\"\n}" }
}
},
{
"name": "Analytics Dashboard",
"request": { "method": "GET", "header": [ { "key": "Authorization", "value": "Bearer {{token}}" } ], "url": "{{baseUrl}}/analytics/dashboard" }
},
{
"name": "Analytics Metrics",
"request": {
"method": "GET",
"header": [ { "key": "Authorization", "value": "Bearer {{token}}" } ],
"url": "{{baseUrl}}/analytics/metrics?timeRange=24h&metric=requests"
}
},
{
"name": "Analytics Export",
"request": { "method": "GET", "header": [ { "key": "Authorization", "value": "Bearer {{token}}" } ], "url": "{{baseUrl}}/analytics/export?format=json&timeRange=24h" }
}
]
}

View File

@ -0,0 +1,62 @@
#!/usr/bin/env bash
set -euo pipefail
BASE_URL="${BASE_URL:-https://your-domain.com}"
TOKEN="${TOKEN:-YOUR_TOKEN}"
_auth_header() {
echo "Authorization: Bearer ${TOKEN}"
}
usage() {
cat <<EOF
Usage: BASE_URL=... TOKEN=... $0 <command>
Commands:
health
chat <message>
rag_search <query>
plugin_execute <plugin> <action> <json_parameters>
analytics_dashboard
EOF
}
health() {
curl -sS "${BASE_URL}/health" | jq .
}
chat() {
local msg="${1:-Hello}"
curl -sS -X POST "${BASE_URL}/chat" \
-H "$(_auth_header)" -H 'Content-Type: application/json' \
-d "{\"message\": \"${msg}\"}" | jq .
}
rag_search() {
local q="${1:-machine learning}"
curl -sS -X POST "${BASE_URL}/rag/search" \
-H "$(_auth_header)" -H 'Content-Type: application/json' \
-d "{\"query\": \"${q}\", \"collection\": \"knowledge_base\", \"limit\": 5}" | jq .
}
plugin_execute() {
local plugin="${1:?pluginName}"
local action="${2:?action}"
local params="${3:-{}}"
curl -sS -X POST "${BASE_URL}/plugins/${plugin}/execute" \
-H "$(_auth_header)" -H 'Content-Type: application/json' \
-d "{\"action\": \"${action}\", \"parameters\": ${params}}" | jq .
}
analytics_dashboard() {
curl -sS "${BASE_URL}/analytics/dashboard" -H "$(_auth_header)" | jq .
}
cmd="${1:-}"
case "$cmd" in
health) shift; health "$@" ;;
chat) shift; chat "$@" ;;
rag_search) shift; rag_search "$@" ;;
plugin_execute) shift; plugin_execute "$@" ;;
analytics_dashboard) shift; analytics_dashboard "$@" ;;
*) usage; exit 1 ;;
esac

View File

@ -0,0 +1,44 @@
export async function rateLimitedFetch(fetchFn, url, options = {}, {
maxRetries = 4,
baseDelayMs = 500,
backoffFactor = 2,
maxDelayMs = 8000
} = {}) {
let attempt = 0;
const originalBody = options.body;
while (true) {
try {
// Re-clone simple bodies for retries
if (attempt > 0 && typeof originalBody === 'string') {
options.body = originalBody;
}
const response = await fetchFn(url, options);
if (response.status !== 429 && response.status < 500) {
return response; // success or client error
}
// 429 or 5xx -> retry
if (attempt >= maxRetries) {
return response; // give back last response
}
const retryAfter = parseInt(response.headers.get('Retry-After') || '0', 10);
const delayFromHeader = Number.isFinite(retryAfter) && retryAfter > 0 ? retryAfter * 1000 : 0;
const backoff = Math.min(baseDelayMs * Math.pow(backoffFactor, attempt), maxDelayMs);
const jitter = Math.floor(Math.random() * 250);
const delayMs = Math.max(delayFromHeader, backoff) + jitter;
await new Promise((r) => setTimeout(r, delayMs));
attempt += 1;
continue;
} catch (err) {
if (attempt >= maxRetries) throw err;
const backoff = Math.min(baseDelayMs * Math.pow(backoffFactor, attempt), maxDelayMs);
const jitter = Math.floor(Math.random() * 250);
await new Promise((r) => setTimeout(r, backoff + jitter));
attempt += 1;
}
}
}

View File

@ -0,0 +1,36 @@
import time
import random
from typing import Callable, Dict, Any
def request_with_retries(sender: Callable[..., Any], max_retries: int = 4, base_delay: float = 0.5, backoff: float = 2.0, max_delay: float = 8.0, **kwargs) -> Any:
"""
rate-limit-safe request wrapper. Expects `sender` to be a callable like
`session.request(method, url, **kwargs)` returning a `requests.Response`.
Retries on HTTP 429 and 5xx. Honors Retry-After header when present.
"""
attempt = 0
while True:
try:
resp = sender(**kwargs)
if resp.status_code != 429 and resp.status_code < 500:
return resp
if attempt >= max_retries:
return resp
retry_after = resp.headers.get('Retry-After')
delay_from_header = 0.0
if retry_after is not None:
try:
delay_from_header = float(retry_after)
except ValueError:
delay_from_header = 0.0
backoff_delay = min(base_delay * (backoff ** attempt), max_delay)
delay = max(delay_from_header, backoff_delay) + random.uniform(0, 0.25)
time.sleep(delay)
attempt += 1
except Exception:
if attempt >= max_retries:
raise
backoff_delay = min(base_delay * (backoff ** attempt), max_delay)
time.sleep(backoff_delay + random.uniform(0, 0.25))
attempt += 1