moving
Some checks failed
Installer Smoke / installer-smoke (push) Has been cancelled

This commit is contained in:
Oleg Maslov
2026-09-02 10:10:29 +02:00
commit 0c3e2ead3b
3841 changed files with 970576 additions and 0 deletions

View File

@@ -0,0 +1,152 @@
import { describe, it, expect, vi } from 'vitest';
import { AgentMessageBus } from '../src/agent-message-bus.js';
import { createAgentCommsTools } from '../src/agent-comms-tools.js';
describe('AgentMessageBus', () => {
it('send() delivers message to recipient workspace', () => {
const bus = new AgentMessageBus();
const id = bus.send({ from: 'ws-1', to: 'ws-2', content: 'Hello from ws-1' });
expect(id).toBeTruthy();
const messages = bus.receive('ws-2');
expect(messages).toHaveLength(1);
expect(messages[0].from).toBe('ws-1');
expect(messages[0].content).toBe('Hello from ws-1');
});
it('receive() clears messages after read (one-shot)', () => {
const bus = new AgentMessageBus();
bus.send({ from: 'ws-1', to: 'ws-2', content: 'Message 1' });
bus.send({ from: 'ws-1', to: 'ws-2', content: 'Message 2' });
const first = bus.receive('ws-2');
expect(first).toHaveLength(2);
const second = bus.receive('ws-2');
expect(second).toHaveLength(0);
});
it('messages have sender, recipient, content, timestamp', () => {
const bus = new AgentMessageBus();
bus.send({ from: 'ws-1', to: 'ws-2', content: 'Test' });
const messages = bus.receive('ws-2');
expect(messages[0].id).toBeTruthy();
expect(messages[0].from).toBe('ws-1');
expect(messages[0].to).toBe('ws-2');
expect(messages[0].content).toBe('Test');
expect(messages[0].timestamp).toBeGreaterThan(0);
});
it('request/response pattern with correlationId', () => {
const bus = new AgentMessageBus();
const requestId = bus.send({ from: 'ws-1', to: 'ws-2', content: 'What is X?' });
const responseId = bus.reply(requestId, 'X is 42', 'ws-2', 'ws-1');
const responses = bus.receive('ws-1');
expect(responses).toHaveLength(1);
expect(responses[0].correlationId).toBe(requestId);
expect(responses[0].content).toBe('X is 42');
});
it('messages expire after TTL', () => {
const bus = new AgentMessageBus();
bus.send({ from: 'ws-1', to: 'ws-2', content: 'Expired', ttlMs: 1 });
// Wait for expiry
const start = Date.now();
while (Date.now() - start < 5) { /* spin */ }
const messages = bus.receive('ws-2');
expect(messages).toHaveLength(0);
});
it('peek() shows messages without consuming them', () => {
const bus = new AgentMessageBus();
bus.send({ from: 'ws-1', to: 'ws-2', content: 'Peek test' });
expect(bus.peek('ws-2')).toHaveLength(1);
expect(bus.peek('ws-2')).toHaveLength(1); // Still there
bus.receive('ws-2'); // Consume
expect(bus.peek('ws-2')).toHaveLength(0);
});
it('cleanup() removes expired messages', () => {
const bus = new AgentMessageBus();
bus.send({ from: 'ws-1', to: 'ws-2', content: 'Expired', ttlMs: 1 });
bus.send({ from: 'ws-1', to: 'ws-3', content: 'Still valid', ttlMs: 60000 });
const start = Date.now();
while (Date.now() - start < 5) { /* spin */ }
const removed = bus.cleanup();
expect(removed).toBe(1);
expect(bus.peek('ws-3')).toHaveLength(1);
});
it('pendingCount() returns message count', () => {
const bus = new AgentMessageBus();
bus.send({ from: 'ws-1', to: 'ws-2', content: 'A' });
bus.send({ from: 'ws-1', to: 'ws-2', content: 'B' });
expect(bus.pendingCount('ws-2')).toBe(2);
expect(bus.pendingCount('ws-3')).toBe(0);
});
});
describe('send_agent_message tool', () => {
it('sends message to another workspace agent', async () => {
const bus = new AgentMessageBus();
const tools = createAgentCommsTools(bus, 'ws-1');
const sendTool = tools.find(t => t.name === 'send_agent_message')!;
const result = JSON.parse(await sendTool.execute({ workspace: 'ws-2', message: 'Research findings' }));
expect(result.success).toBe(true);
expect(result.messageId).toBeTruthy();
// Verify message arrived
const messages = bus.receive('ws-2');
expect(messages).toHaveLength(1);
expect(messages[0].content).toBe('Research findings');
});
it('rejects sending to self', async () => {
const bus = new AgentMessageBus();
const tools = createAgentCommsTools(bus, 'ws-1');
const sendTool = tools.find(t => t.name === 'send_agent_message')!;
const result = JSON.parse(await sendTool.execute({ workspace: 'ws-1', message: 'Self' }));
expect(result.success).toBe(false);
expect(result.error).toContain('yourself');
});
it('fails if target workspace is not active', async () => {
const bus = new AgentMessageBus();
const tools = createAgentCommsTools(bus, 'ws-1', (id) => id === 'ws-1');
const sendTool = tools.find(t => t.name === 'send_agent_message')!;
const result = JSON.parse(await sendTool.execute({ workspace: 'ws-2', message: 'Hello' }));
expect(result.success).toBe(false);
expect(result.error).toContain('not active');
});
});
describe('check_agent_messages tool', () => {
it('returns pending messages and consumes them', async () => {
const bus = new AgentMessageBus();
bus.send({ from: 'ws-2', to: 'ws-1', content: 'Here are the findings' });
const tools = createAgentCommsTools(bus, 'ws-1');
const checkTool = tools.find(t => t.name === 'check_agent_messages')!;
const result = JSON.parse(await checkTool.execute({}));
expect(result.count).toBe(1);
expect(result.messages[0].from).toBe('ws-2');
expect(result.messages[0].content).toBe('Here are the findings');
// Second check should be empty (consumed)
const result2 = JSON.parse(await checkTool.execute({}));
expect(result2.count).toBe(0);
});
});