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.
- package/dashboard/dist/app.js +1723 -574
- package/dashboard/dist/app.js.map +1 -1
- package/dist/cli/.-3G6VX5S7.js +327 -0
- package/dist/cli/.-6YRPB2C7.js +329 -0
- package/dist/cli/.-6YRPB2C7.js.map +1 -0
- package/dist/cli/.-EYSVINK3.js +317 -0
- package/dist/cli/.-EYSVINK3.js.map +1 -0
- package/dist/cli/banner-demo-QKOPDSTL.js +77 -0
- package/dist/cli/banner-demo-QKOPDSTL.js.map +1 -0
- package/dist/cli/card-demo-5TVXJISK.js +944 -0
- package/dist/cli/card-demo-5TVXJISK.js.map +1 -0
- package/dist/cli/chunk-2H7UOFLK.js +11 -0
- package/dist/cli/chunk-2H7UOFLK.js.map +1 -0
- package/dist/cli/chunk-BGTXZKNY.js +197 -0
- package/dist/cli/chunk-BGTXZKNY.js.map +1 -0
- package/dist/cli/chunk-JHXQDL7B.js +2056 -0
- package/dist/cli/chunk-JHXQDL7B.js.map +1 -0
- package/dist/cli/flicker-demo-MOB6GAW4.js +165 -0
- package/dist/cli/flicker-demo-MOB6GAW4.js.map +1 -0
- package/dist/cli/index.js +3654 -2035
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/preview-4FOEEE5G.js +224 -0
- package/dist/cli/preview-4FOEEE5G.js.map +1 -0
- package/dist/cli/{prompt-YUL7CYKY.js → prompt-VZQ2CPID.js} +2 -1
- package/dist/cli/prompt-VZQ2CPID.js.map +1 -0
- package/dist/cli/renderer-demo-2BIGEV2T.js +95 -0
- package/dist/cli/renderer-demo-2BIGEV2T.js.map +1 -0
- package/dist/cli/select-demo-OA5N34BJ.js +107 -0
- package/dist/cli/select-demo-OA5N34BJ.js.map +1 -0
- package/dist/cli/stress-demo-I7XRPQMM.js +211 -0
- package/dist/cli/stress-demo-I7XRPQMM.js.map +1 -0
- package/dist/index.d.ts +3 -2
- package/dist/index.js +22 -9
- package/dist/index.js.map +1 -1
- package/package.json +6 -4
- /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
|
|
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(
|
|
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) +
|
|
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} (${
|
|
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(
|
|
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
|
-
|
|
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
|
|
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)}${
|
|
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";
|