Something went wrong. Try again.
source dump of claude code forked from oppi.li/claude-code
Something went wrong. Try again.
11 kB · 330 lines
TypeScript
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331import type { UUID } from 'crypto'import type { FileHistorySnapshot } from 'src/utils/fileHistory.js'import type { ContentReplacementRecord } from 'src/utils/toolResultStorage.js'import type { AgentId } from './ids.js'import type { Message } from './message.js'import type { QueueOperationMessage } from './messageQueueTypes.js'
export type SerializedMessage = Message & { cwd: string userType: string entrypoint?: string // CLAUDE_CODE_ENTRYPOINT — distinguishes cli/sdk-ts/sdk-py/etc. sessionId: string timestamp: string version: string gitBranch?: string slug?: string // Session slug for files like plans (used for resume)}
export type LogOption = { date: string messages: SerializedMessage[] fullPath?: string value: number created: Date modified: Date firstPrompt: string messageCount: number fileSize?: number // File size in bytes (for display) isSidechain: boolean isLite?: boolean // True for lite logs (messages not loaded) sessionId?: string // Session ID for lite logs teamName?: string // Team name if this is a spawned agent session agentName?: string // Agent's custom name (from /rename or swarm) agentColor?: string // Agent's color (from /rename or swarm) agentSetting?: string // Agent definition used (from --agent flag or settings.agent) isTeammate?: boolean // Whether this session was created by a swarm teammate leafUuid?: UUID // If given, this uuid must appear in the DB summary?: string // Optional conversation summary customTitle?: string // Optional user-set custom title tag?: string // Optional tag for the session (searchable in /resume) fileHistorySnapshots?: FileHistorySnapshot[] // Optional file history snapshots attributionSnapshots?: AttributionSnapshotMessage[] // Optional attribution snapshots contextCollapseCommits?: ContextCollapseCommitEntry[] // Ordered — commit B may reference commit A's summary contextCollapseSnapshot?: ContextCollapseSnapshotEntry // Last-wins — staged queue + spawn state gitBranch?: string // Git branch at the end of the session projectPath?: string // Original project directory path prNumber?: number // GitHub PR number linked to this session prUrl?: string // Full URL to the linked PR prRepository?: string // Repository in "owner/repo" format mode?: 'coordinator' | 'normal' // Session mode for coordinator/normal detection worktreeSession?: PersistedWorktreeSession | null // Worktree state at session end (null = exited, undefined = never entered) contentReplacements?: ContentReplacementRecord[] // Replacement decisions for resume reconstruction}
export type SummaryMessage = { type: 'summary' leafUuid: UUID summary: string}
export type CustomTitleMessage = { type: 'custom-title' sessionId: UUID customTitle: string}
/** * AI-generated session title. Distinct from CustomTitleMessage so that: * - User renames (custom-title) always win over AI titles in read preference * - reAppendSessionMetadata never re-appends AI titles (they're ephemeral/ * regeneratable; re-appending would clobber user renames on resume) * - VS Code's onlyIfNoCustomTitle CAS check only matches user titles, * allowing AI to overwrite its own previous AI title but not user titles */export type AiTitleMessage = { type: 'ai-title' sessionId: UUID aiTitle: string}
export type LastPromptMessage = { type: 'last-prompt' sessionId: UUID lastPrompt: string}
/** * Periodic fork-generated summary of what the agent is currently doing. * Written every min(5 steps, 2min) by forking the main thread mid-turn so * `claude ps` can show something more useful than the last user prompt * (which is often "ok go" or "fix it"). */export type TaskSummaryMessage = { type: 'task-summary' sessionId: UUID summary: string timestamp: string}
export type TagMessage = { type: 'tag' sessionId: UUID tag: string}
export type AgentNameMessage = { type: 'agent-name' sessionId: UUID agentName: string}
export type AgentColorMessage = { type: 'agent-color' sessionId: UUID agentColor: string}
export type AgentSettingMessage = { type: 'agent-setting' sessionId: UUID agentSetting: string}
/** * PR link message stored in session transcript. * Links a session to a GitHub pull request for tracking and navigation. */export type PRLinkMessage = { type: 'pr-link' sessionId: UUID prNumber: number prUrl: string prRepository: string // e.g., "owner/repo" timestamp: string // ISO timestamp when linked}
export type ModeEntry = { type: 'mode' sessionId: UUID mode: 'coordinator' | 'normal'}
/** * Worktree session state persisted to the transcript for resume. * Subset of WorktreeSession from utils/worktree.ts — excludes ephemeral * fields (creationDurationMs, usedSparsePaths) that are only used for * first-run analytics. */export type PersistedWorktreeSession = { originalCwd: string worktreePath: string worktreeName: string worktreeBranch?: string originalBranch?: string originalHeadCommit?: string sessionId: string tmuxSessionName?: string hookBased?: boolean}
/** * Records whether the session is currently inside a worktree created by * EnterWorktree or --worktree. Last-wins: an enter writes the session, * an exit writes null. On --resume, restored only if the worktreePath * still exists on disk (the /exit dialog may have removed it). */export type WorktreeStateEntry = { type: 'worktree-state' sessionId: UUID worktreeSession: PersistedWorktreeSession | null}
/** * Records content blocks whose in-context representation was replaced with a * smaller stub (the full content was persisted elsewhere). Replayed on resume * for prompt cache stability. Written once per enforcement pass that replaces * at least one block. When agentId is set, the record belongs to a subagent * sidechain (AgentTool resume reads these); when absent, it's main-thread * (/resume reads these). */export type ContentReplacementEntry = { type: 'content-replacement' sessionId: UUID agentId?: AgentId replacements: ContentReplacementRecord[]}
export type FileHistorySnapshotMessage = { type: 'file-history-snapshot' messageId: UUID snapshot: FileHistorySnapshot isSnapshotUpdate: boolean}
/** * Per-file attribution state tracking Claude's character contributions. */export type FileAttributionState = { contentHash: string // SHA-256 hash of file content claudeContribution: number // Characters written by Claude mtime: number // File modification time}
/** * Attribution snapshot message stored in session transcript. * Tracks character-level contributions by Claude for commit attribution. */export type AttributionSnapshotMessage = { type: 'attribution-snapshot' messageId: UUID surface: string // Client surface (cli, ide, web, api) fileStates: Record<string, FileAttributionState> promptCount?: number // Total prompts in session promptCountAtLastCommit?: number // Prompts at last commit permissionPromptCount?: number // Total permission prompts shown permissionPromptCountAtLastCommit?: number // Permission prompts at last commit escapeCount?: number // Total ESC presses (cancelled permission prompts) escapeCountAtLastCommit?: number // ESC presses at last commit}
export type TranscriptMessage = SerializedMessage & { parentUuid: UUID | null logicalParentUuid?: UUID | null // Preserves logical parent when parentUuid is nullified for session breaks isSidechain: boolean gitBranch?: string agentId?: string // Agent ID for sidechain transcripts to enable resuming agents teamName?: string // Team name if this is a spawned agent session agentName?: string // Agent's custom name (from /rename or swarm) agentColor?: string // Agent's color (from /rename or swarm) promptId?: string // Correlates with OTel prompt.id for user prompt messages}
export type SpeculationAcceptMessage = { type: 'speculation-accept' timestamp: string timeSavedMs: number}
/** * Persisted context-collapse commit. The archived messages themselves are * NOT persisted — they're already in the transcript as ordinary user/ * assistant messages. We only persist enough to reconstruct the splice * instruction (boundary uuids) and the summary placeholder (which is NOT * in the transcript because it's never yielded to the REPL). * * On restore, the store reconstructs CommittedCollapse with archived=[]; * projectView lazily fills the archive the first time it finds the span. * * Discriminator is obfuscated to match the gate name. sessionStorage.ts * isn't feature-gated (it's the generic transcript plumbing used by every * entry type), so a descriptive string here would leak into external builds * via the appendEntry dispatch / loadTranscriptFile parser even though * nothing in an external build ever writes or reads this entry. */export type ContextCollapseCommitEntry = { type: 'marble-origami-commit' sessionId: UUID /** 16-digit collapse ID. Max across entries reseeds the ID counter. */ collapseId: string /** The summary placeholder's uuid — registerSummary() needs it. */ summaryUuid: string /** Full <collapsed id="...">text</collapsed> string for the placeholder. */ summaryContent: string /** Plain summary text for ctx_inspect. */ summary: string /** Span boundaries — projectView finds these in the resumed Message[]. */ firstArchivedUuid: string lastArchivedUuid: string}
/** * Snapshot of the staged queue and spawn trigger state. Unlike commits * (append-only, replay-all), snapshots are last-wins — only the most * recent snapshot entry is applied on restore. Written after every * ctx-agent spawn resolves (when staged contents may have changed). * * Staged boundaries are UUIDs (session-stable), not collapse IDs (which * reset with the uuidToId bimap). Restoring a staged span issues fresh * collapse IDs for those messages on the next decorate/display, but the * span itself resolves correctly. */export type ContextCollapseSnapshotEntry = { type: 'marble-origami-snapshot' sessionId: UUID staged: Array<{ startUuid: string endUuid: string summary: string risk: number stagedAt: number }> /** Spawn trigger state — so the +interval clock picks up where it left off. */ armed: boolean lastSpawnTokens: number}
export type Entry = | TranscriptMessage | SummaryMessage | CustomTitleMessage | AiTitleMessage | LastPromptMessage | TaskSummaryMessage | TagMessage | AgentNameMessage | AgentColorMessage | AgentSettingMessage | PRLinkMessage | FileHistorySnapshotMessage | AttributionSnapshotMessage | QueueOperationMessage | SpeculationAcceptMessage | ModeEntry | WorktreeStateEntry | ContentReplacementEntry | ContextCollapseCommitEntry | ContextCollapseSnapshotEntry
export function sortLogs(logs: LogOption[]): LogOption[] { return logs.sort((a, b) => { // Sort by modified date (newest first) const modifiedDiff = b.modified.getTime() - a.modified.getTime() if (modifiedDiff !== 0) { return modifiedDiff }
// If modified dates are equal, sort by created date (newest first) return b.created.getTime() - a.created.getTime() })}