329 lines · 10.3 KB · TypeScript
RawDownload
/** * 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;}