Files
spoon/apps/agent-worker/tests/unit/agent-events.test.ts
T
Gabriel Brown 65aae85369
Build and Push Spoon Images / quality (push) Successful in 1m27s
Build and Push Spoon Images / build-images (push) Successful in 7m13s
Update formatting on worker
2026-06-24 08:40:52 -04:00

295 lines
7.2 KiB
TypeScript

import { describe, expect, test } from 'vitest';
import {
normalizeCodexJsonLine,
normalizeOpenCodeEvent,
} from '../../src/agent-events';
describe('agent event normalization', () => {
test('normalizes Codex assistant deltas and session ids', () => {
expect(
normalizeCodexJsonLine(
JSON.stringify({
type: 'session.created',
session_id: 'codex-session-1',
}),
),
).toContainEqual({ kind: 'session', sessionId: 'codex-session-1' });
expect(
normalizeCodexJsonLine(
JSON.stringify({
type: 'response.output_text.delta',
delta: 'hello',
}),
),
).toContainEqual({ kind: 'assistant_delta', content: 'hello' });
});
test('normalizes legacy codex-rs msg-wrapped events', () => {
expect(
normalizeCodexJsonLine(
JSON.stringify({
id: '0',
msg: { type: 'agent_message', message: 'hello there' },
}),
),
).toContainEqual({ kind: 'assistant_delta', content: 'hello there\n\n' });
expect(
normalizeCodexJsonLine(
JSON.stringify({
id: '1',
msg: { type: 'error', message: 'usage limit reached' },
}),
),
).toContainEqual({ kind: 'error', message: 'usage limit reached' });
expect(
normalizeCodexJsonLine(
JSON.stringify({ id: '2', msg: { type: 'task_complete' } }),
),
).toContainEqual({ kind: 'assistant_completed' });
});
test('normalizes Codex CLI thread lifecycle events', () => {
expect(
normalizeCodexJsonLine(
JSON.stringify({
type: 'thread.started',
thread_id: '019ef701-f7d7-76a0-a96b-15c059631dd9',
}),
),
).toContainEqual({
kind: 'session',
sessionId: '019ef701-f7d7-76a0-a96b-15c059631dd9',
});
expect(
normalizeCodexJsonLine(
JSON.stringify({
type: 'turn.started',
}),
),
).toContainEqual({ kind: 'status', status: 'turn.started' });
expect(
normalizeCodexJsonLine(
JSON.stringify({
type: 'turn.completed',
}),
),
).toContainEqual({ kind: 'assistant_completed' });
});
test('normalizes Codex command and file events', () => {
expect(
normalizeCodexJsonLine(
JSON.stringify({
type: 'command.completed',
command: 'bun test',
output: 'ok',
}),
),
).toContainEqual({
kind: 'command_executed',
command: 'bun test',
output: 'ok',
});
expect(
normalizeCodexJsonLine(
JSON.stringify({
type: 'file.edited',
path: 'src/app.ts',
}),
),
).toContainEqual({ kind: 'file_edited', path: 'src/app.ts' });
});
test('normalizes current Codex item events', () => {
expect(
normalizeCodexJsonLine(
JSON.stringify({
type: 'item.completed',
item: {
id: 'item-1',
type: 'agent_message',
text: 'I updated the auth provider.',
},
}),
),
).toContainEqual({
kind: 'assistant_delta',
content: 'I updated the auth provider.\n\n',
externalMessageId: 'item-1',
});
expect(
normalizeCodexJsonLine(
JSON.stringify({
type: 'item.completed',
item: {
id: 'item-2',
type: 'error',
message: 'sandbox failed',
},
}),
),
).toContainEqual({
kind: 'error',
message: 'sandbox failed',
});
expect(
normalizeCodexJsonLine(
JSON.stringify({
type: 'turn.failed',
error: { message: 'request failed' },
}),
),
).toContainEqual({
kind: 'error',
message: '{\n "message": "request failed"\n}',
});
expect(
normalizeCodexJsonLine(
JSON.stringify({
type: 'item.completed',
item: {
id: 'item-warning',
type: 'error',
message:
'`[features].codex_hooks` is deprecated. Use `[features].hooks` instead.',
},
}),
),
).toContainEqual({
kind: 'status',
status:
'`[features].codex_hooks` is deprecated. Use `[features].hooks` instead.',
});
});
test('normalizes Codex tool item lifecycle events', () => {
expect(
normalizeCodexJsonLine(
JSON.stringify({
type: 'item.started',
item: {
id: 'tool-1',
type: 'local_shell_call',
command: ['bash', '-lc', 'rg Authentik'],
},
}),
),
).toContainEqual({
kind: 'tool_started',
name: 'Command',
input: 'bash -lc rg Authentik',
externalMessageId: 'tool-1',
});
expect(
normalizeCodexJsonLine(
JSON.stringify({
type: 'item.completed',
item: {
id: 'tool-1',
type: 'local_shell_call',
command: ['bash', '-lc', 'rg Authentik'],
output: 'apps/web/auth.ts',
},
}),
),
).toContainEqual({
kind: 'tool_completed',
name: 'Command',
output: 'apps/web/auth.ts',
externalMessageId: 'tool-1',
});
expect(
normalizeCodexJsonLine(
JSON.stringify({
type: 'item.completed',
item: {
id: 'tool-2',
type: 'exec_command',
command: 'cat package.json',
aggregated_output: '{"scripts":{"build":"turbo build"}}',
exit_code: 0,
},
}),
),
).toContainEqual({
kind: 'tool_completed',
name: 'Command',
output: '{"scripts":{"build":"turbo build"}}',
externalMessageId: 'tool-2',
});
});
test('normalizes OpenCode assistant, tool, and permission events', () => {
expect(
normalizeOpenCodeEvent({
type: 'message.part.delta',
properties: {
part: { text: 'streamed' },
messageID: 'message-1',
},
}),
).toContainEqual({
kind: 'assistant_delta',
content: 'streamed',
externalMessageId: 'message-1',
});
expect(
normalizeOpenCodeEvent({
type: 'tool.started',
properties: { tool: 'edit', input: { path: 'README.md' } },
}),
).toContainEqual({
kind: 'tool_started',
name: 'edit',
input: '{\n "path": "README.md"\n}',
externalMessageId: '',
});
expect(
normalizeOpenCodeEvent({
type: 'permission.asked',
properties: {
permissionID: 'perm-1',
message: 'Run bun test?',
},
}),
).toContainEqual({
kind: 'permission_requested',
externalRequestId: 'perm-1',
title: 'Permission requested',
body: 'Run bun test?',
metadata:
'{\n "permissionID": "perm-1",\n "message": "Run bun test?"\n}',
});
expect(
normalizeOpenCodeEvent({
type: 'tool.output',
properties: {
tool: 'read',
output: 'apps/web/auth.ts',
messageID: 'message-2',
},
}),
).toContainEqual({
kind: 'tool_completed',
name: 'read',
output: 'apps/web/auth.ts',
externalMessageId: 'message-2',
});
});
});