codesesh 1.0.8 → 1.0.10
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/README.md +19 -0
- package/dist/{chunk-YLXHGL4S.js → chunk-2LXZFMSH.js} +28 -2
- package/dist/{chunk-YLXHGL4S.js.map → chunk-2LXZFMSH.js.map} +1 -1
- package/dist/{chunk-L4G3LE7I.js → chunk-543OWZIC.js} +2 -2
- package/dist/{chunk-DHQPM5FF.js → chunk-56FKVL5K.js} +5 -5
- package/dist/{chunk-V3HKVTIO.js → chunk-CYZ6OC6J.js} +2 -2
- package/dist/{chunk-KVTLNX7V.js → chunk-DWY4HWVI.js} +2 -2
- package/dist/{chunk-AGUAXTKC.js → chunk-R6QKSHPH.js} +2 -2
- package/dist/{chunk-RBCCNCDO.js → chunk-WRVILHZR.js} +1059 -26
- package/dist/chunk-WRVILHZR.js.map +1 -0
- package/dist/{discovery-KEZQU6RL.js → discovery-NTMSA6UE.js} +5 -5
- package/dist/index.js +36 -9
- package/dist/index.js.map +1 -1
- package/dist/project-identity-worker.js +4 -4
- package/dist/scan-refresh-worker.js +6 -6
- package/dist/search-index-worker.js +6 -6
- package/dist/session-detail-worker.js +6 -6
- package/dist/smart-tag-worker.js +3 -3
- package/dist/web/assets/CustomTimeWindowDialog-CGPvUFkc.js +1 -0
- package/dist/web/assets/DetailLanding-D1FLK4EW.js +1 -0
- package/dist/web/assets/{InteractiveReceipt-Bsj37HtN.js → InteractiveReceipt-C7FJhzdv.js} +1 -1
- package/dist/web/assets/OverviewScreen-DX7F_6dH.js +1 -0
- package/dist/web/assets/{PrismHighlighter-DWS6Nx_X.js → PrismHighlighter-DZ2CWVc0.js} +1 -1
- package/dist/web/assets/Projects-B_7w5TDw.js +1 -0
- package/dist/web/assets/{SearchResultsPanel-BAManMmt.js → SearchResultsPanel-BMBhKuPS.js} +1 -1
- package/dist/web/assets/SessionDetail-wJYzzF0i.js +53 -0
- package/dist/web/assets/index-BXhaumu7.css +1 -0
- package/dist/web/assets/index-DUcpWdzX.js +1423 -0
- package/dist/web/assets/{panel-DcOuALYX.js → panel-B-5dVddJ.js} +1 -1
- package/dist/web/assets/session-indexes-3LjxBYNe.js +4 -0
- package/dist/web/assets/utils-BuYa9y6l.js +1 -0
- package/dist/web/icon/agent/cherrystudio.svg +7 -0
- package/dist/web/icon/agent/deepchat.LICENSE.txt +206 -0
- package/dist/web/icon/agent/deepchat.svg +6 -0
- package/dist/web/icon/agent/minimax-code.svg +1 -0
- package/dist/web/index.html +5 -192
- package/package.json +3 -3
- package/dist/chunk-RBCCNCDO.js.map +0 -1
- package/dist/web/assets/CustomTimeWindowDialog-z5xtqkBF.js +0 -1
- package/dist/web/assets/DetailLanding-CpV0jLmT.js +0 -1
- package/dist/web/assets/OverviewScreen-B9qZqEQA.js +0 -1
- package/dist/web/assets/Projects-oY3KCgS4.js +0 -1
- package/dist/web/assets/SessionDetail-KSgkmLV7.js +0 -53
- package/dist/web/assets/index-BSLHxV0w.css +0 -1
- package/dist/web/assets/index-DNw59Qsn.js +0 -1423
- package/dist/web/assets/session-indexes-DKukxoe1.js +0 -4
- package/dist/web/assets/utils-Dk_44zMo.js +0 -1
- /package/dist/{chunk-L4G3LE7I.js.map → chunk-543OWZIC.js.map} +0 -0
- /package/dist/{chunk-DHQPM5FF.js.map → chunk-56FKVL5K.js.map} +0 -0
- /package/dist/{chunk-V3HKVTIO.js.map → chunk-CYZ6OC6J.js.map} +0 -0
- /package/dist/{chunk-KVTLNX7V.js.map → chunk-DWY4HWVI.js.map} +0 -0
- /package/dist/{chunk-AGUAXTKC.js.map → chunk-R6QKSHPH.js.map} +0 -0
- /package/dist/{discovery-KEZQU6RL.js.map → discovery-NTMSA6UE.js.map} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../core/src/agents/session-source-synchronization.ts","../../core/src/agents/base.ts","../../core/src/agents/claudecode.ts","../../core/src/discovery/paths.ts","../../core/src/utils/timestamp.ts","../../core/src/agents/claudecode-record-converter.ts","../../core/src/agents/transcript-builder.ts","../../core/src/agents/opencode.ts","../../core/src/agents/opencode-sqlite.ts","../../core/src/agents/kimi.ts","../../core/src/agents/tool-arguments.ts","../../core/src/agents/kimi-code.ts","../../core/src/agents/codex.ts","../../core/src/agents/codex-exec-decode.ts","../../core/src/agents/codex-record-converter.ts","../../core/src/agents/codex-token-usage.ts","../../core/src/agents/cursor.ts","../../core/src/agents/cursor-records.ts","../../core/src/agents/pi.ts","../../core/src/agents/zcode.ts","../../core/src/agents/grok.ts","../../core/src/agents/dsh.ts","../../core/src/agents/dsh-session-log.ts","../../core/src/agents/dsh-transcript.ts","../../core/src/agents/register.ts","../../core/src/agents/registry.ts"],"sourcesContent":["import { statSync } from \"node:fs\";\nimport type { SessionSnapshotCompleteness } from \"../discovery/cache/snapshot-types.js\";\nimport { PRICING_CAPTURE_EPOCH, pricingBecameAvailable } from \"../pricing/cost.js\";\nimport type { SessionHead } from \"../types/index.js\";\nimport { getCoreDiagnostics } from \"../utils/diagnostics.js\";\nimport type {\n AgentScanOptions,\n SessionCacheMeta,\n SessionCacheMetaSnapshot,\n SessionSourceAbsenceOutcome,\n SessionSourceDiff,\n SessionSourceFailure,\n SessionSourceOutcome,\n SessionSourceRef,\n} from \"./session-source-types.js\";\n\ninterface SessionSourceSynchronizationAdapter {\n readonly name: string;\n listSessionSources(options?: AgentScanOptions): SessionSourceRef[];\n scanSessionSourceOutcome(\n source: SessionSourceRef,\n options?: AgentScanOptions,\n ): SessionSourceOutcome;\n expandChangedSessionIds(changedIds: string[], refs?: SessionSourceRef[]): string[];\n filterCachedSessions(sessions: SessionHead[]): SessionHead[];\n getSessionCacheMeta(sessionId: string): SessionCacheMeta | undefined;\n snapshotSessionCacheMeta(sessionIds?: ReadonlySet<string>): Record<string, SessionCacheMeta>;\n restoreSessionCacheMeta(meta: SessionCacheMetaSnapshot): void;\n removeSessionCacheMeta(sessionIds: Iterable<string>): void;\n}\n\nexport interface SessionSourceSynchronizationBaseline {\n sessions: SessionHead[];\n meta: SessionCacheMetaSnapshot;\n}\n\nexport type SessionSourceSynchronizationRequest =\n | { kind: \"inspect\"; scanOptions?: AgentScanOptions }\n | { kind: \"refresh\"; scanOptions?: AgentScanOptions }\n | { kind: \"reload\"; scanOptions?: AgentScanOptions }\n | {\n kind: \"known-changes\";\n changedIds: string[];\n refs?: SessionSourceRef[];\n scanOptions?: AgentScanOptions;\n };\n\nexport interface SessionSourceSynchronizationOutcome {\n sessions: SessionHead[];\n meta: Record<string, SessionCacheMeta>;\n sources: SessionSourceRef[];\n sourceOutcomes: SessionSourceOutcome[];\n detectedSessionIds: string[];\n changedSessionIds: string[];\n explicitRemovedSessionIds: string[];\n finalizeSessionIds: string[];\n sourceFailures: SessionSourceFailure[];\n completeness: SessionSnapshotCompleteness;\n sourceCount: number;\n removedSourceCount: number;\n timing: SessionSourceSynchronizationTiming;\n}\n\nexport interface SessionSourceSynchronizationTiming {\n totalMs: number;\n enumerationMs: number;\n diffMs: number;\n parseMs: number;\n enumeratedSourceCount: number;\n changedSourceCount: number;\n processedSourceCount: number;\n}\n\n/** Parser/index revisions live inside the fingerprint, so comparison must be exact. */\nfunction fingerprintMatches(ref: SessionSourceRef, cached: SessionCacheMeta | undefined): boolean {\n return (\n typeof cached?.sourceFingerprint === \"string\" && cached.sourceFingerprint === ref.fingerprint\n );\n}\n\n/** Unknown or out-of-window mtime cannot prove deletion; retain last-known-good facts. */\nfunction wasEnumeratedThisPass(\n cached: SessionCacheMeta | undefined,\n options: AgentScanOptions | undefined,\n): boolean {\n if (options?.from == null && options?.to == null) return true;\n const mtimeMs = cached?.sourceMtimeMs;\n return typeof mtimeMs === \"number\" && matchesScanWindow(mtimeMs, options);\n}\n\nexport function matchesScanWindow(activityTime: number, options?: AgentScanOptions): boolean {\n if (options?.from != null && activityTime < options.from) return false;\n if (options?.to != null && activityTime > options.to) return false;\n return true;\n}\n\nexport function isMissingSessionSourceError(error: unknown): boolean {\n if (typeof error !== \"object\" || error === null || !(\"code\" in error)) return false;\n const code = (error as { code?: unknown }).code;\n return code === \"ENOENT\" || code === \"ENOTDIR\";\n}\n\nconst FAILURE_MESSAGE_LIMIT = 500;\n\nfunction failureClass(error: unknown): string {\n if (typeof error === \"object\" && error !== null && \"code\" in error) {\n const code = (error as { code?: unknown }).code;\n if (typeof code === \"string\" && code) return code;\n }\n if (error instanceof Error && error.name) return error.name;\n return typeof error;\n}\n\nfunction failureMessage(error: unknown): string {\n const message = error instanceof Error ? error.message : String(error);\n return message.slice(0, FAILURE_MESSAGE_LIMIT);\n}\n\nexport function describeFailure(error: unknown) {\n return {\n errorClass: failureClass(error),\n message: failureMessage(error),\n };\n}\n\nexport function createSessionSourceFailure(\n source: Pick<SessionSourceRef, \"sessionId\" | \"sourcePath\">,\n stage: SessionSourceFailure[\"stage\"],\n error: unknown,\n): SessionSourceFailure {\n return {\n sessionId: source.sessionId,\n sourcePath: source.sourcePath,\n stage,\n ...describeFailure(error),\n };\n}\n\nexport function reportSessionSourceOutcome(agentName: string, outcome: SessionSourceOutcome): void {\n if (outcome.status === \"parsed\") return;\n if (outcome.status === \"filtered\") {\n getCoreDiagnostics()?.info?.(\"agent.session_source_outcome\", {\n agent: agentName,\n session_id: outcome.source.sessionId,\n source_path: outcome.source.sourcePath,\n outcome: outcome.status,\n reason: outcome.reason,\n });\n return;\n }\n if (outcome.status === \"missing\") {\n getCoreDiagnostics()?.info?.(\"agent.session_source_outcome\", {\n agent: agentName,\n session_id: outcome.source.sessionId,\n source_path: outcome.source.sourcePath,\n outcome: outcome.status,\n });\n return;\n }\n getCoreDiagnostics()?.warn(\"agent.session_source_outcome\", {\n agent: agentName,\n session_id: outcome.failure.sessionId,\n source_path: outcome.failure.sourcePath,\n outcome: outcome.status,\n stage: outcome.failure.stage,\n error_class: outcome.failure.errorClass,\n message: outcome.failure.message,\n });\n}\n\nexport function diffSessionSources(\n refs: SessionSourceRef[],\n cachedSessions: SessionHead[],\n cachedMeta: SessionCacheMetaSnapshot,\n options?: AgentScanOptions,\n): SessionSourceDiff {\n const cachedIds = new Set(cachedSessions.map((session) => session.reference.sessionId));\n const enumeratedIds = new Set<string>();\n const changedIds: string[] = [];\n\n for (const ref of refs) {\n enumeratedIds.add(ref.sessionId);\n const meta = cachedMeta[ref.sessionId];\n const unchanged =\n cachedIds.has(ref.sessionId) &&\n meta?.sourcePath === ref.sourcePath &&\n fingerprintMatches(ref, meta) &&\n meta.pricingCaptureEpoch === PRICING_CAPTURE_EPOCH &&\n !pricingBecameAvailable(meta.unpricedModels);\n if (!unchanged) changedIds.push(ref.sessionId);\n }\n\n const removedIds: string[] = [];\n const failedIds: string[] = [];\n const sourceOutcomes: SessionSourceAbsenceOutcome[] = [];\n for (const session of cachedSessions) {\n const sessionId = session.reference.sessionId;\n if (enumeratedIds.has(sessionId)) continue;\n const meta = cachedMeta[sessionId];\n if (!wasEnumeratedThisPass(meta, options)) continue;\n const source = {\n sessionId,\n sourcePath: typeof meta?.sourcePath === \"string\" ? meta.sourcePath : \"\",\n fingerprint: typeof meta?.sourceFingerprint === \"string\" ? meta.sourceFingerprint : \"\",\n };\n if (!source.sourcePath) {\n // No path can ever be re-checked, so keeping this entry would fail on\n // every future pass; a complete enumeration finding neither file nor\n // path proves the entry is unrecoverable.\n removedIds.push(sessionId);\n sourceOutcomes.push({ status: \"missing\", source });\n continue;\n }\n try {\n statSync(source.sourcePath);\n failedIds.push(sessionId);\n sourceOutcomes.push({\n status: \"failed\",\n failure: createSessionSourceFailure(\n source,\n \"enumeration\",\n new Error(\"cached source was not enumerated\"),\n ),\n });\n } catch (error) {\n if (!isMissingSessionSourceError(error)) {\n failedIds.push(sessionId);\n sourceOutcomes.push({\n status: \"failed\",\n failure: createSessionSourceFailure(source, \"enumeration\", error),\n });\n continue;\n }\n removedIds.push(sessionId);\n sourceOutcomes.push({ status: \"missing\", source });\n }\n }\n\n return { changedIds, removedIds, failedIds, sourceOutcomes };\n}\n\nfunction unique(values: Iterable<string>): string[] {\n return [...new Set(values)];\n}\n\nfunction sourceForMissingId(\n sessionId: string,\n cached: SessionCacheMeta | undefined,\n): SessionSourceRef {\n return {\n sessionId,\n sourcePath: typeof cached?.sourcePath === \"string\" ? cached.sourcePath : \"\",\n fingerprint: typeof cached?.sourceFingerprint === \"string\" ? cached.sourceFingerprint : \"\",\n };\n}\n\nfunction isWindowed(options: AgentScanOptions | undefined): boolean {\n return options?.from != null || options?.to != null;\n}\n\nexport function synchronizeSessionSources(\n adapter: SessionSourceSynchronizationAdapter,\n baseline: SessionSourceSynchronizationBaseline,\n request: SessionSourceSynchronizationRequest,\n): SessionSourceSynchronizationOutcome {\n const startedAt = performance.now();\n adapter.restoreSessionCacheMeta(baseline.meta);\n const baselineMeta = adapter.snapshotSessionCacheMeta();\n const baselineSessions = adapter.filterCachedSessions(baseline.sessions);\n const visibleBaselineIds = new Set(\n baselineSessions.map((session) => session.reference.sessionId),\n );\n const filteredBaselineIds = baseline.sessions\n .map((session) => session.reference.sessionId)\n .filter((sessionId) => !visibleBaselineIds.has(sessionId));\n const filteredBaselineOutcomes: SessionSourceOutcome[] = filteredBaselineIds.map((sessionId) => ({\n status: \"filtered\",\n source: sourceForMissingId(sessionId, baselineMeta[sessionId]),\n reason: \"cached session rejected by adapter\",\n }));\n adapter.removeSessionCacheMeta(filteredBaselineIds);\n const scanOptions = request.scanOptions;\n const suppliedSources = request.kind === \"known-changes\" ? request.refs : undefined;\n const enumerationStartedAt = performance.now();\n const sources = suppliedSources ?? adapter.listSessionSources(scanOptions);\n const enumerationMs = suppliedSources ? 0 : performance.now() - enumerationStartedAt;\n const sourceById = new Map(sources.map((source) => [source.sessionId, source]));\n const diffStartedAt = performance.now();\n const diff =\n request.kind === \"known-changes\"\n ? { changedIds: request.changedIds, removedIds: [], failedIds: [], sourceOutcomes: [] }\n : diffSessionSources(\n sources,\n baselineSessions,\n adapter.snapshotSessionCacheMeta(),\n scanOptions,\n );\n const diffMs = performance.now() - diffStartedAt;\n const detectedSessionIds = unique([\n ...filteredBaselineIds,\n ...diff.changedIds,\n ...diff.removedIds,\n ]);\n const sourceOutcomes: SessionSourceOutcome[] = [\n ...filteredBaselineOutcomes,\n ...diff.sourceOutcomes,\n ];\n const sourceFailures = sourceOutcomes.flatMap((outcome) =>\n outcome.status === \"failed\" ? [outcome.failure] : [],\n );\n for (const outcome of sourceOutcomes) reportSessionSourceOutcome(adapter.name, outcome);\n\n if (request.kind === \"inspect\") {\n return {\n sessions: baselineSessions,\n meta: adapter.snapshotSessionCacheMeta(visibleBaselineIds),\n sources,\n sourceOutcomes,\n detectedSessionIds,\n changedSessionIds: [],\n explicitRemovedSessionIds: unique([...filteredBaselineIds, ...diff.removedIds]),\n finalizeSessionIds: [],\n sourceFailures,\n completeness: isWindowed(scanOptions) || sourceFailures.length > 0 ? \"partial\" : \"complete\",\n sourceCount: sources.length,\n removedSourceCount: diff.removedIds.length,\n timing: {\n totalMs: performance.now() - startedAt,\n enumerationMs,\n diffMs,\n parseMs: 0,\n enumeratedSourceCount: sources.length,\n changedSourceCount: diff.changedIds.length,\n processedSourceCount: 0,\n },\n };\n }\n\n const sessionsById = new Map(\n baselineSessions.map((session) => [session.reference.sessionId, session]),\n );\n const changedSessionIds = new Set(filteredBaselineIds);\n const explicitRemovedSessionIds = new Set(filteredBaselineIds);\n for (const outcome of diff.sourceOutcomes) {\n if (outcome.status !== \"missing\") continue;\n sessionsById.delete(outcome.source.sessionId);\n adapter.removeSessionCacheMeta([outcome.source.sessionId]);\n changedSessionIds.add(outcome.source.sessionId);\n explicitRemovedSessionIds.add(outcome.source.sessionId);\n }\n\n const requestedIds =\n request.kind === \"reload\"\n ? sources.map((source) => source.sessionId)\n : request.kind === \"known-changes\"\n ? request.changedIds\n : detectedSessionIds;\n const synchronizationIds = unique(adapter.expandChangedSessionIds(requestedIds, sources));\n if (synchronizationIds.length > 0 || request.kind === \"reload\") {\n scanOptions?.onProgress?.({\n total: synchronizationIds.length,\n processed: 0,\n sessions: sessionsById.size,\n });\n }\n\n const parseStartedAt = performance.now();\n synchronizationIds.forEach((sessionId, index) => {\n const source = sourceById.get(sessionId);\n if (!source) {\n if (!changedSessionIds.has(sessionId)) {\n const missing: SessionSourceOutcome = {\n status: \"missing\",\n source: sourceForMissingId(sessionId, adapter.getSessionCacheMeta(sessionId)),\n };\n sourceOutcomes.push(missing);\n reportSessionSourceOutcome(adapter.name, missing);\n sessionsById.delete(sessionId);\n adapter.removeSessionCacheMeta([sessionId]);\n changedSessionIds.add(sessionId);\n explicitRemovedSessionIds.add(sessionId);\n }\n } else {\n const outcome = adapter.scanSessionSourceOutcome(source, scanOptions);\n sourceOutcomes.push(outcome);\n if (outcome.status === \"parsed\") {\n const parsedSessionId = outcome.session.reference.sessionId;\n if (parsedSessionId !== source.sessionId) sessionsById.delete(source.sessionId);\n sessionsById.set(parsedSessionId, outcome.session);\n if (parsedSessionId !== source.sessionId)\n adapter.removeSessionCacheMeta([source.sessionId]);\n if (parsedSessionId === source.sessionId)\n explicitRemovedSessionIds.delete(source.sessionId);\n changedSessionIds.add(source.sessionId);\n } else if (outcome.status === \"filtered\" || outcome.status === \"missing\") {\n sessionsById.delete(source.sessionId);\n adapter.removeSessionCacheMeta([source.sessionId]);\n changedSessionIds.add(source.sessionId);\n explicitRemovedSessionIds.add(source.sessionId);\n reportSessionSourceOutcome(adapter.name, outcome);\n } else {\n // \"last-known-good data retained\" is only a failure when data exists;\n // a source that never produced a session (empty or malformed file) is\n // logged and skipped so it cannot poison every future pass.\n if (visibleBaselineIds.has(source.sessionId)) sourceFailures.push(outcome.failure);\n reportSessionSourceOutcome(adapter.name, outcome);\n }\n }\n scanOptions?.onProgress?.({\n total: synchronizationIds.length,\n processed: index + 1,\n sessions: sessionsById.size,\n });\n });\n const parseMs = performance.now() - parseStartedAt;\n\n const failedIds = new Set(sourceFailures.map((failure) => failure.sessionId));\n const finalizeSessionIds = (\n request.kind === \"reload\" || (request.kind === \"refresh\" && !isWindowed(scanOptions))\n ? sources.map((source) => source.sessionId)\n : [...changedSessionIds]\n ).filter((sessionId) => !failedIds.has(sessionId));\n const sessions = [...sessionsById.values()];\n\n return {\n sessions,\n meta: adapter.snapshotSessionCacheMeta(new Set(sessionsById.keys())),\n sources,\n sourceOutcomes,\n detectedSessionIds,\n changedSessionIds: [...changedSessionIds],\n explicitRemovedSessionIds: [...explicitRemovedSessionIds],\n finalizeSessionIds,\n sourceFailures,\n completeness: isWindowed(scanOptions) || sourceFailures.length > 0 ? \"partial\" : \"complete\",\n sourceCount: sources.length,\n removedSourceCount: diff.removedIds.length,\n timing: {\n totalMs: performance.now() - startedAt,\n enumerationMs,\n diffMs,\n parseMs,\n enumeratedSourceCount: sources.length,\n changedSourceCount: diff.changedIds.length,\n processedSourceCount: synchronizationIds.length,\n },\n };\n}\n","import { readdirSync, statSync, type Dirent, type Stats } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { createSessionIdentity, type SessionIdentity } from \"../contract/session-reference.js\";\nimport type { SessionHead, SessionDetail, ParseSessionResult } from \"../types/index.js\";\nimport {\n capturePricingMisses,\n PRICING_CAPTURE_EPOCH,\n pricingBecameAvailable,\n} from \"../pricing/cost.js\";\nimport { getCoreDiagnostics } from \"../utils/diagnostics.js\";\nimport {\n createSessionSourceFailure,\n describeFailure,\n isMissingSessionSourceError,\n matchesScanWindow,\n synchronizeSessionSources as runSessionSourceSynchronization,\n} from \"./session-source-synchronization.js\";\nimport type {\n SessionSourceSynchronizationBaseline,\n SessionSourceSynchronizationOutcome,\n SessionSourceSynchronizationRequest,\n} from \"./session-source-synchronization.js\";\nimport type {\n AgentScanOptions,\n SessionCacheMeta,\n SessionCacheMetaSnapshot,\n SessionSourceFailure,\n SessionSourceOutcome,\n SessionSourceRef,\n SessionSourceScanBatch,\n} from \"./session-source-types.js\";\n\nexport {\n createSessionSourceFailure,\n diffSessionSources,\n matchesScanWindow,\n reportSessionSourceOutcome,\n} from \"./session-source-synchronization.js\";\nexport type {\n SessionSourceSynchronizationBaseline,\n SessionSourceSynchronizationOutcome,\n SessionSourceSynchronizationRequest,\n SessionSourceSynchronizationTiming,\n} from \"./session-source-synchronization.js\";\n\nexport type { ParseSessionResult };\nexport type {\n AgentScanOptions,\n AgentScanProgress,\n SessionCacheMeta,\n SessionCacheMetaSnapshot,\n SessionSourceAbsenceOutcome,\n SessionSourceDiff,\n SessionSourceFailure,\n SessionSourceOutcome,\n SessionSourceRef,\n SessionSourceScanBatch,\n} from \"./session-source-types.js\";\n\nexport function parsedSession<T>(session: T): ParseSessionResult<T> {\n return { status: \"parsed\", data: session };\n}\n\nexport function skippedSession<T>(reason: string): ParseSessionResult<T> {\n return { status: \"skipped\", reason };\n}\n\nexport function filteredSession<T>(reason: string): ParseSessionResult<T> {\n return { status: \"filtered\", reason };\n}\n\nexport function getParsedSession<T>(result: ParseSessionResult<T>): T | null {\n return result.status === \"parsed\" ? result.data : null;\n}\n\nexport interface AgentSourceOptions {\n readonly sourceRoot?: string;\n}\n\nexport interface FileWalkOptions {\n recursive?: boolean;\n scanWindow?: Pick<AgentScanOptions, \"from\" | \"to\">;\n}\n\nexport interface ChangeCheckFailure {\n sourcePath: string;\n errorClass: string;\n message: string;\n}\n\ninterface SuccessfulChangeCheck {\n status?: \"checked\";\n /** 是否有变更 */\n hasChanges: boolean;\n /** 可精确定位时的变更会话 ID;省略表示只能确认数据源发生过变化 */\n changedIds?: string[];\n /** 检测时间戳 */\n timestamp: number;\n /** 检测过程中已枚举的会话源(可选),供 incrementalScan 复用以避免二次枚举 */\n refs?: SessionSourceRef[];\n sourceFailures?: SessionSourceFailure[];\n failure?: never;\n}\n\ninterface FailedChangeCheck {\n status: \"failed\";\n hasChanges: false;\n timestamp: number;\n failure: ChangeCheckFailure;\n changedIds?: never;\n refs?: never;\n sourceFailures?: never;\n}\n\n/** 变更检测结果 */\nexport type ChangeCheckResult = SuccessfulChangeCheck | FailedChangeCheck;\n\nexport interface AgentScanFailure {\n agentName: string;\n stage: string;\n sourcePath?: string;\n errorClass: string;\n message: string;\n}\n\nexport interface SessionSourceFile {\n file: string;\n stat: Stats;\n}\n\nexport interface FileSessionMeta extends SessionCacheMeta {\n id: string;\n title: string;\n sourcePath: string;\n sourceFingerprint: string;\n sourceMtimeMs: number;\n directory: string;\n messageCount: number;\n createdAt: number;\n updatedAt: number;\n}\n\nexport interface SessionWatchTarget {\n /** Session source path whose related changes should trigger a refresh. */\n path: string;\n /** Stable ancestor to watch when the source path can be created or replaced. */\n root?: string;\n /** Exact descendant file names that do not represent session changes. */\n ignoredFileNames?: readonly string[];\n}\n\n/** `supported` may have no targets when the provider has no location in the current environment. */\nexport type SessionWatchPlan =\n | { status: \"supported\"; targets: SessionWatchTarget[] }\n | { status: \"unsupported\"; reason: string }\n | { status: \"not-needed\"; reason: string };\n\n/** What a source enumeration says needs re-parsing and what disappeared. */\nfunction cloneSessionCacheMeta(meta: SessionCacheMeta): SessionCacheMeta {\n return structuredClone(meta);\n}\n\nfunction snapshotSessionCacheMeta<TMeta extends SessionCacheMeta>(\n meta: ReadonlyMap<string, TMeta>,\n sessionIds?: ReadonlySet<string>,\n): Record<string, SessionCacheMeta> {\n const snapshot: Record<string, SessionCacheMeta> = {};\n for (const [sessionId, value] of meta) {\n if (sessionIds && !sessionIds.has(sessionId)) continue;\n snapshot[sessionId] = cloneSessionCacheMeta({ ...value, id: sessionId });\n }\n return snapshot;\n}\n\nexport interface EnumeratedSessionSourceCapability {\n readonly kind: \"enumerated\";\n synchronize(\n baseline: SessionSourceSynchronizationBaseline,\n request: SessionSourceSynchronizationRequest,\n ): SessionSourceSynchronizationOutcome;\n count(options?: AgentScanOptions): number;\n}\n\nexport interface AggregateSessionSourceCapability {\n readonly kind: \"aggregate\";\n checkForChanges(\n sinceTimestamp: number,\n cachedSessions: SessionHead[],\n ): Promise<ChangeCheckResult> | ChangeCheckResult;\n commitChangeCheck(): void;\n incrementalScan(\n cachedSessions: SessionHead[],\n changedIds: string[],\n refs?: SessionSourceRef[],\n scanOptions?: AgentScanOptions,\n ): Promise<SessionHead[]> | SessionHead[];\n}\n\nexport type SessionSourceCapability =\n | EnumeratedSessionSourceCapability\n | AggregateSessionSourceCapability;\n\nexport function createAgentScanFailure(\n agentName: string,\n stage: string,\n error: unknown,\n sourcePath?: string,\n): AgentScanFailure {\n const scanError = error instanceof SessionScanError ? error : null;\n const cause = scanError?.cause ?? error;\n return {\n agentName: scanError?.agentName ?? agentName,\n stage: scanError?.stage ?? stage,\n ...((scanError?.sourcePath ?? sourcePath)\n ? { sourcePath: scanError?.sourcePath ?? sourcePath }\n : {}),\n ...describeFailure(cause),\n };\n}\n\nexport function reportAgentScanFailure(failure: AgentScanFailure, baselineRetained: boolean): void {\n getCoreDiagnostics()?.warn(\"agent.scan_failed\", {\n agent: failure.agentName,\n stage: failure.stage,\n source_path: failure.sourcePath,\n error_class: failure.errorClass,\n message: failure.message,\n baseline_retained: baselineRetained,\n });\n}\n\nexport abstract class BaseAgent<TMeta extends SessionCacheMeta = SessionCacheMeta> {\n abstract readonly name: string;\n abstract readonly displayName: string;\n abstract readonly sessionSourceAccess: SessionSourceCapability;\n\n protected sessionMetaMap = new Map<string, TMeta>();\n\n /** Check if this agent has data available on the local filesystem. */\n abstract isAvailable(): boolean;\n\n /** Scan for available sessions, returning lightweight metadata. */\n abstract scan(options?: AgentScanOptions): SessionHead[];\n\n /** Load full session data including all messages. */\n abstract getSessionData(sessionId: string): SessionDetail;\n\n /** Describe how changes to this agent's session sources can be observed. */\n abstract getSessionWatchPlan(): SessionWatchPlan;\n\n /** Wrap an enumeration/database read so failures follow the error taxonomy. */\n protected scanStep<T>(stage: string, sourcePath: string, read: () => T): T {\n try {\n return read();\n } catch (error) {\n if (error instanceof SessionScanError) throw error;\n throw new SessionScanError(this.name, stage, { cause: error, sourcePath });\n }\n }\n\n filterCachedSessions(sessions: SessionHead[]): SessionHead[] {\n return sessions;\n }\n\n /** Read one isolated session metadata value. */\n getSessionCacheMeta(sessionId: string): SessionCacheMeta | undefined {\n const meta = this.sessionMetaMap.get(sessionId);\n return meta ? cloneSessionCacheMeta(meta) : undefined;\n }\n\n /** Export an isolated cache snapshot, optionally restricted to selected sessions. */\n snapshotSessionCacheMeta(sessionIds?: ReadonlySet<string>): Record<string, SessionCacheMeta> {\n return snapshotSessionCacheMeta(this.sessionMetaMap, sessionIds);\n }\n\n /** Restore session metadata from cache. */\n restoreSessionCacheMeta(meta: SessionCacheMetaSnapshot): void {\n this.sessionMetaMap = new Map(\n Object.entries(meta).map(([sessionId, value]) => [\n sessionId,\n cloneSessionCacheMeta({ ...value, id: sessionId }) as TMeta,\n ]),\n );\n }\n\n /** Remove metadata for sessions that are no longer retained. */\n removeSessionCacheMeta(sessionIds: Iterable<string>): void {\n for (const sessionId of sessionIds) this.sessionMetaMap.delete(sessionId);\n }\n\n getUri(sessionId: string): string {\n return `${this.name}://${sessionId}`;\n }\n\n protected sessionIdentity(sessionId: string): SessionIdentity {\n return createSessionIdentity({ agentName: this.name, sessionId });\n }\n}\n\n/**\n * 文件型 Agent 基类:每个会话对应磁盘上一个独立文件/目录。\n *\n * 子类只需实现两个必需的文件级原语:\n * - listSessionSources(): 枚举所有源 + 计算指纹\n * - scanSessionSourceResult(): 解析单个源(同时写入 metaMap)\n *\n * scanSessionSource() 是兼容旧调用方的公开入口,由富结果统一派生。\n *\n * 源同步与 metaMap 管理由本基类统一提供:\n * 同步流程用 listSessionSources 的指纹与缓存 metaMap 比对,\n * 并对变更集合调用 scanSessionSource 重解析。\n * 两原语在各子类中复用同一个 sourceFingerprint 计算,故指纹精确比对即等价于变更检测。\n */\nexport abstract class FileSystemSessionSource<\n TMeta extends SessionCacheMeta = SessionCacheMeta,\n> extends BaseAgent<TMeta> {\n protected readonly configuredSourceRoot: string | null;\n\n constructor(options: AgentSourceOptions = {}) {\n super();\n this.configuredSourceRoot = options.sourceRoot ?? null;\n }\n\n readonly sessionSourceAccess: EnumeratedSessionSourceCapability = {\n kind: \"enumerated\",\n synchronize: (baseline, request) => runSessionSourceSynchronization(this, baseline, request),\n count: (options) => this.listSessionSources(options).length,\n };\n\n private sourceFileStats = new Map<string, Stats>();\n\n /** 枚举所有会话源及其指纹。传入 options 时按 mtime 限定扫描窗口。 */\n abstract listSessionSources(options?: AgentScanOptions): SessionSourceRef[];\n\n /** 解析单个源并写入 metaMap,返回会话 head(解析失败/不可见返回 null)。 */\n scanSessionSource(sourcePath: string, options?: AgentScanOptions): SessionHead | null {\n return getParsedSession(\n this.scanSessionSourceResult({ sessionId: \"\", sourcePath, fingerprint: \"\" }, options),\n );\n }\n\n protected abstract scanSessionSourceResult(\n source: SessionSourceRef,\n options?: AgentScanOptions,\n ): ParseSessionResult<SessionHead>;\n\n scanSessionSourceOutcome(\n source: SessionSourceRef,\n options?: AgentScanOptions,\n ): SessionSourceOutcome {\n const previousMeta = this.sessionMetaMap.get(source.sessionId);\n let result: ParseSessionResult<SessionHead>;\n let unpricedModels: string[] = [];\n try {\n ({ result, unpricedModels } = capturePricingMisses(() =>\n this.scanSessionSourceResult(source, options),\n ));\n } catch (error) {\n if (previousMeta) this.sessionMetaMap.set(source.sessionId, previousMeta);\n else this.sessionMetaMap.delete(source.sessionId);\n if (isMissingSessionSourceError(error)) return { status: \"missing\", source };\n return {\n status: \"failed\",\n failure: createSessionSourceFailure(source, \"parsing\", error),\n };\n }\n if (result.status === \"parsed\") {\n const meta = this.sessionMetaMap.get(result.data.reference.sessionId);\n if (meta) {\n meta.pricingCaptureEpoch = PRICING_CAPTURE_EPOCH;\n if (unpricedModels.length > 0) meta.unpricedModels = unpricedModels;\n else delete meta.unpricedModels;\n }\n return { status: \"parsed\", source, session: result.data };\n }\n if (result.status === \"filtered\") {\n return { status: \"filtered\", source, reason: result.reason ?? \"filtered by agent\" };\n }\n if (previousMeta) this.sessionMetaMap.set(source.sessionId, previousMeta);\n else this.sessionMetaMap.delete(source.sessionId);\n return {\n status: \"failed\",\n failure: createSessionSourceFailure(\n source,\n \"parsing\",\n new Error(result.reason ?? \"source parse skipped\"),\n ),\n };\n }\n\n /**\n * 变更集合扩展:当某些会话变更会影响其他会话的派生数据时\n * (如 subagent 文件变更需要父会话重新聚合 token 统计),\n * 子类返回需要一并重解析的会话 ID 集合。默认无关联,原样返回。\n */\n expandChangedSessionIds(changedIds: string[], _refs?: SessionSourceRef[]): string[] {\n return changedIds;\n }\n\n scan(options?: AgentScanOptions): SessionHead[] {\n return this.scanSessionSources(options).sessions;\n }\n\n scanSessionSources(options?: AgentScanOptions): SessionSourceScanBatch {\n const outcome = this.sessionSourceAccess.synchronize(\n { sessions: [], meta: this.snapshotSessionCacheMeta() },\n { kind: \"reload\", scanOptions: options },\n );\n return {\n sources: outcome.sources,\n outcomes: outcome.sourceOutcomes,\n sessions: outcome.sessions,\n };\n }\n\n protected walkFiles(\n roots: string | readonly string[],\n isSessionFile: (entry: Dirent) => boolean,\n options: FileWalkOptions = {},\n ): SessionSourceFile[] {\n const files: SessionSourceFile[] = [];\n this.sourceFileStats.clear();\n\n const walk = (directory: string): void => {\n const entries = this.readSessionSourceDirectory(directory);\n\n for (const entry of entries) {\n const filePath = join(directory, entry.name);\n if (entry.isDirectory()) {\n if (options.recursive !== false) walk(filePath);\n continue;\n }\n if (!entry.isFile() || !isSessionFile(entry)) continue;\n\n let stat: Stats;\n try {\n stat = statSync(filePath);\n } catch (error) {\n if (isMissingSessionSourceError(error)) continue;\n throw new SessionScanError(this.name, \"reading session source metadata\", {\n cause: error,\n sourcePath: filePath,\n });\n }\n if (!matchesScanWindow(stat.mtimeMs, options.scanWindow)) continue;\n\n files.push({ file: filePath, stat });\n this.sourceFileStats.set(filePath, stat);\n }\n };\n\n for (const root of typeof roots === \"string\" ? [roots] : roots) walk(root);\n return files;\n }\n\n protected readSessionSourceDirectory(directory: string): Dirent[] {\n try {\n return readdirSync(directory, { withFileTypes: true });\n } catch (error) {\n throw new SessionScanError(this.name, \"enumerating session sources\", {\n cause: error,\n sourcePath: directory,\n });\n }\n }\n\n protected sessionSourceFile(sourcePath: string): SessionSourceFile {\n return {\n file: sourcePath,\n stat: this.sourceFileStats.get(sourcePath) ?? statSync(sourcePath),\n };\n }\n\n protected readFileMtimeMs(filePath: string | null): number | null {\n if (!filePath) return null;\n try {\n return statSync(filePath).mtimeMs;\n } catch {\n return null;\n }\n }\n}\n\n/** Shared scan template for agents whose session source is a single stat-able file. */\nexport abstract class SingleFileSessionSource<\n TMeta extends FileSessionMeta = FileSessionMeta,\n> extends FileSystemSessionSource<TMeta> {\n protected abstract parseFileSessionHeadResult(\n sourcePath: string,\n options?: AgentScanOptions,\n ): ParseSessionResult<SessionHead>;\n\n protected abstract createFileSessionMeta(head: SessionHead, source: SessionSourceFile): TMeta;\n\n private parseSessionSource(\n sourcePath: string,\n options?: AgentScanOptions,\n ): ParseSessionResult<SessionHead> {\n const result = this.parseFileSessionHeadResult(sourcePath, options);\n if (result.status === \"parsed\") {\n this.sessionMetaMap.set(\n result.data.reference.sessionId,\n this.createFileSessionMeta(result.data, this.sessionSourceFile(sourcePath)),\n );\n }\n return result;\n }\n\n protected override scanSessionSourceResult(\n source: SessionSourceRef,\n options?: AgentScanOptions,\n ): ParseSessionResult<SessionHead> {\n return this.parseSessionSource(source.sourcePath, options);\n }\n\n protected buildFileSessionMeta<TExtra extends object>({\n head,\n source,\n fingerprint,\n extras,\n }: {\n head: SessionHead;\n source: SessionSourceFile;\n fingerprint: string;\n extras: TExtra;\n }): FileSessionMeta & TExtra {\n return {\n ...extras,\n id: head.reference.sessionId,\n title: head.title,\n sourcePath: source.file,\n sourceFingerprint: fingerprint,\n sourceMtimeMs: source.stat.mtimeMs,\n directory: head.directory,\n messageCount: head.stats.message_count,\n createdAt: head.time_created,\n updatedAt: head.time_updated ?? head.time_created,\n };\n }\n}\n\n/**\n * 数据库型 Agent 基类:所有会话聚合在单个 SQLite 数据库中,\n * 无法做 per-file 指纹,故变更检测退化为\"库文件 mtime 是否推进\",\n * 增量扫描退化为全量重扫。\n */\n/**\n * A scan that could not prove its result complete — the database would not\n * open, a table was missing, or a top-level query failed.\n *\n * This is not the same as an agent with no sessions. Callers must keep the last\n * successful snapshot: treating it as an empty result would diff every known\n * session into a removal and wipe the agent from cache, search and the UI.\n */\n/**\n * Error taxonomy for adapters — the same failure class must produce the same\n * user-visible outcome regardless of agent:\n *\n * 1. Malformed record inside an otherwise readable source → skip the record;\n * visibility comes from counted diagnostics (see readJsonlFile's\n * `agent.jsonl_lines_skipped`), never from a hard failure.\n * 2. One source fails to parse → the scan template converts the throw into a\n * `createSessionSourceFailure` (\"parsing\"), keeping the rest of the scan.\n * 3. Enumeration or database access fails → throw `SessionScanError` (wrap\n * reads in `scanStep`); the scanner surfaces it as an agent scan failure.\n *\n * What is never acceptable: catching an I/O or database error and returning\n * an empty/zero result — that makes a broken source indistinguishable from an\n * empty one.\n */\nexport class SessionScanError extends Error {\n constructor(\n readonly agentName: string,\n readonly stage: string,\n options?: { cause?: unknown; sourcePath?: string },\n ) {\n super(`${agentName} session scan failed while ${stage}`, options);\n this.name = \"SessionScanError\";\n this.sourcePath = options?.sourcePath;\n }\n\n readonly sourcePath?: string;\n}\n\n/**\n * Files that reflect committed data. `-shm` is deliberately absent: opening the\n * database read-only rewrites it, so including it would report a change after\n * every scan.\n */\nexport function sqliteSourceFiles(dbPath: string): string[] {\n return [dbPath, `${dbPath}-wal`];\n}\n\nfunction statOrNull(path: string): { size: number; mtimeMs: number } | null {\n try {\n return statSync(path);\n } catch (error) {\n if (isMissingSessionSourceError(error)) return null;\n throw error;\n }\n}\n\n/** Changes whenever committed data changes, and only then. */\nfunction sqliteSourceFingerprint(dbPath: string): string {\n return sqliteSourceFiles(dbPath)\n .map((path) => {\n const stats = statOrNull(path);\n return stats ? `${stats.size}:${Math.round(stats.mtimeMs)}` : \"-\";\n })\n .join(\"|\");\n}\n\nfunction latestSqliteSourceMtime(dbPath: string): number {\n return sqliteSourceFiles(dbPath).reduce((latest, path) => {\n const stats = statOrNull(path);\n return stats && stats.mtimeMs > latest ? stats.mtimeMs : latest;\n }, 0);\n}\n\nexport abstract class DatabaseSessionSource extends BaseAgent {\n readonly sessionSourceAccess: AggregateSessionSourceCapability = {\n kind: \"aggregate\",\n checkForChanges: (sinceTimestamp, cachedSessions) =>\n this.checkForChanges(sinceTimestamp, cachedSessions),\n commitChangeCheck: () => this.commitChangeCheck(),\n incrementalScan: (cachedSessions, changedIds, refs, scanOptions) =>\n this.incrementalScan(cachedSessions, changedIds, refs, scanOptions),\n };\n\n private lastSourceFingerprint: string | null = null;\n private pendingSourceFingerprint: string | null = null;\n\n /** 返回数据库文件路径(供 mtime 检测)。 */\n protected abstract getDatabasePath(): string | null;\n\n /** 记录单个会话的缓存 meta(sourcePath = dbPath)。 */\n protected rememberSession(sessionId: string, additionalMeta: Record<string, unknown> = {}): void {\n const dbPath = this.getDatabasePath();\n if (!dbPath) return;\n this.sessionMetaMap.set(sessionId, {\n ...additionalMeta,\n id: sessionId,\n sourcePath: dbPath,\n pricingCaptureEpoch: PRICING_CAPTURE_EPOCH,\n });\n }\n\n protected captureSessionPricingMisses<T extends SessionHead | null>(scan: () => T): T {\n const { result, unpricedModels } = capturePricingMisses(scan);\n if (result) {\n this.rememberSession(\n result.reference.sessionId,\n unpricedModels.length > 0 ? { unpricedModels } : {},\n );\n }\n return result;\n }\n\n commitChangeCheck(): void {\n if (this.pendingSourceFingerprint == null) return;\n this.lastSourceFingerprint = this.pendingSourceFingerprint;\n this.pendingSourceFingerprint = null;\n }\n\n /**\n * 变更检测:数据库内部变更难以按行定位,按库文件集合的指纹判定。\n *\n * In WAL mode a commit appends to the sidecar and leaves the main file\n * untouched until checkpoint, so watching the database alone misses recent\n * writes entirely. Size is part of the fingerprint because an uncheckpointed\n * commit may land in the same millisecond as the previous one.\n */\n checkForChanges(sinceTimestamp: number, cachedSessions: SessionHead[]): ChangeCheckResult {\n const dbPath = this.getDatabasePath();\n if (!dbPath) {\n return { hasChanges: false, timestamp: Date.now() };\n }\n\n try {\n if (!statOrNull(dbPath)) {\n return { hasChanges: false, timestamp: Date.now() };\n }\n const pricingChanged = cachedSessions.some((session) => {\n const meta = this.sessionMetaMap.get(session.reference.sessionId);\n return (\n meta?.pricingCaptureEpoch !== PRICING_CAPTURE_EPOCH ||\n pricingBecameAvailable(meta.unpricedModels)\n );\n });\n if (pricingChanged) return { hasChanges: true, timestamp: Date.now() };\n\n const fingerprint = sqliteSourceFingerprint(dbPath);\n const previous = this.lastSourceFingerprint;\n // Advancing the baseline here would make a failed scan look \"unchanged\"\n // on the next pass; stash it until the orchestrator commits the scan.\n this.pendingSourceFingerprint = fingerprint;\n // Nothing to compare against on the first pass — fall back to the caller's\n // baseline, which also covers a WAL written while the process was down.\n const hasChanges =\n previous == null\n ? latestSqliteSourceMtime(dbPath) > sinceTimestamp\n : fingerprint !== previous;\n return {\n hasChanges,\n timestamp: Date.now(),\n };\n } catch (error) {\n const failure = {\n sourcePath: dbPath,\n errorClass: error instanceof Error ? error.name : typeof error,\n message: error instanceof Error ? error.message : String(error),\n };\n getCoreDiagnostics()?.warn(\"agent.change_check_failed\", {\n agent: this.name,\n source_path: failure.sourcePath,\n error_class: failure.errorClass,\n message: failure.message,\n baseline_advanced: false,\n });\n return {\n status: \"failed\",\n hasChanges: false,\n timestamp: sinceTimestamp,\n failure,\n };\n }\n }\n\n /** 增量扫描:数据库型无法增量,直接全量重扫。 */\n incrementalScan(\n _cachedSessions: SessionHead[],\n _changedIds: string[],\n _refs?: SessionSourceRef[],\n scanOptions?: AgentScanOptions,\n ): SessionHead[] {\n return this.scan(scanOptions);\n }\n}\n","import { existsSync, readFileSync, statSync } from \"node:fs\";\nimport { join, basename, dirname } from \"node:path\";\nimport { getAgentCatalogEntry } from \"../contract/agent-catalog.js\";\nimport { SingleFileSessionSource, filteredSession, parsedSession, skippedSession } from \"./base.js\";\nimport type { ParseSessionResult } from \"./base.js\";\nimport type { Message, SessionHead, SessionDetail } from \"../types/index.js\";\nimport { firstExisting, resolveHomePath } from \"../discovery/paths.js\";\nimport { readJsonlFile, readJsonlFileLines } from \"../utils/jsonl.js\";\nimport { basenameTitle, normalizeTitleText, resolveSessionTitle } from \"../utils/title-fallback.js\";\nimport { isInternalEventType } from \"../utils/parse-cleanup.js\";\nimport { estimateTokenCost } from \"../utils/cost.js\";\nimport { asRecord, asString, reportFieldMismatch } from \"../utils/narrow.js\";\nimport {\n matchesScanWindow,\n type AgentScanOptions,\n type FileSessionMeta,\n type SessionCacheMeta,\n type SessionSourceFile,\n type SessionSourceRef,\n} from \"./base.js\";\nimport {\n ClaudeRecordConverter,\n extractClaudeUsage,\n parseClaudeTimestampMs,\n type ClaudeUsage,\n} from \"./claudecode-record-converter.js\";\nimport { TranscriptBuilder } from \"./transcript-builder.js\";\n\nconst HEAD_INDEX_VERSION = \"claudecode-head-v9\";\n\nexport function resolveClaudeCodeDataRoot(): string {\n return resolveHomePath(\"CLAUDE_CONFIG_DIR\", \".claude\");\n}\n\ninterface SessionMeta extends FileSessionMeta {\n indexPath: string | null;\n indexMtimeMs: number | null;\n headIndexVersion: string;\n model: string | null | undefined;\n parentSessionId: string | null;\n toolUseId: string | null;\n}\n\ninterface ClaudeChildContext {\n sessionId: string;\n projectDir: string;\n parentSessionId: string | null;\n explicitTitle: string | null;\n metaMtimeMs: number | null;\n toolUseId: string | null;\n}\n\ninterface ClaudeChildContextCacheEntry {\n metaMtimeMs: number | null;\n context: ClaudeChildContext;\n}\n\nconst CLAUDE_RECORD_CONVERTER = new ClaudeRecordConverter();\n\nconst AGENT_METADATA = getAgentCatalogEntry(\"claudecode\");\n\nexport class ClaudeCodeAgent extends SingleFileSessionSource<SessionMeta> {\n readonly name = AGENT_METADATA.name;\n readonly displayName = AGENT_METADATA.displayName;\n\n private basePath: string | null = this.configuredSourceRoot;\n private sessionsIndexCache = new Map<string, Map<string, Record<string, unknown>>>();\n private sessionsIndexMtime: Record<string, number | null> = {};\n private childContextsBySource = new Map<string, ClaudeChildContext>();\n private childContextCache = new Map<string, ClaudeChildContextCacheEntry>();\n private childSessionIdByToolUseId = new Map<string, string>();\n private childIndexReady = false;\n\n private findBasePath(): string | null {\n return (\n this.configuredSourceRoot ??\n firstExisting(join(resolveClaudeCodeDataRoot(), \"projects\"), \"data/claudecode\")\n );\n }\n\n getSessionWatchPlan() {\n if (this.configuredSourceRoot) {\n return {\n status: \"supported\" as const,\n targets: [{ root: dirname(this.configuredSourceRoot), path: this.configuredSourceRoot }],\n };\n }\n const dataRoot = resolveClaudeCodeDataRoot();\n return {\n status: \"supported\" as const,\n targets: [{ root: dataRoot, path: join(dataRoot, \"projects\") }, { path: \"data/claudecode\" }],\n };\n }\n\n isAvailable(): boolean {\n this.basePath = this.findBasePath();\n if (!this.basePath) return false;\n for (const entry of this.readSessionSourceDirectory(this.basePath)) {\n if (!entry.isDirectory()) continue;\n const directory = join(this.basePath, entry.name);\n if (\n this.readSessionSourceDirectory(directory).some(\n (child) => child.isFile() && child.name.endsWith(\".jsonl\"),\n )\n ) {\n return true;\n }\n }\n return false;\n }\n\n listSessionSources(options?: AgentScanOptions): SessionSourceRef[] {\n if (!this.basePath) return [];\n const projectDirs = this.listProjectDirs();\n const indexMtimes = new Map<string, number | null>();\n for (const projectDir of projectDirs) {\n const indexPath = this.getSessionsIndexPath(projectDir);\n indexMtimes.set(projectDir, this.readFileMtimeMs(indexPath));\n }\n\n const projectDirSet = new Set(projectDirs);\n const allSources = this.walkFiles(projectDirs, (entry) => entry.name.endsWith(\".jsonl\"), {\n recursive: true,\n });\n this.indexChildContexts(allSources);\n const indexedSources = allSources.flatMap((source) => {\n const child = this.childContextsBySource.get(source.file);\n if (!child && !projectDirSet.has(dirname(source.file))) return [];\n return [\n {\n source,\n sessionId: child?.sessionId ?? basename(source.file, \".jsonl\"),\n child,\n },\n ];\n });\n let selectedSources = indexedSources.filter(({ source }) =>\n matchesScanWindow(source.stat.mtimeMs, options),\n );\n\n if (options?.from != null || options?.to != null) {\n type IndexedSource = (typeof indexedSources)[number];\n const knownSessionIds = new Set(indexedSources.map(({ sessionId }) => sessionId));\n const childrenByParent = new Map<string, IndexedSource[]>();\n for (const indexed of indexedSources) {\n const parentId = indexed.child?.parentSessionId;\n if (!parentId) continue;\n const children = childrenByParent.get(parentId);\n if (children) children.push(indexed);\n else childrenByParent.set(parentId, [indexed]);\n }\n\n const windowSelectedById = new Map(\n selectedSources.map((indexed) => [indexed.sessionId, indexed]),\n );\n const connectedSelected = new Map<string, IndexedSource>();\n const acceptedIds = new Set<string>();\n const visitingIds = new Set<string>();\n const hasSelectedParent = (sessionId: string): boolean => {\n if (acceptedIds.has(sessionId)) return true;\n if (visitingIds.has(sessionId)) return false;\n\n const indexed = windowSelectedById.get(sessionId);\n if (!indexed) return false;\n const parentId = indexed.child?.parentSessionId;\n if (!parentId || !knownSessionIds.has(parentId)) {\n acceptedIds.add(sessionId);\n return true;\n }\n\n visitingIds.add(sessionId);\n const connected = hasSelectedParent(parentId);\n visitingIds.delete(sessionId);\n if (connected) acceptedIds.add(sessionId);\n return connected;\n };\n\n for (const indexed of selectedSources) {\n if (hasSelectedParent(indexed.sessionId)) {\n connectedSelected.set(indexed.sessionId, indexed);\n }\n }\n\n if (options?.includeRelatedSessions !== false) {\n const pending = [...connectedSelected.values()]\n .filter(\n ({ child }) => !child?.parentSessionId || !knownSessionIds.has(child.parentSessionId),\n )\n .map(({ sessionId }) => sessionId);\n while (pending.length > 0) {\n const parentId = pending.pop()!;\n for (const child of childrenByParent.get(parentId) ?? []) {\n if (connectedSelected.has(child.sessionId)) continue;\n connectedSelected.set(child.sessionId, child);\n pending.push(child.sessionId);\n }\n }\n }\n\n selectedSources = [...connectedSelected.values()];\n }\n\n return selectedSources.map(({ source: { file, stat }, sessionId, child }) => {\n const projectDir = child?.projectDir ?? dirname(file);\n return {\n sessionId,\n sourcePath: file,\n fingerprint: this.sourceFingerprint(\n stat,\n indexMtimes.get(projectDir) ?? null,\n child?.metaMtimeMs,\n ),\n };\n });\n }\n\n restoreSessionCacheMeta(meta: Readonly<Record<string, SessionCacheMeta>>): void {\n const childIndexInputsChanged = this.childIndexReady && this.didChildIndexInputsChange(meta);\n super.restoreSessionCacheMeta(meta);\n if (!childIndexInputsChanged) return;\n this.childContextsBySource.clear();\n this.childSessionIdByToolUseId.clear();\n this.childIndexReady = false;\n }\n\n protected override parseFileSessionHeadResult(\n sourcePath: string,\n ): ParseSessionResult<SessionHead> {\n const child = this.getChildContext(sourcePath);\n const projectDir = child?.projectDir ?? dirname(sourcePath);\n return this.parseSessionHeadResult(sourcePath, projectDir, child);\n }\n\n getSessionData(sessionId: string): SessionDetail {\n const meta = this.sessionMetaMap.get(sessionId);\n if (!meta) {\n throw new Error(`Session not found: ${sessionId}`);\n }\n if (!existsSync(meta.sourcePath)) {\n throw new Error(`Session file missing: ${meta.sourcePath}`);\n }\n\n this.ensureChildIndex();\n const builder = new TranscriptBuilder();\n const assistantUuidToToolCalls = new Map<string, string[]>();\n const requestMessages = new Map<string, Message>();\n for (const record of readJsonlFile(meta.sourcePath)) {\n try {\n CLAUDE_RECORD_CONVERTER.convertRecord(\n record,\n builder,\n assistantUuidToToolCalls,\n requestMessages,\n this.childSessionIdByToolUseId,\n );\n } catch {\n // skip malformed records\n }\n }\n\n const transcript = builder.finish();\n\n return {\n ...this.sessionIdentity(meta.id),\n title: meta.title,\n directory: meta.directory,\n parent_reference:\n meta.parentSessionId == null\n ? undefined\n : { agentName: this.name, sessionId: meta.parentSessionId },\n version: undefined,\n time_created: meta.createdAt,\n time_updated: meta.updatedAt,\n stats: transcript.stats,\n messages: transcript.messages,\n };\n }\n\n // --- Private helpers ---\n\n private listProjectDirs(): string[] {\n if (!this.basePath) return [];\n return this.readSessionSourceDirectory(this.basePath)\n .filter((entry) => entry.isDirectory())\n .map((entry) => join(this.basePath!, entry.name));\n }\n\n private didChildIndexInputsChange(meta: Readonly<Record<string, SessionCacheMeta>>): boolean {\n if (Object.keys(meta).length !== this.sessionMetaMap.size) return true;\n\n for (const [sessionId, next] of Object.entries(meta)) {\n const current = this.sessionMetaMap.get(sessionId);\n if (!current || current.sourcePath !== next.sourcePath) return true;\n if (\n basename(dirname(next.sourcePath)) === \"subagents\" &&\n (current.title !== next[\"title\"] ||\n current.parentSessionId !== next[\"parentSessionId\"] ||\n this.readToolUseId(current) !== this.readToolUseId(next))\n ) {\n return true;\n }\n }\n\n return false;\n }\n\n private readToolUseId(meta: SessionCacheMeta): string | null {\n const value = meta[\"toolUseId\"];\n return typeof value === \"string\" && value.length > 0 ? value : null;\n }\n\n private ensureChildIndex(): void {\n if (this.childIndexReady) return;\n this.basePath ??= this.findBasePath();\n if (!this.basePath) {\n this.childIndexReady = true;\n return;\n }\n\n const projectDirs = this.listProjectDirs();\n this.indexChildContexts(\n this.walkFiles(projectDirs, (entry) => entry.name.endsWith(\".jsonl\"), {\n recursive: true,\n }),\n );\n }\n\n private indexChildContexts(sources: readonly SessionSourceFile[]): void {\n this.childContextsBySource.clear();\n this.childSessionIdByToolUseId.clear();\n\n for (const source of sources) {\n const child = this.readChildContext(source.file);\n if (!child) continue;\n this.childContextsBySource.set(source.file, child);\n if (child.toolUseId) {\n this.childSessionIdByToolUseId.set(child.toolUseId, child.sessionId);\n }\n }\n\n this.childIndexReady = true;\n }\n\n private getChildContext(sourcePath: string): ClaudeChildContext | null {\n const cached = this.childContextsBySource.get(sourcePath);\n if (cached) return cached;\n\n const child = this.readChildContext(sourcePath);\n if (!child) return null;\n this.childContextsBySource.set(sourcePath, child);\n if (child.toolUseId) {\n this.childSessionIdByToolUseId.set(child.toolUseId, child.sessionId);\n }\n return child;\n }\n\n private readChildContext(sourcePath: string): ClaudeChildContext | null {\n const subagentsDir = dirname(sourcePath);\n if (basename(subagentsDir) !== \"subagents\") return null;\n\n const parentDir = dirname(subagentsDir);\n // Claude stores nested transcripts flat here; parentAgentId carries the nesting relation.\n const projectDir = dirname(parentDir);\n const fileStem = basename(sourcePath, \".jsonl\");\n const metaPath = join(subagentsDir, fileStem + \".meta.json\");\n const metaMtimeMs = this.readFileMtimeMs(metaPath);\n const cached = this.childContextCache.get(sourcePath);\n if (cached?.metaMtimeMs === metaMtimeMs) return cached.context;\n\n let metadata: Record<string, unknown> | null = null;\n if (metaMtimeMs !== null) {\n try {\n metadata = asRecord(JSON.parse(readFileSync(metaPath, \"utf-8\"))) ?? null;\n } catch {\n // Child transcripts can outlive their metadata during an interrupted spawn.\n }\n }\n\n const sessionId = asString(metadata?.[\"agentId\"])?.trim() || fileStem.replace(/^agent-/, \"\");\n if (!sessionId) return null;\n\n const parentAgentId = asString(metadata?.[\"parentAgentId\"])?.trim();\n const parentSessionId = parentAgentId || basename(parentDir) || null;\n const name = asString(metadata?.[\"name\"])?.trim();\n const description = asString(metadata?.[\"description\"])?.trim();\n\n const context = {\n sessionId,\n projectDir,\n parentSessionId,\n explicitTitle: name || description || null,\n metaMtimeMs,\n toolUseId: asString(metadata?.[\"toolUseId\"])?.trim() || null,\n };\n this.childContextCache.set(sourcePath, { metaMtimeMs, context });\n return context;\n }\n\n protected createFileSessionMeta(head: SessionHead, source: SessionSourceFile): SessionMeta {\n const child = this.getChildContext(source.file);\n const projectDir = child?.projectDir ?? dirname(source.file);\n const indexPath = this.getSessionsIndexPath(projectDir);\n const indexMtime = this.readFileMtimeMs(indexPath);\n return this.buildFileSessionMeta({\n head,\n source,\n fingerprint: this.sourceFingerprint(source.stat, indexMtime, child?.metaMtimeMs),\n extras: {\n indexPath: indexMtime === null ? null : indexPath,\n indexMtimeMs: indexMtime,\n headIndexVersion: HEAD_INDEX_VERSION,\n model: head.stats.total_tokens ? \"unknown\" : undefined,\n parentSessionId: head.parent_reference?.sessionId ?? null,\n toolUseId: child?.toolUseId ?? null,\n },\n });\n }\n\n /** Fingerprint depends on an already-fetched stat to avoid re-statting the same file. */\n private sourceFingerprint(\n stat: { mtimeMs: number; size: number },\n indexMtime: number | null,\n metaMtime?: number | null,\n ): string {\n const fingerprint = [HEAD_INDEX_VERSION, stat.mtimeMs, stat.size, indexMtime];\n if (metaMtime !== undefined) fingerprint.push(metaMtime);\n return JSON.stringify(fingerprint);\n }\n\n private getSessionsIndexPath(projectDir: string): string {\n return join(projectDir, \"sessions-index.json\");\n }\n\n private loadSessionsIndex(projectDir: string): Map<string, Record<string, unknown>> {\n const cacheKey = basename(projectDir);\n const indexPath = this.getSessionsIndexPath(projectDir);\n const mtime = this.readFileMtimeMs(indexPath);\n\n // Invalidate when the index file mtime advances so long-running processes\n // pick up title changes without relying on callers to evict manually.\n const cached = this.sessionsIndexCache.get(cacheKey);\n if (cached && this.sessionsIndexMtime[cacheKey] === mtime) {\n return cached;\n }\n\n const map = new Map<string, Record<string, unknown>>();\n\n if (existsSync(indexPath)) {\n try {\n const data = JSON.parse(readFileSync(indexPath, \"utf-8\"));\n const entries: Record<string, unknown>[] = data?.entries ?? [];\n for (const entry of entries) {\n const sid = entry?.sessionId;\n if (typeof sid === \"string\") {\n map.set(sid, entry);\n }\n }\n } catch {\n // ignore\n }\n }\n\n this.sessionsIndexCache.set(cacheKey, map);\n this.sessionsIndexMtime[cacheKey] = mtime;\n return map;\n }\n\n private parseSessionHeadResult(\n filePath: string,\n projectDir: string,\n child?: ClaudeChildContext | null,\n ): ParseSessionResult<SessionHead> {\n const sessionId = child?.sessionId ?? basename(filePath, \".jsonl\");\n\n // Try to get title from sessions-index.json\n const index = this.loadSessionsIndex(projectDir);\n const indexEntry = index.get(sessionId);\n const explicitTitle =\n child?.explicitTitle ?? (indexEntry?.summary ? String(indexEntry.summary) : null);\n\n // Extract lightweight metadata; cwd lives in user-type records, not the first line\n let createdAt = 0;\n let updatedAt = 0;\n let lineIndex = 0;\n let messageCount = 0;\n let model: string | null = null;\n let cwd: string | null = null;\n let totalInputTokens = 0;\n let totalOutputTokens = 0;\n let totalCacheReadTokens = 0;\n let totalCacheCreateTokens = 0;\n let totalCost = 0;\n const modelUsageMap: Record<string, number> = {};\n const usageByRequest = new Map<string, ClaudeUsage>();\n let messageTitle: string | null = null;\n\n for (const line of readJsonlFileLines(filePath)) {\n let data: Record<string, unknown>;\n try {\n data = JSON.parse(line) as Record<string, unknown>;\n } catch {\n // A malformed opening record means the file is not a session we can read;\n // later ones are individually skippable.\n if (lineIndex === 0) return skippedSession(\"malformed first record\");\n lineIndex += 1;\n continue;\n }\n\n if (lineIndex === 0) {\n createdAt = parseClaudeTimestampMs(data) || statSync(filePath).mtimeMs;\n updatedAt = createdAt;\n }\n const recordIndex = lineIndex;\n lineIndex += 1;\n\n try {\n if (isInternalEventType(data[\"type\"])) continue;\n if (data[\"isMeta\"] === true) continue;\n const ts = parseClaudeTimestampMs(data);\n if (ts > updatedAt) updatedAt = ts;\n\n if (!cwd && data[\"cwd\"] && typeof data[\"cwd\"] === \"string\") {\n cwd = data[\"cwd\"];\n }\n\n const msg = asRecord(data[\"message\"]);\n if (!msg && data[\"message\"] !== undefined && data[\"message\"] !== null) {\n reportFieldMismatch(\"claudecode\", \"message\");\n }\n if (msg) {\n const role = asString(msg[\"role\"]);\n if (msg[\"role\"] !== undefined && role === undefined) {\n reportFieldMismatch(\"claudecode\", \"message.role\");\n }\n const userTitle = role === \"user\" ? this.extractUserMessageTitle(msg[\"content\"]) : null;\n if (role?.trim() && (role !== \"user\" || userTitle !== null)) {\n messageCount++;\n }\n if (!model) {\n const m = asString(msg[\"model\"]);\n if (m?.trim()) model = m.trim();\n }\n // Title fallback mirrors the removed extractTitle(): first non-empty\n // visible user text within the first 20 lines.\n if (messageTitle === null && recordIndex < 20 && userTitle) {\n messageTitle = userTitle;\n }\n if (role === \"assistant\") {\n const usage = extractClaudeUsage(data, msg);\n if (usage) usageByRequest.set(usage.key, usage);\n }\n }\n } catch {\n // skip\n }\n }\n\n if (lineIndex === 0) return skippedSession(\"empty file\");\n\n for (const usage of usageByRequest.values()) {\n const input = usage.input + usage.cacheRead + usage.cacheCreate;\n totalInputTokens += input;\n totalOutputTokens += usage.output;\n totalCacheReadTokens += usage.cacheRead;\n totalCacheCreateTokens += usage.cacheCreate;\n if (!usage.model) continue;\n modelUsageMap[usage.model] = (modelUsageMap[usage.model] ?? 0) + input + usage.output;\n totalCost +=\n estimateTokenCost(usage.model, {\n input,\n output: usage.output,\n cache_read: usage.cacheRead,\n cache_create: usage.cacheCreate,\n }) ?? 0;\n }\n\n const directory = cwd ?? projectDir;\n const directoryTitle = basenameTitle(directory) || basenameTitle(projectDir);\n\n const title = resolveSessionTitle(explicitTitle, messageTitle, directoryTitle);\n\n const hasModelUsage = Object.keys(modelUsageMap).length > 0;\n if (messageCount === 0) return filteredSession(\"no visible messages\");\n\n return parsedSession({\n ...this.sessionIdentity(sessionId),\n title,\n directory,\n parent_reference:\n child?.parentSessionId == null\n ? undefined\n : { agentName: this.name, sessionId: child.parentSessionId },\n time_created: createdAt,\n time_updated: updatedAt,\n stats: {\n message_count: messageCount,\n total_input_tokens: totalInputTokens,\n total_output_tokens: totalOutputTokens,\n total_cost: totalCost,\n cost_source: totalCost > 0 ? \"estimated\" : undefined,\n total_cache_read_tokens: totalCacheReadTokens,\n total_cache_create_tokens: totalCacheCreateTokens,\n },\n model_usage: hasModelUsage ? modelUsageMap : undefined,\n });\n }\n\n /** Mirrors the title-candidate extraction previously done in a second JSON.parse pass. */\n private extractUserMessageTitle(content: unknown): string | null {\n if (!content) return null;\n\n if (typeof content === \"string\") {\n const title = normalizeTitleText(content);\n return title || null;\n }\n if (Array.isArray(content)) {\n const texts = content\n .filter((item): item is Record<string, unknown> => {\n const record = asRecord(item);\n return record !== undefined && \"text\" in record;\n })\n .map((item) => String(item[\"text\"] ?? \"\"))\n .join(\" \");\n const title = normalizeTitleText(texts);\n return title || null;\n }\n return null;\n }\n}\n","import { existsSync } from \"node:fs\";\nimport { homedir, platform } from \"node:os\";\nimport { isAbsolute, join, resolve } from \"node:path\";\n\n/** Expand the tilde prefixes shells accept for home-relative paths. */\nfunction expandHomePath(path: string): string {\n if (path === \"~\") return homedir();\n if (path.startsWith(\"~/\") || path.startsWith(\"~\\\\\")) return join(homedir(), path.slice(2));\n return path;\n}\n\n/**\n * Blank values count as unset, `~` expands, and relative paths resolve — so\n * CODEX_HOME=~/data points at the home directory instead of a literal\n * ./~/data that silently yields zero sessions.\n */\nexport function readEnvPath(name: string): string | null {\n const value = process.env[name];\n if (!value || !value.trim()) return null;\n const expanded = expandHomePath(value.trim());\n // resolve() would also prepend a drive letter to POSIX-absolute paths on\n // Windows; only relative inputs actually need anchoring.\n return isAbsolute(expanded) ? expanded : resolve(expanded);\n}\n\nfunction firstExisting(...paths: string[]): string | null {\n for (const p of paths) {\n if (existsSync(p)) return p;\n }\n return null;\n}\n\nexport function resolveDataHome(): string {\n const xdg = readEnvPath(\"XDG_DATA_HOME\");\n if (xdg) return xdg;\n\n const p = platform();\n if (p === \"win32\") {\n return (\n readEnvPath(\"LOCALAPPDATA\") ?? readEnvPath(\"APPDATA\") ?? join(homedir(), \"AppData\", \"Local\")\n );\n }\n\n // macOS / Linux\n return join(homedir(), \".local\", \"share\");\n}\n\nexport function resolveHomePath(environmentVariable: string, fallbackDirectory: string): string {\n return readEnvPath(environmentVariable) ?? join(homedir(), fallbackDirectory);\n}\n\nexport { firstExisting };\n","import { getCoreDiagnostics } from \"./diagnostics.js\";\n\nconst TIMEZONE_SUFFIX_PATTERN = /(?:Z|[+-]\\d{2}:?\\d{2})$/i;\n\nexport interface AgentTimestampOptions {\n /** Accept bare numeric strings as epoch milliseconds (Kimi wire format). */\n numericStrings?: boolean;\n}\n\n/**\n * The one timestamp parser for agent-supplied values of unknown shape.\n * Missing values are null without noise; present-but-unparseable values are\n * reported once and return null so callers pick their own fallback.\n */\nexport function parseAgentTimestamp(\n value: unknown,\n agentName: string,\n options: AgentTimestampOptions = {},\n): number | null {\n if (value == null) return null;\n if (typeof value === \"number\") {\n if (Number.isFinite(value)) return value;\n reportTimestampParseFailure(agentName, value);\n return null;\n }\n if (typeof value !== \"string\") {\n reportTimestampParseFailure(agentName, value);\n return null;\n }\n\n const timestamp = value.trim().replace(\" \", \"T\");\n if (!timestamp) return null;\n\n if (options.numericStrings) {\n const numeric = Number(timestamp);\n if (Number.isFinite(numeric)) return numeric;\n }\n\n const normalized = TIMEZONE_SUFFIX_PATTERN.test(timestamp) ? timestamp : `${timestamp}Z`;\n const timestampMs = Date.parse(normalized);\n if (Number.isFinite(timestampMs)) return timestampMs;\n\n reportTimestampParseFailure(agentName, value, normalized);\n return null;\n}\n\nfunction reportTimestampParseFailure(agentName: string, value: unknown, normalized?: string): void {\n getCoreDiagnostics()?.warn(\"agent.timestamp_parse_failed\", {\n agentName,\n value: typeof value === \"string\" || typeof value === \"number\" ? value : typeof value,\n normalized,\n });\n}\n","import type { Message, MessagePart, ToolPart, ToolPartState } from \"../types/index.js\";\nimport { estimateTokenCost } from \"../utils/cost.js\";\nimport { asArray, asNumber, asRecord, asString, reportFieldMismatch } from \"../utils/narrow.js\";\nimport { isInternalEventType } from \"../utils/parse-cleanup.js\";\nimport { cleanInternalText } from \"../utils/session-normalization.js\";\nimport { parseAgentTimestamp } from \"../utils/timestamp.js\";\nimport { TranscriptBuilder, type TranscriptMessageInput } from \"./transcript-builder.js\";\n\nexport interface ClaudeUsage {\n key: string;\n model: string | undefined;\n input: number;\n output: number;\n cacheRead: number;\n cacheCreate: number;\n}\n\nexport function parseClaudeTimestampMs(data: Record<string, unknown>): number {\n return parseAgentTimestamp(data[\"timestamp\"], \"claudecode\") ?? 0;\n}\n\n/** Reads a numeric usage field; a present-but-wrong-typed field is a schema drift signal. */\nfunction readUsageNumber(usage: Record<string, unknown>, field: string): number {\n const raw = usage[field];\n if (raw === undefined) return 0;\n const value = asNumber(raw);\n if (value === undefined) {\n reportFieldMismatch(\"claudecode\", `message.usage.${field}`);\n return 0;\n }\n return value;\n}\n\nexport function extractClaudeUsage(\n data: Record<string, unknown>,\n msg: Record<string, unknown>,\n): ClaudeUsage | null {\n const rawUsage = msg[\"usage\"];\n if (rawUsage === undefined || rawUsage === null) return null;\n\n const usage = asRecord(rawUsage);\n if (!usage) {\n reportFieldMismatch(\"claudecode\", \"message.usage\");\n return null;\n }\n\n const requestId = typeof data[\"requestId\"] === \"string\" ? data[\"requestId\"].trim() : \"\";\n const uuid = typeof data[\"uuid\"] === \"string\" ? data[\"uuid\"].trim() : \"\";\n const key = requestId || uuid;\n if (!key) return null;\n\n return {\n key,\n model: asString(msg[\"model\"])?.trim() || undefined,\n input: readUsageNumber(usage, \"input_tokens\"),\n output: readUsageNumber(usage, \"output_tokens\"),\n cacheRead: readUsageNumber(usage, \"cache_read_input_tokens\"),\n cacheCreate: readUsageNumber(usage, \"cache_creation_input_tokens\"),\n };\n}\n\nexport class ClaudeRecordConverter {\n // --- Record conversion ---\n\n convertRecord(\n data: Record<string, unknown>,\n builder: TranscriptBuilder,\n assistantUuidToToolCalls: Map<string, string[]>,\n requestMessages: Map<string, Message>,\n childSessionIdByToolUseId: ReadonlyMap<string, string>,\n ): void {\n if (data[\"isMeta\"] === true) return;\n\n const msgType = String(data[\"type\"] ?? \"\");\n if (isInternalEventType(msgType)) return;\n\n if (msgType === \"assistant\") {\n this.convertAssistantRecord(\n data,\n builder,\n assistantUuidToToolCalls,\n requestMessages,\n childSessionIdByToolUseId,\n );\n } else if (msgType === \"user\") {\n this.convertUserRecord(data, builder, assistantUuidToToolCalls);\n } else if (msgType === \"tool_result\") {\n this.convertToolResultRecord(data, builder);\n }\n }\n\n private convertAssistantRecord(\n data: Record<string, unknown>,\n builder: TranscriptBuilder,\n assistantUuidToToolCalls: Map<string, string[]>,\n requestMessages: Map<string, Message>,\n childSessionIdByToolUseId: ReadonlyMap<string, string>,\n ): void {\n const msg = asRecord(data[\"message\"]) ?? {};\n const timestampMs = parseClaudeTimestampMs(data);\n const model = asString(msg[\"model\"])?.trim();\n const rawContent = asArray(msg[\"content\"]) ?? [];\n const uuid = String(data[\"uuid\"] ?? \"\");\n const usage = extractClaudeUsage(data, msg);\n let usageMessage = usage ? requestMessages.get(usage.key) : undefined;\n // A distinct request must not inherit another request's model or usage.\n if (usage && !usageMessage) builder.beginTurn();\n\n const toolCallIds: string[] = [];\n for (const item of rawContent) {\n const part = asRecord(item);\n if (!part) continue;\n const partType = String(part[\"type\"] ?? \"\");\n\n if (partType === \"thinking\") {\n const text = cleanInternalText(String(part[\"thinking\"] ?? \"\"));\n if (text) {\n const message = builder.appendAssistantPart(\n this.buildReasoningPart(text, timestampMs),\n { id: uuid, timestampMs, agent: \"claude\", model },\n { deduplicateTail: true },\n );\n usageMessage ??= message;\n }\n continue;\n }\n\n if (partType === \"text\") {\n const text = cleanInternalText(String(part[\"text\"] ?? \"\"));\n if (text) {\n const message = builder.appendAssistantPart(\n this.buildTextPart(text, timestampMs),\n {\n id: uuid,\n timestampMs,\n agent: \"claude\",\n model,\n },\n { deduplicateTail: true },\n );\n usageMessage ??= message;\n }\n continue;\n }\n\n if (partType !== \"tool_use\") continue;\n\n const toolCallId = String(part[\"id\"] ?? \"\").trim();\n const subagentId = childSessionIdByToolUseId.get(toolCallId);\n\n const toolPart = this.buildToolPart(part, timestampMs);\n const message = builder.appendToolCall(\n toolPart,\n { id: uuid, timestampMs, agent: \"claude\", subagentId, model },\n { modeOnCreate: \"tool\" },\n );\n if (subagentId) message.subagent_id = subagentId;\n usageMessage ??= message;\n if (toolCallId) {\n toolCallIds.push(toolCallId);\n }\n }\n\n if (toolCallIds.length > 0) {\n assistantUuidToToolCalls.set(uuid, toolCallIds);\n }\n if (usage) {\n usageMessage ??= builder.appendMessage({\n id: uuid,\n role: \"assistant\",\n timestampMs,\n agent: \"claude\",\n model,\n });\n requestMessages.set(usage.key, usageMessage);\n usageMessage.model = usage.model;\n usageMessage.tokens = {\n input: usage.input + usage.cacheCreate + usage.cacheRead,\n output: usage.output,\n cache_read: usage.cacheRead,\n cache_create: usage.cacheCreate,\n };\n usageMessage.time_completed = timestampMs;\n usageMessage.cost = estimateTokenCost(usage.model, usageMessage.tokens) ?? 0;\n usageMessage.cost_source = usageMessage.cost > 0 ? \"estimated\" : undefined;\n }\n }\n\n private convertUserRecord(\n data: Record<string, unknown>,\n builder: TranscriptBuilder,\n assistantUuidToToolCalls: Map<string, string[]>,\n ): void {\n const msg = asRecord(data[\"message\"]) ?? {};\n const timestampMs = parseClaudeTimestampMs(data);\n const content = msg[\"content\"] ?? \"\";\n const uuid = String(data[\"uuid\"] ?? \"\");\n\n // String content — simple user message\n if (typeof content === \"string\") {\n const parts = this.normalizeUserTextParts(content, timestampMs);\n if (parts.length === 0) {\n builder.beginTurn();\n return;\n }\n builder.appendMessage({ id: uuid, role: \"user\", timestampMs, parts });\n return;\n }\n\n if (!Array.isArray(content)) {\n builder.beginTurn();\n return;\n }\n\n const visibleParts = this.normalizeUserTextParts(content, timestampMs);\n const toolStateUpdates = this.extractToolStateUpdates(data[\"toolUseResult\"]);\n\n for (const item of content) {\n const ci = asRecord(item);\n if (!ci || ci[\"type\"] !== \"tool_result\") continue;\n\n const toolCallId = this.resolveToolCallId(data, ci, assistantUuidToToolCalls);\n\n const outputParts = this.normalizeClaudeToolOutput(ci[\"content\"], timestampMs);\n if (this.backfillToolOutput(builder, toolCallId, outputParts, toolStateUpdates)) {\n continue;\n }\n\n const fallback = this.buildFallbackToolMessage({\n messageId: uuid,\n timestampMs,\n toolCallId,\n outputParts,\n });\n if (fallback) builder.appendMessage(fallback);\n }\n\n if (visibleParts.length > 0) {\n builder.appendMessage({ id: uuid, role: \"user\", timestampMs, parts: visibleParts });\n }\n\n builder.beginTurn();\n }\n\n private convertToolResultRecord(data: Record<string, unknown>, builder: TranscriptBuilder): void {\n const timestampMs = parseClaudeTimestampMs(data);\n const msg = asRecord(data[\"message\"]) ?? {};\n const outputParts = this.normalizeClaudeToolOutput(msg[\"content\"], timestampMs);\n const uuid = String(data[\"uuid\"] ?? \"\");\n\n const fallback = this.buildFallbackToolMessage({\n messageId: uuid,\n timestampMs,\n toolCallId: null,\n outputParts,\n });\n if (fallback) builder.appendMessage(fallback);\n builder.beginTurn();\n }\n\n private buildTextPart(text: string, timestampMs: number): MessagePart {\n return { type: \"text\", text, time_created: timestampMs };\n }\n\n private buildReasoningPart(text: string, timestampMs: number): MessagePart {\n return { type: \"reasoning\", text, time_created: timestampMs };\n }\n\n private buildToolPart(part: Record<string, unknown>, timestampMs: number): ToolPart {\n const toolName = String(part[\"name\"] ?? \"\");\n return {\n type: \"tool\",\n tool: toolName,\n callID: String(part[\"id\"] ?? \"\"),\n title: `Tool: ${toolName}`,\n state: {\n status: \"running\",\n input: part[\"input\"] ?? {},\n output: null,\n },\n time_created: timestampMs,\n };\n }\n\n // --- User content normalization ---\n\n private normalizeUserTextParts(content: unknown, timestampMs: number): MessagePart[] {\n if (typeof content === \"string\") {\n const text = cleanInternalText(content);\n return text ? [this.buildTextPart(text, timestampMs)] : [];\n }\n if (!Array.isArray(content)) return [];\n\n const parts: MessagePart[] = [];\n for (const item of content) {\n const ci = asRecord(item);\n if (ci) {\n if (ci[\"type\"] === \"tool_result\") continue;\n const text = cleanInternalText(String(ci[\"text\"] ?? \"\"));\n if (text) parts.push(this.buildTextPart(text, timestampMs));\n } else if (typeof item === \"string\") {\n const text = cleanInternalText(item);\n if (text) parts.push(this.buildTextPart(text, timestampMs));\n }\n }\n return parts;\n }\n\n private normalizeClaudeToolOutput(content: unknown, timestampMs: number): MessagePart[] {\n if (typeof content === \"string\") {\n const text = cleanInternalText(content);\n return text ? [this.buildTextPart(text, timestampMs)] : [];\n }\n if (content === null || content === undefined) return [];\n\n if (Array.isArray(content)) {\n const parts: MessagePart[] = [];\n for (const item of content) {\n const itemRecord = asRecord(item);\n if (itemRecord) {\n const rawSource = itemRecord[\"source\"];\n if (itemRecord[\"type\"] === \"image\" && rawSource) {\n const source = asRecord(rawSource);\n const data = asString(source?.[\"data\"]) ?? \"\";\n const mimeType = asString(source?.[\"media_type\"]) ?? \"\";\n if (data && mimeType.startsWith(\"image/\")) {\n parts.push({ type: \"image\", data, mime_type: mimeType, time_created: timestampMs });\n }\n continue;\n }\n const text = String(itemRecord[\"text\"] ?? itemRecord[\"content\"] ?? \"\");\n const cleaned = cleanInternalText(text);\n if (cleaned) parts.push(this.buildTextPart(cleaned, timestampMs));\n } else if (typeof item === \"string\") {\n const text = cleanInternalText(item);\n if (text) parts.push(this.buildTextPart(text, timestampMs));\n }\n }\n return parts;\n }\n\n const text = cleanInternalText(String(content));\n return text ? [this.buildTextPart(text, timestampMs)] : [];\n }\n\n // --- Tool backfill ---\n\n private backfillToolOutput(\n builder: TranscriptBuilder,\n callId: string,\n outputParts: MessagePart[],\n stateUpdates?: Partial<Pick<ToolPartState, \"status\" | \"metadata\">>,\n ): boolean {\n if (!callId) return false;\n\n return builder.updateToolCall(callId, (part) => {\n const state = part.state;\n if (outputParts.length > 0) {\n const existing = state.output;\n if (Array.isArray(existing)) existing.push(...outputParts);\n else if (existing == null) state.output = [...outputParts];\n else state.output = [existing, ...outputParts];\n }\n if (stateUpdates?.status) state.status = stateUpdates.status;\n if (stateUpdates?.metadata !== undefined) state.metadata = stateUpdates.metadata;\n if (outputParts.length > 0 && state.status === \"running\") state.status = \"completed\";\n });\n }\n\n private resolveToolCallId(\n data: Record<string, unknown>,\n item: Record<string, unknown>,\n assistantUuidToToolCalls: Map<string, string[]>,\n ): string {\n const directId = String(item[\"tool_use_id\"] ?? \"\").trim();\n if (directId) return directId;\n\n const sourceUuid = String(data[\"sourceToolAssistantUUID\"] ?? \"\").trim();\n if (!sourceUuid) return \"\";\n\n const ids = assistantUuidToToolCalls.get(sourceUuid);\n if (ids && ids.length === 1) return ids[0]!;\n return \"\";\n }\n\n private extractToolStateUpdates(\n toolUseResult: unknown,\n ): Partial<Pick<ToolPartState, \"status\" | \"metadata\">> {\n const result = asRecord(toolUseResult);\n if (!result) return {};\n\n const updates: Partial<Pick<ToolPartState, \"status\" | \"metadata\">> = {};\n\n const success = result[\"success\"];\n if (typeof success === \"boolean\") {\n updates.status = success ? \"completed\" : \"error\";\n }\n\n const commandName = result[\"commandName\"];\n if (commandName) {\n updates.metadata = { commandName };\n }\n\n return updates;\n }\n\n // --- Fallback ---\n\n private buildFallbackToolMessage(opts: {\n messageId: string;\n timestampMs: number;\n toolCallId: string | null;\n outputParts: MessagePart[];\n }): TranscriptMessageInput | null {\n if (opts.outputParts.length === 0) return null;\n return {\n id: opts.messageId,\n role: \"tool\",\n timestampMs: opts.timestampMs,\n parts: opts.outputParts,\n };\n }\n}\n","import type {\n Message,\n MessagePart,\n SessionStats,\n ToolPart,\n ToolPartStatus,\n} from \"../types/index.js\";\nimport { cleanParsedMessages } from \"../utils/session-normalization.js\";\n\nexport interface TranscriptMessageInput {\n id: string;\n role: Message[\"role\"];\n timestampMs: number;\n parts?: MessagePart[];\n agent?: string | null;\n mode?: string | null;\n model?: string | null;\n provider?: string | null;\n tokens?: Message[\"tokens\"];\n cost?: number;\n costSource?: Message[\"cost_source\"];\n subagentId?: string;\n nickname?: string;\n automated?: boolean;\n}\n\nexport type AssistantMessageInput = Omit<TranscriptMessageInput, \"role\" | \"parts\">;\n\nexport interface ToolResolution {\n output?: unknown;\n status?: ToolPartStatus;\n metadata?: unknown;\n consume?: boolean;\n}\n\nexport interface TranscriptResult {\n messages: Message[];\n stats: SessionStats;\n}\n\ninterface TranscriptBuilderOptions {\n messageDefaults?: \"nullable\" | \"sparse\";\n contentRetention?: \"full\" | \"structure\";\n}\n\nconst RETAINED_CONTENT = \"[content]\";\n\nfunction mergeTokens(base: Message[\"tokens\"], extra: Message[\"tokens\"]): Message[\"tokens\"] {\n if (!base) return extra;\n if (!extra) return base;\n const merged = { ...base };\n for (const key of Object.keys(extra) as (keyof NonNullable<Message[\"tokens\"]>)[]) {\n const value = extra[key];\n if (typeof value === \"number\") merged[key] = (merged[key] ?? 0) + value;\n }\n return merged;\n}\n\ninterface PartFlags {\n hasText: boolean;\n hasTool: boolean;\n}\n\nexport class TranscriptBuilder {\n private readonly messages: Message[] = [];\n private readonly pendingToolCalls = new Map<string, ToolPart>();\n // Tracks per-message part kinds so grouping checks are O(1) instead of\n // rescanning the growing parts array on every append (CS-283).\n private readonly partFlags = new WeakMap<Message, PartFlags>();\n private currentAssistant: Message | null = null;\n private latestTextAssistant: Message | null = null;\n\n constructor(private readonly options: TranscriptBuilderOptions = {}) {}\n\n beginTurn(): void {\n this.currentAssistant = null;\n this.latestTextAssistant = null;\n }\n\n appendMessage(input: TranscriptMessageInput): Message {\n const message = this.createMessage(input);\n this.messages.push(message);\n for (const part of message.parts) {\n this.registerToolCall(part);\n this.notePart(message, part);\n }\n\n if (message.role === \"assistant\") {\n this.currentAssistant = message;\n if (this.flagsFor(message).hasText) {\n this.latestTextAssistant = message;\n }\n } else if (message.role === \"user\") {\n this.beginTurn();\n }\n\n return message;\n }\n\n appendAssistantPart(\n part: MessagePart,\n input: AssistantMessageInput,\n options: {\n grouping?: \"compatible\" | \"current\";\n resetLatestText?: boolean;\n deduplicateTail?: boolean;\n } = {},\n ): Message {\n const current = this.currentAssistant;\n const currentFlags = current === null ? null : this.flagsFor(current);\n const canReuse =\n current !== null &&\n (options.grouping === \"current\" ||\n (part.type === \"text\"\n ? !currentFlags!.hasTool\n : part.type === \"reasoning\"\n ? !currentFlags!.hasText && !currentFlags!.hasTool\n : false));\n\n const message = canReuse\n ? current\n : this.appendMessage({ ...input, role: \"assistant\", parts: [part] });\n\n if (canReuse) {\n if (options.deduplicateTail) this.appendPartIfNew(message, part);\n else this.pushPart(message, part);\n this.applyMissingMetadata(message, input);\n }\n if (part.type === \"text\") {\n this.latestTextAssistant = message;\n } else if (options.resetLatestText) {\n this.latestTextAssistant = null;\n }\n return message;\n }\n\n appendToolCall(\n part: ToolPart,\n input: AssistantMessageInput,\n options: {\n markModeAsTool?: boolean;\n modeOnCreate?: string;\n target?: \"latest-text\" | \"current\";\n } = {},\n ): Message {\n const target =\n options.target === \"current\"\n ? this.currentAssistant\n : (this.latestTextAssistant ?? this.currentAssistant);\n const message = target\n ? target\n : this.appendMessage({\n ...input,\n role: \"assistant\",\n mode: options.modeOnCreate ?? (options.markModeAsTool ? \"tool\" : input.mode),\n parts: [part],\n });\n\n if (target) {\n const retainedPart = this.pushPart(message, part);\n this.applyMissingMetadata(message, input);\n if (options.markModeAsTool) message.mode = \"tool\";\n this.registerToolCall(retainedPart);\n }\n\n this.currentAssistant = message;\n return message;\n }\n\n appendToCurrentAssistant(part: MessagePart): boolean {\n if (!this.currentAssistant) return false;\n this.pushPart(this.currentAssistant, part);\n return true;\n }\n\n updateToolCall(callId: string, update: (part: ToolPart) => void): boolean {\n const part = this.pendingToolCalls.get(callId);\n if (!part) return false;\n update(part);\n return true;\n }\n\n resolveToolCall(callId: string, resolution: ToolResolution): boolean {\n return this.updateToolCall(callId, (part) => {\n const state = part.state;\n if (resolution.output !== undefined && this.options.contentRetention !== \"structure\") {\n state.output = resolution.output;\n }\n if (resolution.status !== undefined) state.status = resolution.status;\n else if (resolution.output !== undefined && state.status === \"running\") {\n state.status = \"completed\";\n }\n if (resolution.metadata !== undefined && this.options.contentRetention !== \"structure\") {\n state.metadata = resolution.metadata;\n }\n if (resolution.consume) this.pendingToolCalls.delete(callId);\n });\n }\n\n attachUsageToLatestAssistant(\n tokens: Message[\"tokens\"],\n options: { model?: string | null; cost?: number; costSource?: Message[\"cost_source\"] } = {},\n ): boolean {\n let mergeTarget: Message | null = null;\n for (let index = this.messages.length - 1; index >= 0; index -= 1) {\n const message = this.messages[index]!;\n if (message.role !== \"assistant\") continue;\n if (!message.tokens) {\n message.tokens = tokens;\n if (options.model !== undefined) message.model ??= options.model;\n if (options.cost !== undefined) message.cost = options.cost;\n if (options.costSource !== undefined) message.cost_source = options.costSource;\n return true;\n }\n if (!mergeTarget && (message.model ?? null) === (options.model ?? null)) {\n mergeTarget = message;\n }\n }\n // A turn can report usage more often than it produces assistant messages;\n // folding the surplus into the latest same-model message keeps its tokens\n // and cost attributed instead of silently dropping them.\n if (!mergeTarget) return false;\n mergeTarget.tokens = mergeTokens(mergeTarget.tokens, tokens);\n if (options.cost !== undefined) {\n mergeTarget.cost = (mergeTarget.cost ?? 0) + options.cost;\n if (options.costSource !== undefined) mergeTarget.cost_source ??= options.costSource;\n }\n return true;\n }\n\n finish(baseStats?: SessionStats): TranscriptResult {\n const messages = cleanParsedMessages(this.messages);\n const derived = this.deriveStats(messages);\n if (!baseStats) return { messages, stats: derived };\n\n return {\n messages,\n stats: {\n ...derived,\n ...baseStats,\n message_count: messages.length,\n cost_source: baseStats.cost_source,\n },\n };\n }\n\n private createMessage(input: TranscriptMessageInput): Message {\n const sparse = this.options.messageDefaults === \"sparse\";\n return {\n id: input.id,\n role: input.role,\n agent: sparse ? input.agent : (input.agent ?? null),\n time_created: input.timestampMs,\n mode: sparse ? input.mode : (input.mode ?? null),\n model: sparse ? input.model : (input.model ?? null),\n provider: sparse ? input.provider : (input.provider ?? null),\n tokens: input.tokens,\n cost: sparse ? input.cost : (input.cost ?? 0),\n cost_source: input.costSource,\n parts: (input.parts ?? []).map((part) => this.retainPart(part)),\n subagent_id: input.subagentId,\n nickname: input.nickname,\n ...(input.automated ? { automated: true } : {}),\n };\n }\n\n private registerToolCall(part: MessagePart): void {\n if (part.type === \"tool\" && part.callID) {\n this.pendingToolCalls.set(part.callID, part);\n }\n }\n\n private appendPartIfNew(message: Message, part: MessagePart): void {\n const tail = message.parts.at(-1);\n if (\"text\" in part && tail?.type === part.type && \"text\" in tail && tail.text === part.text) {\n return;\n }\n this.pushPart(message, part);\n }\n\n private pushPart(message: Message, part: MessagePart): MessagePart {\n const retainedPart = this.retainPart(part);\n message.parts.push(retainedPart);\n this.notePart(message, retainedPart);\n return retainedPart;\n }\n\n private retainPart(part: MessagePart): MessagePart {\n if (this.options.contentRetention !== \"structure\") return part;\n if (part.type === \"text\" || part.type === \"reasoning\") {\n return { ...part, text: RETAINED_CONTENT };\n }\n if (part.type === \"plan\") return { ...part, text: RETAINED_CONTENT };\n if (part.type === \"image\") {\n return { type: \"image\", url: RETAINED_CONTENT, time_created: part.time_created };\n }\n return {\n type: \"tool\",\n tool: part.tool,\n title: part.title,\n callID: part.callID,\n state: { status: part.state.status },\n time_created: part.time_created,\n };\n }\n\n private notePart(message: Message, part: MessagePart): void {\n const flags = this.flagsFor(message);\n if (part.type === \"text\") flags.hasText = true;\n else if (part.type === \"tool\") flags.hasTool = true;\n }\n\n private flagsFor(message: Message): PartFlags {\n let flags = this.partFlags.get(message);\n if (!flags) {\n flags = { hasText: false, hasTool: false };\n this.partFlags.set(message, flags);\n }\n return flags;\n }\n\n private applyMissingMetadata(message: Message, input: AssistantMessageInput): void {\n if (!message.id && input.id) message.id = input.id;\n if (message.agent == null && input.agent !== undefined) message.agent = input.agent;\n if (message.mode == null && input.mode !== undefined) message.mode = input.mode;\n if (message.model == null && input.model !== undefined) message.model = input.model;\n if (message.provider == null && input.provider !== undefined) message.provider = input.provider;\n if (!message.tokens && input.tokens) message.tokens = input.tokens;\n if ((message.cost ?? 0) === 0 && input.cost !== undefined) message.cost = input.cost;\n if (!message.cost_source && input.costSource) message.cost_source = input.costSource;\n }\n\n private deriveStats(messages: Message[]): SessionStats {\n let totalInputTokens = 0;\n let totalOutputTokens = 0;\n let totalCacheReadTokens = 0;\n let totalCacheCreateTokens = 0;\n let totalCost = 0;\n let hasEstimatedCost = false;\n\n for (const message of messages) {\n totalInputTokens += message.tokens?.input ?? 0;\n totalOutputTokens += message.tokens?.output ?? 0;\n totalCacheReadTokens += message.tokens?.cache_read ?? 0;\n totalCacheCreateTokens += message.tokens?.cache_create ?? 0;\n totalCost += message.cost ?? 0;\n if (message.cost_source === \"estimated\") hasEstimatedCost = true;\n }\n\n return {\n message_count: messages.length,\n total_input_tokens: totalInputTokens,\n total_output_tokens: totalOutputTokens,\n total_cache_read_tokens: totalCacheReadTokens || undefined,\n total_cache_create_tokens: totalCacheCreateTokens || undefined,\n total_cost: totalCost,\n cost_source: totalCost > 0 ? (hasEstimatedCost ? \"estimated\" : \"recorded\") : undefined,\n };\n }\n}\n","import { join } from \"node:path\";\nimport { getAgentCatalogEntry } from \"../contract/agent-catalog.js\";\nimport { firstExisting, resolveDataHome } from \"../discovery/paths.js\";\nimport { isSqliteAvailable } from \"../utils/sqlite.js\";\nimport { OpenCodeSqliteAgent } from \"./opencode-sqlite.js\";\nimport type { AgentSourceOptions } from \"./base.js\";\n\nconst AGENT_METADATA = getAgentCatalogEntry(\"opencode\");\n\nexport function resolveOpenCodeDataRoot(): string {\n return join(resolveDataHome(), \"opencode\");\n}\n\nfunction findOpenCodeDbPath(sourceRoot?: string): string | null {\n if (!isSqliteAvailable()) return null;\n if (sourceRoot) return firstExisting(join(sourceRoot, \"opencode.db\"));\n return firstExisting(join(resolveOpenCodeDataRoot(), \"opencode.db\"), \"data/opencode/opencode.db\");\n}\n\nfunction getOpenCodeSessionWatchPlan(sourceRoot?: string) {\n const dataRoot = sourceRoot ?? resolveOpenCodeDataRoot();\n return {\n status: \"supported\" as const,\n targets: sourceRoot\n ? [{ root: dataRoot, path: join(dataRoot, \"opencode.db\") }]\n : [\n { root: dataRoot, path: join(dataRoot, \"opencode.db\") },\n { root: \"data/opencode\", path: \"data/opencode/opencode.db\" },\n ],\n };\n}\n\nexport class OpenCodeAgent extends OpenCodeSqliteAgent {\n constructor(options: AgentSourceOptions = {}) {\n super({\n name: AGENT_METADATA.name,\n displayName: AGENT_METADATA.displayName,\n findDbPath: () => findOpenCodeDbPath(options.sourceRoot),\n getSessionWatchPlan: () => getOpenCodeSessionWatchPlan(options.sourceRoot),\n });\n }\n}\n","import {\n DatabaseSessionSource,\n SessionScanError,\n filteredSession,\n getParsedSession,\n parsedSession,\n skippedSession,\n} from \"./base.js\";\nimport type {\n AgentScanOptions,\n ChangeCheckResult,\n ParseSessionResult,\n SessionWatchPlan,\n} from \"./base.js\";\nimport type { SessionHead, SessionDetail, Message, MessagePart } from \"../types/index.js\";\nimport { normalizeMessageParts } from \"../contract/message-part.js\";\nimport { capturePricingMisses } from \"../pricing/cost.js\";\nimport { columnExists, openDbReadOnly, type SQLiteDatabase } from \"../utils/sqlite.js\";\nimport { estimateTokenCost } from \"../utils/cost.js\";\nimport { resolveSessionTitle } from \"../utils/title-fallback.js\";\nimport { isInternalEventType } from \"../utils/parse-cleanup.js\";\nimport { asRecord, asString, narrowField, reportFieldMismatch } from \"../utils/narrow.js\";\nimport { getCoreDiagnostics } from \"../utils/diagnostics.js\";\nimport {\n cleanMessagePart,\n cleanParsedMessages,\n firstUserMessageTitle,\n} from \"../utils/session-normalization.js\";\n\ninterface OpenCodeMessageRow {\n id?: unknown;\n session_id?: unknown;\n data?: string;\n time_created?: unknown;\n}\n\ninterface OpenCodePartRow {\n message_id?: unknown;\n data?: string;\n time_created?: unknown;\n}\n\ninterface OpenCodeHeadContext {\n stats: SessionHead[\"stats\"];\n messageTitle: string | null;\n unpricedModels: Set<string>;\n}\n\ninterface OpenCodeSqliteAgentConfig {\n name: string;\n displayName: string;\n findDbPath: () => string | null;\n getSessionWatchPlan: () => SessionWatchPlan;\n}\n\nconst MESSAGE_ROLES = new Set<Message[\"role\"]>([\"user\", \"assistant\", \"tool\"]);\nconst SESSION_ID_QUERY_CHUNK_SIZE = 500;\nconst HEAD_PARSER_VERSION = \"opencode-sqlite-head-v1\";\n\nfunction compareSessionRowsByActivityDesc(\n left: Record<string, unknown>,\n right: Record<string, unknown>,\n): number {\n const leftUpdated = Number(left.time_updated ?? left.time_created ?? 0);\n const rightUpdated = Number(right.time_updated ?? right.time_created ?? 0);\n return (\n rightUpdated - leftUpdated ||\n Number(right.time_created ?? 0) - Number(left.time_created ?? 0) ||\n String(right.id ?? \"\").localeCompare(String(left.id ?? \"\"))\n );\n}\n\nfunction accumulateTokenStats(\n stats: SessionHead[\"stats\"],\n msgData: Record<string, unknown>,\n agentName: string,\n): void {\n const cost = Number(msgData.cost ?? 0);\n const tokens = parseTokens(msgData.tokens, agentName);\n const inputTokens = Number(tokens?.input ?? 0);\n const outputTokens = Number(tokens?.output ?? 0);\n const model = parseModel(msgData.modelID, agentName);\n const estimatedCost =\n cost > 0 ? null : estimateTokenCost(model, { input: inputTokens, output: outputTokens });\n\n if (estimatedCost !== null) stats.cost_source = \"estimated\";\n stats.total_cost += cost || estimatedCost || 0;\n stats.total_input_tokens += inputTokens;\n stats.total_output_tokens += outputTokens;\n}\n\n/** Parses a SQLite `data` JSON column; non-object payloads fall back to `{}` (reported as drift). */\nfunction parseJsonRecord(raw: unknown, agentName: string, field: string): Record<string, unknown> {\n const parsed = asRecord(JSON.parse(String(raw ?? \"{}\")));\n if (parsed) return parsed;\n reportFieldMismatch(agentName, field);\n return {};\n}\n\nfunction narrowMessageRole(value: unknown): Message[\"role\"] | undefined {\n const role = asString(value);\n return role !== undefined && (MESSAGE_ROLES as Set<string>).has(role)\n ? (role as Message[\"role\"])\n : undefined;\n}\n\nfunction parseMessageRole(value: unknown, agentName: string): Message[\"role\"] {\n return narrowField(agentName, \"message.role\", value, narrowMessageRole) ?? \"assistant\";\n}\n\nfunction parseTokens(value: unknown, agentName: string): Record<string, unknown> | undefined {\n return narrowField(agentName, \"message.tokens\", value, asRecord);\n}\n\nfunction parseModel(value: unknown, agentName: string): string | null {\n return narrowField(agentName, \"message.modelID\", value, asString) ?? null;\n}\n\nexport class OpenCodeSqliteAgent extends DatabaseSessionSource {\n readonly name: string;\n readonly displayName: string;\n\n private dbPath: string | null = null;\n\n constructor(private readonly config: OpenCodeSqliteAgentConfig) {\n super();\n this.name = config.name;\n this.displayName = config.displayName;\n }\n\n protected getDatabasePath(): string | null {\n if (!this.dbPath) {\n this.dbPath = this.findDbPath();\n }\n return this.dbPath;\n }\n\n getSessionWatchPlan(): SessionWatchPlan {\n return this.config.getSessionWatchPlan();\n }\n\n private findDbPath(): string | null {\n return this.config.findDbPath();\n }\n\n isAvailable(): boolean {\n this.dbPath = this.findDbPath();\n return this.dbPath !== null;\n }\n\n scan(options?: AgentScanOptions): SessionHead[] {\n const dbPath = this.getDatabasePath();\n if (!dbPath) return [];\n\n const db = openDbReadOnly(dbPath);\n if (!db) throw new SessionScanError(this.name, \"opening the database\");\n\n try {\n const cutoffTime = options?.from ?? Date.now() - 3650 * 24 * 60 * 60 * 1000;\n const activityPredicate =\n options?.to == null\n ? \"COALESCE(s.time_updated, s.time_created) >= ?\"\n : \"COALESCE(s.time_updated, s.time_created) >= ? AND COALESCE(s.time_updated, s.time_created) <= ?\";\n const activityBindings = options?.to == null ? [cutoffTime] : [cutoffTime, options.to];\n\n const hasMessageTable = Boolean(\n db\n .prepare(\"SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'message'\")\n .get(),\n );\n\n const hasTaskType = columnExists(db, \"session\", \"task_type\");\n const hasParentId = columnExists(db, \"session\", \"parent_id\");\n const childPredicate = hasParentId\n ? \"AND s.parent_id IS NULL\"\n : hasTaskType\n ? \"AND (s.task_type IS NULL OR s.task_type != 'subagent_child')\"\n : \"\";\n\n let rows: Record<string, unknown>[];\n const parentIdSelect = hasParentId ? \", s.parent_id\" : \"\";\n if (hasMessageTable) {\n rows = db\n .prepare(`\n SELECT\n s.id, s.title, s.time_created, s.time_updated, s.slug, s.directory,\n s.version, s.summary_files${parentIdSelect}\n FROM session s\n WHERE ${activityPredicate}\n ${childPredicate}\n ORDER BY COALESCE(s.time_updated, s.time_created) DESC, s.time_created DESC, s.id DESC\n `)\n .all(...activityBindings);\n } else {\n rows = db\n .prepare(`\n SELECT s.id, s.title, s.time_created, s.time_updated, s.slug, s.directory,\n s.version, s.summary_files, 0 AS message_count, NULL AS model_message_data${parentIdSelect}\n FROM session s\n WHERE ${activityPredicate}\n ${childPredicate}\n ORDER BY COALESCE(s.time_updated, s.time_created) DESC, s.time_created DESC, s.id DESC\n `)\n .all(...activityBindings);\n }\n\n if (hasParentId && options?.includeRelatedSessions !== false) {\n const rootIds = rows.map((row) => String(row.id ?? \"\")).filter(Boolean);\n const relatedRows = this.readRelatedSessionRows(db, rootIds);\n const knownIds = new Set(rootIds);\n rows.push(...relatedRows.filter((row) => !knownIds.has(String(row.id ?? \"\"))));\n }\n\n rows.sort(compareSessionRowsByActivityDesc);\n\n const sessionIds = new Set(rows.map((row) => String(row.id ?? \"\")).filter(Boolean));\n\n const headContexts = hasMessageTable\n ? this.buildHeadContexts(\n this.readHeadMessageRows(db, cutoffTime, sessionIds.size > 0 ? sessionIds : undefined),\n this.readHeadPartRows(db, cutoffTime, sessionIds.size > 0 ? sessionIds : undefined),\n )\n : new Map<string, OpenCodeHeadContext>();\n const heads: SessionHead[] = [];\n options?.onProgress?.({ total: rows.length, processed: 0, sessions: 0 });\n let processed = 0;\n for (const row of rows) {\n const context = headContexts.get(String(row.id ?? \"\"));\n const head = getParsedSession(this.parseSessionHeadRow(row, hasMessageTable, context));\n if (head) {\n heads.push(head);\n this.rememberSession(head.reference.sessionId, {\n headParserVersion: HEAD_PARSER_VERSION,\n ...(context && context.unpricedModels.size > 0\n ? { unpricedModels: [...context.unpricedModels] }\n : {}),\n });\n }\n processed += 1;\n options?.onProgress?.({ total: rows.length, processed, sessions: heads.length });\n }\n\n return heads;\n } catch (error) {\n throw new SessionScanError(this.name, \"reading sessions\", { cause: error });\n } finally {\n db.close();\n }\n }\n\n private parseSessionHeadRow(\n row: Record<string, unknown>,\n hasMessageTable: boolean,\n context?: OpenCodeHeadContext,\n ): ParseSessionResult<SessionHead> {\n const id = String(row.id ?? \"\");\n if (!id) return skippedSession(\"missing session id\");\n\n const timeCreated = Number(row.time_created ?? 0);\n const timeUpdated = Number(row.time_updated ?? timeCreated);\n const stats = context?.stats ?? null;\n const messageCount = stats?.message_count ?? 0;\n if (hasMessageTable && messageCount === 0) return filteredSession(\"no visible messages\");\n const messageTitle = context?.messageTitle ?? null;\n\n return parsedSession({\n ...this.sessionIdentity(id),\n title: resolveSessionTitle(String(row.title ?? \"\"), messageTitle, null),\n directory: String(row.directory ?? \"\"),\n parent_reference:\n row.parent_id == null || String(row.parent_id) === \"\"\n ? undefined\n : { agentName: this.name, sessionId: String(row.parent_id) },\n time_created: timeCreated,\n time_updated: timeUpdated,\n stats: {\n message_count: messageCount,\n total_input_tokens: stats?.total_input_tokens ?? 0,\n total_output_tokens: stats?.total_output_tokens ?? 0,\n total_cost: stats?.total_cost ?? 0,\n cost_source: stats?.cost_source,\n },\n });\n }\n\n private readHeadMessageRows(\n db: SQLiteDatabase,\n cutoffTime: number,\n sessionIds?: Set<string>,\n ): OpenCodeMessageRow[] {\n const ids = sessionIds ? [...sessionIds] : [];\n if (ids.length === 0) {\n return db\n .prepare(\n `\n SELECT m.id, m.session_id, m.data, m.time_created\n FROM message m\n JOIN session s ON s.id = m.session_id\n WHERE COALESCE(s.time_updated, s.time_created) >= ?\n ORDER BY m.session_id, m.time_created ASC\n `,\n )\n .all(cutoffTime) as OpenCodeMessageRow[];\n }\n\n const rows: OpenCodeMessageRow[] = [];\n for (let offset = 0; offset < ids.length; offset += SESSION_ID_QUERY_CHUNK_SIZE) {\n const chunk = ids.slice(offset, offset + SESSION_ID_QUERY_CHUNK_SIZE);\n rows.push(\n ...(db\n .prepare(\n `\n SELECT m.id, m.session_id, m.data, m.time_created\n FROM message m\n JOIN session s ON s.id = m.session_id\n WHERE s.id IN (${chunk.map(() => \"?\").join(\",\")})\n ORDER BY m.session_id, m.time_created ASC\n `,\n )\n .all(...chunk) as OpenCodeMessageRow[]),\n );\n }\n return rows;\n }\n\n private readHeadPartRows(\n db: SQLiteDatabase,\n cutoffTime: number,\n sessionIds?: Set<string>,\n ): OpenCodePartRow[] {\n const ids = sessionIds ? [...sessionIds] : [];\n if (ids.length === 0) {\n return db\n .prepare(\n `\n SELECT p.message_id, p.data, p.time_created\n FROM part p\n JOIN message m ON m.id = p.message_id\n JOIN session s ON s.id = m.session_id\n WHERE COALESCE(s.time_updated, s.time_created) >= ?\n ORDER BY p.message_id, p.time_created ASC, p.id ASC\n `,\n )\n .all(cutoffTime) as OpenCodePartRow[];\n }\n\n const rows: OpenCodePartRow[] = [];\n for (let offset = 0; offset < ids.length; offset += SESSION_ID_QUERY_CHUNK_SIZE) {\n const chunk = ids.slice(offset, offset + SESSION_ID_QUERY_CHUNK_SIZE);\n rows.push(\n ...(db\n .prepare(\n `\n SELECT p.message_id, p.data, p.time_created\n FROM part p\n JOIN message m ON m.id = p.message_id\n JOIN session s ON s.id = m.session_id\n WHERE s.id IN (${chunk.map(() => \"?\").join(\",\")})\n ORDER BY p.message_id, p.time_created ASC, p.id ASC\n `,\n )\n .all(...chunk) as OpenCodePartRow[]),\n );\n }\n return rows;\n }\n\n private readRelatedSessionRows(db: SQLiteDatabase, rootIds: string[]): Record<string, unknown>[] {\n if (rootIds.length === 0) return [];\n\n const startedAt = performance.now();\n const relatedById = new Map<string, Record<string, unknown>>();\n let candidateRows = 0;\n let queryCount = 0;\n for (let offset = 0; offset < rootIds.length; offset += SESSION_ID_QUERY_CHUNK_SIZE) {\n const chunk = rootIds.slice(offset, offset + SESSION_ID_QUERY_CHUNK_SIZE);\n const rows = db\n .prepare(\n `\n WITH RECURSIVE related_sessions(\n id, title, time_created, time_updated, slug, directory,\n version, summary_files, parent_id\n ) AS (\n SELECT\n s.id, s.title, s.time_created, s.time_updated, s.slug, s.directory,\n s.version, s.summary_files, s.parent_id\n FROM session s\n WHERE s.parent_id IN (${chunk.map(() => \"?\").join(\",\")})\n\n UNION\n\n SELECT\n child.id, child.title, child.time_created, child.time_updated,\n child.slug, child.directory, child.version, child.summary_files, child.parent_id\n FROM session child\n JOIN related_sessions parent ON child.parent_id = parent.id\n )\n SELECT\n id, title, time_created, time_updated, slug, directory,\n version, summary_files, parent_id\n FROM related_sessions\n ORDER BY time_created ASC, id ASC\n `,\n )\n .all(...chunk) as Record<string, unknown>[];\n queryCount += 1;\n candidateRows += rows.length;\n for (const row of rows) {\n const id = String(row.id ?? \"\");\n if (id && !relatedById.has(id)) relatedById.set(id, row);\n }\n }\n const result = [...relatedById.values()];\n getCoreDiagnostics()?.info?.(\"agent.related_sessions.query\", {\n agent_name: this.name,\n root_count: rootIds.length,\n query_count: queryCount,\n candidate_rows: candidateRows,\n related_rows: result.length,\n duration_ms: Number((performance.now() - startedAt).toFixed(2)),\n });\n return result;\n }\n\n private parsePartRow(\n partRow: Pick<OpenCodePartRow, \"data\" | \"time_created\">,\n ): MessagePart | null {\n const partData = parseJsonRecord(partRow.data, this.name, \"part.data\");\n const partType = String(partData.type ?? \"\");\n if (isInternalEventType(partType)) return null;\n const [part] = normalizeMessageParts([\n { ...partData, time_created: Number(partRow.time_created ?? 0) },\n ]);\n return part ? cleanMessagePart(part) : null;\n }\n\n /**\n * Every part of one session in a single read. Fetching per message turned a\n * detail into M+2 queries, and without an index on part(message_id) each one\n * scanned the whole table.\n */\n private readSessionPartRows(db: SQLiteDatabase, sessionId: string): OpenCodePartRow[] {\n return db\n .prepare(\n `\n SELECT p.message_id, p.data, p.time_created\n FROM part p\n JOIN message m ON m.id = p.message_id\n WHERE m.session_id = ?\n ORDER BY p.message_id, p.time_created ASC, p.id ASC\n `,\n )\n .all(sessionId) as OpenCodePartRow[];\n }\n\n private buildPartsByMessage(partRows: OpenCodePartRow[]): Map<string, MessagePart[]> {\n const partsByMessage = new Map<string, MessagePart[]>();\n for (const row of partRows) {\n const messageId = String(row.message_id ?? \"\");\n if (!messageId) continue;\n const part = this.parsePartRow(row);\n if (!part) continue;\n const parts = partsByMessage.get(messageId);\n if (parts) {\n parts.push(part);\n } else {\n partsByMessage.set(messageId, [part]);\n }\n }\n return partsByMessage;\n }\n\n private buildHeadContexts(\n messageRows: OpenCodeMessageRow[],\n partRows: OpenCodePartRow[],\n ): Map<string, OpenCodeHeadContext> {\n const partsByMessage = this.buildPartsByMessage(partRows);\n const contexts = new Map<string, OpenCodeHeadContext>();\n\n const ensureContext = (sessionId: string): OpenCodeHeadContext => {\n let context = contexts.get(sessionId);\n if (!context) {\n context = {\n stats: {\n message_count: 0,\n total_input_tokens: 0,\n total_output_tokens: 0,\n total_cost: 0,\n },\n messageTitle: null,\n unpricedModels: new Set(),\n };\n contexts.set(sessionId, context);\n }\n return context;\n };\n\n for (const row of messageRows) {\n const sessionId = String(row.session_id ?? \"\");\n if (!sessionId) continue;\n const msgData = parseJsonRecord(row.data, this.name, \"message.data\");\n if (isInternalEventType(msgData.type)) continue;\n\n const parts = partsByMessage.get(String(row.id ?? \"\")) ?? [];\n if (parts.length === 0) continue;\n\n const context = ensureContext(sessionId);\n const { unpricedModels } = capturePricingMisses(() =>\n accumulateTokenStats(context.stats, msgData, this.name),\n );\n for (const model of unpricedModels) context.unpricedModels.add(model);\n context.stats.message_count += 1;\n\n if (!context.messageTitle && String(msgData.role ?? \"\") === \"user\") {\n context.messageTitle = firstUserMessageTitle([\n {\n id: String(row.id ?? \"\"),\n role: \"user\",\n agent: null,\n time_created: Number(row.time_created ?? 0),\n parts,\n },\n ]);\n }\n }\n\n for (const context of contexts.values()) {\n if (context.stats.total_cost > 0 && context.stats.cost_source !== \"estimated\") {\n context.stats.cost_source = \"recorded\";\n }\n }\n\n return contexts;\n }\n\n checkForChanges(sinceTimestamp: number, cachedSessions: SessionHead[]): ChangeCheckResult {\n const hasStaleHead = cachedSessions.some(\n (session) =>\n this.sessionMetaMap.get(session.reference.sessionId)?.headParserVersion !==\n HEAD_PARSER_VERSION,\n );\n if (hasStaleHead) return { hasChanges: true, timestamp: Date.now() };\n return super.checkForChanges(sinceTimestamp, cachedSessions);\n }\n\n private sumChildTokenStats(db: SQLiteDatabase, parentSessionId: string): SessionHead[\"stats\"][] {\n if (!columnExists(db, \"session\", \"parent_id\")) return [];\n\n const childRows = this.readRelatedSessionRows(db, [parentSessionId]).filter(\n (row) => String(row.id ?? \"\") !== parentSessionId,\n );\n\n const results: SessionHead[\"stats\"][] = [];\n for (const child of childRows) {\n const childId = String(child.id ?? \"\");\n if (!childId) continue;\n const msgRows = db\n .prepare(\"SELECT data FROM message WHERE session_id = ? ORDER BY time_created ASC, id ASC\")\n .all(childId) as OpenCodeMessageRow[];\n const stats: SessionHead[\"stats\"] = {\n message_count: 0,\n total_input_tokens: 0,\n total_output_tokens: 0,\n total_cost: 0,\n };\n for (const row of msgRows) {\n const msgData = parseJsonRecord(row.data, this.name, \"message.data\");\n if (isInternalEventType(msgData.type)) continue;\n accumulateTokenStats(stats, msgData, this.name);\n }\n results.push(stats);\n }\n return results;\n }\n\n getSessionData(sessionId: string): SessionDetail {\n // Ensure dbPath is set\n if (!this.dbPath) {\n this.dbPath = this.findDbPath();\n }\n if (!this.dbPath) {\n throw new Error(`${this.displayName} database is missing`);\n }\n\n const db = openDbReadOnly(this.dbPath);\n if (!db) {\n throw new Error(`${this.displayName} database is missing`);\n }\n\n try {\n // First get session metadata\n const sessionRow = db.prepare(\"SELECT * FROM session WHERE id = ?\").get(sessionId) as\n | Record<string, unknown>\n | undefined;\n if (!sessionRow) {\n throw new Error(`Session not found: ${sessionId}`);\n }\n\n const id = String(sessionRow.id ?? sessionId);\n const directory = String(sessionRow.directory ?? \"\");\n const timeCreated = Number(sessionRow.time_created ?? 0);\n const timeUpdated = Number(sessionRow.time_updated ?? timeCreated);\n\n const messages: Message[] = [];\n let hasEstimatedCost = false;\n\n // Get messages\n const msgRows = db\n .prepare(\"SELECT * FROM message WHERE session_id = ? ORDER BY time_created ASC, id ASC\")\n .all(sessionId) as Record<string, unknown>[];\n const partsByMessage = this.buildPartsByMessage(this.readSessionPartRows(db, sessionId));\n\n for (const msgRow of msgRows) {\n const msgData = parseJsonRecord(msgRow.data, this.name, \"message.data\");\n if (isInternalEventType(msgData.type)) continue;\n\n const cost = Number(msgData.cost ?? 0);\n const tokens = parseTokens(msgData.tokens, this.name);\n const inputTokens = Number(tokens?.input ?? 0);\n const outputTokens = Number(tokens?.output ?? 0);\n const model = parseModel(msgData.modelID, this.name);\n const estimatedCost =\n cost > 0 ? null : estimateTokenCost(model, { input: inputTokens, output: outputTokens });\n const resolvedCost = cost || estimatedCost || 0;\n\n const parts = partsByMessage.get(String(msgRow.id ?? \"\")) ?? [];\n if (parts.length === 0) continue;\n\n messages.push({\n id: String(msgRow.id ?? \"\"),\n role: parseMessageRole(msgData.role, this.name),\n agent: asString(msgData.agent) ?? null,\n mode: asString(msgData.mode) ?? null,\n model,\n provider: asString(msgData.providerID) ?? null,\n time_created: Number(msgRow.time_created ?? 0),\n tokens: tokens ? { input: inputTokens, output: outputTokens } : undefined,\n cost: resolvedCost,\n cost_source: resolvedCost > 0 ? (cost > 0 ? \"recorded\" : \"estimated\") : undefined,\n parts,\n });\n }\n\n const cleanedMessages = cleanParsedMessages(messages);\n const title = resolveSessionTitle(\n String(sessionRow.title ?? \"\"),\n firstUserMessageTitle(cleanedMessages),\n null,\n );\n const stats: SessionHead[\"stats\"] = {\n message_count: cleanedMessages.length,\n total_input_tokens: 0,\n total_output_tokens: 0,\n total_cost: 0,\n };\n for (const message of cleanedMessages) {\n stats.total_cost += message.cost ?? 0;\n stats.total_input_tokens += message.tokens?.input ?? 0;\n stats.total_output_tokens += message.tokens?.output ?? 0;\n if (message.cost_source === \"estimated\") hasEstimatedCost = true;\n }\n\n for (const childStats of this.sumChildTokenStats(db, sessionId)) {\n stats.total_cost += childStats.total_cost;\n stats.total_input_tokens += childStats.total_input_tokens;\n stats.total_output_tokens += childStats.total_output_tokens;\n if (childStats.cost_source === \"estimated\") hasEstimatedCost = true;\n }\n\n return {\n ...this.sessionIdentity(id),\n title,\n directory,\n parent_reference:\n sessionRow.parent_id == null || String(sessionRow.parent_id) === \"\"\n ? undefined\n : { agentName: this.name, sessionId: String(sessionRow.parent_id) },\n version: asString(sessionRow.version) ?? undefined,\n time_created: timeCreated,\n time_updated: timeUpdated,\n summary_files: sessionRow.summary_files ?? undefined,\n stats: {\n message_count: stats.message_count,\n total_input_tokens: stats.total_input_tokens,\n total_output_tokens: stats.total_output_tokens,\n total_cost: stats.total_cost,\n cost_source:\n stats.total_cost > 0 ? (hasEstimatedCost ? \"estimated\" : \"recorded\") : undefined,\n },\n messages: cleanedMessages,\n };\n } finally {\n db.close();\n }\n }\n}\n","import { createHash } from \"node:crypto\";\nimport { existsSync, readFileSync, statSync } from \"node:fs\";\nimport { join, basename, dirname } from \"node:path\";\nimport { getAgentCatalogEntry } from \"../contract/agent-catalog.js\";\nimport {\n FileSystemSessionSource,\n getParsedSession,\n matchesScanWindow,\n parsedSession,\n skippedSession,\n} from \"./base.js\";\nimport type {\n AgentScanOptions,\n AgentSourceOptions,\n ParseSessionResult,\n SessionCacheMeta,\n SessionSourceRef,\n} from \"./base.js\";\nimport type { SessionHead, SessionDetail, MessagePart } from \"../types/index.js\";\nimport { firstExisting, resolveHomePath } from \"../discovery/paths.js\";\nimport { readJsonlFile } from \"../utils/jsonl.js\";\nimport { normalizeTitleText, resolveSessionTitle } from \"../utils/title-fallback.js\";\nimport { isInternalEventType } from \"../utils/parse-cleanup.js\";\nimport { cleanInternalText } from \"../utils/session-normalization.js\";\nimport { estimateTokenCost } from \"../utils/cost.js\";\nimport {\n asArray,\n asNumber,\n asRecord,\n asString,\n narrowField,\n reportFieldMismatch,\n} from \"../utils/narrow.js\";\nimport { parseAgentTimestamp } from \"../utils/timestamp.js\";\nimport { TranscriptBuilder, type TranscriptMessageInput } from \"./transcript-builder.js\";\nimport { normalizeToolArguments } from \"./tool-arguments.js\";\n\nconst KIMI_TOOL_TITLE_MAP: Record<string, string> = {\n ReadFile: \"read\",\n Glob: \"glob\",\n StrReplaceFile: \"edit\",\n Grep: \"grep\",\n WriteFile: \"write\",\n Shell: \"bash\",\n};\n\nconst KIMI_IGNORED_TOOLS = new Set([\"SetTodoList\"]);\nconst KIMI_PARSER_REVISION = \"kimi-parser-v2\";\n\nexport function resolveKimiDataRoot(): string {\n return resolveHomePath(\"KIMI_SHARE_DIR\", \".kimi\");\n}\n\nfunction mapToolTitle(toolName: string): string {\n return KIMI_TOOL_TITLE_MAP[toolName] ?? toolName;\n}\n\n/**\n * 会话源的轻量视图:只需要目录遍历 + 小 JSON 文件(state/metadata)即可得出,\n * 不触碰 transcript。枚举路径(listSessionSources)每次刷新都会跑,只用这一层。\n */\ninterface SessionSource {\n id: string;\n sourcePath: string;\n cwd: string;\n contextFile: string | null;\n wireFile: string | null;\n createdAt: number;\n activityAt: number;\n metaFile: string;\n explicitTitle: string;\n}\n\ninterface SessionMeta extends SessionCacheMeta, SessionSource {\n title: string;\n sourceMtimeMs: number;\n}\n\n/** Reads state/metadata `wire_mtime`; reports drift when the field is present but not a number. */\nfunction readWireMtime(record: Record<string, unknown>): number | null {\n return narrowField(\"kimi\", \"session.wire_mtime\", record.wire_mtime, asNumber) ?? null;\n}\n\n/** Reads a wire record's `timestamp`; reports drift when the field is present but not a number. */\nfunction readWireTimestamp(record: Record<string, unknown>): number {\n return narrowField(\"kimi\", \"wire.timestamp\", record.timestamp, asNumber) ?? 0;\n}\n\nfunction parseTimestamp(raw: unknown): number | null {\n return parseAgentTimestamp(raw, \"kimi\", { numericStrings: true });\n}\n\n/** Reads a token count from a usage record; reports drift when the field is present but not a number. */\nfunction extractTokenField(usage: Record<string, unknown>, field: string): number {\n return narrowField(\"kimi\", `usage.${field}`, usage[field], asNumber) ?? 0;\n}\n\nclass KimiUsageAccumulator {\n readonly stats: SessionDetail[\"stats\"] = {\n total_cost: 0,\n total_input_tokens: 0,\n total_output_tokens: 0,\n total_tokens: 0,\n message_count: 0,\n };\n\n private totalCost = 0;\n\n constructor(\n private readonly model: string | null,\n private readonly usesWireTotalFallback: boolean,\n ) {}\n\n applyContextRecord(record: Record<string, unknown>): void {\n if (record.role !== \"_usage\") return;\n const tokenCount = asNumber(record.token_count);\n if (tokenCount === undefined) {\n reportFieldMismatch(\"kimi\", \"usage.token_count\");\n return;\n }\n this.stats.total_tokens = tokenCount;\n }\n\n applyWireRecord(record: Record<string, unknown>) {\n if (this.usesWireTotalFallback) this.applyContextRecord(record);\n\n const tokenUsage = asRecord(asRecord(record.message)?.usage);\n if (!tokenUsage) return null;\n\n const inputTokens = extractTokenField(tokenUsage, \"input_tokens\");\n const outputTokens = extractTokenField(tokenUsage, \"output_tokens\");\n const cost = estimateTokenCost(this.model, { input: inputTokens, output: outputTokens });\n this.stats.total_input_tokens += inputTokens;\n this.stats.total_output_tokens += outputTokens;\n if (cost !== null) this.totalCost += cost;\n return { inputTokens, outputTokens, cost };\n }\n\n finish(): SessionDetail[\"stats\"] {\n const stats = { ...this.stats, total_cost: Number(this.totalCost.toFixed(8)) };\n if (stats.total_cost > 0) stats.cost_source = \"estimated\";\n return stats;\n }\n}\n\nfunction normalizeToolOutputParts(content: unknown, timestampMs: number): MessagePart[] {\n if (typeof content === \"string\") {\n const text = cleanInternalText(content);\n return text ? [{ type: \"text\" as const, text, time_created: timestampMs }] : [];\n }\n if (Array.isArray(content)) {\n const parts: MessagePart[] = [];\n for (const item of content) {\n const record = asRecord(item);\n if (record && \"text\" in record) {\n const text = String(record.text ?? \"\");\n const cleaned = cleanInternalText(text);\n if (cleaned) parts.push({ type: \"text\", text: cleaned, time_created: timestampMs });\n } else if (typeof item === \"string\") {\n const text = cleanInternalText(item);\n if (text) parts.push({ type: \"text\", text, time_created: timestampMs });\n }\n }\n return parts;\n }\n if (content == null) return [];\n const text = cleanInternalText(String(content));\n return text ? [{ type: \"text\", text, time_created: timestampMs }] : [];\n}\n\nfunction normalizeWireToolOutputParts(returnValue: unknown, timestampMs: number): MessagePart[] {\n if (returnValue == null) return [];\n if (typeof returnValue === \"string\") {\n const text = cleanInternalText(returnValue);\n return text ? [{ type: \"text\" as const, text, time_created: timestampMs }] : [];\n }\n if (typeof returnValue === \"object\") {\n const text = cleanInternalText(JSON.stringify(returnValue, null, 2));\n return text ? [{ type: \"text\", text, time_created: timestampMs }] : [];\n }\n const text = cleanInternalText(String(returnValue));\n return text ? [{ type: \"text\", text, time_created: timestampMs }] : [];\n}\n\nfunction kimiContentText(content: unknown): string {\n if (typeof content === \"string\") return content;\n if (!Array.isArray(content)) return \"\";\n\n return content\n .map((item) => {\n if (typeof item === \"string\") return item;\n const record = asRecord(item);\n if (record) return String(record.text ?? record.content ?? \"\");\n return \"\";\n })\n .join(\" \");\n}\n\nfunction extractFirstUserTitle(contextFile: string | null, wireFile: string | null): string | null {\n if (contextFile && existsSync(contextFile)) {\n for (const record of readJsonlFile(contextFile)) {\n if (record.role !== \"user\") continue;\n const title = normalizeTitleText(kimiContentText(record.content));\n if (title) return title;\n }\n }\n\n if (wireFile && existsSync(wireFile)) {\n for (const record of readJsonlFile(wireFile)) {\n const message = asRecord(record.message) ?? {};\n if (message.type !== \"TurnBegin\") continue;\n const payload = asRecord(message.payload) ?? {};\n const userInput = payload.user_input;\n if (!Array.isArray(userInput)) continue;\n const title = normalizeTitleText(kimiContentText(userInput));\n if (title) return title;\n }\n }\n\n return null;\n}\n\nconst AGENT_METADATA = getAgentCatalogEntry(\"kimi\");\n\nexport interface KimiAgentOptions extends AgentSourceOptions {\n projectDirectories?: ReadonlyMap<string, string>;\n defaultModel?: string | null;\n}\n\nexport class KimiAgent extends FileSystemSessionSource<SessionMeta> {\n readonly name = AGENT_METADATA.name;\n readonly displayName = AGENT_METADATA.displayName;\n\n private basePath: string | null;\n private projectMap: Map<string, string>;\n private defaultModel: string | null;\n\n constructor(options: KimiAgentOptions = {}) {\n super(options);\n this.basePath = this.configuredSourceRoot;\n this.projectMap = new Map(options.projectDirectories);\n this.defaultModel = options.defaultModel ?? null;\n }\n\n private findBasePath(): string | null {\n return (\n this.configuredSourceRoot ??\n firstExisting(join(resolveKimiDataRoot(), \"sessions\"), \"data/kimi\")\n );\n }\n\n getSessionWatchPlan() {\n if (this.configuredSourceRoot) {\n return {\n status: \"supported\" as const,\n targets: [{ root: dirname(this.configuredSourceRoot), path: this.configuredSourceRoot }],\n };\n }\n const dataRoot = resolveKimiDataRoot();\n return {\n status: \"supported\" as const,\n targets: [{ root: dataRoot, path: join(dataRoot, \"sessions\") }, { path: \"data/kimi\" }],\n };\n }\n\n /** Parse kimi.json and build md5(project_path) → cwd mapping */\n private loadKimiConfig(): void {\n const dataRoot = resolveKimiDataRoot();\n const configPath = join(dataRoot, \"kimi.json\");\n const tomlPath = join(dataRoot, \"config.toml\");\n if (existsSync(tomlPath)) {\n const configText = readFileSync(tomlPath, \"utf-8\");\n this.defaultModel = configText.match(/^default_model\\s*=\\s*\"([^\"]+)\"/m)?.[1] ?? null;\n }\n if (!existsSync(configPath)) return;\n try {\n const raw = asRecord(JSON.parse(readFileSync(configPath, \"utf-8\")));\n const workDirs = asArray(raw?.work_dirs);\n if (!workDirs) return;\n for (const wd of workDirs) {\n const path = asString(asRecord(wd)?.path);\n if (!path) continue;\n const hash = createHash(\"md5\").update(path).digest(\"hex\");\n this.projectMap.set(hash, path);\n }\n } catch {\n // ignore malformed config\n }\n }\n\n isAvailable(): boolean {\n this.basePath = this.findBasePath();\n if (!this.basePath) return false;\n this.loadKimiConfig();\n return this.listSessionDirs().length > 0;\n }\n\n /** Walk sessions/{project_hash}/{session_id}/ and find valid session dirs */\n private listSessionDirs(): string[] {\n if (!this.basePath) return [];\n const dirs: string[] = [];\n for (const hashEntry of this.readSessionSourceDirectory(this.basePath)) {\n if (!hashEntry.isDirectory()) continue;\n const hashPath = join(this.basePath, hashEntry.name);\n for (const sessionEntry of this.readSessionSourceDirectory(hashPath)) {\n if (!sessionEntry.isDirectory()) continue;\n const sessionPath = join(hashPath, sessionEntry.name);\n if (\n existsSync(join(sessionPath, \"metadata.json\")) ||\n existsSync(join(sessionPath, \"state.json\"))\n ) {\n dirs.push(sessionPath);\n }\n }\n }\n return dirs;\n }\n\n /**\n * 解析会话源,优先 state.json 而非 metadata.json。\n * 只读小 JSON 文件与 statSync,不触碰 transcript——枚举路径依赖这一点。\n */\n private resolveSessionSourceResult(sessionDir: string): ParseSessionResult<SessionSource> {\n const sessionId = basename(sessionDir);\n const projectHash = basename(dirname(sessionDir));\n const contextFile = join(sessionDir, \"context.jsonl\");\n const wireFile = join(sessionDir, \"wire.jsonl\");\n\n const existingContextFile = existsSync(contextFile) ? contextFile : null;\n const existingWireFile = existsSync(wireFile) ? wireFile : null;\n if (!existingContextFile && !existingWireFile) {\n return skippedSession(\"missing transcript\");\n }\n\n const statePath = join(sessionDir, \"state.json\");\n const metaPath = join(sessionDir, \"metadata.json\");\n const metaFile = existsSync(statePath) ? statePath : existsSync(metaPath) ? metaPath : \"\";\n let metadata: Record<string, unknown> = {};\n\n if (metaFile) {\n const content = this.scanStep(\"reading session metadata\", metaFile, () =>\n readFileSync(metaFile, \"utf-8\"),\n );\n try {\n metadata = asRecord(JSON.parse(content)) ?? {};\n } catch {\n return skippedSession(\"malformed metadata\");\n }\n }\n\n const explicitTitle = String(\n metaFile === statePath ? (metadata.custom_title ?? \"\") : (metadata.title ?? \"\"),\n );\n const wireMtime = readWireMtime(metadata);\n const [sessionStat, contextMtimeMs, wireMtimeMs] = this.scanStep(\n \"reading session source metadata\",\n sessionDir,\n () => {\n const sessionStat = statSync(sessionDir);\n return [\n sessionStat,\n existingContextFile ? statSync(existingContextFile).mtimeMs : 0,\n existingWireFile ? statSync(existingWireFile).mtimeMs : 0,\n ] as const;\n },\n );\n const createdAt =\n parseTimestamp(metadata.createdAt) ??\n parseTimestamp(metadata.created_at) ??\n (sessionStat.birthtimeMs > 0 ? sessionStat.birthtimeMs : sessionStat.ctimeMs);\n const activityAt = Math.max(\n createdAt,\n wireMtime === null ? 0 : wireMtime * 1000,\n contextMtimeMs,\n wireMtimeMs,\n );\n\n return parsedSession({\n id: sessionId,\n sourcePath: sessionDir,\n cwd: this.projectMap.get(projectHash) || \"\",\n contextFile: existingContextFile,\n wireFile: existingWireFile,\n createdAt,\n activityAt,\n metaFile,\n explicitTitle,\n });\n }\n\n /**\n * 在会话源之上补齐 title。仅当 state/metadata 里没有可用标题时才回退去读\n * transcript 找首条用户消息,所以标题解析的成本只在真正需要重解析时付出。\n */\n private parseSessionDirResult(sessionDir: string): ParseSessionResult<SessionMeta> {\n const result = this.resolveSessionSourceResult(sessionDir);\n if (result.status !== \"parsed\") return result;\n\n const source = result.data;\n const title =\n normalizeTitleText(source.explicitTitle) ??\n resolveSessionTitle(null, extractFirstUserTitle(source.contextFile, source.wireFile), null);\n\n return parsedSession({ ...source, title, sourceMtimeMs: source.activityAt });\n }\n\n listSessionSources(options?: AgentScanOptions): SessionSourceRef[] {\n if (!this.basePath) return [];\n const refs: SessionSourceRef[] = [];\n for (const dir of this.listSessionDirs()) {\n const source = getParsedSession(this.resolveSessionSourceResult(dir));\n if (!source || !matchesScanWindow(source.activityAt, options)) continue;\n refs.push({\n sessionId: source.id,\n sourcePath: source.sourcePath,\n fingerprint: this.sourceFingerprint(source),\n });\n }\n return refs;\n }\n\n protected override scanSessionSourceResult(\n source: SessionSourceRef,\n ): ParseSessionResult<SessionHead> {\n return this.parseSessionHeadResult(source.sourcePath);\n }\n\n private parseSessionHeadResult(sourcePath: string): ParseSessionResult<SessionHead> {\n const result = this.parseSessionDirResult(sourcePath);\n if (result.status !== \"parsed\") return result;\n const meta = result.data;\n meta.sourceFingerprint = this.sourceFingerprint(meta);\n this.sessionMetaMap.set(meta.id, meta);\n const stats = this.extractStats(meta.sourcePath);\n return parsedSession({\n ...this.sessionIdentity(meta.id),\n title: meta.title,\n directory: meta.cwd,\n time_created: meta.createdAt,\n time_updated: meta.activityAt,\n stats,\n });\n }\n\n getSessionData(sessionId: string): SessionDetail {\n const meta = this.sessionMetaMap.get(sessionId);\n if (!meta) throw new Error(`Session not found: ${sessionId}`);\n\n if (meta.contextFile) {\n return this.getSessionDataFromContext(meta);\n }\n return this.getSessionDataFromWire(meta);\n }\n\n private getSessionDataFromContext(meta: SessionMeta): SessionDetail {\n if (!meta.contextFile) throw new Error(\"context.jsonl is missing\");\n\n const builder = new TranscriptBuilder();\n const ignoredToolCallIds = new Set<string>();\n const accumulator = new KimiUsageAccumulator(this.defaultModel, false);\n\n let seq = 0;\n const fallbackTs = meta.createdAt;\n for (const record of readJsonlFile(meta.contextFile)) {\n seq++;\n accumulator.applyContextRecord(record);\n try {\n const role = String(record.role ?? \"\");\n if (role === \"_checkpoint\" || role === \"_usage\" || isInternalEventType(role)) continue;\n\n if (role === \"user\") {\n const text = cleanInternalText(kimiContentText(record.content));\n if (text) {\n builder.appendMessage({\n id: `context-${seq}`,\n role: \"user\",\n timestampMs: fallbackTs,\n parts: [{ type: \"text\", text, time_created: fallbackTs }],\n });\n }\n continue;\n }\n\n if (role === \"assistant\") {\n const message = this.buildContextAssistantMessage(\n record,\n seq,\n ignoredToolCallIds,\n fallbackTs,\n );\n if (!message) continue;\n builder.appendMessage(message);\n continue;\n }\n\n if (role === \"tool\") {\n const callId = String(record.tool_call_id ?? \"\").trim();\n if (callId && ignoredToolCallIds.has(callId)) continue;\n const outputParts = normalizeToolOutputParts(record.content, fallbackTs);\n if (callId && this.backfillToolOutput(builder, callId, outputParts)) {\n continue;\n }\n if (outputParts.length > 0) {\n builder.appendMessage({\n id: `context-${seq}`,\n role: \"tool\",\n timestampMs: fallbackTs,\n parts: outputParts,\n });\n }\n }\n } catch {\n // skip\n }\n }\n\n this.collectWireUsage(meta.sourcePath, accumulator);\n return this.buildSessionData(meta, builder, accumulator.finish());\n }\n\n private getSessionDataFromWire(meta: SessionMeta): SessionDetail {\n const wirePath = meta.wireFile ?? join(meta.sourcePath, \"wire.jsonl\");\n if (!existsSync(wirePath)) throw new Error(\"wire.jsonl is missing\");\n\n const builder = new TranscriptBuilder();\n const ignoredToolCallIds = new Set<string>();\n const openToolArgumentBuffer = new Map<string, string>();\n const accumulator = new KimiUsageAccumulator(this.defaultModel, true);\n\n let openToolCallId: string | null = null;\n let seq = 0;\n\n for (const record of readJsonlFile(wirePath)) {\n seq++;\n try {\n const tokenUsage = accumulator.applyWireRecord(record);\n const message = asRecord(record.message) ?? {};\n const msgType = asString(message.type) ?? \"\";\n if (isInternalEventType(msgType)) continue;\n const payload = asRecord(message.payload) ?? {};\n const timestampMs = Math.floor(readWireTimestamp(record) * 1000);\n\n // Bind usage to the most recent assistant message without tokens\n if (tokenUsage && (tokenUsage.inputTokens || tokenUsage.outputTokens)) {\n const tokens = { input: tokenUsage.inputTokens, output: tokenUsage.outputTokens };\n builder.attachUsageToLatestAssistant(tokens, {\n model: this.defaultModel,\n cost: tokenUsage.cost ?? undefined,\n costSource: tokenUsage.cost === null ? undefined : \"estimated\",\n });\n }\n\n if (msgType === \"TurnBegin\") {\n const userInput = payload.user_input;\n if (Array.isArray(userInput) && userInput.length > 0) {\n const text = cleanInternalText(kimiContentText(userInput));\n if (text) {\n builder.appendMessage({\n id: `wire-${seq}`,\n role: \"user\",\n timestampMs,\n parts: [{ type: \"text\", text, time_created: timestampMs }],\n });\n }\n }\n builder.beginTurn();\n openToolCallId = null;\n continue;\n }\n\n if (msgType === \"ContentPart\") {\n const partType = String(payload.type ?? \"\");\n if (partType === \"think\") {\n const text = cleanInternalText(String(payload.think ?? \"\"));\n if (text) {\n builder.appendAssistantPart(\n { type: \"reasoning\", text, time_created: timestampMs },\n { id: `wire-${seq}`, timestampMs, agent: \"kimi\" },\n { grouping: \"current\" },\n );\n }\n } else if (partType === \"text\") {\n const text = cleanInternalText(String(payload.text ?? \"\"));\n if (text) {\n builder.appendAssistantPart(\n { type: \"text\", text, time_created: timestampMs },\n { id: `wire-${seq}`, timestampMs, agent: \"kimi\" },\n { grouping: \"current\" },\n );\n }\n }\n continue;\n }\n\n if (msgType === \"ToolCall\") {\n const function_ = asRecord(payload.function);\n const toolName = String(function_?.name ?? \"\").trim();\n const callId = String(payload.id ?? \"\").trim();\n\n if (toolName && callId && KIMI_IGNORED_TOOLS.has(toolName)) {\n ignoredToolCallIds.add(callId);\n openToolCallId = callId;\n continue;\n }\n\n if (!function_ || !callId || !toolName) continue;\n\n const rawArgs = function_.arguments;\n const normalizedArgs = normalizeToolArguments(rawArgs);\n const buffer =\n typeof rawArgs === \"string\" && typeof normalizedArgs !== \"string\" ? rawArgs : null;\n\n const toolPart: MessagePart = {\n type: \"tool\",\n tool: toolName,\n callID: callId,\n title: mapToolTitle(toolName),\n state: { status: \"running\", input: normalizedArgs, output: null },\n time_created: timestampMs,\n };\n\n builder.appendToolCall(\n toolPart,\n { id: `wire-${seq}`, timestampMs, agent: \"kimi\" },\n { markModeAsTool: true, target: \"current\" },\n );\n openToolCallId = callId;\n\n if (buffer !== null) {\n openToolArgumentBuffer.set(callId, buffer);\n }\n continue;\n }\n\n if (msgType === \"ToolCallPart\") {\n if (openToolCallId && ignoredToolCallIds.has(openToolCallId)) continue;\n const argumentsPart = String(payload.arguments_part ?? \"\");\n this.appendWireToolCallPart(\n argumentsPart,\n openToolCallId,\n openToolArgumentBuffer,\n builder,\n );\n continue;\n }\n\n if (msgType === \"ToolResult\") {\n const callId = String(payload.tool_call_id ?? \"\").trim();\n if (callId && ignoredToolCallIds.has(callId)) continue;\n const outputParts = normalizeWireToolOutputParts(payload.return_value, timestampMs);\n if (callId && this.backfillToolOutput(builder, callId, outputParts)) {\n continue;\n }\n if (outputParts.length > 0) {\n builder.appendMessage({\n id: `wire-${seq}`,\n role: \"tool\",\n timestampMs,\n parts: outputParts,\n });\n }\n continue;\n }\n\n // Skip StepBegin, StatusUpdate, ApprovalRequest, ApprovalResponse, TurnEnd\n } catch {\n // skip\n }\n }\n\n return this.buildSessionData(meta, builder, accumulator.finish());\n }\n\n // --- Helpers ---\n\n private sourceFingerprint(meta: Pick<SessionSource, \"metaFile\" | \"contextFile\" | \"wireFile\">) {\n return JSON.stringify([\n KIMI_PARSER_REVISION,\n ...this.fileSnapshot(meta.metaFile),\n ...this.fileSnapshot(meta.contextFile),\n ...this.fileSnapshot(meta.wireFile),\n ]);\n }\n\n private fileSnapshot(filePath: string | null): [number | null, number | null] {\n if (!filePath) return [null, null];\n try {\n const stat = statSync(filePath);\n return [stat.mtimeMs, stat.size];\n } catch {\n return [null, null];\n }\n }\n\n private buildContextAssistantMessage(\n record: Record<string, unknown>,\n seq: number,\n ignoredToolCallIds: Set<string>,\n fallbackTs: number,\n ): TranscriptMessageInput | null {\n const parts: MessagePart[] = [];\n\n const content = record.content;\n if (Array.isArray(content)) {\n for (const item of content) {\n const ci = asRecord(item);\n if (!ci) continue;\n const partType = String(ci.type ?? \"\");\n\n if (partType === \"think\") {\n const text = cleanInternalText(String(ci.think ?? \"\"));\n if (text) parts.push({ type: \"reasoning\", text, time_created: fallbackTs });\n } else if (partType === \"text\") {\n const text = cleanInternalText(String(ci.text ?? \"\"));\n if (text) parts.push({ type: \"text\", text, time_created: fallbackTs });\n }\n }\n }\n\n const toolCalls = asArray(record.tool_calls);\n if (toolCalls) {\n for (const tc of toolCalls) {\n const tcRecord = asRecord(tc);\n const function_ = asRecord(tcRecord?.function);\n\n if (!function_) continue;\n const toolName = String(function_.name ?? \"\").trim();\n const callId = String(tcRecord?.id ?? \"\").trim();\n\n if (toolName && callId && KIMI_IGNORED_TOOLS.has(toolName)) {\n ignoredToolCallIds.add(callId);\n continue;\n }\n\n if (!toolName || !callId) continue;\n\n const part: MessagePart = {\n type: \"tool\",\n tool: toolName,\n callID: callId,\n title: mapToolTitle(toolName),\n state: {\n status: \"running\",\n input: normalizeToolArguments(function_.arguments),\n output: null,\n },\n time_created: fallbackTs,\n };\n parts.push(part);\n }\n }\n\n if (parts.length === 0) {\n return null;\n }\n\n const allTools = parts.every((p) => p.type === \"tool\");\n return {\n id: `context-${seq}`,\n role: \"assistant\",\n timestampMs: fallbackTs,\n parts,\n agent: \"kimi\",\n mode: allTools ? \"tool\" : undefined,\n };\n }\n\n private appendWireToolCallPart(\n argumentsPart: string,\n openCallId: string | null,\n buffer: Map<string, string>,\n builder: TranscriptBuilder,\n ): void {\n if (!openCallId) return;\n\n const existing = buffer.get(openCallId) ?? \"\";\n const combined = existing + argumentsPart;\n\n try {\n const parsed: unknown = JSON.parse(combined);\n if (\n builder.updateToolCall(openCallId, (part) => {\n part.state.input = parsed;\n })\n ) {\n buffer.delete(openCallId);\n }\n } catch {\n buffer.set(openCallId, combined);\n }\n }\n\n private backfillToolOutput(\n builder: TranscriptBuilder,\n callId: string,\n outputParts: MessagePart[],\n ): boolean {\n if (!outputParts.length || !callId) return false;\n\n return builder.resolveToolCall(callId, { output: [...outputParts] });\n }\n\n private extractStats(sessionDir: string): SessionDetail[\"stats\"] {\n const contextPath = join(sessionDir, \"context.jsonl\");\n const hasContext = existsSync(contextPath);\n const accumulator = new KimiUsageAccumulator(this.defaultModel, !hasContext);\n\n if (hasContext) {\n try {\n for (const record of readJsonlFile(contextPath)) accumulator.applyContextRecord(record);\n } catch {\n // skip unreadable context logs\n }\n }\n\n this.collectWireUsage(sessionDir, accumulator);\n return accumulator.finish();\n }\n\n private collectWireUsage(sessionDir: string, accumulator: KimiUsageAccumulator): void {\n const wirePath = join(sessionDir, \"wire.jsonl\");\n if (existsSync(wirePath)) {\n try {\n for (const record of readJsonlFile(wirePath)) accumulator.applyWireRecord(record);\n } catch {\n // skip unreadable wire logs\n }\n }\n }\n\n private buildSessionData(\n meta: SessionMeta,\n builder: TranscriptBuilder,\n stats: SessionDetail[\"stats\"],\n ): SessionDetail {\n const transcript = builder.finish(stats);\n return {\n ...this.sessionIdentity(meta.id),\n title: meta.title,\n directory: meta.cwd,\n time_created: meta.createdAt,\n time_updated: meta.activityAt,\n stats: transcript.stats,\n messages: transcript.messages,\n };\n }\n}\n","export function normalizeToolArguments(raw: unknown): unknown {\n if (typeof raw !== \"string\") return raw;\n try {\n return JSON.parse(raw);\n } catch {\n return raw;\n }\n}\n","import { existsSync, readFileSync, statSync } from \"node:fs\";\nimport { basename, dirname, join, resolve } from \"node:path\";\nimport { getAgentCatalogEntry } from \"../contract/agent-catalog.js\";\nimport {\n FileSystemSessionSource,\n filteredSession,\n getParsedSession,\n matchesScanWindow,\n parsedSession,\n skippedSession,\n} from \"./base.js\";\nimport type {\n AgentScanOptions,\n ParseSessionResult,\n SessionCacheMeta,\n SessionSourceRef,\n} from \"./base.js\";\nimport type {\n MessagePart,\n SessionDetail,\n SessionHead,\n SessionStats,\n ToolPart,\n} from \"../types/index.js\";\nimport { resolveHomePath } from \"../discovery/paths.js\";\nimport { readJsonlFile } from \"../utils/jsonl.js\";\nimport { asArray, asNumber, asRecord, asString } from \"../utils/narrow.js\";\nimport { parseAgentTimestamp } from \"../utils/timestamp.js\";\nimport { cleanInternalText } from \"../utils/session-normalization.js\";\nimport { normalizeTitleText, resolveSessionTitle } from \"../utils/title-fallback.js\";\nimport { estimateTokenCost } from \"../utils/cost.js\";\nimport { TranscriptBuilder, type TranscriptMessageInput } from \"./transcript-builder.js\";\nimport { normalizeToolArguments } from \"./tool-arguments.js\";\n\nconst KIMI_CODE_TOOL_TITLE_MAP: Record<string, string> = {\n Read: \"read\",\n Write: \"write\",\n Edit: \"edit\",\n Bash: \"bash\",\n TodoList: \"todo\",\n AskUserQuestion: \"ask\",\n EnterPlanMode: \"plan mode\",\n ExitPlanMode: \"plan approved\",\n ReadFile: \"read\",\n Glob: \"glob\",\n StrReplaceFile: \"edit\",\n Grep: \"grep\",\n WriteFile: \"write\",\n Shell: \"bash\",\n};\n\nconst KIMI_CODE_IGNORED_TOOLS = new Set([\"SetTodoList\"]);\nconst KIMI_CODE_PARSER_REVISION = \"kimi-code-parser-v2\";\n\nexport function resolveKimiCodeDataRoot(): string {\n return resolveHomePath(\"KIMI_CODE_HOME\", \".kimi-code\");\n}\n\ninterface SessionSource {\n id: string;\n sourcePath: string;\n stateFile: string;\n wireFile: string;\n workDir: string;\n createdAt: number;\n activityAt: number;\n stateMtimeMs: number;\n stateSize: number;\n wireMtimeMs: number;\n wireSize: number;\n explicitTitle: string;\n}\n\ninterface SessionMeta extends SessionCacheMeta {\n wireFile: string;\n workDir: string;\n createdAt: number;\n activityAt: number;\n title: string;\n sourceMtimeMs: number;\n}\n\ninterface UsageTotals {\n totalCost: number;\n totalInputTokens: number;\n totalOutputTokens: number;\n totalCacheReadTokens: number;\n totalCacheCreateTokens: number;\n modelUsage: Record<string, number>;\n}\n\ninterface ParsedWire {\n builder: TranscriptBuilder;\n stats: SessionStats;\n firstUserTitle: string | null;\n modelUsage: Record<string, number>;\n}\n\nfunction mapToolTitle(toolName: string): string {\n return KIMI_CODE_TOOL_TITLE_MAP[toolName] ?? toolName;\n}\n\nfunction parseTimestamp(raw: unknown): number | null {\n return parseAgentTimestamp(raw, \"kimi-code\", { numericStrings: true });\n}\n\nfunction timestampFromRecord(record: Record<string, unknown>): number {\n return parseTimestamp(record.time) ?? 0;\n}\n\nfunction contentText(content: unknown): string {\n if (typeof content === \"string\") return content;\n if (!Array.isArray(content)) {\n const record = asRecord(content);\n return record ? String(record.text ?? \"\") : \"\";\n }\n\n return content\n .map((item) => {\n if (typeof item === \"string\") return item;\n const record = asRecord(item);\n return record ? String(record.text ?? \"\") : \"\";\n })\n .join(\" \");\n}\n\nfunction contentParts(content: unknown, timestampMs: number): MessagePart[] {\n const values = Array.isArray(content) ? content : [content];\n const parts: MessagePart[] = [];\n\n for (const value of values) {\n if (typeof value === \"string\") {\n const text = cleanInternalText(value);\n if (text) parts.push({ type: \"text\", text, time_created: timestampMs });\n continue;\n }\n\n const record = asRecord(value);\n if (!record) continue;\n const type = asString(record.type) ?? \"\";\n if (type === \"text\") {\n const text = cleanInternalText(asString(record.text) ?? \"\");\n if (text) parts.push({ type: \"text\", text, time_created: timestampMs });\n continue;\n }\n if (type === \"think\") {\n const text = cleanInternalText(asString(record.think) ?? \"\");\n if (text) parts.push({ type: \"reasoning\", text, time_created: timestampMs });\n continue;\n }\n if (type === \"plan\") {\n const text = cleanInternalText(asString(record.text) ?? \"\");\n if (text) {\n parts.push({\n type: \"plan\",\n text,\n approval_status: record.approved === false ? \"fail\" : \"success\",\n time_created: timestampMs,\n });\n }\n continue;\n }\n if (type === \"image\") {\n const source = asRecord(record.source);\n const imageUrl = asRecord(record.imageUrl);\n const url =\n asString(record.url) ??\n asString(imageUrl?.url) ??\n (source?.kind === \"url\" ? asString(source.url) : undefined);\n const data =\n asString(record.data) ?? (source?.kind === \"base64\" ? asString(source.data) : undefined);\n const mimeType =\n asString(record.mime_type) ??\n asString(record.media_type) ??\n (source?.kind === \"base64\" ? asString(source.media_type) : undefined) ??\n \"application/octet-stream\";\n if (url) parts.push({ type: \"image\", url, mime_type: mimeType, time_created: timestampMs });\n else if (data) {\n parts.push({\n type: \"image\",\n data,\n mime_type: mimeType,\n time_created: timestampMs,\n });\n }\n continue;\n }\n if (type === \"image_url\") {\n const imageUrl = asRecord(record.imageUrl);\n const url = asString(imageUrl?.url) ?? asString(record.url);\n if (url) parts.push({ type: \"image\", url, time_created: timestampMs });\n }\n }\n\n return parts;\n}\n\nfunction toolOutputParts(output: unknown, timestampMs: number): MessagePart[] {\n if (typeof output === \"string\") {\n const text = cleanInternalText(output);\n return text ? [{ type: \"text\", text, time_created: timestampMs }] : [];\n }\n if (Array.isArray(output)) return contentParts(output, timestampMs);\n if (output == null) return [];\n\n const record = asRecord(output);\n if (record?.type === \"text\") return contentParts([record], timestampMs);\n\n const text = cleanInternalText(JSON.stringify(output, null, 2));\n return text ? [{ type: \"text\", text, time_created: timestampMs }] : [];\n}\n\nfunction toolPart(toolName: string, callId: string, input: unknown, timestampMs: number): ToolPart {\n return {\n type: \"tool\",\n tool: toolName,\n callID: callId,\n title: mapToolTitle(toolName),\n state: {\n status: \"running\",\n ...(input === undefined ? {} : { input }),\n output: null,\n },\n time_created: timestampMs,\n };\n}\n\nfunction toolCallParts(\n message: Record<string, unknown>,\n timestampMs: number,\n ignoredToolCallIds: Set<string>,\n): MessagePart[] {\n const calls = asArray(message.toolCalls) ?? [];\n const parts: MessagePart[] = [];\n\n for (const call of calls) {\n const callRecord = asRecord(call);\n const functionRecord = asRecord(callRecord?.function) ?? callRecord;\n const toolName = asString(functionRecord?.name)?.trim() ?? \"\";\n const callId = asString(callRecord?.id)?.trim() ?? \"\";\n if (!toolName || !callId) continue;\n if (KIMI_CODE_IGNORED_TOOLS.has(toolName)) {\n ignoredToolCallIds.add(callId);\n continue;\n }\n\n const rawArguments = functionRecord?.arguments ?? callRecord?.arguments;\n parts.push(toolPart(toolName, callId, normalizeToolArguments(rawArguments), timestampMs));\n }\n\n return parts;\n}\n\nfunction addToolResolution(\n builder: TranscriptBuilder,\n callId: string,\n output: unknown,\n timestampMs: number,\n isError = false,\n note?: string,\n): boolean {\n const outputParts = toolOutputParts(output, timestampMs);\n return builder.resolveToolCall(callId, {\n output: outputParts,\n status: isError ? \"error\" : \"completed\",\n ...(note ? { metadata: { note: cleanInternalText(note) } } : {}),\n });\n}\n\nfunction usageNumber(usage: Record<string, unknown>, field: string): number {\n return asNumber(usage[field]) ?? 0;\n}\n\nfunction emptyStats(): SessionStats {\n return {\n message_count: 0,\n total_input_tokens: 0,\n total_output_tokens: 0,\n total_cost: 0,\n };\n}\n\nfunction buildUsageTotals(): UsageTotals {\n return {\n totalCost: 0,\n totalInputTokens: 0,\n totalOutputTokens: 0,\n totalCacheReadTokens: 0,\n totalCacheCreateTokens: 0,\n modelUsage: {},\n };\n}\n\nfunction applyUsage(\n builder: TranscriptBuilder,\n record: Record<string, unknown>,\n activeModel: string | null,\n totals: UsageTotals,\n): void {\n const usage = asRecord(record.usage);\n if (!usage) return;\n\n const cacheRead = usageNumber(usage, \"inputCacheRead\");\n const cacheCreate = usageNumber(usage, \"inputCacheCreation\");\n const inputOther = usageNumber(usage, \"inputOther\");\n const output = usageNumber(usage, \"output\");\n const input = inputOther + cacheRead + cacheCreate;\n const model = asString(record.model) ?? activeModel;\n const tokens = {\n input,\n output,\n cache_read: cacheRead,\n cache_create: cacheCreate,\n };\n const cost = estimateTokenCost(model, tokens);\n\n totals.totalInputTokens += input;\n totals.totalOutputTokens += output;\n totals.totalCacheReadTokens += cacheRead;\n totals.totalCacheCreateTokens += cacheCreate;\n if (model) totals.modelUsage[model] = (totals.modelUsage[model] ?? 0) + input + output;\n if (cost !== null) totals.totalCost += cost;\n\n builder.attachUsageToLatestAssistant(tokens, {\n model,\n cost: cost ?? undefined,\n costSource: cost === null ? undefined : \"estimated\",\n });\n}\n\nfunction parseState(content: string): Record<string, unknown> | null {\n try {\n return asRecord(JSON.parse(content)) ?? null;\n } catch {\n return null;\n }\n}\n\nconst AGENT_METADATA = getAgentCatalogEntry(\"kimi-code\");\n\nexport class KimiCodeAgent extends FileSystemSessionSource<SessionMeta> {\n readonly name = AGENT_METADATA.name;\n readonly displayName = AGENT_METADATA.displayName;\n\n private basePath: string | null = this.configuredSourceRoot;\n private workDirBySessionPath = new Map<string, string>();\n\n private findBasePath(): string | null {\n if (this.configuredSourceRoot) return this.configuredSourceRoot;\n const sessionsPath = join(resolveKimiCodeDataRoot(), \"sessions\");\n return existsSync(sessionsPath) ? sessionsPath : null;\n }\n\n getSessionWatchPlan() {\n if (this.configuredSourceRoot) {\n const root = dirname(this.configuredSourceRoot);\n return {\n status: \"supported\" as const,\n targets: [\n { root, path: this.configuredSourceRoot },\n { root, path: join(root, \"session_index.jsonl\") },\n ],\n };\n }\n const dataRoot = resolveKimiCodeDataRoot();\n return {\n status: \"supported\" as const,\n targets: [\n { root: dataRoot, path: join(dataRoot, \"sessions\") },\n { root: dataRoot, path: join(dataRoot, \"session_index.jsonl\") },\n ],\n };\n }\n\n isAvailable(): boolean {\n this.basePath = this.findBasePath();\n if (!this.basePath) return false;\n return this.listSessionDirs().length > 0;\n }\n\n private loadSessionIndex(): void {\n this.workDirBySessionPath.clear();\n if (!this.basePath) return;\n\n const indexPath = join(dirname(this.basePath), \"session_index.jsonl\");\n if (!existsSync(indexPath)) return;\n for (const record of readJsonlFile(indexPath)) {\n const sessionPath = asString(record.sessionDir);\n const workDir = asString(record.workDir);\n if (!sessionPath || !workDir) continue;\n this.workDirBySessionPath.set(resolve(sessionPath), workDir);\n }\n }\n\n private listSessionDirs(): string[] {\n if (!this.basePath) return [];\n const dirs: string[] = [];\n\n for (const bucket of this.readSessionSourceDirectory(this.basePath)) {\n if (!bucket.isDirectory()) continue;\n const bucketPath = join(this.basePath, bucket.name);\n for (const session of this.readSessionSourceDirectory(bucketPath)) {\n if (!session.isDirectory()) continue;\n const sessionPath = join(bucketPath, session.name);\n if (\n existsSync(join(sessionPath, \"state.json\")) &&\n existsSync(join(sessionPath, \"agents\", \"main\", \"wire.jsonl\"))\n ) {\n dirs.push(sessionPath);\n }\n }\n }\n\n return dirs;\n }\n\n private resolveSessionSourceResult(sessionDir: string): ParseSessionResult<SessionSource> {\n const stateFile = join(sessionDir, \"state.json\");\n const wireFile = join(sessionDir, \"agents\", \"main\", \"wire.jsonl\");\n if (!existsSync(stateFile) || !existsSync(wireFile)) return skippedSession(\"missing wire\");\n\n const content = this.scanStep(\"reading session state\", stateFile, () =>\n readFileSync(stateFile, \"utf-8\"),\n );\n const state = parseState(content);\n if (!state) return skippedSession(\"malformed state\");\n\n const [stateStat, wireStat] = this.scanStep(\n \"reading session source metadata\",\n sessionDir,\n () => [statSync(stateFile), statSync(wireFile)] as const,\n );\n const createdAt =\n parseTimestamp(state.createdAt) ?? parseTimestamp(state.created_at) ?? stateStat.mtimeMs;\n const activityAt = Math.max(\n parseTimestamp(state.updatedAt) ?? parseTimestamp(state.updated_at) ?? createdAt,\n wireStat.mtimeMs,\n );\n const custom = asRecord(state.custom);\n const workDir =\n asString(state.workDir) ??\n asString(custom?.cwd) ??\n this.workDirBySessionPath.get(resolve(sessionDir)) ??\n \"\";\n const explicitTitle = asString(state.title) ?? asString(state.customTitle) ?? \"\";\n\n return parsedSession({\n id: basename(sessionDir),\n sourcePath: sessionDir,\n stateFile,\n wireFile,\n workDir,\n createdAt,\n activityAt,\n stateMtimeMs: stateStat.mtimeMs,\n stateSize: stateStat.size,\n wireMtimeMs: wireStat.mtimeMs,\n wireSize: wireStat.size,\n explicitTitle,\n });\n }\n\n private sourceFingerprint(source: SessionSource): string {\n return JSON.stringify([\n KIMI_CODE_PARSER_REVISION,\n source.stateMtimeMs,\n source.stateSize,\n source.wireMtimeMs,\n source.wireSize,\n source.createdAt,\n source.activityAt,\n source.workDir,\n source.explicitTitle,\n ]);\n }\n\n listSessionSources(options?: AgentScanOptions): SessionSourceRef[] {\n if (!this.basePath) return [];\n this.loadSessionIndex();\n const refs: SessionSourceRef[] = [];\n\n for (const sessionDir of this.listSessionDirs()) {\n const source = getParsedSession(this.resolveSessionSourceResult(sessionDir));\n if (!source || !matchesScanWindow(source.activityAt, options)) continue;\n refs.push({\n sessionId: source.id,\n sourcePath: source.sourcePath,\n fingerprint: this.sourceFingerprint(source),\n });\n }\n\n return refs;\n }\n\n filterCachedSessions(sessions: SessionHead[]): SessionHead[] {\n return this.removeEmptyCachedSessions(sessions);\n }\n\n private hasMessages(session: SessionHead): boolean {\n return session.stats.message_count > 0;\n }\n\n private removeEmptyCachedSessions(sessions: SessionHead[]): SessionHead[] {\n return sessions.filter((session) => {\n if (this.hasMessages(session)) return true;\n this.sessionMetaMap.delete(session.reference.sessionId);\n return false;\n });\n }\n\n protected override scanSessionSourceResult(\n source: SessionSourceRef,\n ): ParseSessionResult<SessionHead> {\n return this.parseSessionHeadResult(source.sourcePath);\n }\n\n private parseSessionHeadResult(sourcePath: string): ParseSessionResult<SessionHead> {\n this.loadSessionIndex();\n const result = this.resolveSessionSourceResult(sourcePath);\n if (result.status !== \"parsed\") return result;\n const source = result.data;\n\n const parsed = this.parseWire(source, \"head\");\n const transcript = parsed.builder.finish(parsed.stats);\n if (transcript.messages.length === 0) {\n this.sessionMetaMap.delete(source.id);\n return filteredSession(\"no visible messages\");\n }\n\n const title = resolveSessionTitle(source.explicitTitle, parsed.firstUserTitle, null);\n const meta: SessionMeta = {\n id: source.id,\n sourcePath: source.sourcePath,\n wireFile: source.wireFile,\n workDir: source.workDir,\n createdAt: source.createdAt,\n activityAt: source.activityAt,\n title,\n sourceMtimeMs: source.activityAt,\n sourceFingerprint: this.sourceFingerprint(source),\n };\n this.sessionMetaMap.set(meta.id, meta);\n return parsedSession({\n ...this.sessionIdentity(meta.id),\n title: meta.title,\n directory: meta.workDir,\n time_created: meta.createdAt,\n time_updated: meta.activityAt,\n stats: transcript.stats,\n ...(Object.keys(parsed.modelUsage).length > 0 ? { model_usage: parsed.modelUsage } : {}),\n });\n }\n\n getSessionData(sessionId: string): SessionDetail {\n const meta = this.sessionMetaMap.get(sessionId);\n if (!meta) throw new Error(`Session not found: ${sessionId}`);\n\n const parsed = this.parseWire(meta);\n const transcript = parsed.builder.finish(parsed.stats);\n return {\n ...this.sessionIdentity(meta.id),\n title: meta.title,\n directory: meta.workDir,\n time_created: meta.createdAt,\n time_updated: meta.activityAt,\n stats: transcript.stats,\n messages: transcript.messages,\n };\n }\n\n private parseWire(\n source: Pick<SessionSource, \"wireFile\">,\n projection: \"head\" | \"detail\" = \"detail\",\n ): ParsedWire {\n const builder = new TranscriptBuilder({\n contentRetention: projection === \"head\" ? \"structure\" : \"full\",\n });\n const totals = buildUsageTotals();\n const ignoredToolCallIds = new Set<string>();\n let activeModel: string | null = null;\n let activeProvider: string | null = null;\n let firstUserTitle: string | null = null;\n let sequence = 0;\n\n for (const record of readJsonlFile(source.wireFile)) {\n sequence += 1;\n try {\n const timestampMs = timestampFromRecord(record);\n const recordType = asString(record.type) ?? \"\";\n\n if (recordType === \"llm.request\") {\n activeModel = asString(record.model) ?? activeModel;\n activeProvider = asString(record.provider) ?? activeProvider;\n continue;\n }\n if (recordType === \"config.update\") {\n activeModel = asString(record.modelAlias) ?? activeModel;\n continue;\n }\n if (recordType === \"usage.record\") {\n applyUsage(builder, record, activeModel, totals);\n continue;\n }\n if (recordType === \"context.append_message\") {\n const message = asRecord(record.message);\n if (!message) continue;\n const role = asString(message.role) ?? \"\";\n const messageTimestamp = timestampMs;\n\n if (role === \"user\") {\n const text = normalizeTitleText(contentText(message.content));\n if (!firstUserTitle && text) firstUserTitle = text;\n }\n\n if (role === \"tool\") {\n const callId = asString(message.toolCallId)?.trim() ?? \"\";\n const output = message.content;\n if (callId && ignoredToolCallIds.has(callId)) continue;\n if (callId && addToolResolution(builder, callId, output, messageTimestamp)) continue;\n const outputParts = toolOutputParts(output, messageTimestamp);\n if (outputParts.length > 0) {\n builder.appendMessage({\n id: `wire-${sequence}`,\n role: \"tool\",\n timestampMs: messageTimestamp,\n parts: outputParts,\n });\n }\n continue;\n }\n\n if (role !== \"user\" && role !== \"assistant\") continue;\n const parts = [\n ...contentParts(message.content, messageTimestamp),\n ...(role === \"assistant\"\n ? toolCallParts(message, messageTimestamp, ignoredToolCallIds)\n : []),\n ];\n if (parts.length === 0) continue;\n const allTools = parts.every((part) => part.type === \"tool\");\n const input: TranscriptMessageInput = {\n id: `wire-${sequence}`,\n role,\n timestampMs: messageTimestamp,\n parts,\n ...(role === \"assistant\"\n ? {\n agent: this.name,\n mode: allTools ? \"tool\" : undefined,\n model: activeModel,\n provider: activeProvider,\n }\n : {}),\n };\n builder.appendMessage(input);\n continue;\n }\n if (recordType === \"context.append_loop_event\") {\n const event = asRecord(record.event);\n if (!event) continue;\n const eventType = asString(event.type) ?? \"\";\n const metadata = {\n id: `wire-${sequence}`,\n timestampMs,\n agent: this.name,\n model: activeModel,\n provider: activeProvider,\n };\n\n if (eventType === \"step.begin\") {\n builder.beginTurn();\n continue;\n }\n if (eventType === \"content.part\") {\n const part = asRecord(event.part);\n if (!part) continue;\n const parts = contentParts([part], timestampMs);\n for (const contentPart of parts) {\n if (contentPart.type === \"tool\") continue;\n if (contentPart.type === \"image\" && builder.appendToCurrentAssistant(contentPart)) {\n continue;\n }\n builder.appendAssistantPart(contentPart, metadata, { grouping: \"current\" });\n }\n continue;\n }\n if (eventType === \"tool.call\") {\n const toolName = asString(event.name)?.trim() ?? \"\";\n const callId = asString(event.toolCallId)?.trim() ?? \"\";\n if (!toolName || !callId) continue;\n if (KIMI_CODE_IGNORED_TOOLS.has(toolName)) {\n ignoredToolCallIds.add(callId);\n continue;\n }\n builder.appendToolCall(toolPart(toolName, callId, event.args, timestampMs), metadata, {\n markModeAsTool: true,\n target: \"current\",\n });\n continue;\n }\n if (eventType === \"tool.result\") {\n const callId = asString(event.toolCallId)?.trim() ?? \"\";\n const result = asRecord(event.result);\n if (!callId || ignoredToolCallIds.has(callId)) continue;\n const output = result?.output;\n const isError = result?.isError === true;\n const note = asString(result?.note);\n if (addToolResolution(builder, callId, output, timestampMs, isError, note)) continue;\n const outputParts = toolOutputParts(output, timestampMs);\n if (outputParts.length > 0) {\n builder.appendMessage({\n id: `wire-${sequence}`,\n role: \"tool\",\n timestampMs,\n parts: outputParts,\n });\n }\n }\n continue;\n }\n if (recordType === \"context.apply_compaction\") {\n const summary = cleanInternalText(asString(record.summary) ?? \"\");\n if (summary) {\n builder.appendMessage({\n id: `wire-${sequence}`,\n role: \"user\",\n timestampMs,\n parts: [{ type: \"text\", text: summary, time_created: timestampMs }],\n });\n }\n }\n } catch {\n continue;\n }\n }\n\n const stats: SessionStats = {\n ...emptyStats(),\n total_input_tokens: totals.totalInputTokens,\n total_output_tokens: totals.totalOutputTokens,\n total_cost: Number(totals.totalCost.toFixed(8)),\n total_tokens: totals.totalInputTokens + totals.totalOutputTokens,\n ...(totals.totalCacheReadTokens > 0\n ? { total_cache_read_tokens: totals.totalCacheReadTokens }\n : {}),\n ...(totals.totalCacheCreateTokens > 0\n ? { total_cache_create_tokens: totals.totalCacheCreateTokens }\n : {}),\n ...(totals.totalCost > 0 ? { cost_source: \"estimated\" as const } : {}),\n };\n return { builder, stats, firstUserTitle, modelUsage: totals.modelUsage };\n }\n}\n","import { existsSync, readFileSync, statSync } from \"node:fs\";\nimport { join, basename, dirname } from \"node:path\";\nimport { getAgentCatalogEntry } from \"../contract/agent-catalog.js\";\nimport { SingleFileSessionSource, filteredSession, parsedSession, skippedSession } from \"./base.js\";\nimport type { ParseSessionResult } from \"./base.js\";\nimport type { Message, SessionHead, SessionDetail, MessagePart } from \"../types/index.js\";\nimport { firstExisting, resolveHomePath } from \"../discovery/paths.js\";\nimport { parseJsonlLines, readJsonlFile, readJsonlFileLines } from \"../utils/jsonl.js\";\nimport { basenameTitle, normalizeTitleText, resolveSessionTitle } from \"../utils/title-fallback.js\";\nimport { cleanInternalText, isInternalEventType } from \"../utils/session-normalization.js\";\nimport { getCoreDiagnostics } from \"../utils/diagnostics.js\";\nimport { asRecord, asString } from \"../utils/narrow.js\";\nimport { TranscriptBuilder } from \"./transcript-builder.js\";\nimport {\n CodexRecordConverter,\n extractAssistantOutputText,\n extractCodexPayload,\n isDeveloperLikeUserMessage,\n narrowRecordField,\n parseCodexTimestampMs,\n} from \"./codex-record-converter.js\";\nimport { CodexTokenUsageAccumulator } from \"./codex-token-usage.js\";\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst HEAD_INDEX_VERSION = \"codex-head-v2\";\nconst PARSER_VERSION = \"codex-parser-v8\";\n\nexport function resolveCodexDataRoot(): string {\n return resolveHomePath(\"CODEX_HOME\", \".codex\");\n}\n\n// ---------------------------------------------------------------------------\n// Session ID extraction\n// ---------------------------------------------------------------------------\n\n/**\n * Extract session UUID from Codex filename.\n * \"rollout-2026-02-03T10-04-47-019c213e-c251-73a3-af66-0ec9d7cb9e29.jsonl\"\n * → last 5 dash-delimited parts joined with \"-\"\n */\nfunction extractSessionId(filename: string): string {\n const stem = basename(filename, \".jsonl\");\n const parts = stem.split(\"-\");\n if (parts.length >= 5) {\n return parts.slice(-5).join(\"-\");\n }\n return stem;\n}\n\n// ---------------------------------------------------------------------------\n// Timestamp\n// ---------------------------------------------------------------------------\n\nfunction extractModelName(raw: unknown): string | null {\n return typeof raw === \"string\" && raw.trim() ? raw.trim() : null;\n}\n\ninterface ThreadMeta {\n threadSource: string;\n parentThreadId: string | null;\n agentNickname: string | null;\n}\n\nfunction extractThreadMeta(firstRecord: Record<string, unknown>): ThreadMeta | null {\n if (firstRecord[\"type\"] !== \"session_meta\") return null;\n const payload = extractCodexPayload(firstRecord);\n const threadSource = asString(payload[\"thread_source\"]) ?? \"\";\n const parentThreadId = asString(payload[\"parent_thread_id\"]) ?? null;\n const agentNickname = asString(payload[\"agent_nickname\"]) ?? null;\n return { threadSource, parentThreadId, agentNickname };\n}\n\n// Leading-line reads want a few KB, not the default 1 MiB streaming buffer;\n// readJsonlFileLines keeps accumulating chunks if a single line runs longer.\nconst LEADING_READ_CHUNK_BYTES = 64 * 1024;\n\nfunction readLeadingJsonlLines(filePath: string, limit: number): string[] {\n const lines: string[] = [];\n for (const line of readJsonlFileLines(filePath, LEADING_READ_CHUNK_BYTES)) {\n if (!line.trim()) continue;\n lines.push(line);\n if (lines.length === limit) break;\n }\n return lines;\n}\n\n// ---------------------------------------------------------------------------\n// Session meta\n// ---------------------------------------------------------------------------\n\nimport type {\n AgentScanOptions,\n FileSessionMeta,\n SessionCacheMeta,\n SessionSourceFile,\n SessionSourceRef,\n} from \"./base.js\";\n\n/** 一次全量前缀扫构建的 subagent 关系索引;miss 即代表\"无子会话\"。 */\ninterface SubagentIndex {\n childFilesByParent: Map<string, string[]>;\n subagentFiles: Set<string>;\n}\n\ninterface SessionMeta extends FileSessionMeta {\n indexPath: string | null;\n indexMtimeMs: number | null;\n headIndexVersion: string;\n parserVersion: string;\n isSubagent: boolean;\n parentThreadId: string | null;\n}\n\ninterface ChildSessionSummary {\n stats: SessionHead[\"stats\"];\n message: Message | null;\n}\n\ninterface ChildSessionSummaryCacheEntry extends ChildSessionSummary {\n sourceFingerprint: string;\n parserVersion: string;\n}\n\nclass ChildMessageVisibilityIndex {\n private readonly visibleSubagentIds = new Set<string>();\n private readonly visibleNicknameTexts = new Map<string, Set<string>>();\n\n constructor(messages: Message[]) {\n for (const message of messages) this.add(message);\n }\n\n hasEquivalent(message: Message): boolean {\n if (message.subagent_id !== undefined && this.visibleSubagentIds.has(message.subagent_id)) {\n return true;\n }\n\n const nickname = message.nickname;\n const text = message.parts.find((part) => part.type === \"text\")?.text;\n return (\n nickname !== undefined &&\n text !== undefined &&\n this.visibleNicknameTexts.get(nickname)?.has(text) === true\n );\n }\n\n add(message: Message): void {\n if (message.subagent_id !== undefined) {\n this.visibleSubagentIds.add(message.subagent_id);\n return;\n }\n if (message.nickname === undefined) return;\n\n let texts = this.visibleNicknameTexts.get(message.nickname);\n if (!texts) {\n texts = new Set();\n this.visibleNicknameTexts.set(message.nickname, texts);\n }\n for (const part of message.parts) {\n if (part.type === \"text\") texts.add(part.text);\n }\n }\n}\n\nfunction compareSourceActivityDesc(left: SessionSourceFile, right: SessionSourceFile): number {\n const leftTimestamp = sourceTimestamp(left.file, left.stat.mtimeMs);\n const rightTimestamp = sourceTimestamp(right.file, right.stat.mtimeMs);\n return rightTimestamp - leftTimestamp || left.file.localeCompare(right.file);\n}\n\nfunction sourceTimestamp(filePath: string, fallback: number): number {\n // Sort before parsing heads; the rollout filename is the only cheap activity hint.\n const match = basename(filePath).match(/^rollout-(\\d{4}-\\d{2}-\\d{2}T\\d{2}-\\d{2}-\\d{2})-/);\n if (!match) return fallback;\n const timestamp = match[1]!.replace(/-(\\d{2})-(\\d{2})$/, \":$1:$2\");\n const parsed = Date.parse(timestamp);\n return Number.isFinite(parsed) ? parsed : fallback;\n}\n\n// ---------------------------------------------------------------------------\n// CodexAgent\n// ---------------------------------------------------------------------------\n\nconst CODEX_RECORD_CONVERTER = new CodexRecordConverter();\n\nconst AGENT_METADATA = getAgentCatalogEntry(\"codex\");\n\nexport class CodexAgent extends SingleFileSessionSource<SessionMeta> {\n readonly name = AGENT_METADATA.name;\n readonly displayName = AGENT_METADATA.displayName;\n\n private basePath: string | null = this.configuredSourceRoot;\n private sessionIndexCache = new Map<string, string>();\n private sessionIndexMtime: number | null | undefined;\n private sessionIndexPath: string | undefined;\n private subagentIndex: SubagentIndex | null = null;\n // Thread meta lives in a rollout's immutable first line; fingerprinting by\n // (mtime, size) lets index rebuilds stat files instead of re-reading them.\n private readonly threadMetaByPath = new Map<\n string,\n { fingerprint: string; meta: ThreadMeta | null }\n >();\n private childSessionSummariesByParent = new Map<\n string,\n Map<string, ChildSessionSummaryCacheEntry>\n >();\n\n // ---- BaseAgent implementation ----\n\n private findBasePath(): string | null {\n return this.configuredSourceRoot ?? firstExisting(join(resolveCodexDataRoot(), \"sessions\"));\n }\n\n getSessionWatchPlan() {\n if (this.configuredSourceRoot) {\n const root = dirname(this.configuredSourceRoot);\n return {\n status: \"supported\" as const,\n targets: [\n { root, path: this.configuredSourceRoot },\n { root, path: join(root, \"session_index.jsonl\") },\n ],\n };\n }\n const dataRoot = resolveCodexDataRoot();\n return {\n status: \"supported\" as const,\n targets: [\n { path: join(dataRoot, \"sessions\") },\n { path: join(dataRoot, \"session_index.jsonl\") },\n ],\n };\n }\n\n isAvailable(): boolean {\n this.basePath = this.findBasePath();\n if (!this.basePath) return false;\n return this.listRolloutFiles().length > 0;\n }\n\n listSessionSources(options?: AgentScanOptions): SessionSourceRef[] {\n if (!this.basePath) return [];\n this.loadSessionIndex();\n return this.listScanSources(options).map(({ file, stat }) => ({\n sessionId: extractSessionId(file),\n sourcePath: file,\n fingerprint: this.sourceFingerprint(file, stat),\n }));\n }\n\n restoreSessionCacheMeta(meta: Readonly<Record<string, SessionCacheMeta>>): void {\n super.restoreSessionCacheMeta(meta);\n this.subagentIndex = null;\n this.childSessionSummariesByParent.clear();\n }\n\n /**\n * A changed subagent file leaves its parent's aggregated token stats stale,\n * so the parent must re-parse alongside the child.\n */\n expandChangedSessionIds(changedIds: string[], refs?: SessionSourceRef[]): string[] {\n if (changedIds.length === 0) return changedIds;\n const pathById = new Map((refs ?? []).map((ref) => [ref.sessionId, ref.sourcePath]));\n const expanded = new Set(changedIds);\n for (const id of changedIds) {\n const sourcePath = pathById.get(id) ?? this.sessionMetaMap.get(id)?.sourcePath;\n const threadMeta = sourcePath ? this.readThreadMeta(sourcePath) : null;\n // A removed file cannot be read back; cached meta still knows its parent.\n const parentId = threadMeta\n ? threadMeta.threadSource === \"subagent\"\n ? threadMeta.parentThreadId\n : null\n : (this.sessionMetaMap.get(id)?.parentThreadId ?? null);\n if (!parentId) continue;\n expanded.add(parentId);\n this.subagentIndex = null;\n this.childSessionSummariesByParent.delete(parentId);\n }\n return [...expanded];\n }\n\n private readThreadMeta(\n filePath: string,\n sourceStat?: { mtimeMs: number; size: number },\n ): ThreadMeta | null {\n try {\n const { mtimeMs, size } = sourceStat ?? statSync(filePath);\n const fingerprint = `${mtimeMs}:${size}`;\n const cached = this.threadMetaByPath.get(filePath);\n if (cached && cached.fingerprint === fingerprint) return cached.meta;\n const firstLine = readLeadingJsonlLines(filePath, 1)[0];\n const meta = firstLine ? extractThreadMeta(JSON.parse(firstLine)) : null;\n this.threadMetaByPath.set(filePath, { fingerprint, meta });\n return meta;\n } catch (error) {\n getCoreDiagnostics()?.warn(\"codex.thread_meta_read_failed\", {\n filePath,\n message: error instanceof Error ? error.message : String(error),\n });\n return null;\n }\n }\n\n getSessionData(sessionId: string): SessionDetail {\n const meta = this.sessionMetaMap.get(sessionId);\n if (!meta) throw new Error(`Session not found: ${sessionId}`);\n if (!existsSync(meta.sourcePath)) throw new Error(`Session file missing: ${meta.sourcePath}`);\n this.basePath ??= this.findBasePath();\n\n const transcript = new TranscriptBuilder();\n const usage = new CodexTokenUsageAccumulator();\n\n let pendingPlan: MessagePart | null = null;\n let activeModel: string | null = null;\n\n for (const record of readJsonlFile(meta.sourcePath)) {\n try {\n const recordType = String(record[\"type\"] ?? \"\");\n if (recordType === \"session_meta\" || recordType === \"turn_context\") {\n const payload = extractCodexPayload(record);\n activeModel = extractModelName(payload[\"model\"]) ?? activeModel;\n }\n\n pendingPlan = CODEX_RECORD_CONVERTER.convertRecord(\n record,\n transcript,\n pendingPlan,\n activeModel,\n );\n\n // Process Codex token_count events\n if (recordType === \"event_msg\") {\n const payload = extractCodexPayload(record);\n if (String(payload[\"type\"] ?? \"\") === \"token_count\") {\n const delta = usage.consume(payload, activeModel);\n if (delta) {\n transcript.attachUsageToLatestAssistant(delta.tokens, {\n model: delta.model,\n cost: delta.cost ?? undefined,\n costSource: delta.cost === null ? undefined : \"estimated\",\n });\n }\n }\n }\n } catch {\n // skip malformed records\n }\n }\n\n if (pendingPlan) transcript.appendToCurrentAssistant(pendingPlan);\n const result = transcript.finish(usage.stats());\n\n const childSummaries = this.collectChildSummaries(meta.id);\n this.applyChildStats(result.stats, childSummaries);\n\n const childMessages = childSummaries\n .flatMap(({ message }) => (message ? [message] : []))\n .sort((left, right) => left.time_created - right.time_created);\n this.mergeChildMessages(result.messages, childMessages);\n result.stats.message_count = result.messages.length;\n\n return {\n ...this.sessionIdentity(meta.id),\n title: meta.title,\n directory: meta.directory,\n parent_reference:\n meta.parentThreadId == null\n ? undefined\n : { agentName: this.name, sessionId: meta.parentThreadId },\n time_created: meta.createdAt,\n time_updated: meta.updatedAt,\n stats: result.stats,\n messages: result.messages,\n };\n }\n\n /**\n * Builds the complete parent→children map in one prefix sweep. A cache miss\n * afterwards means \"no children\", so per-session directory rescans (the old\n * O(N²) finalization hotspot) never happen.\n */\n private ensureSubagentIndex(currentSources?: readonly SessionSourceFile[]): SubagentIndex {\n if (this.subagentIndex) return this.subagentIndex;\n this.basePath ??= this.findBasePath();\n const index: SubagentIndex = { childFilesByParent: new Map(), subagentFiles: new Set() };\n const sourceByPath = new Map(currentSources?.map((source) => [source.file, source]));\n const paths = currentSources?.map((source) => source.file) ?? this.listRolloutFilePaths();\n const activePaths = currentSources ? null : new Set(paths);\n const addSubagent = (file: string, parentThreadId: string | null): void => {\n index.subagentFiles.add(file);\n if (!parentThreadId) return;\n const files = index.childFilesByParent.get(parentThreadId);\n if (!files) index.childFilesByParent.set(parentThreadId, [file]);\n else if (!files.includes(file)) files.push(file);\n };\n for (const meta of this.sessionMetaMap.values()) {\n if (activePaths && !activePaths.has(meta.sourcePath)) continue;\n const isKnownSubagent =\n meta.isSubagent === true ||\n (typeof meta.isSubagent !== \"boolean\" && meta.parentThreadId != null);\n if (isKnownSubagent) addSubagent(meta.sourcePath, meta.parentThreadId);\n }\n for (const file of paths) {\n const cached = this.sessionMetaMap.get(extractSessionId(file));\n const hasCachedThreadMeta =\n cached?.sourcePath === file && typeof cached.isSubagent === \"boolean\";\n if (hasCachedThreadMeta) continue;\n const threadMeta = this.readThreadMeta(file, sourceByPath.get(file)?.stat);\n const isSubagent = threadMeta?.threadSource === \"subagent\";\n if (cached?.sourcePath === file && threadMeta) {\n cached.isSubagent = isSubagent;\n cached.parentThreadId = isSubagent ? threadMeta.parentThreadId : null;\n }\n if (!isSubagent) continue;\n addSubagent(file, threadMeta?.parentThreadId ?? null);\n }\n if (!currentSources && this.threadMetaByPath.size > paths.length) {\n const active = new Set(paths);\n for (const path of this.threadMetaByPath.keys()) {\n if (!active.has(path)) this.threadMetaByPath.delete(path);\n }\n }\n this.subagentIndex = index;\n return index;\n }\n\n private applyChildStats(target: SessionHead[\"stats\"], summaries: ChildSessionSummary[]): void {\n for (const { stats } of summaries) {\n target.total_input_tokens += stats.total_input_tokens ?? 0;\n target.total_output_tokens += stats.total_output_tokens ?? 0;\n target.total_cost += stats.total_cost ?? 0;\n if (stats.total_cache_read_tokens) {\n target.total_cache_read_tokens =\n (target.total_cache_read_tokens ?? 0) + stats.total_cache_read_tokens;\n }\n }\n }\n\n private collectChildFiles(parentSessionId: string): string[] {\n return this.ensureSubagentIndex().childFilesByParent.get(parentSessionId) ?? [];\n }\n\n private mergeChildMessages(visibleMessages: Message[], childMessages: Message[]): void {\n const visible = new ChildMessageVisibilityIndex(visibleMessages);\n for (const message of childMessages) {\n if (visible.hasEquivalent(message)) continue;\n visibleMessages.push(message);\n visible.add(message);\n }\n }\n\n private collectChildSummaries(parentSessionId: string): ChildSessionSummary[] {\n const childFiles = this.collectChildFiles(parentSessionId);\n this.reconcileChildSummaryCache(parentSessionId, childFiles);\n return childFiles.map((file) => this.getChildSummary(parentSessionId, file));\n }\n\n private getChildSummary(parentSessionId: string, filePath: string): ChildSessionSummary {\n const { mtimeMs, size } = statSync(filePath);\n const sourceFingerprint = JSON.stringify([mtimeMs, size]);\n let cache = this.childSessionSummariesByParent.get(parentSessionId);\n if (!cache) {\n cache = new Map();\n this.childSessionSummariesByParent.set(parentSessionId, cache);\n }\n\n const cached = cache.get(filePath);\n if (\n cached?.sourceFingerprint === sourceFingerprint &&\n cached.parserVersion === PARSER_VERSION\n ) {\n return cached;\n }\n\n const summary = this.readChildSummary(filePath, mtimeMs, size);\n cache.set(filePath, { sourceFingerprint, parserVersion: PARSER_VERSION, ...summary });\n return summary;\n }\n\n private reconcileChildSummaryCache(parentSessionId: string, childFiles: string[]): void {\n const cache = this.childSessionSummariesByParent.get(parentSessionId);\n if (!cache) return;\n\n const activeFiles = new Set(childFiles);\n for (const filePath of cache.keys()) {\n if (!activeFiles.has(filePath)) cache.delete(filePath);\n }\n if (cache.size === 0) this.childSessionSummariesByParent.delete(parentSessionId);\n }\n\n private readChildSummary(\n filePath: string,\n fallbackMtimeMs: number,\n size: number,\n ): ChildSessionSummary {\n const sessionId = extractSessionId(filePath);\n const threadMeta = this.readThreadMeta(filePath, { mtimeMs: fallbackMtimeMs, size });\n const usage = new CodexTokenUsageAccumulator();\n let activeModel: string | null = null;\n type ChildOutput = { id: string; text: string; timestampMs: number; isFinal: boolean };\n let latestOutput: ChildOutput | null = null;\n let finalOutput: ChildOutput | null = null;\n\n for (const record of readJsonlFile(filePath)) {\n try {\n const recordType = String(record[\"type\"] ?? \"\");\n const payload = extractCodexPayload(record);\n if (recordType === \"session_meta\" || recordType === \"turn_context\") {\n activeModel = extractModelName(payload[\"model\"]) ?? activeModel;\n continue;\n }\n if (recordType === \"event_msg\" && String(payload[\"type\"] ?? \"\") === \"token_count\") {\n usage.consume(payload, activeModel);\n continue;\n }\n if (recordType !== \"response_item\") continue;\n if (String(payload[\"type\"] ?? \"\") !== \"message\") continue;\n if (String(payload[\"role\"] ?? \"\") !== \"assistant\") continue;\n\n const text = cleanInternalText(extractAssistantOutputText(payload));\n if (!text) continue;\n\n const candidate: ChildOutput = {\n id: asString(payload[\"id\"]) ?? `codex-subagent-${sessionId}`,\n text,\n timestampMs:\n parseCodexTimestampMs(record) || parseCodexTimestampMs(payload) || fallbackMtimeMs,\n isFinal:\n String(record[\"phase\"] ?? \"\") === \"final_answer\" ||\n String(payload[\"phase\"] ?? \"\") === \"final_answer\",\n };\n latestOutput = candidate;\n if (candidate.isFinal) finalOutput = candidate;\n } catch {\n // skip malformed records\n }\n }\n\n const selected = finalOutput ?? latestOutput;\n return {\n stats: usage.stats(),\n message: selected\n ? {\n id: selected.id,\n role: \"assistant\",\n agent: \"codex\",\n time_created: selected.timestampMs,\n mode: null,\n model: null,\n provider: null,\n cost: 0,\n subagent_id: sessionId,\n nickname: threadMeta?.agentNickname ?? undefined,\n parts: [{ type: \"text\", text: selected.text, time_created: selected.timestampMs }],\n }\n : null,\n };\n }\n\n // ---- File listing ----\n\n private listRolloutFiles(options?: AgentScanOptions): SessionSourceFile[] {\n if (!this.basePath) return [];\n return this.walkFiles(\n this.basePath,\n (entry) => entry.name.endsWith(\".jsonl\") && entry.name.startsWith(\"rollout-\"),\n { scanWindow: options },\n );\n }\n\n /** Path-only listing for the subagent index: no per-file stat needed. */\n private listRolloutFilePaths(): string[] {\n if (!this.basePath) return [];\n const paths: string[] = [];\n const walk = (directory: string): void => {\n const entries = this.readSessionSourceDirectory(directory);\n for (const entry of entries) {\n const filePath = join(directory, entry.name);\n if (entry.isDirectory()) walk(filePath);\n else if (entry.name.startsWith(\"rollout-\") && entry.name.endsWith(\".jsonl\")) {\n paths.push(filePath);\n }\n }\n };\n walk(this.basePath);\n return paths;\n }\n\n private listScanSources(options?: AgentScanOptions): SessionSourceFile[] {\n const windowed = this.listRolloutFiles(options).sort(compareSourceActivityDesc);\n if (options?.from == null && options?.to == null) return windowed;\n\n const { childFilesByParent, subagentFiles } = this.ensureSubagentIndex(windowed);\n const rootFiles = windowed.filter((source) => !subagentFiles.has(source.file));\n const rootIds = new Set(rootFiles.map(({ file }) => extractSessionId(file)));\n if (rootIds.size === 0) return rootFiles;\n\n const selected = new Map(rootFiles.map((source) => [source.file, source]));\n const pending = [...rootIds];\n const seenParents = new Set<string>();\n while (pending.length > 0) {\n const parentId = pending.pop()!;\n if (seenParents.has(parentId)) continue;\n seenParents.add(parentId);\n const childFiles = childFilesByParent.get(parentId) ?? [];\n for (let childIndex = childFiles.length - 1; childIndex >= 0; childIndex -= 1) {\n const file = childFiles[childIndex]!;\n if (selected.has(file)) continue;\n try {\n selected.set(file, this.sessionSourceFile(file));\n } catch {\n childFiles.splice(childIndex, 1);\n subagentFiles.delete(file);\n continue;\n }\n pending.push(extractSessionId(file));\n }\n }\n return [...selected.values()].sort(compareSourceActivityDesc);\n }\n\n protected createFileSessionMeta(head: SessionHead, source: SessionSourceFile): SessionMeta {\n const indexPath = this.getSessionIndexPath();\n const indexMtime = this.sessionIndexMtime ?? null;\n const threadMeta = this.readThreadMeta(source.file, source.stat);\n const isSubagent = threadMeta?.threadSource === \"subagent\";\n return this.buildFileSessionMeta({\n head,\n source,\n fingerprint: this.sourceFingerprint(source.file, source.stat),\n extras: {\n indexPath: indexMtime === null ? null : indexPath,\n indexMtimeMs: indexMtime,\n headIndexVersion: HEAD_INDEX_VERSION,\n parserVersion: PARSER_VERSION,\n isSubagent,\n parentThreadId: isSubagent ? threadMeta.parentThreadId : null,\n },\n });\n }\n\n /** Fingerprint depends on an already-fetched stat to avoid re-statting the same file. */\n private sourceFingerprint(file: string, stat: { mtimeMs: number; size: number }): string {\n const sessionId = extractSessionId(file);\n return JSON.stringify([\n HEAD_INDEX_VERSION,\n PARSER_VERSION,\n stat.mtimeMs,\n stat.size,\n this.getTitleForSession(sessionId),\n ]);\n }\n\n private getSessionIndexPath(): string {\n this.sessionIndexPath ??= join(resolveCodexDataRoot(), \"session_index.jsonl\");\n return this.sessionIndexPath;\n }\n\n // ---- Session index ----\n\n private loadSessionIndex(): void {\n const indexPath = this.getSessionIndexPath();\n const mtime = this.readFileMtimeMs(indexPath);\n\n // Invalidate when the index file mtime advances so long-running processes\n // pick up title changes without relying on callers to evict manually.\n if (this.sessionIndexMtime !== undefined && this.sessionIndexMtime === mtime) return;\n\n if (mtime === null) {\n this.sessionIndexCache.clear();\n this.sessionIndexMtime = null;\n return;\n }\n\n try {\n const content = readFileSync(indexPath, \"utf-8\");\n const cache = new Map<string, string>();\n for (const record of parseJsonlLines(content)) {\n const sid = String(record[\"id\"] ?? \"\").trim();\n const threadName = String(record[\"thread_name\"] ?? \"\").trim();\n if (sid && threadName) {\n cache.set(sid, threadName);\n }\n }\n this.sessionIndexCache = cache;\n this.sessionIndexMtime = mtime;\n } catch (error) {\n // Titles silently falling back to filenames is a confusing failure\n // mode; keep the degradation but make it visible.\n getCoreDiagnostics()?.warn(\"codex.session_index_read_failed\", {\n path: indexPath,\n message: error instanceof Error ? error.message : String(error),\n });\n this.sessionIndexCache.clear();\n this.sessionIndexMtime = undefined;\n }\n }\n\n private getTitleForSession(sessionId: string): string | null {\n return this.sessionIndexCache.get(sessionId) ?? null;\n }\n\n // ---- Session head parsing ----\n\n protected override parseFileSessionHeadResult(\n filePath: string,\n options?: AgentScanOptions,\n ): ParseSessionResult<SessionHead> {\n this.loadSessionIndex();\n if (options?.fast) {\n return this.parseFastSessionHeadResult(filePath);\n }\n\n const sessionId = extractSessionId(filePath);\n\n let firstPayload: Record<string, unknown> = {};\n let parentThreadId: string | null = null;\n let createdAt = 0;\n let lineCount = 0;\n let messageTitle: string | null = null;\n\n // Single streaming pass: read the first record, extract the title\n // candidate, count messages, extract models, and pre-accumulate tokens.\n let updatedAt = 0;\n let messageCount = 0;\n let activeModel: string | null = null;\n const usage = new CodexTokenUsageAccumulator();\n\n const COUNTED_TYPES = new Set([\"message\", \"function_call\", \"function_call_output\"]);\n\n let hasNonInternalRecord = false;\n\n for (const line of readJsonlFileLines(filePath)) {\n lineCount += 1;\n if (lineCount === 1) {\n let firstRecord: Record<string, unknown>;\n try {\n firstRecord = JSON.parse(line);\n } catch {\n return skippedSession(\"malformed first record\");\n }\n firstPayload = extractCodexPayload(firstRecord);\n const threadMeta = extractThreadMeta(firstRecord);\n parentThreadId = threadMeta?.threadSource === \"subagent\" ? threadMeta.parentThreadId : null;\n createdAt =\n parseCodexTimestampMs(firstRecord) ||\n parseCodexTimestampMs(firstPayload) ||\n statSync(filePath).mtimeMs;\n updatedAt = createdAt;\n }\n\n try {\n const data = JSON.parse(line);\n const recordType = String(data[\"type\"] ?? \"\");\n const payload = extractCodexPayload(data);\n const payloadType = String(payload[\"type\"] ?? \"\");\n if (isInternalEventType(recordType) || isInternalEventType(payloadType)) continue;\n hasNonInternalRecord = true;\n const recordTs = parseCodexTimestampMs(data) || parseCodexTimestampMs(payload);\n if (recordTs > updatedAt) updatedAt = recordTs;\n\n // Title fallback mirrors the removed extractTitleFromLines(): first\n // visible user message within the first 20 lines.\n if (messageTitle === null && lineCount <= 20) {\n const candidate = this.extractCodexRecordTitle(data);\n if (candidate) messageTitle = candidate;\n }\n\n if (recordType === \"session_meta\" || recordType === \"turn_context\") {\n const nextModel = extractModelName(payload[\"model\"]);\n if (nextModel) {\n activeModel = nextModel;\n }\n continue;\n }\n\n if (recordType === \"response_item\") {\n const p = payload;\n const pType = String(p[\"type\"] ?? \"\");\n if (COUNTED_TYPES.has(pType)) {\n messageCount++;\n }\n // Extract model from response_item\n const info = narrowRecordField(p[\"info\"], \"response_item.info\");\n const m = info?.[\"model\"] ?? p[\"model\"];\n if (typeof m === \"string\" && m.trim()) {\n activeModel = m.trim();\n }\n }\n\n if (recordType === \"event_msg\") {\n if (String(payload[\"type\"] ?? \"\") === \"token_count\") {\n usage.consume(payload, activeModel);\n }\n }\n } catch {\n // skip\n }\n }\n\n if (lineCount === 0) return skippedSession(\"empty file\");\n if (!hasNonInternalRecord) return filteredSession(\"internal events only\");\n\n const indexTitle = this.getTitleForSession(sessionId);\n const directory = firstPayload[\"cwd\"] ? String(firstPayload[\"cwd\"]) : \"\";\n const title = resolveSessionTitle(indexTitle, messageTitle, basenameTitle(directory || null));\n\n return parsedSession({\n ...this.sessionIdentity(sessionId),\n title,\n directory,\n parent_reference:\n parentThreadId == null ? undefined : { agentName: this.name, sessionId: parentThreadId },\n time_created: createdAt,\n time_updated: updatedAt,\n stats: usage.stats(messageCount),\n model_usage: usage.modelUsage(),\n });\n }\n\n private parseFastSessionHeadResult(filePath: string): ParseSessionResult<SessionHead> {\n const lines = readLeadingJsonlLines(filePath, 20);\n if (lines.length === 0) return skippedSession(\"empty file\");\n\n const sessionId = extractSessionId(filePath);\n\n let firstRecord: Record<string, unknown>;\n try {\n firstRecord = JSON.parse(lines[0]!);\n } catch (error) {\n getCoreDiagnostics()?.warn(\"codex.fast_head_first_record_failed\", {\n filePath,\n firstLineLength: lines[0]?.length ?? 0,\n message: error instanceof Error ? error.message : String(error),\n });\n return skippedSession(\"malformed first record\");\n }\n\n const threadMeta = extractThreadMeta(firstRecord);\n const parentThreadId =\n threadMeta?.threadSource === \"subagent\" ? threadMeta.parentThreadId : null;\n\n const payload = extractCodexPayload(firstRecord);\n const stat = statSync(filePath);\n const createdAt =\n parseCodexTimestampMs(firstRecord) || parseCodexTimestampMs(payload) || stat.mtimeMs;\n const indexTitle = this.getTitleForSession(sessionId);\n const messageTitle = this.extractTitleFromLines(lines);\n const directory = payload[\"cwd\"] ? String(payload[\"cwd\"]) : \"\";\n const directoryTitle = basenameTitle(directory || null);\n const title = resolveSessionTitle(indexTitle, messageTitle, directoryTitle);\n\n return parsedSession({\n ...this.sessionIdentity(sessionId),\n title,\n directory,\n parent_reference:\n parentThreadId == null ? undefined : { agentName: this.name, sessionId: parentThreadId },\n time_created: createdAt,\n time_updated: stat.mtimeMs,\n stats: {\n message_count: 0,\n total_input_tokens: 0,\n total_output_tokens: 0,\n total_cost: 0,\n },\n });\n }\n\n /** Fast path only: parses each of the first 20 lines to find a title (no full stats pass available). */\n private extractTitleFromLines(lines: string[]): string | null {\n for (const line of lines.slice(0, 20)) {\n try {\n const title = this.extractCodexRecordTitle(JSON.parse(line));\n if (title) return title;\n } catch {\n // skip\n }\n }\n return null;\n }\n\n /**\n * Title candidate from a single already-parsed record, if it's a visible\n * user message. Shared by the main streaming pass (which parses every line\n * once) and the fast path's extractTitleFromLines().\n */\n private extractCodexRecordTitle(data: Record<string, unknown>): string | null {\n const recordType = String(data[\"type\"] ?? \"\");\n if (recordType !== \"response_item\" || isInternalEventType(recordType)) return null;\n\n const payload = extractCodexPayload(data);\n const pType = String(payload[\"type\"] ?? \"\");\n if (pType !== \"message\" || isInternalEventType(pType)) return null;\n if (String(payload[\"role\"] ?? \"\") !== \"user\") return null;\n\n const content = payload[\"content\"];\n let text: string | null = null;\n if (Array.isArray(content)) {\n text = content\n .map((item) => {\n const record = asRecord(item);\n return record ? String(record[\"text\"] ?? \"\") : \"\";\n })\n .join(\" \");\n } else if (typeof content === \"string\") {\n text = content;\n }\n if (!text || isDeveloperLikeUserMessage(text)) return null;\n return normalizeTitleText(text) || null;\n }\n}\n","/**\n * Codex \"code mode\" exec decoding.\n *\n * Since Codex 0.144.x the agent no longer calls tools directly. Every tool\n * invocation is now a `custom_tool_call` named \"exec\" whose `input` is a small\n * JS program that calls `tools.<name>({...})` (e.g. `tools.exec_command`,\n * `tools.apply_patch`). This module extracts those inner invocations so the\n * adapter can present each one as the native tool call it used to be.\n *\n * The inner argument objects are JS object literals, not JSON — unquoted keys,\n * single/double/template strings, and shorthand `{patch}` that references a\n * `const patch = \"...\"` declared earlier. A small tolerant reader handles that\n * subset and resolves string variables; anything it cannot parse degrades to an\n * empty result so the caller can fall back to the raw exec display.\n */\n\nexport interface ExecInnerCall {\n name: string;\n args: unknown;\n}\n\nconst PARSE_FAIL = Symbol(\"parse-fail\");\n\nconst EXEC_OUTPUT_ENVELOPE_RE = /^Script completed\\nWall time [^\\n]*\\nOutput:\\n?/;\n\n/** Strip the `Script completed / Wall time / Output:` wrapper code-mode adds. */\nexport function stripExecOutputEnvelope(text: string): string {\n return text.replace(EXEC_OUTPUT_ENVELOPE_RE, \"\");\n}\n\n/**\n * Split an inner tool name into `resolveToolIdentity(name, namespace)` inputs.\n * `mcp__node_repl__js` → { name: \"js\", namespace: \"mcp__node_repl__\" }.\n */\nexport function splitExecToolName(name: string): { name: string; namespace?: string } {\n if (name.startsWith(\"mcp__\")) {\n const separator = name.lastIndexOf(\"__\");\n if (separator > 0 && separator + 2 < name.length) {\n return { name: name.slice(separator + 2), namespace: name.slice(0, separator + 2) };\n }\n }\n return { name };\n}\n\n/**\n * Pick which decoded call receives the exec program's combined output. Patch\n * and plan calls do not emit stdout, so prefer the last output-bearing call;\n * otherwise fall back to the last call.\n */\nexport function pickExecOutputTarget(calls: ExecInnerCall[]): number {\n for (let index = calls.length - 1; index >= 0; index -= 1) {\n const { name } = splitExecToolName(calls[index]!.name);\n if (name !== \"apply_patch\" && name !== \"update_plan\") return index;\n }\n return calls.length - 1;\n}\n\n/** Extract the patch text from an `apply_patch` argument (`{patch}` or a string). */\nexport function getExecPatchText(args: unknown): string {\n if (typeof args === \"string\") return args;\n if (args && typeof args === \"object\") {\n const patch = (args as Record<string, unknown>)[\"patch\"];\n if (typeof patch === \"string\") return patch;\n }\n return \"\";\n}\n\n/** Decode the `tools.<name>({...})` invocations inside a code-mode exec program. */\nexport function decodeExecCalls(input: unknown): ExecInnerCall[] {\n if (typeof input !== \"string\" || !input.includes(\"tools.\")) return [];\n\n const scope = collectStringVars(input);\n const calls: ExecInnerCall[] = [];\n const callRe = /tools\\.([A-Za-z_$][\\w$]*)\\s*\\(/g;\n let match: RegExpExecArray | null;\n while ((match = callRe.exec(input)) !== null) {\n const reader = new JsValueReader(input, callRe.lastIndex, scope);\n const args = reader.parseValue();\n if (args !== PARSE_FAIL) {\n calls.push({ name: match[1]!, args });\n callRe.lastIndex = reader.pos;\n }\n }\n return calls;\n}\n\n/** Pre-scan `const/let/var NAME = \"...\"` so shorthand args can resolve them. */\nfunction collectStringVars(input: string): Map<string, string> {\n const scope = new Map<string, string>();\n const assignRe = /(?:const|let|var)\\s+([A-Za-z_$][\\w$]*)\\s*=\\s*/g;\n let match: RegExpExecArray | null;\n while ((match = assignRe.exec(input)) !== null) {\n const reader = new JsValueReader(input, assignRe.lastIndex, scope);\n const value = reader.parseValue();\n if (value !== PARSE_FAIL) {\n if (typeof value === \"string\") scope.set(match[1]!, value);\n assignRe.lastIndex = reader.pos;\n }\n }\n return scope;\n}\n\nconst IDENT_START_RE = /[A-Za-z_$]/;\nconst IDENT_PART_RE = /[\\w$]/;\n\n/** Recursive-descent reader for the JS-literal subset used in exec args. */\nclass JsValueReader {\n pos: number;\n private readonly src: string;\n private readonly scope: Map<string, string>;\n\n constructor(src: string, start: number, scope: Map<string, string>) {\n this.src = src;\n this.pos = start;\n this.scope = scope;\n }\n\n parseValue(): unknown | typeof PARSE_FAIL {\n this.skipTrivia();\n const char = this.src[this.pos];\n if (char === undefined) return PARSE_FAIL;\n if (char === \"{\") return this.parseObject();\n if (char === \"[\") return this.parseArray();\n if (char === '\"' || char === \"'\" || char === \"`\") return this.parseString(char);\n if (char === \"-\" || char === \"+\" || (char >= \"0\" && char <= \"9\")) return this.parseNumber();\n if (IDENT_START_RE.test(char)) return this.parseIdentifierValue();\n return PARSE_FAIL;\n }\n\n private parseObject(): unknown | typeof PARSE_FAIL {\n this.pos++; // {\n const result: Record<string, unknown> = {};\n this.skipTrivia();\n if (this.src[this.pos] === \"}\") {\n this.pos++;\n return result;\n }\n while (this.pos < this.src.length) {\n this.skipTrivia();\n const key = this.parseKey();\n if (key === PARSE_FAIL) return PARSE_FAIL;\n this.skipTrivia();\n if (this.src[this.pos] === \":\") {\n this.pos++;\n const value = this.parseValue();\n if (value === PARSE_FAIL) return PARSE_FAIL;\n result[key] = value;\n } else {\n result[key] = this.resolveIdentifier(key);\n }\n this.skipTrivia();\n const next = this.src[this.pos];\n if (next === \",\") {\n this.pos++;\n this.skipTrivia();\n if (this.src[this.pos] === \"}\") {\n this.pos++;\n return result;\n }\n continue;\n }\n if (next === \"}\") {\n this.pos++;\n return result;\n }\n return PARSE_FAIL;\n }\n return PARSE_FAIL;\n }\n\n private parseArray(): unknown | typeof PARSE_FAIL {\n this.pos++; // [\n const result: unknown[] = [];\n this.skipTrivia();\n if (this.src[this.pos] === \"]\") {\n this.pos++;\n return result;\n }\n while (this.pos < this.src.length) {\n const value = this.parseValue();\n if (value === PARSE_FAIL) return PARSE_FAIL;\n result.push(value);\n this.skipTrivia();\n const next = this.src[this.pos];\n if (next === \",\") {\n this.pos++;\n this.skipTrivia();\n if (this.src[this.pos] === \"]\") {\n this.pos++;\n return result;\n }\n continue;\n }\n if (next === \"]\") {\n this.pos++;\n return result;\n }\n return PARSE_FAIL;\n }\n return PARSE_FAIL;\n }\n\n private parseKey(): string | typeof PARSE_FAIL {\n const char = this.src[this.pos];\n if (char === '\"' || char === \"'\" || char === \"`\") {\n const value = this.parseString(char);\n return typeof value === \"string\" ? value : PARSE_FAIL;\n }\n if (char !== undefined && IDENT_START_RE.test(char)) return this.readIdentifier();\n return PARSE_FAIL;\n }\n\n private parseString(quote: string): string {\n this.pos++; // opening quote\n let out = \"\";\n while (this.pos < this.src.length) {\n const char = this.src[this.pos++]!;\n if (char === \"\\\\\") {\n out += this.readEscape();\n continue;\n }\n if (char === quote) break;\n out += char;\n }\n return out;\n }\n\n private readEscape(): string {\n const char = this.src[this.pos++];\n switch (char) {\n case \"n\":\n return \"\\n\";\n case \"t\":\n return \"\\t\";\n case \"r\":\n return \"\\r\";\n case \"b\":\n return \"\\b\";\n case \"f\":\n return \"\\f\";\n case \"v\":\n return \"\\v\";\n case \"0\":\n return \"\\0\";\n case \"u\": {\n const hex = this.src.slice(this.pos, this.pos + 4);\n if (/^[0-9a-fA-F]{4}$/.test(hex)) {\n this.pos += 4;\n return String.fromCharCode(parseInt(hex, 16));\n }\n return \"u\";\n }\n case \"x\": {\n const hex = this.src.slice(this.pos, this.pos + 2);\n if (/^[0-9a-fA-F]{2}$/.test(hex)) {\n this.pos += 2;\n return String.fromCharCode(parseInt(hex, 16));\n }\n return \"x\";\n }\n default:\n return char ?? \"\";\n }\n }\n\n private parseNumber(): number | typeof PARSE_FAIL {\n const numberRe = /[-+]?(?:0[xX][0-9a-fA-F]+|(?:\\d+\\.?\\d*|\\.\\d+)(?:[eE][-+]?\\d+)?)/y;\n numberRe.lastIndex = this.pos;\n const match = numberRe.exec(this.src);\n if (!match) return PARSE_FAIL;\n this.pos += match[0].length;\n return Number(match[0]);\n }\n\n private parseIdentifierValue(): string | boolean | null | undefined {\n const name = this.readIdentifier();\n if (name === \"true\") return true;\n if (name === \"false\") return false;\n if (name === \"null\") return null;\n if (name === \"undefined\") return undefined;\n return this.resolveIdentifier(name);\n }\n\n private resolveIdentifier(name: string): string | undefined {\n return this.scope.has(name) ? this.scope.get(name) : undefined;\n }\n\n private readIdentifier(): string {\n const start = this.pos;\n while (this.pos < this.src.length && IDENT_PART_RE.test(this.src[this.pos]!)) this.pos++;\n return this.src.slice(start, this.pos);\n }\n\n private skipTrivia(): void {\n while (this.pos < this.src.length) {\n const char = this.src[this.pos]!;\n if (char === \" \" || char === \"\\t\" || char === \"\\n\" || char === \"\\r\") {\n this.pos++;\n continue;\n }\n if (char === \"/\" && this.src[this.pos + 1] === \"/\") {\n const newline = this.src.indexOf(\"\\n\", this.pos + 2);\n this.pos = newline === -1 ? this.src.length : newline + 1;\n continue;\n }\n if (char === \"/\" && this.src[this.pos + 1] === \"*\") {\n const close = this.src.indexOf(\"*/\", this.pos + 2);\n this.pos = close === -1 ? this.src.length : close + 2;\n continue;\n }\n break;\n }\n }\n}\n","import type { MessagePart } from \"../types/index.js\";\nimport { cleanInternalText, isInternalEventType } from \"../utils/session-normalization.js\";\nimport { parseAgentTimestamp } from \"../utils/timestamp.js\";\nimport { asRecord, asString, narrowField } from \"../utils/narrow.js\";\nimport { TranscriptBuilder } from \"./transcript-builder.js\";\nimport { normalizeToolArguments } from \"./tool-arguments.js\";\nimport {\n type ExecInnerCall,\n decodeExecCalls,\n getExecPatchText,\n pickExecOutputTarget,\n splitExecToolName,\n stripExecOutputEnvelope,\n} from \"./codex-exec-decode.js\";\n\nconst PROPOSED_PLAN_PATTERN = /<proposed_plan>\\s*([\\s\\S]*?)\\s*<\\/proposed_plan>/;\nconst PLAN_APPROVAL_PREFIX = \"PLEASE IMPLEMENT THIS PLAN\";\nconst SUBAGENT_NOTIFICATION_PATTERN =\n /<subagent_notification>\\s*([\\s\\S]*?)\\s*<\\/subagent_notification>/;\n\nconst DEVELOPER_LIKE_USER_MARKERS = [\n \"agents.md instructions for\",\n \"<instructions>\",\n \"<environment_context>\",\n \"<permissions instructions>\",\n \"<collaboration_mode>\",\n];\n\nexport function isDeveloperLikeUserMessage(text: string): boolean {\n const lower = text.toLowerCase();\n return DEVELOPER_LIKE_USER_MARKERS.some((m) => lower.includes(m));\n}\n\nconst CODEX_TOOL_TITLE_MAP: Record<string, string> = {\n exec_command: \"bash\",\n apply_patch: \"patch\",\n patch: \"patch\",\n spawn_agent: \"subagent\",\n subagent: \"subagent\",\n};\n\nexport function parseCodexTimestampMs(data: Record<string, unknown>): number {\n return parseAgentTimestamp(data[\"timestamp\"], \"codex\") ?? 0;\n}\n\nexport function narrowRecordField(\n value: unknown,\n field: string,\n): Record<string, unknown> | undefined {\n return narrowField(\"codex\", field, value, asRecord);\n}\n\nexport function extractCodexPayload(data: Record<string, unknown>): Record<string, unknown> {\n return narrowRecordField(data[\"payload\"], \"payload\") ?? {};\n}\n\n// ---------------------------------------------------------------------------\n// Tool helpers\n// ---------------------------------------------------------------------------\n\nfunction resolveToolIdentity(\n name: string,\n namespace: unknown,\n): { tool: string; metadata?: { name: string; namespace: string } } {\n const mappedName = CODEX_TOOL_TITLE_MAP[name];\n if (mappedName) return { tool: mappedName };\n\n const namespaceText = typeof namespace === \"string\" ? namespace.trim() : \"\";\n if (!namespaceText) return { tool: name };\n\n const namespaceName = namespaceText.split(\"__\").at(-1) ?? namespaceText;\n const toolName = name.replace(/^[_.]+/, \"\");\n if (!namespaceName) {\n return {\n tool: toolName || name,\n metadata: { name, namespace: namespaceText },\n };\n }\n\n return {\n tool: `${namespaceName}.${toolName || name}`,\n metadata: { name, namespace: namespaceText },\n };\n}\n\nfunction normalizeCustomToolArguments(toolName: string, input: unknown): unknown {\n if (toolName === \"apply_patch\") {\n return parseApplyPatchInput(input);\n }\n return input;\n}\n\n/**\n * Flatten tool-call output to text. Classic outputs are strings; code-mode\n * outputs are arrays of `{ type: \"input_text\", text }` segments.\n */\nfunction flattenOutputText(output: unknown): string {\n if (typeof output === \"string\") return output;\n if (Array.isArray(output)) {\n return output\n .map((item) => {\n if (typeof item === \"string\") return item;\n const record = asRecord(item);\n return record ? (asString(record[\"text\"]) ?? \"\") : \"\";\n })\n .join(\"\");\n }\n return \"\";\n}\n\nexport function extractAssistantOutputText(payload: Record<string, unknown>): string {\n const content = payload[\"content\"];\n if (Array.isArray(content)) {\n return content\n .map((item) => {\n const record = asRecord(item);\n return record && String(record[\"type\"] ?? \"\") === \"output_text\"\n ? String(record[\"text\"] ?? \"\")\n : \"\";\n })\n .filter(Boolean)\n .join(\"\\n\");\n }\n return \"\";\n}\n\n// ---------------------------------------------------------------------------\n// Patch parsing\n// ---------------------------------------------------------------------------\n\ninterface PatchBlock {\n type: \"write_file\" | \"delete_file\" | \"move_file\" | \"edit_file\";\n path?: string;\n content?: string;\n targetPath?: string;\n}\n\nconst PATCH_BEGIN_RE = /\\*\\*\\* Begin Patch/;\nconst PATCH_END_RE = /\\*\\*\\* End Patch/;\nconst PATCH_HEADER_RE = /\\*\\*\\*\\s+(Add|Delete|Update|Move)\\s+File:\\s*(.+)/;\nconst PATCH_MOVE_TO_RE = /\\*\\*\\*\\s+Move to:\\s*(.+)/;\n\nfunction parseApplyPatchInput(input: unknown): PatchBlock[] {\n const text = typeof input === \"string\" ? input : \"\";\n if (!text) return [];\n\n const blocks: PatchBlock[] = [];\n const lines = text.split(\"\\n\");\n let inPatch = false;\n let i = 0;\n\n while (i < lines.length) {\n const line = lines[i]!;\n\n if (!inPatch && PATCH_BEGIN_RE.test(line)) {\n inPatch = true;\n i++;\n continue;\n }\n\n if (inPatch && PATCH_END_RE.test(line)) {\n inPatch = false;\n i++;\n continue;\n }\n\n if (inPatch) {\n const headerMatch = line.match(PATCH_HEADER_RE);\n if (headerMatch) {\n const action = headerMatch[1]!;\n const filePath = headerMatch[2]!.trim();\n i++;\n\n if (action === \"Add\") {\n const content = extractPatchContent(lines, i);\n i = content.nextLineIndex;\n blocks.push({ type: \"write_file\", path: filePath, content: content.text });\n } else if (action === \"Update\") {\n // Check for Move to on the next non-empty line\n let moveToTarget: string | null = null;\n let contentStart = i;\n for (let j = i; j < lines.length; j++) {\n const l = lines[j]!;\n if (!l.trim()) continue;\n const moveMatch = l.match(PATCH_MOVE_TO_RE);\n if (moveMatch) {\n moveToTarget = moveMatch[1]!.trim();\n contentStart = j + 1;\n break;\n }\n break;\n }\n if (moveToTarget) {\n const content = extractPatchContent(lines, contentStart);\n i = content.nextLineIndex;\n blocks.push({\n type: \"move_file\",\n path: filePath,\n targetPath: moveToTarget,\n content: content.text,\n });\n } else {\n const content = extractPatchContent(lines, i);\n i = content.nextLineIndex;\n blocks.push({ type: \"edit_file\", path: filePath, content: content.text });\n }\n } else if (action === \"Delete\") {\n blocks.push({ type: \"delete_file\", path: filePath });\n // No content to read for delete\n }\n continue;\n }\n }\n\n i++;\n }\n\n return blocks;\n}\n\nfunction extractPatchContent(\n lines: string[],\n startIndex: number,\n): { text: string; nextLineIndex: number } {\n const contentLines: string[] = [];\n let i = startIndex;\n while (i < lines.length) {\n const line = lines[i]!;\n // Stop at next patch header or end patch\n if (PATCH_HEADER_RE.test(line) || PATCH_END_RE.test(line)) break;\n contentLines.push(line);\n i++;\n }\n return { text: contentLines.join(\"\\n\"), nextLineIndex: i };\n}\n\nexport class CodexRecordConverter {\n // ---- Record conversion ----\n\n convertRecord(\n data: Record<string, unknown>,\n transcript: TranscriptBuilder,\n pendingPlan: MessagePart | null,\n activeModel: string | null,\n ): MessagePart | null {\n const recordType = String(data[\"type\"] ?? \"\");\n if (isInternalEventType(recordType)) return pendingPlan;\n\n if (recordType === \"session_meta\" || recordType === \"event_msg\") {\n return pendingPlan;\n }\n\n if (recordType !== \"response_item\") return pendingPlan;\n\n const payload = extractCodexPayload(data);\n const payloadType = String(payload[\"type\"] ?? \"\");\n if (isInternalEventType(payloadType)) return pendingPlan;\n const timestampMs = parseCodexTimestampMs(data) || parseCodexTimestampMs(payload);\n\n switch (payloadType) {\n case \"message\": {\n const role = String(payload[\"role\"] ?? \"\");\n if (role === \"assistant\") {\n return this.convertAssistantMessage(\n payload,\n transcript,\n timestampMs,\n pendingPlan,\n activeModel,\n );\n }\n if (role === \"user\") {\n return this.convertUserMessage(payload, transcript, timestampMs, pendingPlan);\n }\n break;\n }\n\n case \"reasoning\":\n this.convertReasoning(payload, transcript, timestampMs, activeModel);\n return null;\n\n case \"function_call\":\n this.convertFunctionCall(payload, transcript, timestampMs, activeModel);\n return null;\n\n case \"function_call_output\":\n this.convertToolCallOutput(payload, transcript, timestampMs);\n return pendingPlan;\n\n case \"custom_tool_call\":\n this.convertCustomToolCall(payload, transcript, timestampMs, activeModel);\n return null;\n\n case \"custom_tool_call_output\":\n this.convertToolCallOutput(payload, transcript, timestampMs);\n return pendingPlan;\n }\n\n return pendingPlan;\n }\n\n // ---- Assistant message ----\n\n private convertAssistantMessage(\n payload: Record<string, unknown>,\n transcript: TranscriptBuilder,\n timestampMs: number,\n pendingPlan: MessagePart | null,\n activeModel: string | null,\n ): MessagePart | null {\n const fullText = extractAssistantOutputText(payload);\n if (!fullText) return pendingPlan;\n\n const planMatch = fullText.match(PROPOSED_PLAN_PATTERN);\n if (planMatch) {\n const planText = planMatch[1]!.trim();\n const planPart: MessagePart = {\n type: \"plan\",\n text: planText,\n approval_status: \"success\",\n time_created: timestampMs,\n };\n pendingPlan = planPart;\n }\n\n const displayText = cleanInternalText(fullText.replace(PROPOSED_PLAN_PATTERN, \"\"));\n if (!displayText) return pendingPlan;\n\n const textPart: MessagePart = { type: \"text\", text: displayText, time_created: timestampMs };\n transcript.appendAssistantPart(textPart, {\n id: \"\",\n timestampMs,\n agent: \"codex\",\n model: activeModel,\n });\n return pendingPlan;\n }\n\n // ---- User message ----\n\n private convertUserMessage(\n payload: Record<string, unknown>,\n transcript: TranscriptBuilder,\n timestampMs: number,\n pendingPlan: MessagePart | null,\n ): MessagePart | null {\n const content = payload[\"content\"];\n const text = Array.isArray(content)\n ? content\n .map((c) => {\n if (Array.isArray(c)) return \"\";\n const record = asRecord(c);\n return record ? String(record[\"text\"] ?? \"\") : String(c ?? \"\");\n })\n .join(\" \")\n : String(content ?? \"\");\n\n const visibleText = cleanInternalText(text);\n if (!visibleText) return pendingPlan;\n\n if (isDeveloperLikeUserMessage(visibleText)) return pendingPlan;\n\n if (visibleText.trimStart().startsWith(PLAN_APPROVAL_PREFIX)) {\n if (pendingPlan) transcript.appendToCurrentAssistant(pendingPlan);\n transcript.appendMessage({\n id: \"\",\n role: \"user\",\n timestampMs,\n parts: [{ type: \"text\", text: visibleText, time_created: timestampMs }],\n });\n return null;\n }\n\n const subagentMatch = visibleText.match(SUBAGENT_NOTIFICATION_PATTERN);\n if (subagentMatch) {\n // Malformed or non-object notification payloads fall through and are\n // treated as normal user messages below.\n let notifPayload: Record<string, unknown> | undefined;\n try {\n notifPayload = asRecord(JSON.parse(subagentMatch[1]!));\n } catch {\n notifPayload = undefined;\n }\n\n if (notifPayload) {\n const agentId = String(notifPayload[\"agent_id\"] ?? \"\");\n const nickname = String(notifPayload[\"nickname\"] ?? \"\");\n const completedText = String(notifPayload[\"completed\"] ?? \"\");\n\n const textPart: MessagePart = {\n type: \"text\",\n text: completedText || `Subagent ${nickname} completed`,\n time_created: timestampMs,\n };\n\n transcript.appendMessage({\n id: \"\",\n role: \"assistant\",\n timestampMs,\n parts: [textPart],\n agent: \"codex\",\n subagentId: agentId || undefined,\n nickname: nickname || undefined,\n });\n transcript.beginTurn();\n return pendingPlan;\n }\n }\n\n transcript.appendMessage({\n id: \"\",\n role: \"user\",\n timestampMs,\n parts: [{ type: \"text\", text: visibleText, time_created: timestampMs }],\n });\n return pendingPlan;\n }\n\n // ---- Reasoning ----\n\n private convertReasoning(\n payload: Record<string, unknown>,\n transcript: TranscriptBuilder,\n timestampMs: number,\n activeModel: string | null,\n ): void {\n const summary = payload[\"summary\"];\n if (!Array.isArray(summary)) return;\n\n const texts: string[] = [];\n for (const item of summary) {\n const ci = asRecord(item);\n if (!ci) continue;\n if (String(ci[\"type\"] ?? \"\") === \"summary_text\") {\n const text = String(ci[\"text\"] ?? \"\");\n if (text.trim()) texts.push(text);\n }\n }\n\n if (texts.length === 0) return;\n\n const reasoningText = texts.join(\"\\n\");\n const part: MessagePart = { type: \"reasoning\", text: reasoningText, time_created: timestampMs };\n transcript.appendAssistantPart(\n part,\n {\n id: \"\",\n timestampMs,\n agent: \"codex\",\n model: activeModel,\n },\n { resetLatestText: true },\n );\n }\n\n // ---- Function call ----\n\n private convertFunctionCall(\n payload: Record<string, unknown>,\n transcript: TranscriptBuilder,\n timestampMs: number,\n activeModel: string | null,\n ): void {\n const callId = String(payload[\"call_id\"] ?? \"\").trim();\n const name = String(payload[\"name\"] ?? \"\").trim();\n if (!name) return;\n\n const toolIdentity = resolveToolIdentity(name, payload[\"namespace\"]);\n const arguments_ = normalizeToolArguments(payload[\"arguments\"]);\n\n const toolPart: MessagePart = {\n type: \"tool\",\n tool: toolIdentity.tool,\n callID: callId,\n title: `Tool: ${toolIdentity.tool}`,\n state: {\n status: \"running\",\n input: arguments_,\n output: null,\n metadata: toolIdentity.metadata,\n },\n time_created: timestampMs,\n };\n\n transcript.appendToolCall(\n toolPart,\n { id: \"\", timestampMs, agent: \"codex\", model: activeModel },\n { markModeAsTool: true },\n );\n }\n\n // ---- Function call output ----\n\n private convertToolCallOutput(\n payload: Record<string, unknown>,\n transcript: TranscriptBuilder,\n timestampMs: number,\n ): void {\n const callId = String(payload[\"call_id\"] ?? \"\").trim();\n if (!callId) return;\n\n const outputText = cleanInternalText(\n stripExecOutputEnvelope(flattenOutputText(payload[\"output\"])),\n );\n const outputParts: MessagePart[] = outputText\n ? [{ type: \"text\", text: outputText, time_created: timestampMs }]\n : [];\n\n if (outputParts.length > 0) {\n transcript.resolveToolCall(callId, { output: outputParts, status: \"completed\" });\n }\n }\n\n // ---- Custom tool call ----\n\n private convertCustomToolCall(\n payload: Record<string, unknown>,\n transcript: TranscriptBuilder,\n timestampMs: number,\n activeModel: string | null,\n ): void {\n const callId = String(payload[\"call_id\"] ?? \"\").trim();\n const name = String(payload[\"name\"] ?? \"\").trim();\n if (!name) return;\n\n // Code-mode exec: the JS program wraps native tool calls. Decode each\n // inner call back to its classic tool part so existing displays apply.\n // Programs with no recognizable call fall through to the raw exec part.\n if (name === \"exec\") {\n const decoded = decodeExecCalls(payload[\"input\"]);\n if (decoded.length > 0) {\n this.appendDecodedExecCalls(decoded, callId, transcript, timestampMs, activeModel);\n return;\n }\n }\n\n const toolIdentity = resolveToolIdentity(name, payload[\"namespace\"]);\n const rawInput = payload[\"input\"];\n const normalizedInput = normalizeCustomToolArguments(name, rawInput);\n\n const toolPart: MessagePart = {\n type: \"tool\",\n tool: toolIdentity.tool,\n callID: callId,\n title: `Tool: ${toolIdentity.tool}`,\n state: {\n status: \"running\",\n input: normalizedInput,\n output: null,\n metadata: toolIdentity.metadata,\n },\n time_created: timestampMs,\n };\n\n transcript.appendToolCall(\n toolPart,\n { id: \"\", timestampMs, agent: \"codex\", model: activeModel },\n { markModeAsTool: true },\n );\n }\n\n // ---- Decoded code-mode exec calls ----\n\n private appendDecodedExecCalls(\n calls: ExecInnerCall[],\n callId: string,\n transcript: TranscriptBuilder,\n timestampMs: number,\n activeModel: string | null,\n ): void {\n // Only one output record follows, keyed by the exec call id; route it to\n // the output-bearing part and give the rest unique ids so they still\n // register and render, just without a resolved output.\n const outputIndex = pickExecOutputTarget(calls);\n calls.forEach((call, index) => {\n const partCallId = index === outputIndex ? callId : `${callId}#${index}`;\n this.appendDecodedExecCall(call, partCallId, transcript, timestampMs, activeModel);\n });\n }\n\n private appendDecodedExecCall(\n call: ExecInnerCall,\n callId: string,\n transcript: TranscriptBuilder,\n timestampMs: number,\n activeModel: string | null,\n ): void {\n const { name, namespace } = splitExecToolName(call.name);\n const toolIdentity = resolveToolIdentity(name, namespace);\n const arguments_ =\n name === \"apply_patch\" ? parseApplyPatchInput(getExecPatchText(call.args)) : call.args;\n\n const toolPart: MessagePart = {\n type: \"tool\",\n tool: toolIdentity.tool,\n callID: callId,\n title: `Tool: ${toolIdentity.tool}`,\n state: {\n status: \"running\",\n input: arguments_,\n output: null,\n metadata: toolIdentity.metadata,\n },\n time_created: timestampMs,\n };\n\n transcript.appendToolCall(\n toolPart,\n { id: \"\", timestampMs, agent: \"codex\", model: activeModel },\n { markModeAsTool: true },\n );\n }\n}\n","import type { MessageTokens, SessionStats } from \"../types/index.js\";\nimport { estimateTokenCost } from \"../utils/cost.js\";\nimport { asRecord, narrowField } from \"../utils/narrow.js\";\n\nexport interface CodexTokenUsageDelta {\n tokens: MessageTokens;\n model: string | null;\n cost: number | null;\n}\n\nfunction usageRecord(value: unknown, field: string): Record<string, unknown> | undefined {\n return narrowField(\"codex\", field, value, asRecord);\n}\n\nfunction tokenCount(value: unknown): number {\n const count = Number(value ?? 0);\n return Number.isFinite(count) ? count : 0;\n}\n\nfunction cachedInputTokens(usage: Record<string, unknown> | undefined): number {\n if (!usage) return 0;\n return tokenCount(usage[\"cached_input_tokens\"] ?? usage[\"cache_read_input_tokens\"]);\n}\n\nexport class CodexTokenUsageAccumulator {\n private previousCumulativeTotal = 0;\n private previousInput = 0;\n private previousOutput = 0;\n private previousReasoning = 0;\n private previousCachedInput = 0;\n private totalInput = 0;\n private totalOutput = 0;\n private totalCacheRead = 0;\n private totalCost = 0;\n private readonly tokensByModel: Record<string, number> = {};\n\n consume(payload: Record<string, unknown>, model: string | null): CodexTokenUsageDelta | null {\n const info = usageRecord(payload[\"info\"], \"token_count.info\");\n const totalUsage = info\n ? usageRecord(info[\"total_token_usage\"], \"token_count.total_token_usage\")\n : undefined;\n const lastUsage = info\n ? usageRecord(info[\"last_token_usage\"], \"token_count.last_token_usage\")\n : undefined;\n const cumulativeTotal = tokenCount(totalUsage?.[\"total_tokens\"]);\n const hasCumulativeTotal = cumulativeTotal > 0;\n\n if (hasCumulativeTotal && cumulativeTotal === this.previousCumulativeTotal) return null;\n\n let input = 0;\n let output = 0;\n let reasoning = 0;\n let cacheRead = 0;\n if (lastUsage) {\n input = tokenCount(lastUsage[\"input_tokens\"]);\n output = tokenCount(lastUsage[\"output_tokens\"]);\n reasoning = tokenCount(lastUsage[\"reasoning_output_tokens\"]);\n cacheRead = cachedInputTokens(lastUsage);\n } else if (totalUsage && hasCumulativeTotal) {\n input = tokenCount(totalUsage[\"input_tokens\"]) - this.previousInput;\n output = tokenCount(totalUsage[\"output_tokens\"]) - this.previousOutput;\n reasoning = tokenCount(totalUsage[\"reasoning_output_tokens\"]) - this.previousReasoning;\n cacheRead = cachedInputTokens(totalUsage) - this.previousCachedInput;\n } else {\n return null;\n }\n\n if (totalUsage) {\n this.previousInput = tokenCount(totalUsage[\"input_tokens\"]);\n this.previousOutput = tokenCount(totalUsage[\"output_tokens\"]);\n this.previousReasoning = tokenCount(totalUsage[\"reasoning_output_tokens\"]);\n this.previousCachedInput = cachedInputTokens(totalUsage);\n }\n if (hasCumulativeTotal) this.previousCumulativeTotal = cumulativeTotal;\n\n const normalizedInput = Math.max(0, input);\n const normalizedOutput = Math.max(0, output);\n const normalizedReasoning = Math.max(0, reasoning);\n const normalizedCacheRead = Math.max(0, cacheRead);\n if (\n normalizedInput === 0 &&\n normalizedOutput === 0 &&\n normalizedReasoning === 0 &&\n normalizedCacheRead === 0\n ) {\n return null;\n }\n\n const tokens: MessageTokens = {\n input: normalizedInput,\n output: normalizedOutput,\n reasoning: normalizedReasoning || undefined,\n cache_read: normalizedCacheRead || undefined,\n };\n const cost = estimateTokenCost(model, tokens);\n const modelTokens = normalizedInput + normalizedOutput + normalizedReasoning;\n if (model && modelTokens > 0) {\n this.tokensByModel[model] = (this.tokensByModel[model] ?? 0) + modelTokens;\n }\n this.totalInput += normalizedInput;\n this.totalOutput += normalizedOutput + normalizedReasoning;\n this.totalCacheRead += normalizedCacheRead;\n this.totalCost += cost ?? 0;\n\n return { tokens, model, cost };\n }\n\n stats(messageCount = 0): SessionStats {\n return {\n message_count: messageCount,\n total_input_tokens: this.totalInput,\n total_output_tokens: this.totalOutput,\n total_cache_read_tokens: this.totalCacheRead || undefined,\n total_cost: this.totalCost,\n cost_source: this.totalCost > 0 ? \"estimated\" : undefined,\n };\n }\n\n modelUsage(): Record<string, number> | undefined {\n return Object.keys(this.tokensByModel).length > 0 ? { ...this.tokensByModel } : undefined;\n }\n}\n","import { existsSync, lstatSync, readdirSync, readFileSync } from \"node:fs\";\nimport { homedir, platform } from \"node:os\";\nimport { join, normalize } from \"node:path\";\nimport { getAgentCatalogEntry } from \"../contract/agent-catalog.js\";\nimport {\n DatabaseSessionSource,\n filteredSession,\n getParsedSession,\n matchesScanWindow,\n parsedSession,\n SessionScanError,\n} from \"./base.js\";\nimport type { AgentScanOptions, AgentSourceOptions } from \"./base.js\";\nimport type {\n SessionHead,\n SessionDetail,\n Message,\n MessagePart,\n ToolPartState,\n} from \"../types/index.js\";\nimport { firstExisting, readEnvPath } from \"../discovery/paths.js\";\nimport { openDbReadOnly, isSqliteAvailable, type SQLiteDatabase } from \"../utils/sqlite.js\";\nimport { resolveSessionTitle } from \"../utils/title-fallback.js\";\nimport { isInternalEventType } from \"../utils/parse-cleanup.js\";\nimport {\n cleanInternalText,\n cleanParsedMessages,\n firstUserMessageTitle,\n} from \"../utils/session-normalization.js\";\nimport { perf } from \"../utils/perf.js\";\nimport { estimateTokenCost } from \"../utils/cost.js\";\nimport { getCoreDiagnostics } from \"../utils/diagnostics.js\";\nimport { asArray, asRecord } from \"../utils/narrow.js\";\n\nexport function resolveCursorDataRoot(): string | null {\n const override = readEnvPath(\"CURSOR_DATA_PATH\");\n if (override) return override;\n\n const currentPlatform = platform();\n if (currentPlatform === \"darwin\") {\n return firstExisting(join(homedir(), \"Library\", \"Application Support\", \"Cursor\", \"User\"));\n }\n if (currentPlatform === \"linux\") {\n const configRoot = readEnvPath(\"XDG_CONFIG_HOME\") ?? join(homedir(), \".config\");\n return firstExisting(join(configRoot, \"Cursor\", \"User\"));\n }\n if (currentPlatform === \"win32\") {\n const appData = readEnvPath(\"APPDATA\") ?? join(homedir(), \"AppData\", \"Roaming\");\n return firstExisting(join(appData, \"Cursor\", \"User\"));\n }\n return null;\n}\n\nimport {\n composerUpdatedAt,\n composerIdFromBubbleKey,\n convertActionToPart,\n cursorToolStatus,\n extractTimestamp,\n groupBubbleRows,\n isInternalBubble,\n mapToolTitle,\n narrowString,\n parseBubbleRow,\n parseComposerRow,\n type BubbleData,\n type BubbleRow,\n type ComposerBubbles,\n type ComposerData,\n type PendingComposer,\n} from \"./cursor-records.js\";\n\n// ---------------------------------------------------------------------------\n// CursorAgent\n// ---------------------------------------------------------------------------\n\nconst AGENT_METADATA = getAgentCatalogEntry(\"cursor\");\n\nexport class CursorAgent extends DatabaseSessionSource {\n readonly name = AGENT_METADATA.name;\n readonly displayName = AGENT_METADATA.displayName;\n\n private dbPath: string | null = null;\n\n private composerCache = new Map<string, ComposerData>();\n private directoryCache = new Map<string, string>();\n\n constructor(private readonly options: AgentSourceOptions = {}) {\n super();\n }\n\n private getDataRoot(): string | null {\n return this.options.sourceRoot ?? resolveCursorDataRoot();\n }\n\n protected getDatabasePath(): string | null {\n if (!this.dbPath) {\n this.dbPath = this.findDbPath();\n }\n return this.dbPath;\n }\n\n private findDbPath(): string | null {\n if (!isSqliteAvailable()) return null;\n const dataPath = this.getDataRoot();\n if (!dataPath) return null;\n return join(dataPath, \"globalStorage\", \"state.vscdb\");\n }\n\n getSessionWatchPlan() {\n const dataPath = this.getDataRoot();\n return {\n status: \"supported\" as const,\n targets: dataPath\n ? [\n {\n root: dataPath,\n path: join(dataPath, \"globalStorage\", \"state.vscdb\"),\n },\n {\n root: dataPath,\n path: join(dataPath, \"workspaceStorage\"),\n // Read-only SQLite opens can rewrite shared memory without changing sessions.\n ignoredFileNames: [\"state.vscdb-shm\"],\n },\n ]\n : [],\n };\n }\n\n /**\n * Build a map of composerId → workspace folder path by reading\n * workspaceStorage/{id}/workspace.json and the corresponding state.vscdb.\n */\n private buildWorkspacePathMap(): Map<string, string> {\n const map = new Map<string, string>();\n const dataPath = this.getDataRoot();\n if (!dataPath) return map;\n\n const wsStoragePath = join(dataPath, \"workspaceStorage\");\n if (!existsSync(wsStoragePath)) return map;\n\n let entryNames: string[];\n try {\n entryNames = readdirSync(wsStoragePath) as string[];\n } catch {\n return map;\n }\n\n for (const name of entryNames) {\n const wsDir = join(wsStoragePath, name);\n try {\n if (!lstatSync(wsDir).isDirectory()) continue;\n } catch {\n continue;\n }\n const wsJsonPath = join(wsDir, \"workspace.json\");\n if (!existsSync(wsJsonPath)) continue;\n\n // Parse workspace.json to get the project folder path\n let workspacePath: string;\n try {\n const data = asRecord(JSON.parse(readFileSync(wsJsonPath, \"utf-8\")));\n const uri =\n narrowString(\"workspaceJson.folder\", data?.folder) ??\n narrowString(\"workspaceJson.workspace\", data?.workspace) ??\n \"\";\n if (!uri) continue;\n workspacePath = normalize(decodeURIComponent(uri.replace(/^file:\\/\\//, \"\")));\n } catch {\n continue;\n }\n\n // Read composer IDs from this workspace's state.vscdb (ItemTable)\n const wsDbPath = join(wsDir, \"state.vscdb\");\n if (!existsSync(wsDbPath)) continue;\n\n const wsDb = openDbReadOnly(wsDbPath);\n if (!wsDb) continue;\n\n try {\n const row = wsDb\n .prepare(\"SELECT value FROM ItemTable WHERE key = 'composer.composerData'\")\n .get() as { value: string } | undefined;\n if (!row?.value) continue;\n\n const parsed: unknown = JSON.parse(row.value);\n const composers = asArray(asRecord(parsed)?.allComposers) ?? asArray(parsed) ?? [];\n\n for (const item of composers) {\n const composer = asRecord(item);\n if (!composer) continue;\n const id =\n narrowString(\"workspaceComposer.composerId\", composer.composerId) ??\n narrowString(\"workspaceComposer.id\", composer.id);\n if (id) map.set(id, workspacePath);\n }\n } catch {\n // skip unreadable workspace db\n } finally {\n wsDb.close();\n }\n }\n\n return map;\n }\n\n isAvailable(): boolean {\n this.dbPath = this.findDbPath();\n return this.dbPath !== null && existsSync(this.dbPath);\n }\n\n scan(options?: AgentScanOptions): SessionHead[] {\n this.composerCache.clear();\n this.directoryCache.clear();\n if (!this.getDatabasePath()) return [];\n\n const scanMarker = perf.start(\"cursor:scan\");\n\n const dbMarker = perf.start(\"openDatabase\");\n const db = this.openDatabase();\n perf.end(dbMarker);\n\n if (!db) throw new SessionScanError(this.name, \"opening the database\");\n\n // Build composerId → workspace path map from workspaceStorage\n const wsMarker = perf.start(\"buildWorkspacePathMap\");\n const workspacePathMap = this.buildWorkspacePathMap();\n perf.end(wsMarker);\n\n try {\n const rows = db\n .prepare(\"SELECT key, value FROM cursorDiskKV WHERE key LIKE 'composerData:%'\")\n .all() as Array<{ key: string; value: string }>;\n\n // Heads are emitted by composer order regardless of which phase produced\n // them, so the scan output does not depend on how bubbles are read.\n const emitted = new Map<number, SessionHead>();\n const pending: PendingComposer[] = [];\n let order = 0;\n options?.onProgress?.({ total: rows.length, processed: 0, sessions: 0 });\n let processed = 0;\n\n for (const row of rows) {\n try {\n const composer = parseComposerRow(row.value);\n if (!composer || (!composer.id && !composer.composerId)) continue;\n\n const composerId = composer.id || composer.composerId || \"\";\n const createdAt = composer.createdAt ?? 0;\n const updatedAt = composerUpdatedAt(composer);\n if (!matchesScanWindow(updatedAt, options)) continue;\n\n const fastTitle = this.extractTitle(composer);\n const hasFastMessages = Array.isArray(composer.chatMessages);\n const fastMessageCount = composer.chatMessages?.length ?? 0;\n const hasSubagents =\n Array.isArray(composer.subagentInfos) && composer.subagentInfos.length > 0;\n if (options?.fast) {\n const directory = workspacePathMap.get(composerId) ?? \"\";\n const head = this.captureSessionPricingMisses(() => {\n const totalCost =\n estimateTokenCost(composer.modelConfig?.modelName ?? composer.model, {\n input: composer.inputTokenCount ?? 0,\n output: composer.outputTokenCount ?? 0,\n }) ?? 0;\n return getParsedSession(\n hasFastMessages && fastMessageCount === 0 && !hasSubagents\n ? filteredSession<SessionHead>(\"no visible messages\")\n : parsedSession<SessionHead>({\n ...this.sessionIdentity(composerId),\n title: fastTitle,\n directory,\n time_created: createdAt,\n time_updated: updatedAt || undefined,\n stats: {\n message_count: fastMessageCount,\n total_input_tokens: composer.inputTokenCount ?? 0,\n total_output_tokens: composer.outputTokenCount ?? 0,\n total_cost: totalCost,\n cost_source: totalCost > 0 ? \"estimated\" : undefined,\n },\n }),\n );\n });\n if (!head) continue;\n emitted.set(order, head);\n order += 1;\n this.composerCache.set(composerId, composer);\n if (directory) this.directoryCache.set(composerId, directory);\n continue;\n }\n\n pending.push({ composer, composerId, createdAt, updatedAt, hasSubagents, order });\n order += 1;\n } catch {\n // skip malformed entries\n } finally {\n processed += 1;\n options?.onProgress?.({ total: rows.length, processed, sessions: emitted.size });\n }\n }\n\n // Second phase: one ordered pass over every bubble row. Keys share the\n // composer prefix, so each group arrives contiguously and only one group\n // is held at a time — replacing two full scans per composer.\n const bubbleMarker = perf.start(\"cursor:bubbles\");\n const wanted = new Map(pending.map((entry) => [entry.composerId, entry]));\n this.forEachComposerBubbles(db, wanted, (bubbles) => {\n const entry = wanted.get(bubbles.composerId);\n if (!entry) return;\n wanted.delete(bubbles.composerId);\n const head = this.captureSessionPricingMisses(() =>\n this.buildScanHead(entry, bubbles, workspacePathMap),\n );\n if (head) emitted.set(entry.order, head);\n });\n // Composers with no bubbles at all still go through the same builder.\n for (const entry of wanted.values()) {\n const head = this.captureSessionPricingMisses(() =>\n this.buildScanHead(\n entry,\n { composerId: entry.composerId, byKey: [], byRowId: [] },\n workspacePathMap,\n ),\n );\n if (head) emitted.set(entry.order, head);\n }\n perf.end(bubbleMarker);\n\n const heads = [...emitted.entries()]\n .sort(([left], [right]) => left - right)\n .map(([, head]) => head);\n options?.onProgress?.({ total: rows.length, processed, sessions: heads.length });\n\n perf.end(scanMarker);\n return heads;\n } catch (error) {\n throw new SessionScanError(this.name, \"reading composers\", { cause: error });\n } finally {\n db.close();\n }\n }\n\n getSessionData(sessionId: string): SessionDetail {\n // Ensure dbPath is set\n if (!this.dbPath) {\n this.dbPath = this.findDbPath();\n }\n if (!this.dbPath) {\n throw new Error(\"Cursor database is missing\");\n }\n\n const db = this.openDatabase();\n if (!db) {\n throw new Error(\"Cursor database is missing\");\n }\n\n try {\n // Try cached composer data first\n let composer = this.composerCache.get(sessionId);\n\n if (!composer) {\n // Try loading directly by sessionId (might be composerId)\n composer = this.loadComposer(db, sessionId) ?? undefined;\n }\n\n if (!composer) {\n // sessionId might be a requestId - try to find the composer\n const composerId = this.findComposerIdByRequestId(db, sessionId);\n if (composerId) {\n composer = this.loadComposer(db, composerId) ?? undefined;\n }\n }\n\n if (!composer) {\n throw new Error(`Session not found: ${sessionId}`);\n }\n\n const composerId = composer.id || composer.composerId || \"\";\n const createdAt = composer.createdAt ?? 0;\n const updatedAt = composerUpdatedAt(composer);\n\n // Load messages from bubbles (like agent-dump does)\n const messages = this.loadMessagesFromBubbles(\n db,\n composerId,\n composer.modelConfig?.modelName ?? composer.model ?? null,\n );\n\n // Append subagent messages\n this.appendSubagentMessages(db, composer, messages);\n const cleanedMessages = cleanParsedMessages(messages);\n const title = this.extractTitle(composer, cleanedMessages);\n\n // Aggregate stats\n let totalInputTokens = 0;\n let totalOutputTokens = 0;\n let totalCost = 0;\n\n for (const msg of cleanedMessages) {\n totalInputTokens += msg.tokens?.input ?? 0;\n totalOutputTokens += msg.tokens?.output ?? 0;\n totalCost += msg.cost ?? 0;\n }\n\n // Use session-level token counts if per-message counts are zero\n if (totalInputTokens === 0) totalInputTokens = composer.inputTokenCount ?? 0;\n if (totalOutputTokens === 0) totalOutputTokens = composer.outputTokenCount ?? 0;\n if (totalCost === 0) {\n totalCost =\n estimateTokenCost(composer.modelConfig?.modelName ?? composer.model, {\n input: totalInputTokens,\n output: totalOutputTokens,\n }) ?? 0;\n }\n\n const directory =\n this.directoryCache.get(composerId) ?? this.buildWorkspacePathMap().get(composerId) ?? \"\";\n\n return {\n ...this.sessionIdentity(composerId),\n title,\n directory,\n time_created: createdAt,\n time_updated: updatedAt || undefined,\n stats: {\n message_count: cleanedMessages.length,\n total_input_tokens: totalInputTokens,\n total_output_tokens: totalOutputTokens,\n total_cost: totalCost,\n cost_source: totalCost > 0 ? \"estimated\" : undefined,\n },\n messages: cleanedMessages,\n };\n } finally {\n db.close();\n }\n }\n\n // --- Private helpers ---\n\n private openDatabase(): SQLiteDatabase | null {\n if (!this.dbPath) return null;\n return openDbReadOnly(this.dbPath);\n }\n\n /**\n * Streams every bubble row once, in key order, handing each composer's group\n * to the caller. A key-ordered scan keeps a composer's bubbles contiguous, so\n * only one group is materialized at a time.\n */\n private forEachComposerBubbles(\n db: SQLiteDatabase,\n wanted: Map<string, PendingComposer>,\n onGroup: (bubbles: ComposerBubbles) => void,\n ): void {\n if (wanted.size === 0) return;\n\n let currentId: string | null = null;\n let group: BubbleRow[] = [];\n const flush = () => {\n if (currentId != null && group.length > 0) onGroup(groupBubbleRows(group));\n group = [];\n };\n\n const rows = db\n .prepare(\n \"SELECT rowid AS row_id, key, value FROM cursorDiskKV WHERE key LIKE 'bubbleId:%' ORDER BY key\",\n )\n .iterate() as Iterable<BubbleRow>;\n for (const row of rows) {\n const composerId = composerIdFromBubbleKey(row.key);\n if (composerId !== currentId) {\n flush();\n currentId = composerId;\n }\n if (wanted.has(composerId)) group.push(row);\n }\n flush();\n }\n\n /** Builds the head for one composer from bubbles that were parsed once. */\n private buildScanHead(\n entry: PendingComposer,\n bubbles: ComposerBubbles,\n workspacePathMap: Map<string, string>,\n ): SessionHead | null {\n const { composer, composerId, createdAt, updatedAt, hasSubagents } = entry;\n const legacySessionId = this.legacySessionIdFromBubbles(bubbles);\n\n const parsedMessages = cleanParsedMessages(\n this.messagesFromBubbles(bubbles, composer.modelConfig?.modelName ?? composer.model ?? null),\n );\n const messages = getParsedSession(\n parsedMessages.length === 0 && !hasSubagents\n ? filteredSession<Message[]>(\"no visible messages\")\n : parsedSession(parsedMessages),\n );\n if (!messages) return null;\n if (legacySessionId) this.migrateLegacySessionMeta(legacySessionId, composerId);\n\n const title = this.extractTitle(composer, messages);\n const directory = workspacePathMap.get(composerId) ?? \"\";\n\n const modelUsageMap: Record<string, number> = {};\n let totalCost = 0;\n for (const msg of messages) {\n totalCost += msg.cost ?? 0;\n if (msg.model) {\n const msgTokens = (msg.tokens?.input ?? 0) + (msg.tokens?.output ?? 0);\n if (msgTokens > 0) {\n modelUsageMap[msg.model] = (modelUsageMap[msg.model] ?? 0) + msgTokens;\n }\n }\n }\n const hasModelUsage = Object.keys(modelUsageMap).length > 0;\n\n this.composerCache.set(composerId, composer);\n if (directory) this.directoryCache.set(composerId, directory);\n return {\n ...this.sessionIdentity(composerId),\n title,\n directory,\n time_created: createdAt,\n time_updated: updatedAt || undefined,\n stats: {\n message_count: messages.length,\n total_input_tokens: composer.inputTokenCount ?? 0,\n total_output_tokens: composer.outputTokenCount ?? 0,\n total_cost: totalCost,\n cost_source: totalCost > 0 ? \"estimated\" : undefined,\n },\n model_usage: hasModelUsage ? modelUsageMap : undefined,\n };\n }\n\n private legacySessionIdFromBubbles(bubbles: ComposerBubbles): string | null {\n for (const entry of bubbles.byKey) {\n const requestId = entry.bubble.requestId?.trim();\n if (requestId) return requestId;\n }\n return null;\n }\n\n private migrateLegacySessionMeta(legacySessionId: string, sessionId: string): void {\n if (legacySessionId === sessionId) return;\n const legacyMeta = this.sessionMetaMap.get(legacySessionId);\n if (!legacyMeta) return;\n\n this.sessionMetaMap.delete(legacySessionId);\n if (!this.sessionMetaMap.has(sessionId)) {\n this.sessionMetaMap.set(sessionId, { ...legacyMeta, id: sessionId });\n }\n getCoreDiagnostics()?.info?.(\"cursor.session_id_migrated\", {\n legacy_session_id: legacySessionId,\n session_id: sessionId,\n });\n }\n\n /** Find composerId by requestId (reverse lookup) */\n private findComposerIdByRequestId(db: SQLiteDatabase, requestId: string): string | null {\n try {\n const rows = db\n .prepare(\"SELECT key, value FROM cursorDiskKV WHERE key LIKE 'bubbleId:%' AND value LIKE ?\")\n .all(`%\"requestId\":\"${requestId}\"%`) as Array<{ key: string; value: string }>;\n\n for (const row of rows) {\n try {\n const bubble = parseBubbleRow(row.value);\n if (bubble?.requestId === requestId) {\n // Extract composerId from key (bubbleId:{composerId}:{bubbleId})\n const keyParts = row.key.split(\":\");\n if (keyParts.length >= 2 && keyParts[1]) {\n return keyParts[1];\n }\n }\n } catch {\n // skip malformed bubbles\n }\n }\n } catch {\n // ignore errors\n }\n return null;\n }\n\n /** Extract title from composer (like agent-dump) */\n private extractTitle(composer: ComposerData, messages: Message[] = []): string {\n const explicit = composer.name || composer.title;\n const messageTitle = firstUserMessageTitle(messages) ?? composer.text;\n return resolveSessionTitle(explicit, messageTitle, null);\n }\n\n /**\n * Load one composer's bubbles, for the detail path that only needs a\n * single session. A failing bubble query throws instead of returning [] —\n * a broken database must not read as an empty session.\n */\n private loadMessagesFromBubbles(\n db: SQLiteDatabase,\n composerId: string,\n initialModelName: string | null,\n ): Message[] {\n const rows = this.scanStep(\n \"reading composer bubbles\",\n this.getDatabasePath() ?? \"\",\n () =>\n db\n .prepare(\"SELECT rowid AS row_id, key, value FROM cursorDiskKV WHERE key LIKE ?\")\n .all(`bubbleId:${composerId}:%`) as BubbleRow[],\n );\n return this.messagesFromBubbles(groupBubbleRows(rows), initialModelName);\n }\n\n /** Build messages from bubbles already parsed once, in insertion order. */\n private messagesFromBubbles(\n bubbles: ComposerBubbles,\n initialModelName: string | null,\n ): Message[] {\n const messages: Message[] = [];\n\n {\n let activeModelName: string | null = initialModelName;\n let messageIndex = 0;\n\n for (const entry of bubbles.byRowId) {\n {\n const bubble = entry.bubble;\n if (isInternalBubble(bubble)) continue;\n const bubbleId = entry.key.split(\":\").pop() || String(messageIndex);\n\n // Determine role: type 2 = assistant, otherwise user\n const role = bubble.type === 2 ? \"assistant\" : \"user\";\n\n // Extract timestamp\n let timestampMs = 0;\n if (bubble.timingInfo?.clientRpcSendTime) {\n timestampMs = Math.floor(bubble.timingInfo.clientRpcSendTime);\n } else if (bubble.createdAt) {\n timestampMs = bubble.createdAt;\n } else if (bubble.timestamp) {\n timestampMs = bubble.timestamp;\n }\n\n // Track model from user turn\n if (bubble.modelInfo?.modelName) {\n activeModelName = bubble.modelInfo.modelName;\n }\n\n // Extract tokens\n const inputTokens = bubble.tokenCount?.inputTokens ?? 0;\n const outputTokens = bubble.tokenCount?.outputTokens ?? 0;\n\n // Build message parts\n const parts: MessagePart[] = [];\n\n // Text content\n const text = cleanInternalText(bubble.text ?? \"\");\n if (text) {\n parts.push({ type: \"text\", text, time_created: timestampMs });\n }\n\n // Tool calls from toolFormerData\n if (bubble.toolFormerData) {\n const toolPart = this.convertToolFormerData(bubble.toolFormerData, timestampMs);\n if (toolPart) {\n parts.push(toolPart);\n }\n }\n\n // Skip empty messages\n if (parts.length === 0) continue;\n\n const modelName = bubble.modelInfo?.modelName ?? activeModelName;\n const tokens = { input: inputTokens, output: outputTokens };\n const cost = estimateTokenCost(modelName, tokens);\n\n messages.push({\n id: `cursor-${bubbles.composerId}-${bubbleId}`,\n role: role as Message[\"role\"],\n agent: \"cursor\",\n time_created: timestampMs,\n time_completed: null,\n mode: role === \"assistant\" && parts.some((p) => p.type === \"tool\") ? \"tool\" : null,\n model: modelName,\n provider: null,\n tokens,\n cost: cost ?? 0,\n cost_source: cost !== null ? \"estimated\" : undefined,\n parts,\n });\n\n messageIndex++;\n }\n }\n }\n\n return messages;\n }\n\n /** Convert toolFormerData to MessagePart */\n private convertToolFormerData(\n toolData: BubbleData[\"toolFormerData\"],\n timestampMs: number,\n ): MessagePart | null {\n if (!toolData || !toolData.name) return null;\n\n const toolName = toolData.name;\n const normalizedName = toolName === \"create_plan\" ? \"plan\" : mapToolTitle(toolName);\n\n // Build state\n const state: ToolPartState = {\n status: cursorToolStatus(toolData.status),\n };\n\n // Parse input params\n if (toolData.params) {\n if (typeof toolData.params === \"string\") {\n try {\n state.input = JSON.parse(toolData.params);\n } catch {\n state.input = { _raw: toolData.params };\n }\n } else {\n state.input = toolData.params;\n }\n }\n\n // Parse result/output\n if (toolData.result !== undefined) {\n let result = toolData.result;\n if (typeof toolData.result === \"string\") {\n try {\n result = JSON.parse(toolData.result);\n } catch {}\n }\n state.output = result;\n if (state.status === \"error\") {\n const resultRecord = asRecord(result);\n state.error =\n resultRecord?.error ?? resultRecord?.message ?? resultRecord?.stderr ?? result;\n }\n }\n\n // Handle plan tool specially\n if (toolName === \"create_plan\") {\n const planText = String(asRecord(state.input)?.plan ?? \"\").trim();\n if (planText) {\n return {\n type: \"plan\",\n text: planText,\n approval_status: state.status === \"completed\" ? \"success\" : \"fail\",\n time_created: timestampMs,\n };\n }\n }\n\n return {\n type: \"tool\",\n tool: normalizedName,\n callID: toolData.toolCallId || \"\",\n title: `Tool: ${normalizedName}`,\n state,\n time_created: timestampMs,\n };\n }\n\n private loadComposer(db: SQLiteDatabase, sessionId: string): ComposerData | null {\n const row = db\n .prepare(\"SELECT value FROM cursorDiskKV WHERE key = ?\")\n .get(`composerData:${sessionId}`) as { value: string } | undefined;\n\n if (!row) return null;\n\n return parseComposerRow(row.value);\n }\n\n private loadBubble(db: SQLiteDatabase, sessionId: string): BubbleData | null {\n const row = db\n .prepare(\"SELECT value FROM cursorDiskKV WHERE key = ?\")\n .get(`bubble:${sessionId}`) as { value: string } | undefined;\n\n if (!row) return null;\n\n return parseBubbleRow(row.value);\n }\n\n private appendSubagentMessages(\n db: SQLiteDatabase,\n composer: ComposerData,\n messages: Message[],\n ): void {\n const subagentInfos = composer.subagentInfos;\n if (!Array.isArray(subagentInfos) || subagentInfos.length === 0) return;\n\n for (const subInfo of subagentInfos) {\n if (!subInfo.id) continue;\n\n const bubble = this.loadBubble(db, subInfo.id);\n if (!bubble || !Array.isArray(bubble.chatMessages)) continue;\n\n for (const chatMsg of bubble.chatMessages) {\n const role = chatMsg.role?.trim().toLowerCase();\n if (role !== \"user\" && role !== \"assistant\") continue;\n\n const timestampMs = extractTimestamp(chatMsg);\n const parts: MessagePart[] = [];\n\n const text = cleanInternalText(chatMsg.text ?? \"\");\n if (text) {\n parts.push({ type: \"text\", text, time_created: timestampMs });\n }\n\n if (role === \"assistant\" && Array.isArray(chatMsg.actions)) {\n for (const action of chatMsg.actions) {\n if (isInternalEventType(action.type) || isInternalEventType(action.tool)) continue;\n const part = convertActionToPart(action, timestampMs);\n if (part) parts.push(part);\n }\n }\n\n if (parts.length === 0) continue;\n\n messages.push({\n id: `cursor-sub-${subInfo.id}`,\n role: role as Message[\"role\"],\n agent: \"cursor\",\n time_created: timestampMs,\n time_completed: null,\n mode: null,\n model: null,\n provider: null,\n tokens: undefined,\n cost: 0,\n subagent_id: subInfo.id,\n nickname: subInfo.nickname ?? subInfo.title,\n parts,\n });\n }\n }\n }\n}\n","import { normalizeMessageParts } from \"../contract/message-part.js\";\nimport type { MessagePart, ToolPartState } from \"../types/index.js\";\nimport { isInternalEventType } from \"../utils/parse-cleanup.js\";\nimport { cleanInternalText } from \"../utils/session-normalization.js\";\nimport type { DatabaseRow } from \"../utils/sqlite.js\";\nimport {\n asArray,\n asNumber,\n asRecord,\n asString,\n narrowField,\n safeParseJsonRecord,\n} from \"../utils/narrow.js\";\n\n// ---------------------------------------------------------------------------\n// Cursor data model interfaces\n// ---------------------------------------------------------------------------\n\nexport interface ComposerData {\n id?: string;\n composerId?: string;\n text?: string;\n name?: string;\n title?: string;\n createdAt?: number;\n updatedAt?: number;\n lastSendTime?: number;\n lastUpdatedAt?: number;\n model?: string;\n modelConfig?: { modelName?: string };\n inputTokenCount?: number;\n outputTokenCount?: number;\n subagentInfos?: SubagentInfo[];\n chatMessages?: ChatMessage[];\n usageData?: {\n contextTokensUsed?: number;\n contextTokenLimit?: number;\n contextUsagePercent?: number;\n };\n}\n\nexport interface BubbleData {\n id?: string;\n composerId?: string;\n chatMessages?: ChatMessage[];\n type?: number; // 1 = user, 2 = assistant\n text?: string;\n requestId?: string;\n createdAt?: number;\n timestamp?: number;\n timingInfo?: {\n clientRpcSendTime?: number;\n clientSettleTime?: number;\n clientEndTime?: number;\n };\n tokenCount?: {\n inputTokens?: number;\n outputTokens?: number;\n };\n modelInfo?: {\n modelName?: string;\n };\n toolFormerData?: {\n name?: string;\n toolCallId?: string;\n status?: string;\n params?: unknown;\n result?: unknown;\n additionalData?: Record<string, unknown>;\n };\n [key: string]: unknown;\n}\n\ninterface SubagentInfo {\n id?: string;\n composerId?: string;\n title?: string;\n nickname?: string;\n}\n\ninterface ChatMessage {\n role: string;\n text?: string;\n createdAt?: number;\n timestamp?: number;\n actions?: ActionEntry[];\n isCompletion?: boolean;\n [key: string]: unknown;\n}\n\ninterface ActionEntry {\n type?: string;\n tool?: string;\n input?: Record<string, unknown>;\n output?: unknown;\n state?: Record<string, unknown>;\n [key: string]: unknown;\n}\n\n// ---------------------------------------------------------------------------\n// Safe parsing of external rows — cursorDiskKV values and workspace.json are\n// untrusted (cross Cursor-version drift), so their fields are narrowed\n// individually instead of blindly cast. A field that's absent behaves like\n// today's optional-field fallback (?? 0 / skip); a field that's present but\n// wrong-typed additionally reports once via diagnostics.\n// ---------------------------------------------------------------------------\n\nexport function narrowString(field: string, value: unknown): string | undefined {\n return narrowField(\"cursor\", field, value, asString);\n}\n\nfunction narrowNumber(field: string, value: unknown): number | undefined {\n return narrowField(\"cursor\", field, value, asNumber);\n}\n\nfunction parseSubagentInfos(value: unknown): SubagentInfo[] | undefined {\n const arr = asArray(value);\n if (arr === undefined) return undefined;\n const infos: SubagentInfo[] = [];\n for (const item of arr) {\n const record = asRecord(item);\n if (!record) continue;\n infos.push({\n id: narrowString(\"subagentInfo.id\", record.id),\n composerId: narrowString(\"subagentInfo.composerId\", record.composerId),\n title: narrowString(\"subagentInfo.title\", record.title),\n nickname: narrowString(\"subagentInfo.nickname\", record.nickname),\n });\n }\n return infos;\n}\n\nfunction parseChatMessages(value: unknown): ChatMessage[] | undefined {\n const arr = asArray(value);\n if (arr === undefined) return undefined;\n const messages: ChatMessage[] = [];\n for (const item of arr) {\n const record = asRecord(item);\n if (!record) continue;\n const role = narrowString(\"chatMessage.role\", record.role);\n if (role === undefined) continue;\n messages.push({ ...record, role, text: narrowString(\"chatMessage.text\", record.text) });\n }\n return messages;\n}\n\n/** Parse a `composerData:*` row value into a field-validated ComposerData. */\nexport function parseComposerRow(value: string): ComposerData | null {\n const record = safeParseJsonRecord(value);\n if (!record) return null;\n\n const modelConfig = asRecord(record.modelConfig);\n\n return {\n id: narrowString(\"composer.id\", record.id),\n composerId: narrowString(\"composer.composerId\", record.composerId),\n text: narrowString(\"composer.text\", record.text),\n name: narrowString(\"composer.name\", record.name),\n title: narrowString(\"composer.title\", record.title),\n createdAt: narrowNumber(\"composer.createdAt\", record.createdAt),\n updatedAt: narrowNumber(\"composer.updatedAt\", record.updatedAt),\n lastSendTime: narrowNumber(\"composer.lastSendTime\", record.lastSendTime),\n lastUpdatedAt: narrowNumber(\"composer.lastUpdatedAt\", record.lastUpdatedAt),\n model: narrowString(\"composer.model\", record.model),\n modelConfig: modelConfig\n ? { modelName: narrowString(\"composer.modelConfig.modelName\", modelConfig.modelName) }\n : undefined,\n inputTokenCount: narrowNumber(\"composer.inputTokenCount\", record.inputTokenCount),\n outputTokenCount: narrowNumber(\"composer.outputTokenCount\", record.outputTokenCount),\n subagentInfos: parseSubagentInfos(record.subagentInfos),\n chatMessages: parseChatMessages(record.chatMessages),\n };\n}\n\nexport interface BubbleRow extends DatabaseRow {\n row_id: number;\n key: string;\n value: string;\n}\n\ninterface BubbleEntry {\n rowId: number;\n key: string;\n bubble: BubbleData;\n}\n\n/**\n * One composer's bubbles, parsed once and offered in both orders the readers\n * need: request ids come from the key-ordered view, messages from insertion\n * order.\n */\nexport interface ComposerBubbles {\n composerId: string;\n byKey: BubbleEntry[];\n byRowId: BubbleEntry[];\n}\n\n/** A composer waiting for its bubbles in the second phase of a scan. */\nexport interface PendingComposer {\n composer: ComposerData;\n composerId: string;\n createdAt: number;\n updatedAt: number;\n hasSubagents: boolean;\n order: number;\n}\n\nexport function composerIdFromBubbleKey(key: string): string {\n const start = key.indexOf(\":\") + 1;\n const end = key.indexOf(\":\", start);\n return end === -1 ? key.slice(start) : key.slice(start, end);\n}\n\nexport function groupBubbleRows(rows: BubbleRow[]): ComposerBubbles {\n const byKey: BubbleEntry[] = [];\n for (const row of rows) {\n const bubble = parseBubbleRow(row.value);\n if (bubble) byKey.push({ rowId: row.row_id, key: row.key, bubble });\n }\n byKey.sort((left, right) => left.key.localeCompare(right.key));\n return {\n composerId: rows.length > 0 ? composerIdFromBubbleKey(rows[0]!.key) : \"\",\n byKey,\n byRowId: [...byKey].sort((left, right) => left.rowId - right.rowId),\n };\n}\n\n/** Parse a `bubbleId:*` / `bubble:*` row value into a field-validated BubbleData. */\nexport function parseBubbleRow(value: string): BubbleData | null {\n const record = safeParseJsonRecord(value);\n if (!record) return null;\n\n const timingInfo = asRecord(record.timingInfo);\n const tokenCount = asRecord(record.tokenCount);\n const modelInfo = asRecord(record.modelInfo);\n const toolFormerData = asRecord(record.toolFormerData);\n\n return {\n ...record,\n id: narrowString(\"bubble.id\", record.id),\n composerId: narrowString(\"bubble.composerId\", record.composerId),\n chatMessages: parseChatMessages(record.chatMessages),\n type: narrowNumber(\"bubble.type\", record.type),\n text: narrowString(\"bubble.text\", record.text),\n requestId: narrowString(\"bubble.requestId\", record.requestId),\n createdAt: narrowNumber(\"bubble.createdAt\", record.createdAt),\n timestamp: narrowNumber(\"bubble.timestamp\", record.timestamp),\n timingInfo: timingInfo\n ? {\n clientRpcSendTime: narrowNumber(\n \"bubble.timingInfo.clientRpcSendTime\",\n timingInfo.clientRpcSendTime,\n ),\n clientSettleTime: narrowNumber(\n \"bubble.timingInfo.clientSettleTime\",\n timingInfo.clientSettleTime,\n ),\n clientEndTime: narrowNumber(\"bubble.timingInfo.clientEndTime\", timingInfo.clientEndTime),\n }\n : undefined,\n tokenCount: tokenCount\n ? {\n inputTokens: narrowNumber(\"bubble.tokenCount.inputTokens\", tokenCount.inputTokens),\n outputTokens: narrowNumber(\"bubble.tokenCount.outputTokens\", tokenCount.outputTokens),\n }\n : undefined,\n modelInfo: modelInfo\n ? { modelName: narrowString(\"bubble.modelInfo.modelName\", modelInfo.modelName) }\n : undefined,\n toolFormerData: toolFormerData\n ? {\n name: narrowString(\"bubble.toolFormerData.name\", toolFormerData.name),\n toolCallId: narrowString(\"bubble.toolFormerData.toolCallId\", toolFormerData.toolCallId),\n status: narrowString(\"bubble.toolFormerData.status\", toolFormerData.status),\n params: toolFormerData.params,\n result: toolFormerData.result,\n additionalData: asRecord(toolFormerData.additionalData),\n }\n : undefined,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nconst CURSOR_TOOL_TITLE_MAP: Record<string, string> = {\n read_file_v2: \"read\",\n edit_file_v2: \"edit\",\n run_terminal_command_v2: \"bash\",\n ripgrep_raw_search: \"grep\",\n glob_file_search: \"glob\",\n};\n\nexport function mapToolTitle(toolName: string): string {\n return CURSOR_TOOL_TITLE_MAP[toolName] ?? toolName;\n}\n\n/** Normalize tool output into MessagePart[] */\nfunction normalizeToolOutputParts(output: unknown, timestampMs: number): MessagePart[] {\n if (output == null) return [];\n\n if (typeof output === \"string\") {\n const text = cleanInternalText(output);\n return text ? [{ type: \"text\" as const, text, time_created: timestampMs }] : [];\n }\n\n if (Array.isArray(output)) {\n const parts: MessagePart[] = [];\n for (const item of output) {\n if (typeof item === \"object\" && item !== null) {\n const record = asRecord(item);\n const text = String(record?.text ?? record?.content ?? \"\");\n const cleaned = cleanInternalText(text);\n if (cleaned) parts.push({ type: \"text\", text: cleaned, time_created: timestampMs });\n } else if (typeof item === \"string\") {\n const text = cleanInternalText(item);\n if (text) parts.push({ type: \"text\", text, time_created: timestampMs });\n }\n }\n return parts;\n }\n\n // For object output, stringify for readability\n const text = cleanInternalText(String(output));\n return text ? [{ type: \"text\", text, time_created: timestampMs }] : [];\n}\n\n/** Extract a timestamp (in ms) from a chat message */\nexport function extractTimestamp(msg: ChatMessage): number {\n if (msg.createdAt && typeof msg.createdAt === \"number\" && msg.createdAt > 0) {\n return msg.createdAt;\n }\n if (msg.timestamp && typeof msg.timestamp === \"number\" && msg.timestamp > 0) {\n return msg.timestamp;\n }\n return 0;\n}\n\nexport function isInternalBubble(bubble: BubbleData): boolean {\n return [\"eventType\", \"kind\", \"subtype\", \"name\"].some((key) => isInternalEventType(bubble[key]));\n}\n\nexport function composerUpdatedAt(composer: ComposerData): number {\n return (\n composer.updatedAt ?? composer.lastUpdatedAt ?? composer.lastSendTime ?? composer.createdAt ?? 0\n );\n}\n\nexport function cursorToolStatus(status: string | undefined): ToolPartState[\"status\"] {\n if (status === \"completed\") return \"completed\";\n if (status === \"error\" || status === \"failed\") return \"error\";\n return \"running\";\n}\n\n/** Build a normalized tool state object from an action entry */\nfunction buildToolState(action: ActionEntry): ToolPartState {\n let output = action.output;\n if (action.output != null) {\n const ts = 0; // we don't have a finer-grained timestamp for the output\n const outputParts = normalizeToolOutputParts(action.output, ts);\n output = outputParts.length > 0 ? outputParts : action.output;\n }\n\n const [part] = normalizeMessageParts([\n {\n type: \"tool\",\n tool: action.tool ?? \"unknown\",\n input: action.input,\n output,\n state: action.state,\n },\n ]);\n return part?.type === \"tool\" ? part.state : { status: \"running\" };\n}\n\n/** Build a MessagePart for a tool action */\nfunction buildToolPart(action: ActionEntry, timestampMs: number): MessagePart {\n const toolName = action.tool ?? \"unknown\";\n return {\n type: \"tool\",\n tool: mapToolTitle(toolName),\n callID: action.type ? `${action.type}:${String(action.input?.id ?? \"\")}` : \"\",\n title: `Tool: ${mapToolTitle(toolName)}`,\n state: buildToolState(action),\n time_created: timestampMs,\n };\n}\n\n/** Build a MessagePart for terminal command actions */\nfunction buildTerminalToolPart(action: ActionEntry, timestampMs: number): MessagePart {\n const command = String(action.input?.command ?? \"\");\n const description = cleanInternalText(String(action.input?.commandDescription ?? \"\"));\n\n const state = buildToolState(action);\n state.input = { command };\n state.output =\n typeof action.output === \"string\"\n ? [{ type: \"text\" as const, text: action.output, time_created: timestampMs }]\n : normalizeToolOutputParts(action.output, timestampMs);\n\n return {\n type: \"tool\",\n tool: \"bash\",\n callID: \"\",\n title: description || `bash: ${command.slice(0, 60)}`,\n state,\n time_created: timestampMs,\n };\n}\n\n/** Convert an ActionEntry into a MessagePart */\nexport function convertActionToPart(action: ActionEntry, timestampMs: number): MessagePart | null {\n const toolName = action.tool ?? \"\";\n\n // Terminal commands get special handling\n if (toolName === \"run_terminal_command_v2\") {\n return buildTerminalToolPart(action, timestampMs);\n }\n\n // Generic tool call\n if (toolName && action.type === \"tool\") {\n return buildToolPart(action, timestampMs);\n }\n\n return null;\n}\n","import { existsSync } from \"node:fs\";\nimport { basename, dirname, join } from \"node:path\";\nimport { getAgentCatalogEntry } from \"../contract/agent-catalog.js\";\nimport { SingleFileSessionSource, filteredSession, parsedSession } from \"./base.js\";\nimport type {\n AgentScanOptions,\n FileSessionMeta,\n ParseSessionResult,\n SessionSourceFile,\n SessionSourceRef,\n} from \"./base.js\";\nimport type { Message, MessagePart, SessionDetail, SessionHead } from \"../types/index.js\";\nimport { firstExisting, resolveHomePath } from \"../discovery/paths.js\";\nimport { readJsonlFile } from \"../utils/jsonl.js\";\nimport { estimateTokenCost } from \"../utils/cost.js\";\nimport { asNumber, asRecord, asString, narrowField } from \"../utils/narrow.js\";\nimport { cleanInternalText } from \"../utils/session-normalization.js\";\nimport { parseAgentTimestamp } from \"../utils/timestamp.js\";\nimport { basenameTitle, normalizeTitleText, resolveSessionTitle } from \"../utils/title-fallback.js\";\nimport { TranscriptBuilder, type TranscriptMessageInput } from \"./transcript-builder.js\";\n\nconst HEAD_INDEX_VERSION = \"pi-head-v2\";\nconst PARSER_VERSION = \"pi-parser-v3\";\n\nexport function resolvePiDataRoot(): string {\n return resolveHomePath(\"PI_HOME\", \".pi\");\n}\n\ninterface SessionMeta extends FileSessionMeta {\n headIndexVersion: string;\n parserVersion: string;\n}\n\ninterface ParsedPiFile {\n sessionId: string;\n directory: string;\n createdAt: number;\n updatedAt: number;\n title: string;\n pathEntries: Record<string, unknown>[];\n}\n\nfunction narrowPiField<T>(\n field: string,\n value: unknown,\n narrow: (v: unknown) => T | undefined,\n): T | undefined {\n return narrowField(\"pi\", field, value, narrow);\n}\n\n/**\n * Reports drift only when the timestamp is present but neither a number nor\n * a string (e.g. an object); parsing goes through the shared agent parser\n * (numeric strings accepted, unparseable text reported and treated as 0).\n */\nfunction narrowTimestampMs(field: string, value: unknown): number {\n const shaped = narrowPiField(field, value, (v) =>\n typeof v === \"number\" || typeof v === \"string\" ? v : undefined,\n );\n return shaped === undefined\n ? 0\n : (parseAgentTimestamp(shaped, \"pi\", { numericStrings: true }) ?? 0);\n}\n\nfunction extractSessionIdFromFilename(filePath: string): string {\n const stem = basename(filePath, \".jsonl\");\n const underscore = stem.indexOf(\"_\");\n return underscore >= 0 ? stem.slice(underscore + 1) || stem : stem;\n}\n\nfunction isObject(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n\nfunction contentToText(content: unknown): string {\n if (typeof content === \"string\") return content;\n if (!Array.isArray(content)) return \"\";\n return content\n .map((item) => {\n if (!isObject(item)) return \"\";\n if (item[\"type\"] === \"text\") return String(item[\"text\"] ?? \"\");\n if (item[\"type\"] === \"image\") return \"[image]\";\n return \"\";\n })\n .filter(Boolean)\n .join(\"\\n\");\n}\n\nfunction normalizeTextParts(content: unknown, timestampMs: number): MessagePart[] {\n const text = cleanInternalText(contentToText(content));\n return text ? [{ type: \"text\", text, time_created: timestampMs }] : [];\n}\n\nfunction getEntryTimestamp(entry: Record<string, unknown>): number {\n return narrowTimestampMs(\"entry.timestamp\", entry[\"timestamp\"]);\n}\n\nfunction chooseLeafEntry(entries: Record<string, unknown>[]): Record<string, unknown> | null {\n for (let index = entries.length - 1; index >= 0; index -= 1) {\n if (typeof entries[index]?.[\"id\"] === \"string\") return entries[index]!;\n }\n return null;\n}\n\nfunction buildCurrentPathEntries(entries: Record<string, unknown>[]): Record<string, unknown>[] {\n const byId = new Map<string, Record<string, unknown>>();\n for (const entry of entries) {\n const id = entry[\"id\"];\n if (typeof id === \"string\" && id) byId.set(id, entry);\n }\n\n const leaf = chooseLeafEntry(entries);\n if (!leaf) return [];\n\n const path: Record<string, unknown>[] = [];\n const seen = new Set<string>();\n let current: Record<string, unknown> | undefined = leaf;\n while (current) {\n const id = String(current[\"id\"] ?? \"\");\n if (!id || seen.has(id)) break;\n seen.add(id);\n path.push(current);\n const parentId: unknown = current[\"parentId\"];\n current = typeof parentId === \"string\" ? byId.get(parentId) : undefined;\n }\n\n return path.reverse();\n}\n\nconst AGENT_METADATA = getAgentCatalogEntry(\"pi\");\n\nexport class PiAgent extends SingleFileSessionSource<SessionMeta> {\n readonly name = AGENT_METADATA.name;\n readonly displayName = AGENT_METADATA.displayName;\n\n private basePath: string | null = this.configuredSourceRoot;\n\n private findBasePath(): string | null {\n return (\n this.configuredSourceRoot ??\n firstExisting(join(resolvePiDataRoot(), \"agent\", \"sessions\"), \"data/pi\")\n );\n }\n\n getSessionWatchPlan() {\n if (this.configuredSourceRoot) {\n return {\n status: \"supported\" as const,\n targets: [{ root: dirname(this.configuredSourceRoot), path: this.configuredSourceRoot }],\n };\n }\n const dataRoot = resolvePiDataRoot();\n return {\n status: \"supported\" as const,\n targets: [\n { root: dataRoot, path: join(dataRoot, \"agent\", \"sessions\") },\n { root: \"data/pi\", path: \"data/pi\" },\n ],\n };\n }\n\n isAvailable(): boolean {\n this.basePath = this.findBasePath();\n if (!this.basePath) return false;\n return this.listSessionFiles().length > 0;\n }\n\n listSessionSources(options?: AgentScanOptions): SessionSourceRef[] {\n if (!this.basePath) return [];\n return this.listSessionFiles(options).map(({ file, stat }) => ({\n sessionId: extractSessionIdFromFilename(file),\n sourcePath: file,\n fingerprint: this.sourceFingerprint(stat),\n }));\n }\n\n getSessionData(sessionId: string): SessionDetail {\n const meta = this.sessionMetaMap.get(sessionId);\n if (!meta) throw new Error(`Session not found: ${sessionId}`);\n if (!existsSync(meta.sourcePath)) throw new Error(`Session file missing: ${meta.sourcePath}`);\n\n const parsed = this.parsePiFile(meta.sourcePath);\n const state = this.convertEntries(parsed.pathEntries);\n\n return {\n ...this.sessionIdentity(meta.id),\n title: meta.title,\n directory: meta.directory,\n time_created: meta.createdAt,\n time_updated: meta.updatedAt,\n stats: {\n message_count: state.messages.length,\n total_input_tokens: state.totalInputTokens,\n total_output_tokens: state.totalOutputTokens,\n total_cache_read_tokens: state.totalCacheReadTokens || undefined,\n total_cache_create_tokens: state.totalCacheCreateTokens || undefined,\n total_cost: state.totalCost,\n cost_source: state.costSource,\n },\n messages: state.messages,\n };\n }\n\n private listSessionFiles(options?: AgentScanOptions): SessionSourceFile[] {\n if (!this.basePath) return [];\n return this.walkFiles(\n this.basePath,\n (entry) => entry.isFile() && entry.name.endsWith(\".jsonl\"),\n { scanWindow: options },\n );\n }\n\n protected createFileSessionMeta(head: SessionHead, source: SessionSourceFile): SessionMeta {\n return this.buildFileSessionMeta({\n head,\n source,\n fingerprint: this.sourceFingerprint(source.stat),\n extras: {\n headIndexVersion: HEAD_INDEX_VERSION,\n parserVersion: PARSER_VERSION,\n },\n });\n }\n\n /** Fingerprint depends on an already-fetched stat to avoid re-statting the same file. */\n private sourceFingerprint(stat: { mtimeMs: number; size: number }): string {\n return JSON.stringify([HEAD_INDEX_VERSION, PARSER_VERSION, stat.mtimeMs, stat.size]);\n }\n\n protected override parseFileSessionHeadResult(filePath: string): ParseSessionResult<SessionHead> {\n const parsed = this.parsePiFile(filePath);\n const state = this.convertEntries(parsed.pathEntries);\n const messageCount = state.messages.length;\n if (messageCount === 0) return filteredSession(\"no visible messages\");\n\n const modelUsage = Object.keys(state.modelUsage).length > 0 ? state.modelUsage : undefined;\n return parsedSession({\n ...this.sessionIdentity(parsed.sessionId),\n title: parsed.title,\n directory: parsed.directory,\n time_created: parsed.createdAt,\n time_updated: parsed.updatedAt,\n stats: {\n message_count: messageCount,\n total_input_tokens: state.totalInputTokens,\n total_output_tokens: state.totalOutputTokens,\n total_cache_read_tokens: state.totalCacheReadTokens || undefined,\n total_cache_create_tokens: state.totalCacheCreateTokens || undefined,\n total_cost: state.totalCost,\n cost_source: state.costSource,\n },\n model_usage: modelUsage,\n });\n }\n\n private parsePiFile(filePath: string): ParsedPiFile {\n // Single streaming pass: the file is never held as a string, and header\n // selection happens inline instead of scanning a materialized record array.\n let header: Record<string, unknown> | null = null;\n let recordCount = 0;\n const entries: Record<string, unknown>[] = [];\n\n for (const record of readJsonlFile(filePath)) {\n recordCount += 1;\n if (record[\"type\"] === \"session\") {\n header ??= record;\n continue;\n }\n entries.push(record);\n }\n\n if (recordCount === 0) throw new Error(\"empty file\");\n if (!header) throw new Error(\"missing session header\");\n\n const pathEntries = buildCurrentPathEntries(entries);\n if (pathEntries.length === 0) throw new Error(\"empty session tree\");\n\n const sessionId = extractSessionIdFromFilename(filePath);\n if (!sessionId) throw new Error(\"missing session id\");\n\n const stat = this.sessionSourceFile(filePath).stat;\n const directory = String(header[\"cwd\"] ?? \"\").trim() || basename(filePath, \".jsonl\");\n const createdAt = narrowTimestampMs(\"session.timestamp\", header[\"timestamp\"]) || stat.mtimeMs;\n const updatedAt = pathEntries.reduce(\n (max, entry) => Math.max(max, getEntryTimestamp(entry)),\n createdAt,\n );\n const explicitTitle = this.extractSessionName(pathEntries);\n const messageTitle = this.extractTitle(pathEntries);\n const directoryTitle = basenameTitle(directory);\n\n return {\n sessionId,\n directory,\n createdAt,\n updatedAt,\n title: resolveSessionTitle(explicitTitle, messageTitle, directoryTitle),\n pathEntries,\n };\n }\n\n private extractSessionName(entries: Record<string, unknown>[]): string | null {\n for (let index = entries.length - 1; index >= 0; index -= 1) {\n const entry = entries[index]!;\n if (entry[\"type\"] !== \"session_info\") continue;\n const name = normalizeTitleText(String(entry[\"name\"] ?? \"\"));\n if (name) return name;\n }\n return null;\n }\n\n private extractTitle(entries: Record<string, unknown>[]): string | null {\n for (const entry of entries) {\n if (entry[\"type\"] !== \"message\") continue;\n const message = entry[\"message\"];\n if (!isObject(message) || message[\"role\"] !== \"user\") continue;\n const title = normalizeTitleText(contentToText(message[\"content\"]));\n if (title) return title;\n }\n return null;\n }\n\n private convertEntries(entries: Record<string, unknown>[]): {\n messages: Message[];\n totalInputTokens: number;\n totalOutputTokens: number;\n totalCacheReadTokens: number;\n totalCacheCreateTokens: number;\n totalCost: number;\n costSource: Message[\"cost_source\"];\n modelUsage: Record<string, number>;\n } {\n const builder = new TranscriptBuilder({ messageDefaults: \"sparse\" });\n const modelUsage: Record<string, number> = {};\n\n for (const entry of entries) {\n const timestampMs = getEntryTimestamp(entry);\n const type = String(entry[\"type\"] ?? \"\");\n\n if (type === \"message\") {\n const message = narrowPiField(\"entry.message\", entry[\"message\"], asRecord);\n if (!message) continue;\n const result = this.convertAgentMessage(entry, message, timestampMs, builder);\n if (!result) continue;\n if (result.message) builder.appendMessage(result.message);\n if (result.model && result.totalTokens > 0) {\n modelUsage[result.model] = (modelUsage[result.model] ?? 0) + result.totalTokens;\n }\n continue;\n }\n\n const summary = this.convertSummaryEntry(entry, timestampMs);\n if (summary) builder.appendMessage(summary);\n }\n\n const result = builder.finish();\n\n return {\n messages: result.messages,\n totalInputTokens: result.stats.total_input_tokens,\n totalOutputTokens: result.stats.total_output_tokens,\n totalCacheReadTokens: result.stats.total_cache_read_tokens ?? 0,\n totalCacheCreateTokens: result.stats.total_cache_create_tokens ?? 0,\n totalCost: result.stats.total_cost,\n costSource: result.stats.cost_source,\n modelUsage,\n };\n }\n\n private convertAgentMessage(\n entry: Record<string, unknown>,\n message: Record<string, unknown>,\n timestampMs: number,\n builder: TranscriptBuilder,\n ): {\n message?: TranscriptMessageInput;\n totalTokens: number;\n model: string | null;\n } | null {\n const id = narrowPiField(\"message.id\", entry[\"id\"], asString) ?? \"\";\n const role = narrowPiField(\"message.role\", message[\"role\"], asString) ?? \"\";\n\n if (role === \"user\") {\n const parts = normalizeTextParts(message[\"content\"], timestampMs);\n if (parts.length === 0) return null;\n return this.emptyUsageResult({ id, role: \"user\", timestampMs, parts });\n }\n\n if (role === \"assistant\") {\n const parts = this.normalizeAssistantParts(message[\"content\"], timestampMs);\n if (parts.length === 0) return null;\n const usage = this.normalizeUsage(message[\"usage\"]);\n const model = typeof message[\"model\"] === \"string\" ? message[\"model\"].trim() : null;\n const estimatedCost = usage.cost === null ? estimateTokenCost(model, usage.tokens) : null;\n const cost = usage.cost ?? estimatedCost ?? 0;\n const costSource = cost > 0 ? (usage.cost === null ? \"estimated\" : \"recorded\") : undefined;\n return {\n message: {\n id,\n role: \"assistant\",\n agent: \"pi\",\n timestampMs,\n parts,\n provider: typeof message[\"provider\"] === \"string\" ? message[\"provider\"] : null,\n model,\n tokens: usage.tokens,\n cost: cost || undefined,\n costSource,\n },\n totalTokens: usage.totalTokens,\n model,\n };\n }\n\n if (role === \"toolResult\") {\n this.attachToolResult(message, timestampMs, builder);\n return this.emptyUsageResult();\n }\n\n if (role === \"bashExecution\") {\n return this.emptyUsageResult(this.convertBashExecution(id, message, timestampMs));\n }\n\n if (role === \"custom\" && message[\"display\"] === true) {\n const parts = normalizeTextParts(message[\"content\"], timestampMs);\n if (parts.length === 0) return null;\n return this.emptyUsageResult({ id, role: \"user\", timestampMs, parts, automated: true });\n }\n\n if (role === \"branchSummary\" || role === \"compactionSummary\") {\n const summary = String(message[\"summary\"] ?? \"\").trim();\n if (!summary) return null;\n return this.emptyUsageResult({\n id,\n role: \"assistant\",\n agent: \"pi\",\n timestampMs,\n parts: [{ type: \"text\", text: summary, time_created: timestampMs }],\n });\n }\n\n return null;\n }\n\n private normalizeAssistantParts(content: unknown, timestampMs: number): MessagePart[] {\n if (!Array.isArray(content)) return [];\n\n const parts: MessagePart[] = [];\n for (const item of content) {\n if (!isObject(item)) continue;\n const type = item[\"type\"];\n\n if (type === \"text\") {\n const text = cleanInternalText(String(item[\"text\"] ?? \"\"));\n if (text) parts.push({ type: \"text\", text, time_created: timestampMs });\n continue;\n }\n\n if (type === \"thinking\") {\n const text = cleanInternalText(String(item[\"thinking\"] ?? \"\"));\n if (text) parts.push({ type: \"reasoning\", text, time_created: timestampMs });\n continue;\n }\n\n if (type === \"toolCall\") {\n const callId = String(item[\"id\"] ?? \"\").trim();\n const toolName = String(item[\"name\"] ?? \"\").trim() || \"tool\";\n const toolPart: MessagePart = {\n type: \"tool\",\n tool: toolName,\n title: `Tool: ${toolName}`,\n callID: callId || undefined,\n time_created: timestampMs,\n state: {\n status: \"running\",\n input: item[\"arguments\"] ?? {},\n },\n };\n parts.push(toolPart);\n }\n }\n\n return parts;\n }\n\n private attachToolResult(\n message: Record<string, unknown>,\n timestampMs: number,\n builder: TranscriptBuilder,\n ): void {\n const callId = String(message[\"toolCallId\"] ?? \"\").trim();\n const output = normalizeTextParts(message[\"content\"], timestampMs);\n if (!callId) return;\n builder.resolveToolCall(callId, {\n output,\n status: message[\"isError\"] === true ? \"error\" : \"completed\",\n metadata: message[\"details\"],\n consume: true,\n });\n }\n\n private convertBashExecution(\n id: string,\n message: Record<string, unknown>,\n timestampMs: number,\n ): TranscriptMessageInput {\n const command = String(message[\"command\"] ?? \"\");\n const output = String(message[\"output\"] ?? \"\");\n const isError = Number(message[\"exitCode\"] ?? 0) !== 0 || message[\"cancelled\"] === true;\n return {\n id,\n role: \"tool\",\n timestampMs,\n parts: [\n {\n type: \"tool\",\n tool: \"bash\",\n title: \"Tool: bash\",\n time_created: timestampMs,\n state: {\n status: isError ? \"error\" : \"completed\",\n input: { command },\n output: output ? [{ type: \"text\", text: output, time_created: timestampMs }] : [],\n metadata: {\n exitCode: message[\"exitCode\"],\n cancelled: message[\"cancelled\"],\n truncated: message[\"truncated\"],\n fullOutputPath: message[\"fullOutputPath\"],\n },\n },\n },\n ],\n };\n }\n\n private convertSummaryEntry(\n entry: Record<string, unknown>,\n timestampMs: number,\n ): TranscriptMessageInput | null {\n const type = entry[\"type\"];\n if (type !== \"compaction\" && type !== \"branch_summary\" && type !== \"custom_message\") {\n return null;\n }\n\n if (type === \"custom_message\" && entry[\"display\"] !== true) return null;\n\n const rawText =\n type === \"custom_message\" ? contentToText(entry[\"content\"]) : String(entry[\"summary\"] ?? \"\");\n const text = cleanInternalText(rawText);\n if (!text) return null;\n\n return {\n id: narrowPiField(\"summary.id\", entry[\"id\"], asString) ?? \"\",\n role: type === \"custom_message\" ? \"user\" : \"assistant\",\n automated: type === \"custom_message\",\n agent: type === \"custom_message\" ? undefined : \"pi\",\n timestampMs,\n parts: [{ type: \"text\", text, time_created: timestampMs }],\n };\n }\n\n private normalizeUsage(raw: unknown): {\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens: number;\n cacheCreateTokens: number;\n totalTokens: number;\n cost: number | null;\n tokens: Message[\"tokens\"];\n } {\n const usage = narrowPiField(\"message.usage\", raw, asRecord) ?? {};\n const inputTokens = narrowPiField(\"message.usage.input\", usage[\"input\"], asNumber) ?? 0;\n const outputTokens = narrowPiField(\"message.usage.output\", usage[\"output\"], asNumber) ?? 0;\n const cacheReadTokens =\n narrowPiField(\"message.usage.cacheRead\", usage[\"cacheRead\"], asNumber) ?? 0;\n const cacheCreateTokens =\n narrowPiField(\"message.usage.cacheWrite\", usage[\"cacheWrite\"], asNumber) ?? 0;\n const totalTokens =\n narrowPiField(\"message.usage.totalTokens\", usage[\"totalTokens\"], asNumber) ??\n inputTokens + outputTokens + cacheReadTokens + cacheCreateTokens;\n const cost = isObject(usage[\"cost\"]) ? Number(usage[\"cost\"][\"total\"] ?? 0) : null;\n\n return {\n inputTokens: inputTokens + cacheReadTokens + cacheCreateTokens,\n outputTokens,\n cacheReadTokens,\n cacheCreateTokens,\n totalTokens,\n cost: cost && Number.isFinite(cost) ? cost : null,\n tokens: {\n input: inputTokens + cacheReadTokens + cacheCreateTokens,\n output: outputTokens,\n cache_read: cacheReadTokens || undefined,\n cache_create: cacheCreateTokens || undefined,\n },\n };\n }\n\n private emptyUsageResult(message?: TranscriptMessageInput): {\n message?: TranscriptMessageInput;\n totalTokens: number;\n model: string | null;\n } {\n return {\n message,\n totalTokens: 0,\n model: null,\n };\n }\n}\n","import { homedir, platform } from \"node:os\";\nimport { join } from \"node:path\";\nimport { getAgentCatalogEntry } from \"../contract/agent-catalog.js\";\nimport { firstExisting } from \"../discovery/paths.js\";\nimport { isSqliteAvailable } from \"../utils/sqlite.js\";\nimport { OpenCodeSqliteAgent } from \"./opencode-sqlite.js\";\nimport type { AgentSourceOptions } from \"./base.js\";\n\nconst AGENT_METADATA = getAgentCatalogEntry(\"zcode\");\n\nexport function resolveZCodeDataRoot(): string | null {\n const currentPlatform = platform();\n if (currentPlatform !== \"darwin\" && currentPlatform !== \"win32\") return null;\n return join(homedir(), \".zcode\");\n}\n\nfunction findZCodeDbPath(sourceRoot?: string): string | null {\n if (!isSqliteAvailable()) return null;\n const dataRoot = sourceRoot ?? resolveZCodeDataRoot();\n if (!dataRoot) return null;\n return firstExisting(join(dataRoot, \"cli\", \"db\", \"db.sqlite\"));\n}\n\nfunction getZCodeSessionWatchPlan(sourceRoot?: string) {\n const dataRoot = sourceRoot ?? resolveZCodeDataRoot();\n return {\n status: \"supported\" as const,\n targets: dataRoot ? [{ root: dataRoot, path: join(dataRoot, \"cli\", \"db\", \"db.sqlite\") }] : [],\n };\n}\n\nexport class ZCodeAgent extends OpenCodeSqliteAgent {\n constructor(options: AgentSourceOptions = {}) {\n super({\n name: AGENT_METADATA.name,\n displayName: AGENT_METADATA.displayName,\n findDbPath: () => findZCodeDbPath(options.sourceRoot),\n getSessionWatchPlan: () => getZCodeSessionWatchPlan(options.sourceRoot),\n });\n }\n}\n","import { existsSync, readFileSync, statSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { getAgentCatalogEntry } from \"../contract/agent-catalog.js\";\nimport {\n FileSystemSessionSource,\n filteredSession,\n matchesScanWindow,\n parsedSession,\n skippedSession,\n type AgentScanOptions,\n type FileSessionMeta,\n type ParseSessionResult,\n type SessionSourceFile,\n type SessionSourceRef,\n} from \"./base.js\";\nimport type {\n Message,\n MessagePart,\n MessageTokens,\n PlanPart,\n SessionDetail,\n SessionHead,\n SessionStats,\n ToolPart,\n ToolPartStatus,\n} from \"../types/index.js\";\nimport { firstExisting, resolveHomePath } from \"../discovery/paths.js\";\nimport { readJsonlFile, readJsonlFileLines } from \"../utils/jsonl.js\";\nimport { asArray, asNumber, asRecord, asString } from \"../utils/narrow.js\";\nimport { cleanInternalText } from \"../utils/session-normalization.js\";\nimport { basenameTitle, resolveSessionTitle } from \"../utils/title-fallback.js\";\nimport { TranscriptBuilder, type TranscriptResult } from \"./transcript-builder.js\";\n\nconst HEAD_INDEX_VERSION = \"grok-head-v2\";\nconst PARSER_VERSION = \"grok-parser-v1\";\nconst SUMMARY_FILE = \"summary.json\";\nconst UPDATES_FILE = \"updates.jsonl\";\nconst ACP_UPDATE_METHOD = \"session/update\";\nconst XAI_UPDATE_METHOD = \"_x.ai/session/update\";\nconst USD_TICKS_PER_USD = 10_000_000_000;\n\nconst GROK_TOOL_TITLE_MAP: Record<string, string> = {\n get_command_or_subagent_output: \"task\",\n grep: \"grep\",\n list_dir: \"list\",\n read_file: \"read\",\n run_terminal_command: \"bash\",\n search_replace: \"edit\",\n todo_write: \"todo\",\n web_fetch: \"web fetch\",\n};\n\ninterface GrokSummary {\n id: string;\n cwd: string;\n title: string | null;\n createdAt: number;\n updatedAt: number;\n currentModel: string | null;\n parentSessionId: string | null;\n}\n\ninterface GrokSessionMeta extends FileSessionMeta {\n currentModel: string | null;\n parentSessionId: string | null;\n updatesPath: string | null;\n stats: SessionStats;\n}\n\ninterface GrokUpdate {\n method: string;\n params: Record<string, unknown>;\n update: Record<string, unknown>;\n timestampMs: number;\n}\n\ninterface GrokUsage {\n tokens: MessageTokens;\n totalTokens: number;\n cost: number | null;\n modelUsage: Record<string, number>;\n primaryModel: string | null;\n}\n\ninterface GrokHeadData {\n firstUserText: string | null;\n visibleMessageCount: number;\n stats: Omit<SessionStats, \"message_count\">;\n modelUsage: Record<string, number>;\n}\n\nexport function resolveGrokDataRoot(): string {\n return resolveHomePath(\"GROK_HOME\", \".grok\");\n}\n\nfunction safeCount(value: unknown): number {\n const number = asNumber(value);\n return number !== undefined && Number.isSafeInteger(number) && number >= 0 ? number : 0;\n}\n\nfunction addCount(total: number, value: number): number {\n return Math.min(Number.MAX_SAFE_INTEGER, total + value);\n}\n\nfunction timestampFromIso(value: unknown): number | null {\n const text = asString(value);\n if (!text) return null;\n const timestamp = Date.parse(text);\n return Number.isFinite(timestamp) ? timestamp : null;\n}\n\nfunction readJsonRecord(filePath: string): Record<string, unknown> | null {\n try {\n return asRecord(JSON.parse(readFileSync(filePath, \"utf8\"))) ?? null;\n } catch {\n return null;\n }\n}\n\nfunction parseSummary(source: SessionSourceFile): GrokSummary | null {\n const summary = readJsonRecord(source.file);\n const info = asRecord(summary?.info);\n const id = asString(info?.id)?.trim();\n const cwd = asString(info?.cwd)?.trim();\n if (!id || !cwd) return null;\n\n const createdAt = timestampFromIso(summary?.created_at) ?? source.stat.mtimeMs;\n const updatedAt =\n timestampFromIso(summary?.last_active_at) ?? timestampFromIso(summary?.updated_at) ?? createdAt;\n const generatedTitle = asString(summary?.generated_title)?.trim();\n const sessionSummary = asString(summary?.session_summary)?.trim();\n const parentSessionId = asString(summary?.parent_session_id)?.trim() || null;\n\n return {\n id,\n cwd,\n title: generatedTitle || sessionSummary || null,\n createdAt,\n updatedAt,\n currentModel: asString(summary?.current_model_id)?.trim() || null,\n parentSessionId: parentSessionId === id ? null : parentSessionId,\n };\n}\n\nfunction optionalFileFingerprint(filePath: string): [number, number] | null {\n try {\n const stat = statSync(filePath);\n return [stat.mtimeMs, stat.size];\n } catch {\n return null;\n }\n}\n\nfunction unpackUpdate(\n record: Record<string, unknown>,\n fallbackTimestampMs: number,\n): GrokUpdate | null {\n const method = asString(record.method) ?? ACP_UPDATE_METHOD;\n const params = asRecord(record.params) ?? record;\n const update = asRecord(params.update);\n if (!update) return null;\n\n const paramsMeta = asRecord(params._meta);\n const agentTimestampMs = asNumber(paramsMeta?.agentTimestampMs);\n const envelopeTimestamp = asNumber(record.timestamp);\n const timestampMs =\n agentTimestampMs !== undefined &&\n Number.isSafeInteger(agentTimestampMs) &&\n agentTimestampMs >= 0\n ? agentTimestampMs\n : envelopeTimestamp !== undefined &&\n Number.isSafeInteger(envelopeTimestamp) &&\n envelopeTimestamp >= 0 &&\n envelopeTimestamp <= Number.MAX_SAFE_INTEGER / 1000\n ? envelopeTimestamp * 1000\n : fallbackTimestampMs;\n\n return { method, params, update, timestampMs };\n}\n\nfunction isHostTurn(update: Record<string, unknown>): boolean {\n return asRecord(update._meta)?.hostTurn === true;\n}\n\nfunction updateType(update: GrokUpdate): string {\n return asString(update.update.sessionUpdate) ?? \"\";\n}\n\nfunction parseUsage(update: Record<string, unknown>): GrokUsage | null {\n const usage = asRecord(update.usage);\n if (!usage) return null;\n\n const input = safeCount(usage.inputTokens);\n const output = safeCount(usage.outputTokens);\n const reasoning = safeCount(usage.reasoningTokens);\n const cacheRead = safeCount(usage.cachedReadTokens);\n const cacheCreate = safeCount(usage.cacheCreationTokens);\n const totalTokens = safeCount(usage.totalTokens) || addCount(input, output);\n const isIncomplete = usage.usageIsIncomplete === true || usage.costIsPartial === true;\n const costTicks = safeCount(usage.costUsdTicks);\n const cost = !isIncomplete && costTicks > 0 ? costTicks / USD_TICKS_PER_USD : null;\n\n const modelUsage: Record<string, number> = {};\n const modelUsageRecord = asRecord(usage.modelUsage);\n if (modelUsageRecord) {\n for (const [model, rawUsage] of Object.entries(modelUsageRecord)) {\n const modelRecord = asRecord(rawUsage);\n if (!modelRecord) continue;\n const modelTotal =\n safeCount(modelRecord.totalTokens) ||\n addCount(safeCount(modelRecord.inputTokens), safeCount(modelRecord.outputTokens));\n if (modelTotal > 0) modelUsage[model] = modelTotal;\n }\n }\n\n const models = Object.keys(modelUsage);\n return {\n tokens: {\n input,\n output,\n reasoning: reasoning || undefined,\n cache_read: cacheRead || undefined,\n cache_create: cacheCreate || undefined,\n },\n totalTokens,\n cost,\n modelUsage,\n primaryModel: models.length === 1 ? models[0]! : null,\n };\n}\n\nfunction textFromContentBlock(value: unknown): string {\n const content = asRecord(value);\n if (!content) return \"\";\n if (content.type === \"text\") return asString(content.text) ?? \"\";\n const resource = asRecord(content.resource);\n return asString(resource?.text) ?? \"\";\n}\n\nfunction messagePartFromContentBlock(value: unknown, timestampMs: number): MessagePart | null {\n const content = asRecord(value);\n if (!content) return null;\n\n if (content.type === \"text\") {\n const text = asString(content.text) ?? \"\";\n return text ? { type: \"text\", text, time_created: timestampMs } : null;\n }\n\n if (content.type === \"image\") {\n const data = asString(content.data);\n const url = asString(content.uri) ?? asString(content.url);\n const mimeType = asString(content.mimeType) ?? asString(content.mime_type);\n if (data && mimeType) {\n return { type: \"image\", data, mime_type: mimeType, url, time_created: timestampMs };\n }\n if (url) return { type: \"image\", url, mime_type: mimeType, time_created: timestampMs };\n }\n\n const text = textFromContentBlock(content);\n return text ? { type: \"text\", text, time_created: timestampMs } : null;\n}\n\nfunction visibleMessagePartFromContentBlock(\n value: unknown,\n timestampMs: number,\n): MessagePart | null {\n const part = messagePartFromContentBlock(value, timestampMs);\n if (part?.type === \"text\" && !cleanInternalText(part.text)) return null;\n return part;\n}\n\ntype GrokMessageTransition = \"ignored\" | \"started\" | \"continued\";\n\ntype ActiveGrokMessage =\n | { role: \"user\"; promptIndex: number | null }\n | { role: \"assistant\"; promptId: string | null };\n\nclass GrokMessageGrouping {\n private active: ActiveGrokMessage | null = null;\n\n appendUser(envelope: GrokUpdate, hasVisibleContent: boolean): GrokMessageTransition {\n if (isHostTurn(envelope.update) || !hasVisibleContent) return \"ignored\";\n\n const promptIndexValue = asNumber(asRecord(envelope.update._meta)?.promptIndex);\n const promptIndex =\n promptIndexValue !== undefined && Number.isSafeInteger(promptIndexValue)\n ? promptIndexValue\n : null;\n const canReuse =\n this.active?.role === \"user\" &&\n (promptIndex === null ||\n this.active.promptIndex === null ||\n promptIndex === this.active.promptIndex);\n\n this.active = { role: \"user\", promptIndex };\n return canReuse ? \"continued\" : \"started\";\n }\n\n appendAssistant(envelope: GrokUpdate, hasVisibleContent: boolean): GrokMessageTransition {\n if (!hasVisibleContent) return \"ignored\";\n\n const promptId = asString(asRecord(envelope.params._meta)?.promptId)?.trim() || null;\n const canReuse =\n this.active?.role === \"assistant\" &&\n !(promptId && this.active.promptId && promptId !== this.active.promptId);\n const activePromptId =\n promptId || (this.active?.role === \"assistant\" ? this.active.promptId : null);\n\n this.active = { role: \"assistant\", promptId: activePromptId };\n return canReuse ? \"continued\" : \"started\";\n }\n}\n\nclass GrokMessageCounter {\n firstUserText: string | null = null;\n messageCount = 0;\n private readonly grouping = new GrokMessageGrouping();\n\n process(envelope: GrokUpdate): void {\n if (envelope.method === XAI_UPDATE_METHOD) return;\n\n switch (updateType(envelope)) {\n case \"user_message_chunk\":\n this.appendUser(envelope);\n break;\n case \"agent_thought_chunk\":\n case \"agent_message_chunk\":\n this.appendAssistant(\n envelope,\n Boolean(cleanInternalText(textFromContentBlock(envelope.update.content))),\n );\n break;\n case \"tool_call\":\n this.appendAssistant(envelope, Boolean(asString(envelope.update.toolCallId)?.trim()));\n break;\n case \"plan\":\n this.appendAssistant(envelope, Boolean(planPart(envelope.update, envelope.timestampMs)));\n break;\n }\n }\n\n private appendUser(envelope: GrokUpdate): void {\n const part = visibleMessagePartFromContentBlock(envelope.update.content, envelope.timestampMs);\n const transition = this.grouping.appendUser(envelope, part !== null);\n if (!part || transition === \"ignored\") return;\n if (transition === \"started\") this.messageCount += 1;\n\n if (this.firstUserText === null && part.type === \"text\") {\n this.firstUserText = cleanInternalText(part.text) || null;\n }\n }\n\n private appendAssistant(envelope: GrokUpdate, hasVisibleContent: boolean): void {\n if (this.grouping.appendAssistant(envelope, hasVisibleContent) === \"started\") {\n this.messageCount += 1;\n }\n }\n}\n\nfunction scanCanonicalMessages(updatesPath: string, fallbackTimestampMs: number) {\n const rewindIndex = new RewindIndex();\n let recordIndex = 0;\n for (const record of readJsonlFile(updatesPath)) {\n rewindIndex.process(record, recordIndex, fallbackTimestampMs);\n recordIndex += 1;\n }\n\n const survivingIndexes = new Set(rewindIndex.survivingRecordIndexes);\n const counter = new GrokMessageCounter();\n recordIndex = 0;\n for (const record of readJsonlFile(updatesPath)) {\n if (survivingIndexes.has(recordIndex)) {\n const envelope = unpackUpdate(record, fallbackTimestampMs);\n if (envelope) counter.process(envelope);\n }\n recordIndex += 1;\n }\n return counter;\n}\n\nfunction scanHeadData(updatesPath: string | null, fallbackTimestampMs: number): GrokHeadData {\n let totalInputTokens = 0;\n let totalOutputTokens = 0;\n let totalCacheReadTokens = 0;\n let totalCacheCreateTokens = 0;\n let totalTokens = 0;\n let totalCost = 0;\n let hasUnknownCost = false;\n let hasRewinds = false;\n const modelUsage: Record<string, number> = {};\n let messageCounter = new GrokMessageCounter();\n\n if (updatesPath && existsSync(updatesPath)) {\n for (const line of readJsonlFileLines(updatesPath)) {\n const affectsMessages =\n line.includes('\"user_message_chunk\"') ||\n line.includes('\"agent_thought_chunk\"') ||\n line.includes('\"agent_message_chunk\"') ||\n line.includes('\"tool_call\"') ||\n line.includes('\"plan\"');\n const isTurnCompleted = line.includes('\"turn_completed\"');\n const isRewind = line.includes('\"rewind_marker\"');\n if (!affectsMessages && !isTurnCompleted && !isRewind) continue;\n\n let record: Record<string, unknown>;\n try {\n record = asRecord(JSON.parse(line)) ?? {};\n } catch {\n continue;\n }\n const envelope = unpackUpdate(record, fallbackTimestampMs);\n if (!envelope) continue;\n const type = updateType(envelope);\n if (affectsMessages) messageCounter.process(envelope);\n if (envelope.method === XAI_UPDATE_METHOD && type === \"rewind_marker\") {\n hasRewinds = true;\n }\n\n if (envelope.method !== XAI_UPDATE_METHOD || type !== \"turn_completed\") continue;\n const usage = parseUsage(envelope.update);\n if (!usage) continue;\n\n totalInputTokens = addCount(totalInputTokens, usage.tokens.input ?? 0);\n totalOutputTokens = addCount(totalOutputTokens, usage.tokens.output ?? 0);\n totalCacheReadTokens = addCount(totalCacheReadTokens, usage.tokens.cache_read ?? 0);\n totalCacheCreateTokens = addCount(totalCacheCreateTokens, usage.tokens.cache_create ?? 0);\n totalTokens = addCount(totalTokens, usage.totalTokens);\n if (usage.cost === null && usage.totalTokens > 0) hasUnknownCost = true;\n else totalCost += usage.cost ?? 0;\n\n for (const [model, tokens] of Object.entries(usage.modelUsage)) {\n modelUsage[model] = addCount(modelUsage[model] ?? 0, tokens);\n }\n }\n\n if (hasRewinds) messageCounter = scanCanonicalMessages(updatesPath, fallbackTimestampMs);\n }\n\n return {\n firstUserText: messageCounter.firstUserText,\n visibleMessageCount: messageCounter.messageCount,\n stats: {\n total_input_tokens: totalInputTokens,\n total_output_tokens: totalOutputTokens,\n total_cache_read_tokens: totalCacheReadTokens || undefined,\n total_cache_create_tokens: totalCacheCreateTokens || undefined,\n total_tokens: totalTokens || addCount(totalInputTokens, totalOutputTokens),\n total_cost: totalCost,\n cost_source: totalCost > 0 && !hasUnknownCost ? \"recorded\" : undefined,\n },\n modelUsage,\n };\n}\n\nfunction toolTitle(toolName: string): string {\n return GROK_TOOL_TITLE_MAP[toolName] ?? toolName;\n}\n\nfunction toolStatus(value: unknown): ToolPartStatus | null {\n switch (asString(value)?.toLowerCase()) {\n case \"completed\":\n return \"completed\";\n case \"failed\":\n return \"error\";\n case \"in_progress\":\n case \"pending\":\n return \"running\";\n default:\n return null;\n }\n}\n\nfunction toolOutput(update: Record<string, unknown>): unknown {\n if (update.rawOutput !== undefined && update.rawOutput !== null) return update.rawOutput;\n const content = asArray(update.content);\n if (!content) return undefined;\n\n const texts = content.flatMap((item) => {\n const wrapper = asRecord(item);\n const block = wrapper?.type === \"content\" ? wrapper.content : item;\n const text = textFromContentBlock(block);\n return text ? [text] : [];\n });\n if (texts.length === 0) return content;\n return texts.join(\"\\n\");\n}\n\nfunction planPart(update: Record<string, unknown>, timestampMs: number): PlanPart | null {\n const entries = asArray(update.entries)?.flatMap((value) => {\n const entry = asRecord(value);\n const content = cleanInternalText(asString(entry?.content) ?? \"\");\n if (!entry || !content) return [];\n return [{ content, status: asString(entry.status) ?? \"pending\" }];\n });\n if (!entries || entries.length === 0) return null;\n\n const text = entries\n .map(({ content, status }) => `- [${status === \"completed\" ? \"x\" : \" \"}] ${content}`)\n .join(\"\\n\");\n return {\n type: \"plan\",\n text,\n approval_status: entries.every(({ status }) => status === \"completed\") ? \"success\" : \"fail\",\n time_created: timestampMs,\n };\n}\n\nclass GrokTranscriptReducer {\n private readonly builder = new TranscriptBuilder();\n private readonly grouping = new GrokMessageGrouping();\n private activeAssistant: Message | null = null;\n private activeUser: Message | null = null;\n private latestPlan: PlanPart | null = null;\n private currentMode: string | null = null;\n private currentModel: string | null;\n\n constructor(\n private readonly sessionId: string,\n currentModel: string | null,\n private readonly fallbackTimestampMs: number,\n ) {\n this.currentModel = currentModel;\n }\n\n process(record: Record<string, unknown>): void {\n const envelope = unpackUpdate(record, this.fallbackTimestampMs);\n if (!envelope) return;\n if (envelope.method === XAI_UPDATE_METHOD) {\n this.processXaiUpdate(envelope);\n return;\n }\n this.processAcpUpdate(envelope);\n }\n\n finish(stats: SessionStats): TranscriptResult {\n return this.builder.finish(stats);\n }\n\n private processAcpUpdate(envelope: GrokUpdate): void {\n switch (updateType(envelope)) {\n case \"user_message_chunk\":\n this.appendUserChunk(envelope);\n break;\n case \"agent_thought_chunk\":\n this.appendAssistantText(envelope, \"reasoning\");\n break;\n case \"agent_message_chunk\":\n this.appendAssistantText(envelope, \"text\");\n break;\n case \"tool_call\":\n this.appendToolCall(envelope);\n break;\n case \"tool_call_update\":\n this.updateToolCall(envelope);\n break;\n case \"plan\":\n this.updatePlan(envelope);\n break;\n case \"current_mode_update\":\n this.currentMode = asString(envelope.update.currentModeId)?.trim() || null;\n break;\n }\n }\n\n private processXaiUpdate(envelope: GrokUpdate): void {\n switch (updateType(envelope)) {\n case \"turn_completed\": {\n const usage = parseUsage(envelope.update);\n if (!usage) return;\n this.builder.attachUsageToLatestAssistant(usage.tokens, {\n model: usage.primaryModel ?? this.currentModel,\n cost: usage.cost ?? undefined,\n costSource: usage.cost === null ? undefined : \"recorded\",\n });\n return;\n }\n case \"model_changed\":\n this.currentModel = asString(envelope.update.model_id)?.trim() || this.currentModel;\n return;\n case \"model_auto_switched\":\n this.currentModel = asString(envelope.update.new_model_id)?.trim() || this.currentModel;\n return;\n case \"subagent_spawned\": {\n const childSessionId = asString(envelope.update.child_session_id)?.trim();\n if (childSessionId && this.activeAssistant && !this.activeAssistant.subagent_id) {\n this.activeAssistant.subagent_id = childSessionId;\n }\n }\n }\n }\n\n private appendUserChunk(envelope: GrokUpdate): void {\n const part = visibleMessagePartFromContentBlock(envelope.update.content, envelope.timestampMs);\n const transition = this.grouping.appendUser(envelope, part !== null);\n if (!part || transition === \"ignored\") return;\n\n if (transition === \"continued\") {\n const tail = this.activeUser!.parts.at(-1);\n if (tail?.type === \"text\" && part.type === \"text\") tail.text += part.text;\n else this.activeUser!.parts.push(part);\n } else {\n const eventId = asString(asRecord(envelope.params._meta)?.eventId);\n this.activeUser = this.builder.appendMessage({\n id: eventId || `${this.sessionId}-user-${envelope.timestampMs}`,\n role: \"user\",\n timestampMs: envelope.timestampMs,\n parts: [part],\n });\n }\n\n this.activeAssistant = null;\n this.latestPlan = null;\n }\n\n private prepareAssistant(envelope: GrokUpdate, hasVisibleContent: boolean): boolean {\n const transition = this.grouping.appendAssistant(envelope, hasVisibleContent);\n if (transition === \"ignored\") return false;\n if (transition === \"started\") {\n this.builder.beginTurn();\n this.activeAssistant = null;\n this.latestPlan = null;\n }\n this.activeUser = null;\n return true;\n }\n\n private assistantInput(envelope: GrokUpdate) {\n const paramsMeta = asRecord(envelope.params._meta);\n return {\n id:\n asString(paramsMeta?.promptId) ||\n asString(paramsMeta?.eventId) ||\n `${this.sessionId}-assistant-${envelope.timestampMs}`,\n timestampMs: envelope.timestampMs,\n agent: \"grok\",\n mode: this.currentMode,\n model: this.currentModel,\n provider: \"xai\",\n };\n }\n\n private appendAssistantText(envelope: GrokUpdate, type: \"text\" | \"reasoning\"): void {\n const text = textFromContentBlock(envelope.update.content);\n if (!this.prepareAssistant(envelope, Boolean(cleanInternalText(text)))) return;\n\n const tail = this.activeAssistant?.parts.at(-1);\n if (tail?.type === type) {\n tail.text += text;\n return;\n }\n\n this.activeAssistant = this.builder.appendAssistantPart(\n { type, text, time_created: envelope.timestampMs },\n this.assistantInput(envelope),\n { grouping: \"current\" },\n );\n }\n\n private appendToolCall(envelope: GrokUpdate): void {\n const callId = asString(envelope.update.toolCallId)?.trim();\n const updateMeta = asRecord(envelope.update._meta);\n const nativeTool = asRecord(updateMeta?.[\"x.ai/tool\"]);\n const name =\n asString(nativeTool?.name)?.trim() || asString(envelope.update.title)?.trim() || \"tool\";\n if (!this.prepareAssistant(envelope, Boolean(callId))) return;\n const metadata = {\n kind: asString(nativeTool?.kind) ?? asString(envelope.update.kind),\n locations: envelope.update.locations,\n };\n const part: ToolPart = {\n type: \"tool\",\n tool: name,\n title: toolTitle(name),\n callID: callId,\n state: {\n status: toolStatus(envelope.update.status) ?? \"running\",\n input: envelope.update.rawInput,\n output: null,\n metadata,\n },\n time_created: envelope.timestampMs,\n };\n\n this.activeAssistant = this.builder.appendToolCall(part, this.assistantInput(envelope), {\n markModeAsTool: true,\n target: \"current\",\n });\n }\n\n private updateToolCall(envelope: GrokUpdate): void {\n const callId = asString(envelope.update.toolCallId)?.trim();\n if (!callId) return;\n this.builder.updateToolCall(callId, (part) => {\n const status = toolStatus(envelope.update.status);\n if (status) part.state.status = status;\n if (envelope.update.rawInput !== undefined) part.state.input = envelope.update.rawInput;\n\n const output = toolOutput(envelope.update);\n if (output !== undefined) {\n if (status === \"error\") part.state.error = output;\n else part.state.output = output;\n }\n\n const metadata = asRecord(part.state.metadata) ?? {};\n if (envelope.update.kind !== undefined) metadata.kind = envelope.update.kind;\n if (envelope.update.locations !== undefined) metadata.locations = envelope.update.locations;\n part.state.metadata = metadata;\n });\n }\n\n private updatePlan(envelope: GrokUpdate): void {\n const part = planPart(envelope.update, envelope.timestampMs);\n if (!this.prepareAssistant(envelope, part !== null) || !part) return;\n\n if (this.latestPlan) {\n this.latestPlan.text = part.text;\n this.latestPlan.approval_status = part.approval_status;\n this.latestPlan.time_created = part.time_created;\n return;\n }\n\n this.latestPlan = part;\n this.activeAssistant = this.builder.appendAssistantPart(part, this.assistantInput(envelope), {\n grouping: \"current\",\n });\n }\n}\n\nclass UserRunTracker {\n private hasSeenPromptIndex = false;\n private isInUserRun = false;\n private currentPromptIndex: number | null = null;\n\n onUser(promptIndex: number | null): boolean {\n if (promptIndex !== null) this.hasSeenPromptIndex = true;\n const isCounted = this.hasSeenPromptIndex ? promptIndex !== null : true;\n const isNewRun =\n !this.isInUserRun ||\n ((this.hasSeenPromptIndex || promptIndex !== null) &&\n promptIndex !== this.currentPromptIndex);\n\n this.isInUserRun = true;\n if (!isNewRun) return false;\n this.currentPromptIndex = promptIndex;\n return isCounted;\n }\n\n onNonUser(): void {\n this.isInUserRun = false;\n this.currentPromptIndex = null;\n }\n}\n\nclass RewindIndex {\n readonly survivingRecordIndexes: number[] = [];\n hasRewinds = false;\n private readonly promptStarts: number[] = [];\n private readonly userRuns = new UserRunTracker();\n\n process(record: Record<string, unknown>, recordIndex: number, fallbackTimestampMs: number): void {\n const envelope = unpackUpdate(record, fallbackTimestampMs);\n if (!envelope) {\n this.userRuns.onNonUser();\n this.survivingRecordIndexes.push(recordIndex);\n return;\n }\n\n const type = updateType(envelope);\n if (envelope.method === XAI_UPDATE_METHOD && type === \"rewind_marker\") {\n const target = asNumber(envelope.update.target_prompt_index);\n if (target === undefined || !Number.isSafeInteger(target) || target < 0) {\n this.userRuns.onNonUser();\n this.survivingRecordIndexes.push(recordIndex);\n return;\n }\n const truncateAt = this.promptStarts[target] ?? this.survivingRecordIndexes.length;\n this.survivingRecordIndexes.length = truncateAt;\n this.promptStarts.length = Math.min(this.promptStarts.length, target);\n this.userRuns.onNonUser();\n this.hasRewinds = true;\n return;\n }\n\n if (\n envelope.method !== XAI_UPDATE_METHOD &&\n type === \"user_message_chunk\" &&\n !isHostTurn(envelope.update)\n ) {\n const rawPromptIndex = asNumber(asRecord(envelope.update._meta)?.promptIndex);\n const promptIndex =\n rawPromptIndex !== undefined && Number.isSafeInteger(rawPromptIndex) && rawPromptIndex >= 0\n ? rawPromptIndex\n : null;\n if (this.userRuns.onUser(promptIndex)) {\n this.promptStarts.push(this.survivingRecordIndexes.length);\n }\n } else {\n this.userRuns.onNonUser();\n }\n\n this.survivingRecordIndexes.push(recordIndex);\n }\n}\n\nfunction parseTranscript(meta: GrokSessionMeta): TranscriptResult {\n const reducer = new GrokTranscriptReducer(meta.id, meta.currentModel, meta.createdAt);\n if (!meta.updatesPath || !existsSync(meta.updatesPath)) return reducer.finish(meta.stats);\n\n const rewindIndex = new RewindIndex();\n let recordIndex = 0;\n for (const record of readJsonlFile(meta.updatesPath)) {\n rewindIndex.process(record, recordIndex, meta.createdAt);\n reducer.process(record);\n recordIndex += 1;\n }\n if (!rewindIndex.hasRewinds) return reducer.finish(meta.stats);\n\n const survivingIndexes = new Set(rewindIndex.survivingRecordIndexes);\n const replay = new GrokTranscriptReducer(meta.id, meta.currentModel, meta.createdAt);\n recordIndex = 0;\n for (const record of readJsonlFile(meta.updatesPath)) {\n if (survivingIndexes.has(recordIndex)) replay.process(record);\n recordIndex += 1;\n }\n return replay.finish(meta.stats);\n}\n\nconst AGENT_METADATA = getAgentCatalogEntry(\"grok\");\n\nexport class GrokAgent extends FileSystemSessionSource<GrokSessionMeta> {\n readonly name = AGENT_METADATA.name;\n readonly displayName = AGENT_METADATA.displayName;\n\n private basePath: string | null = this.configuredSourceRoot;\n\n private findBasePath(): string | null {\n return (\n this.configuredSourceRoot ??\n firstExisting(join(resolveGrokDataRoot(), \"sessions\"), \"data/grok\")\n );\n }\n\n isAvailable(): boolean {\n this.basePath = this.findBasePath();\n return this.basePath !== null && this.listSessionSources().length > 0;\n }\n\n getSessionWatchPlan() {\n if (this.configuredSourceRoot) {\n return {\n status: \"supported\" as const,\n targets: [{ root: dirname(this.configuredSourceRoot), path: this.configuredSourceRoot }],\n };\n }\n const dataRoot = resolveGrokDataRoot();\n return {\n status: \"supported\" as const,\n targets: [{ root: dataRoot, path: join(dataRoot, \"sessions\") }, { path: \"data/grok\" }],\n };\n }\n\n listSessionSources(options?: AgentScanOptions): SessionSourceRef[] {\n this.basePath ??= this.findBasePath();\n if (!this.basePath) return [];\n\n const sources = this.walkFiles(this.basePath, (entry) => entry.name === SUMMARY_FILE);\n return sources.flatMap((source) => {\n const summary = parseSummary(source);\n if (!summary || !matchesScanWindow(summary.updatedAt, options)) return [];\n return [\n {\n sessionId: summary.id,\n sourcePath: source.file,\n fingerprint: this.sourceFingerprint(source),\n },\n ];\n });\n }\n\n protected override scanSessionSourceResult(\n source: SessionSourceRef,\n ): ParseSessionResult<SessionHead> {\n return this.parseSessionHeadResult(source.sourcePath);\n }\n\n private parseSessionHeadResult(sourcePath: string): ParseSessionResult<SessionHead> {\n const source = this.sessionSourceFile(sourcePath);\n const summary = parseSummary(source);\n if (!summary) return skippedSession(\"malformed summary\");\n\n const sessionDir = dirname(source.file);\n const updatesPath = join(sessionDir, UPDATES_FILE);\n const existingUpdatesPath = existsSync(updatesPath) ? updatesPath : null;\n const headData = scanHeadData(existingUpdatesPath, summary.createdAt);\n const messageCount = headData.visibleMessageCount;\n if (messageCount === 0) return filteredSession(\"no visible messages\");\n\n const title = resolveSessionTitle(\n summary.title,\n headData.firstUserText,\n basenameTitle(summary.cwd),\n );\n const stats: SessionStats = { message_count: messageCount, ...headData.stats };\n const fingerprint = this.sourceFingerprint(source);\n const head: SessionHead = {\n ...this.sessionIdentity(summary.id),\n title,\n directory: summary.cwd,\n parent_reference: summary.parentSessionId\n ? { agentName: this.name, sessionId: summary.parentSessionId }\n : undefined,\n time_created: summary.createdAt,\n time_updated: summary.updatedAt,\n stats,\n model_usage: Object.keys(headData.modelUsage).length > 0 ? headData.modelUsage : undefined,\n };\n\n this.sessionMetaMap.set(summary.id, {\n id: summary.id,\n title,\n sourcePath: source.file,\n sourceFingerprint: fingerprint,\n sourceMtimeMs: summary.updatedAt,\n directory: summary.cwd,\n messageCount,\n createdAt: summary.createdAt,\n updatedAt: summary.updatedAt,\n currentModel: summary.currentModel,\n parentSessionId: summary.parentSessionId,\n updatesPath: existingUpdatesPath,\n stats,\n });\n return parsedSession(head);\n }\n\n getSessionData(sessionId: string): SessionDetail {\n const meta = this.sessionMetaMap.get(sessionId);\n if (!meta) throw new Error(`Session not found: ${sessionId}`);\n\n const transcript = parseTranscript(meta);\n return {\n ...this.sessionIdentity(meta.id),\n title: meta.title,\n directory: meta.directory,\n parent_reference: meta.parentSessionId\n ? { agentName: this.name, sessionId: meta.parentSessionId }\n : undefined,\n version: undefined,\n time_created: meta.createdAt,\n time_updated: meta.updatedAt,\n stats: transcript.stats,\n messages: transcript.messages,\n };\n }\n\n private sourceFingerprint(source: SessionSourceFile): string {\n const sessionDir = dirname(source.file);\n return JSON.stringify([\n HEAD_INDEX_VERSION,\n PARSER_VERSION,\n source.stat.mtimeMs,\n source.stat.size,\n optionalFileFingerprint(join(sessionDir, UPDATES_FILE)),\n ]);\n }\n}\n","/**\n * DeepSeek Harness (DSH) adapter.\n *\n * Enumeration walks the two-level `sessions/<project-key>/<session-id>/` layout\n * DSH writes. The project key is deliberately lossy — separators collapse and\n * long paths truncate — so it is used only to find candidates; the header's own\n * `id` and `cwd` are the identity, and every artifact must sit exactly where\n * those fields say it does.\n */\nimport { existsSync, readdirSync, realpathSync, statSync } from \"node:fs\";\nimport { basename, dirname, join } from \"node:path\";\nimport { getAgentCatalogEntry } from \"../contract/agent-catalog.js\";\nimport {\n FileSystemSessionSource,\n SessionScanError,\n filteredSession,\n matchesScanWindow,\n parsedSession,\n} from \"./base.js\";\nimport type {\n AgentScanOptions,\n ParseSessionResult,\n SessionCacheMeta,\n SessionSourceRef,\n SessionWatchPlan,\n} from \"./base.js\";\nimport type { SessionDetail, SessionHead } from \"../types/index.js\";\nimport { basenameTitle, resolveSessionTitle } from \"../utils/title-fallback.js\";\nimport {\n DshSessionLogError,\n dshAttachmentsRoot,\n dshFileIdentity,\n dshLogFileName,\n dshLogPath,\n dshSessionsRoot,\n readDshSessionHeader,\n readDshSessionLog,\n resolveDshDataRoot,\n type DshEncoding,\n type DshSessionHeader,\n} from \"./dsh-session-log.js\";\nimport { projectDshSession, type DshProjection } from \"./dsh-transcript.js\";\n\nexport { resolveDshDataRoot } from \"./dsh-session-log.js\";\n\n/** Bump when event mapping, packed-row handling or token semantics change. */\nconst PARSER_REVISION = \"dsh-parser-v1\";\n\nconst ENCODINGS: readonly DshEncoding[] = [\"zstd\", \"none\"];\n\ninterface DshSessionMeta extends SessionCacheMeta {\n id: string;\n sourcePath: string;\n sourceFingerprint: string;\n sourceMtimeMs: number;\n encoding: DshEncoding;\n directory: string;\n title: string;\n createdAt: number;\n updatedAt: number;\n messageCount: number;\n parentSessionId: string | null;\n}\n\n/** One candidate artifact found by walking the session root. */\ninterface DshArtifact {\n sourcePath: string;\n encoding: DshEncoding;\n}\n\ninterface ParsedDshSession {\n header: DshSessionHeader;\n projection: DshProjection;\n}\n\nfunction encodingOfPath(sourcePath: string): DshEncoding {\n return basename(sourcePath) === dshLogFileName(\"zstd\") ? \"zstd\" : \"none\";\n}\n\n/** Two spellings of one physical file (a casing alias) are the same artifact. */\nfunction sameFile(left: string, right: string): boolean {\n if (left === right) return true;\n try {\n return realpathSync(left) === realpathSync(right);\n } catch {\n return false;\n }\n}\n\nconst AGENT_METADATA = getAgentCatalogEntry(\"dsh\");\n\nexport class DshAgent extends FileSystemSessionSource<DshSessionMeta> {\n readonly name = AGENT_METADATA.name;\n readonly displayName = AGENT_METADATA.displayName;\n\n getSessionWatchPlan(): SessionWatchPlan {\n const dataRoot = this.dataRoot();\n return {\n status: \"supported\",\n targets: [{ root: dataRoot, path: this.sessionsRoot() }],\n };\n }\n\n isAvailable(): boolean {\n try {\n return this.listArtifacts().length > 0;\n } catch {\n // A permission error, mixed encoding or legacy layout is a scan failure\n // to report, never proof that the agent has no data.\n return true;\n }\n }\n\n listSessionSources(options?: AgentScanOptions): SessionSourceRef[] {\n const sessionsRoot = this.sessionsRoot();\n const refs: SessionSourceRef[] = [];\n const seenIds = new Map<string, string>();\n\n for (const artifact of this.listArtifacts()) {\n const stats = this.statArtifact(artifact.sourcePath);\n if (!stats) continue;\n if (!matchesScanWindow(Number(stats.mtimeMs), options)) continue;\n\n const header = this.scanStep(\"reading session headers\", artifact.sourcePath, () =>\n readDshSessionHeader(artifact.sourcePath, artifact.encoding),\n );\n this.assertStoredIdentity(sessionsRoot, artifact, header);\n\n const previous = seenIds.get(header.id);\n if (previous) {\n throw new SessionScanError(this.name, \"enumerating session sources\", {\n cause: new DshSessionLogError(\n `duplicate DSH session id ${JSON.stringify(header.id)} in ${JSON.stringify(previous)} and ${JSON.stringify(artifact.sourcePath)}`,\n ),\n sourcePath: artifact.sourcePath,\n });\n }\n seenIds.set(header.id, artifact.sourcePath);\n\n refs.push({\n sessionId: header.id,\n sourcePath: artifact.sourcePath,\n fingerprint: JSON.stringify([\n PARSER_REVISION,\n artifact.encoding,\n ...dshFileIdentity(stats),\n ]),\n });\n }\n\n return refs;\n }\n\n /** The scan window is applied during enumeration, so parsing needs no options. */\n protected override scanSessionSourceResult(\n source: SessionSourceRef,\n ): ParseSessionResult<SessionHead> {\n const encoding = encodingOfPath(source.sourcePath);\n const { header, projection } = this.parseSession(source.sourcePath, encoding);\n if (projection.messages.length === 0) {\n return filteredSession(\"no visible messages\");\n }\n\n const head: SessionHead = {\n ...this.sessionIdentity(header.id),\n title: this.resolveTitle(header, projection),\n directory: header.cwd ?? \"\",\n ...(header.parentSession\n ? { parent_reference: { agentName: this.name, sessionId: header.parentSession } }\n : {}),\n time_created: header.createdAt,\n time_updated: projection.updatedAt,\n stats: projection.stats,\n ...(Object.keys(projection.modelUsage).length > 0\n ? { model_usage: projection.modelUsage }\n : {}),\n };\n\n this.sessionMetaMap.set(head.reference.sessionId, {\n id: head.reference.sessionId,\n sourcePath: source.sourcePath,\n sourceFingerprint: JSON.stringify([\n PARSER_REVISION,\n encoding,\n ...dshFileIdentity(statSync(source.sourcePath, { bigint: true })),\n ]),\n sourceMtimeMs: statSync(source.sourcePath).mtimeMs,\n encoding,\n directory: head.directory,\n title: head.title,\n createdAt: head.time_created,\n updatedAt: projection.updatedAt,\n messageCount: projection.messages.length,\n parentSessionId: header.parentSession ?? null,\n });\n\n return parsedSession(head);\n }\n\n getSessionData(sessionId: string): SessionDetail {\n const meta = this.sessionMetaMap.get(sessionId);\n if (!meta) throw new Error(`Session not found: ${sessionId}`);\n\n const { header, projection } = this.parseSession(meta.sourcePath, meta.encoding);\n return {\n ...this.sessionIdentity(header.id),\n title: this.resolveTitle(header, projection),\n directory: header.cwd ?? \"\",\n ...(header.parentSession\n ? { parent_reference: { agentName: this.name, sessionId: header.parentSession } }\n : {}),\n version: \"0\",\n time_created: header.createdAt,\n time_updated: projection.updatedAt,\n stats: projection.stats,\n messages: projection.messages,\n };\n }\n\n /**\n * A cached head with no visible messages was materialized from context-only\n * events; dropping it keeps blank sessions out of the list after a restart.\n */\n override filterCachedSessions(sessions: SessionHead[]): SessionHead[] {\n return sessions.filter((session) => session.stats.message_count > 0);\n }\n\n private parseSession(sourcePath: string, encoding: DshEncoding): ParsedDshSession {\n const dataRoot = this.dataRoot();\n const { header, events } = readDshSessionLog(sourcePath, encoding);\n return {\n header,\n projection: projectDshSession({\n header,\n events,\n sourcePath,\n attachmentsRoot: dshAttachmentsRoot(dataRoot),\n }),\n };\n }\n\n private resolveTitle(header: DshSessionHeader, projection: DshProjection): string {\n return resolveSessionTitle(projection.title, null, basenameTitle(header.cwd ?? null));\n }\n\n /**\n * Walk `sessions/<project>/<session>/` and reject the layouts DSH itself\n * refuses: a flat pre-directory artifact, and a root or session directory\n * holding both physical encodings (which one is current is unknowable).\n */\n private listArtifacts(): DshArtifact[] {\n const sessionsRoot = this.sessionsRoot();\n const artifacts: DshArtifact[] = [];\n let rootEncoding: DshEncoding | null = null;\n\n for (const project of this.listDirectories(sessionsRoot, true)) {\n this.rejectLegacyLayout(project);\n for (const sessionDir of this.listDirectories(project, false)) {\n const present = ENCODINGS.filter((encoding) =>\n existsSync(join(sessionDir, dshLogFileName(encoding))),\n );\n if (present.length === 0) continue;\n if (present.length > 1) {\n this.rejectEnumeration(\n sessionDir,\n `session directory ${JSON.stringify(sessionDir)} holds both physical encodings`,\n );\n }\n const encoding = present[0] as DshEncoding;\n if (rootEncoding !== null && rootEncoding !== encoding) {\n this.rejectEnumeration(\n sessionDir,\n `session root ${JSON.stringify(sessionsRoot)} mixes ${rootEncoding} and ${encoding} artifacts`,\n );\n }\n rootEncoding = encoding;\n artifacts.push({ sourcePath: join(sessionDir, dshLogFileName(encoding)), encoding });\n }\n }\n\n return artifacts;\n }\n\n private dataRoot(): string {\n return this.configuredSourceRoot ? dirname(this.configuredSourceRoot) : resolveDshDataRoot();\n }\n\n private sessionsRoot(): string {\n return this.configuredSourceRoot ?? dshSessionsRoot(this.dataRoot());\n }\n\n private listDirectories(directory: string, tolerateMissing: boolean): string[] {\n try {\n return readdirSync(directory, { withFileTypes: true })\n .filter((entry) => entry.isDirectory())\n .map((entry) => join(directory, entry.name));\n } catch (error) {\n // Only an absent session root means \"no DSH data\"; every other I/O\n // failure must surface so a readable baseline is not discarded.\n if (tolerateMissing && isMissingDirectory(error)) return [];\n throw new SessionScanError(this.name, \"enumerating session sources\", {\n cause: error,\n sourcePath: directory,\n });\n }\n }\n\n private rejectLegacyLayout(project: string): void {\n const legacy = readdirSync(project, { withFileTypes: true }).find(\n (entry) =>\n entry.isFile() && (entry.name.endsWith(\".jsonl\") || entry.name.endsWith(\".jsonl.zstd\")),\n );\n if (!legacy) return;\n this.rejectEnumeration(\n join(project, legacy.name),\n `session artifact ${JSON.stringify(join(project, legacy.name))} uses the unsupported flat-file layout`,\n );\n }\n\n /** The header's id and cwd must name exactly the artifact they were read from. */\n private assertStoredIdentity(\n sessionsRoot: string,\n artifact: DshArtifact,\n header: DshSessionHeader,\n ): void {\n let expected: string;\n try {\n expected = dshLogPath(sessionsRoot, header.cwd, header.id, artifact.encoding);\n } catch (error) {\n this.rejectEnumeration(\n artifact.sourcePath,\n `header id ${JSON.stringify(header.id)} cannot name a storage path`,\n error,\n );\n }\n if (!sameFile(artifact.sourcePath, expected)) {\n this.rejectEnumeration(\n artifact.sourcePath,\n `header identifies ${JSON.stringify(expected)}, not ${JSON.stringify(artifact.sourcePath)}`,\n );\n }\n }\n\n private statArtifact(sourcePath: string) {\n try {\n return statSync(sourcePath, { bigint: true });\n } catch (error) {\n if (isMissingDirectory(error)) return null;\n throw new SessionScanError(this.name, \"reading session source metadata\", {\n cause: error,\n sourcePath,\n });\n }\n }\n\n private rejectEnumeration(sourcePath: string, reason: string, cause?: unknown): never {\n throw new SessionScanError(this.name, \"enumerating session sources\", {\n cause: new DshSessionLogError(reason, cause ? { cause } : undefined),\n sourcePath,\n });\n }\n}\n\nfunction isMissingDirectory(error: unknown): boolean {\n if (typeof error !== \"object\" || error === null || !(\"code\" in error)) return false;\n const code = (error as { code?: unknown }).code;\n return code === \"ENOENT\" || code === \"ENOTDIR\";\n}\n","/**\n * Read-only reader for DeepSeek Harness (DSH) v0 session artifacts.\n *\n * A DSH log is not one compressed blob: it is a concatenation of independently\n * checksummed Zstandard frames — the first holding the header line, each later\n * one holding a durable append batch. Decompressing the whole file at once\n * yields only the first frame, so this module scans frame ranges structurally\n * and decodes them one by one. It also expands the packed `*-chunks` storage\n * rows DSH writes for streaming deltas, so a physical JSONL line count is\n * never mistaken for an event count.\n *\n * CodeSesh is a strictly read-only consumer: nothing here writes, truncates or\n * repairs a DSH artifact, and a torn tail is reported as a warning over the\n * verified complete prefix.\n */\nimport { closeSync, openSync, readFileSync, readSync, statSync, type BigIntStats } from \"node:fs\";\nimport { join } from \"node:path\";\nimport * as zlib from \"node:zlib\";\nimport { getCoreDiagnostics } from \"../utils/diagnostics.js\";\nimport { resolveHomePath } from \"../discovery/paths.js\";\n\n/** Physical encoding of a session artifact; DSH defaults to `zstd`. */\nexport type DshEncoding = \"zstd\" | \"none\";\n\n/** The on-disk session format version this reader understands. */\nconst DSH_FORMAT_VERSION = 0;\n\n/** DSH truncates a project-directory slug to this many characters. */\nconst PROJECT_SLUG_MAX_LENGTH = 251;\n\n/** Reads racing an active append retry this many times before failing. */\nconst STABLE_READ_ATTEMPTS = 3;\n\n/** Enough for any DSH header record; a longer one falls back to a whole-file read. */\nconst HEADER_PREFIX_BYTES = 64 * 1024;\n\nconst ZSTD_MAGIC = 0xfd2fb528;\n\n/**\n * DSH's `KNOWN_SESSION_EVENT_TYPES` for format version 0. An unrecognized type\n * without the envelope's `ignorable` marker means the log was written by a\n * newer harness whose semantics could change how the rest of it reads, so the\n * source is refused rather than silently reconstructed wrong.\n */\nconst KNOWN_DSH_EVENT_TYPES: ReadonlySet<string> = new Set([\n \"agent-preset/selected\",\n \"agent/inbox/spliced\",\n \"approval/asked\",\n \"approval/decided\",\n \"approval/policy\",\n \"assistant/chunk\",\n \"assistant/message\",\n \"command/done\",\n \"command/run\",\n \"compaction/end\",\n \"compaction/prune\",\n \"compaction/start\",\n \"compaction/summary\",\n \"feedback/record\",\n \"goal/change\",\n \"hook/invoked\",\n \"hook/result\",\n \"llm/retry\",\n \"llm/retry-started\",\n \"permission/preset\",\n \"plan/mode\",\n \"request/context\",\n \"request/header\",\n \"sandbox/mode\",\n \"schedule/change\",\n \"session/end-seed\",\n \"session/title\",\n \"session/title-llm-request\",\n \"step/end\",\n \"step/start\",\n \"subagent/descriptor\",\n \"todo/write\",\n \"tool-workflow/agent-end\",\n \"tool-workflow/agent-start\",\n \"tool-workflow/run-end\",\n \"tool-workflow/run-start\",\n \"tool/call\",\n \"tool/code-dispatch\",\n \"tool/code-dispatch-start\",\n \"tool/result\",\n \"turn/end\",\n \"turn/start\",\n \"user/message\",\n \"web/deepseek-search-llm-request\",\n]);\n\n/** Storage-row tags: a durable encoding vocabulary, never session events. */\nconst TEXT_CHUNK_ROWS: ReadonlySet<string> = new Set([\"text-chunks\", \"reasoning-chunks\"]);\nconst TOOL_CALL_CHUNK_ROW = \"tool-call-chunks\";\n\n/** Immutable storage metadata from a log's first record. */\nexport interface DshSessionHeader {\n id: string;\n createdAt: number;\n cwd: string | undefined;\n parentSession: string | undefined;\n seedLength: number | undefined;\n origin: \"subagent\" | undefined;\n delegationDepth: number;\n agentPreset: string | undefined;\n}\n\n/** One entry of the DSH append-only log, after storage rows are expanded. */\nexport interface DshEvent {\n type: string;\n seq: number;\n time: number;\n data: unknown;\n surfaceOp?: unknown;\n ignorable?: unknown;\n}\n\n/** A header plus the contiguous event prefix this reader could verify. */\nexport interface DshSessionLog {\n header: DshSessionHeader;\n events: DshEvent[];\n}\n\nexport class DshSessionLogError extends Error {\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = \"DshSessionLogError\";\n }\n}\n\n// ---------------------------------------------------------------------------\n// Data root and path layout\n// ---------------------------------------------------------------------------\n\n/**\n * Reproduce DSH's `resolveDshHome`: a non-blank `DSH_HOME`, else `~/.dsh`.\n * DSH consults no XDG or Windows AppData location, so neither does this.\n * The blank/tilde/relative handling now lives in the shared resolveHomePath.\n */\nexport function resolveDshDataRoot(): string {\n return resolveHomePath(\"DSH_HOME\", \".dsh\");\n}\n\nexport function dshSessionsRoot(dataRoot: string): string {\n return join(dataRoot, \"sessions\");\n}\n\nexport function dshAttachmentsRoot(dataRoot: string): string {\n return join(dataRoot, \"attachments\", \"v1\");\n}\n\nexport function dshLogFileName(encoding: DshEncoding): string {\n return encoding === \"zstd\" ? \"session.jsonl.zstd\" : \"session.jsonl\";\n}\n\nfunction isSafeSegmentChar(ch: string): boolean {\n return /^[A-Za-z0-9._-]$/.test(ch);\n}\n\nfunction escapeCodeUnit(code: number): string {\n return `~${code.toString(16).toUpperCase().padStart(4, \"0\")}`;\n}\n\n/**\n * DSH's `encodeSegment`: injective over all UTF-16 strings, so a session id\n * can never escape its directory. Operates on code units to preserve lone\n * surrogates, and special-cases `.` / `..` which are safe per character yet\n * traversing as whole segments.\n */\nexport function dshEncodeSegment(raw: string): string {\n if (raw.length === 0) throw new DshSessionLogError(\"cannot encode an empty path segment\");\n if (raw === \".\") return \"~002E\";\n if (raw === \"..\") return \"~002E~002E\";\n let out = \"\";\n for (let index = 0; index < raw.length; index += 1) {\n const code = raw.charCodeAt(index);\n const ch = String.fromCharCode(code);\n out += ch !== \"~\" && isSafeSegmentChar(ch) ? ch : escapeCodeUnit(code);\n }\n return out;\n}\n\n/**\n * DSH's `projectKey`: a human-navigable, deliberately lossy directory name.\n * Separator runs collapse to one `-` and the slug is truncated, so the key\n * cannot recover a cwd — only the header can.\n */\nexport function dshProjectKey(cwd: string): string {\n if (cwd.length === 0) throw new DshSessionLogError(\"cannot encode an empty project path\");\n let readable = \"\";\n let separatorRun = false;\n for (let index = 0; index < cwd.length; index += 1) {\n const code = cwd.charCodeAt(index);\n const ch = String.fromCharCode(code);\n if (ch === \"/\" || ch === \"\\\\\" || ch === \":\") {\n if (!separatorRun) readable += \"-\";\n separatorRun = true;\n continue;\n }\n readable += ch !== \"~\" && isSafeSegmentChar(ch) ? ch : escapeCodeUnit(code);\n separatorRun = false;\n }\n const slug = readable.replace(/^-+/, \"\") || \"root\";\n return `--${slug.slice(0, PROJECT_SLUG_MAX_LENGTH)}--`;\n}\n\n/** The artifact path the header's own identity fields name. */\nexport function dshLogPath(\n sessionsRoot: string,\n cwd: string | undefined,\n id: string,\n encoding: DshEncoding,\n): string {\n const project = cwd === undefined ? \"_no-cwd\" : dshProjectKey(cwd);\n return join(sessionsRoot, project, dshEncodeSegment(id), dshLogFileName(encoding));\n}\n\n// ---------------------------------------------------------------------------\n// Stable snapshot\n// ---------------------------------------------------------------------------\n\n/** A file's bytes plus the identity proving nothing changed while reading. */\nexport interface DshFileSnapshot {\n buffer: Buffer;\n stats: BigIntStats;\n}\n\nfunction sameFileIdentity(before: BigIntStats, after: BigIntStats): boolean {\n return (\n before.dev === after.dev &&\n before.ino === after.ino &&\n before.size === after.size &&\n before.mtimeNs === after.mtimeNs &&\n before.ctimeNs === after.ctimeNs\n );\n}\n\n/**\n * Read a file whose writer may be appending concurrently. Bracketing the read\n * with two identical `stat`s proves the bytes belong to one point in time; a\n * file that keeps changing is a transient failure the watcher retries, never a\n * reason to publish a half-read session.\n */\nexport function readDshFileSnapshot(sourcePath: string): DshFileSnapshot {\n for (let attempt = 0; attempt < STABLE_READ_ATTEMPTS; attempt += 1) {\n const before = statSync(sourcePath, { bigint: true });\n const buffer = readFileSync(sourcePath);\n const after = statSync(sourcePath, { bigint: true });\n if (sameFileIdentity(before, after)) return { buffer, stats: after };\n }\n throw new DshSessionLogError(\n `DSH session log ${JSON.stringify(sourcePath)} changed during every read attempt`,\n );\n}\n\n/** Identity fields that must all change together for an append to go unnoticed. */\nexport function dshFileIdentity(stats: BigIntStats): string[] {\n return [stats.dev, stats.ino, stats.size, stats.mtimeNs, stats.ctimeNs].map(String);\n}\n\n/** Read at most `maxBytes` from the start of a file, without loading the rest. */\nfunction readFilePrefix(sourcePath: string, maxBytes: number): Buffer {\n const handle = openSync(sourcePath, \"r\");\n try {\n const buffer = Buffer.allocUnsafe(maxBytes);\n return buffer.subarray(0, readSync(handle, buffer, 0, maxBytes, 0));\n } finally {\n closeSync(handle);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Zstandard container\n// ---------------------------------------------------------------------------\n\ninterface ZstdFrameRange {\n start: number;\n end: number;\n}\n\ninterface ZstdFrameScan {\n frames: ZstdFrameRange[];\n /** Start of an incomplete final frame, when EOF interrupts one. */\n tornStart?: number;\n}\n\ntype ZstdDecompressSync = (input: Buffer) => Buffer;\n\n/**\n * Namespace import plus a runtime probe: a named import of a function absent\n * on older Node fails at ESM link time, taking every other agent down with it.\n */\nfunction resolveZstdDecoder(sourcePath: string): ZstdDecompressSync {\n const decoder = (zlib as { zstdDecompressSync?: ZstdDecompressSync }).zstdDecompressSync;\n if (typeof decoder !== \"function\") {\n throw new DshSessionLogError(\n `DSH session log ${JSON.stringify(sourcePath)} is Zstandard-compressed, but this Node ` +\n `runtime (${process.version}) has no native Zstandard decoder; DSH itself requires ` +\n \"Node ^22.19.0 || >=24.0.0\",\n );\n }\n return decoder;\n}\n\n/**\n * Locate structurally complete frames without decompressing any block. Only\n * the final frame may be cut short by EOF; anything else malformed is\n * corruption, because DSH publishes each batch as a whole frame.\n */\nfunction scanZstdFrames(\n buffer: Buffer,\n sourcePath: string,\n maxFrames = Number.POSITIVE_INFINITY,\n): ZstdFrameScan {\n const frames: ZstdFrameRange[] = [];\n let offset = 0;\n\n const corrupt = (reason: string): never => {\n throw new DshSessionLogError(\n `corrupt Zstandard session log ${JSON.stringify(sourcePath)}: ${reason}`,\n );\n };\n\n while (offset < buffer.length) {\n const start = offset;\n if (buffer.length - offset < 4) return { frames, tornStart: start };\n if (buffer.readUInt32LE(offset) !== ZSTD_MAGIC)\n corrupt(`invalid frame magic at byte ${offset}`);\n offset += 4;\n\n if (offset === buffer.length) return { frames, tornStart: start };\n const descriptor = buffer.readUInt8(offset);\n offset += 1;\n if ((descriptor & 0x18) !== 0) corrupt(`reserved frame-header bit at byte ${offset - 1}`);\n\n const contentSizeFlag = descriptor >>> 6;\n const singleSegment = (descriptor & 0x20) !== 0;\n const hasChecksum = (descriptor & 0x04) !== 0;\n const dictionaryFlag = descriptor & 0x03;\n const dictionaryBytes = dictionaryFlag === 3 ? 4 : dictionaryFlag;\n const contentSizeBytes = contentSizeFlag === 0 ? (singleSegment ? 1 : 0) : 1 << contentSizeFlag;\n const remainingHeaderBytes = (singleSegment ? 0 : 1) + dictionaryBytes + contentSizeBytes;\n if (buffer.length - offset < remainingHeaderBytes) return { frames, tornStart: start };\n offset += remainingHeaderBytes;\n\n for (;;) {\n if (buffer.length - offset < 3) return { frames, tornStart: start };\n const blockHeader = buffer.readUIntLE(offset, 3);\n offset += 3;\n const lastBlock = (blockHeader & 1) !== 0;\n const blockType = (blockHeader >>> 1) & 0x03;\n const blockSize = blockHeader >>> 3;\n if (blockType === 0x03) corrupt(`reserved block type at byte ${offset - 3}`);\n // An RLE block stores one repeated byte regardless of its declared size.\n const payloadBytes = blockType === 0x01 ? 1 : blockSize;\n if (buffer.length - offset < payloadBytes) return { frames, tornStart: start };\n offset += payloadBytes;\n if (lastBlock) break;\n }\n\n if (hasChecksum) {\n if (buffer.length - offset < 4) return { frames, tornStart: start };\n offset += 4;\n }\n frames.push({ start, end: offset });\n if (frames.length === maxFrames) return { frames };\n }\n\n return { frames };\n}\n\n/** Decode one complete frame; Node's decoder validates the frame checksum. */\nfunction decodeFrame(\n decoder: ZstdDecompressSync,\n buffer: Buffer,\n frame: ZstdFrameRange,\n sourcePath: string,\n): string {\n try {\n return decoder(buffer.subarray(frame.start, frame.end)).toString(\"utf8\");\n } catch (error) {\n throw new DshSessionLogError(\n `corrupt Zstandard session log ${JSON.stringify(sourcePath)}: frame at byte ${frame.start} failed validation`,\n { cause: error },\n );\n }\n}\n\n/**\n * Split one frame's plaintext into whole JSONL records. A complete frame that\n * ends mid-record is corruption, not a torn tail: DSH writes each batch as\n * newline-terminated lines inside a single frame.\n */\nfunction frameRecords(plaintext: string, sourcePath: string, frameStart: number): string[] {\n if (!plaintext.endsWith(\"\\n\")) {\n throw new DshSessionLogError(\n `corrupt Zstandard session log ${JSON.stringify(sourcePath)}: complete frame at byte ${frameStart} ends mid-record`,\n );\n }\n return plaintext.slice(0, -1).split(\"\\n\");\n}\n\nfunction warnTornTail(sourcePath: string, detail: Record<string, unknown>): void {\n getCoreDiagnostics()?.warn(\"dsh.torn_session_tail\", { source_path: sourcePath, ...detail });\n}\n\n/** Records of a compressed artifact, header line first. */\nfunction readCompressedRecords(buffer: Buffer, sourcePath: string, headerOnly: boolean): string[] {\n const decoder = resolveZstdDecoder(sourcePath);\n const scan = scanZstdFrames(buffer, sourcePath, headerOnly ? 1 : Number.POSITIVE_INFINITY);\n const first = scan.frames[0];\n if (!first) {\n throw new DshSessionLogError(\n `DSH session log ${JSON.stringify(sourcePath)} has no complete header frame`,\n );\n }\n\n const headerPlaintext = decodeFrame(decoder, buffer, first, sourcePath);\n if (headerPlaintext.indexOf(\"\\n\") !== headerPlaintext.length - 1) {\n throw new DshSessionLogError(\n `corrupt Zstandard session log ${JSON.stringify(sourcePath)}: header frame does not hold exactly one record`,\n );\n }\n const records = [headerPlaintext.slice(0, -1)];\n if (headerOnly) return records;\n\n for (const frame of scan.frames.slice(1)) {\n records.push(\n ...frameRecords(decodeFrame(decoder, buffer, frame, sourcePath), sourcePath, frame.start),\n );\n }\n if (scan.tornStart !== undefined) {\n warnTornTail(sourcePath, { encoding: \"zstd\", torn_start: scan.tornStart });\n }\n return records;\n}\n\n/** Records of a plaintext artifact; an unterminated final line is a torn tail. */\nfunction readPlaintextRecords(buffer: Buffer, sourcePath: string, headerOnly: boolean): string[] {\n const text = buffer.toString(\"utf8\");\n const newline = text.indexOf(\"\\n\");\n if (newline === -1) {\n throw new DshSessionLogError(\n `DSH session log ${JSON.stringify(sourcePath)} has no complete header record`,\n );\n }\n if (headerOnly) return [text.slice(0, newline)];\n\n const complete = text.endsWith(\"\\n\");\n const records = (complete ? text.slice(0, -1) : text).split(\"\\n\");\n if (!complete) {\n records.pop();\n warnTornTail(sourcePath, {\n encoding: \"none\",\n torn_bytes: text.length - text.lastIndexOf(\"\\n\") - 1,\n });\n }\n return records;\n}\n\nfunction readRecords(\n buffer: Buffer,\n sourcePath: string,\n encoding: DshEncoding,\n headerOnly: boolean,\n): string[] {\n return encoding === \"zstd\"\n ? readCompressedRecords(buffer, sourcePath, headerOnly)\n : readPlaintextRecords(buffer, sourcePath, headerOnly);\n}\n\n// ---------------------------------------------------------------------------\n// Header and event validation\n// ---------------------------------------------------------------------------\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isCount(value: unknown): value is number {\n return typeof value === \"number\" && Number.isSafeInteger(value) && value >= 0;\n}\n\nfunction optionalString(value: unknown, field: string, sourcePath: string): string | undefined {\n if (value === undefined) return undefined;\n if (typeof value !== \"string\") {\n throw new DshSessionLogError(\n `corrupt DSH session log ${JSON.stringify(sourcePath)}: header ${field} must be a string`,\n );\n }\n return value;\n}\n\nfunction parseJsonRecord(line: string, what: string, sourcePath: string): Record<string, unknown> {\n let parsed: unknown;\n try {\n parsed = JSON.parse(line);\n } catch (error) {\n throw new DshSessionLogError(\n `corrupt DSH session log ${JSON.stringify(sourcePath)}: ${what} is not valid JSON`,\n { cause: error },\n );\n }\n if (!isRecord(parsed)) {\n throw new DshSessionLogError(\n `corrupt DSH session log ${JSON.stringify(sourcePath)}: ${what} is not an object`,\n );\n }\n return parsed;\n}\n\n/**\n * Refuse a foreign format version before any structural check: a future format\n * need not satisfy today's shape at all, and its reader owes the user \"upgrade\n * CodeSesh\", never \"corrupt session log\".\n */\nfunction parseHeaderRecord(line: string, sourcePath: string): DshSessionHeader {\n const parsed = parseJsonRecord(line, \"header line\", sourcePath);\n const version = parsed[\"version\"];\n if (typeof version !== \"number\" || version !== DSH_FORMAT_VERSION) {\n throw new DshSessionLogError(\n `unsupported DSH session format version ${JSON.stringify(version)} in ${JSON.stringify(sourcePath)}; ` +\n `this build reads version ${DSH_FORMAT_VERSION}`,\n );\n }\n const invalid = (reason: string): never => {\n throw new DshSessionLogError(\n `corrupt DSH session log ${JSON.stringify(sourcePath)}: ${reason}`,\n );\n };\n\n if (parsed[\"type\"] !== \"session\") invalid(\"first record is not a session header\");\n const id = parsed[\"id\"];\n if (typeof id !== \"string\" || id.length === 0) invalid(\"header id must be a non-empty string\");\n const createdAt = parsed[\"createdAt\"];\n if (!isCount(createdAt)) invalid(\"header createdAt must be a non-negative safe integer\");\n const delegationDepth = parsed[\"delegationDepth\"];\n if (!isCount(delegationDepth)) {\n invalid(\"header delegationDepth must be a non-negative safe integer\");\n }\n const seedLength = parsed[\"seedLength\"];\n if (seedLength !== undefined && !isCount(seedLength)) {\n invalid(\"header seedLength must be a non-negative safe integer\");\n }\n const origin = parsed[\"origin\"];\n if (origin !== undefined && origin !== \"subagent\") invalid(\"header origin must be 'subagent'\");\n\n return {\n id: id as string,\n createdAt: createdAt as number,\n cwd: optionalString(parsed[\"cwd\"], \"cwd\", sourcePath),\n parentSession: optionalString(parsed[\"parentSession\"], \"parentSession\", sourcePath),\n seedLength: seedLength as number | undefined,\n origin: origin as \"subagent\" | undefined,\n delegationDepth: delegationDepth as number,\n agentPreset: optionalString(parsed[\"agentPreset\"], \"agentPreset\", sourcePath),\n };\n}\n\n/** Validate the run-shared fields of a packed chunk row and return its members. */\nfunction chunkRunMembers(\n data: Record<string, unknown>,\n payloadKey: \"texts\" | \"args\",\n tag: string,\n sourcePath: string,\n): { members: string[]; gaps: number[] } {\n const malformed = (reason: string): never => {\n throw new DshSessionLogError(\n `corrupt DSH session log ${JSON.stringify(sourcePath)}: malformed ${tag} storage row: ${reason}`,\n );\n };\n if (\n typeof data[\"turn\"] !== \"number\" ||\n typeof data[\"step\"] !== \"number\" ||\n typeof data[\"index\"] !== \"number\"\n ) {\n malformed(\"turn/step/index must be numbers\");\n }\n const payload = data[payloadKey];\n if (\n !Array.isArray(payload) ||\n payload.length === 0 ||\n payload.some((entry) => typeof entry !== \"string\")\n ) {\n malformed(`${payloadKey} must be a non-empty string array`);\n }\n const gaps = data[\"dt\"];\n if (!Array.isArray(gaps) || gaps.some((gap) => !Number.isSafeInteger(gap))) {\n malformed(\"dt must be an array of safe integers\");\n }\n const members = payload as string[];\n if ((gaps as number[]).length !== members.length - 1) {\n malformed(`dt length ${(gaps as number[]).length} does not match ${members.length} members`);\n }\n return { members, gaps: gaps as number[] };\n}\n\n/**\n * Expand one packed chunk row back into the exact `assistant/chunk` events it\n * stores. A malformed row throws: treating it as a single opaque event would\n * silently drop an entire streaming run.\n */\nfunction expandChunkRow(row: Record<string, unknown>, tag: string, sourcePath: string): DshEvent[] {\n const malformed = (reason: string): never => {\n throw new DshSessionLogError(\n `corrupt DSH session log ${JSON.stringify(sourcePath)}: malformed ${tag} storage row: ${reason}`,\n );\n };\n const seq0 = row[\"seq0\"];\n const time0 = row[\"time0\"];\n if (!isCount(seq0)) malformed(\"seq0 must be a non-negative safe integer\");\n if (!Number.isSafeInteger(time0)) malformed(\"time0 must be a safe integer\");\n const data = row[\"data\"];\n if (!isRecord(data)) malformed(\"data must be an object\");\n const payload = data as Record<string, unknown>;\n\n const isToolCall = tag === TOOL_CALL_CHUNK_ROW;\n const { members, gaps } = chunkRunMembers(\n payload,\n isToolCall ? \"args\" : \"texts\",\n tag,\n sourcePath,\n );\n const callId = payload[\"id\"];\n const callName = payload[\"name\"];\n if (isToolCall) {\n if (typeof callId !== \"string\") malformed(\"id must be a string\");\n if (callName !== undefined && typeof callName !== \"string\") malformed(\"name must be a string\");\n }\n if (!Number.isSafeInteger((seq0 as number) + members.length - 1)) {\n malformed(\"member seqs must stay safe integers\");\n }\n\n const turn = payload[\"turn\"] as number;\n const step = payload[\"step\"] as number;\n const index = payload[\"index\"] as number;\n const deltaType =\n tag === \"text-chunks\"\n ? \"text-delta\"\n : tag === \"reasoning-chunks\"\n ? \"reasoning-delta\"\n : \"tool-call-delta\";\n\n const events: DshEvent[] = [];\n let time = time0 as number;\n for (let member = 0; member < members.length; member += 1) {\n if (member > 0) {\n time += gaps[member - 1] as number;\n if (!Number.isSafeInteger(time)) malformed(\"member times must stay safe integers\");\n }\n const chunk = isToolCall\n ? {\n type: deltaType,\n index,\n id: callId,\n ...(callName !== undefined ? { name: callName } : {}),\n argumentsDelta: members[member],\n }\n : { type: deltaType, index, text: members[member] };\n events.push({\n type: \"assistant/chunk\",\n seq: (seq0 as number) + member,\n time,\n data: { turn, step, chunk },\n });\n }\n return events;\n}\n\n/** Decode one storage record into the event(s) it holds, in log order. */\nfunction decodeStorageRecord(line: string, sourcePath: string): DshEvent[] {\n const parsed = parseJsonRecord(line, \"event record\", sourcePath);\n const tag = parsed[\"type\"];\n if (typeof tag === \"string\" && (TEXT_CHUNK_ROWS.has(tag) || tag === TOOL_CALL_CHUNK_ROW)) {\n return expandChunkRow(parsed, tag, sourcePath);\n }\n if (typeof tag !== \"string\" || tag.length === 0) {\n throw new DshSessionLogError(\n `corrupt DSH session log ${JSON.stringify(sourcePath)}: event record has no type`,\n );\n }\n if (!KNOWN_DSH_EVENT_TYPES.has(tag) && parsed[\"ignorable\"] !== true) {\n throw new DshSessionLogError(\n `DSH session log ${JSON.stringify(sourcePath)} contains unsupported required event ` +\n `${JSON.stringify(tag)}; upgrade CodeSesh to read it`,\n );\n }\n if (!isCount(parsed[\"seq\"]) || !Number.isSafeInteger(parsed[\"time\"])) {\n throw new DshSessionLogError(\n `corrupt DSH session log ${JSON.stringify(sourcePath)}: event ${JSON.stringify(tag)} has an invalid seq/time`,\n );\n }\n // SAFETY: The tag and seq/time guards validate the envelope; materialization checks event-specific payloads.\n // oxlint-disable-next-line anti-slop/no-chained-type-assertions -- Preserve the decoded JSON object after validating its envelope.\n return [parsed as unknown as DshEvent];\n}\n\n// ---------------------------------------------------------------------------\n// Public reads\n// ---------------------------------------------------------------------------\n\n/**\n * Read a log's authoritative identity without decoding its conversation, so\n * enumeration scales with the session count rather than total log size.\n *\n * The header is an immutable prefix that only a whole-file replacement can\n * change, and a replacement moves the fingerprint, so this read deliberately\n * skips the stable-snapshot handshake a full parse needs.\n */\nexport function readDshSessionHeader(sourcePath: string, encoding: DshEncoding): DshSessionHeader {\n const prefix = readFilePrefix(sourcePath, HEADER_PREFIX_BYTES);\n const line =\n firstRecordOf(prefix, sourcePath, encoding, prefix.length === HEADER_PREFIX_BYTES) ??\n firstRecordOf(readFileSync(sourcePath), sourcePath, encoding, false);\n return parseHeaderRecord(line as string, sourcePath);\n}\n\n/** The first record, or null when only a longer read could contain it. */\nfunction firstRecordOf(\n buffer: Buffer,\n sourcePath: string,\n encoding: DshEncoding,\n mayBeTruncated: boolean,\n): string | null {\n if (mayBeTruncated) {\n const complete =\n encoding === \"zstd\"\n ? scanZstdFrames(buffer, sourcePath, 1).frames.length > 0\n : buffer.includes(0x0a);\n if (!complete) return null;\n }\n return readRecords(buffer, sourcePath, encoding, true)[0] as string;\n}\n\n/**\n * Read the header and the contiguous event prefix a log can prove. Expanded\n * events must be densely numbered from zero: a gap, duplicate or rewind means\n * the source is corrupt, not merely incomplete.\n */\nexport function readDshSessionLog(sourcePath: string, encoding: DshEncoding): DshSessionLog {\n const { buffer } = readDshFileSnapshot(sourcePath);\n const records = readRecords(buffer, sourcePath, encoding, false);\n const header = parseHeaderRecord(records[0] as string, sourcePath);\n\n const events: DshEvent[] = [];\n for (let line = 1; line < records.length; line += 1) {\n for (const event of decodeStorageRecord(records[line] as string, sourcePath)) {\n if (event.seq !== events.length) {\n throw new DshSessionLogError(\n `corrupt DSH session log ${JSON.stringify(sourcePath)}: seq ${event.seq} at record ` +\n `${line} breaks the contiguous prefix (expected ${events.length})`,\n );\n }\n events.push(event);\n }\n }\n\n if (header.seedLength !== undefined && header.seedLength > events.length) {\n throw new DshSessionLogError(\n `corrupt DSH session log ${JSON.stringify(sourcePath)}: seedLength ${header.seedLength} ` +\n `exceeds ${events.length} events`,\n );\n }\n\n return { header, events };\n}\n","/**\n * Projection from a DSH v0 event log onto CodeSesh's session contract.\n *\n * Three DSH distinctions drive everything here and have no CodeSesh equivalent\n * yet, so they are resolved during projection rather than shown raw:\n *\n * - `user/message` covers direct human prompts AND injected context (agent\n * instructions, system-prompt snapshots, skill catalogs); only `source.kind\n * === 'user'` is a human turn.\n * - the model-visible surface deliberately shadows compacted ranges, so a\n * human transcript projects append-origin events only.\n * - a forked log carries its parent's history as an inherited seed prefix;\n * counting it in the child would bill the same tokens once per descendant.\n */\nimport { createHash } from \"node:crypto\";\nimport { readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type {\n ImagePart,\n Message,\n MessagePart,\n MessageTokens,\n SessionStats,\n ToolPart,\n} from \"../types/index.js\";\nimport { estimateTokenCost } from \"../utils/cost.js\";\nimport { getCoreDiagnostics } from \"../utils/diagnostics.js\";\nimport { cleanInternalText } from \"../utils/session-normalization.js\";\nimport { normalizeTitleText } from \"../utils/title-fallback.js\";\nimport { DshSessionLogError, type DshEvent, type DshSessionHeader } from \"./dsh-session-log.js\";\nimport { TranscriptBuilder } from \"./transcript-builder.js\";\n\nconst AGENT_NAME = \"dsh\";\n\n/** DSH's version-one attachment path accepts exactly these raster formats. */\nconst IMAGE_MEDIA_TYPES: ReadonlySet<string> = new Set([\n \"image/png\",\n \"image/jpeg\",\n \"image/webp\",\n \"image/gif\",\n]);\n\nconst ATTACHMENT_ID_PATTERN = /^sha256:([a-f0-9]{64})$/;\n\nconst IMAGE_UNAVAILABLE_TEXT = \"Image attachment unavailable\";\n\nexport interface DshProjection {\n messages: Message[];\n stats: SessionStats;\n modelUsage: Record<string, number>;\n title: string | null;\n updatedAt: number;\n}\n\ninterface UsageTotals {\n input: number;\n /** Raw DSH output tokens; reasoning is already included in it. */\n output: number;\n cacheRead: number;\n cacheCreate: number;\n cost: number;\n}\n\n/** Streaming state for one `(turn, step)` that has no settled message yet. */\ninterface PendingStep {\n turn: number;\n step: number;\n firstTime: number;\n lastTime: number;\n blocks: Map<number, PendingBlock>;\n usage: DshTokenUsage | null;\n}\n\ntype PendingBlock =\n | { type: \"text\" | \"reasoning\"; text: string }\n | { type: \"tool-call\"; id: string; name: string; args: string };\n\ninterface DshTokenUsage {\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens?: number;\n cacheWriteTokens?: number;\n reasoningTokens?: number;\n}\n\ninterface ProjectionContext {\n sessionId: string;\n sourcePath: string;\n attachmentsRoot: string;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> {\n return isRecord(value) ? value : {};\n}\n\nfunction asText(value: unknown): string {\n return typeof value === \"string\" ? value : \"\";\n}\n\nfunction corrupt(context: ProjectionContext, reason: string): never {\n throw new DshSessionLogError(\n `corrupt DSH session log ${JSON.stringify(context.sourcePath)}: ${reason}`,\n );\n}\n\nfunction warn(context: ProjectionContext, event: string, detail: Record<string, unknown>): void {\n getCoreDiagnostics()?.warn(event, {\n agent: AGENT_NAME,\n session_id: context.sessionId,\n ...detail,\n });\n}\n\n// ---------------------------------------------------------------------------\n// Surface placement\n// ---------------------------------------------------------------------------\n\nconst SURFACE_EVENT_TYPES: ReadonlySet<string> = new Set([\n \"user/message\",\n \"assistant/message\",\n \"tool/result\",\n]);\n\n/**\n * Classify how a surface-eligible event entered the model-visible surface.\n * Only `append` belongs in a human transcript: a replacement is a compaction\n * copy that shadows conversation the user already saw.\n */\nfunction isAppendOrigin(event: DshEvent, context: ProjectionContext): boolean {\n if (!SURFACE_EVENT_TYPES.has(event.type)) return false;\n const op = event.surfaceOp;\n if (op === \"append\") return true;\n if (op === undefined) {\n corrupt(\n context,\n `surface event ${JSON.stringify(event.type)} at seq ${event.seq} has no surfaceOp`,\n );\n }\n const replace = asRecord(op);\n if (\n replace[\"op\"] !== \"replace\" ||\n !Number.isSafeInteger(replace[\"start\"]) ||\n !Number.isSafeInteger(replace[\"end\"])\n ) {\n corrupt(\n context,\n `surface event ${JSON.stringify(event.type)} at seq ${event.seq} has an invalid surfaceOp`,\n );\n }\n return false;\n}\n\n// ---------------------------------------------------------------------------\n// Content blocks\n// ---------------------------------------------------------------------------\n\n/**\n * Load a content-addressed image and prove the bytes still match the durable\n * reference. The attachment id is matched against a strict `sha256:<hex>`\n * pattern and used only to derive the object path — never joined as a path.\n */\nfunction readImageBlock(\n block: Record<string, unknown>,\n timeMs: number,\n context: ProjectionContext,\n): ImagePart | null {\n const attachment = asRecord(block[\"attachment\"]);\n const attachmentId = asText(attachment[\"attachmentId\"]);\n const mediaType = asText(attachment[\"mediaType\"]);\n const digest = ATTACHMENT_ID_PATTERN.exec(attachmentId)?.[1];\n\n const reject = (reason: string): null => {\n warn(context, \"dsh.attachment_unreadable\", { attachment_id: attachmentId, reason });\n return null;\n };\n\n if (!digest) return reject(\"invalid attachment reference\");\n if (!IMAGE_MEDIA_TYPES.has(mediaType)) return reject(\"unsupported media type\");\n\n let data: Buffer;\n try {\n data = readFileSync(join(context.attachmentsRoot, \"objects\", digest.slice(0, 2), digest));\n } catch {\n return reject(\"attachment object is missing\");\n }\n const declaredBytes = attachment[\"bytes\"];\n if (typeof declaredBytes === \"number\" && data.byteLength !== declaredBytes) {\n return reject(\"attachment byte length does not match its reference\");\n }\n if (createHash(\"sha256\").update(data).digest(\"hex\") !== digest) {\n return reject(\"attachment failed integrity verification\");\n }\n\n return {\n type: \"image\",\n data: data.toString(\"base64\"),\n mime_type: mediaType,\n time_created: timeMs,\n };\n}\n\n/**\n * Convert DSH content blocks into CodeSesh parts. `tool-call` blocks are\n * skipped when a canonical `tool/call` event carries the same call: the two\n * describe one invocation and rendering both would duplicate the tool card.\n */\nfunction convertContentBlocks(\n content: unknown,\n timeMs: number,\n context: ProjectionContext,\n canonicalCallIds: ReadonlySet<string>,\n): MessagePart[] {\n if (!Array.isArray(content)) return [];\n const parts: MessagePart[] = [];\n let droppedImages = 0;\n\n for (const raw of content) {\n const block = asRecord(raw);\n switch (block[\"type\"]) {\n case \"text\":\n case \"reasoning\": {\n const text = cleanInternalText(asText(block[\"text\"]));\n if (text) parts.push({ type: block[\"type\"], text, time_created: timeMs });\n break;\n }\n case \"image\": {\n const image = readImageBlock(block, timeMs, context);\n if (image) parts.push(image);\n else droppedImages += 1;\n break;\n }\n case \"tool-call\": {\n const callId = asText(block[\"id\"]);\n if (callId && canonicalCallIds.has(callId)) break;\n parts.push(buildToolPart(callId, asText(block[\"name\"]), block[\"arguments\"], timeMs));\n break;\n }\n default:\n break;\n }\n }\n\n // A message whose only content was an unreadable image must keep its place\n // in the timeline rather than vanish from the conversation.\n if (parts.length === 0 && droppedImages > 0) {\n parts.push({ type: \"text\", text: IMAGE_UNAVAILABLE_TEXT, time_created: timeMs });\n }\n return parts;\n}\n\n/** Raw arguments stay verbatim when unparsable so an interrupted call is still diagnosable. */\nfunction parseToolArguments(raw: unknown): unknown {\n if (typeof raw !== \"string\") return raw ?? {};\n try {\n return JSON.parse(raw);\n } catch {\n return raw;\n }\n}\n\nfunction buildToolPart(\n callId: string,\n name: string,\n rawArguments: unknown,\n timeMs: number,\n): ToolPart {\n const tool = name.trim() || \"tool\";\n return {\n type: \"tool\",\n tool,\n title: tool.toLowerCase(),\n callID: callId || undefined,\n time_created: timeMs,\n state: { status: \"running\", input: parseToolArguments(rawArguments) },\n };\n}\n\n// ---------------------------------------------------------------------------\n// Token accounting\n// ---------------------------------------------------------------------------\n\nfunction nonNegative(value: unknown): number {\n return typeof value === \"number\" && Number.isFinite(value) && value > 0 ? value : 0;\n}\n\nfunction readUsage(value: unknown): DshTokenUsage | null {\n if (!isRecord(value)) return null;\n return {\n inputTokens: nonNegative(value[\"inputTokens\"]),\n outputTokens: nonNegative(value[\"outputTokens\"]),\n cacheReadTokens: nonNegative(value[\"cacheReadTokens\"]),\n cacheWriteTokens: nonNegative(value[\"cacheWriteTokens\"]),\n reasoningTokens: nonNegative(value[\"reasoningTokens\"]),\n };\n}\n\n/**\n * DSH input buckets are disjoint (`inputTokens` is uncached input, cache reads\n * and writes are separate) and reasoning is already inside `outputTokens`.\n * CodeSesh prices a total input and a visible output separately, so the buckets\n * are folded in and reasoning is split out — counting either twice would\n * inflate both the token totals and the estimated cost.\n */\nfunction toMessageTokens(usage: DshTokenUsage): { tokens: MessageTokens; totals: UsageTotals } {\n const cacheRead = nonNegative(usage.cacheReadTokens);\n const cacheCreate = nonNegative(usage.cacheWriteTokens);\n const totalInput = nonNegative(usage.inputTokens) + cacheRead + cacheCreate;\n const output = nonNegative(usage.outputTokens);\n const reasoning = Math.min(nonNegative(usage.reasoningTokens), output);\n\n return {\n tokens: {\n input: totalInput,\n output: output - reasoning,\n reasoning: reasoning || undefined,\n cache_read: cacheRead || undefined,\n cache_create: cacheCreate || undefined,\n },\n totals: { input: totalInput, output, cacheRead, cacheCreate, cost: 0 },\n };\n}\n\n// ---------------------------------------------------------------------------\n// Projection\n// ---------------------------------------------------------------------------\n\nclass DshProjector {\n private readonly builder = new TranscriptBuilder({ messageDefaults: \"sparse\" });\n private readonly totals: UsageTotals = {\n input: 0,\n output: 0,\n cacheRead: 0,\n cacheCreate: 0,\n cost: 0,\n };\n private readonly modelUsage: Record<string, number> = {};\n private readonly settledSteps = new Set<string>();\n private pending: PendingStep | null = null;\n private provider: string | null = null;\n private model: string | null = null;\n private ownTitle: string | null = null;\n private inheritedTitle: string | null = null;\n private subagentLabel: string | null = null;\n private firstHumanText: string | null = null;\n private updatedAt = 0;\n\n constructor(\n private readonly context: ProjectionContext,\n private readonly seedLength: number,\n private readonly canonicalCallIds: ReadonlySet<string>,\n ) {}\n\n project(events: readonly DshEvent[]): DshProjection {\n for (const event of events) {\n const own = event.seq >= this.seedLength;\n if (own) this.updatedAt = Math.max(this.updatedAt, event.time);\n this.consume(event, own);\n }\n this.flushPendingStep();\n\n const result = this.builder.finish({\n message_count: 0,\n total_input_tokens: this.totals.input,\n total_output_tokens: this.totals.output,\n total_cache_read_tokens: this.totals.cacheRead || undefined,\n total_cache_create_tokens: this.totals.cacheCreate || undefined,\n total_cost: this.totals.cost,\n cost_source: this.totals.cost > 0 ? \"estimated\" : undefined,\n });\n\n return {\n messages: result.messages,\n stats: result.stats,\n modelUsage: this.modelUsage,\n title: this.resolveTitle(),\n updatedAt: this.updatedAt,\n };\n }\n\n private consume(event: DshEvent, own: boolean): void {\n switch (event.type) {\n case \"user/message\":\n this.consumeUserMessage(event, own);\n return;\n case \"assistant/message\":\n this.consumeAssistantMessage(event, own);\n return;\n case \"tool/call\":\n if (own) this.consumeToolCall(event);\n return;\n case \"tool/result\":\n if (isAppendOrigin(event, this.context) && own) this.consumeToolResult(event);\n return;\n case \"assistant/chunk\":\n if (own) this.consumeChunk(event);\n return;\n case \"request/context\":\n this.consumeRequestContext(event);\n return;\n case \"session/title\":\n this.consumeTitle(event, own);\n return;\n case \"subagent/descriptor\":\n if (own) this.consumeSubagentDescriptor(event);\n return;\n default:\n return;\n }\n }\n\n private consumeUserMessage(event: DshEvent, own: boolean): void {\n // Every user/message is validated for surface placement, but injected\n // context and compaction replacements never become human turns.\n const appendOrigin = isAppendOrigin(event, this.context);\n const data = asRecord(event.data);\n if (!appendOrigin || !own || asRecord(data[\"source\"])[\"kind\"] !== \"user\") return;\n\n const parts = convertContentBlocks(\n data[\"content\"],\n event.time,\n this.context,\n this.canonicalCallIds,\n );\n if (parts.length === 0) return;\n this.builder.appendMessage({\n id: asText(data[\"id\"]) || `dsh-user-${event.seq}`,\n role: \"user\",\n timestampMs: event.time,\n parts,\n });\n // Read the title candidate from the source blocks, so an unreadable-image\n // placeholder never becomes the session's name.\n this.firstHumanText ??= firstTextBlock(data[\"content\"]);\n }\n\n private consumeAssistantMessage(event: DshEvent, own: boolean): void {\n const appendOrigin = isAppendOrigin(event, this.context);\n const data = asRecord(event.data);\n const turn = data[\"turn\"];\n const step = data[\"step\"];\n if (typeof turn === \"number\" && typeof step === \"number\") {\n this.settleStep(turn, step);\n }\n if (!appendOrigin || !own) return;\n\n const message = asRecord(data[\"message\"]);\n const source = asRecord(message[\"source\"]);\n const provider = asText(source[\"provider\"]) || null;\n const model = asText(source[\"model\"]) || null;\n if (provider) this.provider = provider;\n if (model) this.model = model;\n\n const parts = convertContentBlocks(\n message[\"content\"],\n event.time,\n this.context,\n this.canonicalCallIds,\n );\n const usage = readUsage(data[\"usage\"]);\n this.appendAssistant({\n id: asText(message[\"id\"]) || `dsh-assistant-${event.seq}`,\n timeMs: event.time,\n parts,\n provider,\n model,\n usage,\n });\n }\n\n private consumeToolCall(event: DshEvent): void {\n const data = asRecord(event.data);\n const callId = asText(data[\"callId\"]);\n const part = buildToolPart(callId, asText(data[\"name\"]), data[\"arguments\"], event.time);\n this.builder.appendToolCall(\n part,\n { id: callId, timestampMs: event.time, agent: AGENT_NAME },\n { target: \"current\" },\n );\n }\n\n private consumeToolResult(event: DshEvent): void {\n const data = asRecord(event.data);\n const message = asRecord(data[\"message\"]);\n const source = asRecord(message[\"source\"]);\n if (source[\"kind\"] !== \"tool\") {\n corrupt(this.context, `tool/result at seq ${event.seq} is not sourced from a tool call`);\n }\n const callId = asText(source[\"callId\"]);\n const content = Array.isArray(message[\"content\"]) ? message[\"content\"] : [];\n const block = asRecord(content[0]);\n if (content.length !== 1 || block[\"type\"] !== \"tool-result\") {\n corrupt(\n this.context,\n `tool/result at seq ${event.seq} must carry exactly one tool-result block`,\n );\n }\n if (asText(block[\"toolCallId\"]) !== callId) {\n corrupt(this.context, `tool/result at seq ${event.seq} disagrees with its call identity`);\n }\n\n const failed = block[\"isError\"] === true || isRecord(data[\"error\"]);\n const resolved = this.builder.resolveToolCall(callId, {\n output: convertContentBlocks(\n block[\"content\"],\n event.time,\n this.context,\n this.canonicalCallIds,\n ),\n status: failed ? \"error\" : \"completed\",\n metadata: data[\"meta\"],\n consume: true,\n });\n if (!resolved) {\n warn(this.context, \"dsh.orphan_tool_result\", { call_id: callId, seq: event.seq });\n }\n }\n\n private consumeChunk(event: DshEvent): void {\n const data = asRecord(event.data);\n const turn = data[\"turn\"];\n const step = data[\"step\"];\n if (typeof turn !== \"number\" || typeof step !== \"number\") return;\n if (this.settledSteps.has(stepKey(turn, step))) return;\n\n const pending = this.openStep(turn, step, event.time);\n pending.lastTime = event.time;\n applyChunk(pending, asRecord(data[\"chunk\"]));\n }\n\n private consumeRequestContext(event: DshEvent): void {\n const data = asRecord(event.data);\n const provider = asText(data[\"provider\"]);\n const model = asText(data[\"model\"]);\n if (provider) this.provider = provider;\n if (model) this.model = model;\n }\n\n private consumeTitle(event: DshEvent, own: boolean): void {\n const title = normalizeTitleText(asText(asRecord(event.data)[\"title\"]));\n if (!title) return;\n if (own) this.ownTitle = title;\n else this.inheritedTitle = title;\n }\n\n private consumeSubagentDescriptor(event: DshEvent): void {\n const label = normalizeTitleText(asText(asRecord(event.data)[\"label\"]));\n if (label) this.subagentLabel ??= label;\n }\n\n /** A settled message supersedes the streaming deltas of the same step. */\n private settleStep(turn: number, step: number): void {\n this.settledSteps.add(stepKey(turn, step));\n if (this.pending?.turn === turn && this.pending.step === step) this.pending = null;\n }\n\n private openStep(turn: number, step: number, timeMs: number): PendingStep {\n if (this.pending && (this.pending.turn !== turn || this.pending.step !== step)) {\n this.flushPendingStep();\n }\n this.pending ??= {\n turn,\n step,\n firstTime: timeMs,\n lastTime: timeMs,\n blocks: new Map(),\n usage: null,\n };\n return this.pending;\n }\n\n /** Rebuild the assistant message of a step the log was cut short in. */\n private flushPendingStep(): void {\n const pending = this.pending;\n this.pending = null;\n if (!pending) return;\n\n const parts: MessagePart[] = [];\n for (const index of [...pending.blocks.keys()].sort((a, b) => a - b)) {\n const block = pending.blocks.get(index) as PendingBlock;\n if (block.type === \"tool-call\") {\n if (this.canonicalCallIds.has(block.id)) continue;\n parts.push(buildToolPart(block.id, block.name, block.args, pending.lastTime));\n continue;\n }\n const text = cleanInternalText(block.text);\n if (text) parts.push({ type: block.type, text, time_created: pending.firstTime });\n }\n if (parts.length === 0) return;\n\n this.appendAssistant({\n id: `dsh-step-${pending.turn}-${pending.step}`,\n timeMs: pending.firstTime,\n parts,\n provider: this.provider,\n model: this.model,\n usage: pending.usage,\n });\n }\n\n private appendAssistant(input: {\n id: string;\n timeMs: number;\n parts: MessagePart[];\n provider: string | null;\n model: string | null;\n usage: DshTokenUsage | null;\n }): void {\n const mapped = input.usage ? toMessageTokens(input.usage) : null;\n const cost = mapped ? (estimateTokenCost(input.model, mapped.tokens) ?? 0) : 0;\n\n if (mapped) {\n this.totals.input += mapped.totals.input;\n this.totals.output += mapped.totals.output;\n this.totals.cacheRead += mapped.totals.cacheRead;\n this.totals.cacheCreate += mapped.totals.cacheCreate;\n this.totals.cost += cost;\n if (input.model) {\n const billed = mapped.totals.input + mapped.totals.output;\n this.modelUsage[input.model] = (this.modelUsage[input.model] ?? 0) + billed;\n }\n }\n\n // An empty-content assistant/message exists only to host a step's usage;\n // its tokens are real spend even though it shows nothing.\n if (input.parts.length === 0) return;\n\n this.builder.appendMessage({\n id: input.id,\n role: \"assistant\",\n agent: AGENT_NAME,\n timestampMs: input.timeMs,\n parts: input.parts,\n provider: input.provider,\n model: input.model,\n tokens: mapped?.tokens,\n cost: cost || undefined,\n costSource: cost > 0 ? \"estimated\" : undefined,\n });\n }\n\n private resolveTitle(): string | null {\n return this.ownTitle ?? this.subagentLabel ?? this.firstHumanText ?? this.inheritedTitle;\n }\n}\n\nfunction stepKey(turn: number, step: number): string {\n return `${turn}:${step}`;\n}\n\nfunction firstTextBlock(content: unknown): string | null {\n if (!Array.isArray(content)) return null;\n for (const raw of content) {\n const block = asRecord(raw);\n if (block[\"type\"] !== \"text\") continue;\n const text = cleanInternalText(asText(block[\"text\"]));\n if (text) return text;\n }\n return null;\n}\n\n/** Fold one stream chunk into the pending step's per-block accumulators. */\nfunction applyChunk(pending: PendingStep, chunk: Record<string, unknown>): void {\n const index = chunk[\"index\"];\n if (typeof index !== \"number\") {\n if (chunk[\"type\"] === \"usage\") pending.usage = readUsage(chunk[\"usage\"]);\n return;\n }\n\n switch (chunk[\"type\"]) {\n case \"text-delta\":\n case \"reasoning-delta\": {\n const type = chunk[\"type\"] === \"text-delta\" ? \"text\" : \"reasoning\";\n const current = pending.blocks.get(index);\n const text = current && current.type === type ? current.text : \"\";\n pending.blocks.set(index, { type, text: text + asText(chunk[\"text\"]) });\n return;\n }\n case \"tool-call-delta\": {\n const current = pending.blocks.get(index);\n const args = current && current.type === \"tool-call\" ? current.args : \"\";\n const name = current && current.type === \"tool-call\" ? current.name : \"\";\n pending.blocks.set(index, {\n type: \"tool-call\",\n id: asText(chunk[\"id\"]),\n name: asText(chunk[\"name\"]) || name,\n args: args + asText(chunk[\"argumentsDelta\"]),\n });\n return;\n }\n case \"block-end\": {\n // The assembled block is authoritative over the deltas that built it.\n const block = asRecord(chunk[\"block\"]);\n if (block[\"type\"] === \"text\" || block[\"type\"] === \"reasoning\") {\n pending.blocks.set(index, { type: block[\"type\"], text: asText(block[\"text\"]) });\n } else if (block[\"type\"] === \"tool-call\") {\n pending.blocks.set(index, {\n type: \"tool-call\",\n id: asText(block[\"id\"]),\n name: asText(block[\"name\"]),\n args: asText(block[\"arguments\"]),\n });\n }\n return;\n }\n default:\n return;\n }\n}\n\n/**\n * Collect the canonical call ids so an assistant message's `tool-call` blocks\n * can defer to them. A duplicate id is source corruption: two invocations\n * sharing an id make every result ambiguous.\n */\nfunction collectCanonicalCallIds(\n events: readonly DshEvent[],\n context: ProjectionContext,\n): ReadonlySet<string> {\n const ids = new Set<string>();\n for (const event of events) {\n if (event.type !== \"tool/call\") continue;\n const callId = asText(asRecord(event.data)[\"callId\"]);\n if (!callId) corrupt(context, `tool/call at seq ${event.seq} has no call id`);\n if (ids.has(callId)) corrupt(context, `duplicate tool call id ${JSON.stringify(callId)}`);\n ids.add(callId);\n }\n return ids;\n}\n\n/**\n * Project a DSH log onto CodeSesh messages, stats and title.\n *\n * `updatedAt` and every token total cover the session's own suffix only; the\n * inherited seed prefix still validates, but belongs to the parent.\n */\nexport function projectDshSession(options: {\n header: DshSessionHeader;\n events: readonly DshEvent[];\n sourcePath: string;\n attachmentsRoot: string;\n}): DshProjection {\n const context: ProjectionContext = {\n sessionId: options.header.id,\n sourcePath: options.sourcePath,\n attachmentsRoot: options.attachmentsRoot,\n };\n const projector = new DshProjector(\n context,\n options.header.seedLength ?? 0,\n collectCanonicalCallIds(options.events, context),\n );\n const projection = projector.project(options.events);\n return {\n ...projection,\n updatedAt: projection.updatedAt || options.header.createdAt,\n };\n}\n","import {\n AGENT_CATALOG,\n type AgentCatalogEntry,\n type AgentName,\n} from \"../contract/agent-catalog.js\";\nimport type { BaseAgent } from \"./base.js\";\nimport { ClaudeCodeAgent, resolveClaudeCodeDataRoot } from \"./claudecode.js\";\nimport { OpenCodeAgent, resolveOpenCodeDataRoot } from \"./opencode.js\";\nimport { KimiAgent, resolveKimiDataRoot } from \"./kimi.js\";\nimport { KimiCodeAgent, resolveKimiCodeDataRoot } from \"./kimi-code.js\";\nimport { CodexAgent, resolveCodexDataRoot } from \"./codex.js\";\nimport { CursorAgent, resolveCursorDataRoot } from \"./cursor.js\";\nimport { PiAgent, resolvePiDataRoot } from \"./pi.js\";\nimport { ZCodeAgent, resolveZCodeDataRoot } from \"./zcode.js\";\nimport { GrokAgent, resolveGrokDataRoot } from \"./grok.js\";\nimport { DshAgent, resolveDshDataRoot } from \"./dsh.js\";\n\nexport interface AgentRegistration extends AgentCatalogEntry {\n create: () => BaseAgent;\n resolveDataRoot: () => string | null;\n}\n\ntype AgentRuntimeRegistration = Pick<AgentRegistration, \"create\" | \"resolveDataRoot\">;\n\nconst RUNTIME_REGISTRATIONS = {\n claudecode: {\n create: () => new ClaudeCodeAgent(),\n resolveDataRoot: resolveClaudeCodeDataRoot,\n },\n cursor: {\n create: () => new CursorAgent(),\n resolveDataRoot: resolveCursorDataRoot,\n },\n kimi: {\n create: () => new KimiAgent(),\n resolveDataRoot: resolveKimiDataRoot,\n },\n \"kimi-code\": {\n create: () => new KimiCodeAgent(),\n resolveDataRoot: resolveKimiCodeDataRoot,\n },\n codex: {\n create: () => new CodexAgent(),\n resolveDataRoot: resolveCodexDataRoot,\n },\n grok: {\n create: () => new GrokAgent(),\n resolveDataRoot: resolveGrokDataRoot,\n },\n pi: {\n create: () => new PiAgent(),\n resolveDataRoot: resolvePiDataRoot,\n },\n opencode: {\n create: () => new OpenCodeAgent(),\n resolveDataRoot: resolveOpenCodeDataRoot,\n },\n zcode: {\n create: () => new ZCodeAgent(),\n resolveDataRoot: resolveZCodeDataRoot,\n },\n dsh: {\n create: () => new DshAgent(),\n resolveDataRoot: resolveDshDataRoot,\n },\n} satisfies Record<AgentName, AgentRuntimeRegistration>;\n\nexport const AGENT_REGISTRATIONS: readonly AgentRegistration[] = Object.freeze(\n AGENT_CATALOG.map((catalogEntry) => {\n const runtime = RUNTIME_REGISTRATIONS[catalogEntry.name];\n return Object.freeze({\n ...catalogEntry,\n ...runtime,\n create: () => {\n const agent = runtime.create();\n const expectedSource =\n catalogEntry.sourceKind === \"filesystem\" ? \"enumerated\" : \"aggregate\";\n if (agent.sessionSourceAccess.kind !== expectedSource) {\n throw new Error(\n `Agent ${catalogEntry.name} declares ${catalogEntry.sourceKind} storage but provides ${agent.sessionSourceAccess.kind} source access`,\n );\n }\n return agent;\n },\n });\n }),\n);\n","import type { BaseAgent } from \"./base.js\";\nimport type { AgentInfo } from \"../types/index.js\";\nimport { AGENT_REGISTRATIONS, type AgentRegistration } from \"./register.js\";\n\nexport type { AgentToolStrategy } from \"../contract/agent-catalog.js\";\n\nexport type { AgentRegistration } from \"./register.js\";\n\nexport type AgentRoots = Readonly<Record<string, string | null>>;\n\nexport function createRegisteredAgents(): BaseAgent[] {\n return AGENT_REGISTRATIONS.map((registration) => registration.create());\n}\n\nexport function getRegisteredAgents(): readonly AgentRegistration[] {\n return AGENT_REGISTRATIONS;\n}\n\nexport function resolveAgentRoots(): AgentRoots {\n return Object.fromEntries(\n AGENT_REGISTRATIONS.map((registration) => [registration.name, registration.resolveDataRoot()]),\n );\n}\n\nexport function getAgentInfoMap(sessionsByAgent: Record<string, number>): AgentInfo[] {\n return AGENT_REGISTRATIONS.map((registration) => ({\n name: registration.name,\n displayName: registration.displayName,\n icon: registration.icon,\n iconColored: registration.iconColored,\n resumeCommandPrefix: registration.resumeCommandPrefix,\n count: sessionsByAgent[registration.name] ?? 0,\n }));\n}\n"],"mappings":"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","names":["statSync","existsSync","join","readFileSync","basename","dirname","resolve","readdirSync","homedir","platform","createHash","message","toolPart","text","AGENT_METADATA","tokenCount","sessionStat","mapToolTitle","parseTimestamp","isInternalEventType","planPart","HEAD_INDEX_VERSION","normalizeToolOutputParts","composerId","PARSER_VERSION","result","corrupt","parseJsonRecord","isRecord","asRecord","buildToolPart","encoding"]}
|