This commit is contained in:
103
packages/server/tests/local/agents-durable-run.test.ts
Normal file
103
packages/server/tests/local/agents-durable-run.test.ts
Normal file
@@ -0,0 +1,103 @@
|
||||
import { afterEach, describe, expect, it } from 'vitest';
|
||||
import Fastify from 'fastify';
|
||||
import fs from 'node:fs';
|
||||
import os from 'node:os';
|
||||
import path from 'node:path';
|
||||
import { addAgent } from '../../src/local/agents-store.js';
|
||||
import { AgentRunRegistry } from '../../src/local/agent-run-registry.js';
|
||||
import { agentEntityRoutes } from '../../src/local/routes/agents.js';
|
||||
|
||||
const tempDirs: string[] = [];
|
||||
|
||||
afterEach(() => {
|
||||
for (const dir of tempDirs.splice(0)) fs.rmSync(dir, { recursive: true, force: true });
|
||||
});
|
||||
|
||||
describe('Agent Center durable Fleet run integration', () => {
|
||||
it('passes agentId, derives live state from the registry, and cancels only that run', async () => {
|
||||
const dataDir = fs.mkdtempSync(path.join(os.tmpdir(), 'waggle-agent-durable-'));
|
||||
tempDirs.push(dataDir);
|
||||
const registry = new AgentRunRegistry(path.join(dataDir, 'agent-runs.json'));
|
||||
const agent = addAgent(dataDir, {
|
||||
name: 'Research agent',
|
||||
goal: 'Research the workspace',
|
||||
type: 'workspace',
|
||||
personaId: 'researcher',
|
||||
model: 'test-model',
|
||||
autonomyLevel: 'guided',
|
||||
workspaceIds: ['workspace-1'],
|
||||
memoryScopes: ['personal', 'workspace'],
|
||||
status: 'idle',
|
||||
});
|
||||
let receivedAgentId = '';
|
||||
let cancelledRunId = '';
|
||||
let legacyTraceStarts = 0;
|
||||
let legacyPauses = 0;
|
||||
const server = Fastify({ logger: false });
|
||||
server.decorate('localConfig', { dataDir, port: 0, host: '127.0.0.1', litellmUrl: '' });
|
||||
server.decorate('agentRunRegistry', registry);
|
||||
server.decorate('traceStore', {
|
||||
queryParsed: () => [],
|
||||
start: () => { legacyTraceStarts++; return 1; },
|
||||
} as never);
|
||||
server.decorate('sessionManager', {
|
||||
getActive: () => [],
|
||||
pause: () => { legacyPauses++; return true; },
|
||||
} as never);
|
||||
server.post('/api/fleet/spawn', async (request, reply) => {
|
||||
const body = request.body as { agentId: string; task: string; parentWorkspaceId: string };
|
||||
receivedAgentId = body.agentId;
|
||||
const room = registry.createRoom({
|
||||
workspaceIds: [body.parentWorkspaceId], source: 'fleet', title: 'Agent run', task: body.task,
|
||||
});
|
||||
const run = registry.createWorker({
|
||||
parentRunId: room.id,
|
||||
workspaceId: body.parentWorkspaceId,
|
||||
source: 'fleet',
|
||||
executor: { kind: 'waggle_agent', agentId: body.agentId, personaId: 'researcher', model: 'test-model' },
|
||||
title: 'Research agent',
|
||||
task: body.task,
|
||||
status: 'running',
|
||||
capabilities: { cancel: true },
|
||||
});
|
||||
registry.registerControls(run.id, { cancel: () => { cancelledRunId = run.id; } });
|
||||
return reply.code(202).send({
|
||||
runId: run.id,
|
||||
roomId: room.id,
|
||||
sessionId: `spawn-${run.id}`,
|
||||
workspaceId: body.parentWorkspaceId,
|
||||
status: 'running',
|
||||
statusUrl: `/api/agent-runs/${run.id}`,
|
||||
resumable: false,
|
||||
model: 'test-model',
|
||||
});
|
||||
});
|
||||
await server.register(agentEntityRoutes);
|
||||
|
||||
const started = await server.inject({
|
||||
method: 'POST', url: `/api/agents/${agent.id}/run`, payload: { input: 'Investigate now' },
|
||||
});
|
||||
expect(started.statusCode).toBe(200);
|
||||
const startedBody = started.json() as { runId: string; roomId: string; resumable: boolean; statusUrl: string };
|
||||
expect(receivedAgentId).toBe(agent.id);
|
||||
expect(startedBody.runId).toMatch(/^run_/);
|
||||
expect(startedBody.roomId).toMatch(/^room_/);
|
||||
expect(startedBody.resumable).toBe(false);
|
||||
expect(startedBody.statusUrl).toBe(`/api/agent-runs/${startedBody.runId}`);
|
||||
expect(legacyTraceStarts).toBe(0);
|
||||
|
||||
const agentsWhileRunning = await server.inject({ method: 'GET', url: '/api/agents' });
|
||||
expect(agentsWhileRunning.json().agents[0].status).toBe('running');
|
||||
|
||||
const stopped = await server.inject({ method: 'POST', url: `/api/agents/${agent.id}/pause` });
|
||||
expect(stopped.statusCode).toBe(200);
|
||||
expect(stopped.json()).toMatchObject({ ok: true, paused: 0, cancelled: 1, runId: startedBody.runId });
|
||||
expect(cancelledRunId).toBe(startedBody.runId);
|
||||
expect(registry.get(startedBody.runId)?.status).toBe('cancelled');
|
||||
expect(legacyPauses).toBe(0);
|
||||
|
||||
const agentsAfter = await server.inject({ method: 'GET', url: '/api/agents' });
|
||||
expect(agentsAfter.json().agents[0].status).toBe('completed');
|
||||
await server.close();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user