reasonix 0.4.6 → 0.4.12

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
@@ -120,6 +120,23 @@ interface StreamChunk {
120
120
  finishReason?: string;
121
121
  raw: any;
122
122
  }
123
+ /**
124
+ * Response shape for DeepSeek's `/user/balance` endpoint. One entry
125
+ * per currency the account is funded in (typically CNY, sometimes
126
+ * USD). `total_balance` is the spendable figure; `granted_balance`
127
+ * counts promotional credits that expire, `topped_up_balance` is
128
+ * what the user paid for and keeps.
129
+ */
130
+ interface BalanceInfo {
131
+ currency: string;
132
+ total_balance: string;
133
+ granted_balance?: string;
134
+ topped_up_balance?: string;
135
+ }
136
+ interface UserBalance {
137
+ is_available: boolean;
138
+ balance_infos: BalanceInfo[];
139
+ }
123
140
  interface DeepSeekClientOptions {
124
141
  apiKey?: string;
125
142
  baseUrl?: string;
@@ -136,6 +153,15 @@ declare class DeepSeekClient {
136
153
  private readonly _fetch;
137
154
  constructor(opts?: DeepSeekClientOptions);
138
155
  private buildPayload;
156
+ /**
157
+ * Fetch the current DeepSeek account balance. Separate endpoint
158
+ * from chat completions, no billing impact. Returns null on any
159
+ * network/auth failure so callers can gate the balance display
160
+ * without a hard error — the rest of the session works regardless.
161
+ */
162
+ getBalance(opts?: {
163
+ signal?: AbortSignal;
164
+ }): Promise<UserBalance | null>;
139
165
  chat(opts: ChatRequestOptions): Promise<ChatResponse>;
140
166
  stream(opts: ChatRequestOptions): AsyncGenerator<StreamChunk>;
141
167
  }
@@ -172,7 +198,7 @@ interface HarvestOptions {
172
198
  }
173
199
  declare function emptyPlanState(): TypedPlanState;
174
200
  declare function isPlanStateEmpty(s: TypedPlanState | null | undefined): boolean;
175
- declare function harvest(reasoningContent: string | null | undefined, client?: DeepSeekClient, options?: HarvestOptions): Promise<TypedPlanState>;
201
+ declare function harvest(reasoningContent: string | null | undefined, client?: DeepSeekClient, options?: HarvestOptions, signal?: AbortSignal): Promise<TypedPlanState>;
176
202
 
177
203
  /**
178
204
  * Self-consistency branching.
@@ -373,6 +399,10 @@ declare class ToolCallRepair {
373
399
  }
374
400
 
375
401
  declare function costUsd(model: string, usage: Usage): number;
402
+ /** Input-side cost only (prompt, cache hit + miss). Used for the panel breakdown. */
403
+ declare function inputCostUsd(model: string, usage: Usage): number;
404
+ /** Output-side cost only (completion tokens). Used for the panel breakdown. */
405
+ declare function outputCostUsd(model: string, usage: Usage): number;
376
406
  declare function claudeEquivalentCost(usage: Usage): number;
377
407
  interface TurnStats {
378
408
  turn: number;
@@ -384,7 +414,17 @@ interface TurnStats {
384
414
  interface SessionSummary {
385
415
  turns: number;
386
416
  totalCostUsd: number;
417
+ /**
418
+ * Input-side (prompt) cost aggregated across the session. Split
419
+ * from totalCostUsd so the panel can render "cost $X (in $Y · out
420
+ * $Z)" — users asked for visibility into where the spend lands.
421
+ */
422
+ totalInputCostUsd: number;
423
+ /** Output-side (completion) cost aggregated across the session. */
424
+ totalOutputCostUsd: number;
425
+ /** @deprecated Claude reference; kept for benchmarks + replay compat, no longer surfaced in the TUI. */
387
426
  claudeEquivalentUsd: number;
427
+ /** @deprecated. Same as claudeEquivalentUsd — synthetic ratio, not a real measurement. */
388
428
  savingsVsClaudePct: number;
389
429
  cacheHitRatio: number;
390
430
  /**
@@ -401,15 +441,28 @@ declare class SessionStats {
401
441
  get totalCost(): number;
402
442
  get totalClaudeEquivalent(): number;
403
443
  get savingsVsClaude(): number;
444
+ get totalInputCost(): number;
445
+ get totalOutputCost(): number;
404
446
  get aggregateCacheHitRatio(): number;
405
447
  summary(): SessionSummary;
406
448
  }
407
449
 
450
+ /**
451
+ * Per-call context a tool `fn` can optionally consume. Today the only
452
+ * field is `signal`, plumbed through so long-running tools (MCP calls,
453
+ * HTTP requests) can abort when the user presses Esc. Omitted fields
454
+ * stay optional — tools written against the pre-0.4.9 signature keep
455
+ * working; they just ignore cancellation, which is fine for fast
456
+ * local work where "await finishes" happens before the next tick anyway.
457
+ */
458
+ interface ToolCallContext {
459
+ signal?: AbortSignal;
460
+ }
408
461
  interface ToolDefinition<A = any, R = any> {
409
462
  name: string;
410
463
  description?: string;
411
464
  parameters?: JSONSchema;
412
- fn: (args: A) => R | Promise<R>;
465
+ fn: (args: A, ctx?: ToolCallContext) => R | Promise<R>;
413
466
  }
414
467
  interface ToolRegistryOptions {
415
468
  /**
@@ -430,7 +483,9 @@ declare class ToolRegistry {
430
483
  /** True if a registered tool's schema was flattened for the model. */
431
484
  wasFlattened(name: string): boolean;
432
485
  specs(): ToolSpec[];
433
- dispatch(name: string, argumentsRaw: string | Record<string, unknown>): Promise<string>;
486
+ dispatch(name: string, argumentsRaw: string | Record<string, unknown>, opts?: {
487
+ signal?: AbortSignal;
488
+ }): Promise<string>;
434
489
  }
435
490
 
436
491
  type EventRole = "assistant_delta" | "assistant_final"
@@ -441,7 +496,16 @@ type EventRole = "assistant_delta" | "assistant_final"
441
496
  * takes more than a few hundred ms (a big `filesystem_edit_file`
442
497
  * is a typical trigger).
443
498
  */
444
- | "tool_start" | "tool" | "done" | "error" | "warning" | "branch_start" | "branch_progress" | "branch_done";
499
+ | "tool_start" | "tool" | "done" | "error" | "warning"
500
+ /**
501
+ * Transient "what's happening right now" indicator. Emitted during
502
+ * silent phases — between a tool result and the next iteration's
503
+ * first streaming byte, and right before harvest — so the TUI can
504
+ * show a spinner with explanatory text instead of looking frozen.
505
+ * The UI clears it on the next primary event (assistant_delta,
506
+ * tool_start, tool, assistant_final, error).
507
+ */
508
+ | "status" | "branch_start" | "branch_progress" | "branch_done";
445
509
  interface BranchSummary {
446
510
  budget: number;
447
511
  chosenIndex: number;
@@ -547,11 +611,13 @@ declare class CacheFirstLoop {
547
611
  private _turn;
548
612
  private _streamPreference;
549
613
  /**
550
- * Set by {@link abort} to short-circuit the tool-call loop after the
551
- * current iteration. Reset at the start of each `step()` so an Esc
552
- * during one turn doesn't poison the next.
614
+ * AbortController per active turn. Threaded through the DeepSeek
615
+ * HTTP calls AND every tool dispatch so Esc actually cancels the
616
+ * in-flight network/subprocess work — not "we'll get to it after
617
+ * the current call finishes." Re-created at the start of each
618
+ * `step()` (the prior turn's signal has already fired).
553
619
  */
554
- private _aborted;
620
+ private _turnAbort;
555
621
  constructor(opts: CacheFirstLoopOptions);
556
622
  /**
557
623
  * Shrink the log by re-truncating oversized tool results to a tighter
@@ -569,6 +635,20 @@ declare class CacheFirstLoop {
569
635
  charsSaved: number;
570
636
  };
571
637
  private appendAndPersist;
638
+ /**
639
+ * Start a fresh conversation WITHOUT exiting. Drops every message
640
+ * in the in-memory log AND rewrites the session file to empty so
641
+ * a resume won't re-hydrate the old turns. Unlike `/forget`, which
642
+ * deletes the session entirely, this keeps the session name and
643
+ * config intact — it's the "new chat" button.
644
+ *
645
+ * The immutable prefix (system prompt + tool specs) is preserved
646
+ * — that's the cache-first invariant, not part of the conversation.
647
+ * Returns the number of messages dropped so the UI can show it.
648
+ */
649
+ clearLog(): {
650
+ dropped: number;
651
+ };
572
652
  /**
573
653
  * Reconfigure model/harvest/branch/stream mid-session. The loop's log,
574
654
  * scratch, and stats are preserved — only the per-turn behavior changes.
@@ -578,11 +658,12 @@ declare class CacheFirstLoop {
578
658
  configure(opts: ReconfigurableOptions): void;
579
659
  private buildMessages;
580
660
  /**
581
- * Signal the currently-running {@link step} that the user wants to
582
- * stop exploring. Takes effect at the next iteration boundary — if a
583
- * tool call is mid-flight it will be allowed to finish, then the
584
- * loop diverts to the forced-summary path so the user gets an
585
- * answer instead of a cliff. Called by the TUI on Esc.
661
+ * Signal the currently-running {@link step} to stop **now**. Cancels
662
+ * the in-flight network request (DeepSeek HTTP/SSE) AND any tool call
663
+ * currently dispatching (MCP `notifications/cancelled` + promise
664
+ * reject). The loop itself also sees `signal.aborted` at each
665
+ * iteration boundary and exits quickly instead of looping again.
666
+ * Called by the TUI on Esc.
586
667
  */
587
668
  abort(): void;
588
669
  /**
@@ -613,12 +694,6 @@ declare class CacheFirstLoop {
613
694
  * Exported so tests can exercise it against concrete R1 outputs.
614
695
  */
615
696
  declare function stripHallucinatedToolMarkup(s: string): string;
616
- /**
617
- * Truncate any tool-role message whose content exceeds the cap. User
618
- * and assistant messages are left alone because (a) they're almost
619
- * always small, (b) truncating user prompts would corrupt conversational
620
- * intent in a way the user didn't author. Exported for tests.
621
- */
622
697
  declare function healLoadedMessages(messages: ChatMessage[], maxChars: number): {
623
698
  messages: ChatMessage[];
624
699
  healedCount: number;
@@ -634,6 +709,50 @@ declare function healLoadedMessages(messages: ChatMessage[], maxChars: number):
634
709
  */
635
710
  declare function formatLoopError(err: Error): string;
636
711
 
712
+ /**
713
+ * Built-in filesystem tools for `reasonix code`.
714
+ *
715
+ * Why native instead of the official `@modelcontextprotocol/server-filesystem`:
716
+ * - No subprocess overhead — every call is 50-200 ms cheaper.
717
+ * - Schema shapes tuned for R1: `edit_file` takes a single
718
+ * SEARCH/REPLACE string instead of `string="false"`-encoded
719
+ * JSON arrays, which was the biggest single source of DSML
720
+ * hallucinations in 0.4.x.
721
+ * - Sandbox enforcement lives here so Reasonix can reason about
722
+ * it (tests cover path-traversal, symlink-escape, and the
723
+ * cwd-outside-root case) rather than trusting an external server.
724
+ * - No `npx install` / network dependency in `reasonix code`.
725
+ *
726
+ * Tool names + argument shapes intentionally mirror the official
727
+ * filesystem server so R1's muscle memory carries over. The only
728
+ * intentional divergence is `edit_file`, noted above.
729
+ */
730
+
731
+ interface FilesystemToolsOptions {
732
+ /** Absolute directory the tools may read/write. Paths outside this are refused. */
733
+ rootDir: string;
734
+ /**
735
+ * When `false`, register only read-side tools (read_file, list_directory,
736
+ * search_files, get_file_info, directory_tree). Useful for read-only
737
+ * workflows where the model should never mutate the tree. Default: true.
738
+ */
739
+ allowWriting?: boolean;
740
+ /**
741
+ * Cap for a single file read, in bytes. Prevents a stray `read_file`
742
+ * on a multi-GB blob from OOM'ing Node. 2 MB is enough for any realistic
743
+ * source file (the biggest single-file TypeScript project checked in to
744
+ * GitHub is ~500 KB); pass higher when working with data files.
745
+ */
746
+ maxReadBytes?: number;
747
+ /**
748
+ * Cap for total bytes returned from search_files / directory_tree /
749
+ * grep, so the model can't accidentally pull down the whole tree as
750
+ * one giant string. 256 KB by default.
751
+ */
752
+ maxListBytes?: number;
753
+ }
754
+ declare function registerFilesystemTools(registry: ToolRegistry, opts: FilesystemToolsOptions): ToolRegistry;
755
+
637
756
  /**
638
757
  * Session persistence.
639
758
  *
@@ -974,6 +1093,26 @@ interface ListToolsResult {
974
1093
  tools: McpTool[];
975
1094
  nextCursor?: string;
976
1095
  }
1096
+ /**
1097
+ * Server → client notification emitted during a long-running request
1098
+ * that the client subscribed to via `_meta.progressToken`. `progress`
1099
+ * and `total` are typically matched units (files scanned, bytes
1100
+ * processed, etc.); `total` may be missing when the server can't
1101
+ * estimate the upper bound up front.
1102
+ */
1103
+ interface ProgressNotificationParams {
1104
+ progressToken: string | number;
1105
+ progress: number;
1106
+ total?: number;
1107
+ message?: string;
1108
+ }
1109
+ /** Values a `ProgressHandler` receives — `progressToken` is already matched away. */
1110
+ interface McpProgressInfo {
1111
+ progress: number;
1112
+ total?: number;
1113
+ message?: string;
1114
+ }
1115
+ type McpProgressHandler = (info: McpProgressInfo) => void;
977
1116
  interface McpContentBlockText {
978
1117
  type: "text";
979
1118
  text: string;
@@ -1155,6 +1294,8 @@ declare class McpClient {
1155
1294
  private _serverInfo;
1156
1295
  private _protocolVersion;
1157
1296
  private _instructions;
1297
+ private readonly progressHandlers;
1298
+ private nextProgressToken;
1158
1299
  constructor(opts: McpClientOptions);
1159
1300
  /** Server's advertised capabilities, available after initialize(). */
1160
1301
  get serverCapabilities(): InitializeResult["capabilities"];
@@ -1171,8 +1312,26 @@ declare class McpClient {
1171
1312
  initialize(): Promise<InitializeResult>;
1172
1313
  /** List tools the server exposes. */
1173
1314
  listTools(): Promise<ListToolsResult>;
1174
- /** Invoke a tool by name. Returns the raw MCP result (caller unwraps content). */
1175
- callTool(name: string, args?: Record<string, unknown>): Promise<CallToolResult>;
1315
+ /**
1316
+ * Invoke a tool by name. When `onProgress` is supplied, attaches a
1317
+ * fresh progress token so the server can send incremental updates
1318
+ * via `notifications/progress`; they're routed to the callback until
1319
+ * the final response arrives (or the request times out, in which
1320
+ * case the handler is simply dropped — no extra notification).
1321
+ *
1322
+ * When `signal` is supplied, aborting it:
1323
+ * 1) fires `notifications/cancelled` to the server (MCP 2024-11-05
1324
+ * way of saying "forget this request, I no longer care"), and
1325
+ * 2) rejects the pending promise immediately with an AbortError,
1326
+ * so the caller doesn't have to wait for the subprocess to
1327
+ * finish its in-flight file write or network request.
1328
+ * The server MAY still emit a late response; we drop it in dispatch
1329
+ * since the request id is gone from `pending`.
1330
+ */
1331
+ callTool(name: string, args?: Record<string, unknown>, opts?: {
1332
+ onProgress?: McpProgressHandler;
1333
+ signal?: AbortSignal;
1334
+ }): Promise<CallToolResult>;
1176
1335
  /**
1177
1336
  * List resources the server exposes. Supports a pagination cursor;
1178
1337
  * callers interested in the full set should loop on `nextCursor`.
@@ -1288,6 +1447,19 @@ interface BridgeOptions {
1288
1447
  * legitimately want bigger payloads can raise it explicitly.
1289
1448
  */
1290
1449
  maxResultChars?: number;
1450
+ /**
1451
+ * Callback fired for every `notifications/progress` frame the server
1452
+ * emits during any bridged tool call. Includes the registered
1453
+ * (prefix-applied) tool name so a multi-server UI can attribute
1454
+ * progress correctly. Absent → no `_meta.progressToken` is sent and
1455
+ * the server won't emit progress for these calls.
1456
+ */
1457
+ onProgress?: (info: {
1458
+ toolName: string;
1459
+ progress: number;
1460
+ total?: number;
1461
+ message?: string;
1462
+ }) => void;
1291
1463
  }
1292
1464
  /**
1293
1465
  * 32,000 chars ≈ 8k English tokens, or ~16k CJK tokens. Small enough to
@@ -1579,4 +1751,4 @@ declare function redactKey(key: string): string;
1579
1751
 
1580
1752
  declare const VERSION = "0.4.3";
1581
1753
 
1582
- export { AppendOnlyLog, type ApplyResult, type ApplyStatus, type BranchOptions, type BranchProgress, type BranchResult, type BranchSample, type BranchSelector, type BranchSummary, type BridgeOptions, type BridgeResult, CODE_SYSTEM_PROMPT, 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 EditBlock, type EditSnapshot, type EventRole, type FlattenDecision, type FlattenOptions, type GetPromptResult, type HarvestOptions, ImmutablePrefix, type ImmutablePrefixOptions, type InitializeResult, type InspectionReport, type JSONSchema, type JsonRpcMessage, type JsonRpcRequest, type JsonRpcResponse, type ListPromptsResult, type ListResourcesResult, type ListToolsResult, type LoopEvent, MCP_PROTOCOL_VERSION, McpClient, type McpClientOptions, type McpContentBlock, type McpPrompt, type McpPromptArgument, type McpPromptMessage, type McpPromptResourceBlock, type McpResource, type McpResourceContents, type McpResourceContentsBlob, type McpResourceContentsText, type McpSpec, type McpTool, type McpToolSchema, type McpTransport, type ReadResourceResult, type ReadTranscriptResult, type ReasonixConfig, type ReconfigurableOptions, type RepairReport, type ReplayStats, type RetryInfo, type RetryOptions, type Role, type ScavengeOptions, type ScavengeResult, type SectionResult, 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, applyEditBlock, applyEditBlocks, bridgeMcpTools, claudeEquivalentCost, codeSystemPrompt, computeReplayStats, costUsd, defaultConfigPath, defaultSelector, deleteSession, diffTranscripts, emptyPlanState, fetchWithRetry, flattenMcpResult, flattenSchema, formatLoopError, harvest, healLoadedMessages, inspectMcpServer, isJsonRpcError, isPlanStateEmpty, isPlausibleKey, listSessions, loadApiKey, loadDotenv, loadSessionMessages, nestArguments, openTranscriptFile, parseEditBlocks, parseMcpSpec, parseTranscript, readConfig, readTranscript, recordFromLoopEvent, redactKey, renderMarkdown as renderDiffMarkdown, renderSummaryTable as renderDiffSummary, repairTruncatedJson, replayFromFile, restoreSnapshots, runBranches, sanitizeName as sanitizeSessionName, saveApiKey, scavengeToolCalls, sessionPath, sessionsDir, similarity, snapshotBeforeEdits, stripHallucinatedToolMarkup, truncateForModel, writeConfig, writeMeta, writeRecord };
1754
+ export { AppendOnlyLog, type ApplyResult, type ApplyStatus, type BranchOptions, type BranchProgress, type BranchResult, type BranchSample, type BranchSelector, type BranchSummary, type BridgeOptions, type BridgeResult, CODE_SYSTEM_PROMPT, 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 EditBlock, type EditSnapshot, type EventRole, type FilesystemToolsOptions, type FlattenDecision, type FlattenOptions, type GetPromptResult, type HarvestOptions, ImmutablePrefix, type ImmutablePrefixOptions, type InitializeResult, type InspectionReport, type JSONSchema, type JsonRpcMessage, type JsonRpcRequest, type JsonRpcResponse, type ListPromptsResult, type ListResourcesResult, type ListToolsResult, type LoopEvent, MCP_PROTOCOL_VERSION, McpClient, type McpClientOptions, type McpContentBlock, type McpProgressHandler, type McpProgressInfo, type McpPrompt, type McpPromptArgument, type McpPromptMessage, type McpPromptResourceBlock, type McpResource, type McpResourceContents, type McpResourceContentsBlob, type McpResourceContentsText, type McpSpec, type McpTool, type McpToolSchema, type McpTransport, type ProgressNotificationParams, type ReadResourceResult, type ReadTranscriptResult, type ReasonixConfig, type ReconfigurableOptions, type RepairReport, type ReplayStats, type RetryInfo, type RetryOptions, type Role, type ScavengeOptions, type ScavengeResult, type SectionResult, type SessionInfo, SessionStats, type SessionSummary, type SseMcpSpec, SseTransport, type SseTransportOptions, type StdioMcpSpec, StdioTransport, type StdioTransportOptions, StormBreaker, type StreamChunk, type ToolCall, type ToolCallContext, 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, applyEditBlock, applyEditBlocks, bridgeMcpTools, claudeEquivalentCost, codeSystemPrompt, computeReplayStats, costUsd, defaultConfigPath, defaultSelector, deleteSession, diffTranscripts, emptyPlanState, fetchWithRetry, flattenMcpResult, flattenSchema, formatLoopError, harvest, healLoadedMessages, inputCostUsd, inspectMcpServer, isJsonRpcError, isPlanStateEmpty, isPlausibleKey, listSessions, loadApiKey, loadDotenv, loadSessionMessages, nestArguments, openTranscriptFile, outputCostUsd, parseEditBlocks, parseMcpSpec, parseTranscript, readConfig, readTranscript, recordFromLoopEvent, redactKey, registerFilesystemTools, renderMarkdown as renderDiffMarkdown, renderSummaryTable as renderDiffSummary, repairTruncatedJson, replayFromFile, restoreSnapshots, runBranches, sanitizeName as sanitizeSessionName, saveApiKey, scavengeToolCalls, sessionPath, sessionsDir, similarity, snapshotBeforeEdits, stripHallucinatedToolMarkup, truncateForModel, writeConfig, writeMeta, writeRecord };