Spaces:
Runtime error
Runtime error
| import { test, expect } from '@playwright/test' | |
| import { API_KEY_HEADER } from './helpers' | |
| test.describe('Direct CLI Integration', () => { | |
| const createdConnectionIds: string[] = [] | |
| const createdAgentIds: number[] = [] | |
| test.afterEach(async ({ request }) => { | |
| // Clean up connections | |
| for (const connId of createdConnectionIds) { | |
| await request.delete('/api/connect', { | |
| headers: API_KEY_HEADER, | |
| data: { connection_id: connId }, | |
| }) | |
| } | |
| createdConnectionIds.length = 0 | |
| // Clean up auto-created agents | |
| for (const agentId of createdAgentIds) { | |
| await request.delete(`/api/agents/${agentId}`, { headers: API_KEY_HEADER }) | |
| } | |
| createdAgentIds.length = 0 | |
| }) | |
| test('POST /api/connect creates connection and auto-creates agent', async ({ request }) => { | |
| const agentName = `e2e-cli-${Date.now()}` | |
| const res = await request.post('/api/connect', { | |
| headers: API_KEY_HEADER, | |
| data: { | |
| tool_name: 'claude-code', | |
| tool_version: '1.0.0', | |
| agent_name: agentName, | |
| agent_role: 'developer', | |
| }, | |
| }) | |
| expect(res.status()).toBe(200) | |
| const body = await res.json() | |
| expect(body.connection_id).toBeDefined() | |
| expect(body.agent_id).toBeDefined() | |
| expect(body.agent_name).toBe(agentName) | |
| expect(body.status).toBe('connected') | |
| expect(body.sse_url).toBe('/api/events') | |
| expect(body.heartbeat_url).toContain('/api/agents/') | |
| expect(body.token_report_url).toBe('/api/tokens') | |
| createdConnectionIds.push(body.connection_id) | |
| createdAgentIds.push(body.agent_id) | |
| // Verify agent was created | |
| const agentRes = await request.get(`/api/agents/${body.agent_id}`, { | |
| headers: API_KEY_HEADER, | |
| }) | |
| expect(agentRes.status()).toBe(200) | |
| const agentBody = await agentRes.json() | |
| expect(agentBody.agent.name).toBe(agentName) | |
| expect(agentBody.agent.status).toBe('online') | |
| }) | |
| test('GET /api/connect lists connections', async ({ request }) => { | |
| const agentName = `e2e-cli-list-${Date.now()}` | |
| const postRes = await request.post('/api/connect', { | |
| headers: API_KEY_HEADER, | |
| data: { | |
| tool_name: 'codex', | |
| agent_name: agentName, | |
| }, | |
| }) | |
| const postBody = await postRes.json() | |
| createdConnectionIds.push(postBody.connection_id) | |
| createdAgentIds.push(postBody.agent_id) | |
| const res = await request.get('/api/connect', { headers: API_KEY_HEADER }) | |
| expect(res.status()).toBe(200) | |
| const body = await res.json() | |
| expect(Array.isArray(body.connections)).toBe(true) | |
| const found = body.connections.find((c: any) => c.connection_id === postBody.connection_id) | |
| expect(found).toBeDefined() | |
| expect(found.agent_name).toBe(agentName) | |
| expect(found.tool_name).toBe('codex') | |
| }) | |
| test('POST heartbeat with inline token_usage', async ({ request }) => { | |
| const agentName = `e2e-cli-hb-${Date.now()}` | |
| const postRes = await request.post('/api/connect', { | |
| headers: API_KEY_HEADER, | |
| data: { | |
| tool_name: 'claude-code', | |
| agent_name: agentName, | |
| }, | |
| }) | |
| const postBody = await postRes.json() | |
| createdConnectionIds.push(postBody.connection_id) | |
| createdAgentIds.push(postBody.agent_id) | |
| const hbRes = await request.post(`/api/agents/${postBody.agent_id}/heartbeat`, { | |
| headers: API_KEY_HEADER, | |
| data: { | |
| connection_id: postBody.connection_id, | |
| token_usage: { | |
| model: 'claude-sonnet-4', | |
| inputTokens: 1000, | |
| outputTokens: 500, | |
| }, | |
| }, | |
| }) | |
| expect(hbRes.status()).toBe(200) | |
| const hbBody = await hbRes.json() | |
| expect(hbBody.token_recorded).toBe(true) | |
| expect(hbBody.agent).toBe(agentName) | |
| const costsRes = await request.get('/api/tokens?action=agent-costs&timeframe=hour', { | |
| headers: API_KEY_HEADER, | |
| }) | |
| expect(costsRes.status()).toBe(200) | |
| const costsBody = await costsRes.json() | |
| expect(costsBody.agents).toHaveProperty(agentName) | |
| expect(costsBody.agents[agentName].stats.totalTokens).toBeGreaterThanOrEqual(1500) | |
| }) | |
| test('DELETE /api/connect disconnects and sets agent offline', async ({ request }) => { | |
| const agentName = `e2e-cli-del-${Date.now()}` | |
| const postRes = await request.post('/api/connect', { | |
| headers: API_KEY_HEADER, | |
| data: { | |
| tool_name: 'claude-code', | |
| agent_name: agentName, | |
| }, | |
| }) | |
| const postBody = await postRes.json() | |
| createdAgentIds.push(postBody.agent_id) | |
| const delRes = await request.delete('/api/connect', { | |
| headers: API_KEY_HEADER, | |
| data: { connection_id: postBody.connection_id }, | |
| }) | |
| expect(delRes.status()).toBe(200) | |
| const delBody = await delRes.json() | |
| expect(delBody.status).toBe('disconnected') | |
| // Agent should be offline | |
| const agentRes = await request.get(`/api/agents/${postBody.agent_id}`, { | |
| headers: API_KEY_HEADER, | |
| }) | |
| const agentBody = await agentRes.json() | |
| expect(agentBody.agent.status).toBe('offline') | |
| }) | |
| test('POST /api/connect requires auth', async ({ request }) => { | |
| const res = await request.post('/api/connect', { | |
| data: { | |
| tool_name: 'claude-code', | |
| agent_name: 'unauthorized-agent', | |
| }, | |
| }) | |
| expect(res.status()).toBe(401) | |
| }) | |
| }) | |