(line: string)
| 420 | } |
| 421 | |
| 422 | function parseLargeJsonlLine(line: string): JournalEntry | null { |
| 423 | const rootEnd = findJsonContainerEnd(line, 0, 0x7b, 0x7d) |
| 424 | if (rootEnd === -1) return null |
| 425 | const rootStart = 0 |
| 426 | const rootLimit = rootEnd + 1 |
| 427 | const type = readJsonString(line, findObjectFieldValue(line, rootStart, rootLimit, 'type')) |
| 428 | if (!type) return null |
| 429 | |
| 430 | const entry: JournalEntry = { type } |
| 431 | const timestamp = readJsonString(line, findObjectFieldValue(line, rootStart, rootLimit, 'timestamp')) |
| 432 | const sessionId = readJsonString(line, findObjectFieldValue(line, rootStart, rootLimit, 'sessionId')) |
| 433 | const cwd = readJsonString(line, findObjectFieldValue(line, rootStart, rootLimit, 'cwd')) |
| 434 | if (timestamp !== undefined) entry.timestamp = timestamp |
| 435 | if (sessionId !== undefined) entry.sessionId = sessionId |
| 436 | if (cwd !== undefined) entry.cwd = cwd |
| 437 | const addedNames = extractLargeAddedNames(line, findObjectFieldValue(line, rootStart, rootLimit, 'attachment')) |
| 438 | if (addedNames.length > 0) { |
| 439 | ;(entry as Record<string, unknown>)['attachment'] = { type: 'deferred_tools_delta', addedNames } |
| 440 | } |
| 441 | |
| 442 | if (type === 'user') { |
| 443 | const message = findObjectFieldValue(line, rootStart, rootLimit, 'message') |
| 444 | if (message?.kind === 'object') { |
| 445 | const content = findObjectFieldValue(line, message.start, message.end, 'content') |
| 446 | const text = extractLargeUserText(line, content) |
| 447 | if (text !== undefined) entry.message = { role: 'user', content: text } |
| 448 | } |
| 449 | return entry |
| 450 | } |
| 451 | |
| 452 | if (type !== 'assistant') return entry |
| 453 | const message = findObjectFieldValue(line, rootStart, rootLimit, 'message') |
| 454 | if (message?.kind !== 'object') return entry |
| 455 | const model = readJsonString(line, findObjectFieldValue(line, message.start, message.end, 'model')) |
| 456 | const usageBounds = findObjectFieldValue(line, message.start, message.end, 'usage') |
| 457 | if (!model || usageBounds?.kind !== 'object') return entry |
| 458 | const id = readJsonString(line, findObjectFieldValue(line, message.start, message.end, 'id')) |
| 459 | const contentBounds = findObjectFieldValue(line, message.start, message.end, 'content') |
| 460 | |
| 461 | entry.message = { |
| 462 | type: 'message', |
| 463 | role: 'assistant', |
| 464 | model, |
| 465 | ...(id !== undefined ? { id } : {}), |
| 466 | content: extractLargeToolBlocks(line, contentBounds), |
| 467 | usage: parseLargeUsage(line, usageBounds), |
| 468 | } |
| 469 | |
| 470 | return entry |
| 471 | } |
| 472 | |
| 473 | type BufferJsonValueBounds = { |
| 474 | start: number |
no test coverage detected