reasonix 0.23.1 → 0.24.0

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.
Files changed (36) hide show
  1. package/dashboard/dist/app.js +1723 -574
  2. package/dashboard/dist/app.js.map +1 -1
  3. package/dist/cli/.-3G6VX5S7.js +327 -0
  4. package/dist/cli/.-6YRPB2C7.js +329 -0
  5. package/dist/cli/.-6YRPB2C7.js.map +1 -0
  6. package/dist/cli/.-EYSVINK3.js +317 -0
  7. package/dist/cli/.-EYSVINK3.js.map +1 -0
  8. package/dist/cli/banner-demo-QKOPDSTL.js +77 -0
  9. package/dist/cli/banner-demo-QKOPDSTL.js.map +1 -0
  10. package/dist/cli/card-demo-5TVXJISK.js +944 -0
  11. package/dist/cli/card-demo-5TVXJISK.js.map +1 -0
  12. package/dist/cli/chunk-2H7UOFLK.js +11 -0
  13. package/dist/cli/chunk-2H7UOFLK.js.map +1 -0
  14. package/dist/cli/chunk-BGTXZKNY.js +197 -0
  15. package/dist/cli/chunk-BGTXZKNY.js.map +1 -0
  16. package/dist/cli/chunk-JHXQDL7B.js +2056 -0
  17. package/dist/cli/chunk-JHXQDL7B.js.map +1 -0
  18. package/dist/cli/flicker-demo-MOB6GAW4.js +165 -0
  19. package/dist/cli/flicker-demo-MOB6GAW4.js.map +1 -0
  20. package/dist/cli/index.js +3654 -2035
  21. package/dist/cli/index.js.map +1 -1
  22. package/dist/cli/preview-4FOEEE5G.js +224 -0
  23. package/dist/cli/preview-4FOEEE5G.js.map +1 -0
  24. package/dist/cli/{prompt-YUL7CYKY.js → prompt-VZQ2CPID.js} +2 -1
  25. package/dist/cli/prompt-VZQ2CPID.js.map +1 -0
  26. package/dist/cli/renderer-demo-2BIGEV2T.js +95 -0
  27. package/dist/cli/renderer-demo-2BIGEV2T.js.map +1 -0
  28. package/dist/cli/select-demo-OA5N34BJ.js +107 -0
  29. package/dist/cli/select-demo-OA5N34BJ.js.map +1 -0
  30. package/dist/cli/stress-demo-I7XRPQMM.js +211 -0
  31. package/dist/cli/stress-demo-I7XRPQMM.js.map +1 -0
  32. package/dist/index.d.ts +3 -2
  33. package/dist/index.js +22 -9
  34. package/dist/index.js.map +1 -1
  35. package/package.json +6 -4
  36. /package/dist/cli/{prompt-YUL7CYKY.js.map → .-3G6VX5S7.js.map} +0 -0
@@ -0,0 +1,211 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ CharPool,
4
+ HyperlinkPool,
5
+ StylePool,
6
+ ink_compat_exports,
7
+ mount,
8
+ useKeystroke
9
+ } from "./chunk-JHXQDL7B.js";
10
+ import "./chunk-2H7UOFLK.js";
11
+
12
+ // src/cli/commands/stress-demo.tsx
13
+ import React, { useEffect, useRef, useState } from "react";
14
+ var BRAND = "#79c0ff";
15
+ var FAINT = "#6e7681";
16
+ var META = "#8b949e";
17
+ var ACCENT = "#d2a8ff";
18
+ var OK = "#7ee787";
19
+ var PEND = "#484f58";
20
+ var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
21
+ var SHELL_LINES = [
22
+ " PASS src/loop.test.ts",
23
+ " PASS src/parser.test.ts",
24
+ " PASS src/cli/index.test.ts",
25
+ " PASS src/cli/commands/chat.test.ts",
26
+ " PASS src/diff/cell.test.ts",
27
+ " PASS src/diff/screen.test.ts",
28
+ " PASS src/renderer/layout.test.ts",
29
+ " PASS src/renderer/diff.test.ts",
30
+ " PASS src/renderer/serialize.test.ts",
31
+ "",
32
+ "Test Suites: 9 passed, 9 total",
33
+ "Tests: 142 passed, 142 total"
34
+ ];
35
+ var RESPONSE = [
36
+ "Working through the failing test on src/loop.test.ts.",
37
+ "The assertion on line 42 expects the parser to drop the trailing tool-call",
38
+ "marker, but the new tokenizer keeps it. Two paths forward \u2014 patch the",
39
+ "tokenizer's strip step, or update the expectation."
40
+ ].join(" ");
41
+ var PLAN_STEPS = [
42
+ { label: "identify the failing test", status: "done" },
43
+ { label: "wire the regression check", status: "running" },
44
+ { label: "rebuild dist", status: "pending" },
45
+ { label: "publish patch", status: "pending" }
46
+ ];
47
+ function StatusRow({ elapsedMs }) {
48
+ const seconds = (elapsedMs / 1e3).toFixed(1);
49
+ const cost = elapsedMs / 1e3 * 8e-4;
50
+ return /* @__PURE__ */ React.createElement(ink_compat_exports.Box, { flexDirection: "row", gap: 2 }, /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { color: BRAND, bold: true }, "\u25C8 Reasonix"), /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { color: META }, "working"), /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { color: FAINT }, `${seconds}s elapsed`), /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { color: FAINT }, `$${cost.toFixed(4)}`));
51
+ }
52
+ function PlanCard({ frame }) {
53
+ const spin = SPINNER_FRAMES[frame % SPINNER_FRAMES.length] ?? "\xB7";
54
+ return /* @__PURE__ */ React.createElement(
55
+ ink_compat_exports.Box,
56
+ {
57
+ flexDirection: "column",
58
+ borderStyle: "round",
59
+ borderColor: ACCENT,
60
+ paddingX: 1,
61
+ marginTop: 1
62
+ },
63
+ /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { color: ACCENT, bold: true }, "\u229E Plan"),
64
+ PLAN_STEPS.map((step) => {
65
+ const { glyph, color } = decoratePlan(step.status, spin);
66
+ return /* @__PURE__ */ React.createElement(ink_compat_exports.Box, { key: step.label, flexDirection: "row", gap: 1 }, /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { color }, glyph), /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { dimColor: step.status === "pending" }, step.label));
67
+ })
68
+ );
69
+ }
70
+ function decoratePlan(status, spin) {
71
+ switch (status) {
72
+ case "done":
73
+ return { glyph: "\u2713", color: OK };
74
+ case "running":
75
+ return { glyph: spin, color: BRAND };
76
+ case "pending":
77
+ return { glyph: "\u25CB", color: PEND };
78
+ }
79
+ }
80
+ var SHELL_WINDOW = 5;
81
+ function ShellCard({ lines, frame }) {
82
+ const total = Math.min(lines, SHELL_LINES.length);
83
+ const startIdx = Math.max(0, total - SHELL_WINDOW);
84
+ const visible = SHELL_LINES.slice(startIdx, total);
85
+ const hidden = startIdx;
86
+ const running = lines < SHELL_LINES.length;
87
+ const spin = SPINNER_FRAMES[frame % SPINNER_FRAMES.length] ?? "\xB7";
88
+ return /* @__PURE__ */ React.createElement(
89
+ ink_compat_exports.Box,
90
+ {
91
+ flexDirection: "column",
92
+ borderStyle: "round",
93
+ borderColor: BRAND,
94
+ paddingX: 1,
95
+ marginTop: 1
96
+ },
97
+ /* @__PURE__ */ React.createElement(ink_compat_exports.Box, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { color: BRAND }, running ? spin : "\u2713"), /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { color: BRAND, bold: true }, "npm test"), hidden > 0 ? /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { color: FAINT }, `(+${hidden} earlier)`) : null),
98
+ visible.map((line, i) => (
99
+ // biome-ignore lint/suspicious/noArrayIndexKey: shell output lines are positional + append-only
100
+ /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { key: `shell-${startIdx + i}`, dimColor: line.startsWith(" PASS") }, line || " ")
101
+ ))
102
+ );
103
+ }
104
+ function ResponseCard({
105
+ revealed,
106
+ frame
107
+ }) {
108
+ const text = RESPONSE.slice(0, revealed);
109
+ const done = revealed >= RESPONSE.length;
110
+ const glyph = done ? "\u2039" : SPINNER_FRAMES[frame % SPINNER_FRAMES.length] ?? "\xB7";
111
+ return /* @__PURE__ */ React.createElement(
112
+ ink_compat_exports.Box,
113
+ {
114
+ flexDirection: "column",
115
+ borderStyle: "round",
116
+ borderColor: OK,
117
+ paddingX: 1,
118
+ marginTop: 1
119
+ },
120
+ /* @__PURE__ */ React.createElement(ink_compat_exports.Box, { flexDirection: "row", gap: 1 }, /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { color: done ? OK : BRAND }, glyph), /* @__PURE__ */ React.createElement(ink_compat_exports.Text, null, text || "thinking\u2026"))
121
+ );
122
+ }
123
+ function StressShell({ onExit }) {
124
+ const [elapsed, setElapsed] = useState(0);
125
+ const [planFrame, setPlanFrame] = useState(0);
126
+ const [shellLines, setShellLines] = useState(0);
127
+ const [shellFrame, setShellFrame] = useState(0);
128
+ const [revealed, setRevealed] = useState(0);
129
+ const [responseFrame, setResponseFrame] = useState(0);
130
+ const startedRef = useRef(Date.now());
131
+ useKeystroke((k) => {
132
+ if (k.escape) onExit();
133
+ });
134
+ useEffect(() => {
135
+ const id = setInterval(() => {
136
+ setElapsed(Date.now() - startedRef.current);
137
+ }, 100);
138
+ return () => clearInterval(id);
139
+ }, []);
140
+ useEffect(() => {
141
+ const id = setInterval(() => {
142
+ setPlanFrame((f) => f + 1);
143
+ }, 80);
144
+ return () => clearInterval(id);
145
+ }, []);
146
+ useEffect(() => {
147
+ const id = setInterval(() => {
148
+ setShellFrame((f) => f + 1);
149
+ }, 80);
150
+ return () => clearInterval(id);
151
+ }, []);
152
+ useEffect(() => {
153
+ const id = setInterval(() => {
154
+ setShellLines((n) => Math.min(SHELL_LINES.length, n + 1));
155
+ }, 250);
156
+ return () => clearInterval(id);
157
+ }, []);
158
+ useEffect(() => {
159
+ const id = setInterval(() => {
160
+ setResponseFrame((f) => f + 1);
161
+ }, 80);
162
+ return () => clearInterval(id);
163
+ }, []);
164
+ useEffect(() => {
165
+ const id = setInterval(() => {
166
+ setRevealed((r) => Math.min(RESPONSE.length, r + 4));
167
+ }, 33);
168
+ return () => clearInterval(id);
169
+ }, []);
170
+ return /* @__PURE__ */ React.createElement(ink_compat_exports.Box, { flexDirection: "column" }, /* @__PURE__ */ React.createElement(StatusRow, { elapsedMs: elapsed }), /* @__PURE__ */ React.createElement(PlanCard, { frame: planFrame }), /* @__PURE__ */ React.createElement(ShellCard, { lines: shellLines, frame: shellFrame }), /* @__PURE__ */ React.createElement(ResponseCard, { revealed, frame: responseFrame }), /* @__PURE__ */ React.createElement(ink_compat_exports.Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(ink_compat_exports.Text, { dimColor: true }, "stress mode \xB7 4 concurrent live regions \xB7 Esc exit")));
171
+ }
172
+ async function runStressDemo(opts = {}) {
173
+ const stdout = opts.stdout ?? process.stdout;
174
+ const stdin = opts.stdin ?? process.stdin;
175
+ if (!stdin.isTTY || !stdout.isTTY) {
176
+ console.error("stress-demo requires an interactive TTY.");
177
+ process.exit(1);
178
+ }
179
+ const pools = {
180
+ char: new CharPool(),
181
+ style: new StylePool(),
182
+ hyperlink: new HyperlinkPool()
183
+ };
184
+ let resolveExit = () => {
185
+ };
186
+ const exited = new Promise((resolve) => {
187
+ resolveExit = resolve;
188
+ });
189
+ const handle = mount(/* @__PURE__ */ React.createElement(StressShell, { onExit: () => resolveExit() }), {
190
+ viewportWidth: stdout.columns ?? 80,
191
+ viewportHeight: stdout.rows ?? 30,
192
+ pools,
193
+ write: (bytes) => stdout.write(bytes),
194
+ stdin,
195
+ onExit: () => resolveExit()
196
+ });
197
+ const onResize = () => handle.resize(stdout.columns ?? 80, stdout.rows ?? 30);
198
+ stdout.on("resize", onResize);
199
+ try {
200
+ await exited;
201
+ } finally {
202
+ stdout.off("resize", onResize);
203
+ handle.destroy();
204
+ stdin.pause();
205
+ }
206
+ }
207
+ export {
208
+ StressShell,
209
+ runStressDemo
210
+ };
211
+ //# sourceMappingURL=stress-demo-I7XRPQMM.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/cli/commands/stress-demo.tsx"],"sourcesContent":["// biome-ignore lint/style/useImportType: tsconfig jsx=react needs React in value scope for JSX compilation\nimport React, { useEffect, useRef, useState } from \"react\";\nimport {\n CharPool,\n type Handle,\n HyperlinkPool,\n StylePool,\n inkCompat,\n mount,\n useKeystroke,\n} from \"../../renderer/index.js\";\n\nconst BRAND = \"#79c0ff\";\nconst FAINT = \"#6e7681\";\nconst META = \"#8b949e\";\nconst ACCENT = \"#d2a8ff\";\nconst OK = \"#7ee787\";\nconst PEND = \"#484f58\";\n\nconst SPINNER_FRAMES = [\"⠋\", \"⠙\", \"⠹\", \"⠸\", \"⠼\", \"⠴\", \"⠦\", \"⠧\", \"⠇\", \"⠏\"] as const;\nconst SHELL_LINES = [\n \" PASS src/loop.test.ts\",\n \" PASS src/parser.test.ts\",\n \" PASS src/cli/index.test.ts\",\n \" PASS src/cli/commands/chat.test.ts\",\n \" PASS src/diff/cell.test.ts\",\n \" PASS src/diff/screen.test.ts\",\n \" PASS src/renderer/layout.test.ts\",\n \" PASS src/renderer/diff.test.ts\",\n \" PASS src/renderer/serialize.test.ts\",\n \"\",\n \"Test Suites: 9 passed, 9 total\",\n \"Tests: 142 passed, 142 total\",\n] as const;\nconst RESPONSE = [\n \"Working through the failing test on src/loop.test.ts.\",\n \"The assertion on line 42 expects the parser to drop the trailing tool-call\",\n \"marker, but the new tokenizer keeps it. Two paths forward — patch the\",\n \"tokenizer's strip step, or update the expectation.\",\n].join(\" \");\n\ninterface PlanStep {\n readonly label: string;\n readonly status: \"done\" | \"running\" | \"pending\";\n}\n\nconst PLAN_STEPS: ReadonlyArray<PlanStep> = [\n { label: \"identify the failing test\", status: \"done\" },\n { label: \"wire the regression check\", status: \"running\" },\n { label: \"rebuild dist\", status: \"pending\" },\n { label: \"publish patch\", status: \"pending\" },\n];\n\nfunction StatusRow({ elapsedMs }: { elapsedMs: number }): React.ReactElement {\n const seconds = (elapsedMs / 1000).toFixed(1);\n const cost = (elapsedMs / 1000) * 0.0008;\n return (\n <inkCompat.Box flexDirection=\"row\" gap={2}>\n <inkCompat.Text color={BRAND} bold>\n ◈ Reasonix\n </inkCompat.Text>\n <inkCompat.Text color={META}>working</inkCompat.Text>\n <inkCompat.Text color={FAINT}>{`${seconds}s elapsed`}</inkCompat.Text>\n <inkCompat.Text color={FAINT}>{`$${cost.toFixed(4)}`}</inkCompat.Text>\n </inkCompat.Box>\n );\n}\n\nfunction PlanCard({ frame }: { frame: number }): React.ReactElement {\n const spin = SPINNER_FRAMES[frame % SPINNER_FRAMES.length] ?? \"·\";\n return (\n <inkCompat.Box\n flexDirection=\"column\"\n borderStyle=\"round\"\n borderColor={ACCENT}\n paddingX={1}\n marginTop={1}\n >\n <inkCompat.Text color={ACCENT} bold>\n ⊞ Plan\n </inkCompat.Text>\n {PLAN_STEPS.map((step) => {\n const { glyph, color } = decoratePlan(step.status, spin);\n return (\n <inkCompat.Box key={step.label} flexDirection=\"row\" gap={1}>\n <inkCompat.Text color={color}>{glyph}</inkCompat.Text>\n <inkCompat.Text dimColor={step.status === \"pending\"}>{step.label}</inkCompat.Text>\n </inkCompat.Box>\n );\n })}\n </inkCompat.Box>\n );\n}\n\nfunction decoratePlan(status: PlanStep[\"status\"], spin: string): { glyph: string; color: string } {\n switch (status) {\n case \"done\":\n return { glyph: \"✓\", color: OK };\n case \"running\":\n return { glyph: spin, color: BRAND };\n case \"pending\":\n return { glyph: \"○\", color: PEND };\n }\n}\n\nconst SHELL_WINDOW = 5;\n\nfunction ShellCard({ lines, frame }: { lines: number; frame: number }): React.ReactElement {\n const total = Math.min(lines, SHELL_LINES.length);\n const startIdx = Math.max(0, total - SHELL_WINDOW);\n const visible = SHELL_LINES.slice(startIdx, total);\n const hidden = startIdx;\n const running = lines < SHELL_LINES.length;\n const spin = SPINNER_FRAMES[frame % SPINNER_FRAMES.length] ?? \"·\";\n return (\n <inkCompat.Box\n flexDirection=\"column\"\n borderStyle=\"round\"\n borderColor={BRAND}\n paddingX={1}\n marginTop={1}\n >\n <inkCompat.Box flexDirection=\"row\" gap={1}>\n <inkCompat.Text color={BRAND}>{running ? spin : \"✓\"}</inkCompat.Text>\n <inkCompat.Text color={BRAND} bold>\n npm test\n </inkCompat.Text>\n {hidden > 0 ? (\n <inkCompat.Text color={FAINT}>{`(+${hidden} earlier)`}</inkCompat.Text>\n ) : null}\n </inkCompat.Box>\n {visible.map((line, i) => (\n // biome-ignore lint/suspicious/noArrayIndexKey: shell output lines are positional + append-only\n <inkCompat.Text key={`shell-${startIdx + i}`} dimColor={line.startsWith(\" PASS\")}>\n {line || \" \"}\n </inkCompat.Text>\n ))}\n </inkCompat.Box>\n );\n}\n\nfunction ResponseCard({\n revealed,\n frame,\n}: { revealed: number; frame: number }): React.ReactElement {\n const text = RESPONSE.slice(0, revealed);\n const done = revealed >= RESPONSE.length;\n const glyph = done ? \"‹\" : (SPINNER_FRAMES[frame % SPINNER_FRAMES.length] ?? \"·\");\n return (\n <inkCompat.Box\n flexDirection=\"column\"\n borderStyle=\"round\"\n borderColor={OK}\n paddingX={1}\n marginTop={1}\n >\n <inkCompat.Box flexDirection=\"row\" gap={1}>\n <inkCompat.Text color={done ? OK : BRAND}>{glyph}</inkCompat.Text>\n <inkCompat.Text>{text || \"thinking…\"}</inkCompat.Text>\n </inkCompat.Box>\n </inkCompat.Box>\n );\n}\n\ninterface ShellProps {\n onExit: () => void;\n}\n\nexport function StressShell({ onExit }: ShellProps): React.ReactElement {\n const [elapsed, setElapsed] = useState(0);\n const [planFrame, setPlanFrame] = useState(0);\n const [shellLines, setShellLines] = useState(0);\n const [shellFrame, setShellFrame] = useState(0);\n const [revealed, setRevealed] = useState(0);\n const [responseFrame, setResponseFrame] = useState(0);\n\n const startedRef = useRef(Date.now());\n\n useKeystroke((k) => {\n if (k.escape) onExit();\n });\n\n useEffect(() => {\n const id = setInterval(() => {\n setElapsed(Date.now() - startedRef.current);\n }, 100);\n return () => clearInterval(id);\n }, []);\n\n useEffect(() => {\n const id = setInterval(() => {\n setPlanFrame((f) => f + 1);\n }, 80);\n return () => clearInterval(id);\n }, []);\n\n useEffect(() => {\n const id = setInterval(() => {\n setShellFrame((f) => f + 1);\n }, 80);\n return () => clearInterval(id);\n }, []);\n\n useEffect(() => {\n const id = setInterval(() => {\n setShellLines((n) => Math.min(SHELL_LINES.length, n + 1));\n }, 250);\n return () => clearInterval(id);\n }, []);\n\n useEffect(() => {\n const id = setInterval(() => {\n setResponseFrame((f) => f + 1);\n }, 80);\n return () => clearInterval(id);\n }, []);\n\n useEffect(() => {\n const id = setInterval(() => {\n setRevealed((r) => Math.min(RESPONSE.length, r + 4));\n }, 33);\n return () => clearInterval(id);\n }, []);\n\n return (\n <inkCompat.Box flexDirection=\"column\">\n <StatusRow elapsedMs={elapsed} />\n <PlanCard frame={planFrame} />\n <ShellCard lines={shellLines} frame={shellFrame} />\n <ResponseCard revealed={revealed} frame={responseFrame} />\n <inkCompat.Box marginTop={1}>\n <inkCompat.Text dimColor>stress mode · 4 concurrent live regions · Esc exit</inkCompat.Text>\n </inkCompat.Box>\n </inkCompat.Box>\n );\n}\n\nexport interface StressDemoOptions {\n readonly stdout?: NodeJS.WriteStream;\n readonly stdin?: NodeJS.ReadStream;\n}\n\nexport async function runStressDemo(opts: StressDemoOptions = {}): Promise<void> {\n const stdout = opts.stdout ?? process.stdout;\n const stdin = opts.stdin ?? process.stdin;\n\n if (!stdin.isTTY || !stdout.isTTY) {\n console.error(\"stress-demo requires an interactive TTY.\");\n process.exit(1);\n }\n\n const pools = {\n char: new CharPool(),\n style: new StylePool(),\n hyperlink: new HyperlinkPool(),\n };\n\n let resolveExit: () => void = () => {};\n const exited = new Promise<void>((resolve) => {\n resolveExit = resolve;\n });\n\n const handle: Handle = mount(<StressShell onExit={() => resolveExit()} />, {\n viewportWidth: stdout.columns ?? 80,\n viewportHeight: stdout.rows ?? 30,\n pools,\n write: (bytes) => stdout.write(bytes),\n stdin,\n onExit: () => resolveExit(),\n });\n\n const onResize = () => handle.resize(stdout.columns ?? 80, stdout.rows ?? 30);\n stdout.on(\"resize\", onResize);\n\n try {\n await exited;\n } finally {\n stdout.off(\"resize\", onResize);\n handle.destroy();\n stdin.pause();\n }\n}\n"],"mappings":"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","names":[]}
package/dist/index.d.ts CHANGED
@@ -1830,6 +1830,8 @@ interface CodeSystemPromptOptions {
1830
1830
  }
1831
1831
  declare function codeSystemPrompt(rootDir: string, opts?: CodeSystemPromptOptions): string;
1832
1832
 
1833
+ type LanguageCode = "EN" | "zh-CN";
1834
+
1833
1835
  /** Shared exclude defaults + resolver — chunker, directory_tree, and dashboard read from here. */
1834
1836
  interface IndexUserConfig {
1835
1837
  excludeDirs?: string[];
@@ -1850,6 +1852,7 @@ type ReasoningEffort = "high" | "max";
1850
1852
  interface ReasonixConfig {
1851
1853
  apiKey?: string;
1852
1854
  baseUrl?: string;
1855
+ lang?: LanguageCode;
1853
1856
  preset?: PresetName;
1854
1857
  editMode?: EditMode;
1855
1858
  editModeHintShown?: boolean;
@@ -1861,8 +1864,6 @@ interface ReasonixConfig {
1861
1864
  session?: string | null;
1862
1865
  setupCompleted?: boolean;
1863
1866
  search?: boolean;
1864
- /** Persisted sidebar visibility — undefined = auto (open on cols ≥ 120). */
1865
- sidebarOpen?: boolean;
1866
1867
  projects?: {
1867
1868
  [absoluteRootDir: string]: {
1868
1869
  shellAllowed?: string[];
package/dist/index.js CHANGED
@@ -974,7 +974,8 @@ var ToolRegistry = class {
974
974
  }
975
975
  if (this._planMode && !isReadOnlyCall(tool, args)) {
976
976
  return JSON.stringify({
977
- error: `${name}: unavailable in plan mode \u2014 this is a read-only exploration phase. Use read_file / list_directory / search_files / directory_tree / web_search / allowlisted shell commands to investigate. Call submit_plan with your proposed plan when you're ready for the user's review.`
977
+ error: `${name}: unavailable in plan mode \u2014 this is a read-only exploration phase. Use read_file / list_directory / search_files / directory_tree / web_search / allowlisted shell commands to investigate. Call submit_plan with your proposed plan when you're ready for the user's review.`,
978
+ rejectedReason: "plan-mode"
978
979
  });
979
980
  }
980
981
  if (this._interceptor) {
@@ -4573,22 +4574,25 @@ Prefer \`list_directory\` for a single-level view, \`search_files\` to find spec
4573
4574
  if (args.search.length === 0) {
4574
4575
  throw new Error("edit_file: search cannot be empty");
4575
4576
  }
4576
- const firstIdx = before.indexOf(args.search);
4577
+ const le = before.includes("\r\n") ? "\r\n" : "\n";
4578
+ const adaptedSearch = args.search.replace(/\r?\n/g, le);
4579
+ const adaptedReplace = args.replace.replace(/\r?\n/g, le);
4580
+ const firstIdx = before.indexOf(adaptedSearch);
4577
4581
  if (firstIdx < 0) {
4578
4582
  throw new Error(`edit_file: search text not found in ${pathMod.relative(rootDir, abs)}`);
4579
4583
  }
4580
- const nextIdx = before.indexOf(args.search, firstIdx + 1);
4584
+ const nextIdx = before.indexOf(adaptedSearch, firstIdx + 1);
4581
4585
  if (nextIdx >= 0) {
4582
4586
  throw new Error(
4583
4587
  `edit_file: search text appears multiple times in ${pathMod.relative(rootDir, abs)} \u2014 include more context to disambiguate`
4584
4588
  );
4585
4589
  }
4586
- const after = before.slice(0, firstIdx) + args.replace + before.slice(firstIdx + args.search.length);
4590
+ const after = before.slice(0, firstIdx) + adaptedReplace + before.slice(firstIdx + adaptedSearch.length);
4587
4591
  await fs.writeFile(abs, after, "utf8");
4588
4592
  const rel = pathMod.relative(rootDir, abs);
4589
- const header = `edited ${rel} (${args.search.length}\u2192${args.replace.length} chars)`;
4593
+ const header = `edited ${rel} (${adaptedSearch.length}\u2192${adaptedReplace.length} chars)`;
4590
4594
  const startLine = before.slice(0, firstIdx).split(/\r?\n/).length;
4591
- const diff = renderEditDiff(args.search, args.replace, startLine);
4595
+ const diff = renderEditDiff(adaptedSearch, adaptedReplace, startLine);
4592
4596
  return `${header}
4593
4597
  ${diff}`;
4594
4598
  }
@@ -7381,7 +7385,10 @@ var StdioTransport = class {
7381
7385
  } catch {
7382
7386
  }
7383
7387
  if (this.child.exitCode === null && !this.child.killed) {
7384
- this.child.kill("SIGTERM");
7388
+ try {
7389
+ this.child.kill(process.platform === "win32" ? void 0 : "SIGTERM");
7390
+ } catch {
7391
+ }
7385
7392
  }
7386
7393
  }
7387
7394
  /** Parse incoming stdout chunks into NDJSON messages. */
@@ -7869,7 +7876,10 @@ function applyEditBlock(block, rootDir) {
7869
7876
  message: "empty SEARCH only creates new files \u2014 this file already exists"
7870
7877
  };
7871
7878
  }
7872
- const idx = content.indexOf(block.search);
7879
+ const le = lineEndingOf(content);
7880
+ const adaptedSearch = block.search.replace(/\r?\n/g, le);
7881
+ const adaptedReplace = block.replace.replace(/\r?\n/g, le);
7882
+ const idx = content.indexOf(adaptedSearch);
7873
7883
  if (idx === -1) {
7874
7884
  return {
7875
7885
  path: block.path,
@@ -7877,7 +7887,7 @@ function applyEditBlock(block, rootDir) {
7877
7887
  message: "SEARCH text does not match the current file content exactly"
7878
7888
  };
7879
7889
  }
7880
- const replaced = `${content.slice(0, idx)}${block.replace}${content.slice(idx + block.search.length)}`;
7890
+ const replaced = `${content.slice(0, idx)}${adaptedReplace}${content.slice(idx + adaptedSearch.length)}`;
7881
7891
  writeFileSync4(absTarget, replaced, "utf8");
7882
7892
  return { path: block.path, status: "applied" };
7883
7893
  } catch (err) {
@@ -7941,6 +7951,9 @@ function restoreSnapshots(snapshots, rootDir) {
7941
7951
  function sep() {
7942
7952
  return process.platform === "win32" ? "\\" : "/";
7943
7953
  }
7954
+ function lineEndingOf(text) {
7955
+ return text.includes("\r\n") ? "\r\n" : "\n";
7956
+ }
7944
7957
 
7945
7958
  // src/code/prompt.ts
7946
7959
  import { existsSync as existsSync11, readFileSync as readFileSync13 } from "fs";