@shipfox/api-logs 10.0.0 → 10.2.0
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.
- package/.turbo/turbo-build.log +4 -4
- package/CHANGELOG.md +23 -0
- package/dist/core/append-logs.d.ts.map +1 -1
- package/dist/core/append-logs.js +13 -5
- package/dist/core/append-logs.js.map +1 -1
- package/dist/core/close-stream.d.ts.map +1 -1
- package/dist/core/close-stream.js +16 -1
- package/dist/core/close-stream.js.map +1 -1
- package/dist/core/entities/attempt-stream.d.ts +2 -1
- package/dist/core/entities/attempt-stream.d.ts.map +1 -1
- package/dist/core/entities/attempt-stream.js.map +1 -1
- package/dist/core/session/claude/rows.d.ts +15 -3
- package/dist/core/session/claude/rows.d.ts.map +1 -1
- package/dist/core/session/claude/rows.js +221 -15
- package/dist/core/session/claude/rows.js.map +1 -1
- package/dist/core/session/claude-parser.d.ts +4 -2
- package/dist/core/session/claude-parser.d.ts.map +1 -1
- package/dist/core/session/claude-parser.js +56 -10
- package/dist/core/session/claude-parser.js.map +1 -1
- package/dist/db/db.d.ts +113 -0
- package/dist/db/db.d.ts.map +1 -1
- package/dist/db/schema/attempt-streams.d.ts +113 -0
- package/dist/db/schema/attempt-streams.d.ts.map +1 -1
- package/dist/db/schema/attempt-streams.js +2 -0
- package/dist/db/schema/attempt-streams.js.map +1 -1
- package/dist/db/streams.d.ts +3 -1
- package/dist/db/streams.d.ts.map +1 -1
- package/dist/db/streams.js +6 -1
- package/dist/db/streams.js.map +1 -1
- package/dist/tsconfig.test.tsbuildinfo +1 -1
- package/drizzle/0002_wise_dorian_gray.sql +1 -0
- package/drizzle/meta/0002_snapshot.json +561 -0
- package/drizzle/meta/_journal.json +7 -0
- package/package.json +4 -4
- package/src/core/append-logs.test.ts +57 -0
- package/src/core/append-logs.ts +15 -3
- package/src/core/close-stream.ts +17 -1
- package/src/core/entities/attempt-stream.ts +2 -1
- package/src/core/session/claude/rows.ts +295 -13
- package/src/core/session/claude-parser.test.ts +620 -11
- package/src/core/session/claude-parser.ts +59 -10
- package/src/db/schema/attempt-streams.ts +3 -1
- package/src/db/streams.ts +10 -2
- package/test/fixtures/claude-session/agent-step.jsonl +12 -0
- package/test/fixtures/claude-session/sdk-system-subtypes.json +32 -0
- package/test/fixtures/claude-session.ts +45 -0
- package/tsconfig.build.tsbuildinfo +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { asLooseObject } from '../entry-schema.js';
|
|
2
|
-
import { booleanField, field, formatNumber, isMeta, metaItem, stringField, stringifyValue, toJson } from '../object.js';
|
|
2
|
+
import { booleanField, field, formatNumber, isMeta, metaItem, numberField, stringField, stringifyValue, toJson } from '../object.js';
|
|
3
3
|
import { lifecycleRow, messageRow, thinkingRow } from '../rows.js';
|
|
4
4
|
export const PURE_PROGRESS_CLAUDE_SYSTEM_SUBTYPES = new Set([
|
|
5
5
|
'thinking_tokens',
|
|
@@ -15,6 +15,99 @@ export const PURE_PROGRESS_CLAUDE_SYSTEM_SUBTYPES = new Set([
|
|
|
15
15
|
'plugin_install'
|
|
16
16
|
]);
|
|
17
17
|
const OUTPUT_REPROMPT_PREFIX = 'The previous turn ended without setting required workflow outputs:';
|
|
18
|
+
export const SYSTEM_EVENT_MAPPINGS = {
|
|
19
|
+
permission_denied: {
|
|
20
|
+
label: 'Permission denied',
|
|
21
|
+
tone: 'error',
|
|
22
|
+
detail: (message)=>stringField(message, 'tool_name') ?? null,
|
|
23
|
+
meta: (message)=>[
|
|
24
|
+
metaItem('reason', stringField(message, 'decision_reason') ?? stringField(message, 'message'))
|
|
25
|
+
].filter(isMeta)
|
|
26
|
+
},
|
|
27
|
+
api_retry: {
|
|
28
|
+
label: 'API retry',
|
|
29
|
+
tone: 'warning',
|
|
30
|
+
detail: (message)=>{
|
|
31
|
+
const attempt = numberField(message, 'attempt');
|
|
32
|
+
const maxRetries = numberField(message, 'max_retries');
|
|
33
|
+
return attempt == null || maxRetries == null ? null : `attempt ${formatNumber(attempt)}/${formatNumber(maxRetries)}`;
|
|
34
|
+
},
|
|
35
|
+
meta: (message)=>[
|
|
36
|
+
numberMeta(message, 'error_status', 'status'),
|
|
37
|
+
numberMeta(message, 'retry_delay_ms', 'retry delay', 'ms')
|
|
38
|
+
].filter(isMeta)
|
|
39
|
+
},
|
|
40
|
+
informational: {
|
|
41
|
+
label: (message)=>titleCase(stringField(message, 'level') ?? 'informational'),
|
|
42
|
+
tone: (message)=>stringField(message, 'level') === 'warning' ? 'warning' : 'default',
|
|
43
|
+
detail: (message)=>stringField(message, 'content') ?? null
|
|
44
|
+
},
|
|
45
|
+
compact_boundary: {
|
|
46
|
+
label: 'Context compacted',
|
|
47
|
+
tone: 'default',
|
|
48
|
+
meta: (message)=>{
|
|
49
|
+
const compactMetadata = asLooseObject(field(message, 'compact_metadata')) ?? {};
|
|
50
|
+
return [
|
|
51
|
+
metaItem('trigger', stringField(compactMetadata, 'trigger')),
|
|
52
|
+
numberMeta(compactMetadata, 'pre_tokens', 'tokens before', 'tokens'),
|
|
53
|
+
numberMeta(compactMetadata, 'post_tokens', 'tokens after', 'tokens'),
|
|
54
|
+
numberMeta(compactMetadata, 'duration_ms', 'duration', 'ms')
|
|
55
|
+
].filter(isMeta);
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
hook_response: {
|
|
59
|
+
label: (message)=>{
|
|
60
|
+
const outcome = stringField(message, 'outcome');
|
|
61
|
+
return outcome === 'error' ? 'Hook failed' : outcome === 'cancelled' ? 'Hook cancelled' : outcome === 'success' ? 'Hook completed' : 'Hook response';
|
|
62
|
+
},
|
|
63
|
+
tone: (message)=>{
|
|
64
|
+
const outcome = stringField(message, 'outcome');
|
|
65
|
+
return outcome === 'error' ? 'error' : outcome === 'cancelled' ? 'warning' : 'default';
|
|
66
|
+
},
|
|
67
|
+
detail: (message)=>stringField(message, 'output') ?? stringField(message, 'stderr') ?? stringField(message, 'stdout') ?? null,
|
|
68
|
+
meta: (message)=>[
|
|
69
|
+
metaItem('hook', stringField(message, 'hook_name')),
|
|
70
|
+
numberMeta(message, 'exit_code', 'exit code')
|
|
71
|
+
].filter(isMeta)
|
|
72
|
+
},
|
|
73
|
+
model_refusal_fallback: {
|
|
74
|
+
label: 'Model refused, fell back',
|
|
75
|
+
tone: 'warning'
|
|
76
|
+
},
|
|
77
|
+
model_refusal_no_fallback: {
|
|
78
|
+
label: 'Model refused',
|
|
79
|
+
tone: 'error'
|
|
80
|
+
},
|
|
81
|
+
mirror_error: {
|
|
82
|
+
label: 'Session mirror failed',
|
|
83
|
+
tone: 'error',
|
|
84
|
+
detail: (message)=>stringField(message, 'error') ?? null
|
|
85
|
+
},
|
|
86
|
+
worker_shutting_down: {
|
|
87
|
+
label: 'Worker shutting down',
|
|
88
|
+
tone: 'warning'
|
|
89
|
+
},
|
|
90
|
+
elicitation_complete: {
|
|
91
|
+
label: 'Elicitation complete',
|
|
92
|
+
tone: 'default'
|
|
93
|
+
},
|
|
94
|
+
notification: {
|
|
95
|
+
label: 'Notification',
|
|
96
|
+
tone: 'default'
|
|
97
|
+
},
|
|
98
|
+
task_started: {
|
|
99
|
+
label: 'Task started',
|
|
100
|
+
tone: 'default'
|
|
101
|
+
},
|
|
102
|
+
task_updated: {
|
|
103
|
+
label: 'Task updated',
|
|
104
|
+
tone: 'default'
|
|
105
|
+
},
|
|
106
|
+
task_notification: {
|
|
107
|
+
label: 'Task notification',
|
|
108
|
+
tone: 'default'
|
|
109
|
+
}
|
|
110
|
+
};
|
|
18
111
|
export function systemRow(timestamp, message, context) {
|
|
19
112
|
const subtype = stringField(message, 'subtype');
|
|
20
113
|
const sessionId = stringField(message, 'session_id') ?? stringField(message, 'sessionId');
|
|
@@ -24,31 +117,121 @@ export function systemRow(timestamp, message, context) {
|
|
|
24
117
|
metaItem('model', stringField(message, 'model')),
|
|
25
118
|
metaItem('permission', stringField(message, 'permissionMode') ?? stringField(message, 'permission_mode'))
|
|
26
119
|
].filter(isMeta);
|
|
27
|
-
if (!isInit)
|
|
120
|
+
if (!isInit) {
|
|
121
|
+
const mapping = subtype === undefined ? undefined : SYSTEM_EVENT_MAPPINGS[subtype];
|
|
122
|
+
const label = mapping === undefined ? `Session event (${subtype ?? 'unknown'})` : typeof mapping.label === 'function' ? mapping.label(message) : mapping.label;
|
|
123
|
+
const tone = mapping === undefined ? 'default' : typeof mapping.tone === 'function' ? mapping.tone(message) : mapping.tone;
|
|
124
|
+
const detail = mapping?.detail?.(message) ?? null;
|
|
125
|
+
const meta = [
|
|
126
|
+
...baseMeta,
|
|
127
|
+
...mapping?.meta?.(message) ?? []
|
|
128
|
+
];
|
|
129
|
+
return lifecycleRow(timestamp, label, detail, tone, false, meta);
|
|
130
|
+
}
|
|
28
131
|
const isNewSession = !context.hasInit || sessionId === undefined || sessionId !== context.sessionId;
|
|
132
|
+
if (isNewSession) {
|
|
133
|
+
context.pendingToolRows.length = 0;
|
|
134
|
+
context.toolCallRows.clear();
|
|
135
|
+
}
|
|
29
136
|
context.hasInit = true;
|
|
30
137
|
context.sessionId = sessionId ?? null;
|
|
31
138
|
context.turn = isNewSession ? 1 : context.turn + 1;
|
|
32
139
|
const label = isNewSession ? 'Session started' : `Turn ${context.turn} started`;
|
|
33
140
|
const meta = [
|
|
141
|
+
metaItem('session', isNewSession ? sessionId : null),
|
|
34
142
|
metaItem('turn', isNewSession ? null : String(context.turn)),
|
|
35
143
|
...baseMeta
|
|
36
144
|
].filter(isMeta);
|
|
37
|
-
return lifecycleRow(timestamp, label,
|
|
145
|
+
return lifecycleRow(timestamp, label, null, 'default', false, meta);
|
|
146
|
+
}
|
|
147
|
+
export function authStatusRow(timestamp, message) {
|
|
148
|
+
const error = stringField(message, 'error');
|
|
149
|
+
const output = stringList(field(message, 'output')).join('\n');
|
|
150
|
+
const isAuthenticating = booleanField(message, 'isAuthenticating');
|
|
151
|
+
return lifecycleRow(timestamp, error ? 'Authentication failed' : isAuthenticating ? 'Authenticating' : 'Authentication complete', (error ?? output) || null, error ? 'error' : 'default', false);
|
|
152
|
+
}
|
|
153
|
+
const RATE_LIMIT_STATUS_MAPPINGS = {
|
|
154
|
+
rejected: {
|
|
155
|
+
label: 'Rate limit exceeded',
|
|
156
|
+
tone: 'error'
|
|
157
|
+
},
|
|
158
|
+
allowed_warning: {
|
|
159
|
+
label: 'Rate limit warning',
|
|
160
|
+
tone: 'warning'
|
|
161
|
+
},
|
|
162
|
+
allowed: {
|
|
163
|
+
label: 'Rate limit available',
|
|
164
|
+
tone: 'default'
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
export function rateLimitRow(timestamp, message) {
|
|
168
|
+
const rateLimitInfo = asLooseObject(field(message, 'rate_limit_info')) ?? {};
|
|
169
|
+
const status = stringField(rateLimitInfo, 'status');
|
|
170
|
+
const rateLimitType = stringField(rateLimitInfo, 'rateLimitType');
|
|
171
|
+
const utilization = numberField(rateLimitInfo, 'utilization');
|
|
172
|
+
const mapping = status === undefined ? undefined : RATE_LIMIT_STATUS_MAPPINGS[status];
|
|
173
|
+
const meta = [
|
|
174
|
+
metaItem('utilization', utilization == null ? null : `${formatNumber(utilization * 100)}%`),
|
|
175
|
+
mapping === undefined ? metaItem('status', status ?? null) : null
|
|
176
|
+
].filter(isMeta);
|
|
177
|
+
return lifecycleRow(timestamp, mapping?.label ?? 'Rate limit updated', rateLimitType == null ? null : humanizeEnumValue(rateLimitType), mapping?.tone ?? 'warning', false, meta);
|
|
178
|
+
}
|
|
179
|
+
export function toolUseSummary(message, context) {
|
|
180
|
+
const summary = stringField(message, 'summary');
|
|
181
|
+
if (summary === undefined) return false;
|
|
182
|
+
const precedingToolUseIds = stringList(field(message, 'preceding_tool_use_ids'));
|
|
183
|
+
const toolUseId = stringField(message, 'tool_use_id');
|
|
184
|
+
const candidateIds = precedingToolUseIds.length > 0 ? precedingToolUseIds : toolUseId === undefined ? [] : [
|
|
185
|
+
toolUseId
|
|
186
|
+
];
|
|
187
|
+
for (const id of [
|
|
188
|
+
...candidateIds
|
|
189
|
+
].reverse()){
|
|
190
|
+
const row = context.toolCallRows.get(id);
|
|
191
|
+
if (row === undefined) continue;
|
|
192
|
+
row.summary = row.summary === undefined ? summary : `${row.summary}\n\n${summary}`;
|
|
193
|
+
return true;
|
|
194
|
+
}
|
|
195
|
+
return false;
|
|
38
196
|
}
|
|
39
|
-
export function
|
|
197
|
+
export function flushPendingToolRows(context) {
|
|
198
|
+
if (context.pendingToolRows.length === 0) return [];
|
|
199
|
+
const rows = context.pendingToolRows;
|
|
200
|
+
context.pendingToolRows = [];
|
|
201
|
+
context.toolCallRows.clear();
|
|
202
|
+
return rows;
|
|
203
|
+
}
|
|
204
|
+
function titleCase(value) {
|
|
205
|
+
return value.length === 0 ? value : `${value[0]?.toUpperCase()}${value.slice(1)}`;
|
|
206
|
+
}
|
|
207
|
+
function humanizeEnumValue(value) {
|
|
208
|
+
return titleCase(value.replaceAll('_', ' '));
|
|
209
|
+
}
|
|
210
|
+
function stringList(value) {
|
|
211
|
+
if (!Array.isArray(value)) return [];
|
|
212
|
+
return value.filter((item)=>typeof item === 'string' && item.length > 0);
|
|
213
|
+
}
|
|
214
|
+
export function assistantRows(timestamp, message, context) {
|
|
40
215
|
const sdkMessage = asLooseObject(message.message) ?? message;
|
|
41
216
|
const rows = [];
|
|
42
217
|
const textParts = [];
|
|
43
218
|
const thinkingParts = [];
|
|
219
|
+
let queueRows = context.toolCallRows.size > 0;
|
|
220
|
+
const pushRow = (row)=>{
|
|
221
|
+
if (queueRows) {
|
|
222
|
+
context.pendingToolRows.push(row);
|
|
223
|
+
} else {
|
|
224
|
+
rows.push(row);
|
|
225
|
+
}
|
|
226
|
+
};
|
|
44
227
|
const pushText = ()=>{
|
|
45
228
|
if (textParts.length === 0) return;
|
|
46
|
-
|
|
229
|
+
pushRow(messageRow(timestamp, 'assistant', 'assistant', textParts.join('\n\n'), false));
|
|
47
230
|
textParts.length = 0;
|
|
48
231
|
};
|
|
49
232
|
const pushThinking = ()=>{
|
|
50
233
|
if (thinkingParts.length === 0) return;
|
|
51
|
-
|
|
234
|
+
pushRow(thinkingRow(timestamp, thinkingParts.join('\n\n')));
|
|
52
235
|
thinkingParts.length = 0;
|
|
53
236
|
};
|
|
54
237
|
for (const block of contentBlocks(sdkMessage)){
|
|
@@ -56,7 +239,14 @@ export function assistantRows(timestamp, message) {
|
|
|
56
239
|
if (type === 'tool_use' || type === 'tool-use' || type === 'toolCall') {
|
|
57
240
|
pushText();
|
|
58
241
|
pushThinking();
|
|
59
|
-
|
|
242
|
+
const row = toolCallRow(timestamp, block);
|
|
243
|
+
if (row.id === null) {
|
|
244
|
+
pushRow(row);
|
|
245
|
+
} else {
|
|
246
|
+
queueRows = true;
|
|
247
|
+
context.pendingToolRows.push(row);
|
|
248
|
+
context.toolCallRows.set(row.id, row);
|
|
249
|
+
}
|
|
60
250
|
continue;
|
|
61
251
|
}
|
|
62
252
|
if (type === 'thinking' || type === 'reasoning') {
|
|
@@ -71,17 +261,19 @@ export function assistantRows(timestamp, message) {
|
|
|
71
261
|
}
|
|
72
262
|
pushText();
|
|
73
263
|
pushThinking();
|
|
74
|
-
if (rows.length > 0) return rows;
|
|
264
|
+
if (rows.length > 0 || queueRows) return rows;
|
|
75
265
|
const text = stringField(sdkMessage, 'content') ?? stringField(message, 'result');
|
|
76
266
|
return [
|
|
77
267
|
messageRow(timestamp, 'assistant', 'assistant', text ?? toJson(message), false)
|
|
78
268
|
];
|
|
79
269
|
}
|
|
80
|
-
export function userRows(timestamp, message) {
|
|
270
|
+
export function userRows(timestamp, message, context) {
|
|
81
271
|
const sdkMessage = asLooseObject(message.message) ?? message;
|
|
82
272
|
const role = isPlatformMessage(sdkMessage) ? 'platform' : 'user';
|
|
83
273
|
const rows = [];
|
|
84
274
|
const textParts = [];
|
|
275
|
+
const hadPendingToolCall = context.toolCallRows.size > 0;
|
|
276
|
+
let matchedToolResult = false;
|
|
85
277
|
const pushText = ()=>{
|
|
86
278
|
if (textParts.length === 0) return;
|
|
87
279
|
rows.push(messageRow(timestamp, role, role, textParts.join('\n\n'), false));
|
|
@@ -91,18 +283,32 @@ export function userRows(timestamp, message) {
|
|
|
91
283
|
const type = stringField(block, 'type');
|
|
92
284
|
if (type === 'tool_result' || type === 'tool-result') {
|
|
93
285
|
pushText();
|
|
94
|
-
|
|
286
|
+
const row = toolResultRow(timestamp, block);
|
|
287
|
+
if (row.toolCallId !== null && context.toolCallRows.has(row.toolCallId)) {
|
|
288
|
+
matchedToolResult = true;
|
|
289
|
+
}
|
|
290
|
+
rows.push(row);
|
|
95
291
|
continue;
|
|
96
292
|
}
|
|
97
293
|
const text = blockText(block);
|
|
98
294
|
if (text) textParts.push(text);
|
|
99
295
|
}
|
|
100
296
|
pushText();
|
|
101
|
-
if (rows.length
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
297
|
+
if (rows.length === 0) {
|
|
298
|
+
const content = stringField(sdkMessage, 'content');
|
|
299
|
+
rows.push(messageRow(timestamp, role, role, content ?? toJson(message), false));
|
|
300
|
+
}
|
|
301
|
+
if (hadPendingToolCall) {
|
|
302
|
+
if (matchedToolResult) {
|
|
303
|
+
context.pendingToolRows.push(...rows);
|
|
304
|
+
return [];
|
|
305
|
+
}
|
|
306
|
+
return [
|
|
307
|
+
...flushPendingToolRows(context),
|
|
308
|
+
...rows
|
|
309
|
+
];
|
|
310
|
+
}
|
|
311
|
+
return rows;
|
|
106
312
|
}
|
|
107
313
|
export function resultRow(timestamp, message, turn, isFinalResult) {
|
|
108
314
|
const isError = booleanField(message, 'is_error') || booleanField(message, 'isError');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/core/session/claude/rows.ts"],"sourcesContent":["import type {\n SessionViewLifecycleRow,\n SessionViewRow,\n SessionViewRowMeta,\n SessionViewToolCallRow,\n SessionViewToolResultRow,\n} from '@shipfox/api-logs-dto';\nimport type {ClaudeParseContext} from '../claude-parser.js';\nimport {asLooseObject} from '../entry-schema.js';\nimport {\n booleanField,\n field,\n formatNumber,\n isMeta,\n metaItem,\n stringField,\n stringifyValue,\n toJson,\n} from '../object.js';\nimport {lifecycleRow, messageRow, thinkingRow} from '../rows.js';\n\nexport const PURE_PROGRESS_CLAUDE_SYSTEM_SUBTYPES = new Set<string>([\n 'thinking_tokens',\n 'status',\n 'session_state_changed',\n 'task_progress',\n 'hook_progress',\n 'hook_started',\n 'commands_changed',\n 'files_persisted',\n 'memory_recall',\n 'local_command_output',\n 'plugin_install',\n]);\nconst OUTPUT_REPROMPT_PREFIX = 'The previous turn ended without setting required workflow outputs:';\n\nexport function systemRow(\n timestamp: number,\n message: Record<string, unknown>,\n context: ClaudeParseContext,\n): SessionViewLifecycleRow {\n const subtype = stringField(message, 'subtype');\n const sessionId = stringField(message, 'session_id') ?? stringField(message, 'sessionId');\n const isInit = subtype === 'init' || message.type === 'init';\n const baseMeta = [\n metaItem('cwd', stringField(message, 'cwd'), false),\n metaItem('model', stringField(message, 'model')),\n metaItem(\n 'permission',\n stringField(message, 'permissionMode') ?? stringField(message, 'permission_mode'),\n ),\n ].filter(isMeta);\n\n if (!isInit)\n return lifecycleRow(timestamp, 'Session event', sessionId ?? null, 'default', false, baseMeta);\n\n const isNewSession =\n !context.hasInit || sessionId === undefined || sessionId !== context.sessionId;\n context.hasInit = true;\n context.sessionId = sessionId ?? null;\n context.turn = isNewSession ? 1 : context.turn + 1;\n\n const label = isNewSession ? 'Session started' : `Turn ${context.turn} started`;\n const meta = [metaItem('turn', isNewSession ? null : String(context.turn)), ...baseMeta].filter(\n isMeta,\n );\n\n return lifecycleRow(timestamp, label, sessionId ?? null, 'default', false, meta);\n}\n\nexport function assistantRows(\n timestamp: number,\n message: Record<string, unknown>,\n): readonly SessionViewRow[] {\n const sdkMessage = asLooseObject(message.message) ?? message;\n const rows: SessionViewRow[] = [];\n const textParts: string[] = [];\n const thinkingParts: string[] = [];\n\n const pushText = () => {\n if (textParts.length === 0) return;\n rows.push(messageRow(timestamp, 'assistant', 'assistant', textParts.join('\\n\\n'), false));\n textParts.length = 0;\n };\n const pushThinking = () => {\n if (thinkingParts.length === 0) return;\n rows.push(thinkingRow(timestamp, thinkingParts.join('\\n\\n')));\n thinkingParts.length = 0;\n };\n\n for (const block of contentBlocks(sdkMessage)) {\n const type = stringField(block, 'type');\n if (type === 'tool_use' || type === 'tool-use' || type === 'toolCall') {\n pushText();\n pushThinking();\n rows.push(toolCallRow(timestamp, block));\n continue;\n }\n\n if (type === 'thinking' || type === 'reasoning') {\n pushText();\n const text = blockText(block);\n if (text) thinkingParts.push(text);\n continue;\n }\n\n pushThinking();\n const text = blockText(block);\n if (text) textParts.push(text);\n }\n\n pushText();\n pushThinking();\n\n if (rows.length > 0) return rows;\n\n const text = stringField(sdkMessage, 'content') ?? stringField(message, 'result');\n return [messageRow(timestamp, 'assistant', 'assistant', text ?? toJson(message), false)];\n}\n\nexport function userRows(\n timestamp: number,\n message: Record<string, unknown>,\n): readonly SessionViewRow[] {\n const sdkMessage = asLooseObject(message.message) ?? message;\n const role = isPlatformMessage(sdkMessage) ? 'platform' : 'user';\n const rows: SessionViewRow[] = [];\n const textParts: string[] = [];\n const pushText = () => {\n if (textParts.length === 0) return;\n rows.push(messageRow(timestamp, role, role, textParts.join('\\n\\n'), false));\n textParts.length = 0;\n };\n\n for (const block of contentBlocks(sdkMessage)) {\n const type = stringField(block, 'type');\n if (type === 'tool_result' || type === 'tool-result') {\n pushText();\n rows.push(toolResultRow(timestamp, block));\n continue;\n }\n\n const text = blockText(block);\n if (text) textParts.push(text);\n }\n\n pushText();\n\n if (rows.length > 0) return rows;\n\n const content = stringField(sdkMessage, 'content');\n return [messageRow(timestamp, role, role, content ?? toJson(message), false)];\n}\n\nexport function resultRow(\n timestamp: number,\n message: Record<string, unknown>,\n turn: number,\n isFinalResult: boolean,\n): SessionViewLifecycleRow {\n const isError = booleanField(message, 'is_error') || booleanField(message, 'isError');\n const subtype = stringField(message, 'subtype');\n const terminalFailure = isError || subtype === 'error';\n const detail =\n stringField(message, 'result') ??\n stringField(message, 'error') ??\n stringField(message, 'message') ??\n null;\n const meta = [\n metaItem('turn', !terminalFailure && !isFinalResult && turn > 0 ? String(turn) : null),\n numberMeta(message, 'duration_ms', 'duration', 'ms'),\n numberMeta(message, 'duration_api_ms', 'api duration', 'ms'),\n numberMeta(message, 'num_turns', 'turns'),\n costMeta(message),\n ].filter(isMeta);\n\n return lifecycleRow(\n timestamp,\n terminalFailure\n ? 'Session failed'\n : isFinalResult || turn === 0\n ? 'Session completed'\n : `Turn ${turn} completed`,\n detail,\n terminalFailure ? 'error' : 'default',\n terminalFailure,\n meta,\n );\n}\n\nfunction isPlatformMessage(message: Record<string, unknown>): boolean {\n const content = field(message, 'content');\n if (typeof content === 'string') return content.startsWith(OUTPUT_REPROMPT_PREFIX);\n if (!Array.isArray(content)) return false;\n\n return content.some((block) => {\n const object = asLooseObject(block);\n return stringField(object, 'text')?.startsWith(OUTPUT_REPROMPT_PREFIX) === true;\n });\n}\n\nfunction contentBlocks(message: Record<string, unknown>): Record<string, unknown>[] {\n const content = message.content;\n if (!Array.isArray(content)) return [];\n\n return content.flatMap((block) => {\n const object = asLooseObject(block);\n return object ? [object] : [];\n });\n}\n\nfunction toolCallRow(timestamp: number, block: Record<string, unknown>): SessionViewToolCallRow {\n return {\n kind: 'tool-call',\n timestamp,\n id: stringField(block, 'id') ?? null,\n name: stringField(block, 'name') ?? 'tool',\n input: stringifyValue(field(block, 'input') ?? {}),\n };\n}\n\nfunction toolResultRow(\n timestamp: number,\n block: Record<string, unknown>,\n): SessionViewToolResultRow {\n return {\n kind: 'tool-result',\n timestamp,\n toolCallId: stringField(block, 'tool_use_id') ?? stringField(block, 'toolUseId') ?? null,\n toolName: stringField(block, 'name') ?? 'tool',\n output: blockText(block) || stringifyValue(field(block, 'content') ?? ''),\n isError: booleanField(block, 'is_error') || booleanField(block, 'isError'),\n };\n}\n\nfunction blockText(block: Record<string, unknown>): string {\n const content = field(block, 'content');\n if (Array.isArray(content)) {\n return content\n .map((item) => {\n const object = asLooseObject(item);\n return object ? blockText(object) : typeof item === 'string' ? item : '';\n })\n .filter(Boolean)\n .join('\\n\\n');\n }\n\n return (\n stringField(block, 'text') ??\n stringField(block, 'thinking') ??\n (typeof content === 'string' ? content : '') ??\n ''\n );\n}\n\nfunction numberMeta(\n value: unknown,\n key: string,\n label: string,\n unit?: string,\n): SessionViewRowMeta | null {\n const raw = field(value, key);\n if (typeof raw !== 'number' || !Number.isFinite(raw)) return null;\n\n return metaItem(label, unit ? `${formatNumber(raw)} ${unit}` : formatNumber(raw));\n}\n\nfunction costMeta(message: Record<string, unknown>): SessionViewRowMeta | null {\n const value = field(message, 'total_cost_usd') ?? field(message, 'totalCostUsd');\n if (typeof value !== 'number' || !Number.isFinite(value)) return null;\n\n return metaItem('cost', `$${value.toFixed(value < 0.01 ? 4 : 2)}`);\n}\n"],"names":["asLooseObject","booleanField","field","formatNumber","isMeta","metaItem","stringField","stringifyValue","toJson","lifecycleRow","messageRow","thinkingRow","PURE_PROGRESS_CLAUDE_SYSTEM_SUBTYPES","Set","OUTPUT_REPROMPT_PREFIX","systemRow","timestamp","message","context","subtype","sessionId","isInit","type","baseMeta","filter","isNewSession","hasInit","undefined","turn","label","meta","String","assistantRows","sdkMessage","rows","textParts","thinkingParts","pushText","length","push","join","pushThinking","block","contentBlocks","toolCallRow","text","blockText","userRows","role","isPlatformMessage","toolResultRow","content","resultRow","isFinalResult","isError","terminalFailure","detail","numberMeta","costMeta","startsWith","Array","isArray","some","object","flatMap","kind","id","name","input","toolCallId","toolName","output","map","item","Boolean","value","key","unit","raw","Number","isFinite","toFixed"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../src/core/session/claude/rows.ts"],"sourcesContent":["import type {\n SessionViewLifecycleRow,\n SessionViewRow,\n SessionViewRowMeta,\n SessionViewToolCallRow,\n SessionViewToolResultRow,\n} from '@shipfox/api-logs-dto';\nimport type {ClaudeParseContext} from '../claude-parser.js';\nimport {asLooseObject} from '../entry-schema.js';\nimport {\n booleanField,\n field,\n formatNumber,\n isMeta,\n metaItem,\n numberField,\n stringField,\n stringifyValue,\n toJson,\n} from '../object.js';\nimport {lifecycleRow, messageRow, thinkingRow} from '../rows.js';\n\nexport const PURE_PROGRESS_CLAUDE_SYSTEM_SUBTYPES = new Set<string>([\n 'thinking_tokens',\n 'status',\n 'session_state_changed',\n 'task_progress',\n 'hook_progress',\n 'hook_started',\n 'commands_changed',\n 'files_persisted',\n 'memory_recall',\n 'local_command_output',\n 'plugin_install',\n]);\nconst OUTPUT_REPROMPT_PREFIX = 'The previous turn ended without setting required workflow outputs:';\n\ntype SystemEventMapping = {\n label: string | ((message: Record<string, unknown>) => string);\n tone:\n | SessionViewLifecycleRow['tone']\n | ((message: Record<string, unknown>) => SessionViewLifecycleRow['tone']);\n detail?: (message: Record<string, unknown>) => string | null;\n meta?: (message: Record<string, unknown>) => readonly SessionViewRowMeta[];\n};\n\nexport const SYSTEM_EVENT_MAPPINGS: Record<string, SystemEventMapping> = {\n permission_denied: {\n label: 'Permission denied',\n tone: 'error',\n detail: (message) => stringField(message, 'tool_name') ?? null,\n meta: (message) =>\n [\n metaItem(\n 'reason',\n stringField(message, 'decision_reason') ?? stringField(message, 'message'),\n ),\n ].filter(isMeta),\n },\n api_retry: {\n label: 'API retry',\n tone: 'warning',\n detail: (message) => {\n const attempt = numberField(message, 'attempt');\n const maxRetries = numberField(message, 'max_retries');\n return attempt == null || maxRetries == null\n ? null\n : `attempt ${formatNumber(attempt)}/${formatNumber(maxRetries)}`;\n },\n meta: (message) =>\n [\n numberMeta(message, 'error_status', 'status'),\n numberMeta(message, 'retry_delay_ms', 'retry delay', 'ms'),\n ].filter(isMeta),\n },\n informational: {\n label: (message) => titleCase(stringField(message, 'level') ?? 'informational'),\n tone: (message) => (stringField(message, 'level') === 'warning' ? 'warning' : 'default'),\n detail: (message) => stringField(message, 'content') ?? null,\n },\n compact_boundary: {\n label: 'Context compacted',\n tone: 'default',\n meta: (message) => {\n const compactMetadata = asLooseObject(field(message, 'compact_metadata')) ?? {};\n return [\n metaItem('trigger', stringField(compactMetadata, 'trigger')),\n numberMeta(compactMetadata, 'pre_tokens', 'tokens before', 'tokens'),\n numberMeta(compactMetadata, 'post_tokens', 'tokens after', 'tokens'),\n numberMeta(compactMetadata, 'duration_ms', 'duration', 'ms'),\n ].filter(isMeta);\n },\n },\n hook_response: {\n label: (message) => {\n const outcome = stringField(message, 'outcome');\n return outcome === 'error'\n ? 'Hook failed'\n : outcome === 'cancelled'\n ? 'Hook cancelled'\n : outcome === 'success'\n ? 'Hook completed'\n : 'Hook response';\n },\n tone: (message) => {\n const outcome = stringField(message, 'outcome');\n return outcome === 'error' ? 'error' : outcome === 'cancelled' ? 'warning' : 'default';\n },\n detail: (message) =>\n stringField(message, 'output') ??\n stringField(message, 'stderr') ??\n stringField(message, 'stdout') ??\n null,\n meta: (message) =>\n [\n metaItem('hook', stringField(message, 'hook_name')),\n numberMeta(message, 'exit_code', 'exit code'),\n ].filter(isMeta),\n },\n model_refusal_fallback: {\n label: 'Model refused, fell back',\n tone: 'warning',\n },\n model_refusal_no_fallback: {\n label: 'Model refused',\n tone: 'error',\n },\n mirror_error: {\n label: 'Session mirror failed',\n tone: 'error',\n detail: (message) => stringField(message, 'error') ?? null,\n },\n worker_shutting_down: {\n label: 'Worker shutting down',\n tone: 'warning',\n },\n elicitation_complete: {\n label: 'Elicitation complete',\n tone: 'default',\n },\n notification: {\n label: 'Notification',\n tone: 'default',\n },\n task_started: {\n label: 'Task started',\n tone: 'default',\n },\n task_updated: {\n label: 'Task updated',\n tone: 'default',\n },\n task_notification: {\n label: 'Task notification',\n tone: 'default',\n },\n};\n\nexport function systemRow(\n timestamp: number,\n message: Record<string, unknown>,\n context: ClaudeParseContext,\n): SessionViewLifecycleRow {\n const subtype = stringField(message, 'subtype');\n const sessionId = stringField(message, 'session_id') ?? stringField(message, 'sessionId');\n const isInit = subtype === 'init' || message.type === 'init';\n const baseMeta = [\n metaItem('cwd', stringField(message, 'cwd'), false),\n metaItem('model', stringField(message, 'model')),\n metaItem(\n 'permission',\n stringField(message, 'permissionMode') ?? stringField(message, 'permission_mode'),\n ),\n ].filter(isMeta);\n\n if (!isInit) {\n const mapping = subtype === undefined ? undefined : SYSTEM_EVENT_MAPPINGS[subtype];\n const label =\n mapping === undefined\n ? `Session event (${subtype ?? 'unknown'})`\n : typeof mapping.label === 'function'\n ? mapping.label(message)\n : mapping.label;\n const tone =\n mapping === undefined\n ? 'default'\n : typeof mapping.tone === 'function'\n ? mapping.tone(message)\n : mapping.tone;\n const detail = mapping?.detail?.(message) ?? null;\n const meta = [...baseMeta, ...(mapping?.meta?.(message) ?? [])];\n\n return lifecycleRow(timestamp, label, detail, tone, false, meta);\n }\n\n const isNewSession =\n !context.hasInit || sessionId === undefined || sessionId !== context.sessionId;\n if (isNewSession) {\n context.pendingToolRows.length = 0;\n context.toolCallRows.clear();\n }\n context.hasInit = true;\n context.sessionId = sessionId ?? null;\n context.turn = isNewSession ? 1 : context.turn + 1;\n\n const label = isNewSession ? 'Session started' : `Turn ${context.turn} started`;\n const meta = [\n metaItem('session', isNewSession ? sessionId : null),\n metaItem('turn', isNewSession ? null : String(context.turn)),\n ...baseMeta,\n ].filter(isMeta);\n\n return lifecycleRow(timestamp, label, null, 'default', false, meta);\n}\n\nexport function authStatusRow(\n timestamp: number,\n message: Record<string, unknown>,\n): SessionViewLifecycleRow {\n const error = stringField(message, 'error');\n const output = stringList(field(message, 'output')).join('\\n');\n const isAuthenticating = booleanField(message, 'isAuthenticating');\n\n return lifecycleRow(\n timestamp,\n error\n ? 'Authentication failed'\n : isAuthenticating\n ? 'Authenticating'\n : 'Authentication complete',\n (error ?? output) || null,\n error ? 'error' : 'default',\n false,\n );\n}\n\nconst RATE_LIMIT_STATUS_MAPPINGS: Record<\n string,\n {label: string; tone: SessionViewLifecycleRow['tone']}\n> = {\n rejected: {label: 'Rate limit exceeded', tone: 'error'},\n allowed_warning: {label: 'Rate limit warning', tone: 'warning'},\n allowed: {label: 'Rate limit available', tone: 'default'},\n};\n\nexport function rateLimitRow(\n timestamp: number,\n message: Record<string, unknown>,\n): SessionViewLifecycleRow {\n const rateLimitInfo = asLooseObject(field(message, 'rate_limit_info')) ?? {};\n const status = stringField(rateLimitInfo, 'status');\n const rateLimitType = stringField(rateLimitInfo, 'rateLimitType');\n const utilization = numberField(rateLimitInfo, 'utilization');\n const mapping = status === undefined ? undefined : RATE_LIMIT_STATUS_MAPPINGS[status];\n const meta = [\n metaItem('utilization', utilization == null ? null : `${formatNumber(utilization * 100)}%`),\n mapping === undefined ? metaItem('status', status ?? null) : null,\n ].filter(isMeta);\n\n return lifecycleRow(\n timestamp,\n mapping?.label ?? 'Rate limit updated',\n rateLimitType == null ? null : humanizeEnumValue(rateLimitType),\n mapping?.tone ?? 'warning',\n false,\n meta,\n );\n}\n\nexport function toolUseSummary(\n message: Record<string, unknown>,\n context: ClaudeParseContext,\n): boolean {\n const summary = stringField(message, 'summary');\n if (summary === undefined) return false;\n\n const precedingToolUseIds = stringList(field(message, 'preceding_tool_use_ids'));\n const toolUseId = stringField(message, 'tool_use_id');\n const candidateIds =\n precedingToolUseIds.length > 0\n ? precedingToolUseIds\n : toolUseId === undefined\n ? []\n : [toolUseId];\n\n for (const id of [...candidateIds].reverse()) {\n const row = context.toolCallRows.get(id);\n if (row === undefined) continue;\n\n row.summary = row.summary === undefined ? summary : `${row.summary}\\n\\n${summary}`;\n return true;\n }\n\n return false;\n}\n\nexport function flushPendingToolRows(context: ClaudeParseContext): readonly SessionViewRow[] {\n if (context.pendingToolRows.length === 0) return [];\n\n const rows = context.pendingToolRows;\n context.pendingToolRows = [];\n context.toolCallRows.clear();\n return rows;\n}\n\nfunction titleCase(value: string): string {\n return value.length === 0 ? value : `${value[0]?.toUpperCase()}${value.slice(1)}`;\n}\n\nfunction humanizeEnumValue(value: string): string {\n return titleCase(value.replaceAll('_', ' '));\n}\n\nfunction stringList(value: unknown): string[] {\n if (!Array.isArray(value)) return [];\n\n return value.filter((item): item is string => typeof item === 'string' && item.length > 0);\n}\n\nexport function assistantRows(\n timestamp: number,\n message: Record<string, unknown>,\n context: ClaudeParseContext,\n): readonly SessionViewRow[] {\n const sdkMessage = asLooseObject(message.message) ?? message;\n const rows: SessionViewRow[] = [];\n const textParts: string[] = [];\n const thinkingParts: string[] = [];\n let queueRows = context.toolCallRows.size > 0;\n\n const pushRow = (row: SessionViewRow) => {\n if (queueRows) {\n context.pendingToolRows.push(row);\n } else {\n rows.push(row);\n }\n };\n\n const pushText = () => {\n if (textParts.length === 0) return;\n pushRow(messageRow(timestamp, 'assistant', 'assistant', textParts.join('\\n\\n'), false));\n textParts.length = 0;\n };\n const pushThinking = () => {\n if (thinkingParts.length === 0) return;\n pushRow(thinkingRow(timestamp, thinkingParts.join('\\n\\n')));\n thinkingParts.length = 0;\n };\n\n for (const block of contentBlocks(sdkMessage)) {\n const type = stringField(block, 'type');\n if (type === 'tool_use' || type === 'tool-use' || type === 'toolCall') {\n pushText();\n pushThinking();\n const row = toolCallRow(timestamp, block);\n if (row.id === null) {\n pushRow(row);\n } else {\n queueRows = true;\n context.pendingToolRows.push(row);\n context.toolCallRows.set(row.id, row);\n }\n continue;\n }\n\n if (type === 'thinking' || type === 'reasoning') {\n pushText();\n const text = blockText(block);\n if (text) thinkingParts.push(text);\n continue;\n }\n\n pushThinking();\n const text = blockText(block);\n if (text) textParts.push(text);\n }\n\n pushText();\n pushThinking();\n\n if (rows.length > 0 || queueRows) return rows;\n\n const text = stringField(sdkMessage, 'content') ?? stringField(message, 'result');\n return [messageRow(timestamp, 'assistant', 'assistant', text ?? toJson(message), false)];\n}\n\nexport function userRows(\n timestamp: number,\n message: Record<string, unknown>,\n context: ClaudeParseContext,\n): readonly SessionViewRow[] {\n const sdkMessage = asLooseObject(message.message) ?? message;\n const role = isPlatformMessage(sdkMessage) ? 'platform' : 'user';\n const rows: SessionViewRow[] = [];\n const textParts: string[] = [];\n const hadPendingToolCall = context.toolCallRows.size > 0;\n let matchedToolResult = false;\n const pushText = () => {\n if (textParts.length === 0) return;\n rows.push(messageRow(timestamp, role, role, textParts.join('\\n\\n'), false));\n textParts.length = 0;\n };\n\n for (const block of contentBlocks(sdkMessage)) {\n const type = stringField(block, 'type');\n if (type === 'tool_result' || type === 'tool-result') {\n pushText();\n const row = toolResultRow(timestamp, block);\n if (row.toolCallId !== null && context.toolCallRows.has(row.toolCallId)) {\n matchedToolResult = true;\n }\n rows.push(row);\n continue;\n }\n\n const text = blockText(block);\n if (text) textParts.push(text);\n }\n\n pushText();\n\n if (rows.length === 0) {\n const content = stringField(sdkMessage, 'content');\n rows.push(messageRow(timestamp, role, role, content ?? toJson(message), false));\n }\n\n if (hadPendingToolCall) {\n if (matchedToolResult) {\n context.pendingToolRows.push(...rows);\n return [];\n }\n return [...flushPendingToolRows(context), ...rows];\n }\n return rows;\n}\n\nexport function resultRow(\n timestamp: number,\n message: Record<string, unknown>,\n turn: number,\n isFinalResult: boolean,\n): SessionViewLifecycleRow {\n const isError = booleanField(message, 'is_error') || booleanField(message, 'isError');\n const subtype = stringField(message, 'subtype');\n const terminalFailure = isError || subtype === 'error';\n const detail =\n stringField(message, 'result') ??\n stringField(message, 'error') ??\n stringField(message, 'message') ??\n null;\n const meta = [\n metaItem('turn', !terminalFailure && !isFinalResult && turn > 0 ? String(turn) : null),\n numberMeta(message, 'duration_ms', 'duration', 'ms'),\n numberMeta(message, 'duration_api_ms', 'api duration', 'ms'),\n numberMeta(message, 'num_turns', 'turns'),\n costMeta(message),\n ].filter(isMeta);\n\n return lifecycleRow(\n timestamp,\n terminalFailure\n ? 'Session failed'\n : isFinalResult || turn === 0\n ? 'Session completed'\n : `Turn ${turn} completed`,\n detail,\n terminalFailure ? 'error' : 'default',\n terminalFailure,\n meta,\n );\n}\n\nfunction isPlatformMessage(message: Record<string, unknown>): boolean {\n const content = field(message, 'content');\n if (typeof content === 'string') return content.startsWith(OUTPUT_REPROMPT_PREFIX);\n if (!Array.isArray(content)) return false;\n\n return content.some((block) => {\n const object = asLooseObject(block);\n return stringField(object, 'text')?.startsWith(OUTPUT_REPROMPT_PREFIX) === true;\n });\n}\n\nfunction contentBlocks(message: Record<string, unknown>): Record<string, unknown>[] {\n const content = message.content;\n if (!Array.isArray(content)) return [];\n\n return content.flatMap((block) => {\n const object = asLooseObject(block);\n return object ? [object] : [];\n });\n}\n\nfunction toolCallRow(timestamp: number, block: Record<string, unknown>): SessionViewToolCallRow {\n return {\n kind: 'tool-call',\n timestamp,\n id: stringField(block, 'id') ?? null,\n name: stringField(block, 'name') ?? 'tool',\n input: stringifyValue(field(block, 'input') ?? {}),\n };\n}\n\nfunction toolResultRow(\n timestamp: number,\n block: Record<string, unknown>,\n): SessionViewToolResultRow {\n return {\n kind: 'tool-result',\n timestamp,\n toolCallId: stringField(block, 'tool_use_id') ?? stringField(block, 'toolUseId') ?? null,\n toolName: stringField(block, 'name') ?? 'tool',\n output: blockText(block) || stringifyValue(field(block, 'content') ?? ''),\n isError: booleanField(block, 'is_error') || booleanField(block, 'isError'),\n };\n}\n\nfunction blockText(block: Record<string, unknown>): string {\n const content = field(block, 'content');\n if (Array.isArray(content)) {\n return content\n .map((item) => {\n const object = asLooseObject(item);\n return object ? blockText(object) : typeof item === 'string' ? item : '';\n })\n .filter(Boolean)\n .join('\\n\\n');\n }\n\n return (\n stringField(block, 'text') ??\n stringField(block, 'thinking') ??\n (typeof content === 'string' ? content : '') ??\n ''\n );\n}\n\nfunction numberMeta(\n value: unknown,\n key: string,\n label: string,\n unit?: string,\n): SessionViewRowMeta | null {\n const raw = field(value, key);\n if (typeof raw !== 'number' || !Number.isFinite(raw)) return null;\n\n return metaItem(label, unit ? `${formatNumber(raw)} ${unit}` : formatNumber(raw));\n}\n\nfunction costMeta(message: Record<string, unknown>): SessionViewRowMeta | null {\n const value = field(message, 'total_cost_usd') ?? field(message, 'totalCostUsd');\n if (typeof value !== 'number' || !Number.isFinite(value)) return null;\n\n return metaItem('cost', `$${value.toFixed(value < 0.01 ? 4 : 2)}`);\n}\n"],"names":["asLooseObject","booleanField","field","formatNumber","isMeta","metaItem","numberField","stringField","stringifyValue","toJson","lifecycleRow","messageRow","thinkingRow","PURE_PROGRESS_CLAUDE_SYSTEM_SUBTYPES","Set","OUTPUT_REPROMPT_PREFIX","SYSTEM_EVENT_MAPPINGS","permission_denied","label","tone","detail","message","meta","filter","api_retry","attempt","maxRetries","numberMeta","informational","titleCase","compact_boundary","compactMetadata","hook_response","outcome","model_refusal_fallback","model_refusal_no_fallback","mirror_error","worker_shutting_down","elicitation_complete","notification","task_started","task_updated","task_notification","systemRow","timestamp","context","subtype","sessionId","isInit","type","baseMeta","mapping","undefined","isNewSession","hasInit","pendingToolRows","length","toolCallRows","clear","turn","String","authStatusRow","error","output","stringList","join","isAuthenticating","RATE_LIMIT_STATUS_MAPPINGS","rejected","allowed_warning","allowed","rateLimitRow","rateLimitInfo","status","rateLimitType","utilization","humanizeEnumValue","toolUseSummary","summary","precedingToolUseIds","toolUseId","candidateIds","id","reverse","row","get","flushPendingToolRows","rows","value","toUpperCase","slice","replaceAll","Array","isArray","item","assistantRows","sdkMessage","textParts","thinkingParts","queueRows","size","pushRow","push","pushText","pushThinking","block","contentBlocks","toolCallRow","set","text","blockText","userRows","role","isPlatformMessage","hadPendingToolCall","matchedToolResult","toolResultRow","toolCallId","has","content","resultRow","isFinalResult","isError","terminalFailure","costMeta","startsWith","some","object","flatMap","kind","name","input","toolName","map","Boolean","key","unit","raw","Number","isFinite","toFixed"],"mappings":"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"}
|
|
@@ -1,11 +1,13 @@
|
|
|
1
|
-
import type { SessionViewRow } from '@shipfox/api-logs-dto';
|
|
1
|
+
import type { SessionViewRow, SessionViewToolCallRow } from '@shipfox/api-logs-dto';
|
|
2
2
|
import type { AgentSessionRecord } from './session-record.js';
|
|
3
3
|
export interface ClaudeParseContext {
|
|
4
4
|
hasInit: boolean;
|
|
5
5
|
sessionId: string | null;
|
|
6
6
|
turn: number;
|
|
7
|
+
pendingToolRows: SessionViewRow[];
|
|
8
|
+
toolCallRows: Map<string, SessionViewToolCallRow>;
|
|
7
9
|
}
|
|
8
|
-
export declare function createClaudeParseContext(): ClaudeParseContext;
|
|
10
|
+
export declare function createClaudeParseContext(pendingToolRows?: readonly SessionViewRow[], state?: Pick<ClaudeParseContext, 'hasInit' | 'sessionId' | 'turn'>): ClaudeParseContext;
|
|
9
11
|
export declare function claudeInitSessionId(record: AgentSessionRecord): string | undefined;
|
|
10
12
|
export declare function parseClaudeSessionRecord(record: AgentSessionRecord, context?: ClaudeParseContext, isFinalResult?: boolean): readonly SessionViewRow[];
|
|
11
13
|
//# sourceMappingURL=claude-parser.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude-parser.d.ts","sourceRoot":"","sources":["../../../src/core/session/claude-parser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"claude-parser.d.ts","sourceRoot":"","sources":["../../../src/core/session/claude-parser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,cAAc,EAAE,sBAAsB,EAAC,MAAM,uBAAuB,CAAC;AAelF,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,qBAAqB,CAAC;AAQ5D,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,eAAe,EAAE,cAAc,EAAE,CAAC;IAClC,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,sBAAsB,CAAC,CAAC;CACnD;AAED,wBAAgB,wBAAwB,CACtC,eAAe,GAAE,SAAS,cAAc,EAAO,EAC/C,KAAK,GAAE,IAAI,CAAC,kBAAkB,EAAE,SAAS,GAAG,WAAW,GAAG,MAAM,CAI/D,GACA,kBAAkB,CAQpB;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,kBAAkB,GAAG,MAAM,GAAG,SAAS,CAoBlF;AAED,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,kBAAkB,EAC1B,OAAO,GAAE,kBAA+C,EACxD,aAAa,UAAO,GACnB,SAAS,cAAc,EAAE,CAwD3B"}
|
|
@@ -1,15 +1,26 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import { assistantRows, PURE_PROGRESS_CLAUDE_SYSTEM_SUBTYPES, resultRow, systemRow, userRows } from './claude/rows.js';
|
|
2
|
+
import { assistantRows, authStatusRow, flushPendingToolRows, PURE_PROGRESS_CLAUDE_SYSTEM_SUBTYPES, rateLimitRow, resultRow, systemRow, toolUseSummary, userRows } from './claude/rows.js';
|
|
3
3
|
import { stringField } from './object.js';
|
|
4
4
|
import { rawRecordRow } from './rows.js';
|
|
5
5
|
const claudeMessageSchema = z.object({
|
|
6
6
|
type: z.string().min(1)
|
|
7
7
|
}).catchall(z.unknown());
|
|
8
|
-
export function createClaudeParseContext(
|
|
8
|
+
export function createClaudeParseContext(pendingToolRows = [], state = {
|
|
9
|
+
hasInit: false,
|
|
10
|
+
sessionId: null,
|
|
11
|
+
turn: 0
|
|
12
|
+
}) {
|
|
13
|
+
const rows = [
|
|
14
|
+
...pendingToolRows
|
|
15
|
+
];
|
|
16
|
+
const toolCallRows = new Map();
|
|
17
|
+
for (const row of rows){
|
|
18
|
+
if (row.kind === 'tool-call' && row.id !== null) toolCallRows.set(row.id, row);
|
|
19
|
+
}
|
|
9
20
|
return {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
21
|
+
...state,
|
|
22
|
+
pendingToolRows: rows,
|
|
23
|
+
toolCallRows
|
|
13
24
|
};
|
|
14
25
|
}
|
|
15
26
|
export function claudeInitSessionId(record) {
|
|
@@ -33,36 +44,71 @@ export function parseClaudeSessionRecord(record, context = createClaudeParseCont
|
|
|
33
44
|
json = JSON.parse(record.data);
|
|
34
45
|
} catch {
|
|
35
46
|
return [
|
|
47
|
+
...flushPendingToolRows(context),
|
|
36
48
|
rawRecordRow(record, 'Malformed session entry')
|
|
37
49
|
];
|
|
38
50
|
}
|
|
39
51
|
const parsed = claudeMessageSchema.safeParse(json);
|
|
40
|
-
if (!parsed.success)
|
|
41
|
-
|
|
42
|
-
|
|
52
|
+
if (!parsed.success) {
|
|
53
|
+
return [
|
|
54
|
+
...flushPendingToolRows(context),
|
|
55
|
+
rawRecordRow(record, 'Unsupported Claude message')
|
|
56
|
+
];
|
|
57
|
+
}
|
|
43
58
|
const message = parsed.data;
|
|
44
59
|
if (message.type === 'system' && typeof message.subtype === 'string' && PURE_PROGRESS_CLAUDE_SYSTEM_SUBTYPES.has(message.subtype)) {
|
|
45
60
|
return [];
|
|
46
61
|
}
|
|
47
62
|
switch(message.type){
|
|
48
63
|
case 'system':
|
|
64
|
+
if (stringField(message, 'subtype') === 'init') {
|
|
65
|
+
return [
|
|
66
|
+
...flushPendingToolRows(context),
|
|
67
|
+
systemRow(record.ts, message, context)
|
|
68
|
+
];
|
|
69
|
+
}
|
|
70
|
+
return deferRow(context, systemRow(record.ts, message, context));
|
|
49
71
|
case 'init':
|
|
50
72
|
return [
|
|
73
|
+
...flushPendingToolRows(context),
|
|
51
74
|
systemRow(record.ts, message, context)
|
|
52
75
|
];
|
|
76
|
+
case 'tool_progress':
|
|
77
|
+
case 'prompt_suggestion':
|
|
78
|
+
// These messages describe an already-emitted tool call or an interactive client state.
|
|
79
|
+
// They have no standalone row representation and must not look like parser failures.
|
|
80
|
+
return [];
|
|
81
|
+
case 'tool_use_summary':
|
|
82
|
+
return toolUseSummary(message, context) ? flushPendingToolRows(context) : [];
|
|
83
|
+
case 'auth_status':
|
|
84
|
+
return deferRow(context, authStatusRow(record.ts, message));
|
|
85
|
+
case 'rate_limit_event':
|
|
86
|
+
return deferRow(context, rateLimitRow(record.ts, message));
|
|
53
87
|
case 'assistant':
|
|
54
|
-
return
|
|
88
|
+
return [
|
|
89
|
+
...flushPendingToolRows(context),
|
|
90
|
+
...assistantRows(record.ts, message, context)
|
|
91
|
+
];
|
|
55
92
|
case 'user':
|
|
56
|
-
return userRows(record.ts, message);
|
|
93
|
+
return userRows(record.ts, message, context);
|
|
57
94
|
case 'result':
|
|
58
95
|
return [
|
|
96
|
+
...flushPendingToolRows(context),
|
|
59
97
|
resultRow(record.ts, message, context.turn, isFinalResult)
|
|
60
98
|
];
|
|
61
99
|
default:
|
|
62
100
|
return [
|
|
101
|
+
...flushPendingToolRows(context),
|
|
63
102
|
rawRecordRow(record, `Unknown Claude message: ${message.type}`)
|
|
64
103
|
];
|
|
65
104
|
}
|
|
66
105
|
}
|
|
106
|
+
function deferRow(context, row) {
|
|
107
|
+
if (context.toolCallRows.size === 0) return [
|
|
108
|
+
row
|
|
109
|
+
];
|
|
110
|
+
context.pendingToolRows.push(row);
|
|
111
|
+
return [];
|
|
112
|
+
}
|
|
67
113
|
|
|
68
114
|
//# sourceMappingURL=claude-parser.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/core/session/claude-parser.ts"],"sourcesContent":["import type {SessionViewRow} from '@shipfox/api-logs-dto';\nimport {z} from 'zod';\nimport {\n assistantRows,\n PURE_PROGRESS_CLAUDE_SYSTEM_SUBTYPES,\n resultRow,\n systemRow,\n userRows,\n} from './claude/rows.js';\nimport {stringField} from './object.js';\nimport {rawRecordRow} from './rows.js';\nimport type {AgentSessionRecord} from './session-record.js';\n\nconst claudeMessageSchema = z\n .object({\n type: z.string().min(1),\n })\n .catchall(z.unknown());\n\nexport interface ClaudeParseContext {\n hasInit: boolean;\n sessionId: string | null;\n turn: number;\n}\n\nexport function createClaudeParseContext(
|
|
1
|
+
{"version":3,"sources":["../../../src/core/session/claude-parser.ts"],"sourcesContent":["import type {SessionViewRow, SessionViewToolCallRow} from '@shipfox/api-logs-dto';\nimport {z} from 'zod';\nimport {\n assistantRows,\n authStatusRow,\n flushPendingToolRows,\n PURE_PROGRESS_CLAUDE_SYSTEM_SUBTYPES,\n rateLimitRow,\n resultRow,\n systemRow,\n toolUseSummary,\n userRows,\n} from './claude/rows.js';\nimport {stringField} from './object.js';\nimport {rawRecordRow} from './rows.js';\nimport type {AgentSessionRecord} from './session-record.js';\n\nconst claudeMessageSchema = z\n .object({\n type: z.string().min(1),\n })\n .catchall(z.unknown());\n\nexport interface ClaudeParseContext {\n hasInit: boolean;\n sessionId: string | null;\n turn: number;\n pendingToolRows: SessionViewRow[];\n toolCallRows: Map<string, SessionViewToolCallRow>;\n}\n\nexport function createClaudeParseContext(\n pendingToolRows: readonly SessionViewRow[] = [],\n state: Pick<ClaudeParseContext, 'hasInit' | 'sessionId' | 'turn'> = {\n hasInit: false,\n sessionId: null,\n turn: 0,\n },\n): ClaudeParseContext {\n const rows = [...pendingToolRows];\n const toolCallRows = new Map<string, SessionViewToolCallRow>();\n for (const row of rows) {\n if (row.kind === 'tool-call' && row.id !== null) toolCallRows.set(row.id, row);\n }\n\n return {...state, pendingToolRows: rows, toolCallRows};\n}\n\nexport function claudeInitSessionId(record: AgentSessionRecord): string | undefined {\n let json: unknown;\n try {\n json = JSON.parse(record.data);\n } catch {\n return undefined;\n }\n\n const parsed = claudeMessageSchema.safeParse(json);\n if (!parsed.success) return undefined;\n\n const message = parsed.data;\n if (\n message.type !== 'init' &&\n !(message.type === 'system' && stringField(message, 'subtype') === 'init')\n ) {\n return undefined;\n }\n\n return stringField(message, 'session_id') ?? stringField(message, 'sessionId');\n}\n\nexport function parseClaudeSessionRecord(\n record: AgentSessionRecord,\n context: ClaudeParseContext = createClaudeParseContext(),\n isFinalResult = true,\n): readonly SessionViewRow[] {\n let json: unknown;\n try {\n json = JSON.parse(record.data);\n } catch {\n return [...flushPendingToolRows(context), rawRecordRow(record, 'Malformed session entry')];\n }\n\n const parsed = claudeMessageSchema.safeParse(json);\n if (!parsed.success) {\n return [...flushPendingToolRows(context), rawRecordRow(record, 'Unsupported Claude message')];\n }\n\n const message = parsed.data;\n if (\n message.type === 'system' &&\n typeof message.subtype === 'string' &&\n PURE_PROGRESS_CLAUDE_SYSTEM_SUBTYPES.has(message.subtype)\n ) {\n return [];\n }\n\n switch (message.type) {\n case 'system':\n if (stringField(message, 'subtype') === 'init') {\n return [...flushPendingToolRows(context), systemRow(record.ts, message, context)];\n }\n return deferRow(context, systemRow(record.ts, message, context));\n case 'init':\n return [...flushPendingToolRows(context), systemRow(record.ts, message, context)];\n case 'tool_progress':\n case 'prompt_suggestion':\n // These messages describe an already-emitted tool call or an interactive client state.\n // They have no standalone row representation and must not look like parser failures.\n return [];\n case 'tool_use_summary':\n return toolUseSummary(message, context) ? flushPendingToolRows(context) : [];\n case 'auth_status':\n return deferRow(context, authStatusRow(record.ts, message));\n case 'rate_limit_event':\n return deferRow(context, rateLimitRow(record.ts, message));\n case 'assistant':\n return [...flushPendingToolRows(context), ...assistantRows(record.ts, message, context)];\n case 'user':\n return userRows(record.ts, message, context);\n case 'result':\n return [\n ...flushPendingToolRows(context),\n resultRow(record.ts, message, context.turn, isFinalResult),\n ];\n default:\n return [\n ...flushPendingToolRows(context),\n rawRecordRow(record, `Unknown Claude message: ${message.type}`),\n ];\n }\n}\n\nfunction deferRow(context: ClaudeParseContext, row: SessionViewRow): readonly SessionViewRow[] {\n if (context.toolCallRows.size === 0) return [row];\n\n context.pendingToolRows.push(row);\n return [];\n}\n"],"names":["z","assistantRows","authStatusRow","flushPendingToolRows","PURE_PROGRESS_CLAUDE_SYSTEM_SUBTYPES","rateLimitRow","resultRow","systemRow","toolUseSummary","userRows","stringField","rawRecordRow","claudeMessageSchema","object","type","string","min","catchall","unknown","createClaudeParseContext","pendingToolRows","state","hasInit","sessionId","turn","rows","toolCallRows","Map","row","kind","id","set","claudeInitSessionId","record","json","JSON","parse","data","undefined","parsed","safeParse","success","message","parseClaudeSessionRecord","context","isFinalResult","subtype","has","ts","deferRow","size","push"],"mappings":"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"}
|