/** * Domain/business entity types for claude-devtools. * * These types represent the application's domain model: * - Projects and sessions * - Repository and worktree grouping * - Search and pagination * - Token usage and metrics */import { type UsageMetadata } from './jsonl';// =============================================================================// Application-Specific Type Aliases// =============================================================================/** * Token usage statistics (alias for API compatibility). * Maps to UsageMetadata from the spec. */export type TokenUsage = UsageMetadata;/** * Message type classification for parsed messages. */export type MessageType = | 'user' | 'assistant' | 'system' | 'summary' | 'file-history-snapshot' | 'queue-operation';/** * Message category for chunk building. * Used to classify messages into one of four categories for independent chunk creation. */export type MessageCategory = 'user' | 'system' | 'hardNoise' | 'ai' | 'compact';// =============================================================================// Project & Session Types// =============================================================================/** * Project information derived from ~/.claude/projects/ directory. */export interface Project { /** Encoded directory name (e.g., "-Users-username-projectname") */ id: string; /** Decoded actual filesystem path */ path: string; /** Display name (last path segment) */ name: string; /** List of session IDs (JSONL filenames without extension) */ sessions: string[]; /** Unix timestamp when project directory was created */ createdAt: number; /** Unix timestamp of most recent session activity */ mostRecentSession?: number;}/** * Session metadata and summary. */export type SessionMetadataLevel = 'light' | 'deep';/** * Per-phase token breakdown for compaction-aware context consumption. */export interface PhaseTokenBreakdown { /** 1-based phase number */ phaseNumber: number; /** Tokens added during this phase */ contribution: number; /** Context window at peak (pre-compaction or final) */ peakTokens: number; /** Tokens after compaction (undefined for the last/current phase) */ postCompaction?: number;}export interface Session { /** Session UUID (JSONL filename without extension) */ id: string; /** Parent project ID */ projectId: string; /** Project filesystem path */ projectPath: string; /** Task list data from ~/.claude/todos/{id}.json if exists */ todoData?: unknown; /** Unix timestamp when session file was created */ createdAt: number; /** First user message text (for preview) */ firstMessage?: string; /** Timestamp of first user message (RFC3339) */ messageTimestamp?: string; /** Whether this session has subagents */ hasSubagents: boolean; /** Total message count in the session */ messageCount: number; /** Whether the session is ongoing (last AI response has no output yet) */ isOngoing?: boolean; /** Git branch name if available */ gitBranch?: string; /** Metadata completeness level */ metadataLevel?: SessionMetadataLevel; /** Total context consumed (compaction-aware sum of all phases) */ contextConsumption?: number; /** Number of compaction events */ compactionCount?: number; /** Per-phase token breakdown for tooltip display */ phaseBreakdown?: PhaseTokenBreakdown[];}/** * Aggregated metrics for a session or chunk. */export interface SessionMetrics { /** Duration in milliseconds */ durationMs: number; /** Total tokens (input + output) */ totalTokens: number; /** Input tokens */ inputTokens: number; /** Output tokens */ outputTokens: number; /** Cache read tokens */ cacheReadTokens: number; /** Cache creation tokens */ cacheCreationTokens: number; /** Number of messages */ messageCount: number; /** Estimated cost in USD */ costUsd?: number;}// =============================================================================// Repository & Worktree Grouping Types// =============================================================================/** * Worktree source identifies how/where the worktree was created. * Used for badge display and source-specific naming strategies. */export type WorktreeSource = | 'vibe-kanban' // /tmp/vibe-kanban/worktrees/{issue-branch}/{repo} | 'conductor' // /Users/.../conductor/workspaces/{repo}/{workspace} | 'auto-claude' // /Users/.../.auto-claude/worktrees/tasks/{task-id} | '21st' // /Users/.../.21st/worktrees/{id}/{name [bracket-id]} | 'claude-desktop' // /Users/.../.claude-worktrees/{repo}/{name} | 'ccswitch' // /Users/.../.ccswitch/worktrees/{repo}/{name} | 'git' // Standard git worktree (main repo or detached) | 'unknown'; // Non-git project or undetectable/** * Git repository identity for grouping worktrees. * Multiple projects (worktrees) can share the same RepositoryIdentity. */export interface RepositoryIdentity { /** Unique identifier - hash of remote URL or main repo path */ id: string; /** Git remote URL if available (e.g., "https://github.com/org/repo.git") */ remoteUrl?: string; /** Path to the main git directory (e.g., "/Users/username/projectname/.git") */ mainGitDir: string; /** Display name for the repository (e.g., "projectname") */ name: string;}/** * A worktree represents a single working directory of a git repository. * In the grouped view, projects become worktrees under a RepositoryGroup. */export interface Worktree { /** Encoded directory name (same as Project.id) */ id: string; /** Decoded actual filesystem path */ path: string; /** Display name (worktree-specific, e.g., branch name or "main") */ name: string; /** Git branch name if available */ gitBranch?: string; /** Whether this is the main worktree (not a detached worktree) */ isMainWorktree: boolean; /** Worktree source for badge display (vibe-kanban, conductor, etc.) */ source: WorktreeSource; /** List of session IDs */ sessions: string[]; /** Unix timestamp when first session was created */ createdAt: number; /** Unix timestamp of most recent session activity */ mostRecentSession?: number;}/** * A repository group contains all worktrees of a single git repository. * This is the top-level entity when worktree grouping is enabled. * Non-git projects are represented as single-worktree RepositoryGroups. */export interface RepositoryGroup { /** Unique identifier from RepositoryIdentity.id (or project.id for non-git) */ id: string; /** Repository identity information (null for non-git projects) */ identity: RepositoryIdentity | null; /** All worktrees of this repository */ worktrees: Worktree[]; /** Display name (derived from repo name) */ name: string; /** Unix timestamp of most recent session across all worktrees */ mostRecentSession?: number; /** Total session count across all worktrees */ totalSessions: number;}// =============================================================================// Search Types// =============================================================================/** * A single search result from searching sessions. */export interface SearchResult { /** Session ID where match was found */ sessionId: string; /** Project ID */ projectId: string; /** Session title/first message */ sessionTitle: string; /** The matched text (trimmed) */ matchedText: string; /** Context around the match */ context: string; /** Message type (user/assistant) */ messageType: 'user' | 'assistant'; /** Timestamp of the message */ timestamp: number; /** Stable chat group ID used by in-session navigation (e.g., "user-..." or "ai-...") */ groupId?: string; /** Searchable item type used for in-session matching */ itemType?: 'user' | 'ai'; /** Match index within the item's searchable text (0-based) */ matchIndexInItem?: number; /** Character offset of the match within the searchable text */ matchStartOffset?: number; /** Source message UUID for diagnostics/fallback mapping */ messageUuid?: string;}/** * Result of a search operation. */export interface SearchSessionsResult { /** Search results */ results: SearchResult[]; /** Total matches found */ totalMatches: number; /** Sessions searched */ sessionsSearched: number; /** Search query used */ query: string; /** True when fast mode intentionally returns only a recent subset */ isPartial?: boolean;}// =============================================================================// Pagination Types// =============================================================================/** * Cursor for session pagination. * Uses timestamp + sessionId as a composite cursor for stable pagination. */export interface SessionCursor { /** Unix timestamp (birthtimeMs) of the session file */ timestamp: number; /** Session ID for tie-breaking when timestamps are equal */ sessionId: string;}/** * Result of paginated session listing. */export interface PaginatedSessionsResult { /** Sessions for this page */ sessions: Session[]; /** Cursor for next page (null if no more pages) */ nextCursor: string | null; /** Whether there are more sessions to load */ hasMore: boolean; /** Total count of sessions (for display purposes) */ totalCount: number;}/** * Options controlling paginated session listing behavior. */export interface SessionsPaginationOptions { /** * Whether to compute an accurate totalCount by scanning all sessions. * Disable for faster background refreshes. * @default true */ includeTotalCount?: boolean; /** * Whether to pre-filter all session files before paging. * Disable for faster top-of-list refreshes. * @default true */ prefilterAll?: boolean; /** * Metadata depth to return for listed sessions. * - light: filesystem metadata only (fast) * - deep: includes parsed session content summary fields (slower) * @default 'deep' */ metadataLevel?: SessionMetadataLevel;}/** * Options for targeted session fetches by session ID. */export interface SessionsByIdsOptions { /** * Metadata depth to return for each session. * - light: fast preview fields suitable for list/sidebar * - deep: full summary metadata (slower) * @default provider-specific default (SSH=light, local=deep) */ metadataLevel?: SessionMetadataLevel;}
/**
* Domain/business entity types for claude-devtools.
*
* These types represent the application's domain model:
* - Projects and sessions
* - Repository and worktree grouping
* - Search and pagination
* - Token usage and metrics
*/
import { type UsageMetadata } from './jsonl';
// =============================================================================
// Application-Specific Type Aliases
// =============================================================================
/**
* Token usage statistics (alias for API compatibility).
* Maps to UsageMetadata from the spec.
*/
export type TokenUsage = UsageMetadata;
/**
* Message type classification for parsed messages.
*/
export type MessageType =
| 'user'
| 'assistant'
| 'system'
| 'summary'
| 'file-history-snapshot'
| 'queue-operation';
/**
* Message category for chunk building.
* Used to classify messages into one of four categories for independent chunk creation.
*/
export type MessageCategory = 'user' | 'system' | 'hardNoise' | 'ai' | 'compact';
// =============================================================================
// Project & Session Types
// =============================================================================
/**
* Project information derived from ~/.claude/projects/ directory.
*/
export interface Project {
/** Encoded directory name (e.g., "-Users-username-projectname") */
id: string;
/** Decoded actual filesystem path */
path: string;
/** Display name (last path segment) */
name: string;
/** List of session IDs (JSONL filenames without extension) */
sessions: string[];
/** Unix timestamp when project directory was created */
createdAt: number;
/** Unix timestamp of most recent session activity */
mostRecentSession?: number;
}
/**
* Session metadata and summary.
*/
export type SessionMetadataLevel = 'light' | 'deep';
/**
* Per-phase token breakdown for compaction-aware context consumption.
*/
export interface PhaseTokenBreakdown {
/** 1-based phase number */
phaseNumber: number;
/** Tokens added during this phase */
contribution: number;
/** Context window at peak (pre-compaction or final) */
peakTokens: number;
/** Tokens after compaction (undefined for the last/current phase) */
postCompaction?: number;
}
export interface Session {
/** Session UUID (JSONL filename without extension) */
id: string;
/** Parent project ID */
projectId: string;
/** Project filesystem path */
projectPath: string;
/** Task list data from ~/.claude/todos/{id}.json if exists */
todoData?: unknown;
/** Unix timestamp when session file was created */
createdAt: number;
/** First user message text (for preview) */
firstMessage?: string;
/** Timestamp of first user message (RFC3339) */
messageTimestamp?: string;
/** Whether this session has subagents */
hasSubagents: boolean;
/** Total message count in the session */
messageCount: number;
/** Whether the session is ongoing (last AI response has no output yet) */
isOngoing?: boolean;
/** Git branch name if available */
gitBranch?: string;
/** Metadata completeness level */
metadataLevel?: SessionMetadataLevel;
/** Total context consumed (compaction-aware sum of all phases) */
contextConsumption?: number;
/** Number of compaction events */
compactionCount?: number;
/** Per-phase token breakdown for tooltip display */
phaseBreakdown?: PhaseTokenBreakdown[];
}
/**
* Aggregated metrics for a session or chunk.
*/
export interface SessionMetrics {
/** Duration in milliseconds */
durationMs: number;
/** Total tokens (input + output) */
totalTokens: number;
/** Input tokens */
inputTokens: number;
/** Output tokens */
outputTokens: number;
/** Cache read tokens */
cacheReadTokens: number;
/** Cache creation tokens */
cacheCreationTokens: number;
/** Number of messages */
messageCount: number;
/** Estimated cost in USD */
costUsd?: number;
}
// =============================================================================
// Repository & Worktree Grouping Types
// =============================================================================
/**
* Worktree source identifies how/where the worktree was created.
* Used for badge display and source-specific naming strategies.
*/
export type WorktreeSource =
| 'vibe-kanban' // /tmp/vibe-kanban/worktrees/{issue-branch}/{repo}
| 'conductor' // /Users/.../conductor/workspaces/{repo}/{workspace}
| 'auto-claude' // /Users/.../.auto-claude/worktrees/tasks/{task-id}
| '21st' // /Users/.../.21st/worktrees/{id}/{name [bracket-id]}
| 'claude-desktop' // /Users/.../.claude-worktrees/{repo}/{name}
| 'ccswitch' // /Users/.../.ccswitch/worktrees/{repo}/{name}
| 'git' // Standard git worktree (main repo or detached)
| 'unknown'; // Non-git project or undetectable
/**
* Git repository identity for grouping worktrees.
* Multiple projects (worktrees) can share the same RepositoryIdentity.
*/
export interface RepositoryIdentity {
/** Unique identifier - hash of remote URL or main repo path */
id: string;
/** Git remote URL if available (e.g., "https://github.com/org/repo.git") */
remoteUrl?: string;
/** Path to the main git directory (e.g., "/Users/username/projectname/.git") */
mainGitDir: string;
/** Display name for the repository (e.g., "projectname") */
name: string;
}
/**
* A worktree represents a single working directory of a git repository.
* In the grouped view, projects become worktrees under a RepositoryGroup.
*/
export interface Worktree {
/** Encoded directory name (same as Project.id) */
id: string;
/** Decoded actual filesystem path */
path: string;
/** Display name (worktree-specific, e.g., branch name or "main") */
name: string;
/** Git branch name if available */
gitBranch?: string;
/** Whether this is the main worktree (not a detached worktree) */
isMainWorktree: boolean;
/** Worktree source for badge display (vibe-kanban, conductor, etc.) */
source: WorktreeSource;
/** List of session IDs */
sessions: string[];
/** Unix timestamp when first session was created */
createdAt: number;
/** Unix timestamp of most recent session activity */
mostRecentSession?: number;
}
/**
* A repository group contains all worktrees of a single git repository.
* This is the top-level entity when worktree grouping is enabled.
* Non-git projects are represented as single-worktree RepositoryGroups.
*/
export interface RepositoryGroup {
/** Unique identifier from RepositoryIdentity.id (or project.id for non-git) */
id: string;
/** Repository identity information (null for non-git projects) */
identity: RepositoryIdentity | null;
/** All worktrees of this repository */
worktrees: Worktree[];
/** Display name (derived from repo name) */
name: string;
/** Unix timestamp of most recent session across all worktrees */
mostRecentSession?: number;
/** Total session count across all worktrees */
totalSessions: number;
}
// =============================================================================
// Search Types
// =============================================================================
/**
* A single search result from searching sessions.
*/
export interface SearchResult {
/** Session ID where match was found */
sessionId: string;
/** Project ID */
projectId: string;
/** Session title/first message */
sessionTitle: string;
/** The matched text (trimmed) */
matchedText: string;
/** Context around the match */
context: string;
/** Message type (user/assistant) */
messageType: 'user' | 'assistant';
/** Timestamp of the message */
timestamp: number;
/** Stable chat group ID used by in-session navigation (e.g., "user-..." or "ai-...") */
groupId?: string;
/** Searchable item type used for in-session matching */
itemType?: 'user' | 'ai';
/** Match index within the item's searchable text (0-based) */
matchIndexInItem?: number;
/** Character offset of the match within the searchable text */
matchStartOffset?: number;
/** Source message UUID for diagnostics/fallback mapping */
messageUuid?: string;
}
/**
* Result of a search operation.
*/
export interface SearchSessionsResult {
/** Search results */
results: SearchResult[];
/** Total matches found */
totalMatches: number;
/** Sessions searched */
sessionsSearched: number;
/** Search query used */
query: string;
/** True when fast mode intentionally returns only a recent subset */
isPartial?: boolean;
}
// =============================================================================
// Pagination Types
// =============================================================================
/**
* Cursor for session pagination.
* Uses timestamp + sessionId as a composite cursor for stable pagination.
*/
export interface SessionCursor {
/** Unix timestamp (birthtimeMs) of the session file */
timestamp: number;
/** Session ID for tie-breaking when timestamps are equal */
sessionId: string;
}
/**
* Result of paginated session listing.
*/
export interface PaginatedSessionsResult {
/** Sessions for this page */
sessions: Session[];
/** Cursor for next page (null if no more pages) */
nextCursor: string | null;
/** Whether there are more sessions to load */
hasMore: boolean;
/** Total count of sessions (for display purposes) */
totalCount: number;
}
/**
* Options controlling paginated session listing behavior.
*/
export interface SessionsPaginationOptions {
/**
* Whether to compute an accurate totalCount by scanning all sessions.
* Disable for faster background refreshes.
* @default true
*/
includeTotalCount?: boolean;
/**
* Whether to pre-filter all session files before paging.
* Disable for faster top-of-list refreshes.
* @default true
*/
prefilterAll?: boolean;
/**
* Metadata depth to return for listed sessions.
* - light: filesystem metadata only (fast)
* - deep: includes parsed session content summary fields (slower)
* @default 'deep'
*/
metadataLevel?: SessionMetadataLevel;
}
/**
* Options for targeted session fetches by session ID.
*/
export interface SessionsByIdsOptions {
/**
* Metadata depth to return for each session.
* - light: fast preview fields suitable for list/sidebar
* - deep: full summary metadata (slower)
* @default provider-specific default (SSH=light, local=deep)
*/
metadataLevel?: SessionMetadataLevel;
}