analyzeContextUsage method

Future<ContextData> analyzeContextUsage({
  1. required List<Map<String, dynamic>> messages,
  2. required String model,
  3. required int systemPromptTokens,
  4. required int neomageMdTokens,
  5. required int builtInToolTokens,
  6. required int mcpToolTokens,
  7. required int agentTokens,
  8. required int slashCommandTokens,
  9. required int skillFrontmatterTokens,
  10. required int messageTokens,
  11. required int deferredToolTokens,
  12. required int deferredBuiltinTokens,
  13. required List<MemoryFile> memoryFileDetails,
  14. required List<McpTool> mcpToolDetails,
  15. required List<AgentInfo> agentDetails,
  16. List<DeferredBuiltinTool>? deferredBuiltinDetails,
  17. List<SystemToolDetail>? systemToolDetails,
  18. List<SystemPromptSectionDetail>? systemPromptSections,
  19. SlashCommandInfo? commandInfo,
  20. SkillInfo? skillInfo,
  21. MessageBreakdown? messageBreakdownDetail,
  22. int? terminalWidth,
})

Analyzes context window usage for display.

Implementation

Future<ContextData> analyzeContextUsage({
  required List<Map<String, dynamic>> messages,
  required String model,
  required int systemPromptTokens,
  required int neomageMdTokens,
  required int builtInToolTokens,
  required int mcpToolTokens,
  required int agentTokens,
  required int slashCommandTokens,
  required int skillFrontmatterTokens,
  required int messageTokens,
  required int deferredToolTokens,
  required int deferredBuiltinTokens,
  required List<MemoryFile> memoryFileDetails,
  required List<McpTool> mcpToolDetails,
  required List<AgentInfo> agentDetails,
  List<DeferredBuiltinTool>? deferredBuiltinDetails,
  List<SystemToolDetail>? systemToolDetails,
  List<SystemPromptSectionDetail>? systemPromptSections,
  SlashCommandInfo? commandInfo,
  SkillInfo? skillInfo,
  MessageBreakdown? messageBreakdownDetail,
  int? terminalWidth,
}) async {
  final contextWindow = _getContextWindowForModel(model);
  final isAutoCompact = _isAutoCompactEnabled();
  final autoCompactThreshold = isAutoCompact
      ? _getEffectiveContextWindowSize(model) - autocompactBufferTokens
      : null;

  // Build categories
  final cats = <ContextCategory>[];

  if (systemPromptTokens > 0) {
    cats.add(
      ContextCategory(
        name: 'System prompt',
        tokens: systemPromptTokens,
        color: 'promptBorder',
      ),
    );
  }

  final systemToolsTokens = builtInToolTokens - skillFrontmatterTokens;
  if (systemToolsTokens > 0) {
    cats.add(
      ContextCategory(
        name: 'System tools',
        tokens: systemToolsTokens,
        color: 'inactive',
      ),
    );
  }

  if (mcpToolTokens > 0) {
    cats.add(
      ContextCategory(
        name: 'MCP tools',
        tokens: mcpToolTokens,
        color: 'cyan',
      ),
    );
  }

  if (deferredToolTokens > 0) {
    cats.add(
      ContextCategory(
        name: 'MCP tools (deferred)',
        tokens: deferredToolTokens,
        color: 'inactive',
        isDeferred: true,
      ),
    );
  }

  if (deferredBuiltinTokens > 0) {
    cats.add(
      ContextCategory(
        name: 'System tools (deferred)',
        tokens: deferredBuiltinTokens,
        color: 'inactive',
        isDeferred: true,
      ),
    );
  }

  if (agentTokens > 0) {
    cats.add(
      ContextCategory(
        name: 'Custom agents',
        tokens: agentTokens,
        color: 'permission',
      ),
    );
  }

  if (neomageMdTokens > 0) {
    cats.add(
      ContextCategory(
        name: 'Memory files',
        tokens: neomageMdTokens,
        color: 'neomage',
      ),
    );
  }

  if (skillFrontmatterTokens > 0) {
    cats.add(
      ContextCategory(
        name: 'Skills',
        tokens: skillFrontmatterTokens,
        color: 'warning',
      ),
    );
  }

  if (messageTokens > 0) {
    cats.add(
      ContextCategory(
        name: 'Messages',
        tokens: messageTokens,
        color: 'purple',
      ),
    );
  }

  // Calculate actual content usage
  final actualUsage = cats.fold<int>(
    0,
    (sum, cat) => sum + (cat.isDeferred ? 0 : cat.tokens),
  );

  // Reserved space
  int reservedTokens = 0;
  if (isAutoCompact && autoCompactThreshold != null) {
    reservedTokens = contextWindow - autoCompactThreshold;
    cats.add(
      ContextCategory(
        name: _reservedCategoryName,
        tokens: reservedTokens,
        color: 'inactive',
      ),
    );
  } else if (!isAutoCompact) {
    reservedTokens = manualCompactBufferTokens;
    cats.add(
      ContextCategory(
        name: _manualCompactBufferName,
        tokens: reservedTokens,
        color: 'inactive',
      ),
    );
  }

  // Free space
  final freeTokens = max(0, contextWindow - actualUsage - reservedTokens);
  cats.add(
    ContextCategory(
      name: 'Free space',
      tokens: freeTokens,
      color: 'promptBorder',
    ),
  );

  final totalIncludingReserved = actualUsage;

  // API usage
  final apiUsage = _getCurrentUsage(messages);
  final totalFromAPI = apiUsage != null
      ? apiUsage.inputTokens +
            apiUsage.cacheCreationInputTokens +
            apiUsage.cacheReadInputTokens
      : null;

  final finalTotalTokens = totalFromAPI ?? totalIncludingReserved;

  // Build grid
  final gridRows = buildGrid(
    categories: cats,
    contextWindow: contextWindow,
    terminalWidth: terminalWidth,
  );

  final result = ContextData(
    categories: cats,
    totalTokens: finalTotalTokens,
    maxTokens: contextWindow,
    rawMaxTokens: contextWindow,
    percentage: ((finalTotalTokens / contextWindow) * 100).round(),
    gridRows: gridRows,
    model: model,
    memoryFiles: memoryFileDetails,
    mcpTools: mcpToolDetails,
    deferredBuiltinTools: deferredBuiltinDetails,
    systemTools: systemToolDetails,
    systemPromptSections: systemPromptSections,
    agents: agentDetails,
    slashCommands: commandInfo,
    skills: skillInfo,
    autoCompactThreshold: autoCompactThreshold,
    isAutoCompactEnabled: isAutoCompact,
    messageBreakdown: messageBreakdownDetail,
    apiUsage: apiUsage,
  );

  latestAnalysis.value = result;
  return result;
}