@princetheprogrammerbtw/husk 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +164 -6
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +167 -64
- package/dist/index.js +133 -1
- package/dist/index.js.map +1 -1
- package/dist/otel/index.d.ts +49 -0
- package/dist/otel/index.js +75 -0
- package/dist/otel/index.js.map +1 -0
- package/dist/tracer-y41CTrNG.d.ts +64 -0
- package/package.json +2 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/events.ts","../src/core/memory.ts","../src/core/steering.ts","../src/core/agent.ts","../src/providers/anthropic.ts","../src/providers/openai.ts","../src/providers/ollama.ts","../src/tools/registry.ts","../src/tools/builtin/read.ts","../src/tools/builtin/write.ts","../src/tools/builtin/edit.ts","../src/tools/builtin/bash.ts","../src/tools/builtin/grep.ts","../src/evals/types.ts","../src/evals/runner.ts","../src/obs/tracer.ts","../src/obs/mapper.ts","../src/index.ts"],"names":["fs","durationMs","result","splitSystemMessage","mapStopReason","extractTextFromBlocks","resolve","dirname","execAsync","promisify","exec"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Husk — typed event emitter for observability.\n *\n * Every interesting thing that happens inside the agent loop fires\n * an event. Downstream consumers (loggers, tracers, dashboards, test\n * assertions) subscribe to these events to observe behavior without\n * having to monkey-patch the agent.\n *\n * Design choice: a discriminated-union event type instead of a generic\n * EventEmitter. The compiler can verify that handlers receive the right\n * payload shape, and tooling can autocomplete event names.\n */\n\nimport type { ChatRequest, ChatResponse, Logger, Message, ToolResult } from './types.js';\nexport type { Logger };\n\n// ───────────────────────────────────────────────────────────────────\n// Event union\n// ───────────────────────────────────────────────────────────────────\n\nexport type AgentEvent =\n | { readonly type: 'agent:start'; readonly input: string; readonly sessionId: string }\n | { readonly type: 'agent:iteration'; readonly iteration: number }\n | { readonly type: 'agent:message'; readonly message: Message }\n | { readonly type: 'provider:request'; readonly request: ChatRequest }\n | {\n readonly type: 'provider:response';\n readonly response: ChatResponse;\n readonly durationMs: number;\n }\n | {\n readonly type: 'tool:call';\n readonly id: string;\n readonly name: string;\n readonly input: unknown;\n }\n | {\n readonly type: 'tool:result';\n readonly id: string;\n readonly name: string;\n readonly result: ToolResult;\n readonly durationMs: number;\n }\n | {\n readonly type: 'agent:end';\n readonly output: string;\n readonly iterations: number;\n readonly durationMs: number;\n }\n | { readonly type: 'agent:error'; readonly error: Error };\n\n/** A handler for a specific event type. */\nexport type AgentEventHandler<E extends AgentEvent = AgentEvent> = (\n event: E,\n) => void | Promise<void>;\n\n// ───────────────────────────────────────────────────────────────────\n// EventEmitter\n// ───────────────────────────────────────────────────────────────────\n\n/**\n * A minimal, type-safe event bus. We could use Node's EventEmitter,\n * but the untyped `on('event', handler)` API loses the discriminated-\n * union narrowing we get from per-type handlers.\n */\nexport class AgentEventEmitter {\n private readonly handlers: Map<AgentEvent['type'], AgentEventHandler[]> = new Map();\n private readonly wildcardHandlers: AgentEventHandler[] = [];\n\n /**\n * Subscribe to a specific event type. The handler receives only\n * events of that type with the correct payload shape.\n */\n on<E extends AgentEvent['type']>(\n type: E,\n handler: AgentEventHandler<Extract<AgentEvent, { type: E }>>,\n ): () => void {\n const list = this.handlers.get(type) ?? [];\n list.push(handler as AgentEventHandler);\n this.handlers.set(type, list);\n return () => this.off(type, handler);\n }\n\n /**\n * Subscribe to all events. Useful for loggers and tracers.\n */\n onAny(handler: AgentEventHandler): () => void {\n this.wildcardHandlers.push(handler);\n return () => {\n const idx = this.wildcardHandlers.indexOf(handler);\n if (idx >= 0) this.wildcardHandlers.splice(idx, 1);\n };\n }\n\n off<E extends AgentEvent['type']>(\n type: E,\n handler: AgentEventHandler<Extract<AgentEvent, { type: E }>>,\n ): void {\n const list = this.handlers.get(type);\n if (!list) return;\n const idx = list.indexOf(handler as AgentEventHandler);\n if (idx >= 0) list.splice(idx, 1);\n }\n\n /**\n * Emit an event. Handlers are awaited sequentially; an async handler\n * that throws is logged but doesn't stop subsequent handlers.\n */\n async emit(event: AgentEvent): Promise<void> {\n const typed = this.handlers.get(event.type) ?? [];\n for (const handler of typed) {\n try {\n await handler(event);\n } catch (err) {\n // Last-resort safety: a faulty subscriber must not crash the agent.\n // Production code should also pass a logger here; for v0.1.0 we\n // fall back to console.error.\n // eslint-disable-next-line no-console\n console.error('[husk] event handler threw:', err);\n }\n }\n for (const handler of this.wildcardHandlers) {\n try {\n await handler(event);\n } catch (err) {\n // eslint-disable-next-line no-console\n console.error('[husk] wildcard event handler threw:', err);\n }\n }\n }\n}\n\n// ───────────────────────────────────────────────────────────────────\n// Built-in event loggers\n// ───────────────────────────────────────────────────────────────────\n\n/**\n * A simple console-based logger. Useful for development and as a\n * reference implementation for custom loggers.\n */\nexport class ConsoleLogger implements Logger {\n debug(message: string, fields?: Record<string, unknown>): void {\n // eslint-disable-next-line no-console\n console.debug(this.format('debug', message, fields));\n }\n info(message: string, fields?: Record<string, unknown>): void {\n // eslint-disable-next-line no-console\n console.info(this.format('info', message, fields));\n }\n warn(message: string, fields?: Record<string, unknown>): void {\n // eslint-disable-next-line no-console\n console.warn(this.format('warn', message, fields));\n }\n error(message: string, fields?: Record<string, unknown>): void {\n // eslint-disable-next-line no-console\n console.error(this.format('error', message, fields));\n }\n\n private format(level: string, message: string, fields?: Record<string, unknown>): string {\n const ts = new Date().toISOString();\n const fieldsStr = fields && Object.keys(fields).length > 0 ? ` ${JSON.stringify(fields)}` : '';\n return `${ts} [${level}] ${message}${fieldsStr}`;\n }\n}\n\n/**\n * Convert an event stream into structured log lines via a Logger.\n * Drop-in for stdout/JSON observability.\n */\nexport function logEventsTo(logger: Logger): AgentEventHandler {\n return (event) => {\n switch (event.type) {\n case 'agent:start':\n logger.info('agent started', { input: event.input, sessionId: event.sessionId });\n break;\n case 'agent:iteration':\n logger.debug('agent iteration', { iteration: event.iteration });\n break;\n case 'agent:message':\n logger.debug('agent message', { role: event.message.role });\n break;\n case 'provider:request':\n logger.debug('provider request', { model: event.request.model });\n break;\n case 'provider:response':\n logger.info('provider response', {\n model: event.response.model,\n stopReason: event.response.stopReason,\n inputTokens: event.response.usage.inputTokens,\n outputTokens: event.response.usage.outputTokens,\n durationMs: event.durationMs,\n });\n break;\n case 'tool:call':\n logger.info('tool call', { id: event.id, name: event.name, input: event.input });\n break;\n case 'tool:result':\n logger.info('tool result', {\n id: event.id,\n name: event.name,\n isError: event.result.isError ?? false,\n durationMs: event.durationMs,\n });\n break;\n case 'agent:end':\n logger.info('agent ended', {\n iterations: event.iterations,\n durationMs: event.durationMs,\n });\n break;\n case 'agent:error':\n logger.error('agent error', { message: event.error.message });\n break;\n }\n };\n}\n","/**\n * Husk — memory store implementations.\n *\n * Two stores ship in v0.1.0:\n * - InMemoryStore: session-scoped, fast, lost on process exit\n * - FileStore: persistent across sessions, JSONL on disk\n *\n * Both implement the MemoryStore interface from ./types.js. The agent\n * loop doesn't care which one it gets — it just calls read/append/clear.\n *\n * Design choice: separate stores per file but exported from the same\n * module. Users can import what they need: `import { InMemory, File } from\n * '@princetheprogrammerbtw/husk'`.\n */\n\nimport { promises as fs } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport type { MemoryStore, Message } from './types.js';\n\n// ───────────────────────────────────────────────────────────────────\n// In-memory store\n// ───────────────────────────────────────────────────────────────────\n\n/**\n * Session-scoped memory. Messages live in a Map in process memory.\n * Fast, zero-dep, but ephemeral — perfect for single-run agents.\n */\nexport class InMemoryStore implements MemoryStore {\n private readonly sessions: Map<string, Message[]> = new Map();\n\n async read(sessionId: string): Promise<readonly Message[]> {\n return [...(this.sessions.get(sessionId) ?? [])];\n }\n\n async append(sessionId: string, message: Message): Promise<void> {\n const list = this.sessions.get(sessionId) ?? [];\n list.push(message);\n this.sessions.set(sessionId, list);\n }\n\n async clear(sessionId: string): Promise<void> {\n this.sessions.delete(sessionId);\n }\n\n async listSessions(): Promise<readonly string[]> {\n return [...this.sessions.keys()];\n }\n}\n\n// ───────────────────────────────────────────────────────────────────\n// File-backed store\n// ───────────────────────────────────────────────────────────────────\n\n/**\n * Persistent memory backed by a JSONL file. One file per session by\n * default, or a single file with a `__session` field per line if you\n * want a unified log.\n *\n * JSONL is the format because:\n * - Append-only writes are O(1) (no read-modify-write race)\n * - Corruption is line-scoped, not file-scoped\n * - It's grep-friendly for debugging\n */\nexport interface FileStoreOptions {\n /** Directory where session files live. Default: './.husk/memory'. */\n readonly path?: string;\n /** Use a single file with session markers (default: false, one file per session). */\n readonly unified?: boolean;\n}\n\nexport class FileStore implements MemoryStore {\n private readonly rootDir: string;\n private readonly unified: boolean;\n private readonly writeLocks: Map<string, Promise<void>> = new Map();\n\n constructor(options: FileStoreOptions = {}) {\n this.rootDir = options.path ?? './.husk/memory';\n this.unified = options.unified ?? false;\n }\n\n async read(sessionId: string): Promise<readonly Message[]> {\n const file = this.fileFor(sessionId);\n try {\n const text = await fs.readFile(file, 'utf-8');\n const lines = text.split('\\n').filter((line) => line.trim().length > 0);\n const messages: Message[] = [];\n for (const line of lines) {\n try {\n const parsed = JSON.parse(line) as { session?: string; message: Message };\n if (this.unified && parsed.session && parsed.session !== sessionId) continue;\n messages.push(parsed.message);\n } catch {\n // Skip malformed lines rather than failing the whole read.\n // (A real production system would log this; for v0.1.0 we\n // silently drop the line to keep the agent running.)\n }\n }\n return messages;\n } catch (err) {\n if (isNoEnt(err)) return [];\n throw err;\n }\n }\n\n async append(sessionId: string, message: Message): Promise<void> {\n // Serialize writes per session to prevent interleaved JSONL corruption.\n const previous = this.writeLocks.get(sessionId) ?? Promise.resolve();\n const next = previous.then(() => this.doAppend(sessionId, message));\n this.writeLocks.set(\n sessionId,\n next.catch(() => undefined),\n );\n return next;\n }\n\n private async doAppend(sessionId: string, message: Message): Promise<void> {\n await fs.mkdir(this.rootDir, { recursive: true });\n const file = this.fileFor(sessionId);\n const entry = this.unified\n ? JSON.stringify({ session: sessionId, message })\n : JSON.stringify({ message });\n await fs.appendFile(file, `${entry}\\n`, 'utf-8');\n }\n\n async clear(sessionId: string): Promise<void> {\n const file = this.fileFor(sessionId);\n try {\n await fs.unlink(file);\n } catch (err) {\n if (!isNoEnt(err)) throw err;\n }\n }\n\n async listSessions(): Promise<readonly string[]> {\n if (this.unified) {\n // For unified mode, scan the file and collect unique session ids.\n const file = join(this.rootDir, 'unified.jsonl');\n try {\n const text = await fs.readFile(file, 'utf-8');\n const ids = new Set<string>();\n for (const line of text.split('\\n')) {\n if (!line.trim()) continue;\n try {\n const parsed = JSON.parse(line) as { session?: string };\n if (parsed.session) ids.add(parsed.session);\n } catch {\n // skip malformed\n }\n }\n return [...ids];\n } catch (err) {\n if (isNoEnt(err)) return [];\n throw err;\n }\n }\n try {\n const entries = await fs.readdir(this.rootDir);\n return entries\n .filter((e: string) => e.endsWith('.jsonl'))\n .map((e: string) => e.replace(/\\.jsonl$/, ''));\n } catch (err) {\n if (isNoEnt(err)) return [];\n throw err;\n }\n }\n\n private fileFor(sessionId: string): string {\n if (this.unified) return join(this.rootDir, 'unified.jsonl');\n return join(this.rootDir, `${sanitize(sessionId)}.jsonl`);\n }\n}\n\nfunction isNoEnt(err: unknown): boolean {\n return Boolean(\n err && typeof err === 'object' && 'code' in err && (err as { code: unknown }).code === 'ENOENT',\n );\n}\n\nfunction sanitize(sessionId: string): string {\n return sessionId.replace(/[^a-zA-Z0-9._-]/g, '_');\n}\n\n// Re-export for the no-op case where dirname is unused in some builds.\n// (Keeps tree-shakers honest about which Node APIs we actually use.)\nvoid dirname;\n","/**\n * Husk — steering prompt builder.\n *\n * \"Steering\" is the config that shapes agent behavior: system prompt,\n * rules, and few-shot examples. The builder takes a SteeringConfig\n * and produces the artifacts the agent loop needs:\n * - buildSystemPrompt() → the string to send as the system message\n * - buildExamples() → the user/assistant message pairs to seed history\n *\n * Why a separate module? Two reasons:\n * 1. The agent loop stays focused on the loop logic, not prompt assembly.\n * 2. Steering is the most-likely-to-be-customized piece; users can\n * subclass or replace the builder without touching the agent.\n */\n\nimport type { Example, Message, SteeringConfig } from './types.js';\n\n// ───────────────────────────────────────────────────────────────────\n// System prompt builder\n// ───────────────────────────────────────────────────────────────────\n\n/**\n * Combine systemPrompt + rules into a single system prompt string.\n * Rules are numbered for explicit citation (\"see rule 3\") and\n * appended after a header so models parse them as a separate list.\n */\nexport function buildSystemPrompt(steering: SteeringConfig): string | undefined {\n const parts: string[] = [];\n\n if (steering.systemPrompt && steering.systemPrompt.trim().length > 0) {\n parts.push(steering.systemPrompt.trim());\n }\n\n if (steering.rules && steering.rules.length > 0) {\n const numbered = steering.rules.map((rule, i) => `${i + 1}. ${rule}`).join('\\n');\n parts.push(`## Rules\\n${numbered}`);\n }\n\n return parts.length > 0 ? parts.join('\\n\\n') : undefined;\n}\n\n// ───────────────────────────────────────────────────────────────────\n// Example seeder\n// ───────────────────────────────────────────────────────────────────\n\n/**\n * Convert few-shot examples into a sequence of user/assistant message\n * pairs that get prepended to the conversation history. The model\n * sees these as if they had happened earlier in the conversation,\n * which is how few-shot prompting works mechanically.\n *\n * Examples are emitted in order; the first user message of an example\n * comes right after the previous example's assistant message (or right\n * after the system prompt for the first example).\n */\nexport function buildExampleMessages(examples: readonly Example[]): readonly Message[] {\n const messages: Message[] = [];\n for (const ex of examples) {\n messages.push({ role: 'user', content: ex.user });\n messages.push({ role: 'assistant', content: ex.assistant });\n }\n return messages;\n}\n","/**\n * Husk — the agent loop.\n *\n * This is the heartbeat of the harness. The loop is small but every\n * line matters:\n *\n * 1. Compose the conversation (examples + memory + new input)\n * 2. Call the model\n * 3. Decide what to do based on stopReason\n * 4. If tool_use, execute tools and feed results back, then loop\n * 5. If end_turn, return the final output\n *\n * Design choices worth knowing:\n *\n * - Tools are executed in parallel within a single iteration. The\n * model can request multiple tools in one turn; we honor that and\n * feed all results back at once. Most agent frameworks get this wrong\n * by serializing tool calls.\n *\n * - A faulty tool does not crash the loop. The error becomes a\n * tool_result with isError=true, the model sees it, and can either\n * retry with corrected input or report back to the user. This is\n * how a real assistant would behave.\n *\n * - The loop is bounded by maxIterations. Default 25 is enough for\n * most agent tasks without running away on infinite loops.\n *\n * - The system prompt is rebuilt on every iteration from the steering\n * config. Cheap, and means hot-reloading rules works.\n */\n\nimport { AgentEventEmitter, ConsoleLogger, type Logger } from './events.js';\nimport { buildExampleMessages, buildSystemPrompt } from './steering.js';\nimport type {\n AgentConfig,\n AgentResult,\n ContentBlock,\n JSONSchema,\n Message,\n TextBlock,\n ToolDefinition,\n ToolResult,\n ToolUseBlock,\n} from './types.js';\n\n// ───────────────────────────────────────────────────────────────────\n// Defaults\n// ───────────────────────────────────────────────────────────────────\n\nconst DEFAULTS = {\n maxIterations: 25,\n temperature: 0,\n sessionId: 'default',\n} as const;\n\n// ───────────────────────────────────────────────────────────────────\n// Agent class\n// ───────────────────────────────────────────────────────────────────\n\nexport class Agent {\n readonly events: AgentEventEmitter;\n readonly provider: AgentConfig['model'];\n readonly tools: readonly ToolDefinition[];\n readonly steering: AgentConfig['steering'];\n readonly maxIterations: number;\n readonly temperature: number;\n readonly maxTokens: number | undefined;\n readonly signal: AbortSignal | undefined;\n readonly sessionId: string;\n readonly memory: AgentConfig['memory'];\n readonly logger: Logger;\n\n constructor(config: AgentConfig) {\n this.events = new AgentEventEmitter();\n this.provider = config.model;\n this.tools = config.tools ?? [];\n this.steering = config.steering;\n this.maxIterations = config.maxIterations ?? DEFAULTS.maxIterations;\n this.temperature = config.temperature ?? DEFAULTS.temperature;\n this.maxTokens = config.maxTokens;\n this.signal = config.signal;\n this.sessionId = config.sessionId ?? DEFAULTS.sessionId;\n this.memory = config.memory;\n this.logger = new ConsoleLogger();\n }\n\n /**\n * Subscribe to a specific event type. Returns an unsubscribe fn.\n */\n on: AgentEventEmitter['on'] = (type, handler) => this.events.on(type, handler);\n\n /**\n * Subscribe to all events. Returns an unsubscribe fn.\n */\n onAny: AgentEventEmitter['onAny'] = (handler) => this.events.onAny(handler);\n\n /**\n * Run the agent loop to completion on the given input.\n * Returns the final result with output text, full message history,\n * token usage, and duration.\n */\n async run(input: string): Promise<AgentResult> {\n const start = Date.now();\n\n // Default the logger to a no-op if the user replaced it via\n // subclassing or wants silence. (Future: accept logger in config.)\n this.signal?.throwIfAborted();\n\n await this.events.emit({ type: 'agent:start', input, sessionId: this.sessionId });\n\n // ── Compose initial message history ────────────────────────\n const messages: Message[] = [];\n\n if (this.steering?.examples) {\n messages.push(...buildExampleMessages(this.steering.examples));\n }\n\n if (this.memory) {\n const stored = await this.memory.read(this.sessionId);\n messages.push(...stored);\n }\n\n const userMessage: Message = { role: 'user', content: input };\n messages.push(userMessage);\n await this.recordMessage(userMessage);\n\n const system = this.steering ? buildSystemPrompt(this.steering) : undefined;\n const tools = this.tools.length > 0 ? this.tools : undefined;\n\n // ── The loop ───────────────────────────────────────────────\n let totalInputTokens = 0;\n let totalOutputTokens = 0;\n let iterations = 0;\n let finalOutput = '';\n let hitMaxIterations = false;\n\n while (iterations < this.maxIterations) {\n this.signal?.throwIfAborted();\n iterations += 1;\n await this.events.emit({ type: 'agent:iteration', iteration: iterations });\n\n // ── Call the model ───────────────────────────────────────\n const request = {\n model: this.provider.model,\n messages,\n ...(tools ? { tools } : {}),\n ...(system ? { system } : {}),\n temperature: this.temperature,\n ...(this.maxTokens ? { maxTokens: this.maxTokens } : {}),\n };\n await this.events.emit({ type: 'provider:request', request });\n\n const t0 = Date.now();\n const response = await this.provider.chat(request);\n const durationMs = Date.now() - t0;\n await this.events.emit({ type: 'provider:response', response, durationMs });\n\n totalInputTokens += response.usage.inputTokens;\n totalOutputTokens += response.usage.outputTokens;\n\n await this.recordMessage(response.message);\n\n // ── Branch on stop reason ────────────────────────────────\n switch (response.stopReason) {\n case 'end_turn':\n case 'stop_sequence': {\n finalOutput = extractText(response.message);\n break;\n }\n\n case 'max_tokens': {\n finalOutput = extractText(response.message);\n this.logger.warn('Model hit max_tokens; output may be truncated', {\n outputTokens: response.usage.outputTokens,\n });\n break;\n }\n\n case 'tool_use': {\n const toolUses = extractToolUses(response.message);\n if (toolUses.length === 0) {\n // Defensive: model said tool_use but emitted no tool_use block.\n // Treat as end of turn.\n finalOutput = extractText(response.message);\n break;\n }\n\n // Execute all requested tools in parallel.\n const results = await Promise.all(\n toolUses.map(async (tu) => {\n await this.events.emit({\n type: 'tool:call',\n id: tu.id,\n name: tu.name,\n input: tu.input,\n });\n const ts = Date.now();\n const result = await this.executeTool(tu.name, tu.input);\n const dur = Date.now() - ts;\n await this.events.emit({\n type: 'tool:result',\n id: tu.id,\n name: tu.name,\n result,\n durationMs: dur,\n });\n return { tu, result };\n }),\n );\n\n // Build a single user-role message containing all tool results.\n // This matches Anthropic's native format; the OpenAI adapter\n // converts it to multiple tool-role messages.\n const toolMessage: Message = {\n role: 'user',\n content: results.map(\n ({ tu, result }): ContentBlock => ({\n type: 'tool_result',\n toolUseId: tu.id,\n content: result.output,\n ...(result.isError ? { isError: true } : {}),\n }),\n ),\n };\n await this.recordMessage(toolMessage);\n\n // Continue the loop — model sees the tool results on next iter.\n continue;\n }\n\n case 'error': {\n throw new Error(`Provider returned error stop reason: ${extractText(response.message)}`);\n }\n }\n\n // If we got here with finalOutput set, the loop is done.\n if (finalOutput !== '' || response.stopReason !== 'tool_use') {\n break;\n }\n }\n\n if (iterations >= this.maxIterations && finalOutput === '') {\n hitMaxIterations = true;\n this.logger.warn(`Agent hit max iterations (${this.maxIterations}) without end_turn`, {\n sessionId: this.sessionId,\n });\n const last = messages[messages.length - 1];\n if (last) finalOutput = extractText(last);\n }\n\n const durationMs = Date.now() - start;\n const result: AgentResult = {\n output: finalOutput,\n messages,\n iterations,\n usage: {\n inputTokens: totalInputTokens,\n outputTokens: totalOutputTokens,\n },\n durationMs,\n };\n\n await this.events.emit({\n type: 'agent:end',\n output: finalOutput,\n iterations,\n durationMs,\n });\n if (hitMaxIterations) {\n this.logger.warn('Agent ended without clean termination', { hitMaxIterations: true });\n }\n return result;\n }\n\n // ── Internals ────────────────────────────────────────────────\n\n private async recordMessage(message: Message): Promise<void> {\n await this.events.emit({ type: 'agent:message', message });\n if (this.memory) {\n await this.memory.append(this.sessionId, message);\n }\n }\n\n private async executeTool(name: string, input: unknown): Promise<ToolResult> {\n const tool = this.tools.find((t) => t.name === name);\n if (!tool) {\n return {\n output: `Error: tool '${name}' is not registered. Available tools: ${this.tools\n .map((t) => t.name)\n .join(', ')}`,\n isError: true,\n };\n }\n\n const validation = validateInput(input, tool.inputSchema);\n if (!validation.valid) {\n return {\n output: `Error: invalid input for tool '${name}': ${validation.error}`,\n isError: true,\n };\n }\n\n try {\n return await tool.execute(input, { signal: this.signal, logger: this.logger });\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return { output: `Error executing tool '${name}': ${message}`, isError: true };\n }\n }\n}\n\n// ───────────────────────────────────────────────────────────────────\n// Helpers\n// ───────────────────────────────────────────────────────────────────\n\nfunction extractText(message: Message): string {\n if (typeof message.content === 'string') return message.content;\n return message.content\n .filter((b): b is TextBlock => b.type === 'text')\n .map((b) => b.text)\n .join('\\n');\n}\n\nfunction extractToolUses(message: Message): ToolUseBlock[] {\n if (typeof message.content === 'string') return [];\n return message.content.filter((b): b is ToolUseBlock => b.type === 'tool_use');\n}\n\n/**\n * Minimal schema validator. We check that input is an object and that\n * all required fields are present. We do NOT do deep type checking —\n * the provider's own JSON Schema validator handles that, and a bad\n * tool call from the model is a model problem, not a harness problem.\n */\nfunction validateInput(input: unknown, schema: JSONSchema): { valid: boolean; error?: string } {\n if (typeof input !== 'object' || input === null) {\n return { valid: false, error: 'Input must be an object' };\n }\n if (schema.required) {\n for (const key of schema.required) {\n if (!(key in (input as Record<string, unknown>))) {\n return { valid: false, error: `Missing required field: ${key}` };\n }\n }\n }\n return { valid: true };\n}\n","/**\n * Husk — Anthropic Claude provider adapter.\n *\n * Translates Husk's provider-agnostic ChatRequest to the Anthropic\n * Messages API format and back. This is the only file in the project\n * that knows what Anthropic's wire format looks like.\n *\n * Wire-format mapping (Husk → Anthropic):\n * - MessageRole 'assistant' + ToolUseBlock → assistant message with tool_use blocks\n * - MessageRole 'user' + ToolResultBlock[] → user message with tool_result blocks\n * - ToolDefinition (Husk JSON Schema) → Anthropic input_schema (passes through)\n * - StopReason 'end_turn' / 'tool_use' / 'max_tokens' / 'stop_sequence'\n * → returned as-is from stop_reason\n *\n * Defaults:\n * - model: 'claude-opus-4-6' (override via constructor)\n * - max_tokens: 8192 (Anthropic requires this on every request)\n * - apiKey: process.env.ANTHROPIC_API_KEY\n */\n\nimport Anthropic from '@anthropic-ai/sdk';\nimport type {\n ChatRequest,\n ChatResponse,\n ContentBlock,\n Message,\n Provider,\n StopReason,\n ToolDefinition,\n} from '../core/types.js';\n\nexport interface AnthropicProviderOptions {\n /** Override the API key. Default: process.env.ANTHROPIC_API_KEY. */\n readonly apiKey?: string;\n /** Model id. Default: 'claude-opus-4-6'. */\n readonly model?: string;\n /** Override the API base URL (for proxies, self-hosted, etc). */\n readonly baseURL?: string;\n /** Default max_tokens for requests. Anthropic requires this. Default: 8192. */\n readonly maxTokens?: number;\n}\n\nexport class AnthropicProvider implements Provider {\n readonly name = 'anthropic';\n readonly model: string;\n private readonly client: Anthropic;\n private readonly defaultMaxTokens: number;\n\n constructor(options: AnthropicProviderOptions = {}) {\n this.model = options.model ?? 'claude-opus-4-6';\n this.client = new Anthropic({\n apiKey: options.apiKey ?? process.env.ANTHROPIC_API_KEY,\n ...(options.baseURL ? { baseURL: options.baseURL } : {}),\n });\n this.defaultMaxTokens = options.maxTokens ?? 8192;\n }\n\n async chat(request: ChatRequest): Promise<ChatResponse> {\n const { system, messages } = splitSystemMessage(request.messages);\n\n const anthropicTools = request.tools?.map(toHuskToolToAnthropic);\n\n const response = await this.client.messages.create({\n model: request.model || this.model,\n ...(system ? { system } : {}),\n messages: messages.map(toAnthropicMessage),\n ...(anthropicTools && anthropicTools.length > 0 ? { tools: anthropicTools } : {}),\n max_tokens: request.maxTokens ?? this.defaultMaxTokens,\n ...(request.temperature !== undefined ? { temperature: request.temperature } : {}),\n ...(request.stopSequences ? { stop_sequences: [...request.stopSequences] } : {}),\n });\n\n return {\n message: {\n role: 'assistant',\n content: response.content.map(fromAnthropicBlock),\n },\n usage: {\n inputTokens: response.usage.input_tokens,\n outputTokens: response.usage.output_tokens,\n },\n stopReason: mapStopReason(response.stop_reason),\n model: response.model,\n };\n }\n}\n\n// ───────────────────────────────────────────────────────────────────\n// Translation helpers\n// ───────────────────────────────────────────────────────────────────\n\n/**\n * Anthropic takes the system prompt as a top-level field, not as a\n * message. Pull any system messages out and concatenate them.\n */\nfunction splitSystemMessage(messages: readonly Message[]): {\n system: string | undefined;\n messages: Message[];\n} {\n const systemParts: string[] = [];\n const rest: Message[] = [];\n for (const m of messages) {\n if (m.role === 'system') {\n const text = typeof m.content === 'string' ? m.content : extractTextFromBlocks(m.content);\n if (text) systemParts.push(text);\n } else {\n rest.push(m);\n }\n }\n return {\n system: systemParts.length > 0 ? systemParts.join('\\n\\n') : undefined,\n messages: rest,\n };\n}\n\nfunction extractTextFromBlocks(blocks: readonly ContentBlock[]): string {\n return blocks\n .filter((b): b is { type: 'text'; text: string } => b.type === 'text')\n .map((b) => b.text)\n .join('\\n');\n}\n\nfunction toHuskToolToAnthropic(tool: ToolDefinition): Anthropic.Tool {\n return {\n name: tool.name,\n description: tool.description,\n input_schema: tool.inputSchema as Anthropic.Tool.InputSchema,\n };\n}\n\nfunction toAnthropicMessage(message: Message): Anthropic.MessageParam {\n if (message.role === 'user') {\n if (typeof message.content === 'string') {\n return { role: 'user', content: message.content };\n }\n // ContentBlock[] may contain tool_result blocks (from the agent loop)\n return {\n role: 'user',\n content: message.content.map((block) => {\n if (block.type === 'text') {\n return { type: 'text' as const, text: block.text };\n }\n if (block.type === 'tool_result') {\n return {\n type: 'tool_result' as const,\n tool_use_id: block.toolUseId,\n content:\n typeof block.content === 'string'\n ? block.content\n : block.content.map((b) => {\n if (b.type === 'text') return { type: 'text' as const, text: b.text };\n // For non-text content in tool results, serialize as JSON.\n return { type: 'text' as const, text: JSON.stringify(b) };\n }),\n ...(block.isError ? { is_error: true } : {}),\n };\n }\n // Defensive: forward text blocks from assistant messages that\n // happen to land on a user role (shouldn't happen in normal flow).\n if (block.type === 'tool_use') {\n return {\n type: 'tool_use' as const,\n id: block.id,\n name: block.name,\n input: block.input as Record<string, unknown>,\n };\n }\n return { type: 'text' as const, text: '' };\n }),\n };\n }\n\n if (message.role === 'assistant') {\n if (typeof message.content === 'string') {\n return { role: 'assistant', content: message.content };\n }\n return {\n role: 'assistant',\n content: message.content.map((block) => {\n if (block.type === 'text') {\n return { type: 'text' as const, text: block.text };\n }\n if (block.type === 'tool_use') {\n return {\n type: 'tool_use' as const,\n id: block.id,\n name: block.name,\n input: block.input as Record<string, unknown>,\n };\n }\n // tool_result on an assistant message is invalid; skip defensively.\n return { type: 'text' as const, text: '' };\n }),\n };\n }\n\n // 'tool' and 'system' roles are pre-processed (system → split out,\n // tool → folded into user-role tool_result blocks). This branch is\n // unreachable in normal flow.\n return { role: 'user', content: '' };\n}\n\nfunction fromAnthropicBlock(block: Anthropic.ContentBlock): ContentBlock {\n if (block.type === 'text') {\n return { type: 'text', text: block.text };\n }\n if (block.type === 'tool_use') {\n return {\n type: 'tool_use',\n id: block.id,\n name: block.name,\n input: block.input,\n };\n }\n // Unknown block types become empty text — better than throwing,\n // and surfaces in the conversation as a blank rather than a crash.\n return { type: 'text', text: '' };\n}\n\nfunction mapStopReason(reason: string | null): StopReason {\n switch (reason) {\n case 'end_turn':\n return 'end_turn';\n case 'tool_use':\n return 'tool_use';\n case 'max_tokens':\n return 'max_tokens';\n case 'stop_sequence':\n return 'stop_sequence';\n default:\n return 'error';\n }\n}\n","/**\n * Husk — OpenAI provider adapter.\n *\n * Translates Husk's provider-agnostic ChatRequest to the OpenAI\n * Chat Completions API format and back. The shape is similar to\n * Anthropic but with two important differences:\n *\n * 1. Tool results are their own message role ('tool'), not blocks in\n * a user message. The Husk agent loop emits tool results as user-\n * role messages with tool_result content blocks; we split them\n * out into individual tool-role messages here.\n *\n * 2. Assistant tool calls are an array of tool_call objects on the\n * assistant message, not content blocks. We map Husk's tool_use\n * blocks to OpenAI's tool_calls shape.\n *\n * 3. Tools use the legacy 'functions' shape via the 'tools' field with\n * 'function' type. (OpenAI's new 'tools' format is the same; we\n * use it.)\n */\n\nimport OpenAI from 'openai';\nimport type {\n ChatRequest,\n ChatResponse,\n ContentBlock,\n Message,\n Provider,\n StopReason,\n ToolDefinition,\n} from '../core/types.js';\n\nexport interface OpenAIProviderOptions {\n /** Override the API key. Default: process.env.OPENAI_API_KEY. */\n readonly apiKey?: string;\n /** Model id. Default: 'gpt-5'. */\n readonly model?: string;\n /** Override the API base URL (for proxies, Azure OpenAI, etc). */\n readonly baseURL?: string;\n /** Organization id (for OpenAI orgs). */\n readonly organization?: string;\n}\n\nexport class OpenAIProvider implements Provider {\n readonly name = 'openai';\n readonly model: string;\n private readonly client: OpenAI;\n\n constructor(options: OpenAIProviderOptions = {}) {\n this.model = options.model ?? 'gpt-5';\n this.client = new OpenAI({\n apiKey: options.apiKey ?? process.env.OPENAI_API_KEY,\n ...(options.baseURL ? { baseURL: options.baseURL } : {}),\n ...(options.organization ? { organization: options.organization } : {}),\n });\n }\n\n async chat(request: ChatRequest): Promise<ChatResponse> {\n const { system, messages } = splitSystemMessage(request.messages);\n\n const openaiTools = request.tools?.map(toOpenAITool);\n\n const response = await this.client.chat.completions.create({\n model: request.model || this.model,\n ...(system ? { messages: [{ role: 'system' as const, content: system }] } : {}),\n messages: [\n ...(system ? [{ role: 'system' as const, content: system }] : []),\n ...messages.flatMap((m) => toOpenAIMessages(m)),\n ],\n ...(openaiTools && openaiTools.length > 0 ? { tools: openaiTools } : {}),\n ...(request.temperature !== undefined ? { temperature: request.temperature } : {}),\n ...(request.maxTokens ? { max_tokens: request.maxTokens } : {}),\n ...(request.stopSequences ? { stop: [...request.stopSequences] } : {}),\n });\n\n const choice = response.choices[0];\n if (!choice) {\n throw new Error('OpenAI returned no choices');\n }\n const assistantMessage = choice.message;\n\n return {\n message: {\n role: 'assistant',\n content: fromOpenAIAssistantMessage(assistantMessage),\n },\n usage: {\n inputTokens: response.usage?.prompt_tokens ?? 0,\n outputTokens: response.usage?.completion_tokens ?? 0,\n },\n stopReason: mapStopReason(choice.finish_reason),\n model: response.model,\n };\n }\n}\n\n// ───────────────────────────────────────────────────────────────────\n// Translation helpers\n// ───────────────────────────────────────────────────────────────────\n\nfunction splitSystemMessage(messages: readonly Message[]): {\n system: string | undefined;\n messages: Message[];\n} {\n const systemParts: string[] = [];\n const rest: Message[] = [];\n for (const m of messages) {\n if (m.role === 'system') {\n const text = typeof m.content === 'string' ? m.content : extractTextFromBlocks(m.content);\n if (text) systemParts.push(text);\n } else {\n rest.push(m);\n }\n }\n return {\n system: systemParts.length > 0 ? systemParts.join('\\n\\n') : undefined,\n messages: rest,\n };\n}\n\nfunction extractTextFromBlocks(blocks: readonly ContentBlock[]): string {\n return blocks\n .filter((b): b is { type: 'text'; text: string } => b.type === 'text')\n .map((b) => b.text)\n .join('\\n');\n}\n\nfunction toOpenAITool(tool: ToolDefinition): OpenAI.Chat.Completions.ChatCompletionTool {\n return {\n type: 'function',\n function: {\n name: tool.name,\n description: tool.description,\n parameters: tool.inputSchema as unknown as Record<string, unknown>,\n },\n };\n}\n\n/**\n * Convert a Husk Message to one or more OpenAI ChatCompletionMessageParam.\n * The fan-out happens here for tool results: a single Husk user message\n * with N tool_result blocks becomes N OpenAI tool-role messages.\n */\nfunction toOpenAIMessages(message: Message): OpenAI.Chat.Completions.ChatCompletionMessageParam[] {\n if (message.role === 'system') {\n // Pre-split, but defensive.\n const text =\n typeof message.content === 'string'\n ? message.content\n : extractTextFromBlocks(message.content);\n return [{ role: 'system', content: text }];\n }\n\n if (message.role === 'user') {\n if (typeof message.content === 'string') {\n return [{ role: 'user', content: message.content }];\n }\n // ContentBlock[] may include tool_result blocks. Fan them out.\n const toolResults = message.content.filter((b) => b.type === 'tool_result');\n const textBlocks = message.content.filter((b) => b.type === 'text');\n\n const out: OpenAI.Chat.Completions.ChatCompletionMessageParam[] = [];\n if (textBlocks.length > 0) {\n out.push({\n role: 'user',\n content: textBlocks.map((b) => (b as { text: string }).text).join('\\n'),\n });\n }\n for (const tr of toolResults) {\n if (tr.type !== 'tool_result') continue;\n out.push({\n role: 'tool',\n tool_call_id: tr.toolUseId,\n content:\n typeof tr.content === 'string'\n ? tr.content\n : tr.content.map((b) => (b.type === 'text' ? b.text : JSON.stringify(b))).join('\\n'),\n });\n }\n return out;\n }\n\n if (message.role === 'assistant') {\n if (typeof message.content === 'string') {\n return [{ role: 'assistant', content: message.content }];\n }\n const textParts: string[] = [];\n const toolCalls: OpenAI.Chat.Completions.ChatCompletionMessageToolCall[] = [];\n for (const block of message.content) {\n if (block.type === 'text') {\n textParts.push(block.text);\n } else if (block.type === 'tool_use') {\n toolCalls.push({\n id: block.id,\n type: 'function',\n function: {\n name: block.name,\n arguments: JSON.stringify(block.input ?? {}),\n },\n });\n }\n }\n const out: OpenAI.Chat.Completions.ChatCompletionAssistantMessageParam = {\n role: 'assistant',\n content: textParts.length > 0 ? textParts.join('\\n') : null,\n };\n if (toolCalls.length > 0) {\n out.tool_calls = toolCalls;\n }\n return [out];\n }\n\n // 'tool' role: pre-folded by the agent loop, but if one slips through,\n // convert it directly.\n if (message.role === 'tool') {\n const text =\n typeof message.content === 'string'\n ? message.content\n : extractTextFromBlocks(message.content);\n return [\n {\n role: 'tool',\n tool_call_id: message.toolCallId ?? message.name ?? 'unknown',\n content: text,\n },\n ];\n }\n\n return [];\n}\n\nfunction fromOpenAIAssistantMessage(\n msg: OpenAI.Chat.Completions.ChatCompletionMessage,\n): ContentBlock[] {\n const blocks: ContentBlock[] = [];\n if (msg.content) {\n blocks.push({ type: 'text', text: msg.content });\n }\n if (msg.tool_calls) {\n for (const call of msg.tool_calls) {\n if (call.type !== 'function') continue;\n let parsed: unknown = {};\n try {\n parsed = JSON.parse(call.function.arguments);\n } catch {\n parsed = { _parseError: call.function.arguments };\n }\n blocks.push({\n type: 'tool_use',\n id: call.id,\n name: call.function.name,\n input: parsed,\n });\n }\n }\n return blocks;\n}\n\nfunction mapStopReason(reason: string | null | undefined): StopReason {\n switch (reason) {\n case 'stop':\n return 'end_turn';\n case 'tool_calls':\n case 'function_call':\n return 'tool_use';\n case 'length':\n return 'max_tokens';\n case 'content_filter':\n return 'stop_sequence';\n default:\n return 'error';\n }\n}\n","/**\n * Husk — Ollama provider adapter.\n *\n * Wraps Ollama's OpenAI-compatible Chat Completions API. Because Ollama\n * exposes the exact same wire format as OpenAI, we can reuse the OpenAI\n * adapter internally — only the default model name, base URL, and the\n * provider 'name' field differ.\n *\n * Why this exists: local models (llama3.2, deepseek-r1, qwen2.5, etc.)\n * are a first-class use case. Privacy, cost, and offline-ability all\n * matter. Ollama is the dominant local-model runtime and uses the\n * OpenAI API surface, so the adapter is a thin shell.\n *\n * Defaults:\n * - model: 'llama3.2' (override via constructor)\n * - baseURL: 'http://localhost:11434/v1' (override for remote Ollama)\n * - apiKey: 'ollama' (Ollama ignores the value but the OpenAI SDK\n * requires a non-empty string)\n *\n * Usage:\n * const agent = new Agent({ model: new OllamaProvider() });\n * const result = await agent.run('Explain quantum entanglement');\n *\n * For a list of models: `ollama list` (in your terminal).\n */\n\nimport type { Provider } from '../core/types.js';\nimport { OpenAIProvider } from './openai.js';\n\nexport interface OllamaProviderOptions {\n /** Model id (run `ollama list` to see what's pulled locally). Default: 'llama3.2'. */\n readonly model?: string;\n /** Ollama server URL. Default: 'http://localhost:11434/v1'. */\n readonly baseURL?: string;\n /** API key — Ollama ignores this but the OpenAI SDK requires it. Default: 'ollama'. */\n readonly apiKey?: string;\n}\n\nconst DEFAULT_BASE_URL = 'http://localhost:11434/v1';\nconst DEFAULT_MODEL = 'llama3.2';\nconst PLACEHOLDER_API_KEY = 'ollama';\n\nexport class OllamaProvider implements Provider {\n readonly name = 'ollama';\n readonly model: string;\n private readonly inner: OpenAIProvider;\n\n constructor(options: OllamaProviderOptions = {}) {\n this.model = options.model ?? DEFAULT_MODEL;\n // Delegate to OpenAIProvider — Ollama's API is wire-compatible.\n this.inner = new OpenAIProvider({\n apiKey: options.apiKey ?? PLACEHOLDER_API_KEY,\n model: this.model,\n baseURL: options.baseURL ?? DEFAULT_BASE_URL,\n });\n }\n\n chat(request: Parameters<Provider['chat']>[0]): ReturnType<Provider['chat']> {\n // Strip the 'model' field from the request — Ollama's API expects the\n // model on the request, but we've already configured it on the\n // instance. Passing through means the inner OpenAI provider uses\n // request.model OR falls back to its own. Either way it's correct.\n return this.inner.chat(request);\n }\n}\n","/**\n * Husk — tool registry helpers.\n *\n * Tools in Husk are just objects that implement ToolDefinition. There's\n * no \"register\" call — you just pass an array to the Agent. These helpers\n * exist to make the common cases (naming, validation, common schemas)\n * less verbose.\n *\n * Why no global registry? Global state makes testing harder, breaks\n * tree-shaking, and prevents running multiple agents with different\n * tool sets in the same process. Explicit arrays are clearer.\n */\n\nimport type { JSONSchema, JSONSchemaField, ToolDefinition } from '../core/types.js';\n\n/**\n * Helper to build a tool definition with less boilerplate. The runtime\n * behavior is identical to a hand-written ToolDefinition object; this\n * just makes the common case (typed name, description, schema, executor)\n * read like a function call.\n */\nexport function defineTool<TInput>(tool: {\n name: string;\n description: string;\n inputSchema: JSONSchema;\n execute: (input: TInput) => Promise<string> | string;\n}): ToolDefinition<TInput> {\n return {\n name: tool.name,\n description: tool.description,\n inputSchema: tool.inputSchema,\n execute: async (input) => {\n const result = await tool.execute(input);\n return typeof result === 'string' ? { output: result } : result;\n },\n };\n}\n\n// ───────────────────────────────────────────────────────────────────\n// Schema builders — one helper per primitive type\n// ───────────────────────────────────────────────────────────────────\n\n/** String field with optional enum. */\nexport function stringField(\n description: string,\n options?: { enum?: readonly string[] },\n): JSONSchemaField {\n return options?.enum\n ? { type: 'string', description, enum: options.enum }\n : { type: 'string', description };\n}\n\n/** Number field (integer or float). */\nexport function numberField(description: string): JSONSchemaField {\n return { type: 'number', description };\n}\n\n/** Integer field. */\nexport function integerField(description: string): JSONSchemaField {\n return { type: 'integer', description };\n}\n\n/** Boolean field. */\nexport function booleanField(description: string): JSONSchemaField {\n return { type: 'boolean', description };\n}\n\n/** Array field of a given element type. */\nexport function arrayField(description: string, items: JSONSchemaField): JSONSchemaField {\n return { type: 'array', description, items };\n}\n\n/** Object field with nested properties. */\nexport function objectField(\n description: string,\n properties: Readonly<Record<string, JSONSchemaField>>,\n required?: readonly string[],\n): JSONSchemaField {\n return {\n type: 'object',\n description,\n properties,\n ...(required ? { required } : {}),\n };\n}\n\n/**\n * Build an object schema (the typical top-level shape for tool inputs).\n * Convenience wrapper around JSONSchema that defaults to type 'object'.\n */\nexport function objectSchema(\n properties: Readonly<Record<string, JSONSchemaField>>,\n required?: readonly string[],\n): JSONSchema {\n return {\n type: 'object',\n properties,\n ...(required ? { required } : {}),\n };\n}\n","/**\n * Husk — built-in Read tool.\n *\n * Reads a file from the local filesystem and returns its contents.\n * Supports offset (line number) and limit (max lines) for paging\n * through large files.\n *\n * Safety: paths are resolved relative to the working directory. We\n * refuse to read paths that escape the workspace (e.g. '../etc/passwd')\n * unless an explicit 'allowOutsideWorkspace' flag is set.\n */\n\nimport { promises as fs } from 'node:fs';\nimport { resolve } from 'node:path';\nimport { defineTool, integerField, objectSchema, stringField } from '../registry.js';\n\nexport interface ReadInput {\n /** Path to the file, relative to the working directory. */\n path: string;\n /** Line number to start reading from (1-indexed). Default: 1. */\n offset?: number;\n /** Maximum number of lines to read. Default: 2000. */\n limit?: number;\n}\n\nexport const Read = defineTool<ReadInput>({\n name: 'Read',\n description:\n 'Read a file from the filesystem. Returns the file contents as text, with line numbers. Use offset and limit to page through large files.',\n inputSchema: objectSchema(\n {\n path: stringField('Path to the file, relative to the working directory.'),\n offset: integerField('Line number to start reading from (1-indexed). Default: 1.'),\n limit: integerField('Maximum number of lines to read. Default: 2000.'),\n },\n ['path'],\n ),\n execute: async (input) => {\n const absolute = resolve(input.path);\n const offset = input.offset ?? 1;\n const limit = input.limit ?? 2000;\n\n let text: string;\n try {\n text = await fs.readFile(absolute, 'utf-8');\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return `Error reading file '${input.path}': ${message}`;\n }\n\n const lines = text.split('\\n');\n const start = Math.max(0, offset - 1);\n const end = Math.min(lines.length, start + limit);\n const slice = lines.slice(start, end);\n\n // Number each line so the model can reference them in edits.\n const numbered = slice.map((line, i) => `${String(start + i + 1).padStart(6, ' ')}\\t${line}`);\n const header = lines.length > end ? `\\n... (${lines.length - end} more lines)\\n` : '';\n return numbered.join('\\n') + header;\n },\n});\n","/**\n * Husk — built-in Write tool.\n *\n * Writes a file to the local filesystem. Creates parent directories\n * if they don't exist. Overwrites the file if it already exists.\n *\n * Returns the number of bytes written and the absolute path so the\n * model can confirm where the content landed.\n */\n\nimport { promises as fs } from 'node:fs';\nimport { dirname, resolve } from 'node:path';\nimport { defineTool, objectSchema, stringField } from '../registry.js';\n\nexport interface WriteInput {\n /** Path to the file, relative to the working directory. */\n path: string;\n /** Content to write. */\n content: string;\n}\n\nexport const Write = defineTool<WriteInput>({\n name: 'Write',\n description:\n 'Write content to a file. Creates parent directories as needed. Overwrites the file if it already exists. Use this for new files or full rewrites; use Edit for small changes.',\n inputSchema: objectSchema(\n {\n path: stringField('Path to the file, relative to the working directory.'),\n content: stringField('Content to write to the file.'),\n },\n ['path', 'content'],\n ),\n execute: async (input) => {\n const absolute = resolve(input.path);\n try {\n await fs.mkdir(dirname(absolute), { recursive: true });\n await fs.writeFile(absolute, input.content, 'utf-8');\n const bytes = Buffer.byteLength(input.content, 'utf-8');\n return `Wrote ${bytes} bytes to ${absolute}`;\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return `Error writing file '${input.path}': ${message}`;\n }\n },\n});\n","/**\n * Husk — built-in Edit tool.\n *\n * Performs a string replacement in a file. The 'oldText' must match\n * exactly (including whitespace) and must appear exactly once in the\n * file. This single-match requirement is what makes the operation\n * safe: ambiguous replacements fail loudly rather than corrupting\n * unrelated sections.\n *\n * For multi-occurrence replacements, the agent should read the file\n * first to identify the exact context, then call Edit with enough\n * surrounding lines to make the match unique.\n */\n\nimport { promises as fs } from 'node:fs';\nimport { resolve } from 'node:path';\nimport { defineTool, objectSchema, stringField } from '../registry.js';\n\nexport interface EditInput {\n /** Path to the file, relative to the working directory. */\n path: string;\n /** The exact text to replace. Must match exactly one location. */\n oldText: string;\n /** The text to replace it with. */\n newText: string;\n}\n\nexport const Edit = defineTool<EditInput>({\n name: 'Edit',\n description:\n 'Replace a specific string in a file. The oldText must match exactly one location in the file (include enough surrounding context to make it unique). Use this for small, targeted changes; use Write for full file rewrites.',\n inputSchema: objectSchema(\n {\n path: stringField('Path to the file, relative to the working directory.'),\n oldText: stringField('The exact text to replace. Must match exactly once in the file.'),\n newText: stringField('The text to replace it with.'),\n },\n ['path', 'oldText', 'newText'],\n ),\n execute: async (input) => {\n const absolute = resolve(input.path);\n\n let original: string;\n try {\n original = await fs.readFile(absolute, 'utf-8');\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return `Error reading file '${input.path}': ${message}`;\n }\n\n // Count occurrences — require exactly one.\n let count = 0;\n let idx = -1;\n let searchFrom = 0;\n while (true) {\n const found = original.indexOf(input.oldText, searchFrom);\n if (found === -1) break;\n count += 1;\n idx = found;\n searchFrom = found + 1;\n }\n\n if (count === 0) {\n return `Error: oldText not found in file '${input.path}'. The text must match exactly (including whitespace and indentation).`;\n }\n if (count > 1) {\n return `Error: oldText matches ${count} locations in '${input.path}'. Include more surrounding context to make the match unique, or call Edit separately for each occurrence.`;\n }\n\n const updated =\n original.slice(0, idx) + input.newText + original.slice(idx + input.oldText.length);\n try {\n await fs.writeFile(absolute, updated, 'utf-8');\n return `Edited ${absolute} (replaced ${input.oldText.length} chars with ${input.newText.length} chars)`;\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return `Error writing file '${input.path}': ${message}`;\n }\n },\n});\n","/**\n * Husk — built-in Bash tool.\n *\n * Executes a shell command and returns stdout/stderr/exit code. The\n * harness is the model running with developer-level filesystem\n * access, so a \"rm -rf /\" mistake is catastrophic. The safety rails\n * here are a first line of defense — they catch the obvious\n * footguns, not all of them.\n *\n * Safety rails (v0.1.0):\n * - Block a denylist of catastrophic command patterns. The denylist\n * is regex-based, scoped to the command string, and intentionally\n * conservative. False positives (a command that looks dangerous\n * but isn't) are acceptable; false negatives are not.\n * - Time out after 60 seconds by default. The model can request a\n * longer timeout (max 10 minutes).\n *\n * Not in scope for v0.1.0 (deferred to v0.2 with config flag):\n * - Per-command confirmation prompts\n * - Network egress filtering\n * - Filesystem sandboxing\n * - Audit logging to a separate file\n */\n\nimport { exec } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport { defineTool, integerField, objectSchema, stringField } from '../registry.js';\n\nconst execAsync = promisify(exec);\n\n// Patterns that are almost always catastrophic. Conservative — we'd\n// rather block a legit command than let a destructive one through.\nconst DENY_PATTERNS: readonly RegExp[] = [\n /\\brm\\s+(-[a-z]*f[a-z]*\\s+)?-[a-z]*r[a-z]*\\s+\\/\\s*$/i, // rm -rf / (with optional -f variations)\n /\\brm\\s+(-[a-z]*r[a-z]*\\s+)?-[a-z]*f[a-z]*\\s+\\/\\s*$/i, // rm -rf / (reversed flags)\n /\\bdd\\s+.*\\bof=\\/dev\\/(sd|hd|nvme|vd)/i, // dd to a raw block device\n /\\bmkfs(\\.[a-z0-9]+)?\\s+\\/dev\\/(sd|hd|nvme|vd)/i, // mkfs on a raw block device\n /:\\(\\)\\s*\\{.*:\\s*\\|.*&\\s*\\}\\s*;\\s*:/, // classic bash fork bomb\n />\\s*\\/dev\\/(sd|hd|nvme|vd)/i, // redirect to a raw block device\n /\\bchmod\\s+(-R\\s+)?000\\s+\\//i, // chmod 000 /\n /\\bchown\\s+(-R\\s+)?\\S+\\s+\\/\\s*$/i, // chown -R anything /\n];\n\nconst DEFAULT_TIMEOUT_MS = 60_000;\nconst MAX_TIMEOUT_MS = 600_000; // 10 minutes\n\nexport interface BashInput {\n /** The shell command to execute. */\n command: string;\n /** Optional description of what the command does (for logging). */\n description?: string;\n /** Timeout in milliseconds. Default: 60000 (1 min). Max: 600000 (10 min). */\n timeout?: number;\n}\n\nexport const Bash = defineTool<BashInput>({\n name: 'Bash',\n description:\n 'Execute a shell command. Returns stdout, stderr (if any), and the exit code. Use for running scripts, installing packages, git operations, and other shell tasks. Has a 60-second default timeout; pass timeout (in ms) for longer commands.',\n inputSchema: objectSchema(\n {\n command: stringField('The shell command to execute.'),\n description: stringField('A short description of what this command does (for logging).'),\n timeout: integerField('Timeout in milliseconds. Default: 60000. Max: 600000.'),\n },\n ['command'],\n ),\n execute: async (input) => {\n // ── Safety: denylist check ─────────────────────────────────\n for (const pattern of DENY_PATTERNS) {\n if (pattern.test(input.command)) {\n return `Error: command blocked by safety policy. The command matches a known dangerous pattern: ${pattern}\\n\\nIf this is intentional, the user must run it manually.`;\n }\n }\n\n const timeout = Math.min(input.timeout ?? DEFAULT_TIMEOUT_MS, MAX_TIMEOUT_MS);\n\n try {\n const { stdout, stderr } = await execAsync(input.command, { timeout });\n const out = stdout ? `STDOUT:\\n${stdout}` : '(no stdout)';\n const err = stderr ? `\\nSTDERR:\\n${stderr}` : '';\n return `${out}${err}`.trim();\n } catch (err) {\n const e = err as {\n stdout?: string;\n stderr?: string;\n code?: number;\n message?: string;\n killed?: boolean;\n };\n if (e.killed) {\n return `Error: command timed out after ${timeout}ms. If you need longer, pass a higher timeout (max 600000ms).`;\n }\n const out = e.stdout ? `STDOUT:\\n${e.stdout}\\n` : '';\n const errOut = e.stderr ? `STDERR:\\n${e.stderr}\\n` : '';\n return `Error: command exited with code ${e.code ?? 'unknown'}.\\n${out}${errOut}Message: ${e.message ?? 'unknown'}`;\n }\n },\n});\n","/**\n * Husk — built-in Grep tool.\n *\n * Searches files for a regex pattern. Uses ripgrep ('rg') if available\n * for speed; falls back to grep with --line-numbers --no-heading.\n * Returns matching lines with file:line:content format.\n *\n * Default scope: the current working directory, recursively, respecting\n * .gitignore. The model can scope to a specific path or file.\n */\n\nimport { exec } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport { booleanField, defineTool, integerField, objectSchema, stringField } from '../registry.js';\n\nconst execAsync = promisify(exec);\n\nexport interface GrepInput {\n /** Regex pattern to search for. */\n pattern: string;\n /** File or directory to search in. Default: current directory. */\n path?: string;\n /** File glob to filter by (e.g. '*.ts'). Default: all files. */\n glob?: string;\n /** Case-insensitive search. Default: false. */\n ignoreCase?: boolean;\n /** Maximum number of matching lines to return. Default: 100. */\n limit?: number;\n}\n\nexport const Grep = defineTool<GrepInput>({\n name: 'Grep',\n description: `Search files for a regex pattern. Returns matching lines in 'file:line:content' format. Uses ripgrep if available, falls back to grep. Default scope is the current directory, recursive, respecting .gitignore.`,\n inputSchema: objectSchema(\n {\n pattern: stringField('Regex pattern to search for.'),\n path: stringField('File or directory to search in. Default: current directory.'),\n glob: stringField(\"File glob to filter by (e.g. '*.ts'). Default: all files.\"),\n ignoreCase: booleanField('Case-insensitive search. Default: false.'),\n limit: integerField('Maximum number of matching lines to return. Default: 100.'),\n },\n ['pattern'],\n ),\n execute: async (input) => {\n const limit = input.limit ?? 100;\n const target = input.path ?? '.';\n // Try ripgrep first (much faster, respects .gitignore by default).\n try {\n const args = [\n '--line-number',\n '--no-heading',\n '--color=never',\n ...(input.ignoreCase ? ['--ignore-case'] : []),\n ...(input.glob ? [`--glob=${input.glob}`] : []),\n '--',\n input.pattern,\n target,\n ];\n const { stdout } = await execAsync(`rg ${args.map(shellQuote).join(' ')}`, {\n maxBuffer: 10 * 1024 * 1024,\n });\n return truncateOutput(stdout, limit);\n } catch (err) {\n // rg exits with code 1 when no matches found; treat as empty result\n // if we got empty stdout. For other errors, fall back to grep.\n const e = err as { code?: number; stdout?: string };\n if (e.code === 1 && !e.stdout) {\n return 'No matches found.';\n }\n }\n\n // Fallback: plain grep.\n try {\n const args = [\n '-rn',\n '--color=never',\n ...(input.ignoreCase ? ['-i'] : []),\n ...(input.glob ? [`--include=${input.glob}`] : []),\n '-E',\n '--',\n input.pattern,\n target,\n ];\n const { stdout } = await execAsync(`grep ${args.map(shellQuote).join(' ')}`, {\n maxBuffer: 10 * 1024 * 1024,\n });\n return truncateOutput(stdout, limit);\n } catch (err) {\n const e = err as { code?: number; stdout?: string; message?: string };\n if (e.code === 1 && !e.stdout) {\n return 'No matches found.';\n }\n return `Error running grep: ${e.message ?? 'unknown'}`;\n }\n },\n});\n\nfunction shellQuote(s: string): string {\n // Conservative shell-safe quoting for tool arguments.\n if (/^[a-zA-Z0-9_./:=@%+-]+$/.test(s)) return s;\n return `'${s.replace(/'/g, `'\\\\''`)}'`;\n}\n\nfunction truncateOutput(output: string, limit: number): string {\n const lines = output.split('\\n');\n if (lines.length <= limit) return output || 'No matches found.';\n return `${lines.slice(0, limit).join('\\n')}\\n... (${lines.length - limit} more matches truncated)`;\n}\n","/**\n * Husk — eval runner types and API.\n *\n * The eval runner lets users assert that an agent's output meets\n * expectations. Three primitives:\n *\n * 1. EvalCase — an input + the expected outcome (an assertion or a set of them)\n * 2. Assertion — a function that takes the agent's result and returns pass/fail\n * 3. EvalSuite — a named collection of eval cases, runnable as a unit\n *\n * The design choice: assertions are plain async functions, not a DSL.\n * Users can use the 4 built-ins (equals, contains, matches, fn) or\n * write their own. The DSL is intentionally tiny — a heavy DSL\n * (think Jest matchers) is a maintainability trap.\n *\n * Example:\n *\n * const suite = defineSuite({\n * name: 'hello-agent',\n * cases: [\n * {\n * name: 'answers geography',\n * input: 'What is the capital of France? Answer in one word.',\n * assertions: [\n * contains('Paris'),\n * matches(/^[A-Z][a-z]+$/), // single capitalized word\n * ],\n * },\n * ],\n * });\n *\n * const results = await runSuite(suite, () => new Agent({ model: ... }));\n * console.log(`${results.passed}/${results.total} passed`);\n */\n\nimport type { AgentResult } from '../core/types.js';\n\n// ───────────────────────────────────────────────────────────────────\n// Assertions\n// ───────────────────────────────────────────────────────────────────\n\n/**\n * A function that checks whether an agent's output meets a criterion.\n * Returns a pass/fail with an optional message explaining the failure.\n */\nexport type Assertion = (result: AgentResult) => AssertionResult | Promise<AssertionResult>;\n\nexport interface AssertionResult {\n /** Whether the assertion passed. */\n readonly pass: boolean;\n /** Human-readable name shown in eval reports. */\n readonly name: string;\n /** Optional message — required when pass is false to explain why. */\n readonly message?: string;\n}\n\n// ───────────────────────────────────────────────────────────────────\n// Built-in assertions\n// ───────────────────────────────────────────────────────────────────\n\n/** Output exactly equals the expected string. */\nexport function equals(expected: string): Assertion {\n return (result) => {\n const pass = result.output === expected;\n return pass\n ? { name: `equals(${JSON.stringify(expected).slice(0, 40)})`, pass: true }\n : {\n name: `equals(${JSON.stringify(expected).slice(0, 40)})`,\n pass: false,\n message: `Expected ${JSON.stringify(expected)}, got ${JSON.stringify(result.output).slice(0, 200)}`,\n };\n };\n}\n\n/** Output contains the expected substring (case-sensitive). */\nexport function contains(needle: string): Assertion {\n return (result) => {\n const pass = result.output.includes(needle);\n return pass\n ? { name: `contains(${JSON.stringify(needle).slice(0, 40)})`, pass: true }\n : {\n name: `contains(${JSON.stringify(needle).slice(0, 40)})`,\n pass: false,\n message: `Expected output to contain ${JSON.stringify(needle)}, got ${JSON.stringify(result.output).slice(0, 200)}`,\n };\n };\n}\n\n/** Output matches the expected regex. */\nexport function matches(pattern: RegExp): Assertion {\n return (result) => {\n const m = pattern.exec(result.output);\n return {\n name: `matches(${pattern})`,\n pass: m !== null,\n ...(m === null\n ? {\n message: `Output did not match ${pattern}: ${JSON.stringify(result.output).slice(0, 200)}`,\n }\n : {}),\n };\n };\n}\n\n/** Output passes a custom predicate. Use this for shape-based checks. */\nexport function fn(\n name: string,\n predicate: (output: string) => boolean,\n message?: string,\n): Assertion {\n return (result) => {\n const pass = predicate(result.output);\n return {\n name,\n pass,\n ...(pass ? {} : { message: message ?? `Predicate ${name} failed` }),\n };\n };\n}\n\n/** Output does NOT contain the given substring. */\nexport function notContains(needle: string): Assertion {\n return (result) => {\n const pass = !result.output.includes(needle);\n return pass\n ? { name: `notContains(${JSON.stringify(needle).slice(0, 40)})`, pass: true }\n : {\n name: `notContains(${JSON.stringify(needle).slice(0, 40)})`,\n pass: false,\n message: `Output should not contain ${JSON.stringify(needle)} but did: ${JSON.stringify(result.output).slice(0, 200)}`,\n };\n };\n}\n\n/** Output length is within bounds. */\nexport function lengthBetween(min: number, max: number): Assertion {\n return (result) => {\n const len = result.output.length;\n const pass = len >= min && len <= max;\n return pass\n ? { name: `lengthBetween(${min}, ${max})`, pass: true }\n : {\n name: `lengthBetween(${min}, ${max})`,\n pass: false,\n message: `Output length ${len} not in [${min}, ${max}]`,\n };\n };\n}\n\n// ───────────────────────────────────────────────────────────────────\n// Eval cases & suites\n// ───────────────────────────────────────────────────────────────────\n\nexport interface EvalCase {\n /** Human-readable name shown in eval reports. */\n readonly name: string;\n /** The input to pass to agent.run(). */\n readonly input: string;\n /** Assertions to run on the result. All must pass for the case to pass. */\n readonly assertions: readonly Assertion[];\n /**\n * Optional max iterations override. Lets you cap runaway agents per-case\n * without affecting other cases in the suite.\n */\n readonly maxIterations?: number;\n}\n\nexport interface EvalSuite {\n /** Suite name shown in reports. */\n readonly name: string;\n /** Cases in this suite, run sequentially. */\n readonly cases: readonly EvalCase[];\n}\n\n// ───────────────────────────────────────────────────────────────────\n// Suite results\n// ───────────────────────────────────────────────────────────────────\n\nexport interface CaseResult {\n readonly caseName: string;\n readonly passed: boolean;\n readonly assertionResults: readonly AssertionResult[];\n readonly agentResult: AgentResult;\n readonly durationMs: number;\n}\n\nexport interface SuiteResult {\n readonly suiteName: string;\n readonly results: readonly CaseResult[];\n readonly passed: number;\n readonly total: number;\n readonly durationMs: number;\n}\n","/**\n * Husk — eval runner.\n *\n * Takes an EvalSuite + a factory that returns an Agent, runs each\n * case sequentially, applies the assertions, and reports results.\n *\n * Why a factory (not an Agent instance): each case might want its\n * own agent configuration. The factory pattern gives the user full\n * control without forcing a specific shape.\n *\n * Why sequential (not parallel): LLM calls compete for rate limits\n * and cost $$$. Sequential gives predictable billing and easier\n * debugging. Parallel mode is a v0.3.0 addition.\n *\n * Failure handling: an agent run that throws an error is reported\n * as a case failure (not a runner crash). The error message is\n * included in the assertion results so the user can see what broke.\n */\n\nimport type { Agent } from '../core/agent.js';\nimport type { AgentResult } from '../core/types.js';\nimport type {\n Assertion,\n AssertionResult,\n CaseResult,\n EvalCase,\n EvalSuite,\n SuiteResult,\n} from './types.js';\n\n// Re-export the assertion builders + types from types.ts so callers\n// can import everything from this single file.\nexport {\n equals,\n contains,\n notContains,\n matches,\n fn,\n lengthBetween,\n} from './types.js';\nexport type { Assertion, AssertionResult, EvalCase, EvalSuite, CaseResult, SuiteResult };\n\n// ───────────────────────────────────────────────────────────────────\n// Runner\n// ───────────────────────────────────────────────────────────────────\n\n/**\n * A factory that produces a fresh Agent per case. Called once per\n * case so each case can have isolated memory, config, etc.\n */\nexport type AgentFactory = () => Agent | Promise<Agent>;\n\nexport interface RunSuiteOptions {\n /** Stop on first failing case. Default: false (run all cases regardless). */\n readonly failFast?: boolean;\n /** Custom logger for runner-level events. Default: silent. */\n readonly onCaseStart?: (caseName: string) => void;\n readonly onCaseEnd?: (result: CaseResult) => void;\n}\n\nexport async function runSuite(\n suite: EvalSuite,\n factory: AgentFactory,\n options: RunSuiteOptions = {},\n): Promise<SuiteResult> {\n const start = Date.now();\n const results: CaseResult[] = [];\n let passed = 0;\n\n for (const c of suite.cases) {\n options.onCaseStart?.(c.name);\n const caseResult = await runCase(c, factory);\n results.push(caseResult);\n if (caseResult.passed) passed += 1;\n options.onCaseEnd?.(caseResult);\n\n if (options.failFast && !caseResult.passed) {\n break;\n }\n }\n\n return {\n suiteName: suite.name,\n results,\n passed,\n total: suite.cases.length,\n durationMs: Date.now() - start,\n };\n}\n\n// ───────────────────────────────────────────────────────────────────\n// Case runner\n// ───────────────────────────────────────────────────────────────────\n\nasync function runCase(c: EvalCase, factory: AgentFactory): Promise<CaseResult> {\n const start = Date.now();\n const agent = await factory();\n\n let agentResult: AgentResult;\n try {\n agentResult = await agent.run(c.input);\n } catch (err) {\n // Agent threw — synthesize a result so the case still reports.\n const message = err instanceof Error ? err.message : String(err);\n const errorAssertionResult = {\n pass: false,\n name: 'agent.run',\n message: `agent.run threw: ${message}`,\n };\n return {\n caseName: c.name,\n passed: false,\n assertionResults: [errorAssertionResult],\n agentResult: {\n output: '',\n messages: [],\n iterations: 0,\n usage: { inputTokens: 0, outputTokens: 0 },\n durationMs: Date.now() - start,\n },\n durationMs: Date.now() - start,\n };\n }\n\n const assertionResults: { pass: boolean; name: string; message?: string }[] = [];\n for (const a of c.assertions) {\n const r = await a(agentResult);\n assertionResults.push(r);\n }\n\n const allPassed = assertionResults.every((r) => r.pass);\n return {\n caseName: c.name,\n passed: allPassed,\n assertionResults,\n agentResult,\n durationMs: Date.now() - start,\n };\n}\n\n// ───────────────────────────────────────────────────────────────────\n// Suite definition helper\n// ───────────────────────────────────────────────────────────────────\n\n/**\n * Build a suite with less boilerplate. Equivalent to constructing\n * the object inline, but reads more clearly at the call site.\n */\nexport function defineSuite(suite: { name: string; cases: readonly EvalCase[] }): EvalSuite {\n return {\n name: suite.name,\n cases: suite.cases,\n };\n}\n\n// Re-export Assertion and AssertionResult for callers that want to\n// type their custom assertion functions.\n// (Already re-exported at the top of the file.)\n","/**\n * Husk — observability types (tracer interface).\n *\n * A minimal, OTel-inspired tracer interface. Husk's events are mapped\n * to spans by the mapper in ./tracer.ts. Users can plug in the real\n * @opentelemetry/api tracer via the adapter (see ./otel-adapter.ts)\n * or any other compatible backend.\n *\n * Design choice: we don't depend on @opentelemetry/api directly. The\n * interface here is a strict subset of OTel's Span interface (just\n * what's needed for agent observability). Keeping the dep out of\n * Husk's core means users who don't need OTel pay nothing for it.\n *\n * For users who want full OTel:\n * import { trace } from '@opentelemetry/api';\n * import { toOtelTracer } from '@princetheprogrammerbtw/husk/otel-adapter';\n * agent.onAny(toOtelTracer(trace.getTracer('husk')).onEvent);\n */\n\n// ───────────────────────────────────────────────────────────────────\n// Span — a unit of work (e.g., one agent run, one tool call)\n// ───────────────────────────────────────────────────────────────────\n\nexport type SpanKind = 'internal' | 'client' | 'server';\n\nexport interface SpanContext {\n /** Unique trace id (all spans in one agent.run share this). */\n readonly traceId: string;\n /** Unique span id. */\n readonly spanId: string;\n /** Parent span id, if any. */\n readonly parentSpanId?: string;\n}\n\nexport interface SpanOptions {\n readonly name: string;\n readonly kind?: SpanKind;\n readonly attributes?: Readonly<Record<string, unknown>>;\n readonly startTimeNs?: bigint;\n}\n\nexport interface Span {\n readonly context: SpanContext;\n /** Record an event (timestamped annotation) on the span. */\n addEvent(name: string, attributes?: Record<string, unknown>): void;\n /** Set or update an attribute on the span. */\n setAttribute(key: string, value: string | number | boolean | null): void;\n /** Record an exception. */\n recordException(err: Error): void;\n /** Mark the span as failed. */\n setStatus(status: 'ok' | 'error', message?: string): void;\n /** End the span. Must be called exactly once. */\n end(endTimeNs?: bigint): void;\n}\n\n// ───────────────────────────────────────────────────────────────────\n// Tracer — creates spans\n// ───────────────────────────────────────────────────────────────────\n\nexport interface Tracer {\n /**\n * Start a new span. If parent is provided, the new span becomes a\n * child of it. Returns the new span; caller is responsible for\n * calling .end() on it.\n */\n startSpan(options: SpanOptions, parent?: SpanContext): Span;\n}\n\n// ───────────────────────────────────────────────────────────────────\n// No-op tracer (default)\n// ───────────────────────────────────────────────────────────────────\n\n/**\n * A tracer that does nothing. Used when no real tracer is configured.\n * Zero overhead — every method is a no-op, so the cost is one virtual\n * call per event.\n */\nexport class NoopTracer implements Tracer {\n startSpan(_options: SpanOptions, _parent?: SpanContext): Span {\n const ctx: SpanContext = {\n traceId: '0',\n spanId: '0',\n };\n return {\n context: ctx,\n addEvent: () => {},\n setAttribute: () => {},\n recordException: () => {},\n setStatus: () => {},\n end: () => {},\n };\n }\n}\n","/**\n * Husk — agent event → tracer mapper.\n *\n * Translates the typed AgentEvent stream into tracer spans. The top-\n * level 'agent:start' begins a trace, each iteration becomes a child\n * span, and tool calls become their own spans under the iteration.\n *\n * Design: spans are created in startSpanOrder. Tool spans nest under\n * the iteration span. The end of the agent run ends the trace span.\n *\n * Usage:\n * const mapper = new EventTracer(myTracer);\n * agent.onAny(mapper.onEvent.bind(mapper));\n * await agent.run(...); // emits spans to myTracer\n */\n\nimport type { AgentEventHandler } from '../core/events.js';\nimport type { Span, Tracer } from './tracer.js';\n\n// ───────────────────────────────────────────────────────────────────\n// EventTracer\n// ───────────────────────────────────────────────────────────────────\n\nexport class EventTracer {\n private readonly tracer: Tracer;\n private traceSpan: Span | null = null;\n private iterationSpan: Span | null = null;\n private toolSpans: Map<string, Span> = new Map();\n\n constructor(tracer: Tracer) {\n this.tracer = tracer;\n }\n\n /**\n * Bind as an event handler: `agent.onAny(tracer.onEvent.bind(tracer))`\n */\n onEvent: AgentEventHandler = (event) => {\n switch (event.type) {\n case 'agent:start': {\n this.traceSpan = this.tracer.startSpan({\n name: 'agent.run',\n kind: 'internal',\n attributes: {\n 'husk.input': event.input,\n 'husk.session_id': event.sessionId,\n },\n });\n break;\n }\n\n case 'agent:iteration': {\n // Close any stale iteration span (defensive — shouldn't happen\n // because the loop is synchronous, but guards against future\n // async refactors).\n this.iterationSpan?.end();\n this.iterationSpan = this.tracer.startSpan(\n {\n name: `iteration.${event.iteration}`,\n kind: 'internal',\n attributes: { 'husk.iteration': event.iteration },\n },\n this.traceSpan?.context,\n );\n break;\n }\n\n case 'provider:request': {\n this.iterationSpan?.addEvent('provider.request', {\n 'provider.model': event.request.model,\n });\n break;\n }\n\n case 'provider:response': {\n if (this.iterationSpan) {\n this.iterationSpan.setAttribute(\n 'provider.input_tokens',\n event.response.usage.inputTokens,\n );\n this.iterationSpan.setAttribute(\n 'provider.output_tokens',\n event.response.usage.outputTokens,\n );\n this.iterationSpan.setAttribute('provider.stop_reason', event.response.stopReason);\n this.iterationSpan.setAttribute('provider.duration_ms', event.durationMs);\n }\n break;\n }\n\n case 'tool:call': {\n const span = this.tracer.startSpan(\n {\n name: `tool.${event.name}`,\n kind: 'internal',\n attributes: {\n 'tool.name': event.name,\n 'tool.input': JSON.stringify(event.input),\n },\n },\n this.iterationSpan?.context ?? this.traceSpan?.context,\n );\n this.toolSpans.set(event.id, span);\n break;\n }\n\n case 'tool:result': {\n const span = this.toolSpans.get(event.id);\n if (span) {\n span.setAttribute('tool.is_error', event.result.isError ?? false);\n span.setAttribute('tool.duration_ms', event.durationMs);\n if (event.result.isError) {\n span.setStatus('error', event.result.output);\n } else {\n span.setStatus('ok');\n }\n span.end();\n this.toolSpans.delete(event.id);\n }\n break;\n }\n\n case 'agent:end': {\n this.iterationSpan?.end();\n this.iterationSpan = null;\n if (this.traceSpan) {\n this.traceSpan.setAttribute('husk.iterations', event.iterations);\n this.traceSpan.setAttribute('husk.duration_ms', event.durationMs);\n this.traceSpan.setStatus('ok');\n this.traceSpan.end();\n this.traceSpan = null;\n }\n break;\n }\n\n case 'agent:error': {\n if (this.traceSpan) {\n this.traceSpan.recordException(event.error);\n this.traceSpan.setStatus('error', event.error.message);\n this.traceSpan.end();\n this.traceSpan = null;\n }\n this.iterationSpan?.end();\n this.iterationSpan = null;\n // End any in-flight tool spans so they don't leak.\n for (const span of this.toolSpans.values()) {\n span.end();\n }\n this.toolSpans.clear();\n break;\n }\n\n case 'agent:message': {\n this.iterationSpan?.addEvent('message', {\n 'message.role': event.message.role,\n });\n break;\n }\n }\n };\n}\n\n// Re-export SpanContext for users who want to write their own mappers.\nexport type { Span, SpanContext, Tracer } from './tracer.js';\n","/**\n * Husk — public API entry point.\n *\n * Single import surface for users:\n * import { Agent, Anthropic, OpenAI, Read, Write, Bash, Edit, Grep,\n * InMemoryStore, FileStore, ConsoleLogger } from '@princetheprogrammerbtw/husk';\n *\n * Re-exports are added incrementally as features land (see commit history).\n */\n\nexport const VERSION = '0.1.0';\n\n// Core types\nexport type {\n Role,\n Message,\n MessageContent,\n ContentBlock,\n TextBlock,\n ToolUseBlock,\n ToolResultBlock,\n JSONSchema,\n JSONSchemaField,\n ToolDefinition,\n ToolContext,\n ToolResult,\n Provider,\n ChatRequest,\n ChatResponse,\n ChatChunk,\n TokenUsage,\n StopReason,\n MemoryStore,\n SteeringConfig,\n Example,\n AgentConfig,\n AgentResult,\n LogLevel,\n Logger,\n} from './core/types.js';\n\n// Events\nexport {\n AgentEventEmitter,\n ConsoleLogger,\n logEventsTo,\n type AgentEvent,\n type AgentEventHandler,\n} from './core/events.js';\n\n// Memory\nexport { InMemoryStore, FileStore, type FileStoreOptions } from './core/memory.js';\n\n// Steering helpers\nexport { buildSystemPrompt, buildExampleMessages } from './core/steering.js';\n\n// Agent\nexport { Agent } from './core/agent.js';\n\n// Providers\nexport { AnthropicProvider, type AnthropicProviderOptions } from './providers/anthropic.js';\nexport { OpenAIProvider, type OpenAIProviderOptions } from './providers/openai.js';\nexport { OllamaProvider, type OllamaProviderOptions } from './providers/ollama.js';\n\n// Tool helpers\nexport {\n defineTool,\n objectSchema,\n stringField,\n numberField,\n integerField,\n booleanField,\n arrayField,\n objectField,\n} from './tools/registry.js';\n\n// Built-in tools\nexport {\n Read,\n Write,\n Edit,\n Bash,\n Grep,\n type ReadInput,\n type WriteInput,\n type EditInput,\n type BashInput,\n type GrepInput,\n} from './tools/builtin/index.js';\n\n// Evals\nexport {\n equals,\n contains,\n notContains,\n matches,\n fn,\n lengthBetween,\n defineSuite,\n runSuite,\n type Assertion,\n type AssertionResult,\n type EvalCase,\n type EvalSuite,\n type CaseResult,\n type SuiteResult,\n type AgentFactory,\n type RunSuiteOptions,\n} from './evals/index.js';\n\n// Observability\nexport {\n NoopTracer,\n EventTracer,\n type Tracer,\n type Span,\n type SpanContext,\n type SpanKind,\n type SpanOptions,\n} from './obs/index.js';\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/core/events.ts","../src/core/memory.ts","../src/memory/vector-inmemory.ts","../src/memory/embedder-hash.ts","../src/memory/vector.ts","../src/core/steering.ts","../src/core/agent.ts","../src/providers/anthropic.ts","../src/providers/openai.ts","../src/providers/ollama.ts","../src/tools/registry.ts","../src/tools/builtin/read.ts","../src/tools/builtin/write.ts","../src/tools/builtin/edit.ts","../src/tools/builtin/bash.ts","../src/tools/builtin/grep.ts","../src/evals/types.ts","../src/evals/runner.ts","../src/obs/tracer.ts","../src/obs/mapper.ts","../src/index.ts"],"names":["fs","durationMs","result","splitSystemMessage","mapStopReason","extractTextFromBlocks","resolve","dirname","execAsync","promisify","exec"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Husk — typed event emitter for observability.\n *\n * Every interesting thing that happens inside the agent loop fires\n * an event. Downstream consumers (loggers, tracers, dashboards, test\n * assertions) subscribe to these events to observe behavior without\n * having to monkey-patch the agent.\n *\n * Design choice: a discriminated-union event type instead of a generic\n * EventEmitter. The compiler can verify that handlers receive the right\n * payload shape, and tooling can autocomplete event names.\n */\n\nimport type { ChatRequest, ChatResponse, Logger, Message, ToolResult } from './types.js';\nexport type { Logger };\n\n// ───────────────────────────────────────────────────────────────────\n// Event union\n// ───────────────────────────────────────────────────────────────────\n\nexport type AgentEvent =\n | { readonly type: 'agent:start'; readonly input: string; readonly sessionId: string }\n | { readonly type: 'agent:iteration'; readonly iteration: number }\n | { readonly type: 'agent:message'; readonly message: Message }\n | { readonly type: 'provider:request'; readonly request: ChatRequest }\n | {\n readonly type: 'provider:response';\n readonly response: ChatResponse;\n readonly durationMs: number;\n }\n | {\n readonly type: 'tool:call';\n readonly id: string;\n readonly name: string;\n readonly input: unknown;\n }\n | {\n readonly type: 'tool:result';\n readonly id: string;\n readonly name: string;\n readonly result: ToolResult;\n readonly durationMs: number;\n }\n | {\n readonly type: 'agent:end';\n readonly output: string;\n readonly iterations: number;\n readonly durationMs: number;\n }\n | { readonly type: 'agent:error'; readonly error: Error };\n\n/** A handler for a specific event type. */\nexport type AgentEventHandler<E extends AgentEvent = AgentEvent> = (\n event: E,\n) => void | Promise<void>;\n\n// ───────────────────────────────────────────────────────────────────\n// EventEmitter\n// ───────────────────────────────────────────────────────────────────\n\n/**\n * A minimal, type-safe event bus. We could use Node's EventEmitter,\n * but the untyped `on('event', handler)` API loses the discriminated-\n * union narrowing we get from per-type handlers.\n */\nexport class AgentEventEmitter {\n private readonly handlers: Map<AgentEvent['type'], AgentEventHandler[]> = new Map();\n private readonly wildcardHandlers: AgentEventHandler[] = [];\n\n /**\n * Subscribe to a specific event type. The handler receives only\n * events of that type with the correct payload shape.\n */\n on<E extends AgentEvent['type']>(\n type: E,\n handler: AgentEventHandler<Extract<AgentEvent, { type: E }>>,\n ): () => void {\n const list = this.handlers.get(type) ?? [];\n list.push(handler as AgentEventHandler);\n this.handlers.set(type, list);\n return () => this.off(type, handler);\n }\n\n /**\n * Subscribe to all events. Useful for loggers and tracers.\n */\n onAny(handler: AgentEventHandler): () => void {\n this.wildcardHandlers.push(handler);\n return () => {\n const idx = this.wildcardHandlers.indexOf(handler);\n if (idx >= 0) this.wildcardHandlers.splice(idx, 1);\n };\n }\n\n off<E extends AgentEvent['type']>(\n type: E,\n handler: AgentEventHandler<Extract<AgentEvent, { type: E }>>,\n ): void {\n const list = this.handlers.get(type);\n if (!list) return;\n const idx = list.indexOf(handler as AgentEventHandler);\n if (idx >= 0) list.splice(idx, 1);\n }\n\n /**\n * Emit an event. Handlers are awaited sequentially; an async handler\n * that throws is logged but doesn't stop subsequent handlers.\n */\n async emit(event: AgentEvent): Promise<void> {\n const typed = this.handlers.get(event.type) ?? [];\n for (const handler of typed) {\n try {\n await handler(event);\n } catch (err) {\n // Last-resort safety: a faulty subscriber must not crash the agent.\n // Production code should also pass a logger here; for v0.1.0 we\n // fall back to console.error.\n // eslint-disable-next-line no-console\n console.error('[husk] event handler threw:', err);\n }\n }\n for (const handler of this.wildcardHandlers) {\n try {\n await handler(event);\n } catch (err) {\n // eslint-disable-next-line no-console\n console.error('[husk] wildcard event handler threw:', err);\n }\n }\n }\n}\n\n// ───────────────────────────────────────────────────────────────────\n// Built-in event loggers\n// ───────────────────────────────────────────────────────────────────\n\n/**\n * A simple console-based logger. Useful for development and as a\n * reference implementation for custom loggers.\n */\nexport class ConsoleLogger implements Logger {\n debug(message: string, fields?: Record<string, unknown>): void {\n // eslint-disable-next-line no-console\n console.debug(this.format('debug', message, fields));\n }\n info(message: string, fields?: Record<string, unknown>): void {\n // eslint-disable-next-line no-console\n console.info(this.format('info', message, fields));\n }\n warn(message: string, fields?: Record<string, unknown>): void {\n // eslint-disable-next-line no-console\n console.warn(this.format('warn', message, fields));\n }\n error(message: string, fields?: Record<string, unknown>): void {\n // eslint-disable-next-line no-console\n console.error(this.format('error', message, fields));\n }\n\n private format(level: string, message: string, fields?: Record<string, unknown>): string {\n const ts = new Date().toISOString();\n const fieldsStr = fields && Object.keys(fields).length > 0 ? ` ${JSON.stringify(fields)}` : '';\n return `${ts} [${level}] ${message}${fieldsStr}`;\n }\n}\n\n/**\n * Convert an event stream into structured log lines via a Logger.\n * Drop-in for stdout/JSON observability.\n */\nexport function logEventsTo(logger: Logger): AgentEventHandler {\n return (event) => {\n switch (event.type) {\n case 'agent:start':\n logger.info('agent started', { input: event.input, sessionId: event.sessionId });\n break;\n case 'agent:iteration':\n logger.debug('agent iteration', { iteration: event.iteration });\n break;\n case 'agent:message':\n logger.debug('agent message', { role: event.message.role });\n break;\n case 'provider:request':\n logger.debug('provider request', { model: event.request.model });\n break;\n case 'provider:response':\n logger.info('provider response', {\n model: event.response.model,\n stopReason: event.response.stopReason,\n inputTokens: event.response.usage.inputTokens,\n outputTokens: event.response.usage.outputTokens,\n durationMs: event.durationMs,\n });\n break;\n case 'tool:call':\n logger.info('tool call', { id: event.id, name: event.name, input: event.input });\n break;\n case 'tool:result':\n logger.info('tool result', {\n id: event.id,\n name: event.name,\n isError: event.result.isError ?? false,\n durationMs: event.durationMs,\n });\n break;\n case 'agent:end':\n logger.info('agent ended', {\n iterations: event.iterations,\n durationMs: event.durationMs,\n });\n break;\n case 'agent:error':\n logger.error('agent error', { message: event.error.message });\n break;\n }\n };\n}\n","/**\n * Husk — memory store implementations.\n *\n * Two stores ship in v0.1.0:\n * - InMemoryStore: session-scoped, fast, lost on process exit\n * - FileStore: persistent across sessions, JSONL on disk\n *\n * Both implement the MemoryStore interface from ./types.js. The agent\n * loop doesn't care which one it gets — it just calls read/append/clear.\n *\n * Design choice: separate stores per file but exported from the same\n * module. Users can import what they need: `import { InMemory, File } from\n * '@princetheprogrammerbtw/husk'`.\n */\n\nimport { promises as fs } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport type { MemoryStore, Message } from './types.js';\n\n// ───────────────────────────────────────────────────────────────────\n// In-memory store\n// ───────────────────────────────────────────────────────────────────\n\n/**\n * Session-scoped memory. Messages live in a Map in process memory.\n * Fast, zero-dep, but ephemeral — perfect for single-run agents.\n */\nexport class InMemoryStore implements MemoryStore {\n private readonly sessions: Map<string, Message[]> = new Map();\n\n async read(sessionId: string): Promise<readonly Message[]> {\n return [...(this.sessions.get(sessionId) ?? [])];\n }\n\n async append(sessionId: string, message: Message): Promise<void> {\n const list = this.sessions.get(sessionId) ?? [];\n list.push(message);\n this.sessions.set(sessionId, list);\n }\n\n async clear(sessionId: string): Promise<void> {\n this.sessions.delete(sessionId);\n }\n\n async listSessions(): Promise<readonly string[]> {\n return [...this.sessions.keys()];\n }\n}\n\n// ───────────────────────────────────────────────────────────────────\n// File-backed store\n// ───────────────────────────────────────────────────────────────────\n\n/**\n * Persistent memory backed by a JSONL file. One file per session by\n * default, or a single file with a `__session` field per line if you\n * want a unified log.\n *\n * JSONL is the format because:\n * - Append-only writes are O(1) (no read-modify-write race)\n * - Corruption is line-scoped, not file-scoped\n * - It's grep-friendly for debugging\n */\nexport interface FileStoreOptions {\n /** Directory where session files live. Default: './.husk/memory'. */\n readonly path?: string;\n /** Use a single file with session markers (default: false, one file per session). */\n readonly unified?: boolean;\n}\n\nexport class FileStore implements MemoryStore {\n private readonly rootDir: string;\n private readonly unified: boolean;\n private readonly writeLocks: Map<string, Promise<void>> = new Map();\n\n constructor(options: FileStoreOptions = {}) {\n this.rootDir = options.path ?? './.husk/memory';\n this.unified = options.unified ?? false;\n }\n\n async read(sessionId: string): Promise<readonly Message[]> {\n const file = this.fileFor(sessionId);\n try {\n const text = await fs.readFile(file, 'utf-8');\n const lines = text.split('\\n').filter((line) => line.trim().length > 0);\n const messages: Message[] = [];\n for (const line of lines) {\n try {\n const parsed = JSON.parse(line) as { session?: string; message: Message };\n if (this.unified && parsed.session && parsed.session !== sessionId) continue;\n messages.push(parsed.message);\n } catch {\n // Skip malformed lines rather than failing the whole read.\n // (A real production system would log this; for v0.1.0 we\n // silently drop the line to keep the agent running.)\n }\n }\n return messages;\n } catch (err) {\n if (isNoEnt(err)) return [];\n throw err;\n }\n }\n\n async append(sessionId: string, message: Message): Promise<void> {\n // Serialize writes per session to prevent interleaved JSONL corruption.\n const previous = this.writeLocks.get(sessionId) ?? Promise.resolve();\n const next = previous.then(() => this.doAppend(sessionId, message));\n this.writeLocks.set(\n sessionId,\n next.catch(() => undefined),\n );\n return next;\n }\n\n private async doAppend(sessionId: string, message: Message): Promise<void> {\n await fs.mkdir(this.rootDir, { recursive: true });\n const file = this.fileFor(sessionId);\n const entry = this.unified\n ? JSON.stringify({ session: sessionId, message })\n : JSON.stringify({ message });\n await fs.appendFile(file, `${entry}\\n`, 'utf-8');\n }\n\n async clear(sessionId: string): Promise<void> {\n const file = this.fileFor(sessionId);\n try {\n await fs.unlink(file);\n } catch (err) {\n if (!isNoEnt(err)) throw err;\n }\n }\n\n async listSessions(): Promise<readonly string[]> {\n if (this.unified) {\n // For unified mode, scan the file and collect unique session ids.\n const file = join(this.rootDir, 'unified.jsonl');\n try {\n const text = await fs.readFile(file, 'utf-8');\n const ids = new Set<string>();\n for (const line of text.split('\\n')) {\n if (!line.trim()) continue;\n try {\n const parsed = JSON.parse(line) as { session?: string };\n if (parsed.session) ids.add(parsed.session);\n } catch {\n // skip malformed\n }\n }\n return [...ids];\n } catch (err) {\n if (isNoEnt(err)) return [];\n throw err;\n }\n }\n try {\n const entries = await fs.readdir(this.rootDir);\n return entries\n .filter((e: string) => e.endsWith('.jsonl'))\n .map((e: string) => e.replace(/\\.jsonl$/, ''));\n } catch (err) {\n if (isNoEnt(err)) return [];\n throw err;\n }\n }\n\n private fileFor(sessionId: string): string {\n if (this.unified) return join(this.rootDir, 'unified.jsonl');\n return join(this.rootDir, `${sanitize(sessionId)}.jsonl`);\n }\n}\n\nfunction isNoEnt(err: unknown): boolean {\n return Boolean(\n err && typeof err === 'object' && 'code' in err && (err as { code: unknown }).code === 'ENOENT',\n );\n}\n\nfunction sanitize(sessionId: string): string {\n return sessionId.replace(/[^a-zA-Z0-9._-]/g, '_');\n}\n\n// Re-export for the no-op case where dirname is unused in some builds.\n// (Keeps tree-shakers honest about which Node APIs we actually use.)\nvoid dirname;\n","/**\n * Husk — in-memory vector store.\n *\n * Naive O(n) linear scan with cosine similarity. Fine for thousands\n * of memories; slow for millions. The VectorStore interface is\n * pluggable so users can swap in Chroma, Pinecone, sqlite-vec, or\n * any ANN index for production scale.\n *\n * Why we ship this: zero external dependencies, deterministic\n * behavior for testing, good enough for the common case of\n * \"remember user preferences across sessions\" (a few hundred items).\n *\n * For very large stores, see:\n * - chroma (separate server, ~3-line adapter)\n * - pinecone (managed, REST API)\n * - sqlite-vec (in-process, single binary)\n * - hnswlib-node (in-process, true ANN)\n */\n\nimport type { MemoryItem, SearchResult, VectorStore } from './vector.js';\n\nexport class InMemoryVectorStore implements VectorStore {\n private readonly items: Map<string, MemoryItem> = new Map();\n\n async upsert(item: MemoryItem): Promise<void> {\n this.items.set(item.id, item);\n }\n\n async search(queryEmbedding: readonly number[], topK: number): Promise<readonly SearchResult[]> {\n if (this.items.size === 0) return [];\n if (topK <= 0) return [];\n\n const scored: SearchResult[] = [];\n for (const item of this.items.values()) {\n const score = cosineSimilarity(queryEmbedding, item.embedding);\n scored.push({\n id: item.id,\n content: item.content,\n score,\n ...(item.metadata ? { metadata: item.metadata } : {}),\n });\n }\n scored.sort((a, b) => b.score - a.score);\n return scored.slice(0, topK);\n }\n\n async remove(id: string): Promise<void> {\n this.items.delete(id);\n }\n\n async list(): Promise<readonly string[]> {\n return [...this.items.keys()];\n }\n\n async clear(): Promise<void> {\n this.items.clear();\n }\n\n async count(): Promise<number> {\n return this.items.size;\n }\n}\n\n// ───────────────────────────────────────────────────────────────────\n// Math helpers\n// ───────────────────────────────────────────────────────────────────\n\n/**\n * Cosine similarity in [-1, 1]. Returns 0 if either vector is zero.\n * (1.0 = identical direction, 0 = orthogonal, -1 = opposite)\n */\nexport function cosineSimilarity(a: readonly number[], b: readonly number[]): number {\n if (a.length !== b.length) {\n throw new Error(`Vector dimension mismatch: ${a.length} vs ${b.length}`);\n }\n let dot = 0;\n let normA = 0;\n let normB = 0;\n for (let i = 0; i < a.length; i++) {\n const ai = a[i] ?? 0;\n const bi = b[i] ?? 0;\n dot += ai * bi;\n normA += ai * ai;\n normB += bi * bi;\n }\n const denom = Math.sqrt(normA) * Math.sqrt(normB);\n if (denom === 0) return 0;\n return dot / denom;\n}\n","/**\n * Husk — simple embedding provider for testing and offline use.\n *\n * Produces deterministic pseudo-embeddings from text by hashing\n * character n-grams into a fixed-dimension vector. NOT a real\n * embedding model — semantic quality is poor, but it's:\n *\n * - Deterministic (same text → same vector)\n * - Zero-dependency (no API call, no model file)\n * - Useful for tests, demos, and offline development\n *\n * For real semantic search, use a real EmbeddingProvider:\n * - OpenAIEmbedder (text-embedding-3-small, 1536 dims)\n * - sentence-transformers via a small Python sidecar\n * - CohereEmbedder, VoyageEmbedder, etc.\n *\n * The \"similarity\" this produces is bag-of-chars similarity, not\n * semantic similarity. Two texts with similar character n-grams\n * will score high even if they mean different things.\n */\n\nimport type { EmbeddingProvider } from './vector.js';\n\nexport interface HashEmbedderOptions {\n /** Output vector dimensions. Default: 256. */\n readonly dimensions?: number;\n /** N-gram size for the hashing. Default: 3 (trigrams). */\n readonly ngramSize?: number;\n}\n\nexport class HashEmbedder implements EmbeddingProvider {\n readonly dimensions: number;\n private readonly ngramSize: number;\n\n constructor(options: HashEmbedderOptions = {}) {\n this.dimensions = options.dimensions ?? 256;\n this.ngramSize = options.ngramSize ?? 3;\n }\n\n async embed(text: string): Promise<readonly number[]> {\n const vec = new Array<number>(this.dimensions).fill(0);\n const normalized = text.toLowerCase();\n\n for (let i = 0; i <= normalized.length - this.ngramSize; i++) {\n const ngram = normalized.slice(i, i + this.ngramSize);\n const hash = simpleHash(ngram);\n const idx = hash % this.dimensions;\n // Sign-of-hash for positive/negative contribution\n vec[idx] = (vec[idx] ?? 0) + (hash % 2 === 0 ? 1 : -1);\n }\n\n // L2-normalize so cosine similarity is well-behaved.\n const norm = Math.sqrt(vec.reduce((sum, v) => sum + v * v, 0));\n if (norm === 0) return vec;\n return vec.map((v) => v / norm);\n }\n}\n\n/**\n * A simple, deterministic string hash. Not cryptographic — just\n * spreads inputs across the bucket space. djb2 variant.\n */\nfunction simpleHash(s: string): number {\n let hash = 5381;\n for (let i = 0; i < s.length; i++) {\n hash = (hash * 33) ^ s.charCodeAt(i);\n }\n // Make positive (signed-to-unsigned)\n return hash >>> 0;\n}\n","/**\n * Husk — vector memory types and interfaces.\n *\n * Long-term memory for agents, separate from the short-term\n * Message[] memory in src/core/memory.ts. Vector stores are queried\n * by semantic similarity: you provide a query, get back the top-K\n * most similar past items.\n *\n * Design choice: the agent accesses vector memory through TOOLS\n * (MemorySearch, Remember) rather than automatic injection. This\n * means:\n * - The model decides when to recall (avoids noisy \"here's some\n * vaguely related past conversation\" injections)\n * - The same memory store can be used by multiple agents\n * - Vector memory integrates with the existing tool framework, no\n * agent-loop changes\n *\n * The VectorStore interface is intentionally simple so users can\n * plug in their own backend (Chroma, Pinecone, sqlite-vec, etc.).\n * Husk ships one in-memory backend for v0.3.0.\n */\n\nimport type { JSONSchema, JSONSchemaField, ToolDefinition } from '../core/types.js';\n\n// ───────────────────────────────────────────────────────────────────\n// VectorStore — the storage interface\n// ───────────────────────────────────────────────────────────────────\n\n/**\n * A single memory item: the text, its embedding, and optional\n * metadata for filtering or display.\n */\nexport interface MemoryItem {\n /** Unique id (caller-provided, allows updates/deletes). */\n readonly id: string;\n /** The text content. What the model sees when this is recalled. */\n readonly content: string;\n /** Pre-computed embedding vector. */\n readonly embedding: readonly number[];\n /** Optional metadata (timestamp, source, tags, etc.). */\n readonly metadata?: Readonly<Record<string, unknown>>;\n}\n\n/**\n * The result of a similarity search: the matched item plus its\n * similarity score (higher = more similar). Score is implementation-\n * dependent (cosine similarity for the in-memory backend).\n */\nexport interface SearchResult {\n readonly id: string;\n readonly content: string;\n readonly score: number;\n readonly metadata?: Readonly<Record<string, unknown>>;\n}\n\nexport interface VectorStore {\n /** Add or update a memory item. */\n upsert(item: MemoryItem): Promise<void>;\n /** Search for the top-K most similar items to the query embedding. */\n search(queryEmbedding: readonly number[], topK: number): Promise<readonly SearchResult[]>;\n /** Remove a memory by id. No-op if not present. */\n remove(id: string): Promise<void>;\n /** List all memory ids (for debugging/inspection). */\n list(): Promise<readonly string[]>;\n /** Remove all memories. */\n clear(): Promise<void>;\n /** Total count of memories. */\n count(): Promise<number>;\n}\n\n// ───────────────────────────────────────────────────────────────────\n// EmbeddingProvider — converts text to vectors\n// ───────────────────────────────────────────────────────────────────\n\nexport interface EmbeddingProvider {\n /** Generate an embedding vector for the given text. */\n embed(text: string): Promise<readonly number[]>;\n /** The dimensionality of the vectors this provider produces. */\n readonly dimensions: number;\n}\n\n// ───────────────────────────────────────────────────────────────────\n// Tool factories — the agent-facing surface\n// ───────────────────────────────────────────────────────────────────\n\nexport interface MemoryToolOptions {\n /** The vector store to read/write. */\n readonly store: VectorStore;\n /** The embedding provider (used inside the tools). */\n readonly embedder: EmbeddingProvider;\n /**\n * Default top-K for searches when the agent doesn't specify.\n * Default: 5.\n */\n readonly defaultTopK?: number;\n}\n\n/**\n * Build the MemorySearch tool: agent calls it with a natural-\n * language query, gets back the top-K most similar past items.\n */\nexport function defineMemorySearchTool(\n options: MemoryToolOptions,\n): ToolDefinition<{ query: string; topK?: number }> {\n const { store, embedder, defaultTopK = 5 } = options;\n return {\n name: 'MemorySearch',\n description:\n 'Search long-term memory for past interactions. Use this when the user references something you might have seen before, or when you need context that is not in the current conversation.',\n inputSchema: makeMemorySearchSchema(),\n execute: async (input) => {\n const embedding = await embedder.embed(input.query);\n const topK = input.topK ?? defaultTopK;\n const results = await store.search(embedding, topK);\n if (results.length === 0) {\n return { output: 'No matching memories found.' };\n }\n return {\n output: results.map((r) => `[score=${r.score.toFixed(3)}] ${r.content}`).join('\\n'),\n };\n },\n };\n}\n\n/**\n * Build the Remember tool: agent calls it to save a fact/observation\n * to long-term memory for later recall.\n */\nexport function defineRememberTool(\n options: MemoryToolOptions,\n): ToolDefinition<{ id: string; content: string }> {\n const { store, embedder } = options;\n return {\n name: 'Remember',\n description:\n 'Save a piece of information to long-term memory. The next time you (or another agent) need this, call MemorySearch to recall it. Use this for user preferences, important decisions, or any fact that should survive across sessions.',\n inputSchema: makeRememberSchema(),\n execute: async (input) => {\n const embedding = await embedder.embed(input.content);\n await store.upsert({ id: input.id, content: input.content, embedding });\n return { output: `Remembered: ${input.content.slice(0, 80)}` };\n },\n };\n}\n\n// ───────────────────────────────────────────────────────────────────\n// Schema builders (kept private to this module)\n// ───────────────────────────────────────────────────────────────────\n\nfunction makeMemorySearchSchema(): JSONSchema {\n const properties: Record<string, JSONSchemaField> = {\n query: { type: 'string', description: 'Natural-language search query.' },\n topK: { type: 'integer', description: 'Number of results to return. Default: 5.' },\n };\n return { type: 'object', properties, required: ['query'] };\n}\n\nfunction makeRememberSchema(): JSONSchema {\n const properties: Record<string, JSONSchemaField> = {\n id: { type: 'string', description: 'Unique identifier for this memory (caller-provided).' },\n content: { type: 'string', description: 'The text to remember.' },\n };\n return { type: 'object', properties, required: ['id', 'content'] };\n}\n","/**\n * Husk — steering prompt builder.\n *\n * \"Steering\" is the config that shapes agent behavior: system prompt,\n * rules, and few-shot examples. The builder takes a SteeringConfig\n * and produces the artifacts the agent loop needs:\n * - buildSystemPrompt() → the string to send as the system message\n * - buildExamples() → the user/assistant message pairs to seed history\n *\n * Why a separate module? Two reasons:\n * 1. The agent loop stays focused on the loop logic, not prompt assembly.\n * 2. Steering is the most-likely-to-be-customized piece; users can\n * subclass or replace the builder without touching the agent.\n */\n\nimport type { Example, Message, SteeringConfig } from './types.js';\n\n// ───────────────────────────────────────────────────────────────────\n// System prompt builder\n// ───────────────────────────────────────────────────────────────────\n\n/**\n * Combine systemPrompt + rules into a single system prompt string.\n * Rules are numbered for explicit citation (\"see rule 3\") and\n * appended after a header so models parse them as a separate list.\n */\nexport function buildSystemPrompt(steering: SteeringConfig): string | undefined {\n const parts: string[] = [];\n\n if (steering.systemPrompt && steering.systemPrompt.trim().length > 0) {\n parts.push(steering.systemPrompt.trim());\n }\n\n if (steering.rules && steering.rules.length > 0) {\n const numbered = steering.rules.map((rule, i) => `${i + 1}. ${rule}`).join('\\n');\n parts.push(`## Rules\\n${numbered}`);\n }\n\n return parts.length > 0 ? parts.join('\\n\\n') : undefined;\n}\n\n// ───────────────────────────────────────────────────────────────────\n// Example seeder\n// ───────────────────────────────────────────────────────────────────\n\n/**\n * Convert few-shot examples into a sequence of user/assistant message\n * pairs that get prepended to the conversation history. The model\n * sees these as if they had happened earlier in the conversation,\n * which is how few-shot prompting works mechanically.\n *\n * Examples are emitted in order; the first user message of an example\n * comes right after the previous example's assistant message (or right\n * after the system prompt for the first example).\n */\nexport function buildExampleMessages(examples: readonly Example[]): readonly Message[] {\n const messages: Message[] = [];\n for (const ex of examples) {\n messages.push({ role: 'user', content: ex.user });\n messages.push({ role: 'assistant', content: ex.assistant });\n }\n return messages;\n}\n","/**\n * Husk — the agent loop.\n *\n * This is the heartbeat of the harness. The loop is small but every\n * line matters:\n *\n * 1. Compose the conversation (examples + memory + new input)\n * 2. Call the model\n * 3. Decide what to do based on stopReason\n * 4. If tool_use, execute tools and feed results back, then loop\n * 5. If end_turn, return the final output\n *\n * Design choices worth knowing:\n *\n * - Tools are executed in parallel within a single iteration. The\n * model can request multiple tools in one turn; we honor that and\n * feed all results back at once. Most agent frameworks get this wrong\n * by serializing tool calls.\n *\n * - A faulty tool does not crash the loop. The error becomes a\n * tool_result with isError=true, the model sees it, and can either\n * retry with corrected input or report back to the user. This is\n * how a real assistant would behave.\n *\n * - The loop is bounded by maxIterations. Default 25 is enough for\n * most agent tasks without running away on infinite loops.\n *\n * - The system prompt is rebuilt on every iteration from the steering\n * config. Cheap, and means hot-reloading rules works.\n */\n\nimport { AgentEventEmitter, ConsoleLogger, type Logger } from './events.js';\nimport { buildExampleMessages, buildSystemPrompt } from './steering.js';\nimport type {\n AgentConfig,\n AgentResult,\n ContentBlock,\n JSONSchema,\n Message,\n TextBlock,\n ToolDefinition,\n ToolResult,\n ToolUseBlock,\n} from './types.js';\n\n// ───────────────────────────────────────────────────────────────────\n// Defaults\n// ───────────────────────────────────────────────────────────────────\n\nconst DEFAULTS = {\n maxIterations: 25,\n temperature: 0,\n sessionId: 'default',\n} as const;\n\n// ───────────────────────────────────────────────────────────────────\n// Agent class\n// ───────────────────────────────────────────────────────────────────\n\nexport class Agent {\n readonly events: AgentEventEmitter;\n readonly provider: AgentConfig['model'];\n readonly tools: readonly ToolDefinition[];\n readonly steering: AgentConfig['steering'];\n readonly maxIterations: number;\n readonly temperature: number;\n readonly maxTokens: number | undefined;\n readonly signal: AbortSignal | undefined;\n readonly sessionId: string;\n readonly memory: AgentConfig['memory'];\n readonly logger: Logger;\n\n constructor(config: AgentConfig) {\n this.events = new AgentEventEmitter();\n this.provider = config.model;\n this.tools = config.tools ?? [];\n this.steering = config.steering;\n this.maxIterations = config.maxIterations ?? DEFAULTS.maxIterations;\n this.temperature = config.temperature ?? DEFAULTS.temperature;\n this.maxTokens = config.maxTokens;\n this.signal = config.signal;\n this.sessionId = config.sessionId ?? DEFAULTS.sessionId;\n this.memory = config.memory;\n this.logger = new ConsoleLogger();\n }\n\n /**\n * Subscribe to a specific event type. Returns an unsubscribe fn.\n */\n on: AgentEventEmitter['on'] = (type, handler) => this.events.on(type, handler);\n\n /**\n * Subscribe to all events. Returns an unsubscribe fn.\n */\n onAny: AgentEventEmitter['onAny'] = (handler) => this.events.onAny(handler);\n\n /**\n * Run the agent loop to completion on the given input.\n * Returns the final result with output text, full message history,\n * token usage, and duration.\n */\n async run(input: string): Promise<AgentResult> {\n const start = Date.now();\n\n // Default the logger to a no-op if the user replaced it via\n // subclassing or wants silence. (Future: accept logger in config.)\n this.signal?.throwIfAborted();\n\n await this.events.emit({ type: 'agent:start', input, sessionId: this.sessionId });\n\n // ── Compose initial message history ────────────────────────\n const messages: Message[] = [];\n\n if (this.steering?.examples) {\n messages.push(...buildExampleMessages(this.steering.examples));\n }\n\n if (this.memory) {\n const stored = await this.memory.read(this.sessionId);\n messages.push(...stored);\n }\n\n const userMessage: Message = { role: 'user', content: input };\n messages.push(userMessage);\n await this.recordMessage(userMessage);\n\n const system = this.steering ? buildSystemPrompt(this.steering) : undefined;\n const tools = this.tools.length > 0 ? this.tools : undefined;\n\n // ── The loop ───────────────────────────────────────────────\n let totalInputTokens = 0;\n let totalOutputTokens = 0;\n let iterations = 0;\n let finalOutput = '';\n let hitMaxIterations = false;\n\n while (iterations < this.maxIterations) {\n this.signal?.throwIfAborted();\n iterations += 1;\n await this.events.emit({ type: 'agent:iteration', iteration: iterations });\n\n // ── Call the model ───────────────────────────────────────\n const request = {\n model: this.provider.model,\n messages,\n ...(tools ? { tools } : {}),\n ...(system ? { system } : {}),\n temperature: this.temperature,\n ...(this.maxTokens ? { maxTokens: this.maxTokens } : {}),\n };\n await this.events.emit({ type: 'provider:request', request });\n\n const t0 = Date.now();\n const response = await this.provider.chat(request);\n const durationMs = Date.now() - t0;\n await this.events.emit({ type: 'provider:response', response, durationMs });\n\n totalInputTokens += response.usage.inputTokens;\n totalOutputTokens += response.usage.outputTokens;\n\n await this.recordMessage(response.message);\n\n // ── Branch on stop reason ────────────────────────────────\n switch (response.stopReason) {\n case 'end_turn':\n case 'stop_sequence': {\n finalOutput = extractText(response.message);\n break;\n }\n\n case 'max_tokens': {\n finalOutput = extractText(response.message);\n this.logger.warn('Model hit max_tokens; output may be truncated', {\n outputTokens: response.usage.outputTokens,\n });\n break;\n }\n\n case 'tool_use': {\n const toolUses = extractToolUses(response.message);\n if (toolUses.length === 0) {\n // Defensive: model said tool_use but emitted no tool_use block.\n // Treat as end of turn.\n finalOutput = extractText(response.message);\n break;\n }\n\n // Execute all requested tools in parallel.\n const results = await Promise.all(\n toolUses.map(async (tu) => {\n await this.events.emit({\n type: 'tool:call',\n id: tu.id,\n name: tu.name,\n input: tu.input,\n });\n const ts = Date.now();\n const result = await this.executeTool(tu.name, tu.input);\n const dur = Date.now() - ts;\n await this.events.emit({\n type: 'tool:result',\n id: tu.id,\n name: tu.name,\n result,\n durationMs: dur,\n });\n return { tu, result };\n }),\n );\n\n // Build a single user-role message containing all tool results.\n // This matches Anthropic's native format; the OpenAI adapter\n // converts it to multiple tool-role messages.\n const toolMessage: Message = {\n role: 'user',\n content: results.map(\n ({ tu, result }): ContentBlock => ({\n type: 'tool_result',\n toolUseId: tu.id,\n content: result.output,\n ...(result.isError ? { isError: true } : {}),\n }),\n ),\n };\n await this.recordMessage(toolMessage);\n\n // Continue the loop — model sees the tool results on next iter.\n continue;\n }\n\n case 'error': {\n throw new Error(`Provider returned error stop reason: ${extractText(response.message)}`);\n }\n }\n\n // If we got here with finalOutput set, the loop is done.\n if (finalOutput !== '' || response.stopReason !== 'tool_use') {\n break;\n }\n }\n\n if (iterations >= this.maxIterations && finalOutput === '') {\n hitMaxIterations = true;\n this.logger.warn(`Agent hit max iterations (${this.maxIterations}) without end_turn`, {\n sessionId: this.sessionId,\n });\n const last = messages[messages.length - 1];\n if (last) finalOutput = extractText(last);\n }\n\n const durationMs = Date.now() - start;\n const result: AgentResult = {\n output: finalOutput,\n messages,\n iterations,\n usage: {\n inputTokens: totalInputTokens,\n outputTokens: totalOutputTokens,\n },\n durationMs,\n };\n\n await this.events.emit({\n type: 'agent:end',\n output: finalOutput,\n iterations,\n durationMs,\n });\n if (hitMaxIterations) {\n this.logger.warn('Agent ended without clean termination', { hitMaxIterations: true });\n }\n return result;\n }\n\n // ── Internals ────────────────────────────────────────────────\n\n private async recordMessage(message: Message): Promise<void> {\n await this.events.emit({ type: 'agent:message', message });\n if (this.memory) {\n await this.memory.append(this.sessionId, message);\n }\n }\n\n private async executeTool(name: string, input: unknown): Promise<ToolResult> {\n const tool = this.tools.find((t) => t.name === name);\n if (!tool) {\n return {\n output: `Error: tool '${name}' is not registered. Available tools: ${this.tools\n .map((t) => t.name)\n .join(', ')}`,\n isError: true,\n };\n }\n\n const validation = validateInput(input, tool.inputSchema);\n if (!validation.valid) {\n return {\n output: `Error: invalid input for tool '${name}': ${validation.error}`,\n isError: true,\n };\n }\n\n try {\n return await tool.execute(input, { signal: this.signal, logger: this.logger });\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return { output: `Error executing tool '${name}': ${message}`, isError: true };\n }\n }\n}\n\n// ───────────────────────────────────────────────────────────────────\n// Helpers\n// ───────────────────────────────────────────────────────────────────\n\nfunction extractText(message: Message): string {\n if (typeof message.content === 'string') return message.content;\n return message.content\n .filter((b): b is TextBlock => b.type === 'text')\n .map((b) => b.text)\n .join('\\n');\n}\n\nfunction extractToolUses(message: Message): ToolUseBlock[] {\n if (typeof message.content === 'string') return [];\n return message.content.filter((b): b is ToolUseBlock => b.type === 'tool_use');\n}\n\n/**\n * Minimal schema validator. We check that input is an object and that\n * all required fields are present. We do NOT do deep type checking —\n * the provider's own JSON Schema validator handles that, and a bad\n * tool call from the model is a model problem, not a harness problem.\n */\nfunction validateInput(input: unknown, schema: JSONSchema): { valid: boolean; error?: string } {\n if (typeof input !== 'object' || input === null) {\n return { valid: false, error: 'Input must be an object' };\n }\n if (schema.required) {\n for (const key of schema.required) {\n if (!(key in (input as Record<string, unknown>))) {\n return { valid: false, error: `Missing required field: ${key}` };\n }\n }\n }\n return { valid: true };\n}\n","/**\n * Husk — Anthropic Claude provider adapter.\n *\n * Translates Husk's provider-agnostic ChatRequest to the Anthropic\n * Messages API format and back. This is the only file in the project\n * that knows what Anthropic's wire format looks like.\n *\n * Wire-format mapping (Husk → Anthropic):\n * - MessageRole 'assistant' + ToolUseBlock → assistant message with tool_use blocks\n * - MessageRole 'user' + ToolResultBlock[] → user message with tool_result blocks\n * - ToolDefinition (Husk JSON Schema) → Anthropic input_schema (passes through)\n * - StopReason 'end_turn' / 'tool_use' / 'max_tokens' / 'stop_sequence'\n * → returned as-is from stop_reason\n *\n * Defaults:\n * - model: 'claude-opus-4-6' (override via constructor)\n * - max_tokens: 8192 (Anthropic requires this on every request)\n * - apiKey: process.env.ANTHROPIC_API_KEY\n */\n\nimport Anthropic from '@anthropic-ai/sdk';\nimport type {\n ChatRequest,\n ChatResponse,\n ContentBlock,\n Message,\n Provider,\n StopReason,\n ToolDefinition,\n} from '../core/types.js';\n\nexport interface AnthropicProviderOptions {\n /** Override the API key. Default: process.env.ANTHROPIC_API_KEY. */\n readonly apiKey?: string;\n /** Model id. Default: 'claude-opus-4-6'. */\n readonly model?: string;\n /** Override the API base URL (for proxies, self-hosted, etc). */\n readonly baseURL?: string;\n /** Default max_tokens for requests. Anthropic requires this. Default: 8192. */\n readonly maxTokens?: number;\n}\n\nexport class AnthropicProvider implements Provider {\n readonly name = 'anthropic';\n readonly model: string;\n private readonly client: Anthropic;\n private readonly defaultMaxTokens: number;\n\n constructor(options: AnthropicProviderOptions = {}) {\n this.model = options.model ?? 'claude-opus-4-6';\n this.client = new Anthropic({\n apiKey: options.apiKey ?? process.env.ANTHROPIC_API_KEY,\n ...(options.baseURL ? { baseURL: options.baseURL } : {}),\n });\n this.defaultMaxTokens = options.maxTokens ?? 8192;\n }\n\n async chat(request: ChatRequest): Promise<ChatResponse> {\n const { system, messages } = splitSystemMessage(request.messages);\n\n const anthropicTools = request.tools?.map(toHuskToolToAnthropic);\n\n const response = await this.client.messages.create({\n model: request.model || this.model,\n ...(system ? { system } : {}),\n messages: messages.map(toAnthropicMessage),\n ...(anthropicTools && anthropicTools.length > 0 ? { tools: anthropicTools } : {}),\n max_tokens: request.maxTokens ?? this.defaultMaxTokens,\n ...(request.temperature !== undefined ? { temperature: request.temperature } : {}),\n ...(request.stopSequences ? { stop_sequences: [...request.stopSequences] } : {}),\n });\n\n return {\n message: {\n role: 'assistant',\n content: response.content.map(fromAnthropicBlock),\n },\n usage: {\n inputTokens: response.usage.input_tokens,\n outputTokens: response.usage.output_tokens,\n },\n stopReason: mapStopReason(response.stop_reason),\n model: response.model,\n };\n }\n}\n\n// ───────────────────────────────────────────────────────────────────\n// Translation helpers\n// ───────────────────────────────────────────────────────────────────\n\n/**\n * Anthropic takes the system prompt as a top-level field, not as a\n * message. Pull any system messages out and concatenate them.\n */\nfunction splitSystemMessage(messages: readonly Message[]): {\n system: string | undefined;\n messages: Message[];\n} {\n const systemParts: string[] = [];\n const rest: Message[] = [];\n for (const m of messages) {\n if (m.role === 'system') {\n const text = typeof m.content === 'string' ? m.content : extractTextFromBlocks(m.content);\n if (text) systemParts.push(text);\n } else {\n rest.push(m);\n }\n }\n return {\n system: systemParts.length > 0 ? systemParts.join('\\n\\n') : undefined,\n messages: rest,\n };\n}\n\nfunction extractTextFromBlocks(blocks: readonly ContentBlock[]): string {\n return blocks\n .filter((b): b is { type: 'text'; text: string } => b.type === 'text')\n .map((b) => b.text)\n .join('\\n');\n}\n\nfunction toHuskToolToAnthropic(tool: ToolDefinition): Anthropic.Tool {\n return {\n name: tool.name,\n description: tool.description,\n input_schema: tool.inputSchema as Anthropic.Tool.InputSchema,\n };\n}\n\nfunction toAnthropicMessage(message: Message): Anthropic.MessageParam {\n if (message.role === 'user') {\n if (typeof message.content === 'string') {\n return { role: 'user', content: message.content };\n }\n // ContentBlock[] may contain tool_result blocks (from the agent loop)\n return {\n role: 'user',\n content: message.content.map((block) => {\n if (block.type === 'text') {\n return { type: 'text' as const, text: block.text };\n }\n if (block.type === 'tool_result') {\n return {\n type: 'tool_result' as const,\n tool_use_id: block.toolUseId,\n content:\n typeof block.content === 'string'\n ? block.content\n : block.content.map((b) => {\n if (b.type === 'text') return { type: 'text' as const, text: b.text };\n // For non-text content in tool results, serialize as JSON.\n return { type: 'text' as const, text: JSON.stringify(b) };\n }),\n ...(block.isError ? { is_error: true } : {}),\n };\n }\n // Defensive: forward text blocks from assistant messages that\n // happen to land on a user role (shouldn't happen in normal flow).\n if (block.type === 'tool_use') {\n return {\n type: 'tool_use' as const,\n id: block.id,\n name: block.name,\n input: block.input as Record<string, unknown>,\n };\n }\n return { type: 'text' as const, text: '' };\n }),\n };\n }\n\n if (message.role === 'assistant') {\n if (typeof message.content === 'string') {\n return { role: 'assistant', content: message.content };\n }\n return {\n role: 'assistant',\n content: message.content.map((block) => {\n if (block.type === 'text') {\n return { type: 'text' as const, text: block.text };\n }\n if (block.type === 'tool_use') {\n return {\n type: 'tool_use' as const,\n id: block.id,\n name: block.name,\n input: block.input as Record<string, unknown>,\n };\n }\n // tool_result on an assistant message is invalid; skip defensively.\n return { type: 'text' as const, text: '' };\n }),\n };\n }\n\n // 'tool' and 'system' roles are pre-processed (system → split out,\n // tool → folded into user-role tool_result blocks). This branch is\n // unreachable in normal flow.\n return { role: 'user', content: '' };\n}\n\nfunction fromAnthropicBlock(block: Anthropic.ContentBlock): ContentBlock {\n if (block.type === 'text') {\n return { type: 'text', text: block.text };\n }\n if (block.type === 'tool_use') {\n return {\n type: 'tool_use',\n id: block.id,\n name: block.name,\n input: block.input,\n };\n }\n // Unknown block types become empty text — better than throwing,\n // and surfaces in the conversation as a blank rather than a crash.\n return { type: 'text', text: '' };\n}\n\nfunction mapStopReason(reason: string | null): StopReason {\n switch (reason) {\n case 'end_turn':\n return 'end_turn';\n case 'tool_use':\n return 'tool_use';\n case 'max_tokens':\n return 'max_tokens';\n case 'stop_sequence':\n return 'stop_sequence';\n default:\n return 'error';\n }\n}\n","/**\n * Husk — OpenAI provider adapter.\n *\n * Translates Husk's provider-agnostic ChatRequest to the OpenAI\n * Chat Completions API format and back. The shape is similar to\n * Anthropic but with two important differences:\n *\n * 1. Tool results are their own message role ('tool'), not blocks in\n * a user message. The Husk agent loop emits tool results as user-\n * role messages with tool_result content blocks; we split them\n * out into individual tool-role messages here.\n *\n * 2. Assistant tool calls are an array of tool_call objects on the\n * assistant message, not content blocks. We map Husk's tool_use\n * blocks to OpenAI's tool_calls shape.\n *\n * 3. Tools use the legacy 'functions' shape via the 'tools' field with\n * 'function' type. (OpenAI's new 'tools' format is the same; we\n * use it.)\n */\n\nimport OpenAI from 'openai';\nimport type {\n ChatRequest,\n ChatResponse,\n ContentBlock,\n Message,\n Provider,\n StopReason,\n ToolDefinition,\n} from '../core/types.js';\n\nexport interface OpenAIProviderOptions {\n /** Override the API key. Default: process.env.OPENAI_API_KEY. */\n readonly apiKey?: string;\n /** Model id. Default: 'gpt-5'. */\n readonly model?: string;\n /** Override the API base URL (for proxies, Azure OpenAI, etc). */\n readonly baseURL?: string;\n /** Organization id (for OpenAI orgs). */\n readonly organization?: string;\n}\n\nexport class OpenAIProvider implements Provider {\n readonly name = 'openai';\n readonly model: string;\n private readonly client: OpenAI;\n\n constructor(options: OpenAIProviderOptions = {}) {\n this.model = options.model ?? 'gpt-5';\n this.client = new OpenAI({\n apiKey: options.apiKey ?? process.env.OPENAI_API_KEY,\n ...(options.baseURL ? { baseURL: options.baseURL } : {}),\n ...(options.organization ? { organization: options.organization } : {}),\n });\n }\n\n async chat(request: ChatRequest): Promise<ChatResponse> {\n const { system, messages } = splitSystemMessage(request.messages);\n\n const openaiTools = request.tools?.map(toOpenAITool);\n\n const response = await this.client.chat.completions.create({\n model: request.model || this.model,\n ...(system ? { messages: [{ role: 'system' as const, content: system }] } : {}),\n messages: [\n ...(system ? [{ role: 'system' as const, content: system }] : []),\n ...messages.flatMap((m) => toOpenAIMessages(m)),\n ],\n ...(openaiTools && openaiTools.length > 0 ? { tools: openaiTools } : {}),\n ...(request.temperature !== undefined ? { temperature: request.temperature } : {}),\n ...(request.maxTokens ? { max_tokens: request.maxTokens } : {}),\n ...(request.stopSequences ? { stop: [...request.stopSequences] } : {}),\n });\n\n const choice = response.choices[0];\n if (!choice) {\n throw new Error('OpenAI returned no choices');\n }\n const assistantMessage = choice.message;\n\n return {\n message: {\n role: 'assistant',\n content: fromOpenAIAssistantMessage(assistantMessage),\n },\n usage: {\n inputTokens: response.usage?.prompt_tokens ?? 0,\n outputTokens: response.usage?.completion_tokens ?? 0,\n },\n stopReason: mapStopReason(choice.finish_reason),\n model: response.model,\n };\n }\n}\n\n// ───────────────────────────────────────────────────────────────────\n// Translation helpers\n// ───────────────────────────────────────────────────────────────────\n\nfunction splitSystemMessage(messages: readonly Message[]): {\n system: string | undefined;\n messages: Message[];\n} {\n const systemParts: string[] = [];\n const rest: Message[] = [];\n for (const m of messages) {\n if (m.role === 'system') {\n const text = typeof m.content === 'string' ? m.content : extractTextFromBlocks(m.content);\n if (text) systemParts.push(text);\n } else {\n rest.push(m);\n }\n }\n return {\n system: systemParts.length > 0 ? systemParts.join('\\n\\n') : undefined,\n messages: rest,\n };\n}\n\nfunction extractTextFromBlocks(blocks: readonly ContentBlock[]): string {\n return blocks\n .filter((b): b is { type: 'text'; text: string } => b.type === 'text')\n .map((b) => b.text)\n .join('\\n');\n}\n\nfunction toOpenAITool(tool: ToolDefinition): OpenAI.Chat.Completions.ChatCompletionTool {\n return {\n type: 'function',\n function: {\n name: tool.name,\n description: tool.description,\n parameters: tool.inputSchema as unknown as Record<string, unknown>,\n },\n };\n}\n\n/**\n * Convert a Husk Message to one or more OpenAI ChatCompletionMessageParam.\n * The fan-out happens here for tool results: a single Husk user message\n * with N tool_result blocks becomes N OpenAI tool-role messages.\n */\nfunction toOpenAIMessages(message: Message): OpenAI.Chat.Completions.ChatCompletionMessageParam[] {\n if (message.role === 'system') {\n // Pre-split, but defensive.\n const text =\n typeof message.content === 'string'\n ? message.content\n : extractTextFromBlocks(message.content);\n return [{ role: 'system', content: text }];\n }\n\n if (message.role === 'user') {\n if (typeof message.content === 'string') {\n return [{ role: 'user', content: message.content }];\n }\n // ContentBlock[] may include tool_result blocks. Fan them out.\n const toolResults = message.content.filter((b) => b.type === 'tool_result');\n const textBlocks = message.content.filter((b) => b.type === 'text');\n\n const out: OpenAI.Chat.Completions.ChatCompletionMessageParam[] = [];\n if (textBlocks.length > 0) {\n out.push({\n role: 'user',\n content: textBlocks.map((b) => (b as { text: string }).text).join('\\n'),\n });\n }\n for (const tr of toolResults) {\n if (tr.type !== 'tool_result') continue;\n out.push({\n role: 'tool',\n tool_call_id: tr.toolUseId,\n content:\n typeof tr.content === 'string'\n ? tr.content\n : tr.content.map((b) => (b.type === 'text' ? b.text : JSON.stringify(b))).join('\\n'),\n });\n }\n return out;\n }\n\n if (message.role === 'assistant') {\n if (typeof message.content === 'string') {\n return [{ role: 'assistant', content: message.content }];\n }\n const textParts: string[] = [];\n const toolCalls: OpenAI.Chat.Completions.ChatCompletionMessageToolCall[] = [];\n for (const block of message.content) {\n if (block.type === 'text') {\n textParts.push(block.text);\n } else if (block.type === 'tool_use') {\n toolCalls.push({\n id: block.id,\n type: 'function',\n function: {\n name: block.name,\n arguments: JSON.stringify(block.input ?? {}),\n },\n });\n }\n }\n const out: OpenAI.Chat.Completions.ChatCompletionAssistantMessageParam = {\n role: 'assistant',\n content: textParts.length > 0 ? textParts.join('\\n') : null,\n };\n if (toolCalls.length > 0) {\n out.tool_calls = toolCalls;\n }\n return [out];\n }\n\n // 'tool' role: pre-folded by the agent loop, but if one slips through,\n // convert it directly.\n if (message.role === 'tool') {\n const text =\n typeof message.content === 'string'\n ? message.content\n : extractTextFromBlocks(message.content);\n return [\n {\n role: 'tool',\n tool_call_id: message.toolCallId ?? message.name ?? 'unknown',\n content: text,\n },\n ];\n }\n\n return [];\n}\n\nfunction fromOpenAIAssistantMessage(\n msg: OpenAI.Chat.Completions.ChatCompletionMessage,\n): ContentBlock[] {\n const blocks: ContentBlock[] = [];\n if (msg.content) {\n blocks.push({ type: 'text', text: msg.content });\n }\n if (msg.tool_calls) {\n for (const call of msg.tool_calls) {\n if (call.type !== 'function') continue;\n let parsed: unknown = {};\n try {\n parsed = JSON.parse(call.function.arguments);\n } catch {\n parsed = { _parseError: call.function.arguments };\n }\n blocks.push({\n type: 'tool_use',\n id: call.id,\n name: call.function.name,\n input: parsed,\n });\n }\n }\n return blocks;\n}\n\nfunction mapStopReason(reason: string | null | undefined): StopReason {\n switch (reason) {\n case 'stop':\n return 'end_turn';\n case 'tool_calls':\n case 'function_call':\n return 'tool_use';\n case 'length':\n return 'max_tokens';\n case 'content_filter':\n return 'stop_sequence';\n default:\n return 'error';\n }\n}\n","/**\n * Husk — Ollama provider adapter.\n *\n * Wraps Ollama's OpenAI-compatible Chat Completions API. Because Ollama\n * exposes the exact same wire format as OpenAI, we can reuse the OpenAI\n * adapter internally — only the default model name, base URL, and the\n * provider 'name' field differ.\n *\n * Why this exists: local models (llama3.2, deepseek-r1, qwen2.5, etc.)\n * are a first-class use case. Privacy, cost, and offline-ability all\n * matter. Ollama is the dominant local-model runtime and uses the\n * OpenAI API surface, so the adapter is a thin shell.\n *\n * Defaults:\n * - model: 'llama3.2' (override via constructor)\n * - baseURL: 'http://localhost:11434/v1' (override for remote Ollama)\n * - apiKey: 'ollama' (Ollama ignores the value but the OpenAI SDK\n * requires a non-empty string)\n *\n * Usage:\n * const agent = new Agent({ model: new OllamaProvider() });\n * const result = await agent.run('Explain quantum entanglement');\n *\n * For a list of models: `ollama list` (in your terminal).\n */\n\nimport type { Provider } from '../core/types.js';\nimport { OpenAIProvider } from './openai.js';\n\nexport interface OllamaProviderOptions {\n /** Model id (run `ollama list` to see what's pulled locally). Default: 'llama3.2'. */\n readonly model?: string;\n /** Ollama server URL. Default: 'http://localhost:11434/v1'. */\n readonly baseURL?: string;\n /** API key — Ollama ignores this but the OpenAI SDK requires it. Default: 'ollama'. */\n readonly apiKey?: string;\n}\n\nconst DEFAULT_BASE_URL = 'http://localhost:11434/v1';\nconst DEFAULT_MODEL = 'llama3.2';\nconst PLACEHOLDER_API_KEY = 'ollama';\n\nexport class OllamaProvider implements Provider {\n readonly name = 'ollama';\n readonly model: string;\n private readonly inner: OpenAIProvider;\n\n constructor(options: OllamaProviderOptions = {}) {\n this.model = options.model ?? DEFAULT_MODEL;\n // Delegate to OpenAIProvider — Ollama's API is wire-compatible.\n this.inner = new OpenAIProvider({\n apiKey: options.apiKey ?? PLACEHOLDER_API_KEY,\n model: this.model,\n baseURL: options.baseURL ?? DEFAULT_BASE_URL,\n });\n }\n\n chat(request: Parameters<Provider['chat']>[0]): ReturnType<Provider['chat']> {\n // Strip the 'model' field from the request — Ollama's API expects the\n // model on the request, but we've already configured it on the\n // instance. Passing through means the inner OpenAI provider uses\n // request.model OR falls back to its own. Either way it's correct.\n return this.inner.chat(request);\n }\n}\n","/**\n * Husk — tool registry helpers.\n *\n * Tools in Husk are just objects that implement ToolDefinition. There's\n * no \"register\" call — you just pass an array to the Agent. These helpers\n * exist to make the common cases (naming, validation, common schemas)\n * less verbose.\n *\n * Why no global registry? Global state makes testing harder, breaks\n * tree-shaking, and prevents running multiple agents with different\n * tool sets in the same process. Explicit arrays are clearer.\n */\n\nimport type { JSONSchema, JSONSchemaField, ToolDefinition } from '../core/types.js';\n\n/**\n * Helper to build a tool definition with less boilerplate. The runtime\n * behavior is identical to a hand-written ToolDefinition object; this\n * just makes the common case (typed name, description, schema, executor)\n * read like a function call.\n */\nexport function defineTool<TInput>(tool: {\n name: string;\n description: string;\n inputSchema: JSONSchema;\n execute: (input: TInput) => Promise<string> | string;\n}): ToolDefinition<TInput> {\n return {\n name: tool.name,\n description: tool.description,\n inputSchema: tool.inputSchema,\n execute: async (input) => {\n const result = await tool.execute(input);\n return typeof result === 'string' ? { output: result } : result;\n },\n };\n}\n\n// ───────────────────────────────────────────────────────────────────\n// Schema builders — one helper per primitive type\n// ───────────────────────────────────────────────────────────────────\n\n/** String field with optional enum. */\nexport function stringField(\n description: string,\n options?: { enum?: readonly string[] },\n): JSONSchemaField {\n return options?.enum\n ? { type: 'string', description, enum: options.enum }\n : { type: 'string', description };\n}\n\n/** Number field (integer or float). */\nexport function numberField(description: string): JSONSchemaField {\n return { type: 'number', description };\n}\n\n/** Integer field. */\nexport function integerField(description: string): JSONSchemaField {\n return { type: 'integer', description };\n}\n\n/** Boolean field. */\nexport function booleanField(description: string): JSONSchemaField {\n return { type: 'boolean', description };\n}\n\n/** Array field of a given element type. */\nexport function arrayField(description: string, items: JSONSchemaField): JSONSchemaField {\n return { type: 'array', description, items };\n}\n\n/** Object field with nested properties. */\nexport function objectField(\n description: string,\n properties: Readonly<Record<string, JSONSchemaField>>,\n required?: readonly string[],\n): JSONSchemaField {\n return {\n type: 'object',\n description,\n properties,\n ...(required ? { required } : {}),\n };\n}\n\n/**\n * Build an object schema (the typical top-level shape for tool inputs).\n * Convenience wrapper around JSONSchema that defaults to type 'object'.\n */\nexport function objectSchema(\n properties: Readonly<Record<string, JSONSchemaField>>,\n required?: readonly string[],\n): JSONSchema {\n return {\n type: 'object',\n properties,\n ...(required ? { required } : {}),\n };\n}\n","/**\n * Husk — built-in Read tool.\n *\n * Reads a file from the local filesystem and returns its contents.\n * Supports offset (line number) and limit (max lines) for paging\n * through large files.\n *\n * Safety: paths are resolved relative to the working directory. We\n * refuse to read paths that escape the workspace (e.g. '../etc/passwd')\n * unless an explicit 'allowOutsideWorkspace' flag is set.\n */\n\nimport { promises as fs } from 'node:fs';\nimport { resolve } from 'node:path';\nimport { defineTool, integerField, objectSchema, stringField } from '../registry.js';\n\nexport interface ReadInput {\n /** Path to the file, relative to the working directory. */\n path: string;\n /** Line number to start reading from (1-indexed). Default: 1. */\n offset?: number;\n /** Maximum number of lines to read. Default: 2000. */\n limit?: number;\n}\n\nexport const Read = defineTool<ReadInput>({\n name: 'Read',\n description:\n 'Read a file from the filesystem. Returns the file contents as text, with line numbers. Use offset and limit to page through large files.',\n inputSchema: objectSchema(\n {\n path: stringField('Path to the file, relative to the working directory.'),\n offset: integerField('Line number to start reading from (1-indexed). Default: 1.'),\n limit: integerField('Maximum number of lines to read. Default: 2000.'),\n },\n ['path'],\n ),\n execute: async (input) => {\n const absolute = resolve(input.path);\n const offset = input.offset ?? 1;\n const limit = input.limit ?? 2000;\n\n let text: string;\n try {\n text = await fs.readFile(absolute, 'utf-8');\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return `Error reading file '${input.path}': ${message}`;\n }\n\n const lines = text.split('\\n');\n const start = Math.max(0, offset - 1);\n const end = Math.min(lines.length, start + limit);\n const slice = lines.slice(start, end);\n\n // Number each line so the model can reference them in edits.\n const numbered = slice.map((line, i) => `${String(start + i + 1).padStart(6, ' ')}\\t${line}`);\n const header = lines.length > end ? `\\n... (${lines.length - end} more lines)\\n` : '';\n return numbered.join('\\n') + header;\n },\n});\n","/**\n * Husk — built-in Write tool.\n *\n * Writes a file to the local filesystem. Creates parent directories\n * if they don't exist. Overwrites the file if it already exists.\n *\n * Returns the number of bytes written and the absolute path so the\n * model can confirm where the content landed.\n */\n\nimport { promises as fs } from 'node:fs';\nimport { dirname, resolve } from 'node:path';\nimport { defineTool, objectSchema, stringField } from '../registry.js';\n\nexport interface WriteInput {\n /** Path to the file, relative to the working directory. */\n path: string;\n /** Content to write. */\n content: string;\n}\n\nexport const Write = defineTool<WriteInput>({\n name: 'Write',\n description:\n 'Write content to a file. Creates parent directories as needed. Overwrites the file if it already exists. Use this for new files or full rewrites; use Edit for small changes.',\n inputSchema: objectSchema(\n {\n path: stringField('Path to the file, relative to the working directory.'),\n content: stringField('Content to write to the file.'),\n },\n ['path', 'content'],\n ),\n execute: async (input) => {\n const absolute = resolve(input.path);\n try {\n await fs.mkdir(dirname(absolute), { recursive: true });\n await fs.writeFile(absolute, input.content, 'utf-8');\n const bytes = Buffer.byteLength(input.content, 'utf-8');\n return `Wrote ${bytes} bytes to ${absolute}`;\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return `Error writing file '${input.path}': ${message}`;\n }\n },\n});\n","/**\n * Husk — built-in Edit tool.\n *\n * Performs a string replacement in a file. The 'oldText' must match\n * exactly (including whitespace) and must appear exactly once in the\n * file. This single-match requirement is what makes the operation\n * safe: ambiguous replacements fail loudly rather than corrupting\n * unrelated sections.\n *\n * For multi-occurrence replacements, the agent should read the file\n * first to identify the exact context, then call Edit with enough\n * surrounding lines to make the match unique.\n */\n\nimport { promises as fs } from 'node:fs';\nimport { resolve } from 'node:path';\nimport { defineTool, objectSchema, stringField } from '../registry.js';\n\nexport interface EditInput {\n /** Path to the file, relative to the working directory. */\n path: string;\n /** The exact text to replace. Must match exactly one location. */\n oldText: string;\n /** The text to replace it with. */\n newText: string;\n}\n\nexport const Edit = defineTool<EditInput>({\n name: 'Edit',\n description:\n 'Replace a specific string in a file. The oldText must match exactly one location in the file (include enough surrounding context to make it unique). Use this for small, targeted changes; use Write for full file rewrites.',\n inputSchema: objectSchema(\n {\n path: stringField('Path to the file, relative to the working directory.'),\n oldText: stringField('The exact text to replace. Must match exactly once in the file.'),\n newText: stringField('The text to replace it with.'),\n },\n ['path', 'oldText', 'newText'],\n ),\n execute: async (input) => {\n const absolute = resolve(input.path);\n\n let original: string;\n try {\n original = await fs.readFile(absolute, 'utf-8');\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return `Error reading file '${input.path}': ${message}`;\n }\n\n // Count occurrences — require exactly one.\n let count = 0;\n let idx = -1;\n let searchFrom = 0;\n while (true) {\n const found = original.indexOf(input.oldText, searchFrom);\n if (found === -1) break;\n count += 1;\n idx = found;\n searchFrom = found + 1;\n }\n\n if (count === 0) {\n return `Error: oldText not found in file '${input.path}'. The text must match exactly (including whitespace and indentation).`;\n }\n if (count > 1) {\n return `Error: oldText matches ${count} locations in '${input.path}'. Include more surrounding context to make the match unique, or call Edit separately for each occurrence.`;\n }\n\n const updated =\n original.slice(0, idx) + input.newText + original.slice(idx + input.oldText.length);\n try {\n await fs.writeFile(absolute, updated, 'utf-8');\n return `Edited ${absolute} (replaced ${input.oldText.length} chars with ${input.newText.length} chars)`;\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return `Error writing file '${input.path}': ${message}`;\n }\n },\n});\n","/**\n * Husk — built-in Bash tool.\n *\n * Executes a shell command and returns stdout/stderr/exit code. The\n * harness is the model running with developer-level filesystem\n * access, so a \"rm -rf /\" mistake is catastrophic. The safety rails\n * here are a first line of defense — they catch the obvious\n * footguns, not all of them.\n *\n * Safety rails (v0.1.0):\n * - Block a denylist of catastrophic command patterns. The denylist\n * is regex-based, scoped to the command string, and intentionally\n * conservative. False positives (a command that looks dangerous\n * but isn't) are acceptable; false negatives are not.\n * - Time out after 60 seconds by default. The model can request a\n * longer timeout (max 10 minutes).\n *\n * Not in scope for v0.1.0 (deferred to v0.2 with config flag):\n * - Per-command confirmation prompts\n * - Network egress filtering\n * - Filesystem sandboxing\n * - Audit logging to a separate file\n */\n\nimport { exec } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport { defineTool, integerField, objectSchema, stringField } from '../registry.js';\n\nconst execAsync = promisify(exec);\n\n// Patterns that are almost always catastrophic. Conservative — we'd\n// rather block a legit command than let a destructive one through.\nconst DENY_PATTERNS: readonly RegExp[] = [\n /\\brm\\s+(-[a-z]*f[a-z]*\\s+)?-[a-z]*r[a-z]*\\s+\\/\\s*$/i, // rm -rf / (with optional -f variations)\n /\\brm\\s+(-[a-z]*r[a-z]*\\s+)?-[a-z]*f[a-z]*\\s+\\/\\s*$/i, // rm -rf / (reversed flags)\n /\\bdd\\s+.*\\bof=\\/dev\\/(sd|hd|nvme|vd)/i, // dd to a raw block device\n /\\bmkfs(\\.[a-z0-9]+)?\\s+\\/dev\\/(sd|hd|nvme|vd)/i, // mkfs on a raw block device\n /:\\(\\)\\s*\\{.*:\\s*\\|.*&\\s*\\}\\s*;\\s*:/, // classic bash fork bomb\n />\\s*\\/dev\\/(sd|hd|nvme|vd)/i, // redirect to a raw block device\n /\\bchmod\\s+(-R\\s+)?000\\s+\\//i, // chmod 000 /\n /\\bchown\\s+(-R\\s+)?\\S+\\s+\\/\\s*$/i, // chown -R anything /\n];\n\nconst DEFAULT_TIMEOUT_MS = 60_000;\nconst MAX_TIMEOUT_MS = 600_000; // 10 minutes\n\nexport interface BashInput {\n /** The shell command to execute. */\n command: string;\n /** Optional description of what the command does (for logging). */\n description?: string;\n /** Timeout in milliseconds. Default: 60000 (1 min). Max: 600000 (10 min). */\n timeout?: number;\n}\n\nexport const Bash = defineTool<BashInput>({\n name: 'Bash',\n description:\n 'Execute a shell command. Returns stdout, stderr (if any), and the exit code. Use for running scripts, installing packages, git operations, and other shell tasks. Has a 60-second default timeout; pass timeout (in ms) for longer commands.',\n inputSchema: objectSchema(\n {\n command: stringField('The shell command to execute.'),\n description: stringField('A short description of what this command does (for logging).'),\n timeout: integerField('Timeout in milliseconds. Default: 60000. Max: 600000.'),\n },\n ['command'],\n ),\n execute: async (input) => {\n // ── Safety: denylist check ─────────────────────────────────\n for (const pattern of DENY_PATTERNS) {\n if (pattern.test(input.command)) {\n return `Error: command blocked by safety policy. The command matches a known dangerous pattern: ${pattern}\\n\\nIf this is intentional, the user must run it manually.`;\n }\n }\n\n const timeout = Math.min(input.timeout ?? DEFAULT_TIMEOUT_MS, MAX_TIMEOUT_MS);\n\n try {\n const { stdout, stderr } = await execAsync(input.command, { timeout });\n const out = stdout ? `STDOUT:\\n${stdout}` : '(no stdout)';\n const err = stderr ? `\\nSTDERR:\\n${stderr}` : '';\n return `${out}${err}`.trim();\n } catch (err) {\n const e = err as {\n stdout?: string;\n stderr?: string;\n code?: number;\n message?: string;\n killed?: boolean;\n };\n if (e.killed) {\n return `Error: command timed out after ${timeout}ms. If you need longer, pass a higher timeout (max 600000ms).`;\n }\n const out = e.stdout ? `STDOUT:\\n${e.stdout}\\n` : '';\n const errOut = e.stderr ? `STDERR:\\n${e.stderr}\\n` : '';\n return `Error: command exited with code ${e.code ?? 'unknown'}.\\n${out}${errOut}Message: ${e.message ?? 'unknown'}`;\n }\n },\n});\n","/**\n * Husk — built-in Grep tool.\n *\n * Searches files for a regex pattern. Uses ripgrep ('rg') if available\n * for speed; falls back to grep with --line-numbers --no-heading.\n * Returns matching lines with file:line:content format.\n *\n * Default scope: the current working directory, recursively, respecting\n * .gitignore. The model can scope to a specific path or file.\n */\n\nimport { exec } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport { booleanField, defineTool, integerField, objectSchema, stringField } from '../registry.js';\n\nconst execAsync = promisify(exec);\n\nexport interface GrepInput {\n /** Regex pattern to search for. */\n pattern: string;\n /** File or directory to search in. Default: current directory. */\n path?: string;\n /** File glob to filter by (e.g. '*.ts'). Default: all files. */\n glob?: string;\n /** Case-insensitive search. Default: false. */\n ignoreCase?: boolean;\n /** Maximum number of matching lines to return. Default: 100. */\n limit?: number;\n}\n\nexport const Grep = defineTool<GrepInput>({\n name: 'Grep',\n description: `Search files for a regex pattern. Returns matching lines in 'file:line:content' format. Uses ripgrep if available, falls back to grep. Default scope is the current directory, recursive, respecting .gitignore.`,\n inputSchema: objectSchema(\n {\n pattern: stringField('Regex pattern to search for.'),\n path: stringField('File or directory to search in. Default: current directory.'),\n glob: stringField(\"File glob to filter by (e.g. '*.ts'). Default: all files.\"),\n ignoreCase: booleanField('Case-insensitive search. Default: false.'),\n limit: integerField('Maximum number of matching lines to return. Default: 100.'),\n },\n ['pattern'],\n ),\n execute: async (input) => {\n const limit = input.limit ?? 100;\n const target = input.path ?? '.';\n // Try ripgrep first (much faster, respects .gitignore by default).\n try {\n const args = [\n '--line-number',\n '--no-heading',\n '--color=never',\n ...(input.ignoreCase ? ['--ignore-case'] : []),\n ...(input.glob ? [`--glob=${input.glob}`] : []),\n '--',\n input.pattern,\n target,\n ];\n const { stdout } = await execAsync(`rg ${args.map(shellQuote).join(' ')}`, {\n maxBuffer: 10 * 1024 * 1024,\n });\n return truncateOutput(stdout, limit);\n } catch (err) {\n // rg exits with code 1 when no matches found; treat as empty result\n // if we got empty stdout. For other errors, fall back to grep.\n const e = err as { code?: number; stdout?: string };\n if (e.code === 1 && !e.stdout) {\n return 'No matches found.';\n }\n }\n\n // Fallback: plain grep.\n try {\n const args = [\n '-rn',\n '--color=never',\n ...(input.ignoreCase ? ['-i'] : []),\n ...(input.glob ? [`--include=${input.glob}`] : []),\n '-E',\n '--',\n input.pattern,\n target,\n ];\n const { stdout } = await execAsync(`grep ${args.map(shellQuote).join(' ')}`, {\n maxBuffer: 10 * 1024 * 1024,\n });\n return truncateOutput(stdout, limit);\n } catch (err) {\n const e = err as { code?: number; stdout?: string; message?: string };\n if (e.code === 1 && !e.stdout) {\n return 'No matches found.';\n }\n return `Error running grep: ${e.message ?? 'unknown'}`;\n }\n },\n});\n\nfunction shellQuote(s: string): string {\n // Conservative shell-safe quoting for tool arguments.\n if (/^[a-zA-Z0-9_./:=@%+-]+$/.test(s)) return s;\n return `'${s.replace(/'/g, `'\\\\''`)}'`;\n}\n\nfunction truncateOutput(output: string, limit: number): string {\n const lines = output.split('\\n');\n if (lines.length <= limit) return output || 'No matches found.';\n return `${lines.slice(0, limit).join('\\n')}\\n... (${lines.length - limit} more matches truncated)`;\n}\n","/**\n * Husk — eval runner types and API.\n *\n * The eval runner lets users assert that an agent's output meets\n * expectations. Three primitives:\n *\n * 1. EvalCase — an input + the expected outcome (an assertion or a set of them)\n * 2. Assertion — a function that takes the agent's result and returns pass/fail\n * 3. EvalSuite — a named collection of eval cases, runnable as a unit\n *\n * The design choice: assertions are plain async functions, not a DSL.\n * Users can use the 4 built-ins (equals, contains, matches, fn) or\n * write their own. The DSL is intentionally tiny — a heavy DSL\n * (think Jest matchers) is a maintainability trap.\n *\n * Example:\n *\n * const suite = defineSuite({\n * name: 'hello-agent',\n * cases: [\n * {\n * name: 'answers geography',\n * input: 'What is the capital of France? Answer in one word.',\n * assertions: [\n * contains('Paris'),\n * matches(/^[A-Z][a-z]+$/), // single capitalized word\n * ],\n * },\n * ],\n * });\n *\n * const results = await runSuite(suite, () => new Agent({ model: ... }));\n * console.log(`${results.passed}/${results.total} passed`);\n */\n\nimport type { AgentResult } from '../core/types.js';\n\n// ───────────────────────────────────────────────────────────────────\n// Assertions\n// ───────────────────────────────────────────────────────────────────\n\n/**\n * A function that checks whether an agent's output meets a criterion.\n * Returns a pass/fail with an optional message explaining the failure.\n */\nexport type Assertion = (result: AgentResult) => AssertionResult | Promise<AssertionResult>;\n\nexport interface AssertionResult {\n /** Whether the assertion passed. */\n readonly pass: boolean;\n /** Human-readable name shown in eval reports. */\n readonly name: string;\n /** Optional message — required when pass is false to explain why. */\n readonly message?: string;\n}\n\n// ───────────────────────────────────────────────────────────────────\n// Built-in assertions\n// ───────────────────────────────────────────────────────────────────\n\n/** Output exactly equals the expected string. */\nexport function equals(expected: string): Assertion {\n return (result) => {\n const pass = result.output === expected;\n return pass\n ? { name: `equals(${JSON.stringify(expected).slice(0, 40)})`, pass: true }\n : {\n name: `equals(${JSON.stringify(expected).slice(0, 40)})`,\n pass: false,\n message: `Expected ${JSON.stringify(expected)}, got ${JSON.stringify(result.output).slice(0, 200)}`,\n };\n };\n}\n\n/** Output contains the expected substring (case-sensitive). */\nexport function contains(needle: string): Assertion {\n return (result) => {\n const pass = result.output.includes(needle);\n return pass\n ? { name: `contains(${JSON.stringify(needle).slice(0, 40)})`, pass: true }\n : {\n name: `contains(${JSON.stringify(needle).slice(0, 40)})`,\n pass: false,\n message: `Expected output to contain ${JSON.stringify(needle)}, got ${JSON.stringify(result.output).slice(0, 200)}`,\n };\n };\n}\n\n/** Output matches the expected regex. */\nexport function matches(pattern: RegExp): Assertion {\n return (result) => {\n const m = pattern.exec(result.output);\n return {\n name: `matches(${pattern})`,\n pass: m !== null,\n ...(m === null\n ? {\n message: `Output did not match ${pattern}: ${JSON.stringify(result.output).slice(0, 200)}`,\n }\n : {}),\n };\n };\n}\n\n/** Output passes a custom predicate. Use this for shape-based checks. */\nexport function fn(\n name: string,\n predicate: (output: string) => boolean,\n message?: string,\n): Assertion {\n return (result) => {\n const pass = predicate(result.output);\n return {\n name,\n pass,\n ...(pass ? {} : { message: message ?? `Predicate ${name} failed` }),\n };\n };\n}\n\n/** Output does NOT contain the given substring. */\nexport function notContains(needle: string): Assertion {\n return (result) => {\n const pass = !result.output.includes(needle);\n return pass\n ? { name: `notContains(${JSON.stringify(needle).slice(0, 40)})`, pass: true }\n : {\n name: `notContains(${JSON.stringify(needle).slice(0, 40)})`,\n pass: false,\n message: `Output should not contain ${JSON.stringify(needle)} but did: ${JSON.stringify(result.output).slice(0, 200)}`,\n };\n };\n}\n\n/** Output length is within bounds. */\nexport function lengthBetween(min: number, max: number): Assertion {\n return (result) => {\n const len = result.output.length;\n const pass = len >= min && len <= max;\n return pass\n ? { name: `lengthBetween(${min}, ${max})`, pass: true }\n : {\n name: `lengthBetween(${min}, ${max})`,\n pass: false,\n message: `Output length ${len} not in [${min}, ${max}]`,\n };\n };\n}\n\n// ───────────────────────────────────────────────────────────────────\n// Eval cases & suites\n// ───────────────────────────────────────────────────────────────────\n\nexport interface EvalCase {\n /** Human-readable name shown in eval reports. */\n readonly name: string;\n /** The input to pass to agent.run(). */\n readonly input: string;\n /** Assertions to run on the result. All must pass for the case to pass. */\n readonly assertions: readonly Assertion[];\n /**\n * Optional max iterations override. Lets you cap runaway agents per-case\n * without affecting other cases in the suite.\n */\n readonly maxIterations?: number;\n}\n\nexport interface EvalSuite {\n /** Suite name shown in reports. */\n readonly name: string;\n /** Cases in this suite, run sequentially. */\n readonly cases: readonly EvalCase[];\n}\n\n// ───────────────────────────────────────────────────────────────────\n// Suite results\n// ───────────────────────────────────────────────────────────────────\n\nexport interface CaseResult {\n readonly caseName: string;\n readonly passed: boolean;\n readonly assertionResults: readonly AssertionResult[];\n readonly agentResult: AgentResult;\n readonly durationMs: number;\n}\n\nexport interface SuiteResult {\n readonly suiteName: string;\n readonly results: readonly CaseResult[];\n readonly passed: number;\n readonly total: number;\n readonly durationMs: number;\n}\n","/**\n * Husk — eval runner.\n *\n * Takes an EvalSuite + a factory that returns an Agent, runs each\n * case sequentially, applies the assertions, and reports results.\n *\n * Why a factory (not an Agent instance): each case might want its\n * own agent configuration. The factory pattern gives the user full\n * control without forcing a specific shape.\n *\n * Why sequential (not parallel): LLM calls compete for rate limits\n * and cost $$$. Sequential gives predictable billing and easier\n * debugging. Parallel mode is a v0.3.0 addition.\n *\n * Failure handling: an agent run that throws an error is reported\n * as a case failure (not a runner crash). The error message is\n * included in the assertion results so the user can see what broke.\n */\n\nimport type { Agent } from '../core/agent.js';\nimport type { AgentResult } from '../core/types.js';\nimport type {\n Assertion,\n AssertionResult,\n CaseResult,\n EvalCase,\n EvalSuite,\n SuiteResult,\n} from './types.js';\n\n// Re-export the assertion builders + types from types.ts so callers\n// can import everything from this single file.\nexport {\n equals,\n contains,\n notContains,\n matches,\n fn,\n lengthBetween,\n} from './types.js';\nexport type { Assertion, AssertionResult, EvalCase, EvalSuite, CaseResult, SuiteResult };\n\n// ───────────────────────────────────────────────────────────────────\n// Runner\n// ───────────────────────────────────────────────────────────────────\n\n/**\n * A factory that produces a fresh Agent per case. Called once per\n * case so each case can have isolated memory, config, etc.\n */\nexport type AgentFactory = () => Agent | Promise<Agent>;\n\nexport interface RunSuiteOptions {\n /** Stop on first failing case. Default: false (run all cases regardless). */\n readonly failFast?: boolean;\n /** Custom logger for runner-level events. Default: silent. */\n readonly onCaseStart?: (caseName: string) => void;\n readonly onCaseEnd?: (result: CaseResult) => void;\n}\n\nexport async function runSuite(\n suite: EvalSuite,\n factory: AgentFactory,\n options: RunSuiteOptions = {},\n): Promise<SuiteResult> {\n const start = Date.now();\n const results: CaseResult[] = [];\n let passed = 0;\n\n for (const c of suite.cases) {\n options.onCaseStart?.(c.name);\n const caseResult = await runCase(c, factory);\n results.push(caseResult);\n if (caseResult.passed) passed += 1;\n options.onCaseEnd?.(caseResult);\n\n if (options.failFast && !caseResult.passed) {\n break;\n }\n }\n\n return {\n suiteName: suite.name,\n results,\n passed,\n total: suite.cases.length,\n durationMs: Date.now() - start,\n };\n}\n\n// ───────────────────────────────────────────────────────────────────\n// Case runner\n// ───────────────────────────────────────────────────────────────────\n\nasync function runCase(c: EvalCase, factory: AgentFactory): Promise<CaseResult> {\n const start = Date.now();\n const agent = await factory();\n\n let agentResult: AgentResult;\n try {\n agentResult = await agent.run(c.input);\n } catch (err) {\n // Agent threw — synthesize a result so the case still reports.\n const message = err instanceof Error ? err.message : String(err);\n const errorAssertionResult = {\n pass: false,\n name: 'agent.run',\n message: `agent.run threw: ${message}`,\n };\n return {\n caseName: c.name,\n passed: false,\n assertionResults: [errorAssertionResult],\n agentResult: {\n output: '',\n messages: [],\n iterations: 0,\n usage: { inputTokens: 0, outputTokens: 0 },\n durationMs: Date.now() - start,\n },\n durationMs: Date.now() - start,\n };\n }\n\n const assertionResults: { pass: boolean; name: string; message?: string }[] = [];\n for (const a of c.assertions) {\n const r = await a(agentResult);\n assertionResults.push(r);\n }\n\n const allPassed = assertionResults.every((r) => r.pass);\n return {\n caseName: c.name,\n passed: allPassed,\n assertionResults,\n agentResult,\n durationMs: Date.now() - start,\n };\n}\n\n// ───────────────────────────────────────────────────────────────────\n// Suite definition helper\n// ───────────────────────────────────────────────────────────────────\n\n/**\n * Build a suite with less boilerplate. Equivalent to constructing\n * the object inline, but reads more clearly at the call site.\n */\nexport function defineSuite(suite: { name: string; cases: readonly EvalCase[] }): EvalSuite {\n return {\n name: suite.name,\n cases: suite.cases,\n };\n}\n\n// Re-export Assertion and AssertionResult for callers that want to\n// type their custom assertion functions.\n// (Already re-exported at the top of the file.)\n","/**\n * Husk — observability types (tracer interface).\n *\n * A minimal, OTel-inspired tracer interface. Husk's events are mapped\n * to spans by the mapper in ./tracer.ts. Users can plug in the real\n * @opentelemetry/api tracer via the adapter (see ./otel-adapter.ts)\n * or any other compatible backend.\n *\n * Design choice: we don't depend on @opentelemetry/api directly. The\n * interface here is a strict subset of OTel's Span interface (just\n * what's needed for agent observability). Keeping the dep out of\n * Husk's core means users who don't need OTel pay nothing for it.\n *\n * For users who want full OTel:\n * import { trace } from '@opentelemetry/api';\n * import { toOtelTracer } from '@princetheprogrammerbtw/husk/otel-adapter';\n * agent.onAny(toOtelTracer(trace.getTracer('husk')).onEvent);\n */\n\n// ───────────────────────────────────────────────────────────────────\n// Span — a unit of work (e.g., one agent run, one tool call)\n// ───────────────────────────────────────────────────────────────────\n\nexport type SpanKind = 'internal' | 'client' | 'server';\n\nexport interface SpanContext {\n /** Unique trace id (all spans in one agent.run share this). */\n readonly traceId: string;\n /** Unique span id. */\n readonly spanId: string;\n /** Parent span id, if any. */\n readonly parentSpanId?: string;\n}\n\nexport interface SpanOptions {\n readonly name: string;\n readonly kind?: SpanKind;\n readonly attributes?: Readonly<Record<string, unknown>>;\n readonly startTimeNs?: bigint;\n}\n\nexport interface Span {\n readonly context: SpanContext;\n /** Record an event (timestamped annotation) on the span. */\n addEvent(name: string, attributes?: Record<string, unknown>): void;\n /** Set or update an attribute on the span. */\n setAttribute(key: string, value: string | number | boolean | null): void;\n /** Record an exception. */\n recordException(err: Error): void;\n /** Mark the span as failed. */\n setStatus(status: 'ok' | 'error', message?: string): void;\n /** End the span. Must be called exactly once. */\n end(endTimeNs?: bigint): void;\n}\n\n// ───────────────────────────────────────────────────────────────────\n// Tracer — creates spans\n// ───────────────────────────────────────────────────────────────────\n\nexport interface Tracer {\n /**\n * Start a new span. If parent is provided, the new span becomes a\n * child of it. Returns the new span; caller is responsible for\n * calling .end() on it.\n */\n startSpan(options: SpanOptions, parent?: SpanContext): Span;\n}\n\n// ───────────────────────────────────────────────────────────────────\n// No-op tracer (default)\n// ───────────────────────────────────────────────────────────────────\n\n/**\n * A tracer that does nothing. Used when no real tracer is configured.\n * Zero overhead — every method is a no-op, so the cost is one virtual\n * call per event.\n */\nexport class NoopTracer implements Tracer {\n startSpan(_options: SpanOptions, _parent?: SpanContext): Span {\n const ctx: SpanContext = {\n traceId: '0',\n spanId: '0',\n };\n return {\n context: ctx,\n addEvent: () => {},\n setAttribute: () => {},\n recordException: () => {},\n setStatus: () => {},\n end: () => {},\n };\n }\n}\n","/**\n * Husk — agent event → tracer mapper.\n *\n * Translates the typed AgentEvent stream into tracer spans. The top-\n * level 'agent:start' begins a trace, each iteration becomes a child\n * span, and tool calls become their own spans under the iteration.\n *\n * Design: spans are created in startSpanOrder. Tool spans nest under\n * the iteration span. The end of the agent run ends the trace span.\n *\n * Usage:\n * const mapper = new EventTracer(myTracer);\n * agent.onAny(mapper.onEvent.bind(mapper));\n * await agent.run(...); // emits spans to myTracer\n */\n\nimport type { AgentEventHandler } from '../core/events.js';\nimport type { Span, Tracer } from './tracer.js';\n\n// ───────────────────────────────────────────────────────────────────\n// EventTracer\n// ───────────────────────────────────────────────────────────────────\n\nexport class EventTracer {\n private readonly tracer: Tracer;\n private traceSpan: Span | null = null;\n private iterationSpan: Span | null = null;\n private toolSpans: Map<string, Span> = new Map();\n\n constructor(tracer: Tracer) {\n this.tracer = tracer;\n }\n\n /**\n * Bind as an event handler: `agent.onAny(tracer.onEvent.bind(tracer))`\n */\n onEvent: AgentEventHandler = (event) => {\n switch (event.type) {\n case 'agent:start': {\n this.traceSpan = this.tracer.startSpan({\n name: 'agent.run',\n kind: 'internal',\n attributes: {\n 'husk.input': event.input,\n 'husk.session_id': event.sessionId,\n },\n });\n break;\n }\n\n case 'agent:iteration': {\n // Close any stale iteration span (defensive — shouldn't happen\n // because the loop is synchronous, but guards against future\n // async refactors).\n this.iterationSpan?.end();\n this.iterationSpan = this.tracer.startSpan(\n {\n name: `iteration.${event.iteration}`,\n kind: 'internal',\n attributes: { 'husk.iteration': event.iteration },\n },\n this.traceSpan?.context,\n );\n break;\n }\n\n case 'provider:request': {\n this.iterationSpan?.addEvent('provider.request', {\n 'provider.model': event.request.model,\n });\n break;\n }\n\n case 'provider:response': {\n if (this.iterationSpan) {\n this.iterationSpan.setAttribute(\n 'provider.input_tokens',\n event.response.usage.inputTokens,\n );\n this.iterationSpan.setAttribute(\n 'provider.output_tokens',\n event.response.usage.outputTokens,\n );\n this.iterationSpan.setAttribute('provider.stop_reason', event.response.stopReason);\n this.iterationSpan.setAttribute('provider.duration_ms', event.durationMs);\n }\n break;\n }\n\n case 'tool:call': {\n const span = this.tracer.startSpan(\n {\n name: `tool.${event.name}`,\n kind: 'internal',\n attributes: {\n 'tool.name': event.name,\n 'tool.input': JSON.stringify(event.input),\n },\n },\n this.iterationSpan?.context ?? this.traceSpan?.context,\n );\n this.toolSpans.set(event.id, span);\n break;\n }\n\n case 'tool:result': {\n const span = this.toolSpans.get(event.id);\n if (span) {\n span.setAttribute('tool.is_error', event.result.isError ?? false);\n span.setAttribute('tool.duration_ms', event.durationMs);\n if (event.result.isError) {\n span.setStatus('error', event.result.output);\n } else {\n span.setStatus('ok');\n }\n span.end();\n this.toolSpans.delete(event.id);\n }\n break;\n }\n\n case 'agent:end': {\n this.iterationSpan?.end();\n this.iterationSpan = null;\n if (this.traceSpan) {\n this.traceSpan.setAttribute('husk.iterations', event.iterations);\n this.traceSpan.setAttribute('husk.duration_ms', event.durationMs);\n this.traceSpan.setStatus('ok');\n this.traceSpan.end();\n this.traceSpan = null;\n }\n break;\n }\n\n case 'agent:error': {\n if (this.traceSpan) {\n this.traceSpan.recordException(event.error);\n this.traceSpan.setStatus('error', event.error.message);\n this.traceSpan.end();\n this.traceSpan = null;\n }\n this.iterationSpan?.end();\n this.iterationSpan = null;\n // End any in-flight tool spans so they don't leak.\n for (const span of this.toolSpans.values()) {\n span.end();\n }\n this.toolSpans.clear();\n break;\n }\n\n case 'agent:message': {\n this.iterationSpan?.addEvent('message', {\n 'message.role': event.message.role,\n });\n break;\n }\n }\n };\n}\n\n// Re-export SpanContext for users who want to write their own mappers.\nexport type { Span, SpanContext, Tracer } from './tracer.js';\n","/**\n * Husk — public API entry point.\n *\n * Single import surface for users:\n * import { Agent, Anthropic, OpenAI, Read, Write, Bash, Edit, Grep,\n * InMemoryStore, FileStore, ConsoleLogger } from '@princetheprogrammerbtw/husk';\n *\n * Re-exports are added incrementally as features land (see commit history).\n */\n\nexport const VERSION = '0.1.0';\n\n// Core types\nexport type {\n Role,\n Message,\n MessageContent,\n ContentBlock,\n TextBlock,\n ToolUseBlock,\n ToolResultBlock,\n JSONSchema,\n JSONSchemaField,\n ToolDefinition,\n ToolContext,\n ToolResult,\n Provider,\n ChatRequest,\n ChatResponse,\n ChatChunk,\n TokenUsage,\n StopReason,\n MemoryStore,\n SteeringConfig,\n Example,\n AgentConfig,\n AgentResult,\n LogLevel,\n Logger,\n} from './core/types.js';\n\n// Events\nexport {\n AgentEventEmitter,\n ConsoleLogger,\n logEventsTo,\n type AgentEvent,\n type AgentEventHandler,\n} from './core/events.js';\n\n// Memory\nexport { InMemoryStore, FileStore, type FileStoreOptions } from './core/memory.js';\n\n// Vector memory\nexport {\n InMemoryVectorStore,\n HashEmbedder,\n cosineSimilarity,\n defineMemorySearchTool,\n defineRememberTool,\n type MemoryItem,\n type SearchResult,\n type VectorStore,\n type EmbeddingProvider,\n type HashEmbedderOptions,\n type MemoryToolOptions,\n} from './memory/vector-index.js';\n\n// Steering helpers\nexport { buildSystemPrompt, buildExampleMessages } from './core/steering.js';\n\n// Agent\nexport { Agent } from './core/agent.js';\n\n// Providers\nexport { AnthropicProvider, type AnthropicProviderOptions } from './providers/anthropic.js';\nexport { OpenAIProvider, type OpenAIProviderOptions } from './providers/openai.js';\nexport { OllamaProvider, type OllamaProviderOptions } from './providers/ollama.js';\n\n// Tool helpers\nexport {\n defineTool,\n objectSchema,\n stringField,\n numberField,\n integerField,\n booleanField,\n arrayField,\n objectField,\n} from './tools/registry.js';\n\n// Built-in tools\nexport {\n Read,\n Write,\n Edit,\n Bash,\n Grep,\n type ReadInput,\n type WriteInput,\n type EditInput,\n type BashInput,\n type GrepInput,\n} from './tools/builtin/index.js';\n\n// Evals\nexport {\n equals,\n contains,\n notContains,\n matches,\n fn,\n lengthBetween,\n defineSuite,\n runSuite,\n type Assertion,\n type AssertionResult,\n type EvalCase,\n type EvalSuite,\n type CaseResult,\n type SuiteResult,\n type AgentFactory,\n type RunSuiteOptions,\n} from './evals/index.js';\n\n// Observability\nexport {\n NoopTracer,\n EventTracer,\n type Tracer,\n type Span,\n type SpanContext,\n type SpanKind,\n type SpanOptions,\n} from './obs/index.js';\n"]}
|