feat(worker): ClaudeCodeAdapter runs claude -p stream-json in the per-user box

This commit is contained in:
Gabriel Brown
2026-07-11 10:35:56 -04:00
parent c9ee2e6cde
commit 76886621b5
7 changed files with 465 additions and 0 deletions
@@ -1,6 +1,7 @@
import { describe, expect, test } from 'vitest';
import {
normalizeClaudeJsonLine,
normalizeCodexJsonLine,
normalizeOpenCodeEvent,
normalizeOpenCodeRunLine,
@@ -329,4 +330,73 @@ describe('agent event normalization', () => {
status: 'not json at all',
});
});
test('normalizes Claude Code stream-json output lines', () => {
expect(
normalizeClaudeJsonLine(
JSON.stringify({
type: 'system',
subtype: 'init',
session_id: 'abc',
}),
),
).toContainEqual({ kind: 'session', sessionId: 'abc' });
expect(
normalizeClaudeJsonLine(
JSON.stringify({
type: 'assistant',
message: {
content: [
{ type: 'text', text: 'hello ' },
{ type: 'text', text: 'world' },
],
},
}),
),
).toContainEqual({ kind: 'assistant_delta', content: 'hello world' });
expect(
normalizeClaudeJsonLine(
JSON.stringify({
type: 'assistant',
message: {
content: [
{ type: 'tool_use', name: 'Bash', input: { command: 'ls' } },
],
},
}),
),
).toContainEqual({
kind: 'tool_started',
name: 'Bash',
input: JSON.stringify({ command: 'ls' }),
});
expect(
normalizeClaudeJsonLine(
JSON.stringify({
type: 'result',
subtype: 'success',
result: 'final text',
session_id: 'abc',
}),
),
).toContainEqual({ kind: 'assistant_completed', content: 'final text' });
expect(
normalizeClaudeJsonLine(
JSON.stringify({
type: 'result',
subtype: 'error_max_turns',
result: 'hit the turn limit',
}),
),
).toContainEqual({ kind: 'error', message: 'hit the turn limit' });
expect(normalizeClaudeJsonLine('not json at all')).toContainEqual({
kind: 'status',
status: 'not json at all',
});
});
});