refactor: rename formatters to AgentFormatter/HumanFormatter for semantic clarity

ColorFormatter and MarkdownFormatter names obscured their actual purpose.
The formatters serve two distinct audiences: the AI agent (compressed,
token-efficient context) and the human (rich ANSI-colored terminal output).

- MarkdownFormatter → AgentFormatter (renderMarkdown* → renderAgent*)
- ColorFormatter → HumanFormatter (renderColor* → renderHuman*)
- useColors parameter → forHuman across the pipeline
- Import aliases Color/Markdown → Human/Agent
- API query param `colors=true` unchanged (backward compatible)

Pure rename refactor — no logic or behavior changes.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Alex Newman
2026-03-21 11:50:41 -07:00
parent 9f529a30f5
commit 5b041d6b49
9 changed files with 247 additions and 305 deletions
+10 -10
View File
@@ -6,20 +6,20 @@
import type { ContextConfig, TokenEconomics, PriorMessages } from '../types.js';
import { shouldShowContextEconomics } from '../TokenCalculator.js';
import * as Markdown from '../formatters/MarkdownFormatter.js';
import * as Color from '../formatters/ColorFormatter.js';
import * as Agent from '../formatters/AgentFormatter.js';
import * as Human from '../formatters/HumanFormatter.js';
/**
* Render the previously section (prior assistant message)
*/
export function renderPreviouslySection(
priorMessages: PriorMessages,
useColors: boolean
forHuman: boolean
): string[] {
if (useColors) {
return Color.renderColorPreviouslySection(priorMessages);
if (forHuman) {
return Human.renderHumanPreviouslySection(priorMessages);
}
return Markdown.renderMarkdownPreviouslySection(priorMessages);
return Agent.renderAgentPreviouslySection(priorMessages);
}
/**
@@ -28,15 +28,15 @@ export function renderPreviouslySection(
export function renderFooter(
economics: TokenEconomics,
config: ContextConfig,
useColors: boolean
forHuman: boolean
): string[] {
// Only show footer if we have savings to display
if (!shouldShowContextEconomics(config) || economics.totalDiscoveryTokens <= 0 || economics.savings <= 0) {
return [];
}
if (useColors) {
return Color.renderColorFooter(economics.totalDiscoveryTokens, economics.totalReadTokens);
if (forHuman) {
return Human.renderHumanFooter(economics.totalDiscoveryTokens, economics.totalReadTokens);
}
return Markdown.renderMarkdownFooter(economics.totalDiscoveryTokens, economics.totalReadTokens);
return Agent.renderAgentFooter(economics.totalDiscoveryTokens, economics.totalReadTokens);
}
+18 -18
View File
@@ -6,8 +6,8 @@
import type { ContextConfig, TokenEconomics } from '../types.js';
import { shouldShowContextEconomics } from '../TokenCalculator.js';
import * as Markdown from '../formatters/MarkdownFormatter.js';
import * as Color from '../formatters/ColorFormatter.js';
import * as Agent from '../formatters/AgentFormatter.js';
import * as Human from '../formatters/HumanFormatter.js';
/**
* Render the complete header section
@@ -16,44 +16,44 @@ export function renderHeader(
project: string,
economics: TokenEconomics,
config: ContextConfig,
useColors: boolean
forHuman: boolean
): string[] {
const output: string[] = [];
// Main header
if (useColors) {
output.push(...Color.renderColorHeader(project));
if (forHuman) {
output.push(...Human.renderHumanHeader(project));
} else {
output.push(...Markdown.renderMarkdownHeader(project));
output.push(...Agent.renderAgentHeader(project));
}
// Legend
if (useColors) {
output.push(...Color.renderColorLegend());
if (forHuman) {
output.push(...Human.renderHumanLegend());
} else {
output.push(...Markdown.renderMarkdownLegend());
output.push(...Agent.renderAgentLegend());
}
// Column key
if (useColors) {
output.push(...Color.renderColorColumnKey());
if (forHuman) {
output.push(...Human.renderHumanColumnKey());
} else {
output.push(...Markdown.renderMarkdownColumnKey());
output.push(...Agent.renderAgentColumnKey());
}
// Context index instructions
if (useColors) {
output.push(...Color.renderColorContextIndex());
if (forHuman) {
output.push(...Human.renderHumanContextIndex());
} else {
output.push(...Markdown.renderMarkdownContextIndex());
output.push(...Agent.renderAgentContextIndex());
}
// Context economics
if (shouldShowContextEconomics(config)) {
if (useColors) {
output.push(...Color.renderColorContextEconomics(economics, config));
if (forHuman) {
output.push(...Human.renderHumanContextEconomics(economics, config));
} else {
output.push(...Markdown.renderMarkdownContextEconomics(economics, config));
output.push(...Agent.renderAgentContextEconomics(economics, config));
}
}
@@ -6,8 +6,8 @@
import type { ContextConfig, Observation, SessionSummary } from '../types.js';
import { colors } from '../types.js';
import * as Markdown from '../formatters/MarkdownFormatter.js';
import * as Color from '../formatters/ColorFormatter.js';
import * as Agent from '../formatters/AgentFormatter.js';
import * as Human from '../formatters/HumanFormatter.js';
/**
* Check if summary should be displayed
@@ -45,20 +45,20 @@ export function shouldShowSummary(
*/
export function renderSummaryFields(
summary: SessionSummary,
useColors: boolean
forHuman: boolean
): string[] {
const output: string[] = [];
if (useColors) {
output.push(...Color.renderColorSummaryField('Investigated', summary.investigated, colors.blue));
output.push(...Color.renderColorSummaryField('Learned', summary.learned, colors.yellow));
output.push(...Color.renderColorSummaryField('Completed', summary.completed, colors.green));
output.push(...Color.renderColorSummaryField('Next Steps', summary.next_steps, colors.magenta));
if (forHuman) {
output.push(...Human.renderHumanSummaryField('Investigated', summary.investigated, colors.blue));
output.push(...Human.renderHumanSummaryField('Learned', summary.learned, colors.yellow));
output.push(...Human.renderHumanSummaryField('Completed', summary.completed, colors.green));
output.push(...Human.renderHumanSummaryField('Next Steps', summary.next_steps, colors.magenta));
} else {
output.push(...Markdown.renderMarkdownSummaryField('Investigated', summary.investigated));
output.push(...Markdown.renderMarkdownSummaryField('Learned', summary.learned));
output.push(...Markdown.renderMarkdownSummaryField('Completed', summary.completed));
output.push(...Markdown.renderMarkdownSummaryField('Next Steps', summary.next_steps));
output.push(...Agent.renderAgentSummaryField('Investigated', summary.investigated));
output.push(...Agent.renderAgentSummaryField('Learned', summary.learned));
output.push(...Agent.renderAgentSummaryField('Completed', summary.completed));
output.push(...Agent.renderAgentSummaryField('Next Steps', summary.next_steps));
}
return output;
@@ -1,8 +1,8 @@
/**
* TimelineRenderer - Renders the chronological timeline of observations and summaries
*
* Handles day grouping and rendering. In markdown (LLM) mode, uses flat compact lines.
* In color (terminal) mode, uses file grouping with visual formatting.
* Handles day grouping and rendering. In agent (LLM) mode, uses flat compact lines.
* In human (terminal) mode, uses file grouping with visual formatting.
*/
import type {
@@ -12,8 +12,8 @@ import type {
SummaryTimelineItem,
} from '../types.js';
import { formatTime, formatDate, formatDateTime, extractFirstFile, parseJsonArray } from '../../../shared/timeline-formatting.js';
import * as Markdown from '../formatters/MarkdownFormatter.js';
import * as Color from '../formatters/ColorFormatter.js';
import * as Agent from '../formatters/AgentFormatter.js';
import * as Human from '../formatters/HumanFormatter.js';
/**
* Group timeline items by day
@@ -51,9 +51,9 @@ function getDetailField(obs: Observation, config: ContextConfig): string | null
}
/**
* Render a single day's timeline items (markdown/LLM mode - flat compact lines)
* Render a single day's timeline items (agent/LLM mode - flat compact lines)
*/
function renderDayTimelineMarkdown(
function renderDayTimelineAgent(
day: string,
dayItems: TimelineItem[],
fullObservationIds: Set<number>,
@@ -61,17 +61,15 @@ function renderDayTimelineMarkdown(
): string[] {
const output: string[] = [];
output.push(...Markdown.renderMarkdownDayHeader(day));
output.push(...Agent.renderAgentDayHeader(day));
let lastTime = '';
for (const item of dayItems) {
if (item.type === 'summary') {
lastTime = '';
const summary = item.data as SummaryTimelineItem;
const formattedTime = formatDateTime(summary.displayTime);
output.push(...Markdown.renderMarkdownSummaryItem(summary, formattedTime));
output.push(...Agent.renderAgentSummaryItem(summary, formattedTime));
} else {
const obs = item.data as Observation;
const time = formatTime(obs.created_at);
@@ -83,9 +81,9 @@ function renderDayTimelineMarkdown(
if (shouldShowFull) {
const detailField = getDetailField(obs, config);
output.push(...Markdown.renderMarkdownFullObservation(obs, timeDisplay, detailField, config));
output.push(...Agent.renderAgentFullObservation(obs, timeDisplay, detailField, config));
} else {
output.push(Markdown.renderMarkdownTableRow(obs, timeDisplay, config));
output.push(Agent.renderAgentTableRow(obs, timeDisplay, config));
}
}
}
@@ -94,9 +92,9 @@ function renderDayTimelineMarkdown(
}
/**
* Render a single day's timeline items (color/terminal mode - file grouped with tables)
* Render a single day's timeline items (human/terminal mode - file grouped with tables)
*/
function renderDayTimelineColor(
function renderDayTimelineHuman(
day: string,
dayItems: TimelineItem[],
fullObservationIds: Set<number>,
@@ -105,7 +103,7 @@ function renderDayTimelineColor(
): string[] {
const output: string[] = [];
output.push(...Color.renderColorDayHeader(day));
output.push(...Human.renderHumanDayHeader(day));
let currentFile: string | null = null;
let lastTime = '';
@@ -117,7 +115,7 @@ function renderDayTimelineColor(
const summary = item.data as SummaryTimelineItem;
const formattedTime = formatDateTime(summary.displayTime);
output.push(...Color.renderColorSummaryItem(summary, formattedTime));
output.push(...Human.renderHumanSummaryItem(summary, formattedTime));
} else {
const obs = item.data as Observation;
const file = extractFirstFile(obs.files_modified, cwd, obs.files_read);
@@ -129,15 +127,15 @@ function renderDayTimelineColor(
// Check if we need a new file section
if (file !== currentFile) {
output.push(...Color.renderColorFileHeader(file));
output.push(...Human.renderHumanFileHeader(file));
currentFile = file;
}
if (shouldShowFull) {
const detailField = getDetailField(obs, config);
output.push(...Color.renderColorFullObservation(obs, time, showTime, detailField, config));
output.push(...Human.renderHumanFullObservation(obs, time, showTime, detailField, config));
} else {
output.push(Color.renderColorTableRow(obs, time, showTime, config));
output.push(Human.renderHumanTableRow(obs, time, showTime, config));
}
}
}
@@ -156,12 +154,12 @@ export function renderDayTimeline(
fullObservationIds: Set<number>,
config: ContextConfig,
cwd: string,
useColors: boolean
forHuman: boolean
): string[] {
if (useColors) {
return renderDayTimelineColor(day, dayItems, fullObservationIds, config, cwd);
if (forHuman) {
return renderDayTimelineHuman(day, dayItems, fullObservationIds, config, cwd);
}
return renderDayTimelineMarkdown(day, dayItems, fullObservationIds, config);
return renderDayTimelineAgent(day, dayItems, fullObservationIds, config);
}
/**
@@ -172,13 +170,13 @@ export function renderTimeline(
fullObservationIds: Set<number>,
config: ContextConfig,
cwd: string,
useColors: boolean
forHuman: boolean
): string[] {
const output: string[] = [];
const itemsByDay = groupTimelineByDay(timeline);
for (const [day, dayItems] of itemsByDay) {
output.push(...renderDayTimeline(day, dayItems, fullObservationIds, config, cwd, useColors));
output.push(...renderDayTimeline(day, dayItems, fullObservationIds, config, cwd, forHuman));
}
return output;