@spexcode/transcript 0.7.0-next.3 → 0.7.0-next.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/parsers.js +16 -7
  2. package/package.json +1 -1
package/dist/parsers.js CHANGED
@@ -104,6 +104,9 @@ export function claudeEvent(value) {
104
104
  }
105
105
  return null;
106
106
  }
107
+ const blockText = (content) => typeof content === 'string'
108
+ ? string(content)
109
+ : items(content).map((block) => string(object(block)?.text)).filter(Boolean).join('\n') || null;
107
110
  export function codexEvent(value) {
108
111
  const entry = object(value);
109
112
  const payload = object(entry?.payload);
@@ -113,16 +116,25 @@ export function codexEvent(value) {
113
116
  if (eventAt === null)
114
117
  return { at: null, turn: null };
115
118
  const type = string(payload.type);
116
- if ((entry.type === 'event_msg' && type === 'user_message')
117
- || (entry.type === 'response_item' && (type === 'message' || type === 'input_message') && payload.role === 'user')) {
119
+ // THE PERSON'S MESSAGE is the `user_message` event. Codex also records it as a `response_item` message (the API
120
+ // form, `input_text` blocks) beside harness injections that no person typed (the AGENTS.md instructions), so
121
+ // that form is not a turn — the event is, once.
122
+ if (entry.type === 'event_msg' && type === 'user_message') {
118
123
  const text = typeof payload.message === 'string' ? payload.message : compact(payload.message ?? payload.content ?? '');
119
124
  return text ? { at: eventAt, turn: { id: idOf(payload) ?? idOf(entry), at: eventAt, role: 'user', text, tools: [] } } : null;
120
125
  }
121
- // commentary AND the final answer are both what the agent said; only structured reasoning stays private
126
+ if (entry.type === 'response_item' && (type === 'message' || type === 'input_message') && payload.role === 'user')
127
+ return { at: eventAt, turn: null };
128
+ // WHAT THE AGENT SAID is the `agent_message` event — commentary and the final answer alike. Codex 0.146 also
129
+ // records the same prose as a `response_item` message (`output_text` blocks) beside it, so that form is not read:
130
+ // reading both would say every sentence twice. An empty event (a final answer that was a tool call) is a clock,
131
+ // not a turn. Structured reasoning stays private.
122
132
  if (entry.type === 'event_msg' && type === 'agent_message') {
123
133
  const text = string(payload.message ?? payload.text);
124
- return text ? { at: eventAt, turn: { id: idOf(payload) ?? idOf(entry), at: eventAt, role: 'assistant', text, tools: [] } } : null;
134
+ return text ? { at: eventAt, turn: { id: idOf(payload) ?? idOf(entry), at: eventAt, role: 'assistant', text, tools: [] } } : { at: eventAt, turn: null };
125
135
  }
136
+ if (entry.type === 'response_item' && type === 'message' && payload.role === 'assistant')
137
+ return { at: eventAt, turn: null };
126
138
  if (entry.type === 'response_item' && (type === 'custom_tool_call' || type === 'function_call')) {
127
139
  const id = string(payload.call_id ?? payload.id) ?? 'tool';
128
140
  return { at: eventAt, turn: { id: idOf(payload) ?? idOf(entry), at: eventAt, role: 'assistant', tools: [{ id, name: string(payload.name ?? payload.tool_name) ?? 'tool', input: payload.input === undefined && payload.arguments === undefined ? undefined : compact(payload.input ?? payload.arguments), outputLines: 0, outputBytes: 0 }] } };
@@ -229,9 +241,6 @@ export function codexAppServerStream() {
229
241
  return parsed;
230
242
  };
231
243
  }
232
- const blockText = (content) => typeof content === 'string'
233
- ? string(content)
234
- : items(content).map((block) => string(object(block)?.text)).filter(Boolean).join('\n') || null;
235
244
  export function piEvent(value) {
236
245
  const entry = object(value);
237
246
  const message = object(entry?.message);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spexcode/transcript",
3
- "version": "0.7.0-next.3",
3
+ "version": "0.7.0-next.4",
4
4
  "type": "module",
5
5
  "description": "Normalized agent transcripts: one parser per harness, a bounded interval reader over a native thread file or an in-memory event stream, and the full/delta frame protocol every transport and renderer share.",
6
6
  "files": [