formatProjectContext function

String formatProjectContext(
  1. LoadedProjectContext context
)

Renders the context files as a system-prompt section (kimi's wrapper, reduced): each file annotated with its source path, precedence note for deeper-vs-shallower rules. A dropped file renders as a one-line tombstone naming the path on disk (issue #1761 AC1); a truncated file's From-marker carries the original/excerpt sizes and the read-the-full-file instruction follows its excerpt. Empty when nothing was discovered.

Implementation

String formatProjectContext(LoadedProjectContext context) {
  if (context.isEmpty) return '';
  final buffer = StringBuffer()
    ..writeln('<project_context>')
    ..writeln()
    ..writeln('Project-specific instructions and guidelines:')
    ..writeln();
  for (final drop in context.dropped) {
    buffer.writeln(
      '<!-- ${drop.path} exists (${_sizeLabel(drop.bytes)}) but did not '
      'fit the ${_sizeLabel(context.budgetBytes)} budget — read it with '
      'the read tool if its rules apply -->',
    );
  }
  for (final file in context.files) {
    if (file.isTruncated) {
      buffer.writeln(
        '<!-- From: ${file.path} — ${_groupDigits(file.originalBytes!)} '
        'bytes, only the first ${_groupDigits(file.excerptBytes!)} shown '
        '(${_sizeLabel(context.budgetBytes)} merged budget) -->',
      );
      buffer
        ..writeln(file.content.trim())
        ..writeln();
    } else {
      buffer
        ..writeln('<!-- From: ${file.path} -->')
        ..writeln(file.content.trim())
        ..writeln();
    }
  }
  buffer
    ..writeln('</project_context>')
    ..write(
      'When instructions in deeper files conflict with shallower ones, the '
      'deeper file takes precedence; user instructions given directly in '
      'the conversation take the highest precedence.',
    );
  return buffer.toString();
}