kestrel.markets
Version:
A typed, token-efficient language + runtime for agentic trading: agents author bounded plans, the runtime fires them at the tick. CLI + typed library + MCP server.
42 lines (37 loc) • 1.84 kB
text/typescript
/**
* # cli/render/frame — the human wrapper over the agent Frame ASCII (Kestrel CLI v1 §5)
*
* The Frame ASCII from `src/frame/render.ts` IS the canonical, token-efficient **agent** screen —
* it is emitted verbatim in `text`/agent/piped mode. This module's only job is the `human` branch:
* apply **non-destructive** ANSI color to the already-rendered string when `ctx.color` is set. It
* MUST NOT re-layout, re-wrap, or invent values — the renderer already invents nothing (ADR-0008);
* the human branch only colorizes. If not `ctx.color`, human === text output.
*/
import type { OutputCtx } from "../context.ts";
const RESET = "[0m";
const BOLD = "[1m";
const DIM = "[2m";
const GREEN = "[32m";
const RED = "[31m";
/**
* Colorize the Frame ASCII line-by-line without changing any layout or value:
* - the `KESTREL · …` header line → bold
* - lines that are only box/separator glyphs (`─┈·|` and spaces) → dim
* - a `—` unknown token stays as-is (already meaningful)
* Signed dollar/number fields are left untouched in v1 (coloring them safely requires field
* offsets the ASCII does not expose; over-eager regex coloring risks mangling the aligned tape).
* The result is byte-identical to the input except for injected ANSI escapes on whole lines.
*/
export function colorizeFrame(ascii: string, ctx: OutputCtx): string {
if (!(ctx.mode === "human" && ctx.color)) return ascii;
return ascii
.split("\n")
.map((line) => {
if (line.startsWith("KESTREL")) return `${BOLD}${line}${RESET}`;
if (line.length > 0 && /^[\s─┈·|+]+$/.test(line)) return `${DIM}${line}${RESET}`;
return line;
})
.join("\n");
}
/** Exposed for callers that want the raw color codes (kept internal to v1). */
export const FRAME_ANSI = { RESET, BOLD, DIM, GREEN, RED } as const;