@princetheprogrammerbtw/husk 0.1.0 → 0.1.1
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 +2 -3
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
1
2
|
import { promisify, parseArgs } from 'util';
|
|
2
3
|
import { promises } from 'fs';
|
|
3
4
|
import { resolve, dirname, join } from 'path';
|
|
@@ -5,8 +6,6 @@ import Anthropic from '@anthropic-ai/sdk';
|
|
|
5
6
|
import OpenAI from 'openai';
|
|
6
7
|
import { exec } from 'child_process';
|
|
7
8
|
|
|
8
|
-
// src/cli/index.ts
|
|
9
|
-
|
|
10
9
|
// src/core/events.ts
|
|
11
10
|
var AgentEventEmitter = class {
|
|
12
11
|
handlers = /* @__PURE__ */ new Map();
|
|
@@ -1140,7 +1139,7 @@ Examples:
|
|
|
1140
1139
|
husk run "Summarize README.md" --provider openai --model gpt-5
|
|
1141
1140
|
`);
|
|
1142
1141
|
}
|
|
1143
|
-
var VERSION = "0.0
|
|
1142
|
+
var VERSION = "0.1.0";
|
|
1144
1143
|
await main();
|
|
1145
1144
|
//# sourceMappingURL=index.js.map
|
|
1146
1145
|
//# sourceMappingURL=index.js.map
|
package/dist/cli/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/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/cli/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 — 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 — minimal CLI.\n *\n * v0.1.0 ships a single command: 'husk run' executes an agent against\n * a one-shot prompt and prints the result. More commands (init, eval,\n * trace replay) come in v0.2.\n *\n * Usage:\n * husk run \"What is the capital of France?\" --model claude-opus-4-6\n * husk run \"Refactor src/foo.ts\" --tools read,write,edit,bash,grep\n * husk run --help\n *\n * Configuration:\n * ANTHROPIC_API_KEY required for Anthropic provider\n * OPENAI_API_KEY required for OpenAI provider\n * HUSK_MODEL default model id (default: claude-opus-4-6)\n * HUSK_PROVIDER 'anthropic' (default) or 'openai'\n */\n\nimport { parseArgs } from 'node:util';\nimport {\n Agent,\n AnthropicProvider,\n Bash,\n ConsoleLogger,\n Edit,\n FileStore,\n Grep,\n InMemoryStore,\n OpenAIProvider,\n Read,\n type ToolDefinition,\n Write,\n} from '../index.js';\n\nconst TOOL_REGISTRY = { read: Read, write: Write, edit: Edit, bash: Bash, grep: Grep } as const;\n\nasync function main(): Promise<void> {\n const subcommand = process.argv[2];\n\n if (subcommand === '--help' || subcommand === '-h' || subcommand === undefined) {\n printHelp();\n return;\n }\n\n if (subcommand === 'run') {\n await runCommand();\n return;\n }\n\n if (subcommand === 'version' || subcommand === '--version' || subcommand === '-v') {\n // eslint-disable-next-line no-console\n console.log(`husk ${VERSION}`);\n return;\n }\n\n // eslint-disable-next-line no-console\n console.error(`Unknown command: ${subcommand}\\nRun 'husk --help' for usage.`);\n process.exit(1);\n}\n\nasync function runCommand(): Promise<void> {\n const { values } = parseArgs({\n args: process.argv.slice(3),\n options: {\n model: { type: 'string' },\n provider: { type: 'string' },\n tools: { type: 'string' },\n memory: { type: 'string' },\n max: { type: 'string' },\n help: { type: 'boolean', short: 'h' },\n },\n allowPositionals: true,\n });\n\n if (values.help) {\n printHelp();\n return;\n }\n\n const prompt = values.help === undefined ? process.argv[3] : undefined;\n if (!prompt) {\n // eslint-disable-next-line no-console\n console.error('Error: husk run requires a prompt argument.');\n // eslint-disable-next-line no-console\n console.error('Usage: husk run \"your prompt here\"');\n process.exit(1);\n }\n\n const providerName = values.provider ?? process.env.HUSK_PROVIDER ?? 'anthropic';\n const modelId = values.model ?? process.env.HUSK_MODEL ?? 'claude-opus-4-6';\n\n const provider =\n providerName === 'openai'\n ? new OpenAIProvider({ model: modelId })\n : new AnthropicProvider({ model: modelId });\n\n const toolNames = (values.tools ?? 'read,write,edit,bash,grep')\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean);\n const tools = toolNames.map((name) => {\n const t = TOOL_REGISTRY[name as keyof typeof TOOL_REGISTRY];\n if (!t) {\n // eslint-disable-next-line no-console\n console.error(\n `Error: unknown tool '${name}'. Available: ${Object.keys(TOOL_REGISTRY).join(', ')}`,\n );\n process.exit(1);\n }\n return t;\n });\n\n const memory = values.memory === 'file' ? new FileStore() : new InMemoryStore();\n const maxIterations = values.max ? Number.parseInt(values.max, 10) : 25;\n\n const agent = new Agent({\n model: provider,\n ...(tools.length > 0 ? { tools: tools as readonly ToolDefinition[] } : {}),\n memory,\n maxIterations,\n });\n\n // The agent's default logger is ConsoleLogger; this is here to make\n // the CLI's logger usage explicit and easy to swap (e.g. for JSON\n // output in CI).\n void ConsoleLogger;\n\n const result = await agent.run(prompt);\n\n // eslint-disable-next-line no-console\n console.log(result.output);\n process.exit(0);\n}\n\nfunction printHelp(): void {\n // eslint-disable-next-line no-console\n console.log(`husk — run an agent from the command line\n\nUsage:\n husk run \"<prompt>\" [options]\n\nOptions:\n --model <id> Model id (default: claude-opus-4-6)\n --provider <name> 'anthropic' (default) or 'openai'\n --tools <list> Comma-separated tool names: read,write,edit,bash,grep\n (default: all five)\n --memory <kind> 'in-memory' (default) or 'file'\n --max <n> Max agent iterations (default: 25)\n -h, --help Show this help\n -v, --version Show version\n\nEnvironment:\n ANTHROPIC_API_KEY Required for Anthropic provider\n OPENAI_API_KEY Required for OpenAI provider\n HUSK_MODEL Override default model\n HUSK_PROVIDER Override default provider\n\nExamples:\n husk run \"What is the capital of France?\"\n husk run \"Refactor src/foo.ts\" --tools read,edit,write\n husk run \"Summarize README.md\" --provider openai --model gpt-5\n`);\n}\n\nconst VERSION = '0.0.1';\n\nawait main();\n"]}
|
|
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/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/cli/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 — 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 — minimal CLI.\n *\n * v0.1.0 ships a single command: 'husk run' executes an agent against\n * a one-shot prompt and prints the result. More commands (init, eval,\n * trace replay) come in v0.2.\n *\n * Usage:\n * husk run \"What is the capital of France?\" --model claude-opus-4-6\n * husk run \"Refactor src/foo.ts\" --tools read,write,edit,bash,grep\n * husk run --help\n *\n * Configuration:\n * ANTHROPIC_API_KEY required for Anthropic provider\n * OPENAI_API_KEY required for OpenAI provider\n * HUSK_MODEL default model id (default: claude-opus-4-6)\n * HUSK_PROVIDER 'anthropic' (default) or 'openai'\n */\n\nimport { parseArgs } from 'node:util';\nimport {\n Agent,\n AnthropicProvider,\n Bash,\n ConsoleLogger,\n Edit,\n FileStore,\n Grep,\n InMemoryStore,\n OpenAIProvider,\n Read,\n type ToolDefinition,\n Write,\n} from '../index.js';\n\nconst TOOL_REGISTRY = { read: Read, write: Write, edit: Edit, bash: Bash, grep: Grep } as const;\n\nasync function main(): Promise<void> {\n const subcommand = process.argv[2];\n\n if (subcommand === '--help' || subcommand === '-h' || subcommand === undefined) {\n printHelp();\n return;\n }\n\n if (subcommand === 'run') {\n await runCommand();\n return;\n }\n\n if (subcommand === 'version' || subcommand === '--version' || subcommand === '-v') {\n // eslint-disable-next-line no-console\n console.log(`husk ${VERSION}`);\n return;\n }\n\n // eslint-disable-next-line no-console\n console.error(`Unknown command: ${subcommand}\\nRun 'husk --help' for usage.`);\n process.exit(1);\n}\n\nasync function runCommand(): Promise<void> {\n const { values } = parseArgs({\n args: process.argv.slice(3),\n options: {\n model: { type: 'string' },\n provider: { type: 'string' },\n tools: { type: 'string' },\n memory: { type: 'string' },\n max: { type: 'string' },\n help: { type: 'boolean', short: 'h' },\n },\n allowPositionals: true,\n });\n\n if (values.help) {\n printHelp();\n return;\n }\n\n const prompt = values.help === undefined ? process.argv[3] : undefined;\n if (!prompt) {\n // eslint-disable-next-line no-console\n console.error('Error: husk run requires a prompt argument.');\n // eslint-disable-next-line no-console\n console.error('Usage: husk run \"your prompt here\"');\n process.exit(1);\n }\n\n const providerName = values.provider ?? process.env.HUSK_PROVIDER ?? 'anthropic';\n const modelId = values.model ?? process.env.HUSK_MODEL ?? 'claude-opus-4-6';\n\n const provider =\n providerName === 'openai'\n ? new OpenAIProvider({ model: modelId })\n : new AnthropicProvider({ model: modelId });\n\n const toolNames = (values.tools ?? 'read,write,edit,bash,grep')\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean);\n const tools = toolNames.map((name) => {\n const t = TOOL_REGISTRY[name as keyof typeof TOOL_REGISTRY];\n if (!t) {\n // eslint-disable-next-line no-console\n console.error(\n `Error: unknown tool '${name}'. Available: ${Object.keys(TOOL_REGISTRY).join(', ')}`,\n );\n process.exit(1);\n }\n return t;\n });\n\n const memory = values.memory === 'file' ? new FileStore() : new InMemoryStore();\n const maxIterations = values.max ? Number.parseInt(values.max, 10) : 25;\n\n const agent = new Agent({\n model: provider,\n ...(tools.length > 0 ? { tools: tools as readonly ToolDefinition[] } : {}),\n memory,\n maxIterations,\n });\n\n // The agent's default logger is ConsoleLogger; this is here to make\n // the CLI's logger usage explicit and easy to swap (e.g. for JSON\n // output in CI).\n void ConsoleLogger;\n\n const result = await agent.run(prompt);\n\n // eslint-disable-next-line no-console\n console.log(result.output);\n process.exit(0);\n}\n\nfunction printHelp(): void {\n // eslint-disable-next-line no-console\n console.log(`husk — run an agent from the command line\n\nUsage:\n husk run \"<prompt>\" [options]\n\nOptions:\n --model <id> Model id (default: claude-opus-4-6)\n --provider <name> 'anthropic' (default) or 'openai'\n --tools <list> Comma-separated tool names: read,write,edit,bash,grep\n (default: all five)\n --memory <kind> 'in-memory' (default) or 'file'\n --max <n> Max agent iterations (default: 25)\n -h, --help Show this help\n -v, --version Show version\n\nEnvironment:\n ANTHROPIC_API_KEY Required for Anthropic provider\n OPENAI_API_KEY Required for OpenAI provider\n HUSK_MODEL Override default model\n HUSK_PROVIDER Override default provider\n\nExamples:\n husk run \"What is the capital of France?\"\n husk run \"Refactor src/foo.ts\" --tools read,edit,write\n husk run \"Summarize README.md\" --provider openai --model gpt-5\n`);\n}\n\nconst VERSION = '0.1.0';\n\nawait main();\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -697,6 +697,6 @@ declare const Grep: ToolDefinition<GrepInput>;
|
|
|
697
697
|
*
|
|
698
698
|
* Re-exports are added incrementally as features land (see commit history).
|
|
699
699
|
*/
|
|
700
|
-
declare const VERSION = "0.0
|
|
700
|
+
declare const VERSION = "0.1.0";
|
|
701
701
|
|
|
702
702
|
export { Agent, type AgentConfig, type AgentEvent, AgentEventEmitter, type AgentEventHandler, type AgentResult, AnthropicProvider, type AnthropicProviderOptions, Bash, type BashInput, type ChatChunk, type ChatRequest, type ChatResponse, ConsoleLogger, type ContentBlock, Edit, type EditInput, type Example, FileStore, type FileStoreOptions, Grep, type GrepInput, InMemoryStore, type JSONSchema, type JSONSchemaField, type LogLevel, type Logger, type MemoryStore, type Message, type MessageContent, OpenAIProvider, type OpenAIProviderOptions, type Provider, Read, type ReadInput, type Role, type SteeringConfig, type StopReason, type TextBlock, type TokenUsage, type ToolContext, type ToolDefinition, type ToolResult, type ToolResultBlock, type ToolUseBlock, VERSION, Write, type WriteInput, arrayField, booleanField, buildExampleMessages, buildSystemPrompt, defineTool, integerField, logEventsTo, numberField, objectField, objectSchema, stringField };
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
1
2
|
import { promises } from 'fs';
|
|
2
3
|
import { join, resolve, dirname } from 'path';
|
|
3
4
|
import Anthropic from '@anthropic-ai/sdk';
|
|
@@ -1103,7 +1104,7 @@ function truncateOutput(output, limit) {
|
|
|
1103
1104
|
}
|
|
1104
1105
|
|
|
1105
1106
|
// src/index.ts
|
|
1106
|
-
var VERSION = "0.0
|
|
1107
|
+
var VERSION = "0.1.0";
|
|
1107
1108
|
|
|
1108
1109
|
export { Agent, AgentEventEmitter, AnthropicProvider, Bash, ConsoleLogger, Edit, FileStore, Grep, InMemoryStore, OpenAIProvider, Read, VERSION, Write, arrayField, booleanField, buildExampleMessages, buildSystemPrompt, defineTool, integerField, logEventsTo, numberField, objectField, objectSchema, stringField };
|
|
1109
1110
|
//# sourceMappingURL=index.js.map
|
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/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/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 — 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 — 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.0.1';\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';\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"]}
|
|
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/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/index.ts"],"names":["fs","durationMs","result","splitSystemMessage","mapStopReason","extractTextFromBlocks","resolve","dirname","execAsync","promisify","exec"],"mappings":";;;;;;;;;AAiEO,IAAM,oBAAN,MAAwB;AAAA,EACZ,QAAA,uBAA6D,GAAA,EAAI;AAAA,EACjE,mBAAwC,EAAC;AAAA;AAAA;AAAA;AAAA;AAAA,EAM1D,EAAA,CACE,MACA,OAAA,EACY;AACZ,IAAA,MAAM,OAAO,IAAA,CAAK,QAAA,CAAS,GAAA,CAAI,IAAI,KAAK,EAAC;AACzC,IAAA,IAAA,CAAK,KAAK,OAA4B,CAAA;AACtC,IAAA,IAAA,CAAK,QAAA,CAAS,GAAA,CAAI,IAAA,EAAM,IAAI,CAAA;AAC5B,IAAA,OAAO,MAAM,IAAA,CAAK,GAAA,CAAI,IAAA,EAAM,OAAO,CAAA;AAAA,EACrC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,OAAA,EAAwC;AAC5C,IAAA,IAAA,CAAK,gBAAA,CAAiB,KAAK,OAAO,CAAA;AAClC,IAAA,OAAO,MAAM;AACX,MAAA,MAAM,GAAA,GAAM,IAAA,CAAK,gBAAA,CAAiB,OAAA,CAAQ,OAAO,CAAA;AACjD,MAAA,IAAI,OAAO,CAAA,EAAG,IAAA,CAAK,gBAAA,CAAiB,MAAA,CAAO,KAAK,CAAC,CAAA;AAAA,IACnD,CAAA;AAAA,EACF;AAAA,EAEA,GAAA,CACE,MACA,OAAA,EACM;AACN,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,QAAA,CAAS,GAAA,CAAI,IAAI,CAAA;AACnC,IAAA,IAAI,CAAC,IAAA,EAAM;AACX,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,OAAA,CAAQ,OAA4B,CAAA;AACrD,IAAA,IAAI,GAAA,IAAO,CAAA,EAAG,IAAA,CAAK,MAAA,CAAO,KAAK,CAAC,CAAA;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,KAAK,KAAA,EAAkC;AAC3C,IAAA,MAAM,QAAQ,IAAA,CAAK,QAAA,CAAS,IAAI,KAAA,CAAM,IAAI,KAAK,EAAC;AAChD,IAAA,KAAA,MAAW,WAAW,KAAA,EAAO;AAC3B,MAAA,IAAI;AACF,QAAA,MAAM,QAAQ,KAAK,CAAA;AAAA,MACrB,SAAS,GAAA,EAAK;AAKZ,QAAA,OAAA,CAAQ,KAAA,CAAM,+BAA+B,GAAG,CAAA;AAAA,MAClD;AAAA,IACF;AACA,IAAA,KAAA,MAAW,OAAA,IAAW,KAAK,gBAAA,EAAkB;AAC3C,MAAA,IAAI;AACF,QAAA,MAAM,QAAQ,KAAK,CAAA;AAAA,MACrB,SAAS,GAAA,EAAK;AAEZ,QAAA,OAAA,CAAQ,KAAA,CAAM,wCAAwC,GAAG,CAAA;AAAA,MAC3D;AAAA,IACF;AAAA,EACF;AACF;AAUO,IAAM,gBAAN,MAAsC;AAAA,EAC3C,KAAA,CAAM,SAAiB,MAAA,EAAwC;AAE7D,IAAA,OAAA,CAAQ,MAAM,IAAA,CAAK,MAAA,CAAO,OAAA,EAAS,OAAA,EAAS,MAAM,CAAC,CAAA;AAAA,EACrD;AAAA,EACA,IAAA,CAAK,SAAiB,MAAA,EAAwC;AAE5D,IAAA,OAAA,CAAQ,KAAK,IAAA,CAAK,MAAA,CAAO,MAAA,EAAQ,OAAA,EAAS,MAAM,CAAC,CAAA;AAAA,EACnD;AAAA,EACA,IAAA,CAAK,SAAiB,MAAA,EAAwC;AAE5D,IAAA,OAAA,CAAQ,KAAK,IAAA,CAAK,MAAA,CAAO,MAAA,EAAQ,OAAA,EAAS,MAAM,CAAC,CAAA;AAAA,EACnD;AAAA,EACA,KAAA,CAAM,SAAiB,MAAA,EAAwC;AAE7D,IAAA,OAAA,CAAQ,MAAM,IAAA,CAAK,MAAA,CAAO,OAAA,EAAS,OAAA,EAAS,MAAM,CAAC,CAAA;AAAA,EACrD;AAAA,EAEQ,MAAA,CAAO,KAAA,EAAe,OAAA,EAAiB,MAAA,EAA0C;AACvF,IAAA,MAAM,EAAA,GAAA,iBAAK,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AAClC,IAAA,MAAM,SAAA,GAAY,MAAA,IAAU,MAAA,CAAO,IAAA,CAAK,MAAM,CAAA,CAAE,MAAA,GAAS,CAAA,GAAI,CAAA,CAAA,EAAI,IAAA,CAAK,SAAA,CAAU,MAAM,CAAC,CAAA,CAAA,GAAK,EAAA;AAC5F,IAAA,OAAO,GAAG,EAAE,CAAA,EAAA,EAAK,KAAK,CAAA,EAAA,EAAK,OAAO,GAAG,SAAS,CAAA,CAAA;AAAA,EAChD;AACF;AAMO,SAAS,YAAY,MAAA,EAAmC;AAC7D,EAAA,OAAO,CAAC,KAAA,KAAU;AAChB,IAAA,QAAQ,MAAM,IAAA;AAAM,MAClB,KAAK,aAAA;AACH,QAAA,MAAA,CAAO,IAAA,CAAK,iBAAiB,EAAE,KAAA,EAAO,MAAM,KAAA,EAAO,SAAA,EAAW,KAAA,CAAM,SAAA,EAAW,CAAA;AAC/E,QAAA;AAAA,MACF,KAAK,iBAAA;AACH,QAAA,MAAA,CAAO,MAAM,iBAAA,EAAmB,EAAE,SAAA,EAAW,KAAA,CAAM,WAAW,CAAA;AAC9D,QAAA;AAAA,MACF,KAAK,eAAA;AACH,QAAA,MAAA,CAAO,MAAM,eAAA,EAAiB,EAAE,MAAM,KAAA,CAAM,OAAA,CAAQ,MAAM,CAAA;AAC1D,QAAA;AAAA,MACF,KAAK,kBAAA;AACH,QAAA,MAAA,CAAO,MAAM,kBAAA,EAAoB,EAAE,OAAO,KAAA,CAAM,OAAA,CAAQ,OAAO,CAAA;AAC/D,QAAA;AAAA,MACF,KAAK,mBAAA;AACH,QAAA,MAAA,CAAO,KAAK,mBAAA,EAAqB;AAAA,UAC/B,KAAA,EAAO,MAAM,QAAA,CAAS,KAAA;AAAA,UACtB,UAAA,EAAY,MAAM,QAAA,CAAS,UAAA;AAAA,UAC3B,WAAA,EAAa,KAAA,CAAM,QAAA,CAAS,KAAA,CAAM,WAAA;AAAA,UAClC,YAAA,EAAc,KAAA,CAAM,QAAA,CAAS,KAAA,CAAM,YAAA;AAAA,UACnC,YAAY,KAAA,CAAM;AAAA,SACnB,CAAA;AACD,QAAA;AAAA,MACF,KAAK,WAAA;AACH,QAAA,MAAA,CAAO,IAAA,CAAK,WAAA,EAAa,EAAE,EAAA,EAAI,KAAA,CAAM,EAAA,EAAI,IAAA,EAAM,KAAA,CAAM,IAAA,EAAM,KAAA,EAAO,KAAA,CAAM,KAAA,EAAO,CAAA;AAC/E,QAAA;AAAA,MACF,KAAK,aAAA;AACH,QAAA,MAAA,CAAO,KAAK,aAAA,EAAe;AAAA,UACzB,IAAI,KAAA,CAAM,EAAA;AAAA,UACV,MAAM,KAAA,CAAM,IAAA;AAAA,UACZ,OAAA,EAAS,KAAA,CAAM,MAAA,CAAO,OAAA,IAAW,KAAA;AAAA,UACjC,YAAY,KAAA,CAAM;AAAA,SACnB,CAAA;AACD,QAAA;AAAA,MACF,KAAK,WAAA;AACH,QAAA,MAAA,CAAO,KAAK,aAAA,EAAe;AAAA,UACzB,YAAY,KAAA,CAAM,UAAA;AAAA,UAClB,YAAY,KAAA,CAAM;AAAA,SACnB,CAAA;AACD,QAAA;AAAA,MACF,KAAK,aAAA;AACH,QAAA,MAAA,CAAO,MAAM,aAAA,EAAe,EAAE,SAAS,KAAA,CAAM,KAAA,CAAM,SAAS,CAAA;AAC5D,QAAA;AAAA;AACJ,EACF,CAAA;AACF;AC5LO,IAAM,gBAAN,MAA2C;AAAA,EAC/B,QAAA,uBAAuC,GAAA,EAAI;AAAA,EAE5D,MAAM,KAAK,SAAA,EAAgD;AACzD,IAAA,OAAO,CAAC,GAAI,IAAA,CAAK,QAAA,CAAS,IAAI,SAAS,CAAA,IAAK,EAAG,CAAA;AAAA,EACjD;AAAA,EAEA,MAAM,MAAA,CAAO,SAAA,EAAmB,OAAA,EAAiC;AAC/D,IAAA,MAAM,OAAO,IAAA,CAAK,QAAA,CAAS,GAAA,CAAI,SAAS,KAAK,EAAC;AAC9C,IAAA,IAAA,CAAK,KAAK,OAAO,CAAA;AACjB,IAAA,IAAA,CAAK,QAAA,CAAS,GAAA,CAAI,SAAA,EAAW,IAAI,CAAA;AAAA,EACnC;AAAA,EAEA,MAAM,MAAM,SAAA,EAAkC;AAC5C,IAAA,IAAA,CAAK,QAAA,CAAS,OAAO,SAAS,CAAA;AAAA,EAChC;AAAA,EAEA,MAAM,YAAA,GAA2C;AAC/C,IAAA,OAAO,CAAC,GAAG,IAAA,CAAK,QAAA,CAAS,MAAM,CAAA;AAAA,EACjC;AACF;AAuBO,IAAM,YAAN,MAAuC;AAAA,EAC3B,OAAA;AAAA,EACA,OAAA;AAAA,EACA,UAAA,uBAA6C,GAAA,EAAI;AAAA,EAElE,WAAA,CAAY,OAAA,GAA4B,EAAC,EAAG;AAC1C,IAAA,IAAA,CAAK,OAAA,GAAU,QAAQ,IAAA,IAAQ,gBAAA;AAC/B,IAAA,IAAA,CAAK,OAAA,GAAU,QAAQ,OAAA,IAAW,KAAA;AAAA,EACpC;AAAA,EAEA,MAAM,KAAK,SAAA,EAAgD;AACzD,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,OAAA,CAAQ,SAAS,CAAA;AACnC,IAAA,IAAI;AACF,MAAA,MAAM,IAAA,GAAO,MAAMA,QAAA,CAAG,QAAA,CAAS,MAAM,OAAO,CAAA;AAC5C,MAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,KAAA,CAAM,IAAI,CAAA,CAAE,MAAA,CAAO,CAAC,IAAA,KAAS,IAAA,CAAK,IAAA,EAAK,CAAE,MAAA,GAAS,CAAC,CAAA;AACtE,MAAA,MAAM,WAAsB,EAAC;AAC7B,MAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,QAAA,IAAI;AACF,UAAA,MAAM,MAAA,GAAS,IAAA,CAAK,KAAA,CAAM,IAAI,CAAA;AAC9B,UAAA,IAAI,KAAK,OAAA,IAAW,MAAA,CAAO,OAAA,IAAW,MAAA,CAAO,YAAY,SAAA,EAAW;AACpE,UAAA,QAAA,CAAS,IAAA,CAAK,OAAO,OAAO,CAAA;AAAA,QAC9B,CAAA,CAAA,MAAQ;AAAA,QAIR;AAAA,MACF;AACA,MAAA,OAAO,QAAA;AAAA,IACT,SAAS,GAAA,EAAK;AACZ,MAAA,IAAI,OAAA,CAAQ,GAAG,CAAA,EAAG,OAAO,EAAC;AAC1B,MAAA,MAAM,GAAA;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAM,MAAA,CAAO,SAAA,EAAmB,OAAA,EAAiC;AAE/D,IAAA,MAAM,WAAW,IAAA,CAAK,UAAA,CAAW,IAAI,SAAS,CAAA,IAAK,QAAQ,OAAA,EAAQ;AACnE,IAAA,MAAM,IAAA,GAAO,SAAS,IAAA,CAAK,MAAM,KAAK,QAAA,CAAS,SAAA,EAAW,OAAO,CAAC,CAAA;AAClE,IAAA,IAAA,CAAK,UAAA,CAAW,GAAA;AAAA,MACd,SAAA;AAAA,MACA,IAAA,CAAK,KAAA,CAAM,MAAM,MAAS;AAAA,KAC5B;AACA,IAAA,OAAO,IAAA;AAAA,EACT;AAAA,EAEA,MAAc,QAAA,CAAS,SAAA,EAAmB,OAAA,EAAiC;AACzE,IAAA,MAAMA,SAAG,KAAA,CAAM,IAAA,CAAK,SAAS,EAAE,SAAA,EAAW,MAAM,CAAA;AAChD,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,OAAA,CAAQ,SAAS,CAAA;AACnC,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,OAAA,GACf,IAAA,CAAK,UAAU,EAAE,OAAA,EAAS,SAAA,EAAW,OAAA,EAAS,CAAA,GAC9C,IAAA,CAAK,SAAA,CAAU,EAAE,SAAS,CAAA;AAC9B,IAAA,MAAMA,QAAA,CAAG,UAAA,CAAW,IAAA,EAAM,CAAA,EAAG,KAAK;AAAA,CAAA,EAAM,OAAO,CAAA;AAAA,EACjD;AAAA,EAEA,MAAM,MAAM,SAAA,EAAkC;AAC5C,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,OAAA,CAAQ,SAAS,CAAA;AACnC,IAAA,IAAI;AACF,MAAA,MAAMA,QAAA,CAAG,OAAO,IAAI,CAAA;AAAA,IACtB,SAAS,GAAA,EAAK;AACZ,MAAA,IAAI,CAAC,OAAA,CAAQ,GAAG,CAAA,EAAG,MAAM,GAAA;AAAA,IAC3B;AAAA,EACF;AAAA,EAEA,MAAM,YAAA,GAA2C;AAC/C,IAAA,IAAI,KAAK,OAAA,EAAS;AAEhB,MAAA,MAAM,IAAA,GAAO,IAAA,CAAK,IAAA,CAAK,OAAA,EAAS,eAAe,CAAA;AAC/C,MAAA,IAAI;AACF,QAAA,MAAM,IAAA,GAAO,MAAMA,QAAA,CAAG,QAAA,CAAS,MAAM,OAAO,CAAA;AAC5C,QAAA,MAAM,GAAA,uBAAU,GAAA,EAAY;AAC5B,QAAA,KAAA,MAAW,IAAA,IAAQ,IAAA,CAAK,KAAA,CAAM,IAAI,CAAA,EAAG;AACnC,UAAA,IAAI,CAAC,IAAA,CAAK,IAAA,EAAK,EAAG;AAClB,UAAA,IAAI;AACF,YAAA,MAAM,MAAA,GAAS,IAAA,CAAK,KAAA,CAAM,IAAI,CAAA;AAC9B,YAAA,IAAI,MAAA,CAAO,OAAA,EAAS,GAAA,CAAI,GAAA,CAAI,OAAO,OAAO,CAAA;AAAA,UAC5C,CAAA,CAAA,MAAQ;AAAA,UAER;AAAA,QACF;AACA,QAAA,OAAO,CAAC,GAAG,GAAG,CAAA;AAAA,MAChB,SAAS,GAAA,EAAK;AACZ,QAAA,IAAI,OAAA,CAAQ,GAAG,CAAA,EAAG,OAAO,EAAC;AAC1B,QAAA,MAAM,GAAA;AAAA,MACR;AAAA,IACF;AACA,IAAA,IAAI;AACF,MAAA,MAAM,OAAA,GAAU,MAAMA,QAAA,CAAG,OAAA,CAAQ,KAAK,OAAO,CAAA;AAC7C,MAAA,OAAO,QACJ,MAAA,CAAO,CAAC,CAAA,KAAc,CAAA,CAAE,SAAS,QAAQ,CAAC,CAAA,CAC1C,GAAA,CAAI,CAAC,CAAA,KAAc,CAAA,CAAE,OAAA,CAAQ,UAAA,EAAY,EAAE,CAAC,CAAA;AAAA,IACjD,SAAS,GAAA,EAAK;AACZ,MAAA,IAAI,OAAA,CAAQ,GAAG,CAAA,EAAG,OAAO,EAAC;AAC1B,MAAA,MAAM,GAAA;AAAA,IACR;AAAA,EACF;AAAA,EAEQ,QAAQ,SAAA,EAA2B;AACzC,IAAA,IAAI,KAAK,OAAA,EAAS,OAAO,IAAA,CAAK,IAAA,CAAK,SAAS,eAAe,CAAA;AAC3D,IAAA,OAAO,KAAK,IAAA,CAAK,OAAA,EAAS,GAAG,QAAA,CAAS,SAAS,CAAC,CAAA,MAAA,CAAQ,CAAA;AAAA,EAC1D;AACF;AAEA,SAAS,QAAQ,GAAA,EAAuB;AACtC,EAAA,OAAO,OAAA;AAAA,IACL,OAAO,OAAO,GAAA,KAAQ,YAAY,MAAA,IAAU,GAAA,IAAQ,IAA0B,IAAA,KAAS;AAAA,GACzF;AACF;AAEA,SAAS,SAAS,SAAA,EAA2B;AAC3C,EAAA,OAAO,SAAA,CAAU,OAAA,CAAQ,kBAAA,EAAoB,GAAG,CAAA;AAClD;;;AC1JO,SAAS,kBAAkB,QAAA,EAA8C;AAC9E,EAAA,MAAM,QAAkB,EAAC;AAEzB,EAAA,IAAI,SAAS,YAAA,IAAgB,QAAA,CAAS,aAAa,IAAA,EAAK,CAAE,SAAS,CAAA,EAAG;AACpE,IAAA,KAAA,CAAM,IAAA,CAAK,QAAA,CAAS,YAAA,CAAa,IAAA,EAAM,CAAA;AAAA,EACzC;AAEA,EAAA,IAAI,QAAA,CAAS,KAAA,IAAS,QAAA,CAAS,KAAA,CAAM,SAAS,CAAA,EAAG;AAC/C,IAAA,MAAM,QAAA,GAAW,QAAA,CAAS,KAAA,CAAM,GAAA,CAAI,CAAC,IAAA,EAAM,CAAA,KAAM,CAAA,EAAG,CAAA,GAAI,CAAC,CAAA,EAAA,EAAK,IAAI,CAAA,CAAE,CAAA,CAAE,KAAK,IAAI,CAAA;AAC/E,IAAA,KAAA,CAAM,IAAA,CAAK,CAAA;AAAA,EAAa,QAAQ,CAAA,CAAE,CAAA;AAAA,EACpC;AAEA,EAAA,OAAO,MAAM,MAAA,GAAS,CAAA,GAAI,KAAA,CAAM,IAAA,CAAK,MAAM,CAAA,GAAI,MAAA;AACjD;AAgBO,SAAS,qBAAqB,QAAA,EAAkD;AACrF,EAAA,MAAM,WAAsB,EAAC;AAC7B,EAAA,KAAA,MAAW,MAAM,QAAA,EAAU;AACzB,IAAA,QAAA,CAAS,KAAK,EAAE,IAAA,EAAM,QAAQ,OAAA,EAAS,EAAA,CAAG,MAAM,CAAA;AAChD,IAAA,QAAA,CAAS,KAAK,EAAE,IAAA,EAAM,aAAa,OAAA,EAAS,EAAA,CAAG,WAAW,CAAA;AAAA,EAC5D;AACA,EAAA,OAAO,QAAA;AACT;;;ACbA,IAAM,QAAA,GAAW;AAAA,EACf,aAAA,EAAe,EAAA;AAAA,EACf,WAAA,EAAa,CAAA;AAAA,EACb,SAAA,EAAW;AACb,CAAA;AAMO,IAAM,QAAN,MAAY;AAAA,EACR,MAAA;AAAA,EACA,QAAA;AAAA,EACA,KAAA;AAAA,EACA,QAAA;AAAA,EACA,aAAA;AAAA,EACA,WAAA;AAAA,EACA,SAAA;AAAA,EACA,MAAA;AAAA,EACA,SAAA;AAAA,EACA,MAAA;AAAA,EACA,MAAA;AAAA,EAET,YAAY,MAAA,EAAqB;AAC/B,IAAA,IAAA,CAAK,MAAA,GAAS,IAAI,iBAAA,EAAkB;AACpC,IAAA,IAAA,CAAK,WAAW,MAAA,CAAO,KAAA;AACvB,IAAA,IAAA,CAAK,KAAA,GAAQ,MAAA,CAAO,KAAA,IAAS,EAAC;AAC9B,IAAA,IAAA,CAAK,WAAW,MAAA,CAAO,QAAA;AACvB,IAAA,IAAA,CAAK,aAAA,GAAgB,MAAA,CAAO,aAAA,IAAiB,QAAA,CAAS,aAAA;AACtD,IAAA,IAAA,CAAK,WAAA,GAAc,MAAA,CAAO,WAAA,IAAe,QAAA,CAAS,WAAA;AAClD,IAAA,IAAA,CAAK,YAAY,MAAA,CAAO,SAAA;AACxB,IAAA,IAAA,CAAK,SAAS,MAAA,CAAO,MAAA;AACrB,IAAA,IAAA,CAAK,SAAA,GAAY,MAAA,CAAO,SAAA,IAAa,QAAA,CAAS,SAAA;AAC9C,IAAA,IAAA,CAAK,SAAS,MAAA,CAAO,MAAA;AACrB,IAAA,IAAA,CAAK,MAAA,GAAS,IAAI,aAAA,EAAc;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA,EAKA,EAAA,GAA8B,CAAC,IAAA,EAAM,OAAA,KAAY,KAAK,MAAA,CAAO,EAAA,CAAG,MAAM,OAAO,CAAA;AAAA;AAAA;AAAA;AAAA,EAK7E,QAAoC,CAAC,OAAA,KAAY,IAAA,CAAK,MAAA,CAAO,MAAM,OAAO,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAO1E,MAAM,IAAI,KAAA,EAAqC;AAC7C,IAAA,MAAM,KAAA,GAAQ,KAAK,GAAA,EAAI;AAIvB,IAAA,IAAA,CAAK,QAAQ,cAAA,EAAe;AAE5B,IAAA,MAAM,IAAA,CAAK,MAAA,CAAO,IAAA,CAAK,EAAE,IAAA,EAAM,eAAe,KAAA,EAAO,SAAA,EAAW,IAAA,CAAK,SAAA,EAAW,CAAA;AAGhF,IAAA,MAAM,WAAsB,EAAC;AAE7B,IAAA,IAAI,IAAA,CAAK,UAAU,QAAA,EAAU;AAC3B,MAAA,QAAA,CAAS,KAAK,GAAG,oBAAA,CAAqB,IAAA,CAAK,QAAA,CAAS,QAAQ,CAAC,CAAA;AAAA,IAC/D;AAEA,IAAA,IAAI,KAAK,MAAA,EAAQ;AACf,MAAA,MAAM,SAAS,MAAM,IAAA,CAAK,MAAA,CAAO,IAAA,CAAK,KAAK,SAAS,CAAA;AACpD,MAAA,QAAA,CAAS,IAAA,CAAK,GAAG,MAAM,CAAA;AAAA,IACzB;AAEA,IAAA,MAAM,WAAA,GAAuB,EAAE,IAAA,EAAM,MAAA,EAAQ,SAAS,KAAA,EAAM;AAC5D,IAAA,QAAA,CAAS,KAAK,WAAW,CAAA;AACzB,IAAA,MAAM,IAAA,CAAK,cAAc,WAAW,CAAA;AAEpC,IAAA,MAAM,SAAS,IAAA,CAAK,QAAA,GAAW,iBAAA,CAAkB,IAAA,CAAK,QAAQ,CAAA,GAAI,MAAA;AAClE,IAAA,MAAM,QAAQ,IAAA,CAAK,KAAA,CAAM,MAAA,GAAS,CAAA,GAAI,KAAK,KAAA,GAAQ,MAAA;AAGnD,IAAA,IAAI,gBAAA,GAAmB,CAAA;AACvB,IAAA,IAAI,iBAAA,GAAoB,CAAA;AACxB,IAAA,IAAI,UAAA,GAAa,CAAA;AACjB,IAAA,IAAI,WAAA,GAAc,EAAA;AAClB,IAAA,IAAI,gBAAA,GAAmB,KAAA;AAEvB,IAAA,OAAO,UAAA,GAAa,KAAK,aAAA,EAAe;AACtC,MAAA,IAAA,CAAK,QAAQ,cAAA,EAAe;AAC5B,MAAA,UAAA,IAAc,CAAA;AACd,MAAA,MAAM,IAAA,CAAK,OAAO,IAAA,CAAK,EAAE,MAAM,iBAAA,EAAmB,SAAA,EAAW,YAAY,CAAA;AAGzE,MAAA,MAAM,OAAA,GAAU;AAAA,QACd,KAAA,EAAO,KAAK,QAAA,CAAS,KAAA;AAAA,QACrB,QAAA;AAAA,QACA,GAAI,KAAA,GAAQ,EAAE,KAAA,KAAU,EAAC;AAAA,QACzB,GAAI,MAAA,GAAS,EAAE,MAAA,KAAW,EAAC;AAAA,QAC3B,aAAa,IAAA,CAAK,WAAA;AAAA,QAClB,GAAI,KAAK,SAAA,GAAY,EAAE,WAAW,IAAA,CAAK,SAAA,KAAc;AAAC,OACxD;AACA,MAAA,MAAM,KAAK,MAAA,CAAO,IAAA,CAAK,EAAE,IAAA,EAAM,kBAAA,EAAoB,SAAS,CAAA;AAE5D,MAAA,MAAM,EAAA,GAAK,KAAK,GAAA,EAAI;AACpB,MAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,QAAA,CAAS,KAAK,OAAO,CAAA;AACjD,MAAA,MAAMC,WAAAA,GAAa,IAAA,CAAK,GAAA,EAAI,GAAI,EAAA;AAChC,MAAA,MAAM,IAAA,CAAK,OAAO,IAAA,CAAK,EAAE,MAAM,mBAAA,EAAqB,QAAA,EAAU,UAAA,EAAAA,WAAAA,EAAY,CAAA;AAE1E,MAAA,gBAAA,IAAoB,SAAS,KAAA,CAAM,WAAA;AACnC,MAAA,iBAAA,IAAqB,SAAS,KAAA,CAAM,YAAA;AAEpC,MAAA,MAAM,IAAA,CAAK,aAAA,CAAc,QAAA,CAAS,OAAO,CAAA;AAGzC,MAAA,QAAQ,SAAS,UAAA;AAAY,QAC3B,KAAK,UAAA;AAAA,QACL,KAAK,eAAA,EAAiB;AACpB,UAAA,WAAA,GAAc,WAAA,CAAY,SAAS,OAAO,CAAA;AAC1C,UAAA;AAAA,QACF;AAAA,QAEA,KAAK,YAAA,EAAc;AACjB,UAAA,WAAA,GAAc,WAAA,CAAY,SAAS,OAAO,CAAA;AAC1C,UAAA,IAAA,CAAK,MAAA,CAAO,KAAK,+CAAA,EAAiD;AAAA,YAChE,YAAA,EAAc,SAAS,KAAA,CAAM;AAAA,WAC9B,CAAA;AACD,UAAA;AAAA,QACF;AAAA,QAEA,KAAK,UAAA,EAAY;AACf,UAAA,MAAM,QAAA,GAAW,eAAA,CAAgB,QAAA,CAAS,OAAO,CAAA;AACjD,UAAA,IAAI,QAAA,CAAS,WAAW,CAAA,EAAG;AAGzB,YAAA,WAAA,GAAc,WAAA,CAAY,SAAS,OAAO,CAAA;AAC1C,YAAA;AAAA,UACF;AAGA,UAAA,MAAM,OAAA,GAAU,MAAM,OAAA,CAAQ,GAAA;AAAA,YAC5B,QAAA,CAAS,GAAA,CAAI,OAAO,EAAA,KAAO;AACzB,cAAA,MAAM,IAAA,CAAK,OAAO,IAAA,CAAK;AAAA,gBACrB,IAAA,EAAM,WAAA;AAAA,gBACN,IAAI,EAAA,CAAG,EAAA;AAAA,gBACP,MAAM,EAAA,CAAG,IAAA;AAAA,gBACT,OAAO,EAAA,CAAG;AAAA,eACX,CAAA;AACD,cAAA,MAAM,EAAA,GAAK,KAAK,GAAA,EAAI;AACpB,cAAA,MAAMC,UAAS,MAAM,IAAA,CAAK,YAAY,EAAA,CAAG,IAAA,EAAM,GAAG,KAAK,CAAA;AACvD,cAAA,MAAM,GAAA,GAAM,IAAA,CAAK,GAAA,EAAI,GAAI,EAAA;AACzB,cAAA,MAAM,IAAA,CAAK,OAAO,IAAA,CAAK;AAAA,gBACrB,IAAA,EAAM,aAAA;AAAA,gBACN,IAAI,EAAA,CAAG,EAAA;AAAA,gBACP,MAAM,EAAA,CAAG,IAAA;AAAA,gBACT,MAAA,EAAAA,OAAAA;AAAA,gBACA,UAAA,EAAY;AAAA,eACb,CAAA;AACD,cAAA,OAAO,EAAE,EAAA,EAAI,MAAA,EAAAA,OAAAA,EAAO;AAAA,YACtB,CAAC;AAAA,WACH;AAKA,UAAA,MAAM,WAAA,GAAuB;AAAA,YAC3B,IAAA,EAAM,MAAA;AAAA,YACN,SAAS,OAAA,CAAQ,GAAA;AAAA,cACf,CAAC,EAAE,EAAA,EAAI,MAAA,EAAAA,SAAO,MAAqB;AAAA,gBACjC,IAAA,EAAM,aAAA;AAAA,gBACN,WAAW,EAAA,CAAG,EAAA;AAAA,gBACd,SAASA,OAAAA,CAAO,MAAA;AAAA,gBAChB,GAAIA,OAAAA,CAAO,OAAA,GAAU,EAAE,OAAA,EAAS,IAAA,KAAS;AAAC,eAC5C;AAAA;AACF,WACF;AACA,UAAA,MAAM,IAAA,CAAK,cAAc,WAAW,CAAA;AAGpC,UAAA;AAAA,QACF;AAAA,QAEA,KAAK,OAAA,EAAS;AACZ,UAAA,MAAM,IAAI,KAAA,CAAM,CAAA,qCAAA,EAAwC,YAAY,QAAA,CAAS,OAAO,CAAC,CAAA,CAAE,CAAA;AAAA,QACzF;AAAA;AAIF,MAAA,IAAI,WAAA,KAAgB,EAAA,IAAM,QAAA,CAAS,UAAA,KAAe,UAAA,EAAY;AAC5D,QAAA;AAAA,MACF;AAAA,IACF;AAEA,IAAA,IAAI,UAAA,IAAc,IAAA,CAAK,aAAA,IAAiB,WAAA,KAAgB,EAAA,EAAI;AAC1D,MAAA,gBAAA,GAAmB,IAAA;AACnB,MAAA,IAAA,CAAK,MAAA,CAAO,IAAA,CAAK,CAAA,0BAAA,EAA6B,IAAA,CAAK,aAAa,CAAA,kBAAA,CAAA,EAAsB;AAAA,QACpF,WAAW,IAAA,CAAK;AAAA,OACjB,CAAA;AACD,MAAA,MAAM,IAAA,GAAO,QAAA,CAAS,QAAA,CAAS,MAAA,GAAS,CAAC,CAAA;AACzC,MAAA,IAAI,IAAA,EAAM,WAAA,GAAc,WAAA,CAAY,IAAI,CAAA;AAAA,IAC1C;AAEA,IAAA,MAAM,UAAA,GAAa,IAAA,CAAK,GAAA,EAAI,GAAI,KAAA;AAChC,IAAA,MAAM,MAAA,GAAsB;AAAA,MAC1B,MAAA,EAAQ,WAAA;AAAA,MACR,QAAA;AAAA,MACA,UAAA;AAAA,MACA,KAAA,EAAO;AAAA,QACL,WAAA,EAAa,gBAAA;AAAA,QACb,YAAA,EAAc;AAAA,OAChB;AAAA,MACA;AAAA,KACF;AAEA,IAAA,MAAM,IAAA,CAAK,OAAO,IAAA,CAAK;AAAA,MACrB,IAAA,EAAM,WAAA;AAAA,MACN,MAAA,EAAQ,WAAA;AAAA,MACR,UAAA;AAAA,MACA;AAAA,KACD,CAAA;AACD,IAAA,IAAI,gBAAA,EAAkB;AACpB,MAAA,IAAA,CAAK,OAAO,IAAA,CAAK,uCAAA,EAAyC,EAAE,gBAAA,EAAkB,MAAM,CAAA;AAAA,IACtF;AACA,IAAA,OAAO,MAAA;AAAA,EACT;AAAA;AAAA,EAIA,MAAc,cAAc,OAAA,EAAiC;AAC3D,IAAA,MAAM,KAAK,MAAA,CAAO,IAAA,CAAK,EAAE,IAAA,EAAM,eAAA,EAAiB,SAAS,CAAA;AACzD,IAAA,IAAI,KAAK,MAAA,EAAQ;AACf,MAAA,MAAM,IAAA,CAAK,MAAA,CAAO,MAAA,CAAO,IAAA,CAAK,WAAW,OAAO,CAAA;AAAA,IAClD;AAAA,EACF;AAAA,EAEA,MAAc,WAAA,CAAY,IAAA,EAAc,KAAA,EAAqC;AAC3E,IAAA,MAAM,IAAA,GAAO,KAAK,KAAA,CAAM,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,SAAS,IAAI,CAAA;AACnD,IAAA,IAAI,CAAC,IAAA,EAAM;AACT,MAAA,OAAO;AAAA,QACL,MAAA,EAAQ,CAAA,aAAA,EAAgB,IAAI,CAAA,sCAAA,EAAyC,KAAK,KAAA,CACvE,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,IAAI,CAAA,CACjB,IAAA,CAAK,IAAI,CAAC,CAAA,CAAA;AAAA,QACb,OAAA,EAAS;AAAA,OACX;AAAA,IACF;AAEA,IAAA,MAAM,UAAA,GAAa,aAAA,CAAc,KAAA,EAAO,IAAA,CAAK,WAAW,CAAA;AACxD,IAAA,IAAI,CAAC,WAAW,KAAA,EAAO;AACrB,MAAA,OAAO;AAAA,QACL,MAAA,EAAQ,CAAA,+BAAA,EAAkC,IAAI,CAAA,GAAA,EAAM,WAAW,KAAK,CAAA,CAAA;AAAA,QACpE,OAAA,EAAS;AAAA,OACX;AAAA,IACF;AAEA,IAAA,IAAI;AACF,MAAA,OAAO,MAAM,IAAA,CAAK,OAAA,CAAQ,KAAA,EAAO,EAAE,MAAA,EAAQ,IAAA,CAAK,MAAA,EAAQ,MAAA,EAAQ,IAAA,CAAK,MAAA,EAAQ,CAAA;AAAA,IAC/E,SAAS,GAAA,EAAK;AACZ,MAAA,MAAM,UAAU,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,OAAO,GAAG,CAAA;AAC/D,MAAA,OAAO,EAAE,QAAQ,CAAA,sBAAA,EAAyB,IAAI,MAAM,OAAO,CAAA,CAAA,EAAI,SAAS,IAAA,EAAK;AAAA,IAC/E;AAAA,EACF;AACF;AAMA,SAAS,YAAY,OAAA,EAA0B;AAC7C,EAAA,IAAI,OAAO,OAAA,CAAQ,OAAA,KAAY,QAAA,SAAiB,OAAA,CAAQ,OAAA;AACxD,EAAA,OAAO,QAAQ,OAAA,CACZ,MAAA,CAAO,CAAC,CAAA,KAAsB,EAAE,IAAA,KAAS,MAAM,CAAA,CAC/C,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,IAAI,CAAA,CACjB,KAAK,IAAI,CAAA;AACd;AAEA,SAAS,gBAAgB,OAAA,EAAkC;AACzD,EAAA,IAAI,OAAO,OAAA,CAAQ,OAAA,KAAY,QAAA,SAAiB,EAAC;AACjD,EAAA,OAAO,QAAQ,OAAA,CAAQ,MAAA,CAAO,CAAC,CAAA,KAAyB,CAAA,CAAE,SAAS,UAAU,CAAA;AAC/E;AAQA,SAAS,aAAA,CAAc,OAAgB,MAAA,EAAwD;AAC7F,EAAA,IAAI,OAAO,KAAA,KAAU,QAAA,IAAY,KAAA,KAAU,IAAA,EAAM;AAC/C,IAAA,OAAO,EAAE,KAAA,EAAO,KAAA,EAAO,KAAA,EAAO,yBAAA,EAA0B;AAAA,EAC1D;AACA,EAAA,IAAI,OAAO,QAAA,EAAU;AACnB,IAAA,KAAA,MAAW,GAAA,IAAO,OAAO,QAAA,EAAU;AACjC,MAAA,IAAI,EAAE,OAAQ,KAAA,CAAA,EAAoC;AAChD,QAAA,OAAO,EAAE,KAAA,EAAO,KAAA,EAAO,KAAA,EAAO,CAAA,wBAAA,EAA2B,GAAG,CAAA,CAAA,EAAG;AAAA,MACjE;AAAA,IACF;AAAA,EACF;AACA,EAAA,OAAO,EAAE,OAAO,IAAA,EAAK;AACvB;AChTO,IAAM,oBAAN,MAA4C;AAAA,EACxC,IAAA,GAAO,WAAA;AAAA,EACP,KAAA;AAAA,EACQ,MAAA;AAAA,EACA,gBAAA;AAAA,EAEjB,WAAA,CAAY,OAAA,GAAoC,EAAC,EAAG;AAClD,IAAA,IAAA,CAAK,KAAA,GAAQ,QAAQ,KAAA,IAAS,iBAAA;AAC9B,IAAA,IAAA,CAAK,MAAA,GAAS,IAAI,SAAA,CAAU;AAAA,MAC1B,MAAA,EAAQ,OAAA,CAAQ,MAAA,IAAU,OAAA,CAAQ,GAAA,CAAI,iBAAA;AAAA,MACtC,GAAI,QAAQ,OAAA,GAAU,EAAE,SAAS,OAAA,CAAQ,OAAA,KAAY;AAAC,KACvD,CAAA;AACD,IAAA,IAAA,CAAK,gBAAA,GAAmB,QAAQ,SAAA,IAAa,IAAA;AAAA,EAC/C;AAAA,EAEA,MAAM,KAAK,OAAA,EAA6C;AACtD,IAAA,MAAM,EAAE,MAAA,EAAQ,QAAA,EAAS,GAAI,kBAAA,CAAmB,QAAQ,QAAQ,CAAA;AAEhE,IAAA,MAAM,cAAA,GAAiB,OAAA,CAAQ,KAAA,EAAO,GAAA,CAAI,qBAAqB,CAAA;AAE/D,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,MAAA,CAAO,SAAS,MAAA,CAAO;AAAA,MACjD,KAAA,EAAO,OAAA,CAAQ,KAAA,IAAS,IAAA,CAAK,KAAA;AAAA,MAC7B,GAAI,MAAA,GAAS,EAAE,MAAA,KAAW,EAAC;AAAA,MAC3B,QAAA,EAAU,QAAA,CAAS,GAAA,CAAI,kBAAkB,CAAA;AAAA,MACzC,GAAI,kBAAkB,cAAA,CAAe,MAAA,GAAS,IAAI,EAAE,KAAA,EAAO,cAAA,EAAe,GAAI,EAAC;AAAA,MAC/E,UAAA,EAAY,OAAA,CAAQ,SAAA,IAAa,IAAA,CAAK,gBAAA;AAAA,MACtC,GAAI,QAAQ,WAAA,KAAgB,MAAA,GAAY,EAAE,WAAA,EAAa,OAAA,CAAQ,WAAA,EAAY,GAAI,EAAC;AAAA,MAChF,GAAI,OAAA,CAAQ,aAAA,GAAgB,EAAE,cAAA,EAAgB,CAAC,GAAG,OAAA,CAAQ,aAAa,CAAA,EAAE,GAAI;AAAC,KAC/E,CAAA;AAED,IAAA,OAAO;AAAA,MACL,OAAA,EAAS;AAAA,QACP,IAAA,EAAM,WAAA;AAAA,QACN,OAAA,EAAS,QAAA,CAAS,OAAA,CAAQ,GAAA,CAAI,kBAAkB;AAAA,OAClD;AAAA,MACA,KAAA,EAAO;AAAA,QACL,WAAA,EAAa,SAAS,KAAA,CAAM,YAAA;AAAA,QAC5B,YAAA,EAAc,SAAS,KAAA,CAAM;AAAA,OAC/B;AAAA,MACA,UAAA,EAAY,aAAA,CAAc,QAAA,CAAS,WAAW,CAAA;AAAA,MAC9C,OAAO,QAAA,CAAS;AAAA,KAClB;AAAA,EACF;AACF;AAUA,SAAS,mBAAmB,QAAA,EAG1B;AACA,EAAA,MAAM,cAAwB,EAAC;AAC/B,EAAA,MAAM,OAAkB,EAAC;AACzB,EAAA,KAAA,MAAW,KAAK,QAAA,EAAU;AACxB,IAAA,IAAI,CAAA,CAAE,SAAS,QAAA,EAAU;AACvB,MAAA,MAAM,IAAA,GAAO,OAAO,CAAA,CAAE,OAAA,KAAY,WAAW,CAAA,CAAE,OAAA,GAAU,qBAAA,CAAsB,CAAA,CAAE,OAAO,CAAA;AACxF,MAAA,IAAI,IAAA,EAAM,WAAA,CAAY,IAAA,CAAK,IAAI,CAAA;AAAA,IACjC,CAAA,MAAO;AACL,MAAA,IAAA,CAAK,KAAK,CAAC,CAAA;AAAA,IACb;AAAA,EACF;AACA,EAAA,OAAO;AAAA,IACL,QAAQ,WAAA,CAAY,MAAA,GAAS,IAAI,WAAA,CAAY,IAAA,CAAK,MAAM,CAAA,GAAI,MAAA;AAAA,IAC5D,QAAA,EAAU;AAAA,GACZ;AACF;AAEA,SAAS,sBAAsB,MAAA,EAAyC;AACtE,EAAA,OAAO,MAAA,CACJ,MAAA,CAAO,CAAC,CAAA,KAA2C,EAAE,IAAA,KAAS,MAAM,CAAA,CACpE,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,IAAI,CAAA,CACjB,KAAK,IAAI,CAAA;AACd;AAEA,SAAS,sBAAsB,IAAA,EAAsC;AACnE,EAAA,OAAO;AAAA,IACL,MAAM,IAAA,CAAK,IAAA;AAAA,IACX,aAAa,IAAA,CAAK,WAAA;AAAA,IAClB,cAAc,IAAA,CAAK;AAAA,GACrB;AACF;AAEA,SAAS,mBAAmB,OAAA,EAA0C;AACpE,EAAA,IAAI,OAAA,CAAQ,SAAS,MAAA,EAAQ;AAC3B,IAAA,IAAI,OAAO,OAAA,CAAQ,OAAA,KAAY,QAAA,EAAU;AACvC,MAAA,OAAO,EAAE,IAAA,EAAM,MAAA,EAAQ,OAAA,EAAS,QAAQ,OAAA,EAAQ;AAAA,IAClD;AAEA,IAAA,OAAO;AAAA,MACL,IAAA,EAAM,MAAA;AAAA,MACN,OAAA,EAAS,OAAA,CAAQ,OAAA,CAAQ,GAAA,CAAI,CAAC,KAAA,KAAU;AACtC,QAAA,IAAI,KAAA,CAAM,SAAS,MAAA,EAAQ;AACzB,UAAA,OAAO,EAAE,IAAA,EAAM,MAAA,EAAiB,IAAA,EAAM,MAAM,IAAA,EAAK;AAAA,QACnD;AACA,QAAA,IAAI,KAAA,CAAM,SAAS,aAAA,EAAe;AAChC,UAAA,OAAO;AAAA,YACL,IAAA,EAAM,aAAA;AAAA,YACN,aAAa,KAAA,CAAM,SAAA;AAAA,YACnB,OAAA,EACE,OAAO,KAAA,CAAM,OAAA,KAAY,QAAA,GACrB,KAAA,CAAM,OAAA,GACN,KAAA,CAAM,OAAA,CAAQ,GAAA,CAAI,CAAC,CAAA,KAAM;AACvB,cAAA,IAAI,CAAA,CAAE,SAAS,MAAA,EAAQ,OAAO,EAAE,IAAA,EAAM,MAAA,EAAiB,IAAA,EAAM,CAAA,CAAE,IAAA,EAAK;AAEpE,cAAA,OAAO,EAAE,IAAA,EAAM,MAAA,EAAiB,MAAM,IAAA,CAAK,SAAA,CAAU,CAAC,CAAA,EAAE;AAAA,YAC1D,CAAC,CAAA;AAAA,YACP,GAAI,KAAA,CAAM,OAAA,GAAU,EAAE,QAAA,EAAU,IAAA,KAAS;AAAC,WAC5C;AAAA,QACF;AAGA,QAAA,IAAI,KAAA,CAAM,SAAS,UAAA,EAAY;AAC7B,UAAA,OAAO;AAAA,YACL,IAAA,EAAM,UAAA;AAAA,YACN,IAAI,KAAA,CAAM,EAAA;AAAA,YACV,MAAM,KAAA,CAAM,IAAA;AAAA,YACZ,OAAO,KAAA,CAAM;AAAA,WACf;AAAA,QACF;AACA,QAAA,OAAO,EAAE,IAAA,EAAM,MAAA,EAAiB,IAAA,EAAM,EAAA,EAAG;AAAA,MAC3C,CAAC;AAAA,KACH;AAAA,EACF;AAEA,EAAA,IAAI,OAAA,CAAQ,SAAS,WAAA,EAAa;AAChC,IAAA,IAAI,OAAO,OAAA,CAAQ,OAAA,KAAY,QAAA,EAAU;AACvC,MAAA,OAAO,EAAE,IAAA,EAAM,WAAA,EAAa,OAAA,EAAS,QAAQ,OAAA,EAAQ;AAAA,IACvD;AACA,IAAA,OAAO;AAAA,MACL,IAAA,EAAM,WAAA;AAAA,MACN,OAAA,EAAS,OAAA,CAAQ,OAAA,CAAQ,GAAA,CAAI,CAAC,KAAA,KAAU;AACtC,QAAA,IAAI,KAAA,CAAM,SAAS,MAAA,EAAQ;AACzB,UAAA,OAAO,EAAE,IAAA,EAAM,MAAA,EAAiB,IAAA,EAAM,MAAM,IAAA,EAAK;AAAA,QACnD;AACA,QAAA,IAAI,KAAA,CAAM,SAAS,UAAA,EAAY;AAC7B,UAAA,OAAO;AAAA,YACL,IAAA,EAAM,UAAA;AAAA,YACN,IAAI,KAAA,CAAM,EAAA;AAAA,YACV,MAAM,KAAA,CAAM,IAAA;AAAA,YACZ,OAAO,KAAA,CAAM;AAAA,WACf;AAAA,QACF;AAEA,QAAA,OAAO,EAAE,IAAA,EAAM,MAAA,EAAiB,IAAA,EAAM,EAAA,EAAG;AAAA,MAC3C,CAAC;AAAA,KACH;AAAA,EACF;AAKA,EAAA,OAAO,EAAE,IAAA,EAAM,MAAA,EAAQ,OAAA,EAAS,EAAA,EAAG;AACrC;AAEA,SAAS,mBAAmB,KAAA,EAA6C;AACvE,EAAA,IAAI,KAAA,CAAM,SAAS,MAAA,EAAQ;AACzB,IAAA,OAAO,EAAE,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAM,MAAM,IAAA,EAAK;AAAA,EAC1C;AACA,EAAA,IAAI,KAAA,CAAM,SAAS,UAAA,EAAY;AAC7B,IAAA,OAAO;AAAA,MACL,IAAA,EAAM,UAAA;AAAA,MACN,IAAI,KAAA,CAAM,EAAA;AAAA,MACV,MAAM,KAAA,CAAM,IAAA;AAAA,MACZ,OAAO,KAAA,CAAM;AAAA,KACf;AAAA,EACF;AAGA,EAAA,OAAO,EAAE,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAM,EAAA,EAAG;AAClC;AAEA,SAAS,cAAc,MAAA,EAAmC;AACxD,EAAA,QAAQ,MAAA;AAAQ,IACd,KAAK,UAAA;AACH,MAAA,OAAO,UAAA;AAAA,IACT,KAAK,UAAA;AACH,MAAA,OAAO,UAAA;AAAA,IACT,KAAK,YAAA;AACH,MAAA,OAAO,YAAA;AAAA,IACT,KAAK,eAAA;AACH,MAAA,OAAO,eAAA;AAAA,IACT;AACE,MAAA,OAAO,OAAA;AAAA;AAEb;AC7LO,IAAM,iBAAN,MAAyC;AAAA,EACrC,IAAA,GAAO,QAAA;AAAA,EACP,KAAA;AAAA,EACQ,MAAA;AAAA,EAEjB,WAAA,CAAY,OAAA,GAAiC,EAAC,EAAG;AAC/C,IAAA,IAAA,CAAK,KAAA,GAAQ,QAAQ,KAAA,IAAS,OAAA;AAC9B,IAAA,IAAA,CAAK,MAAA,GAAS,IAAI,MAAA,CAAO;AAAA,MACvB,MAAA,EAAQ,OAAA,CAAQ,MAAA,IAAU,OAAA,CAAQ,GAAA,CAAI,cAAA;AAAA,MACtC,GAAI,QAAQ,OAAA,GAAU,EAAE,SAAS,OAAA,CAAQ,OAAA,KAAY,EAAC;AAAA,MACtD,GAAI,QAAQ,YAAA,GAAe,EAAE,cAAc,OAAA,CAAQ,YAAA,KAAiB;AAAC,KACtE,CAAA;AAAA,EACH;AAAA,EAEA,MAAM,KAAK,OAAA,EAA6C;AACtD,IAAA,MAAM,EAAE,MAAA,EAAQ,QAAA,EAAS,GAAIC,mBAAAA,CAAmB,QAAQ,QAAQ,CAAA;AAEhE,IAAA,MAAM,WAAA,GAAc,OAAA,CAAQ,KAAA,EAAO,GAAA,CAAI,YAAY,CAAA;AAEnD,IAAA,MAAM,WAAW,MAAM,IAAA,CAAK,MAAA,CAAO,IAAA,CAAK,YAAY,MAAA,CAAO;AAAA,MACzD,KAAA,EAAO,OAAA,CAAQ,KAAA,IAAS,IAAA,CAAK,KAAA;AAAA,MAC7B,GAAI,MAAA,GAAS,EAAE,QAAA,EAAU,CAAC,EAAE,IAAA,EAAM,QAAA,EAAmB,OAAA,EAAS,MAAA,EAAQ,CAAA,KAAM,EAAC;AAAA,MAC7E,QAAA,EAAU;AAAA,QACR,GAAI,MAAA,GAAS,CAAC,EAAE,IAAA,EAAM,UAAmB,OAAA,EAAS,MAAA,EAAQ,CAAA,GAAI,EAAC;AAAA,QAC/D,GAAG,QAAA,CAAS,OAAA,CAAQ,CAAC,CAAA,KAAM,gBAAA,CAAiB,CAAC,CAAC;AAAA,OAChD;AAAA,MACA,GAAI,eAAe,WAAA,CAAY,MAAA,GAAS,IAAI,EAAE,KAAA,EAAO,WAAA,EAAY,GAAI,EAAC;AAAA,MACtE,GAAI,QAAQ,WAAA,KAAgB,MAAA,GAAY,EAAE,WAAA,EAAa,OAAA,CAAQ,WAAA,EAAY,GAAI,EAAC;AAAA,MAChF,GAAI,QAAQ,SAAA,GAAY,EAAE,YAAY,OAAA,CAAQ,SAAA,KAAc,EAAC;AAAA,MAC7D,GAAI,OAAA,CAAQ,aAAA,GAAgB,EAAE,IAAA,EAAM,CAAC,GAAG,OAAA,CAAQ,aAAa,CAAA,EAAE,GAAI;AAAC,KACrE,CAAA;AAED,IAAA,MAAM,MAAA,GAAS,QAAA,CAAS,OAAA,CAAQ,CAAC,CAAA;AACjC,IAAA,IAAI,CAAC,MAAA,EAAQ;AACX,MAAA,MAAM,IAAI,MAAM,4BAA4B,CAAA;AAAA,IAC9C;AACA,IAAA,MAAM,mBAAmB,MAAA,CAAO,OAAA;AAEhC,IAAA,OAAO;AAAA,MACL,OAAA,EAAS;AAAA,QACP,IAAA,EAAM,WAAA;AAAA,QACN,OAAA,EAAS,2BAA2B,gBAAgB;AAAA,OACtD;AAAA,MACA,KAAA,EAAO;AAAA,QACL,WAAA,EAAa,QAAA,CAAS,KAAA,EAAO,aAAA,IAAiB,CAAA;AAAA,QAC9C,YAAA,EAAc,QAAA,CAAS,KAAA,EAAO,iBAAA,IAAqB;AAAA,OACrD;AAAA,MACA,UAAA,EAAYC,cAAAA,CAAc,MAAA,CAAO,aAAa,CAAA;AAAA,MAC9C,OAAO,QAAA,CAAS;AAAA,KAClB;AAAA,EACF;AACF;AAMA,SAASD,oBAAmB,QAAA,EAG1B;AACA,EAAA,MAAM,cAAwB,EAAC;AAC/B,EAAA,MAAM,OAAkB,EAAC;AACzB,EAAA,KAAA,MAAW,KAAK,QAAA,EAAU;AACxB,IAAA,IAAI,CAAA,CAAE,SAAS,QAAA,EAAU;AACvB,MAAA,MAAM,IAAA,GAAO,OAAO,CAAA,CAAE,OAAA,KAAY,WAAW,CAAA,CAAE,OAAA,GAAUE,sBAAAA,CAAsB,CAAA,CAAE,OAAO,CAAA;AACxF,MAAA,IAAI,IAAA,EAAM,WAAA,CAAY,IAAA,CAAK,IAAI,CAAA;AAAA,IACjC,CAAA,MAAO;AACL,MAAA,IAAA,CAAK,KAAK,CAAC,CAAA;AAAA,IACb;AAAA,EACF;AACA,EAAA,OAAO;AAAA,IACL,QAAQ,WAAA,CAAY,MAAA,GAAS,IAAI,WAAA,CAAY,IAAA,CAAK,MAAM,CAAA,GAAI,MAAA;AAAA,IAC5D,QAAA,EAAU;AAAA,GACZ;AACF;AAEA,SAASA,uBAAsB,MAAA,EAAyC;AACtE,EAAA,OAAO,MAAA,CACJ,MAAA,CAAO,CAAC,CAAA,KAA2C,EAAE,IAAA,KAAS,MAAM,CAAA,CACpE,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,IAAI,CAAA,CACjB,KAAK,IAAI,CAAA;AACd;AAEA,SAAS,aAAa,IAAA,EAAkE;AACtF,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,UAAA;AAAA,IACN,QAAA,EAAU;AAAA,MACR,MAAM,IAAA,CAAK,IAAA;AAAA,MACX,aAAa,IAAA,CAAK,WAAA;AAAA,MAClB,YAAY,IAAA,CAAK;AAAA;AACnB,GACF;AACF;AAOA,SAAS,iBAAiB,OAAA,EAAwE;AAChG,EAAA,IAAI,OAAA,CAAQ,SAAS,QAAA,EAAU;AAE7B,IAAA,MAAM,IAAA,GACJ,OAAO,OAAA,CAAQ,OAAA,KAAY,WACvB,OAAA,CAAQ,OAAA,GACRA,sBAAAA,CAAsB,OAAA,CAAQ,OAAO,CAAA;AAC3C,IAAA,OAAO,CAAC,EAAE,IAAA,EAAM,QAAA,EAAU,OAAA,EAAS,MAAM,CAAA;AAAA,EAC3C;AAEA,EAAA,IAAI,OAAA,CAAQ,SAAS,MAAA,EAAQ;AAC3B,IAAA,IAAI,OAAO,OAAA,CAAQ,OAAA,KAAY,QAAA,EAAU;AACvC,MAAA,OAAO,CAAC,EAAE,IAAA,EAAM,QAAQ,OAAA,EAAS,OAAA,CAAQ,SAAS,CAAA;AAAA,IACpD;AAEA,IAAA,MAAM,WAAA,GAAc,QAAQ,OAAA,CAAQ,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,SAAS,aAAa,CAAA;AAC1E,IAAA,MAAM,UAAA,GAAa,QAAQ,OAAA,CAAQ,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,SAAS,MAAM,CAAA;AAElE,IAAA,MAAM,MAA4D,EAAC;AACnE,IAAA,IAAI,UAAA,CAAW,SAAS,CAAA,EAAG;AACzB,MAAA,GAAA,CAAI,IAAA,CAAK;AAAA,QACP,IAAA,EAAM,MAAA;AAAA,QACN,OAAA,EAAS,WAAW,GAAA,CAAI,CAAC,MAAO,CAAA,CAAuB,IAAI,CAAA,CAAE,IAAA,CAAK,IAAI;AAAA,OACvE,CAAA;AAAA,IACH;AACA,IAAA,KAAA,MAAW,MAAM,WAAA,EAAa;AAC5B,MAAA,IAAI,EAAA,CAAG,SAAS,aAAA,EAAe;AAC/B,MAAA,GAAA,CAAI,IAAA,CAAK;AAAA,QACP,IAAA,EAAM,MAAA;AAAA,QACN,cAAc,EAAA,CAAG,SAAA;AAAA,QACjB,OAAA,EACE,OAAO,EAAA,CAAG,OAAA,KAAY,WAClB,EAAA,CAAG,OAAA,GACH,EAAA,CAAG,OAAA,CAAQ,GAAA,CAAI,CAAC,MAAO,CAAA,CAAE,IAAA,KAAS,MAAA,GAAS,CAAA,CAAE,IAAA,GAAO,IAAA,CAAK,UAAU,CAAC,CAAE,CAAA,CAAE,IAAA,CAAK,IAAI;AAAA,OACxF,CAAA;AAAA,IACH;AACA,IAAA,OAAO,GAAA;AAAA,EACT;AAEA,EAAA,IAAI,OAAA,CAAQ,SAAS,WAAA,EAAa;AAChC,IAAA,IAAI,OAAO,OAAA,CAAQ,OAAA,KAAY,QAAA,EAAU;AACvC,MAAA,OAAO,CAAC,EAAE,IAAA,EAAM,aAAa,OAAA,EAAS,OAAA,CAAQ,SAAS,CAAA;AAAA,IACzD;AACA,IAAA,MAAM,YAAsB,EAAC;AAC7B,IAAA,MAAM,YAAqE,EAAC;AAC5E,IAAA,KAAA,MAAW,KAAA,IAAS,QAAQ,OAAA,EAAS;AACnC,MAAA,IAAI,KAAA,CAAM,SAAS,MAAA,EAAQ;AACzB,QAAA,SAAA,CAAU,IAAA,CAAK,MAAM,IAAI,CAAA;AAAA,MAC3B,CAAA,MAAA,IAAW,KAAA,CAAM,IAAA,KAAS,UAAA,EAAY;AACpC,QAAA,SAAA,CAAU,IAAA,CAAK;AAAA,UACb,IAAI,KAAA,CAAM,EAAA;AAAA,UACV,IAAA,EAAM,UAAA;AAAA,UACN,QAAA,EAAU;AAAA,YACR,MAAM,KAAA,CAAM,IAAA;AAAA,YACZ,WAAW,IAAA,CAAK,SAAA,CAAU,KAAA,CAAM,KAAA,IAAS,EAAE;AAAA;AAC7C,SACD,CAAA;AAAA,MACH;AAAA,IACF;AACA,IAAA,MAAM,GAAA,GAAmE;AAAA,MACvE,IAAA,EAAM,WAAA;AAAA,MACN,SAAS,SAAA,CAAU,MAAA,GAAS,IAAI,SAAA,CAAU,IAAA,CAAK,IAAI,CAAA,GAAI;AAAA,KACzD;AACA,IAAA,IAAI,SAAA,CAAU,SAAS,CAAA,EAAG;AACxB,MAAA,GAAA,CAAI,UAAA,GAAa,SAAA;AAAA,IACnB;AACA,IAAA,OAAO,CAAC,GAAG,CAAA;AAAA,EACb;AAIA,EAAA,IAAI,OAAA,CAAQ,SAAS,MAAA,EAAQ;AAC3B,IAAA,MAAM,IAAA,GACJ,OAAO,OAAA,CAAQ,OAAA,KAAY,WACvB,OAAA,CAAQ,OAAA,GACRA,sBAAAA,CAAsB,OAAA,CAAQ,OAAO,CAAA;AAC3C,IAAA,OAAO;AAAA,MACL;AAAA,QACE,IAAA,EAAM,MAAA;AAAA,QACN,YAAA,EAAc,OAAA,CAAQ,UAAA,IAAc,OAAA,CAAQ,IAAA,IAAQ,SAAA;AAAA,QACpD,OAAA,EAAS;AAAA;AACX,KACF;AAAA,EACF;AAEA,EAAA,OAAO,EAAC;AACV;AAEA,SAAS,2BACP,GAAA,EACgB;AAChB,EAAA,MAAM,SAAyB,EAAC;AAChC,EAAA,IAAI,IAAI,OAAA,EAAS;AACf,IAAA,MAAA,CAAO,KAAK,EAAE,IAAA,EAAM,QAAQ,IAAA,EAAM,GAAA,CAAI,SAAS,CAAA;AAAA,EACjD;AACA,EAAA,IAAI,IAAI,UAAA,EAAY;AAClB,IAAA,KAAA,MAAW,IAAA,IAAQ,IAAI,UAAA,EAAY;AACjC,MAAA,IAAI,IAAA,CAAK,SAAS,UAAA,EAAY;AAC9B,MAAA,IAAI,SAAkB,EAAC;AACvB,MAAA,IAAI;AACF,QAAA,MAAA,GAAS,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,QAAA,CAAS,SAAS,CAAA;AAAA,MAC7C,CAAA,CAAA,MAAQ;AACN,QAAA,MAAA,GAAS,EAAE,WAAA,EAAa,IAAA,CAAK,QAAA,CAAS,SAAA,EAAU;AAAA,MAClD;AACA,MAAA,MAAA,CAAO,IAAA,CAAK;AAAA,QACV,IAAA,EAAM,UAAA;AAAA,QACN,IAAI,IAAA,CAAK,EAAA;AAAA,QACT,IAAA,EAAM,KAAK,QAAA,CAAS,IAAA;AAAA,QACpB,KAAA,EAAO;AAAA,OACR,CAAA;AAAA,IACH;AAAA,EACF;AACA,EAAA,OAAO,MAAA;AACT;AAEA,SAASD,eAAc,MAAA,EAA+C;AACpE,EAAA,QAAQ,MAAA;AAAQ,IACd,KAAK,MAAA;AACH,MAAA,OAAO,UAAA;AAAA,IACT,KAAK,YAAA;AAAA,IACL,KAAK,eAAA;AACH,MAAA,OAAO,UAAA;AAAA,IACT,KAAK,QAAA;AACH,MAAA,OAAO,YAAA;AAAA,IACT,KAAK,gBAAA;AACH,MAAA,OAAO,eAAA;AAAA,IACT;AACE,MAAA,OAAO,OAAA;AAAA;AAEb;;;AC3PO,SAAS,WAAmB,IAAA,EAKR;AACzB,EAAA,OAAO;AAAA,IACL,MAAM,IAAA,CAAK,IAAA;AAAA,IACX,aAAa,IAAA,CAAK,WAAA;AAAA,IAClB,aAAa,IAAA,CAAK,WAAA;AAAA,IAClB,OAAA,EAAS,OAAO,KAAA,KAAU;AACxB,MAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,OAAA,CAAQ,KAAK,CAAA;AACvC,MAAA,OAAO,OAAO,MAAA,KAAW,QAAA,GAAW,EAAE,MAAA,EAAQ,QAAO,GAAI,MAAA;AAAA,IAC3D;AAAA,GACF;AACF;AAOO,SAAS,WAAA,CACd,aACA,OAAA,EACiB;AACjB,EAAA,OAAO,OAAA,EAAS,IAAA,GACZ,EAAE,IAAA,EAAM,QAAA,EAAU,WAAA,EAAa,IAAA,EAAM,OAAA,CAAQ,IAAA,EAAK,GAClD,EAAE,IAAA,EAAM,UAAU,WAAA,EAAY;AACpC;AAGO,SAAS,YAAY,WAAA,EAAsC;AAChE,EAAA,OAAO,EAAE,IAAA,EAAM,QAAA,EAAU,WAAA,EAAY;AACvC;AAGO,SAAS,aAAa,WAAA,EAAsC;AACjE,EAAA,OAAO,EAAE,IAAA,EAAM,SAAA,EAAW,WAAA,EAAY;AACxC;AAGO,SAAS,aAAa,WAAA,EAAsC;AACjE,EAAA,OAAO,EAAE,IAAA,EAAM,SAAA,EAAW,WAAA,EAAY;AACxC;AAGO,SAAS,UAAA,CAAW,aAAqB,KAAA,EAAyC;AACvF,EAAA,OAAO,EAAE,IAAA,EAAM,OAAA,EAAS,WAAA,EAAa,KAAA,EAAM;AAC7C;AAGO,SAAS,WAAA,CACd,WAAA,EACA,UAAA,EACA,QAAA,EACiB;AACjB,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,QAAA;AAAA,IACN,WAAA;AAAA,IACA,UAAA;AAAA,IACA,GAAI,QAAA,GAAW,EAAE,QAAA,KAAa;AAAC,GACjC;AACF;AAMO,SAAS,YAAA,CACd,YACA,QAAA,EACY;AACZ,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,QAAA;AAAA,IACN,UAAA;AAAA,IACA,GAAI,QAAA,GAAW,EAAE,QAAA,KAAa;AAAC,GACjC;AACF;AC1EO,IAAM,OAAO,UAAA,CAAsB;AAAA,EACxC,IAAA,EAAM,MAAA;AAAA,EACN,WAAA,EACE,0IAAA;AAAA,EACF,WAAA,EAAa,YAAA;AAAA,IACX;AAAA,MACE,IAAA,EAAM,YAAY,sDAAsD,CAAA;AAAA,MACxE,MAAA,EAAQ,aAAa,4DAA4D,CAAA;AAAA,MACjF,KAAA,EAAO,aAAa,iDAAiD;AAAA,KACvE;AAAA,IACA,CAAC,MAAM;AAAA,GACT;AAAA,EACA,OAAA,EAAS,OAAO,KAAA,KAAU;AACxB,IAAA,MAAM,QAAA,GAAW,OAAA,CAAQ,KAAA,CAAM,IAAI,CAAA;AACnC,IAAA,MAAM,MAAA,GAAS,MAAM,MAAA,IAAU,CAAA;AAC/B,IAAA,MAAM,KAAA,GAAQ,MAAM,KAAA,IAAS,GAAA;AAE7B,IAAA,IAAI,IAAA;AACJ,IAAA,IAAI;AACF,MAAA,IAAA,GAAO,MAAMJ,QAAAA,CAAG,QAAA,CAAS,QAAA,EAAU,OAAO,CAAA;AAAA,IAC5C,SAAS,GAAA,EAAK;AACZ,MAAA,MAAM,UAAU,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,OAAO,GAAG,CAAA;AAC/D,MAAA,OAAO,CAAA,oBAAA,EAAuB,KAAA,CAAM,IAAI,CAAA,GAAA,EAAM,OAAO,CAAA,CAAA;AAAA,IACvD;AAEA,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,KAAA,CAAM,IAAI,CAAA;AAC7B,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,SAAS,CAAC,CAAA;AACpC,IAAA,MAAM,MAAM,IAAA,CAAK,GAAA,CAAI,KAAA,CAAM,MAAA,EAAQ,QAAQ,KAAK,CAAA;AAChD,IAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,KAAA,CAAM,KAAA,EAAO,GAAG,CAAA;AAGpC,IAAA,MAAM,WAAW,KAAA,CAAM,GAAA,CAAI,CAAC,IAAA,EAAM,CAAA,KAAM,GAAG,MAAA,CAAO,KAAA,GAAQ,CAAA,GAAI,CAAC,EAAE,QAAA,CAAS,CAAA,EAAG,GAAG,CAAC,CAAA,CAAA,EAAK,IAAI,CAAA,CAAE,CAAA;AAC5F,IAAA,MAAM,MAAA,GAAS,KAAA,CAAM,MAAA,GAAS,GAAA,GAAM;AAAA,KAAA,EAAU,KAAA,CAAM,SAAS,GAAG,CAAA;AAAA,CAAA,GAAmB,EAAA;AACnF,IAAA,OAAO,QAAA,CAAS,IAAA,CAAK,IAAI,CAAA,GAAI,MAAA;AAAA,EAC/B;AACF,CAAC;ACvCM,IAAM,QAAQ,UAAA,CAAuB;AAAA,EAC1C,IAAA,EAAM,OAAA;AAAA,EACN,WAAA,EACE,+KAAA;AAAA,EACF,WAAA,EAAa,YAAA;AAAA,IACX;AAAA,MACE,IAAA,EAAM,YAAY,sDAAsD,CAAA;AAAA,MACxE,OAAA,EAAS,YAAY,+BAA+B;AAAA,KACtD;AAAA,IACA,CAAC,QAAQ,SAAS;AAAA,GACpB;AAAA,EACA,OAAA,EAAS,OAAO,KAAA,KAAU;AACxB,IAAA,MAAM,QAAA,GAAWM,OAAAA,CAAQ,KAAA,CAAM,IAAI,CAAA;AACnC,IAAA,IAAI;AACF,MAAA,MAAMN,QAAAA,CAAG,MAAMO,OAAAA,CAAQ,QAAQ,GAAG,EAAE,SAAA,EAAW,MAAM,CAAA;AACrD,MAAA,MAAMP,QAAAA,CAAG,SAAA,CAAU,QAAA,EAAU,KAAA,CAAM,SAAS,OAAO,CAAA;AACnD,MAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,UAAA,CAAW,KAAA,CAAM,SAAS,OAAO,CAAA;AACtD,MAAA,OAAO,CAAA,MAAA,EAAS,KAAK,CAAA,UAAA,EAAa,QAAQ,CAAA,CAAA;AAAA,IAC5C,SAAS,GAAA,EAAK;AACZ,MAAA,MAAM,UAAU,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,OAAO,GAAG,CAAA;AAC/D,MAAA,OAAO,CAAA,oBAAA,EAAuB,KAAA,CAAM,IAAI,CAAA,GAAA,EAAM,OAAO,CAAA,CAAA;AAAA,IACvD;AAAA,EACF;AACF,CAAC;ACjBM,IAAM,OAAO,UAAA,CAAsB;AAAA,EACxC,IAAA,EAAM,MAAA;AAAA,EACN,WAAA,EACE,8NAAA;AAAA,EACF,WAAA,EAAa,YAAA;AAAA,IACX;AAAA,MACE,IAAA,EAAM,YAAY,sDAAsD,CAAA;AAAA,MACxE,OAAA,EAAS,YAAY,iEAAiE,CAAA;AAAA,MACtF,OAAA,EAAS,YAAY,8BAA8B;AAAA,KACrD;AAAA,IACA,CAAC,MAAA,EAAQ,SAAA,EAAW,SAAS;AAAA,GAC/B;AAAA,EACA,OAAA,EAAS,OAAO,KAAA,KAAU;AACxB,IAAA,MAAM,QAAA,GAAWM,OAAAA,CAAQ,KAAA,CAAM,IAAI,CAAA;AAEnC,IAAA,IAAI,QAAA;AACJ,IAAA,IAAI;AACF,MAAA,QAAA,GAAW,MAAMN,QAAAA,CAAG,QAAA,CAAS,QAAA,EAAU,OAAO,CAAA;AAAA,IAChD,SAAS,GAAA,EAAK;AACZ,MAAA,MAAM,UAAU,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,OAAO,GAAG,CAAA;AAC/D,MAAA,OAAO,CAAA,oBAAA,EAAuB,KAAA,CAAM,IAAI,CAAA,GAAA,EAAM,OAAO,CAAA,CAAA;AAAA,IACvD;AAGA,IAAA,IAAI,KAAA,GAAQ,CAAA;AACZ,IAAA,IAAI,GAAA,GAAM,EAAA;AACV,IAAA,IAAI,UAAA,GAAa,CAAA;AACjB,IAAA,OAAO,IAAA,EAAM;AACX,MAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,OAAA,CAAQ,KAAA,CAAM,SAAS,UAAU,CAAA;AACxD,MAAA,IAAI,UAAU,EAAA,EAAI;AAClB,MAAA,KAAA,IAAS,CAAA;AACT,MAAA,GAAA,GAAM,KAAA;AACN,MAAA,UAAA,GAAa,KAAA,GAAQ,CAAA;AAAA,IACvB;AAEA,IAAA,IAAI,UAAU,CAAA,EAAG;AACf,MAAA,OAAO,CAAA,kCAAA,EAAqC,MAAM,IAAI,CAAA,sEAAA,CAAA;AAAA,IACxD;AACA,IAAA,IAAI,QAAQ,CAAA,EAAG;AACb,MAAA,OAAO,CAAA,uBAAA,EAA0B,KAAK,CAAA,eAAA,EAAkB,KAAA,CAAM,IAAI,CAAA,0GAAA,CAAA;AAAA,IACpE;AAEA,IAAA,MAAM,OAAA,GACJ,QAAA,CAAS,KAAA,CAAM,CAAA,EAAG,GAAG,CAAA,GAAI,KAAA,CAAM,OAAA,GAAU,QAAA,CAAS,KAAA,CAAM,GAAA,GAAM,KAAA,CAAM,QAAQ,MAAM,CAAA;AACpF,IAAA,IAAI;AACF,MAAA,MAAMA,QAAAA,CAAG,SAAA,CAAU,QAAA,EAAU,OAAA,EAAS,OAAO,CAAA;AAC7C,MAAA,OAAO,CAAA,OAAA,EAAU,QAAQ,CAAA,WAAA,EAAc,KAAA,CAAM,QAAQ,MAAM,CAAA,YAAA,EAAe,KAAA,CAAM,OAAA,CAAQ,MAAM,CAAA,OAAA,CAAA;AAAA,IAChG,SAAS,GAAA,EAAK;AACZ,MAAA,MAAM,UAAU,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,OAAO,GAAG,CAAA;AAC/D,MAAA,OAAO,CAAA,oBAAA,EAAuB,KAAA,CAAM,IAAI,CAAA,GAAA,EAAM,OAAO,CAAA,CAAA;AAAA,IACvD;AAAA,EACF;AACF,CAAC;ACnDD,IAAM,SAAA,GAAY,UAAU,IAAI,CAAA;AAIhC,IAAM,aAAA,GAAmC;AAAA,EACvC,qDAAA;AAAA;AAAA,EACA,qDAAA;AAAA;AAAA,EACA,uCAAA;AAAA;AAAA,EACA,gDAAA;AAAA;AAAA,EACA,oCAAA;AAAA;AAAA,EACA,6BAAA;AAAA;AAAA,EACA,6BAAA;AAAA;AAAA,EACA;AAAA;AACF,CAAA;AAEA,IAAM,kBAAA,GAAqB,GAAA;AAC3B,IAAM,cAAA,GAAiB,GAAA;AAWhB,IAAM,OAAO,UAAA,CAAsB;AAAA,EACxC,IAAA,EAAM,MAAA;AAAA,EACN,WAAA,EACE,8OAAA;AAAA,EACF,WAAA,EAAa,YAAA;AAAA,IACX;AAAA,MACE,OAAA,EAAS,YAAY,+BAA+B,CAAA;AAAA,MACpD,WAAA,EAAa,YAAY,8DAA8D,CAAA;AAAA,MACvF,OAAA,EAAS,aAAa,uDAAuD;AAAA,KAC/E;AAAA,IACA,CAAC,SAAS;AAAA,GACZ;AAAA,EACA,OAAA,EAAS,OAAO,KAAA,KAAU;AAExB,IAAA,KAAA,MAAW,WAAW,aAAA,EAAe;AACnC,MAAA,IAAI,OAAA,CAAQ,IAAA,CAAK,KAAA,CAAM,OAAO,CAAA,EAAG;AAC/B,QAAA,OAAO,2FAA2F,OAAO;;AAAA,sDAAA,CAAA;AAAA,MAC3G;AAAA,IACF;AAEA,IAAA,MAAM,UAAU,IAAA,CAAK,GAAA,CAAI,KAAA,CAAM,OAAA,IAAW,oBAAoB,cAAc,CAAA;AAE5E,IAAA,IAAI;AACF,MAAA,MAAM,EAAE,MAAA,EAAQ,MAAA,EAAO,GAAI,MAAM,UAAU,KAAA,CAAM,OAAA,EAAS,EAAE,OAAA,EAAS,CAAA;AACrE,MAAA,MAAM,MAAM,MAAA,GAAS,CAAA;AAAA,EAAY,MAAM,CAAA,CAAA,GAAK,aAAA;AAC5C,MAAA,MAAM,MAAM,MAAA,GAAS;AAAA;AAAA,EAAc,MAAM,CAAA,CAAA,GAAK,EAAA;AAC9C,MAAA,OAAO,CAAA,EAAG,GAAG,CAAA,EAAG,GAAG,GAAG,IAAA,EAAK;AAAA,IAC7B,SAAS,GAAA,EAAK;AACZ,MAAA,MAAM,CAAA,GAAI,GAAA;AAOV,MAAA,IAAI,EAAE,MAAA,EAAQ;AACZ,QAAA,OAAO,kCAAkC,OAAO,CAAA,6DAAA,CAAA;AAAA,MAClD;AACA,MAAA,MAAM,GAAA,GAAM,EAAE,MAAA,GAAS,CAAA;AAAA,EAAY,EAAE,MAAM;AAAA,CAAA,GAAO,EAAA;AAClD,MAAA,MAAM,MAAA,GAAS,EAAE,MAAA,GAAS,CAAA;AAAA,EAAY,EAAE,MAAM;AAAA,CAAA,GAAO,EAAA;AACrD,MAAA,OAAO,CAAA,gCAAA,EAAmC,CAAA,CAAE,IAAA,IAAQ,SAAS,CAAA;AAAA,EAAM,GAAG,CAAA,EAAG,MAAM,CAAA,SAAA,EAAY,CAAA,CAAE,WAAW,SAAS,CAAA,CAAA;AAAA,IACnH;AAAA,EACF;AACF,CAAC;ACnFD,IAAMQ,UAAAA,GAAYC,UAAUC,IAAI,CAAA;AAezB,IAAM,OAAO,UAAA,CAAsB;AAAA,EACxC,IAAA,EAAM,MAAA;AAAA,EACN,WAAA,EAAa,CAAA,gNAAA,CAAA;AAAA,EACb,WAAA,EAAa,YAAA;AAAA,IACX;AAAA,MACE,OAAA,EAAS,YAAY,8BAA8B,CAAA;AAAA,MACnD,IAAA,EAAM,YAAY,6DAA6D,CAAA;AAAA,MAC/E,IAAA,EAAM,YAAY,2DAA2D,CAAA;AAAA,MAC7E,UAAA,EAAY,aAAa,0CAA0C,CAAA;AAAA,MACnE,KAAA,EAAO,aAAa,2DAA2D;AAAA,KACjF;AAAA,IACA,CAAC,SAAS;AAAA,GACZ;AAAA,EACA,OAAA,EAAS,OAAO,KAAA,KAAU;AACxB,IAAA,MAAM,KAAA,GAAQ,MAAM,KAAA,IAAS,GAAA;AAC7B,IAAA,MAAM,MAAA,GAAS,MAAM,IAAA,IAAQ,GAAA;AAE7B,IAAA,IAAI;AACF,MAAA,MAAM,IAAA,GAAO;AAAA,QACX,eAAA;AAAA,QACA,cAAA;AAAA,QACA,eAAA;AAAA,QACA,GAAI,KAAA,CAAM,UAAA,GAAa,CAAC,eAAe,IAAI,EAAC;AAAA,QAC5C,GAAI,MAAM,IAAA,GAAO,CAAC,UAAU,KAAA,CAAM,IAAI,CAAA,CAAE,CAAA,GAAI,EAAC;AAAA,QAC7C,IAAA;AAAA,QACA,KAAA,CAAM,OAAA;AAAA,QACN;AAAA,OACF;AACA,MAAA,MAAM,EAAE,MAAA,EAAO,GAAI,MAAMF,UAAAA,CAAU,CAAA,GAAA,EAAM,IAAA,CAAK,GAAA,CAAI,UAAU,CAAA,CAAE,IAAA,CAAK,GAAG,CAAC,CAAA,CAAA,EAAI;AAAA,QACzE,SAAA,EAAW,KAAK,IAAA,GAAO;AAAA,OACxB,CAAA;AACD,MAAA,OAAO,cAAA,CAAe,QAAQ,KAAK,CAAA;AAAA,IACrC,SAAS,GAAA,EAAK;AAGZ,MAAA,MAAM,CAAA,GAAI,GAAA;AACV,MAAA,IAAI,CAAA,CAAE,IAAA,KAAS,CAAA,IAAK,CAAC,EAAE,MAAA,EAAQ;AAC7B,QAAA,OAAO,mBAAA;AAAA,MACT;AAAA,IACF;AAGA,IAAA,IAAI;AACF,MAAA,MAAM,IAAA,GAAO;AAAA,QACX,KAAA;AAAA,QACA,eAAA;AAAA,QACA,GAAI,KAAA,CAAM,UAAA,GAAa,CAAC,IAAI,IAAI,EAAC;AAAA,QACjC,GAAI,MAAM,IAAA,GAAO,CAAC,aAAa,KAAA,CAAM,IAAI,CAAA,CAAE,CAAA,GAAI,EAAC;AAAA,QAChD,IAAA;AAAA,QACA,IAAA;AAAA,QACA,KAAA,CAAM,OAAA;AAAA,QACN;AAAA,OACF;AACA,MAAA,MAAM,EAAE,MAAA,EAAO,GAAI,MAAMA,UAAAA,CAAU,CAAA,KAAA,EAAQ,IAAA,CAAK,GAAA,CAAI,UAAU,CAAA,CAAE,IAAA,CAAK,GAAG,CAAC,CAAA,CAAA,EAAI;AAAA,QAC3E,SAAA,EAAW,KAAK,IAAA,GAAO;AAAA,OACxB,CAAA;AACD,MAAA,OAAO,cAAA,CAAe,QAAQ,KAAK,CAAA;AAAA,IACrC,SAAS,GAAA,EAAK;AACZ,MAAA,MAAM,CAAA,GAAI,GAAA;AACV,MAAA,IAAI,CAAA,CAAE,IAAA,KAAS,CAAA,IAAK,CAAC,EAAE,MAAA,EAAQ;AAC7B,QAAA,OAAO,mBAAA;AAAA,MACT;AACA,MAAA,OAAO,CAAA,oBAAA,EAAuB,CAAA,CAAE,OAAA,IAAW,SAAS,CAAA,CAAA;AAAA,IACtD;AAAA,EACF;AACF,CAAC;AAED,SAAS,WAAW,CAAA,EAAmB;AAErC,EAAA,IAAI,yBAAA,CAA0B,IAAA,CAAK,CAAC,CAAA,EAAG,OAAO,CAAA;AAC9C,EAAA,OAAO,CAAA,CAAA,EAAI,CAAA,CAAE,OAAA,CAAQ,IAAA,EAAM,OAAO,CAAC,CAAA,CAAA,CAAA;AACrC;AAEA,SAAS,cAAA,CAAe,QAAgB,KAAA,EAAuB;AAC7D,EAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,KAAA,CAAM,IAAI,CAAA;AAC/B,EAAA,IAAI,KAAA,CAAM,MAAA,IAAU,KAAA,EAAO,OAAO,MAAA,IAAU,mBAAA;AAC5C,EAAA,OAAO,CAAA,EAAG,MAAM,KAAA,CAAM,CAAA,EAAG,KAAK,CAAA,CAAE,IAAA,CAAK,IAAI,CAAC;AAAA,KAAA,EAAU,KAAA,CAAM,SAAS,KAAK,CAAA,wBAAA,CAAA;AAC1E;;;ACjGO,IAAM,OAAA,GAAU","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 — 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 — 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';\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"]}
|
package/package.json
CHANGED