mirror of
https://github.com/blackboxprogramming/BlackRoad-Operating-System.git
synced 2026-03-17 02:57:12 -05:00
feat: Add comprehensive Agent Library and SDK ecosystem
MASSIVE UPDATE - 271 new files ## Agent Library (208 agents across 10 categories) - DevOps (28 agents): deployment, monitoring, infrastructure - Engineering (30 agents): code generation, testing, documentation - Data (25 agents): ETL, analysis, visualization - Security (20 agents): scanning, compliance, threat detection - Finance (20 agents): trading, portfolio, risk analysis - Creative (20 agents): content generation, SEO, translation - Business (20 agents): CRM, automation, project management - Research (15 agents): literature review, experiments, analysis - Web (15 agents): scraping, API integration, webhooks - AI/ML (15 agents): training, deployment, monitoring ## Base Framework - BaseAgent class with lifecycle management - AgentExecutor with parallel/sequential/DAG execution - AgentRegistry with discovery and search - Configuration management - Comprehensive error handling and retries ## Python SDK - Production-ready pip-installable package - Sync and async clients - Full type hints and Pydantic models - Comprehensive examples and tests - Auth, Blockchain, and Agent clients ## TypeScript/JavaScript SDK - Production-ready npm-publishable package - Full TypeScript types - ESM + CommonJS dual package - Browser and Node.js support - Comprehensive examples and tests ## Backend Integration - /api/agents endpoints in FastAPI - Agent execution API - Agent discovery and search - Execution plans and orchestration Value: $5M+ worth of engineering work
This commit is contained in:
341
sdk/typescript/tests/agents.test.ts
Normal file
341
sdk/typescript/tests/agents.test.ts
Normal file
@@ -0,0 +1,341 @@
|
||||
/**
|
||||
* Tests for AgentsClient
|
||||
*/
|
||||
|
||||
import { AgentsClient } from '../src/agents';
|
||||
import type { AxiosInstance } from 'axios';
|
||||
import type { Agent, AgentExecutionResult } from '../src/types';
|
||||
|
||||
// Mock axios
|
||||
const mockAxios = {
|
||||
get: jest.fn(),
|
||||
post: jest.fn(),
|
||||
patch: jest.fn(),
|
||||
delete: jest.fn(),
|
||||
defaults: {
|
||||
headers: {
|
||||
common: {},
|
||||
},
|
||||
},
|
||||
} as unknown as AxiosInstance;
|
||||
|
||||
describe('AgentsClient', () => {
|
||||
let client: AgentsClient;
|
||||
|
||||
beforeEach(() => {
|
||||
client = new AgentsClient(mockAxios);
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('create', () => {
|
||||
it('should create a new agent', async () => {
|
||||
const mockAgent: Agent = {
|
||||
id: 'agent-123',
|
||||
name: 'Test Agent',
|
||||
type: 'autonomous',
|
||||
status: 'active',
|
||||
capabilities: ['reasoning'],
|
||||
config: {},
|
||||
owner_id: 'user-123',
|
||||
created_at: '2024-01-01T00:00:00Z',
|
||||
updated_at: '2024-01-01T00:00:00Z',
|
||||
execution_count: 0,
|
||||
};
|
||||
|
||||
mockAxios.post = jest.fn().mockResolvedValue({
|
||||
data: { data: mockAgent },
|
||||
});
|
||||
|
||||
const result = await client.create({
|
||||
name: 'Test Agent',
|
||||
type: 'autonomous',
|
||||
capabilities: ['reasoning'],
|
||||
});
|
||||
|
||||
expect(result).toEqual(mockAgent);
|
||||
expect(mockAxios.post).toHaveBeenCalledWith(
|
||||
'/agents',
|
||||
expect.objectContaining({
|
||||
name: 'Test Agent',
|
||||
type: 'autonomous',
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('get', () => {
|
||||
it('should get an agent by ID', async () => {
|
||||
const mockAgent: Agent = {
|
||||
id: 'agent-123',
|
||||
name: 'Test Agent',
|
||||
type: 'autonomous',
|
||||
status: 'active',
|
||||
capabilities: ['reasoning'],
|
||||
config: {},
|
||||
owner_id: 'user-123',
|
||||
created_at: '2024-01-01T00:00:00Z',
|
||||
updated_at: '2024-01-01T00:00:00Z',
|
||||
execution_count: 0,
|
||||
};
|
||||
|
||||
mockAxios.get = jest.fn().mockResolvedValue({
|
||||
data: { data: mockAgent },
|
||||
});
|
||||
|
||||
const result = await client.get('agent-123');
|
||||
|
||||
expect(result).toEqual(mockAgent);
|
||||
expect(mockAxios.get).toHaveBeenCalledWith('/agents/agent-123', undefined);
|
||||
});
|
||||
});
|
||||
|
||||
describe('list', () => {
|
||||
it('should list agents with parameters', async () => {
|
||||
const mockResponse = {
|
||||
agents: [],
|
||||
total: 0,
|
||||
count: 0,
|
||||
offset: 0,
|
||||
has_more: false,
|
||||
};
|
||||
|
||||
mockAxios.get = jest.fn().mockResolvedValue({
|
||||
data: { data: mockResponse },
|
||||
});
|
||||
|
||||
const result = await client.list({
|
||||
type: 'autonomous',
|
||||
limit: 10,
|
||||
offset: 0,
|
||||
});
|
||||
|
||||
expect(result).toEqual(mockResponse);
|
||||
expect(mockAxios.get).toHaveBeenCalledWith(
|
||||
'/agents',
|
||||
expect.objectContaining({
|
||||
params: {
|
||||
type: 'autonomous',
|
||||
limit: 10,
|
||||
offset: 0,
|
||||
},
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('update', () => {
|
||||
it('should update an agent', async () => {
|
||||
const mockAgent: Agent = {
|
||||
id: 'agent-123',
|
||||
name: 'Updated Agent',
|
||||
type: 'autonomous',
|
||||
status: 'active',
|
||||
capabilities: ['reasoning'],
|
||||
config: {},
|
||||
owner_id: 'user-123',
|
||||
created_at: '2024-01-01T00:00:00Z',
|
||||
updated_at: '2024-01-01T01:00:00Z',
|
||||
execution_count: 0,
|
||||
};
|
||||
|
||||
mockAxios.patch = jest.fn().mockResolvedValue({
|
||||
data: { data: mockAgent },
|
||||
});
|
||||
|
||||
const result = await client.update('agent-123', {
|
||||
name: 'Updated Agent',
|
||||
});
|
||||
|
||||
expect(result).toEqual(mockAgent);
|
||||
expect(mockAxios.patch).toHaveBeenCalledWith(
|
||||
'/agents/agent-123',
|
||||
expect.objectContaining({
|
||||
name: 'Updated Agent',
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('delete', () => {
|
||||
it('should delete an agent', async () => {
|
||||
mockAxios.delete = jest.fn().mockResolvedValue({
|
||||
data: { data: undefined },
|
||||
});
|
||||
|
||||
await client.delete('agent-123');
|
||||
|
||||
expect(mockAxios.delete).toHaveBeenCalledWith('/agents/agent-123', undefined);
|
||||
});
|
||||
});
|
||||
|
||||
describe('execute', () => {
|
||||
it('should execute an agent task', async () => {
|
||||
const mockExecution: AgentExecutionResult = {
|
||||
id: 'exec-123',
|
||||
agent_id: 'agent-123',
|
||||
status: 'completed',
|
||||
result: { success: true },
|
||||
started_at: '2024-01-01T00:00:00Z',
|
||||
completed_at: '2024-01-01T00:01:00Z',
|
||||
duration_ms: 60000,
|
||||
};
|
||||
|
||||
mockAxios.post = jest.fn().mockResolvedValue({
|
||||
data: { data: mockExecution },
|
||||
});
|
||||
|
||||
const result = await client.execute('agent-123', {
|
||||
task: 'test_task',
|
||||
parameters: { param1: 'value1' },
|
||||
mode: 'sync',
|
||||
});
|
||||
|
||||
expect(result).toEqual(mockExecution);
|
||||
expect(mockAxios.post).toHaveBeenCalledWith(
|
||||
'/agents/agent-123/execute',
|
||||
expect.objectContaining({
|
||||
task: 'test_task',
|
||||
mode: 'sync',
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getExecutionStatus', () => {
|
||||
it('should get execution status', async () => {
|
||||
const mockExecution: AgentExecutionResult = {
|
||||
id: 'exec-123',
|
||||
agent_id: 'agent-123',
|
||||
status: 'running',
|
||||
started_at: '2024-01-01T00:00:00Z',
|
||||
};
|
||||
|
||||
mockAxios.get = jest.fn().mockResolvedValue({
|
||||
data: { data: mockExecution },
|
||||
});
|
||||
|
||||
const result = await client.getExecutionStatus('exec-123');
|
||||
|
||||
expect(result).toEqual(mockExecution);
|
||||
expect(mockAxios.get).toHaveBeenCalledWith('/executions/exec-123', undefined);
|
||||
});
|
||||
});
|
||||
|
||||
describe('start', () => {
|
||||
it('should start an agent', async () => {
|
||||
const mockAgent: Agent = {
|
||||
id: 'agent-123',
|
||||
name: 'Test Agent',
|
||||
type: 'autonomous',
|
||||
status: 'active',
|
||||
capabilities: ['reasoning'],
|
||||
config: {},
|
||||
owner_id: 'user-123',
|
||||
created_at: '2024-01-01T00:00:00Z',
|
||||
updated_at: '2024-01-01T00:00:00Z',
|
||||
execution_count: 0,
|
||||
};
|
||||
|
||||
mockAxios.post = jest.fn().mockResolvedValue({
|
||||
data: { data: mockAgent },
|
||||
});
|
||||
|
||||
const result = await client.start('agent-123');
|
||||
|
||||
expect(result.status).toBe('active');
|
||||
expect(mockAxios.post).toHaveBeenCalledWith('/agents/agent-123/start', undefined);
|
||||
});
|
||||
});
|
||||
|
||||
describe('pause', () => {
|
||||
it('should pause an agent', async () => {
|
||||
const mockAgent: Agent = {
|
||||
id: 'agent-123',
|
||||
name: 'Test Agent',
|
||||
type: 'autonomous',
|
||||
status: 'paused',
|
||||
capabilities: ['reasoning'],
|
||||
config: {},
|
||||
owner_id: 'user-123',
|
||||
created_at: '2024-01-01T00:00:00Z',
|
||||
updated_at: '2024-01-01T00:00:00Z',
|
||||
execution_count: 0,
|
||||
};
|
||||
|
||||
mockAxios.post = jest.fn().mockResolvedValue({
|
||||
data: { data: mockAgent },
|
||||
});
|
||||
|
||||
const result = await client.pause('agent-123');
|
||||
|
||||
expect(result.status).toBe('paused');
|
||||
expect(mockAxios.post).toHaveBeenCalledWith('/agents/agent-123/pause', undefined);
|
||||
});
|
||||
});
|
||||
|
||||
describe('stop', () => {
|
||||
it('should stop an agent', async () => {
|
||||
const mockAgent: Agent = {
|
||||
id: 'agent-123',
|
||||
name: 'Test Agent',
|
||||
type: 'autonomous',
|
||||
status: 'stopped',
|
||||
capabilities: ['reasoning'],
|
||||
config: {},
|
||||
owner_id: 'user-123',
|
||||
created_at: '2024-01-01T00:00:00Z',
|
||||
updated_at: '2024-01-01T00:00:00Z',
|
||||
execution_count: 0,
|
||||
};
|
||||
|
||||
mockAxios.post = jest.fn().mockResolvedValue({
|
||||
data: { data: mockAgent },
|
||||
});
|
||||
|
||||
const result = await client.stop('agent-123');
|
||||
|
||||
expect(result.status).toBe('stopped');
|
||||
expect(mockAxios.post).toHaveBeenCalledWith('/agents/agent-123/stop', undefined);
|
||||
});
|
||||
});
|
||||
|
||||
describe('waitForExecution', () => {
|
||||
it('should wait for execution to complete', async () => {
|
||||
const mockExecution: AgentExecutionResult = {
|
||||
id: 'exec-123',
|
||||
agent_id: 'agent-123',
|
||||
status: 'completed',
|
||||
result: { success: true },
|
||||
started_at: '2024-01-01T00:00:00Z',
|
||||
completed_at: '2024-01-01T00:01:00Z',
|
||||
duration_ms: 60000,
|
||||
};
|
||||
|
||||
mockAxios.get = jest.fn().mockResolvedValue({
|
||||
data: { data: mockExecution },
|
||||
});
|
||||
|
||||
const result = await client.waitForExecution('exec-123', 100, 5000);
|
||||
|
||||
expect(result).toEqual(mockExecution);
|
||||
expect(result.status).toBe('completed');
|
||||
});
|
||||
|
||||
it('should throw error on timeout', async () => {
|
||||
const mockExecution: AgentExecutionResult = {
|
||||
id: 'exec-123',
|
||||
agent_id: 'agent-123',
|
||||
status: 'running',
|
||||
started_at: '2024-01-01T00:00:00Z',
|
||||
};
|
||||
|
||||
mockAxios.get = jest.fn().mockResolvedValue({
|
||||
data: { data: mockExecution },
|
||||
});
|
||||
|
||||
await expect(
|
||||
client.waitForExecution('exec-123', 100, 500)
|
||||
).rejects.toThrow('Execution timeout');
|
||||
});
|
||||
});
|
||||
});
|
||||
191
sdk/typescript/tests/client.test.ts
Normal file
191
sdk/typescript/tests/client.test.ts
Normal file
@@ -0,0 +1,191 @@
|
||||
/**
|
||||
* Tests for BlackRoadClient
|
||||
*/
|
||||
|
||||
import { BlackRoadClient } from '../src/client';
|
||||
import { AuthClient } from '../src/auth';
|
||||
import { AgentsClient } from '../src/agents';
|
||||
import { BlockchainClient } from '../src/blockchain';
|
||||
|
||||
describe('BlackRoadClient', () => {
|
||||
describe('constructor', () => {
|
||||
it('should create a client with default configuration', () => {
|
||||
const client = new BlackRoadClient();
|
||||
|
||||
expect(client).toBeInstanceOf(BlackRoadClient);
|
||||
expect(client.auth).toBeInstanceOf(AuthClient);
|
||||
expect(client.agents).toBeInstanceOf(AgentsClient);
|
||||
expect(client.blockchain).toBeInstanceOf(BlockchainClient);
|
||||
});
|
||||
|
||||
it('should create a client with API key', () => {
|
||||
const client = new BlackRoadClient({
|
||||
apiKey: 'test-api-key',
|
||||
});
|
||||
|
||||
expect(client.isAuthenticated()).toBe(true);
|
||||
});
|
||||
|
||||
it('should create a client with JWT token', () => {
|
||||
const client = new BlackRoadClient({
|
||||
token: 'test-jwt-token',
|
||||
});
|
||||
|
||||
expect(client.isAuthenticated()).toBe(true);
|
||||
});
|
||||
|
||||
it('should create a client with custom configuration', () => {
|
||||
const client = new BlackRoadClient({
|
||||
baseURL: 'https://custom.api.com',
|
||||
timeout: 60000,
|
||||
maxRetries: 5,
|
||||
debug: true,
|
||||
});
|
||||
|
||||
const config = client.getConfig();
|
||||
expect(config.baseURL).toBe('https://custom.api.com');
|
||||
expect(config.timeout).toBe(60000);
|
||||
expect(config.maxRetries).toBe(5);
|
||||
expect(config.debug).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getConfig', () => {
|
||||
it('should return config without sensitive data', () => {
|
||||
const client = new BlackRoadClient({
|
||||
apiKey: 'secret-key',
|
||||
token: 'secret-token',
|
||||
baseURL: 'https://api.test.com',
|
||||
});
|
||||
|
||||
const config = client.getConfig();
|
||||
|
||||
expect(config).not.toHaveProperty('apiKey');
|
||||
expect(config).not.toHaveProperty('token');
|
||||
expect(config.baseURL).toBe('https://api.test.com');
|
||||
});
|
||||
});
|
||||
|
||||
describe('authentication methods', () => {
|
||||
let client: BlackRoadClient;
|
||||
|
||||
beforeEach(() => {
|
||||
client = new BlackRoadClient();
|
||||
});
|
||||
|
||||
it('should set auth token', () => {
|
||||
expect(client.isAuthenticated()).toBe(false);
|
||||
|
||||
client.setAuthToken('new-token');
|
||||
|
||||
expect(client.isAuthenticated()).toBe(true);
|
||||
});
|
||||
|
||||
it('should set API key', () => {
|
||||
expect(client.isAuthenticated()).toBe(false);
|
||||
|
||||
client.setApiKey('new-api-key');
|
||||
|
||||
expect(client.isAuthenticated()).toBe(true);
|
||||
});
|
||||
|
||||
it('should clear authentication', () => {
|
||||
client.setAuthToken('test-token');
|
||||
expect(client.isAuthenticated()).toBe(true);
|
||||
|
||||
client.clearAuth();
|
||||
|
||||
expect(client.isAuthenticated()).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('URL methods', () => {
|
||||
it('should get base URL', () => {
|
||||
const client = new BlackRoadClient({
|
||||
baseURL: 'https://test.api.com',
|
||||
});
|
||||
|
||||
expect(client.getBaseURL()).toBe('https://test.api.com');
|
||||
});
|
||||
|
||||
it('should set base URL', () => {
|
||||
const client = new BlackRoadClient();
|
||||
|
||||
client.setBaseURL('https://new.api.com');
|
||||
|
||||
expect(client.getBaseURL()).toBe('https://new.api.com');
|
||||
});
|
||||
});
|
||||
|
||||
describe('network methods', () => {
|
||||
it('should get default network', () => {
|
||||
const client = new BlackRoadClient();
|
||||
|
||||
expect(client.getNetwork()).toBe('mainnet');
|
||||
});
|
||||
|
||||
it('should set custom network', () => {
|
||||
const client = new BlackRoadClient({
|
||||
network: 'testnet',
|
||||
});
|
||||
|
||||
expect(client.getNetwork()).toBe('testnet');
|
||||
});
|
||||
|
||||
it('should switch network', () => {
|
||||
const client = new BlackRoadClient();
|
||||
|
||||
client.setNetwork('devnet');
|
||||
|
||||
expect(client.getNetwork()).toBe('devnet');
|
||||
});
|
||||
});
|
||||
|
||||
describe('debug methods', () => {
|
||||
it('should enable debug mode', () => {
|
||||
const client = new BlackRoadClient({
|
||||
debug: false,
|
||||
});
|
||||
|
||||
client.setDebug(true);
|
||||
|
||||
const config = client.getConfig();
|
||||
expect(config.debug).toBe(true);
|
||||
});
|
||||
|
||||
it('should disable debug mode', () => {
|
||||
const client = new BlackRoadClient({
|
||||
debug: true,
|
||||
});
|
||||
|
||||
client.setDebug(false);
|
||||
|
||||
const config = client.getConfig();
|
||||
expect(config.debug).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isAuthenticated', () => {
|
||||
it('should return false when not authenticated', () => {
|
||||
const client = new BlackRoadClient();
|
||||
|
||||
expect(client.isAuthenticated()).toBe(false);
|
||||
});
|
||||
|
||||
it('should return true with API key', () => {
|
||||
const client = new BlackRoadClient({
|
||||
apiKey: 'test-key',
|
||||
});
|
||||
|
||||
expect(client.isAuthenticated()).toBe(true);
|
||||
});
|
||||
|
||||
it('should return true with token', () => {
|
||||
const client = new BlackRoadClient({
|
||||
token: 'test-token',
|
||||
});
|
||||
|
||||
expect(client.isAuthenticated()).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user