reasonix 0.0.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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/harvest.ts","../src/memory.ts","../src/repair/scavenge.ts","../src/repair/storm.ts","../src/repair/truncation.ts","../src/repair/flatten.ts","../src/repair/index.ts","../src/telemetry.ts","../src/tools.ts","../src/loop.ts","../src/env.ts","../src/index.ts"],"sourcesContent":["/**\n * Pillar 2 — R1 Thought Harvesting.\n *\n * v0.0.1 stub. Real implementation lands in v0.2 as a constrained V3 call\n * against a strict JSON schema. The shape below is the public contract that\n * downstream code may already depend on.\n */\n\nexport interface TypedPlanState {\n subgoals: string[];\n hypotheses: string[];\n uncertainties: string[];\n rejectedPaths: string[];\n}\n\nexport function emptyPlanState(): TypedPlanState {\n return { subgoals: [], hypotheses: [], uncertainties: [], rejectedPaths: [] };\n}\n\nexport function isPlanStateEmpty(s: TypedPlanState): boolean {\n return (\n s.subgoals.length === 0 &&\n s.hypotheses.length === 0 &&\n s.uncertainties.length === 0 &&\n s.rejectedPaths.length === 0\n );\n}\n\n/** v0.0.1 stub — returns empty state. */\nexport async function harvest(_reasoningContent: string | null): Promise<TypedPlanState> {\n return emptyPlanState();\n}\n","import { createHash } from \"node:crypto\";\nimport type { ChatMessage, ToolSpec } from \"./types.js\";\n\nexport interface ImmutablePrefixOptions {\n system: string;\n toolSpecs?: readonly ToolSpec[];\n fewShots?: readonly ChatMessage[];\n}\n\nexport class ImmutablePrefix {\n readonly system: string;\n readonly toolSpecs: readonly ToolSpec[];\n readonly fewShots: readonly ChatMessage[];\n\n constructor(opts: ImmutablePrefixOptions) {\n this.system = opts.system;\n this.toolSpecs = Object.freeze([...(opts.toolSpecs ?? [])]);\n this.fewShots = Object.freeze([...(opts.fewShots ?? [])]);\n }\n\n toMessages(): ChatMessage[] {\n return [{ role: \"system\", content: this.system }, ...this.fewShots.map((m) => ({ ...m }))];\n }\n\n tools(): ToolSpec[] {\n return this.toolSpecs.map((t) => structuredClone(t) as ToolSpec);\n }\n\n get fingerprint(): string {\n const blob = JSON.stringify({\n system: this.system,\n tools: this.toolSpecs,\n shots: this.fewShots,\n });\n return createHash(\"sha256\").update(blob).digest(\"hex\").slice(0, 16);\n }\n}\n\nexport class AppendOnlyLog {\n private _entries: ChatMessage[] = [];\n\n append(message: ChatMessage): void {\n if (!message || typeof message !== \"object\" || !(\"role\" in message)) {\n throw new Error(`invalid log entry: ${JSON.stringify(message)}`);\n }\n this._entries.push(message);\n }\n\n extend(messages: ChatMessage[]): void {\n for (const m of messages) this.append(m);\n }\n\n get entries(): readonly ChatMessage[] {\n return this._entries;\n }\n\n toMessages(): ChatMessage[] {\n return this._entries.map((e) => ({ ...e }));\n }\n\n get length(): number {\n return this._entries.length;\n }\n}\n\nexport class VolatileScratch {\n reasoning: string | null = null;\n planState: Record<string, unknown> | null = null;\n notes: string[] = [];\n\n reset(): void {\n this.reasoning = null;\n this.planState = null;\n this.notes = [];\n }\n}\n","/**\n * Scavenge tool calls leaked into reasoning_content.\n *\n * R1 sometimes emits tool-call JSON inside <think>…</think> and then forgets\n * to surface it in `tool_calls`. This pass extracts plausible calls and\n * proposes them to the loop, which decides whether to merge them with the\n * declared calls.\n */\n\nimport type { ToolCall } from \"../types.js\";\n\nexport interface ScavengeOptions {\n /** Names of tools the model may legitimately call. Other names are ignored. */\n allowedNames: ReadonlySet<string>;\n /** Maximum number of calls to scavenge per pass (defence against runaway). */\n maxCalls?: number;\n}\n\nexport interface ScavengeResult {\n calls: ToolCall[];\n notes: string[];\n}\n\nexport function scavengeToolCalls(\n reasoningContent: string | null | undefined,\n opts: ScavengeOptions,\n): ScavengeResult {\n if (!reasoningContent) return { calls: [], notes: [] };\n const max = opts.maxCalls ?? 4;\n const notes: string[] = [];\n const out: ToolCall[] = [];\n\n for (const candidate of iterateJsonObjects(reasoningContent)) {\n if (out.length >= max) break;\n const call = coerceToToolCall(candidate, opts.allowedNames);\n if (call) {\n out.push(call);\n notes.push(`scavenged call: ${call.function.name}`);\n }\n }\n return { calls: out, notes };\n}\n\n/** Yield every top-level JSON object substring in `text`. */\nfunction* iterateJsonObjects(text: string): Generator<string> {\n for (let i = 0; i < text.length; i++) {\n if (text[i] !== \"{\") continue;\n let depth = 0;\n let inString = false;\n let escaped = false;\n for (let j = i; j < text.length; j++) {\n const c = text[j]!;\n if (escaped) {\n escaped = false;\n continue;\n }\n if (inString) {\n if (c === \"\\\\\") {\n escaped = true;\n continue;\n }\n if (c === '\"') inString = false;\n continue;\n }\n if (c === '\"') inString = true;\n else if (c === \"{\") depth++;\n else if (c === \"}\") {\n depth--;\n if (depth === 0) {\n yield text.slice(i, j + 1);\n i = j;\n break;\n }\n }\n }\n }\n}\n\nfunction coerceToToolCall(\n candidateJson: string,\n allowedNames: ReadonlySet<string>,\n): ToolCall | null {\n let parsed: any;\n try {\n parsed = JSON.parse(candidateJson);\n } catch {\n return null;\n }\n if (!parsed || typeof parsed !== \"object\") return null;\n\n // Pattern 1: { name, arguments }\n if (typeof parsed.name === \"string\" && allowedNames.has(parsed.name)) {\n const args = parsed.arguments;\n return {\n function: {\n name: parsed.name,\n arguments: typeof args === \"string\" ? args : JSON.stringify(args ?? {}),\n },\n };\n }\n\n // Pattern 2: OpenAI-style { type: \"function\", function: { name, arguments } }\n if (\n parsed.type === \"function\" &&\n parsed.function &&\n typeof parsed.function.name === \"string\" &&\n allowedNames.has(parsed.function.name)\n ) {\n const args = parsed.function.arguments;\n return {\n type: \"function\",\n function: {\n name: parsed.function.name,\n arguments: typeof args === \"string\" ? args : JSON.stringify(args ?? {}),\n },\n };\n }\n\n // Pattern 3: { tool_name, tool_args } (R1 free-form variant)\n if (typeof parsed.tool_name === \"string\" && allowedNames.has(parsed.tool_name)) {\n return {\n function: {\n name: parsed.tool_name,\n arguments: JSON.stringify(parsed.tool_args ?? {}),\n },\n };\n }\n\n return null;\n}\n","import type { ToolCall } from \"../types.js\";\n\n/**\n * Call-storm breaker.\n *\n * Detects (tool, args) tuples repeating within a sliding window and suppresses\n * the offending call. Surfaces a synthetic tool_result advising the model to\n * change strategy on its next turn.\n */\nexport class StormBreaker {\n private readonly windowSize: number;\n private readonly threshold: number;\n private readonly recent: Array<readonly [string, string]> = [];\n\n constructor(windowSize = 6, threshold = 3) {\n this.windowSize = windowSize;\n this.threshold = threshold;\n }\n\n inspect(call: ToolCall): { suppress: boolean; reason?: string } {\n const sig = signature(call);\n if (!sig) return { suppress: false };\n const count = this.recent.reduce(\n (n, [name, args]) => (name === sig[0] && args === sig[1] ? n + 1 : n),\n 0,\n );\n if (count >= this.threshold - 1) {\n return {\n suppress: true,\n reason: `call-storm suppressed: ${sig[0]} called with identical args ${count + 1} times within window=${this.windowSize}`,\n };\n }\n this.recent.push(sig);\n while (this.recent.length > this.windowSize) this.recent.shift();\n return { suppress: false };\n }\n\n reset(): void {\n this.recent.length = 0;\n }\n}\n\nfunction signature(call: ToolCall): readonly [string, string] | null {\n const name = call.function?.name;\n if (!name) return null;\n return [name, call.function?.arguments ?? \"\"] as const;\n}\n","/**\n * Truncation recovery for tool-call argument JSON cut off mid-structure\n * (typically when the model hits max_tokens before finishing the JSON object).\n *\n * Strategy is purely local: balance braces, close strings, fill missing values\n * with `null`. We deliberately do NOT make a continuation API call here — that\n * decision belongs to the loop, which knows about budgets.\n */\n\nexport interface TruncationRepairResult {\n repaired: string;\n changed: boolean;\n notes: string[];\n}\n\nexport function repairTruncatedJson(input: string): TruncationRepairResult {\n const notes: string[] = [];\n if (!input || !input.trim()) {\n return { repaired: \"{}\", changed: input !== \"{}\", notes: [\"empty input → {}\"] };\n }\n // Fast path: already parseable.\n try {\n JSON.parse(input);\n return { repaired: input, changed: false, notes: [] };\n } catch {\n /* fall through */\n }\n\n const stack: (\"{\" | \"[\" | '\"')[] = [];\n let escaped = false;\n let inString = false;\n let lastSignificant = -1;\n\n for (let i = 0; i < input.length; i++) {\n const c = input[i]!;\n if (!/\\s/.test(c)) lastSignificant = i;\n if (escaped) {\n escaped = false;\n continue;\n }\n if (inString) {\n if (c === \"\\\\\") {\n escaped = true;\n continue;\n }\n if (c === '\"') {\n inString = false;\n stack.pop();\n }\n continue;\n }\n if (c === '\"') {\n inString = true;\n stack.push('\"');\n continue;\n }\n if (c === \"{\" || c === \"[\") stack.push(c);\n else if (c === \"}\" || c === \"]\") stack.pop();\n }\n\n let s = input.slice(0, lastSignificant + 1);\n\n // Trim a trailing comma which would block re-parse.\n if (/,$/.test(s)) {\n s = s.replace(/,$/, \"\");\n notes.push(\"trimmed trailing comma\");\n }\n\n // If we ended on a key without a value: \"foo\": → \"foo\": null\n if (/\"\\s*:\\s*$/.test(s)) {\n s += \" null\";\n notes.push(\"filled dangling key with null\");\n }\n\n // If we ended inside a string, close it.\n if (inString) {\n s += '\"';\n stack.pop();\n notes.push(\"closed unterminated string\");\n }\n\n // Pop remaining open structures in reverse order.\n while (stack.length > 0) {\n const top = stack.pop();\n if (top === \"{\") s += \"}\";\n else if (top === \"[\") s += \"]\";\n else if (top === '\"') s += '\"';\n }\n\n try {\n JSON.parse(s);\n return { repaired: s, changed: true, notes };\n } catch (err) {\n notes.push(`fallback to {}: ${(err as Error).message}`);\n return { repaired: \"{}\", changed: true, notes };\n }\n}\n","/**\n * Schema flattening for DeepSeek tool calls.\n *\n * DeepSeek loses arguments on schemas that are deep (>2 levels of nesting) or\n * wide (>10 leaf parameters). This module transforms such schemas into a\n * dot-notation flat schema and re-nests the model's arguments before dispatch.\n *\n * Example:\n * { user: { profile: { name, age } } } ⇄ \"user.profile.name\", \"user.profile.age\"\n */\n\nimport type { JSONSchema } from \"../types.js\";\n\nexport interface FlattenDecision {\n shouldFlatten: boolean;\n leafCount: number;\n maxDepth: number;\n}\n\nexport function analyzeSchema(schema: JSONSchema | undefined): FlattenDecision {\n if (!schema) return { shouldFlatten: false, leafCount: 0, maxDepth: 0 };\n let leafCount = 0;\n let maxDepth = 0;\n walk(schema, 0, (depth, isLeaf) => {\n if (isLeaf) leafCount++;\n if (depth > maxDepth) maxDepth = depth;\n });\n return {\n shouldFlatten: leafCount > 10 || maxDepth > 2,\n leafCount,\n maxDepth,\n };\n}\n\nexport function flattenSchema(schema: JSONSchema): JSONSchema {\n const flatProps: Record<string, JSONSchema> = {};\n const required: string[] = [];\n collect(\"\", schema, flatProps, required, true);\n return {\n type: \"object\",\n properties: flatProps,\n required,\n };\n}\n\nexport function nestArguments(flatArgs: Record<string, unknown>): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(flatArgs)) {\n setByPath(out, key.split(\".\"), value);\n }\n return out;\n}\n\nfunction walk(\n schema: JSONSchema,\n depth: number,\n visit: (depth: number, isLeaf: boolean) => void,\n): void {\n if (schema.type === \"object\" && schema.properties) {\n for (const child of Object.values(schema.properties)) {\n walk(child, depth + 1, visit);\n }\n return;\n }\n if (schema.type === \"array\" && schema.items) {\n walk(schema.items, depth + 1, visit);\n return;\n }\n visit(depth, true);\n}\n\nfunction collect(\n prefix: string,\n schema: JSONSchema,\n out: Record<string, JSONSchema>,\n required: string[],\n isRootRequired: boolean,\n): void {\n if (schema.type === \"object\" && schema.properties) {\n const requiredSet = new Set(schema.required ?? []);\n for (const [key, child] of Object.entries(schema.properties)) {\n const nextPrefix = prefix ? `${prefix}.${key}` : key;\n const childRequired = isRootRequired && requiredSet.has(key);\n collect(nextPrefix, child, out, required, childRequired);\n }\n return;\n }\n // Treat anything non-object (including arrays) as a leaf for flattening purposes.\n out[prefix] = schema;\n if (isRootRequired) required.push(prefix);\n}\n\nfunction setByPath(target: Record<string, unknown>, path: string[], value: unknown): void {\n let cur: any = target;\n for (let i = 0; i < path.length - 1; i++) {\n const key = path[i]!;\n if (typeof cur[key] !== \"object\" || cur[key] === null) cur[key] = {};\n cur = cur[key];\n }\n cur[path[path.length - 1]!] = value;\n}\n","/**\n * Pillar 3 — Tool-Call Repair pipeline.\n *\n * Order of passes per turn:\n * 1. scavenge — recover tool calls leaked into <think>\n * 2. truncation — close any half-emitted argument JSON\n * 3. storm breaker — drop call-storm repeats\n *\n * Schema flattening is applied during loop construction (it changes what we\n * advertise to the model), not per-turn.\n */\n\nimport type { ToolCall } from \"../types.js\";\nimport { scavengeToolCalls } from \"./scavenge.js\";\nimport { StormBreaker } from \"./storm.js\";\nimport { repairTruncatedJson } from \"./truncation.js\";\n\nexport { analyzeSchema, flattenSchema, nestArguments } from \"./flatten.js\";\nexport type { FlattenDecision } from \"./flatten.js\";\nexport { repairTruncatedJson } from \"./truncation.js\";\nexport type { TruncationRepairResult } from \"./truncation.js\";\nexport { scavengeToolCalls } from \"./scavenge.js\";\nexport type { ScavengeOptions, ScavengeResult } from \"./scavenge.js\";\nexport { StormBreaker } from \"./storm.js\";\n\nexport interface RepairReport {\n scavenged: number;\n truncationsFixed: number;\n stormsBroken: number;\n notes: string[];\n}\n\nexport interface ToolCallRepairOptions {\n allowedToolNames: ReadonlySet<string>;\n stormWindow?: number;\n stormThreshold?: number;\n maxScavenge?: number;\n}\n\nexport class ToolCallRepair {\n private readonly storm: StormBreaker;\n private readonly opts: ToolCallRepairOptions;\n\n constructor(opts: ToolCallRepairOptions) {\n this.opts = opts;\n this.storm = new StormBreaker(opts.stormWindow ?? 6, opts.stormThreshold ?? 3);\n }\n\n process(\n declaredCalls: ToolCall[],\n reasoningContent: string | null,\n ): { calls: ToolCall[]; report: RepairReport } {\n const report: RepairReport = {\n scavenged: 0,\n truncationsFixed: 0,\n stormsBroken: 0,\n notes: [],\n };\n\n // 1. Scavenge — only add calls whose (name,args) signature is novel.\n const scavenged = scavengeToolCalls(reasoningContent, {\n allowedNames: this.opts.allowedToolNames,\n maxCalls: this.opts.maxScavenge ?? 4,\n });\n const seenSignatures = new Set(declaredCalls.map(signature));\n const merged = [...declaredCalls];\n for (const sc of scavenged.calls) {\n if (!seenSignatures.has(signature(sc))) {\n merged.push(sc);\n report.scavenged++;\n seenSignatures.add(signature(sc));\n }\n }\n report.notes.push(...scavenged.notes);\n\n // 2. Truncation repair on argument JSON.\n for (const call of merged) {\n const args = call.function?.arguments ?? \"\";\n const r = repairTruncatedJson(args);\n if (r.changed) {\n call.function.arguments = r.repaired;\n report.truncationsFixed++;\n report.notes.push(...r.notes.map((n) => `[${call.function.name}] ${n}`));\n }\n }\n\n // 3. Storm breaker.\n const filtered: ToolCall[] = [];\n for (const call of merged) {\n const verdict = this.storm.inspect(call);\n if (verdict.suppress) {\n report.stormsBroken++;\n if (verdict.reason) report.notes.push(verdict.reason);\n continue;\n }\n filtered.push(call);\n }\n\n return { calls: filtered, report };\n }\n}\n\nfunction signature(call: ToolCall): string {\n return `${call.function?.name ?? \"\"}::${call.function?.arguments ?? \"\"}`;\n}\n","import type { Usage } from \"./client.js\";\n\n/** USD per 1M tokens. Update as DeepSeek pricing changes. */\nexport const DEEPSEEK_PRICING: Record<\n string,\n { inputCacheHit: number; inputCacheMiss: number; output: number }\n> = {\n \"deepseek-chat\": { inputCacheHit: 0.07, inputCacheMiss: 0.27, output: 1.1 },\n \"deepseek-reasoner\": { inputCacheHit: 0.14, inputCacheMiss: 0.55, output: 2.19 },\n};\n\n/** Reference Claude Sonnet 4.6 pricing (USD per 1M tokens). */\nexport const CLAUDE_SONNET_PRICING = { input: 3.0, output: 15.0 };\n\nexport function costUsd(model: string, usage: Usage): number {\n const p = DEEPSEEK_PRICING[model];\n if (!p) return 0;\n return (\n (usage.promptCacheHitTokens * p.inputCacheHit +\n usage.promptCacheMissTokens * p.inputCacheMiss +\n usage.completionTokens * p.output) /\n 1_000_000\n );\n}\n\nexport function claudeEquivalentCost(usage: Usage): number {\n return (\n (usage.promptTokens * CLAUDE_SONNET_PRICING.input +\n usage.completionTokens * CLAUDE_SONNET_PRICING.output) /\n 1_000_000\n );\n}\n\nexport interface TurnStats {\n turn: number;\n model: string;\n usage: Usage;\n cost: number;\n cacheHitRatio: number;\n}\n\nexport interface SessionSummary {\n turns: number;\n totalCostUsd: number;\n claudeEquivalentUsd: number;\n savingsVsClaudePct: number;\n cacheHitRatio: number;\n}\n\nexport class SessionStats {\n readonly turns: TurnStats[] = [];\n\n record(turn: number, model: string, usage: Usage): TurnStats {\n const cost = costUsd(model, usage);\n const stats: TurnStats = {\n turn,\n model,\n usage,\n cost,\n cacheHitRatio: usage.cacheHitRatio,\n };\n this.turns.push(stats);\n return stats;\n }\n\n get totalCost(): number {\n return this.turns.reduce((sum, t) => sum + t.cost, 0);\n }\n\n get totalClaudeEquivalent(): number {\n return this.turns.reduce((sum, t) => sum + claudeEquivalentCost(t.usage), 0);\n }\n\n get savingsVsClaude(): number {\n const c = this.totalClaudeEquivalent;\n return c > 0 ? 1 - this.totalCost / c : 0;\n }\n\n get aggregateCacheHitRatio(): number {\n let hit = 0;\n let miss = 0;\n for (const t of this.turns) {\n hit += t.usage.promptCacheHitTokens;\n miss += t.usage.promptCacheMissTokens;\n }\n const denom = hit + miss;\n return denom > 0 ? hit / denom : 0;\n }\n\n summary(): SessionSummary {\n return {\n turns: this.turns.length,\n totalCostUsd: round(this.totalCost, 6),\n claudeEquivalentUsd: round(this.totalClaudeEquivalent, 6),\n savingsVsClaudePct: round(this.savingsVsClaude * 100, 2),\n cacheHitRatio: round(this.aggregateCacheHitRatio, 4),\n };\n }\n}\n\nfunction round(n: number, digits: number): number {\n const f = 10 ** digits;\n return Math.round(n * f) / f;\n}\n","import type { JSONSchema, ToolSpec } from \"./types.js\";\n\nexport interface ToolDefinition<A = any, R = any> {\n name: string;\n description?: string;\n parameters?: JSONSchema;\n fn: (args: A) => R | Promise<R>;\n}\n\nexport class ToolRegistry {\n private readonly _tools = new Map<string, ToolDefinition>();\n\n register<A, R>(def: ToolDefinition<A, R>): this {\n if (!def.name) throw new Error(\"tool requires a name\");\n this._tools.set(def.name, def as ToolDefinition);\n return this;\n }\n\n has(name: string): boolean {\n return this._tools.has(name);\n }\n\n get(name: string): ToolDefinition | undefined {\n return this._tools.get(name);\n }\n\n get size(): number {\n return this._tools.size;\n }\n\n specs(): ToolSpec[] {\n return [...this._tools.values()].map((t) => ({\n type: \"function\",\n function: {\n name: t.name,\n description: t.description ?? \"\",\n parameters: t.parameters ?? { type: \"object\", properties: {} },\n },\n }));\n }\n\n async dispatch(name: string, argumentsRaw: string | Record<string, unknown>): Promise<string> {\n const tool = this._tools.get(name);\n if (!tool) {\n return JSON.stringify({ error: `unknown tool: ${name}` });\n }\n let args: any;\n try {\n args =\n typeof argumentsRaw === \"string\"\n ? argumentsRaw.trim()\n ? JSON.parse(argumentsRaw)\n : {}\n : (argumentsRaw ?? {});\n } catch (err) {\n return JSON.stringify({\n error: `invalid tool arguments JSON: ${(err as Error).message}`,\n });\n }\n try {\n const result = await tool.fn(args);\n return typeof result === \"string\" ? result : JSON.stringify(result);\n } catch (err) {\n return JSON.stringify({\n error: `${(err as Error).name}: ${(err as Error).message}`,\n });\n }\n }\n}\n","import type { DeepSeekClient } from \"./client.js\";\nimport { type TypedPlanState, harvest } from \"./harvest.js\";\nimport { AppendOnlyLog, type ImmutablePrefix, VolatileScratch } from \"./memory.js\";\nimport { type RepairReport, ToolCallRepair } from \"./repair/index.js\";\nimport { SessionStats, type TurnStats } from \"./telemetry.js\";\nimport { ToolRegistry } from \"./tools.js\";\nimport type { ChatMessage, ToolCall } from \"./types.js\";\n\nexport type EventRole = \"assistant_delta\" | \"assistant_final\" | \"tool\" | \"done\" | \"error\";\n\nexport interface LoopEvent {\n turn: number;\n role: EventRole;\n content: string;\n reasoningDelta?: string;\n toolName?: string;\n stats?: TurnStats;\n planState?: TypedPlanState;\n repair?: RepairReport;\n error?: string;\n}\n\nexport interface CacheFirstLoopOptions {\n client: DeepSeekClient;\n prefix: ImmutablePrefix;\n tools?: ToolRegistry;\n model?: string;\n maxToolIters?: number;\n stream?: boolean;\n}\n\n/**\n * Pillar 1 — Cache-First Loop.\n *\n * - prefix is immutable (cache target)\n * - log is append-only (preserves prior-turn prefix)\n * - scratch is per-turn volatile (never sent upstream)\n *\n * Yields a stream of events so a TUI can render progressively.\n */\nexport class CacheFirstLoop {\n readonly client: DeepSeekClient;\n readonly prefix: ImmutablePrefix;\n readonly tools: ToolRegistry;\n readonly model: string;\n readonly maxToolIters: number;\n readonly stream: boolean;\n readonly log = new AppendOnlyLog();\n readonly scratch = new VolatileScratch();\n readonly stats = new SessionStats();\n readonly repair: ToolCallRepair;\n private _turn = 0;\n\n constructor(opts: CacheFirstLoopOptions) {\n this.client = opts.client;\n this.prefix = opts.prefix;\n this.tools = opts.tools ?? new ToolRegistry();\n this.model = opts.model ?? \"deepseek-chat\";\n this.maxToolIters = opts.maxToolIters ?? 8;\n this.stream = opts.stream ?? true;\n const allowedNames = new Set([...this.prefix.toolSpecs.map((s) => s.function.name)]);\n this.repair = new ToolCallRepair({ allowedToolNames: allowedNames });\n }\n\n private buildMessages(pendingUser: string | null): ChatMessage[] {\n const msgs: ChatMessage[] = [...this.prefix.toMessages(), ...this.log.toMessages()];\n if (pendingUser !== null) msgs.push({ role: \"user\", content: pendingUser });\n return msgs;\n }\n\n async *step(userInput: string): AsyncGenerator<LoopEvent> {\n this._turn++;\n this.scratch.reset();\n let pendingUser: string | null = userInput;\n const toolSpecs = this.prefix.tools();\n\n for (let iter = 0; iter < this.maxToolIters; iter++) {\n const messages = this.buildMessages(pendingUser);\n\n let assistantContent = \"\";\n let reasoningContent = \"\";\n let toolCalls: ToolCall[] = [];\n let usage: TurnStats[\"usage\"] | null = null;\n\n try {\n if (this.stream) {\n const callBuf: Map<number, ToolCall> = new Map();\n for await (const chunk of this.client.stream({\n model: this.model,\n messages,\n tools: toolSpecs.length ? toolSpecs : undefined,\n })) {\n if (chunk.contentDelta) {\n assistantContent += chunk.contentDelta;\n yield {\n turn: this._turn,\n role: \"assistant_delta\",\n content: chunk.contentDelta,\n };\n }\n if (chunk.reasoningDelta) {\n reasoningContent += chunk.reasoningDelta;\n yield {\n turn: this._turn,\n role: \"assistant_delta\",\n content: \"\",\n reasoningDelta: chunk.reasoningDelta,\n };\n }\n if (chunk.toolCallDelta) {\n const d = chunk.toolCallDelta;\n const cur = callBuf.get(d.index) ?? {\n id: d.id,\n type: \"function\" as const,\n function: { name: \"\", arguments: \"\" },\n };\n if (d.id) cur.id = d.id;\n if (d.name) cur.function.name = (cur.function.name ?? \"\") + d.name;\n if (d.argumentsDelta)\n cur.function.arguments = (cur.function.arguments ?? \"\") + d.argumentsDelta;\n callBuf.set(d.index, cur);\n }\n if (chunk.usage) usage = chunk.usage;\n }\n toolCalls = [...callBuf.values()];\n } else {\n const resp = await this.client.chat({\n model: this.model,\n messages,\n tools: toolSpecs.length ? toolSpecs : undefined,\n });\n assistantContent = resp.content;\n reasoningContent = resp.reasoningContent ?? \"\";\n toolCalls = resp.toolCalls;\n usage = resp.usage;\n }\n } catch (err) {\n yield {\n turn: this._turn,\n role: \"error\",\n content: \"\",\n error: (err as Error).message,\n };\n return;\n }\n\n const turnStats = this.stats.record(\n this._turn,\n this.model,\n usage ?? new (await import(\"./client.js\")).Usage(),\n );\n\n // Commit the user turn to the log only on success of the first round-trip.\n if (pendingUser !== null) {\n this.log.append({ role: \"user\", content: pendingUser });\n pendingUser = null;\n }\n\n this.scratch.reasoning = reasoningContent || null;\n const planState = await harvest(reasoningContent || null);\n\n const { calls: repairedCalls, report } = this.repair.process(\n toolCalls,\n reasoningContent || null,\n );\n\n this.log.append(this.assistantMessage(assistantContent, repairedCalls));\n\n yield {\n turn: this._turn,\n role: \"assistant_final\",\n content: assistantContent,\n stats: turnStats,\n planState,\n repair: report,\n };\n\n if (repairedCalls.length === 0) {\n yield { turn: this._turn, role: \"done\", content: assistantContent };\n return;\n }\n\n for (const call of repairedCalls) {\n const name = call.function?.name ?? \"\";\n const args = call.function?.arguments ?? \"{}\";\n const result = await this.tools.dispatch(name, args);\n this.log.append({\n role: \"tool\",\n tool_call_id: call.id ?? \"\",\n name,\n content: result,\n });\n yield { turn: this._turn, role: \"tool\", content: result, toolName: name };\n }\n }\n\n yield { turn: this._turn, role: \"done\", content: \"[max_tool_iters reached]\" };\n }\n\n async run(userInput: string, onEvent?: (ev: LoopEvent) => void): Promise<string> {\n let final = \"\";\n for await (const ev of this.step(userInput)) {\n onEvent?.(ev);\n if (ev.role === \"assistant_final\") final = ev.content;\n if (ev.role === \"done\") break;\n }\n return final;\n }\n\n private assistantMessage(content: string, toolCalls: ToolCall[]): ChatMessage {\n const msg: ChatMessage = { role: \"assistant\", content };\n if (toolCalls.length > 0) msg.tool_calls = toolCalls;\n return msg;\n }\n}\n","import { readFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\n\n/**\n * Minimal `.env` loader; no dependency on dotenv.\n *\n * Reads KEY=VALUE lines and populates `process.env` for keys not already set.\n * Silently no-ops if the file is missing. Safe to call from library entry\n * points, CLI commands, examples, and benchmark runners.\n */\nexport function loadDotenv(path = \".env\"): void {\n let raw: string;\n try {\n raw = readFileSync(resolve(process.cwd(), path), \"utf8\");\n } catch {\n return;\n }\n for (const line of raw.split(/\\r?\\n/)) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith(\"#\")) continue;\n const eq = trimmed.indexOf(\"=\");\n if (eq === -1) continue;\n const key = trimmed.slice(0, eq).trim();\n let value = trimmed.slice(eq + 1).trim();\n if (\n (value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\"))\n ) {\n value = value.slice(1, -1);\n }\n if (process.env[key] === undefined) process.env[key] = value;\n }\n}\n","/** Reasonix — DeepSeek-native agent framework. Library entry point. */\n\nexport { DeepSeekClient, Usage } from \"./client.js\";\nexport type { ChatResponse, StreamChunk, DeepSeekClientOptions } from \"./client.js\";\n\nexport { CacheFirstLoop } from \"./loop.js\";\nexport type { CacheFirstLoopOptions, LoopEvent, EventRole } from \"./loop.js\";\n\nexport { ImmutablePrefix, AppendOnlyLog, VolatileScratch } from \"./memory.js\";\nexport type { ImmutablePrefixOptions } from \"./memory.js\";\n\nexport { ToolRegistry } from \"./tools.js\";\nexport type { ToolDefinition } from \"./tools.js\";\n\nexport { SessionStats, costUsd, claudeEquivalentCost } from \"./telemetry.js\";\nexport type { TurnStats, SessionSummary } from \"./telemetry.js\";\n\nexport {\n ToolCallRepair,\n scavengeToolCalls,\n repairTruncatedJson,\n StormBreaker,\n analyzeSchema,\n flattenSchema,\n nestArguments,\n} from \"./repair/index.js\";\nexport type {\n RepairReport,\n ToolCallRepairOptions,\n ScavengeOptions,\n ScavengeResult,\n TruncationRepairResult,\n FlattenDecision,\n} from \"./repair/index.js\";\n\nexport { harvest, emptyPlanState, isPlanStateEmpty } from \"./harvest.js\";\nexport type { TypedPlanState } from \"./harvest.js\";\n\nexport { loadDotenv } from \"./env.js\";\n\nexport { fetchWithRetry } from \"./retry.js\";\nexport type { RetryOptions, RetryInfo } from \"./retry.js\";\n\nexport type {\n ChatMessage,\n ToolCall,\n ToolSpec,\n ToolFunctionSpec,\n Role,\n JSONSchema,\n} from \"./types.js\";\n\nexport const VERSION = \"0.0.1\";\n"],"mappings":"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","names":["signature"]}
package/package.json ADDED
@@ -0,0 +1,75 @@
1
+ {
2
+ "name": "reasonix",
3
+ "version": "0.0.1",
4
+ "description": "DeepSeek-native agent framework: cache-first loop, R1 thought harvesting, tool-call repair.",
5
+ "type": "module",
6
+ "bin": {
7
+ "reasonix": "dist/cli/index.js"
8
+ },
9
+ "main": "./dist/index.js",
10
+ "module": "./dist/index.js",
11
+ "types": "./dist/index.d.ts",
12
+ "exports": {
13
+ ".": {
14
+ "types": "./dist/index.d.ts",
15
+ "import": "./dist/index.js"
16
+ }
17
+ },
18
+ "files": [
19
+ "dist",
20
+ "README.md",
21
+ "LICENSE"
22
+ ],
23
+ "scripts": {
24
+ "build": "tsup",
25
+ "dev": "tsx src/cli/index.ts",
26
+ "chat": "tsx src/cli/index.ts chat",
27
+ "test": "vitest run",
28
+ "test:watch": "vitest",
29
+ "lint": "biome check src tests",
30
+ "lint:fix": "biome check --write src tests",
31
+ "format": "biome format --write src tests",
32
+ "typecheck": "tsc --noEmit",
33
+ "prepublishOnly": "npm run lint && npm run typecheck && npm run test && npm run build"
34
+ },
35
+ "keywords": [
36
+ "agent",
37
+ "llm",
38
+ "deepseek",
39
+ "r1",
40
+ "tool-use",
41
+ "prompt-cache",
42
+ "cli",
43
+ "tui"
44
+ ],
45
+ "author": "esengine",
46
+ "license": "MIT",
47
+ "repository": {
48
+ "type": "git",
49
+ "url": "git+https://github.com/esengine/reasonix.git"
50
+ },
51
+ "bugs": {
52
+ "url": "https://github.com/esengine/reasonix/issues"
53
+ },
54
+ "homepage": "https://github.com/esengine/reasonix#readme",
55
+ "engines": {
56
+ "node": ">=20.10"
57
+ },
58
+ "dependencies": {
59
+ "commander": "^12.1.0",
60
+ "eventsource-parser": "^3.0.0",
61
+ "ink": "^5.1.0",
62
+ "ink-spinner": "^5.0.0",
63
+ "ink-text-input": "^6.0.0",
64
+ "react": "^18.3.1"
65
+ },
66
+ "devDependencies": {
67
+ "@biomejs/biome": "^1.9.4",
68
+ "@types/node": "^22.9.0",
69
+ "@types/react": "^18.3.12",
70
+ "tsup": "^8.3.5",
71
+ "tsx": "^4.19.2",
72
+ "typescript": "^5.6.3",
73
+ "vitest": "^2.1.5"
74
+ }
75
+ }