spb/khaelor Public
KHAELOR — a terminal-native autonomous engineering agent powered by Anthropic.
TypeScript 82.9%
HTML 14.9%
CSS 1.1%
JavaScript 0.7%
1/**2 * KHAELOR3 * File: src/anthropic/types.ts4 * Description: Model Runtime types — ModelClient, ModelRequest, ModelEvent stream vocabulary, honest usage (ARCHITECTURE.md §7).5 *6 * Author: Simon-Pierre Boucher7 * Contact: contact@spboucher.ai8 */910// Layer 1 — this module imports `shared` only (plus @anthropic-ai/sdk).11// It therefore owns its own copies of the model-facing vocabulary; the12// session event catalog mirrors these shapes (EVENT_MODEL.md §4), and the13// agent-layer reducer maps ModelEvents onto session events:14//15// started → ModelRequestStarted16// text-delta → ModelTextDelta (ephemeral)17// thinking-delta → ModelThinkingDelta (ephemeral)18// tool-call-started → ToolCallStarted (ephemeral)19// tool-input-delta → ToolInputDelta (ephemeral)20// text-block-completed → ModelTextBlockCompleted (durable)21// thinking-block-completed → ModelThinkingBlockCompleted (durable)22// tool-call-completed → ToolRequested (durable)23// completed → ModelResponseCompleted (durable)2425// ───────────────────────── stop reason and usage ─────────────────────────2627/** Normalized stop reason (EVENT_MODEL.md §4). */28export type StopReason = "end_turn" | "tool_use" | "max_tokens" | "refusal";2930/**31 * Real API usage only — never estimated (Absolute Rule #4).32 * Field sources (Anthropic Messages API `usage` object):33 * inputTokens ← input_tokens34 * outputTokens ← output_tokens35 * cacheReadTokens ← cache_read_input_tokens36 * cacheWriteTokens ← cache_creation_input_tokens37 */38export interface ModelUsage {39 inputTokens: number;40 outputTokens: number;41 cacheReadTokens: number;42 cacheWriteTokens: number;43}4445// ───────────────────────── request shapes ─────────────────────────4647/** `{ type: "ephemeral" }` cache breakpoint marker (prompt caching). */48export interface CacheControl {49 type: "ephemeral";50}5152/**53 * One stable system-prompt tier (ADR-7): [identity/behavior] →54 * [tool guidance] → [project instructions]. Built once per session,55 * never re-rendered; cache breakpoints are placed at tier ends.56 */57export interface SystemTier {58 /** Stable label for /context stats — e.g. "identity", "project-instructions". */59 name: string;60 text: string;61}6263/** Text content block. */64export interface TextBlockParam {65 type: "text";66 text: string;67 cache_control?: CacheControl;68}6970/** Thinking block — replayed byte-exact (thinking + signature) in tool loops. */71export interface ThinkingBlockParam {72 type: "thinking";73 thinking: string;74 signature: string;75}7677/** Redacted thinking block — opaque, replayed verbatim. */78export interface RedactedThinkingBlockParam {79 type: "redacted_thinking";80 data: string;81}8283/** Assistant tool_use block. */84export interface ToolUseBlockParam {85 type: "tool_use";86 id: string;87 name: string;88 input: unknown;89 cache_control?: CacheControl;90}9192/** User tool_result block — pairs with a tool_use id. */93export interface ToolResultBlockParam {94 type: "tool_result";95 tool_use_id: string;96 content: string | TextBlockParam[];97 is_error?: boolean;98 cache_control?: CacheControl;99}100101export type ContentBlockParam =102 | TextBlockParam103 | ThinkingBlockParam104 | RedactedThinkingBlockParam105 | ToolUseBlockParam106 | ToolResultBlockParam;107108/** One message of the byte-stable LlmHistory projection (ARCHITECTURE.md §6.5). */109export interface AnthropicMessage {110 role: "user" | "assistant";111 content: ContentBlockParam[];112}113114/** Tool schema handed to the API (≤5 properties per ADR-8; enforced upstream). */115export interface ToolSchema {116 name: string;117 description: string;118 /** JSON Schema for the tool input (`input_schema` on the wire). */119 inputSchema: Record<string, unknown>;120}121122/** Extended-thinking configuration. */123export type ThinkingConfig =124 | { mode: "enabled"; budgetTokens: number }125 | { mode: "disabled" };126127/** The assembled model request (ARCHITECTURE.md §7). */128export interface ModelRequest {129 model: string;130 /** Stable tiers; cache_control breakpoints are planned by caching.ts. */131 system: SystemTier[];132 /** Byte-stable projection (§6.5) — never mutated by the client. */133 messages: AnthropicMessage[];134 tools: ToolSchema[];135 maxOutputTokens: number;136 thinking?: ThinkingConfig;137}138139// ───────────────────────── the event stream ─────────────────────────140141/**142 * Events produced by ModelClient.stream(). Errors are NOT events: the143 * async iterable throws a typed ModelError (errors.ts) which the kernel144 * classifies (ARCHITECTURE.md §4.2 / §7).145 */146export type ModelEvent =147 | { type: "started"; requestId: string }148 | { type: "text-delta"; blockIndex: number; text: string }149 | { type: "thinking-delta"; blockIndex: number; text: string }150 | { type: "tool-call-started"; blockIndex: number; toolUseId: string; toolName: string }151 | { type: "tool-input-delta"; blockIndex: number; toolUseId: string; partialJson: string }152 | { type: "text-block-completed"; blockIndex: number; text: string }153 | { type: "thinking-block-completed"; blockIndex: number; thinking: string; signature: string }154 | {155 type: "tool-call-completed";156 blockIndex: number;157 toolUseId: string;158 toolName: string;159 /** Complete parsed input, accumulated across input_json_delta chunks. */160 input: unknown;161 }162 | {163 type: "completed";164 stopReason: StopReason;165 /** REAL usage from message_start/message_delta payloads — sole source for /cost. */166 usage: ModelUsage;167 durationMs: number;168 };169170// ───────────────────────── the client boundary ─────────────────────────171172/**173 * The single model boundary (CLAUDE.md §6, ADR-10). Anthropic-only in V1;174 * this interface exists for clean architecture, not multi-provider plumbing.175 */176export interface ModelClient {177 /**178 * Stream a completion. Cancellation is AbortSignal end to end: aborting179 * `signal` aborts the underlying HTTP request and the iterable throws180 * ModelError{kind:"cancelled"}.181 */182 stream(request: ModelRequest, signal?: AbortSignal): AsyncIterable<ModelEvent>;183184 /** Best-effort budgeting aid (real API count, no retry). */185 countTokens?(request: ModelRequest): Promise<number>;186}187