refactor: add canonical transcript assembly seam

This commit is contained in:
tommy0103
2026-07-21 00:58:34 +08:00
parent 3ee44de4e5
commit f79f1b3e3b
39 changed files with 1741 additions and 670 deletions
+212
View File
@@ -0,0 +1,212 @@
import test from 'node:test';
import assert from 'node:assert/strict';
import { mkdtempSync, readFileSync, writeFileSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
import { DatabaseSync } from 'node:sqlite';
import { assembleSessionDetail } from '../packages/core/src/session-detail.ts';
import { persist } from '../packages/core/src/persist.ts';
import { parse as parseCodex } from '../packages/core/src/providers/codex.ts';
const SCHEMA = readFileSync(new URL('../packages/core/src/schema.sql', import.meta.url), 'utf8');
function writeCodexFixture(lines) {
const dir = mkdtempSync(join(tmpdir(), 'obelisk-provider-detail-'));
const path = join(dir, 'rollout.jsonl');
writeFileSync(path, `${lines.map(line => JSON.stringify(line)).join('\n')}\n`);
return path;
}
test('a provider record stream assembles directly into session detail', () => {
const threadId = '019e8951-3e7d-7343-a3e3-05bff48a317d';
const path = writeCodexFixture([
{
type: 'session_meta',
timestamp: '2026-06-10T10:00:00Z',
payload: { id: threadId, cwd: '/proj', timestamp: '2026-06-10T10:00:00Z' },
},
{
type: 'event_msg',
timestamp: '2026-06-10T10:00:01Z',
payload: { type: 'user_message', message: 'inspect the repository' },
},
{
type: 'event_msg',
timestamp: '2026-06-10T10:00:02Z',
payload: { type: 'agent_message', message: 'I will inspect it.' },
},
{
type: 'response_item',
timestamp: '2026-06-10T10:00:03Z',
payload: { type: 'function_call', call_id: 'call_1', name: 'shell', arguments: '{"cmd":"ls"}' },
},
{
type: 'response_item',
timestamp: '2026-06-10T10:00:04Z',
payload: { type: 'function_call_output', call_id: 'call_1', output: 'package.json' },
},
]);
const records = [...parseCodex({ key: path, sessionId: '' }, null)];
const detail = assembleSessionDetail(records);
assert.deepEqual(detail.messages.map(message => message.text), [
'inspect the repository',
'I will inspect it.',
]);
assert.equal(detail.messages[1].tool_calls?.[0].name, 'shell');
assert.equal(detail.messages[1].tool_calls?.[0].result?.content, 'package.json');
const db = new DatabaseSync(':memory:');
db.exec(SCHEMA);
persist(db, { key: path, sessionId: '' }, parseCodex({ key: path, sessionId: '' }, null));
const persistedDetail = assembleSessionDetail({
session: db.prepare('SELECT * FROM sessions').get(),
messages: db.prepare('SELECT * FROM messages ORDER BY timestamp, uuid').all(),
toolCalls: db.prepare('SELECT * FROM tool_calls').all(),
toolResults: db.prepare('SELECT * FROM tool_results').all(),
});
assert.deepEqual(persistedDetail, detail);
db.close();
});
test('provider-classified hidden context never reaches session detail', () => {
const threadId = '019e8951-3e7d-7343-a3e3-05bff48a317e';
const path = writeCodexFixture([
{
type: 'session_meta',
timestamp: '2026-06-10T10:00:00Z',
payload: { id: threadId, cwd: '/proj', timestamp: '2026-06-10T10:00:00Z' },
},
{
type: 'response_item',
timestamp: '2026-06-10T10:00:01Z',
payload: {
type: 'message',
role: 'user',
content: [{ type: 'input_text', text: '<environment_context>\n <cwd>/proj</cwd>\n</environment_context>' }],
},
},
{
type: 'response_item',
timestamp: '2026-06-10T10:00:02Z',
payload: {
type: 'message',
role: 'user',
content: [{ type: 'input_text', text: '<codex_internal_context source="goal">\nsecret state\n</codex_internal_context>' }],
},
},
{
type: 'event_msg',
timestamp: '2026-06-10T10:00:03Z',
payload: { type: 'user_message', message: 'show the actual request' },
},
]);
const records = [...parseCodex({ key: path, sessionId: '' }, null)];
const detail = assembleSessionDetail(records);
assert.deepEqual(detail.messages.map(message => message.text), ['show the actual request']);
assert.equal(
records.filter(record => record.kind === 'message' && record.visibility === 'hidden').length,
2,
);
});
test('provider normalization removes only structural image wrappers before deduplication', () => {
const threadId = '019e8951-3e7d-7343-a3e3-05bff48a317f';
const path = writeCodexFixture([
{
type: 'session_meta',
timestamp: '2026-06-10T10:00:00Z',
payload: { id: threadId, cwd: '/proj', timestamp: '2026-06-10T10:00:00Z' },
},
{
type: 'event_msg',
timestamp: '2026-06-10T10:00:01Z',
payload: { type: 'user_message', message: 'look at this screenshot' },
},
{
type: 'response_item',
timestamp: '2026-06-10T10:00:01Z',
payload: {
type: 'message',
role: 'user',
content: [
{ type: 'input_text', text: 'look at this screenshot' },
{ type: 'input_text', text: '<image>' },
{ type: 'input_image', image_url: 'data:image/png;base64,AAAA' },
{ type: 'input_text', text: '</image>' },
],
},
},
]);
const records = [...parseCodex({ key: path, sessionId: '' }, null)];
const detail = assembleSessionDetail(records);
assert.deepEqual(detail.messages.map(message => message.text), ['look at this screenshot']);
});
test('canonical visibility survives persistence before row-based assembly', () => {
const threadId = '019e8951-3e7d-7343-a3e3-05bff48a3180';
const path = writeCodexFixture([
{
type: 'session_meta',
timestamp: '2026-06-10T10:00:00Z',
payload: { id: threadId, cwd: '/proj', timestamp: '2026-06-10T10:00:00Z' },
},
{
type: 'response_item',
timestamp: '2026-06-10T10:00:01Z',
payload: {
type: 'message',
role: 'user',
content: [{ type: 'input_text', text: '<environment_context>hidden</environment_context>' }],
},
},
{
type: 'event_msg',
timestamp: '2026-06-10T10:00:02Z',
payload: { type: 'user_message', message: 'visible request' },
},
]);
const db = new DatabaseSync(':memory:');
db.exec(SCHEMA);
persist(db, { key: path, sessionId: '' }, parseCodex({ key: path, sessionId: '' }, null));
const messages = db.prepare('SELECT * FROM messages ORDER BY timestamp, uuid').all();
const assembled = assembleSessionDetail({ messages }).messages;
assert.equal(messages[0].visibility, 'hidden');
assert.deepEqual(assembled.map(message => message.text), ['visible request']);
db.close();
});
test('provider normalization classifies Skill instructions before assembly', () => {
const threadId = '019e8951-3e7d-7343-a3e3-05bff48a3181';
const path = writeCodexFixture([
{
type: 'session_meta',
timestamp: '2026-06-10T10:00:00Z',
payload: { id: threadId, cwd: '/proj', timestamp: '2026-06-10T10:00:00Z' },
},
{
type: 'response_item',
timestamp: '2026-06-10T10:00:01Z',
payload: {
type: 'message',
role: 'user',
content: [{ type: 'input_text', text: 'Base directory for this skill: /tmp/skill\n# Instructions' }],
},
},
]);
const records = [...parseCodex({ key: path, sessionId: '' }, null)];
const message = records.find(record => record.kind === 'message');
assert.equal(message.content_type, 'skill_instructions');
assert.equal(message.is_meta, 1);
assert.equal(message.visibility, 'visible');
});