reasonix 0.3.0-alpha.4 → 0.3.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/index.d.ts CHANGED
@@ -244,6 +244,14 @@ declare class AppendOnlyLog {
244
244
  private _entries;
245
245
  append(message: ChatMessage): void;
246
246
  extend(messages: ChatMessage[]): void;
247
+ /**
248
+ * Bulk-replace entries. Intentionally named to be hard to reach for —
249
+ * this is the one mutation path that breaks the log's append-only
250
+ * spirit, reserved for compaction flows (`/compact`) and recovery
251
+ * where the caller has consciously decided to drop old history. Any
252
+ * other use is almost certainly wrong; append() is what you want.
253
+ */
254
+ compactInPlace(replacement: ChatMessage[]): void;
247
255
  get entries(): readonly ChatMessage[];
248
256
  toMessages(): ChatMessage[];
249
257
  get length(): number;
@@ -379,6 +387,13 @@ interface SessionSummary {
379
387
  claudeEquivalentUsd: number;
380
388
  savingsVsClaudePct: number;
381
389
  cacheHitRatio: number;
390
+ /**
391
+ * Most recent turn's prompt-token count. Used by the TUI's context
392
+ * gauge: we can't know the next call's cost without making it, but
393
+ * the last turn's prompt tokens is the floor (next call is last
394
+ * prompt + user delta + any new tool outputs).
395
+ */
396
+ lastPromptTokens: number;
382
397
  }
383
398
  declare class SessionStats {
384
399
  readonly turns: TurnStats[];
@@ -514,6 +529,21 @@ declare class CacheFirstLoop {
514
529
  private _turn;
515
530
  private _streamPreference;
516
531
  constructor(opts: CacheFirstLoopOptions);
532
+ /**
533
+ * Shrink the log by re-truncating oversized tool results to a tighter
534
+ * cap, and persist the result back to disk so the next launch doesn't
535
+ * re-inherit a fat session file. Returns a summary the TUI can
536
+ * display.
537
+ *
538
+ * Only tool-role messages are touched (same rationale as
539
+ * {@link healLoadedMessages}). User and assistant messages carry
540
+ * authored intent we can't mechanically shrink without losing
541
+ * meaning.
542
+ */
543
+ compact(tightCapChars?: number): {
544
+ healedCount: number;
545
+ charsSaved: number;
546
+ };
517
547
  private appendAndPersist;
518
548
  /**
519
549
  * Reconfigure model/harvest/branch/stream mid-session. The loop's log,
@@ -524,9 +554,30 @@ declare class CacheFirstLoop {
524
554
  configure(opts: ReconfigurableOptions): void;
525
555
  private buildMessages;
526
556
  step(userInput: string): AsyncGenerator<LoopEvent>;
557
+ private forceSummaryAfterIterLimit;
527
558
  run(userInput: string, onEvent?: (ev: LoopEvent) => void): Promise<string>;
528
559
  private assistantMessage;
529
560
  }
561
+ /**
562
+ * Truncate any tool-role message whose content exceeds the cap. User
563
+ * and assistant messages are left alone because (a) they're almost
564
+ * always small, (b) truncating user prompts would corrupt conversational
565
+ * intent in a way the user didn't author. Exported for tests.
566
+ */
567
+ declare function healLoadedMessages(messages: ChatMessage[], maxChars: number): {
568
+ messages: ChatMessage[];
569
+ healedCount: number;
570
+ healedFrom: number;
571
+ };
572
+ /**
573
+ * Annotate the `DeepSeek 400: … maximum context length …` error the API
574
+ * returns when a session's history has grown past 131,072 tokens. The
575
+ * raw message is a JSON blob; we surface a short actionable hint on top
576
+ * so the user knows to `/forget` or `/clear` rather than parsing the
577
+ * JSON themselves. Other errors pass through unchanged — the loop's
578
+ * error channel already formats them well enough.
579
+ */
580
+ declare function formatLoopError(err: Error): string;
530
581
 
531
582
  /**
532
583
  * Session persistence.
@@ -1069,7 +1120,26 @@ interface BridgeOptions {
1069
1120
  registry?: ToolRegistry;
1070
1121
  /** Auto-flatten deep schemas (Pillar 3). Defaults to the registry's own default (true). */
1071
1122
  autoFlatten?: boolean;
1123
+ /**
1124
+ * Per-tool-call result cap, in characters. If a tool returns more than
1125
+ * this, the result is truncated and a `[…truncated N chars…]` marker is
1126
+ * appended before the last KB so the model still sees a useful tail.
1127
+ * Defaults to {@link DEFAULT_MAX_RESULT_CHARS}.
1128
+ *
1129
+ * Why this exists: DeepSeek V3's context is 131,072 tokens. A single
1130
+ * `read_file` against a big source file can return >3 MB of text
1131
+ * (~900k tokens) and permanently poison the session — every subsequent
1132
+ * turn rebuilds the history and 400s. This cap is a floor. Users who
1133
+ * legitimately want bigger payloads can raise it explicitly.
1134
+ */
1135
+ maxResultChars?: number;
1072
1136
  }
1137
+ /**
1138
+ * 32,000 chars ≈ 8k English tokens, or ~16k CJK tokens. Small enough to
1139
+ * fit comfortably in history even across 5–10 tool calls, large enough
1140
+ * that most file reads and directory listings fit un-truncated.
1141
+ */
1142
+ declare const DEFAULT_MAX_RESULT_CHARS = 32000;
1073
1143
  interface BridgeResult {
1074
1144
  registry: ToolRegistry;
1075
1145
  /** Names actually registered (may differ from MCP names when a prefix is applied). */
@@ -1088,6 +1158,10 @@ interface BridgeResult {
1088
1158
  * they fit Reasonix's existing tool-dispatch contract.
1089
1159
  */
1090
1160
  declare function bridgeMcpTools(client: McpClient, opts?: BridgeOptions): Promise<BridgeResult>;
1161
+ interface FlattenOptions {
1162
+ /** Cap the flattened string at this many characters. Default: no cap. */
1163
+ maxChars?: number;
1164
+ }
1091
1165
  /**
1092
1166
  * Turn an MCP CallToolResult into a string — the contract Reasonix's
1093
1167
  * ToolRegistry.dispatch returns. We:
@@ -1097,8 +1171,19 @@ declare function bridgeMcpTools(client: McpClient, opts?: BridgeOptions): Promis
1097
1171
  * prompts later)
1098
1172
  * - prefix error results with "ERROR: " so the calling model sees the
1099
1173
  * failure clearly even through JSON mode
1174
+ * - optionally truncate to `maxChars` so a single oversized tool result
1175
+ * (e.g. a big `read_file`) can't poison the session by blowing past
1176
+ * the model's context window
1100
1177
  */
1101
- declare function flattenMcpResult(result: CallToolResult): string;
1178
+ declare function flattenMcpResult(result: CallToolResult, opts?: FlattenOptions): string;
1179
+ /**
1180
+ * Keep the head AND a short tail so the model sees both "what the tool
1181
+ * started returning" and "how it ended". Head-only loses file endings
1182
+ * (e.g. an error message appended at the bottom of a stack trace); the
1183
+ * 1KB tail window covers that while costing almost nothing. Exported for
1184
+ * tests and reuse by non-MCP tool adapters that want the same policy.
1185
+ */
1186
+ declare function truncateForModel(s: string, maxChars: number): string;
1102
1187
 
1103
1188
  /**
1104
1189
  * Parse the `--mcp` CLI argument into a transport-tagged spec.
@@ -1149,10 +1234,36 @@ declare function parseMcpSpec(input: string): McpSpec;
1149
1234
  * The library itself never touches the config file — it only reads
1150
1235
  * `DEEPSEEK_API_KEY` from the environment. The CLI is responsible for
1151
1236
  * pulling from the config file and exposing it via env var to the loop.
1237
+ *
1238
+ * Beyond the API key, the config also remembers the user's *defaults*
1239
+ * from `reasonix setup`: preset, MCP servers, session. This is what
1240
+ * makes `reasonix chat` with no flags "just work" after first-run.
1152
1241
  */
1242
+ /** One of the preset bundles (model + harvest + branch combo). */
1243
+ type PresetName = "fast" | "smart" | "max";
1153
1244
  interface ReasonixConfig {
1154
1245
  apiKey?: string;
1155
1246
  baseUrl?: string;
1247
+ /**
1248
+ * Default preset for `reasonix chat` / `reasonix run` when no flags override.
1249
+ * Maps to model + harvest + branch combos (see presets.ts). Missing → "fast".
1250
+ */
1251
+ preset?: PresetName;
1252
+ /**
1253
+ * Default MCP server specs to bridge on every `reasonix chat`, in the
1254
+ * same `"name=cmd args..."` format that `--mcp` takes. Stored as strings
1255
+ * so `reasonix setup` stays symmetrical with the flag — one parser, one
1256
+ * format in the config file, grep-friendly.
1257
+ */
1258
+ mcp?: string[];
1259
+ /**
1260
+ * Default session name (null/missing → "default", which is what the
1261
+ * CLI has been doing anyway). `reasonix setup` lets users pick a name
1262
+ * or opt into ephemeral.
1263
+ */
1264
+ session?: string | null;
1265
+ /** Marks that `reasonix setup` has completed at least once. */
1266
+ setupCompleted?: boolean;
1156
1267
  }
1157
1268
  declare function defaultConfigPath(): string;
1158
1269
  declare function readConfig(path?: string): ReasonixConfig;
@@ -1166,6 +1277,6 @@ declare function redactKey(key: string): string;
1166
1277
 
1167
1278
  /** Reasonix — DeepSeek-native agent framework. Library entry point. */
1168
1279
 
1169
- declare const VERSION = "0.3.0-alpha.4";
1280
+ declare const VERSION = "0.3.1";
1170
1281
 
1171
- export { AppendOnlyLog, type BranchOptions, type BranchProgress, type BranchResult, type BranchSample, type BranchSelector, type BranchSummary, type BridgeOptions, type BridgeResult, CacheFirstLoop, type CacheFirstLoopOptions, type CallToolResult, type ChatMessage, type ChatResponse, DeepSeekClient, type DeepSeekClientOptions, type RenderOptions as DiffRenderOptions, type DiffReport, type DiffSide, type EventRole, type FlattenDecision, type HarvestOptions, ImmutablePrefix, type ImmutablePrefixOptions, type InitializeResult, type JSONSchema, type JsonRpcMessage, type JsonRpcRequest, type JsonRpcResponse, type ListToolsResult, type LoopEvent, MCP_PROTOCOL_VERSION, McpClient, type McpClientOptions, type McpContentBlock, type McpSpec, type McpTool, type McpToolSchema, type McpTransport, type ReadTranscriptResult, type ReasonixConfig, type ReconfigurableOptions, type RepairReport, type ReplayStats, type RetryInfo, type RetryOptions, type Role, type ScavengeOptions, type ScavengeResult, type SessionInfo, SessionStats, type SessionSummary, type SseMcpSpec, SseTransport, type SseTransportOptions, type StdioMcpSpec, StdioTransport, type StdioTransportOptions, StormBreaker, type StreamChunk, type ToolCall, ToolCallRepair, type ToolCallRepairOptions, type ToolDefinition, type ToolFunctionSpec, ToolRegistry, type ToolSpec, type TranscriptMeta, type TranscriptRecord, type TruncationRepairResult, type TurnPair, type TurnStats, type TypedPlanState, Usage, VERSION, VolatileScratch, aggregateBranchUsage, analyzeSchema, appendSessionMessage, bridgeMcpTools, claudeEquivalentCost, computeReplayStats, costUsd, defaultConfigPath, defaultSelector, deleteSession, diffTranscripts, emptyPlanState, fetchWithRetry, flattenMcpResult, flattenSchema, harvest, isJsonRpcError, isPlanStateEmpty, isPlausibleKey, listSessions, loadApiKey, loadDotenv, loadSessionMessages, nestArguments, openTranscriptFile, parseMcpSpec, parseTranscript, readConfig, readTranscript, recordFromLoopEvent, redactKey, renderMarkdown as renderDiffMarkdown, renderSummaryTable as renderDiffSummary, repairTruncatedJson, replayFromFile, runBranches, sanitizeName as sanitizeSessionName, saveApiKey, scavengeToolCalls, sessionPath, sessionsDir, similarity, writeConfig, writeMeta, writeRecord };
1282
+ export { AppendOnlyLog, type BranchOptions, type BranchProgress, type BranchResult, type BranchSample, type BranchSelector, type BranchSummary, type BridgeOptions, type BridgeResult, CacheFirstLoop, type CacheFirstLoopOptions, type CallToolResult, type ChatMessage, type ChatResponse, DEFAULT_MAX_RESULT_CHARS, DeepSeekClient, type DeepSeekClientOptions, type RenderOptions as DiffRenderOptions, type DiffReport, type DiffSide, type EventRole, type FlattenDecision, type FlattenOptions, type HarvestOptions, ImmutablePrefix, type ImmutablePrefixOptions, type InitializeResult, type JSONSchema, type JsonRpcMessage, type JsonRpcRequest, type JsonRpcResponse, type ListToolsResult, type LoopEvent, MCP_PROTOCOL_VERSION, McpClient, type McpClientOptions, type McpContentBlock, type McpSpec, type McpTool, type McpToolSchema, type McpTransport, type ReadTranscriptResult, type ReasonixConfig, type ReconfigurableOptions, type RepairReport, type ReplayStats, type RetryInfo, type RetryOptions, type Role, type ScavengeOptions, type ScavengeResult, type SessionInfo, SessionStats, type SessionSummary, type SseMcpSpec, SseTransport, type SseTransportOptions, type StdioMcpSpec, StdioTransport, type StdioTransportOptions, StormBreaker, type StreamChunk, type ToolCall, ToolCallRepair, type ToolCallRepairOptions, type ToolDefinition, type ToolFunctionSpec, ToolRegistry, type ToolSpec, type TranscriptMeta, type TranscriptRecord, type TruncationRepairResult, type TurnPair, type TurnStats, type TypedPlanState, Usage, VERSION, VolatileScratch, aggregateBranchUsage, analyzeSchema, appendSessionMessage, bridgeMcpTools, claudeEquivalentCost, computeReplayStats, costUsd, defaultConfigPath, defaultSelector, deleteSession, diffTranscripts, emptyPlanState, fetchWithRetry, flattenMcpResult, flattenSchema, formatLoopError, harvest, healLoadedMessages, isJsonRpcError, isPlanStateEmpty, isPlausibleKey, listSessions, loadApiKey, loadDotenv, loadSessionMessages, nestArguments, openTranscriptFile, parseMcpSpec, parseTranscript, readConfig, readTranscript, recordFromLoopEvent, redactKey, renderMarkdown as renderDiffMarkdown, renderSummaryTable as renderDiffSummary, repairTruncatedJson, replayFromFile, runBranches, sanitizeName as sanitizeSessionName, saveApiKey, scavengeToolCalls, sessionPath, sessionsDir, similarity, truncateForModel, writeConfig, writeMeta, writeRecord };