reasonix 0.4.15 → 0.4.17

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.
@@ -2,9 +2,9 @@
2
2
  import {
3
3
  CODE_SYSTEM_PROMPT,
4
4
  codeSystemPrompt
5
- } from "./chunk-2P2MZLCE.js";
5
+ } from "./chunk-3YQRWFES.js";
6
6
  export {
7
7
  CODE_SYSTEM_PROMPT,
8
8
  codeSystemPrompt
9
9
  };
10
- //# sourceMappingURL=prompt-MMANQ36Z.js.map
10
+ //# sourceMappingURL=prompt-HK5XLH55.js.map
package/dist/index.d.ts CHANGED
@@ -718,6 +718,61 @@ declare function healLoadedMessages(messages: ChatMessage[], maxChars: number):
718
718
  */
719
719
  declare function formatLoopError(err: Error): string;
720
720
 
721
+ /**
722
+ * Project memory — a user-authored `REASONIX.md` in the project root
723
+ * that gets pinned into the immutable-prefix system prompt.
724
+ *
725
+ * Design notes:
726
+ *
727
+ * - The file lands in `ImmutablePrefix.system`, so the whole memory
728
+ * block is hashed into the cache prefix fingerprint. Editing the
729
+ * file invalidates the prefix; unchanged memory across sessions
730
+ * keeps the DeepSeek prefix cache warm. That matches Pillar 1 —
731
+ * memory is a deliberate, stable prefix, not per-turn drift.
732
+ * - Only one source: the working-root `REASONIX.md`. No parent walk,
733
+ * no `~/.reasonix/REASONIX.md`, no CLAUDE.md fallback. User-global
734
+ * memory can come later; for v1 one file == one mental model.
735
+ * - Truncated at 8 000 chars (≈ 2k tokens). `.gitignore` gets 2 000
736
+ * because it's a constraint dump; memory gets more headroom because
737
+ * it's deliberate instructions.
738
+ * - Opt-out via `REASONIX_MEMORY=off|false|0`. No CLI flag — memory
739
+ * is a file, `rm REASONIX.md` is the other opt-out.
740
+ */
741
+ declare const PROJECT_MEMORY_FILE = "REASONIX.md";
742
+ declare const PROJECT_MEMORY_MAX_CHARS = 8000;
743
+ interface ProjectMemory {
744
+ /** Absolute path the memory was read from. */
745
+ path: string;
746
+ /** Post-truncation content (may include a "… (truncated N chars)" marker). */
747
+ content: string;
748
+ /** Original byte length before truncation. */
749
+ originalChars: number;
750
+ /** True iff `originalChars > PROJECT_MEMORY_MAX_CHARS`. */
751
+ truncated: boolean;
752
+ }
753
+ /**
754
+ * Read `REASONIX.md` from `rootDir`. Returns `null` when the file is
755
+ * missing, unreadable, or empty (whitespace-only counts as empty — an
756
+ * empty memory file shouldn't perturb the cache prefix).
757
+ */
758
+ declare function readProjectMemory(rootDir: string): ProjectMemory | null;
759
+ /**
760
+ * Resolve whether project memory should be read. Default: on.
761
+ * `REASONIX_MEMORY=off|false|0` turns it off (CI, reproducing issues,
762
+ * intentional offline runs).
763
+ */
764
+ declare function memoryEnabled(): boolean;
765
+ /**
766
+ * Return `basePrompt` with the project's `REASONIX.md` appended as a
767
+ * "Project memory" section. No-op when the file is absent, empty, or
768
+ * memory is disabled via env.
769
+ *
770
+ * The appended block is deterministic — identical input ⇒ identical
771
+ * output — so every session that opens against the same memory file
772
+ * gets the same prefix hash.
773
+ */
774
+ declare function applyProjectMemory(basePrompt: string, rootDir: string): string;
775
+
721
776
  /**
722
777
  * Built-in filesystem tools for `reasonix code`.
723
778
  *
@@ -762,6 +817,91 @@ interface FilesystemToolsOptions {
762
817
  }
763
818
  declare function registerFilesystemTools(registry: ToolRegistry, opts: FilesystemToolsOptions): ToolRegistry;
764
819
 
820
+ /**
821
+ * Native shell tool — lets the model run commands inside the sandbox
822
+ * root so it can actually verify its own work (run tests, check git
823
+ * status, inspect a lockfile, etc.). Without this the coding-mode
824
+ * loop is "write code, hope it works, ask the user to run it" —
825
+ * defeats the purpose.
826
+ *
827
+ * Safety model:
828
+ * - Commands run with `cwd` pinned to the registered root. No
829
+ * path traversal via the command itself is enforced (users can
830
+ * `cat ../outside.txt`); the trust boundary is the directory
831
+ * you opened Reasonix from.
832
+ * - Commands are matched against a read-only / testing allowlist.
833
+ * Allowlisted commands execute immediately and return stdout +
834
+ * stderr merged. Everything else throws with a clear message —
835
+ * the UI translates that into an `/apply`-style confirm gate so
836
+ * the user sees the exact command before it runs.
837
+ * - Default timeout: 60s. Output cap: matches tool-result budget.
838
+ * - Every command that DOES run is spawned with `shell: false` and
839
+ * a tokenized argv — no string-to-shell interpolation, so the
840
+ * model can't accidentally construct a chained `rm` via quoting.
841
+ *
842
+ * This is intentionally narrower than what Claude Code / Aider ship:
843
+ * we gate more commands behind confirmation by default. Users who
844
+ * trust the model can widen the allowlist by instantiating their
845
+ * own tool registry.
846
+ */
847
+
848
+ interface ShellToolsOptions {
849
+ /** Directory to run commands in. Must be an absolute path. */
850
+ rootDir: string;
851
+ /** Seconds before an individual command is killed. Default: 60. */
852
+ timeoutSec?: number;
853
+ /**
854
+ * Per-command stdout+stderr cap in characters. Default: 32_000 to
855
+ * match the tool-result budget.
856
+ */
857
+ maxOutputChars?: number;
858
+ /**
859
+ * Extra command-name prefixes the user explicitly trusts. Added on
860
+ * top of the built-in allowlist. Examples: `["my-ci-script", "lint"]`.
861
+ */
862
+ extraAllowed?: string[];
863
+ /**
864
+ * When true, skip the allowlist entirely and auto-run every command.
865
+ * Off by default — this is an escape hatch for non-interactive use
866
+ * (CI, benchmarks) where a human can't be in the loop to confirm.
867
+ */
868
+ allowAll?: boolean;
869
+ }
870
+ /**
871
+ * Tokenize a shell-ish command string into argv. Handles single/double
872
+ * quoting; rejects unclosed quotes. Does NOT expand env vars, globs,
873
+ * backticks, or `$(…)` — the goal is to prevent the model from
874
+ * accidentally (or not) sneaking arbitrary shells past the allowlist
875
+ * via concatenation. Exported for testing.
876
+ */
877
+ declare function tokenizeCommand(cmd: string): string[];
878
+ /**
879
+ * Return true when `cmd` matches an allowlisted prefix. Exported for
880
+ * testing. Match is on the space-normalized leading tokens so
881
+ * `git status -s ` and `git status` both match `git status`.
882
+ */
883
+ declare function isAllowed(cmd: string, extra?: readonly string[]): boolean;
884
+ interface RunCommandResult {
885
+ exitCode: number | null;
886
+ /** Combined stdout+stderr, truncated to `maxOutputChars` with a marker. */
887
+ output: string;
888
+ /** True when the process was killed for exceeding `timeoutSec`. */
889
+ timedOut: boolean;
890
+ }
891
+ declare function runCommand(cmd: string, opts: {
892
+ cwd: string;
893
+ timeoutSec?: number;
894
+ maxOutputChars?: number;
895
+ signal?: AbortSignal;
896
+ }): Promise<RunCommandResult>;
897
+ /** Error thrown by `run_command` when the command isn't allowlisted. */
898
+ declare class NeedsConfirmationError extends Error {
899
+ readonly command: string;
900
+ constructor(command: string);
901
+ }
902
+ declare function registerShellTools(registry: ToolRegistry, opts: ShellToolsOptions): ToolRegistry;
903
+ declare function formatCommandResult(cmd: string, r: RunCommandResult): string;
904
+
765
905
  /**
766
906
  * Built-in web search + fetch tools.
767
907
  *
@@ -1794,7 +1934,8 @@ declare const CODE_SYSTEM_PROMPT = "You are Reasonix Code, a coding assistant. Y
1794
1934
  * the file — we hand it to the model as-is. Truncate long ones so we
1795
1935
  * don't eat context budget on huge generated ignore lists.
1796
1936
  *
1797
- * Missing or unreadable .gitignore returns the base prompt unchanged.
1937
+ * Stacking order (stable for cache prefix):
1938
+ * base prompt → project memory (REASONIX.md) → .gitignore block
1798
1939
  */
1799
1940
  declare function codeSystemPrompt(rootDir: string): string;
1800
1941
 
@@ -1844,6 +1985,17 @@ interface ReasonixConfig {
1844
1985
  * endpoint). Set to `false` to keep the session offline.
1845
1986
  */
1846
1987
  search?: boolean;
1988
+ /**
1989
+ * Per-project state keyed by absolute directory path. Written by the
1990
+ * "always allow" choice on a shell confirmation prompt; merged into
1991
+ * `registerShellTools({ extraAllowed })` when `reasonix code` runs
1992
+ * against that directory again.
1993
+ */
1994
+ projects?: {
1995
+ [absoluteRootDir: string]: {
1996
+ shellAllowed?: string[];
1997
+ };
1998
+ };
1847
1999
  }
1848
2000
  declare function defaultConfigPath(): string;
1849
2001
  declare function readConfig(path?: string): ReasonixConfig;
@@ -1857,6 +2009,6 @@ declare function redactKey(key: string): string;
1857
2009
 
1858
2010
  /** Reasonix — DeepSeek-native agent framework. Library entry point. */
1859
2011
 
1860
- declare const VERSION = "0.4.15";
2012
+ declare const VERSION = "0.4.17";
1861
2013
 
1862
- 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 PageContent, 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 SearchResult, 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, type WebFetchOptions, type WebSearchOptions, type WebToolsOptions, aggregateBranchUsage, analyzeSchema, appendSessionMessage, applyEditBlock, applyEditBlocks, bridgeMcpTools, claudeEquivalentCost, codeSystemPrompt, computeReplayStats, costUsd, defaultConfigPath, defaultSelector, deleteSession, diffTranscripts, emptyPlanState, fetchWithRetry, flattenMcpResult, flattenSchema, formatLoopError, formatSearchResults, harvest, healLoadedMessages, htmlToText, inputCostUsd, inspectMcpServer, isJsonRpcError, isPlanStateEmpty, isPlausibleKey, listSessions, loadApiKey, loadDotenv, loadSessionMessages, nestArguments, openTranscriptFile, outputCostUsd, parseEditBlocks, parseMcpSpec, parseMojeekResults, parseTranscript, readConfig, readTranscript, recordFromLoopEvent, redactKey, registerFilesystemTools, registerWebTools, renderMarkdown as renderDiffMarkdown, renderSummaryTable as renderDiffSummary, repairTruncatedJson, replayFromFile, restoreSnapshots, runBranches, sanitizeName as sanitizeSessionName, saveApiKey, scavengeToolCalls, sessionPath, sessionsDir, similarity, snapshotBeforeEdits, stripHallucinatedToolMarkup, truncateForModel, webFetch, webSearch, writeConfig, writeMeta, writeRecord };
2014
+ 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, NeedsConfirmationError, PROJECT_MEMORY_FILE, PROJECT_MEMORY_MAX_CHARS, type PageContent, type ProgressNotificationParams, type ProjectMemory, type ReadResourceResult, type ReadTranscriptResult, type ReasonixConfig, type ReconfigurableOptions, type RepairReport, type ReplayStats, type RetryInfo, type RetryOptions, type Role, type RunCommandResult, type ScavengeOptions, type ScavengeResult, type SearchResult, type SectionResult, type SessionInfo, SessionStats, type SessionSummary, type ShellToolsOptions, 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, type WebFetchOptions, type WebSearchOptions, type WebToolsOptions, aggregateBranchUsage, analyzeSchema, appendSessionMessage, applyEditBlock, applyEditBlocks, applyProjectMemory, bridgeMcpTools, claudeEquivalentCost, codeSystemPrompt, computeReplayStats, costUsd, defaultConfigPath, defaultSelector, deleteSession, diffTranscripts, emptyPlanState, fetchWithRetry, flattenMcpResult, flattenSchema, formatCommandResult, formatLoopError, formatSearchResults, harvest, healLoadedMessages, htmlToText, inputCostUsd, inspectMcpServer, isAllowed, isJsonRpcError, isPlanStateEmpty, isPlausibleKey, listSessions, loadApiKey, loadDotenv, loadSessionMessages, memoryEnabled, nestArguments, openTranscriptFile, outputCostUsd, parseEditBlocks, parseMcpSpec, parseMojeekResults, parseTranscript, readConfig, readProjectMemory, readTranscript, recordFromLoopEvent, redactKey, registerFilesystemTools, registerShellTools, registerWebTools, renderMarkdown as renderDiffMarkdown, renderSummaryTable as renderDiffSummary, repairTruncatedJson, replayFromFile, restoreSnapshots, runBranches, runCommand, sanitizeName as sanitizeSessionName, saveApiKey, scavengeToolCalls, sessionPath, sessionsDir, similarity, snapshotBeforeEdits, stripHallucinatedToolMarkup, tokenizeCommand, truncateForModel, webFetch, webSearch, writeConfig, writeMeta, writeRecord };