(
relPath: string,
content: string,
opts: { headLines?: number } = {},
)
| 123 | * model gets immediate orientation without a second call. |
| 124 | */ |
| 125 | export async function renderLargeFileMap( |
| 126 | relPath: string, |
| 127 | content: string, |
| 128 | opts: { headLines?: number } = {}, |
| 129 | ): Promise<string> { |
| 130 | const headLines = opts.headLines ?? 40; |
| 131 | const allLines = content.split('\n'); |
| 132 | const outline = await fileOutline(relPath, content); |
| 133 | |
| 134 | const head = allLines.slice(0, headLines) |
| 135 | .map((line, i) => `${String(i + 1).padStart(4, ' ')}\t${line}`) |
| 136 | .join('\n'); |
| 137 | |
| 138 | const parts: string[] = []; |
| 139 | parts.push(`[LARGE FILE — ${allLines.length} lines. Showing a structural map + the first ${Math.min(headLines, allLines.length)} lines.`); |
| 140 | parts.push(`Read a specific section with read_file offset=<startLine> limit=<n>, pass symbol="Name" to read one declaration, or grep for a term.]`); |
| 141 | parts.push(''); |
| 142 | |
| 143 | if (outline.length > 0) { |
| 144 | parts.push('OUTLINE (symbol → lines):'); |
| 145 | for (const e of outline) { |
| 146 | parts.push(` ${e.symbol} — lines ${e.startLine}-${e.endLine}`); |
| 147 | } |
| 148 | parts.push(''); |
| 149 | } |
| 150 | |
| 151 | parts.push(`HEAD (lines 1-${Math.min(headLines, allLines.length)}):`); |
| 152 | parts.push(head); |
| 153 | if (allLines.length > headLines) { |
| 154 | parts.push(`[... ${allLines.length - headLines} more lines below. Use the outline above to jump to a section.]`); |
| 155 | } |
| 156 | |
| 157 | return parts.join('\n'); |
| 158 | } |
no test coverage detected