""" Type definitions for Claude Code Analytics API. """ from dataclasses import dataclass @dataclass class TokenMetrics: """Represents token usage per model.""" input: int output: int cache_read: int cache_creation: int @dataclass class EstimatedCost: """Represents cost estimation in cents USD.""" currency: str amount: int # in cents (e.g., 2908 = $29.08) @dataclass class ModelBreakdown: """Represents per-model usage breakdown for a user/actor.""" model: str tokens: TokenMetrics estimated_cost: EstimatedCost @dataclass class LinesOfCode: """Represents added and removed lines.""" added: int removed: int @dataclass class CoreMetrics: """High-level usage stats for this actor/day.""" num_sessions: int lines_of_code: LinesOfCode commits_by_claude_code: int pull_requests_by_claude_code: int @dataclass class ToolActionStats: """Tracks accepted/rejected actions per tool type.""" accepted: int rejected: int @dataclass class ToolActions: """Tracks all edit/write tool usage types.""" edit_tool: ToolActionStats multi_edit_tool: ToolActionStats write_tool: ToolActionStats notebook_edit_tool: ToolActionStats @dataclass class ActorInfo: """Identifies the actor (user or API).""" type: str # e.g., "user_actor" or "api_actor" email_address: str | None = None api_key_name: str | None = None @dataclass class ClaudeCodeUsageRecord: """Top-level record for each JSON entry (per actor per day).""" date: str # ISO8601 string (UTC) actor: ActorInfo organization_id: str terminal_type: str | None customer_type: str | None subscription_type: str | None core_metrics: CoreMetrics tool_actions: ToolActions model_breakdown: list[ModelBreakdown] @dataclass class ClaudeCodeUsageResponse: """Wrapper for full API response.""" data: list[ClaudeCodeUsageRecord] has_more: bool next_page: str | None def parse_tool_action_stats(data: dict) -> ToolActionStats: """Parse tool action stats from dict.""" return ToolActionStats(accepted=data.get('accepted', 0), rejected=data.get('rejected', 0)) def parse_tool_actions(data: dict) -> ToolActions: """Parse tool actions from dict.""" return ToolActions( edit_tool=parse_tool_action_stats(data.get('edit_tool', {})), multi_edit_tool=parse_tool_action_stats(data.get('multi_edit_tool', {})), write_tool=parse_tool_action_stats(data.get('write_tool', {})), notebook_edit_tool=parse_tool_action_stats(data.get('notebook_edit_tool', {})), ) def parse_lines_of_code(data: dict) -> LinesOfCode: """Parse lines of code from dict.""" return LinesOfCode(added=data.get('added', 0), removed=data.get('removed', 0)) def parse_core_metrics(data: dict) -> CoreMetrics: """Parse core metrics from dict.""" return CoreMetrics( num_sessions=data.get('num_sessions', 0), lines_of_code=parse_lines_of_code(data.get('lines_of_code', {})), commits_by_claude_code=data.get('commits_by_claude_code', 0), pull_requests_by_claude_code=data.get('pull_requests_by_claude_code', 0), ) def parse_token_metrics(data: dict) -> TokenMetrics: """Parse token metrics from dict.""" return TokenMetrics( input=data.get('input', 0), output=data.get('output', 0), cache_read=data.get('cache_read', 0), cache_creation=data.get('cache_creation', 0), ) def parse_estimated_cost(data: dict) -> EstimatedCost: """Parse estimated cost from dict.""" return EstimatedCost(currency=data.get('currency', 'usd'), amount=data.get('amount', 0)) def parse_model_breakdown(data: dict) -> ModelBreakdown: """Parse model breakdown from dict.""" return ModelBreakdown( model=data.get('model', 'unknown'), tokens=parse_token_metrics(data.get('tokens', {})), estimated_cost=parse_estimated_cost(data.get('estimated_cost', {})), ) def parse_actor_info(data: dict) -> ActorInfo: """Parse actor info from dict.""" return ActorInfo( type=data.get('type', 'unknown'), email_address=data.get('email_address'), api_key_name=data.get('api_key_name'), ) def parse_usage_record(data: dict) -> ClaudeCodeUsageRecord: """Parse a single usage record from dict.""" return ClaudeCodeUsageRecord( date=data.get('date', 'unknown'), actor=parse_actor_info(data.get('actor', {})), organization_id=data.get('organization_id', ''), terminal_type=data.get('terminal_type'), customer_type=data.get('customer_type'), subscription_type=data.get('subscription_type'), core_metrics=parse_core_metrics(data.get('core_metrics', {})), tool_actions=parse_tool_actions(data.get('tool_actions', {})), model_breakdown=[parse_model_breakdown(m) for m in data.get('model_breakdown', [])], ) def parse_usage_response(data: dict) -> ClaudeCodeUsageResponse: """Parse full API response from dict.""" return ClaudeCodeUsageResponse( data=[parse_usage_record(r) for r in data.get('data', [])], has_more=data.get('has_more', False), next_page=data.get('next_page'), )