reasonix 0.33.2 → 0.34.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 +1 -21
- package/dashboard/dist/app.js.map +1 -1
- package/dist/cli/{chat-ZMSAXE77.js → chat-TL4HMNEQ.js} +14 -13
- package/dist/cli/chunk-2EBODRRO.js +149 -0
- package/dist/cli/chunk-2EBODRRO.js.map +1 -0
- package/dist/cli/{chunk-DULSP7JH.js → chunk-5JXXEPDM.js} +34 -1
- package/dist/cli/chunk-5JXXEPDM.js.map +1 -0
- package/dist/cli/{chunk-OW7IHE6M.js → chunk-5SAMVHA3.js} +584 -288
- package/dist/cli/chunk-5SAMVHA3.js.map +1 -0
- package/dist/cli/{chunk-WVJL7ZO2.js → chunk-F3ILWP2L.js} +4 -4
- package/dist/cli/{chunk-SDE5U32Z.js → chunk-KZHMKOJH.js} +13 -8
- package/dist/cli/{chunk-SDE5U32Z.js.map → chunk-KZHMKOJH.js.map} +1 -1
- package/dist/cli/{chunk-G7M3QWEN.js → chunk-LNTORE5K.js} +225 -132
- package/dist/cli/chunk-LNTORE5K.js.map +1 -0
- package/dist/cli/chunk-MRLXEMZ7.js +26 -0
- package/dist/cli/chunk-MRLXEMZ7.js.map +1 -0
- package/dist/cli/{chunk-WBDE4IRI.js → chunk-OERAGRJX.js} +2 -2
- package/dist/cli/{chunk-QGE6AF76.js → chunk-Q36KBLSU.js} +207 -8
- package/dist/cli/chunk-Q36KBLSU.js.map +1 -0
- package/dist/cli/{chunk-RZILUXUC.js → chunk-RXGEGA7K.js} +2 -2
- package/dist/cli/{chunk-FXGQ5NHE.js → chunk-SA4UGZPG.js} +21 -1
- package/dist/cli/chunk-SA4UGZPG.js.map +1 -0
- package/dist/cli/{chunk-J5VLP23S.js → chunk-SW3CCXEV.js} +2 -2
- package/dist/cli/{chunk-W4LDFAZ6.js → chunk-SX6L4HZZ.js} +2 -2
- package/dist/cli/chunk-WUI3P4RA.js +319 -0
- package/dist/cli/chunk-WUI3P4RA.js.map +1 -0
- package/dist/cli/{code-R4TXQQEE.js → code-V6F4BKMG.js} +15 -14
- package/dist/cli/{code-R4TXQQEE.js.map → code-V6F4BKMG.js.map} +1 -1
- package/dist/cli/{commands-JWT2MWVH.js → commands-MEZPSEHV.js} +4 -3
- package/dist/cli/{commands-JWT2MWVH.js.map → commands-MEZPSEHV.js.map} +1 -1
- package/dist/cli/{commit-RPZBOZS2.js → commit-CE4EFTUQ.js} +3 -2
- package/dist/cli/{commit-RPZBOZS2.js.map → commit-CE4EFTUQ.js.map} +1 -1
- package/dist/cli/{doctor-V5HLCMSQ.js → doctor-YASM64X6.js} +7 -6
- package/dist/cli/index.js +22 -21
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/{mcp-ARTNQ24O.js → mcp-LDFK5QJI.js} +3 -2
- package/dist/cli/{mcp-ARTNQ24O.js.map → mcp-LDFK5QJI.js.map} +1 -1
- package/dist/cli/{mcp-browse-HLO2ENDL.js → mcp-browse-FYHEITCM.js} +3 -2
- package/dist/cli/{mcp-browse-HLO2ENDL.js.map → mcp-browse-FYHEITCM.js.map} +1 -1
- package/dist/cli/{replay-Q43DSMG6.js → replay-JEDLU7F2.js} +8 -6
- package/dist/cli/{replay-Q43DSMG6.js.map → replay-JEDLU7F2.js.map} +1 -1
- package/dist/cli/{run-HK3FP266.js → run-NHD2RSTD.js} +7 -6
- package/dist/cli/{run-HK3FP266.js.map → run-NHD2RSTD.js.map} +1 -1
- package/dist/cli/{server-SYC3OVOP.js → server-MC4A4WAJ.js} +9 -8
- package/dist/cli/{server-SYC3OVOP.js.map → server-MC4A4WAJ.js.map} +1 -1
- package/dist/cli/{sessions-3XU2GGHX.js → sessions-ZHWJEW4L.js} +7 -6
- package/dist/cli/{sessions-3XU2GGHX.js.map → sessions-ZHWJEW4L.js.map} +1 -1
- package/dist/cli/{setup-CCJZAWTY.js → setup-DK43MT47.js} +6 -5
- package/dist/cli/{setup-CCJZAWTY.js.map → setup-DK43MT47.js.map} +1 -1
- package/dist/cli/{version-5SGI2SEE.js → version-O362UKPM.js} +7 -6
- package/dist/cli/{version-5SGI2SEE.js.map → version-O362UKPM.js.map} +1 -1
- package/dist/index.d.ts +45 -1
- package/dist/index.js +569 -27
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/cli/chunk-63KAV5DX.js +0 -106
- package/dist/cli/chunk-63KAV5DX.js.map +0 -1
- package/dist/cli/chunk-DULSP7JH.js.map +0 -1
- package/dist/cli/chunk-FXGQ5NHE.js.map +0 -1
- package/dist/cli/chunk-G7M3QWEN.js.map +0 -1
- package/dist/cli/chunk-OW7IHE6M.js.map +0 -1
- package/dist/cli/chunk-QGE6AF76.js.map +0 -1
- package/dist/cli/chunk-ZPTSJGX5.js +0 -88
- package/dist/cli/chunk-ZPTSJGX5.js.map +0 -1
- /package/dist/cli/{chat-ZMSAXE77.js.map → chat-TL4HMNEQ.js.map} +0 -0
- /package/dist/cli/{chunk-WVJL7ZO2.js.map → chunk-F3ILWP2L.js.map} +0 -0
- /package/dist/cli/{chunk-WBDE4IRI.js.map → chunk-OERAGRJX.js.map} +0 -0
- /package/dist/cli/{chunk-RZILUXUC.js.map → chunk-RXGEGA7K.js.map} +0 -0
- /package/dist/cli/{chunk-J5VLP23S.js.map → chunk-SW3CCXEV.js.map} +0 -0
- /package/dist/cli/{chunk-W4LDFAZ6.js.map → chunk-SX6L4HZZ.js.map} +0 -0
- /package/dist/cli/{doctor-V5HLCMSQ.js.map → doctor-YASM64X6.js.map} +0 -0
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/cli/ui/theme/tokens.ts
|
|
4
|
+
function card(fg, tone) {
|
|
5
|
+
return {
|
|
6
|
+
user: { color: fg.meta, glyph: "\u25C7" },
|
|
7
|
+
reasoning: { color: tone.accent, glyph: "\u25C6" },
|
|
8
|
+
streaming: { color: tone.brand, glyph: "\u25C8" },
|
|
9
|
+
task: { color: tone.warn, glyph: "\u25B6" },
|
|
10
|
+
tool: { color: tone.info, glyph: "\u25A3" },
|
|
11
|
+
plan: { color: tone.accent, glyph: "\u229E" },
|
|
12
|
+
diff: { color: tone.ok, glyph: "\xB1" },
|
|
13
|
+
error: { color: tone.err, glyph: "\u2716" },
|
|
14
|
+
warn: { color: tone.warn, glyph: "\u26A0" },
|
|
15
|
+
usage: { color: fg.meta, glyph: "\u03A3" },
|
|
16
|
+
subagent: { color: tone.violet, glyph: "\u232C" },
|
|
17
|
+
approval: { color: tone.warn, glyph: "?" },
|
|
18
|
+
search: { color: tone.info, glyph: "\u2299" },
|
|
19
|
+
memory: { color: fg.meta, glyph: "\u2311" },
|
|
20
|
+
ctx: { color: tone.brand, glyph: "\u25D4" },
|
|
21
|
+
doctor: { color: fg.meta, glyph: "\u2695" },
|
|
22
|
+
branch: { color: tone.violet, glyph: "\u2387" }
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
function defineTheme(base) {
|
|
26
|
+
return { ...base, card: card(base.fg, base.tone) };
|
|
27
|
+
}
|
|
28
|
+
var githubDark = defineTheme({
|
|
29
|
+
fg: {
|
|
30
|
+
strong: "#e6edf3",
|
|
31
|
+
body: "#c9d1d9",
|
|
32
|
+
sub: "#8b949e",
|
|
33
|
+
meta: "#6e7681",
|
|
34
|
+
faint: "#484f58"
|
|
35
|
+
},
|
|
36
|
+
tone: {
|
|
37
|
+
brand: "#79c0ff",
|
|
38
|
+
accent: "#d2a8ff",
|
|
39
|
+
violet: "#b395f5",
|
|
40
|
+
ok: "#7ee787",
|
|
41
|
+
warn: "#f0b07d",
|
|
42
|
+
err: "#ff8b81",
|
|
43
|
+
info: "#79c0ff"
|
|
44
|
+
},
|
|
45
|
+
toneActive: {
|
|
46
|
+
brand: "#a5d6ff",
|
|
47
|
+
accent: "#e2c5ff",
|
|
48
|
+
violet: "#c8aaff",
|
|
49
|
+
ok: "#a8f5ad",
|
|
50
|
+
warn: "#ffc99e",
|
|
51
|
+
err: "#ffaba3",
|
|
52
|
+
info: "#a5d6ff"
|
|
53
|
+
},
|
|
54
|
+
surface: {
|
|
55
|
+
bg: "#0a0c10",
|
|
56
|
+
bgInput: "#0d1015",
|
|
57
|
+
bgCode: "#06080c",
|
|
58
|
+
bgElev: "#11141a"
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
var dark = defineTheme({
|
|
62
|
+
fg: {
|
|
63
|
+
strong: "#f4f7fb",
|
|
64
|
+
body: "#d8dee9",
|
|
65
|
+
sub: "#a7b1c2",
|
|
66
|
+
meta: "#778294",
|
|
67
|
+
faint: "#4d5666"
|
|
68
|
+
},
|
|
69
|
+
tone: {
|
|
70
|
+
brand: "#7dd3fc",
|
|
71
|
+
accent: "#c084fc",
|
|
72
|
+
violet: "#a78bfa",
|
|
73
|
+
ok: "#86efac",
|
|
74
|
+
warn: "#fbbf24",
|
|
75
|
+
err: "#f87171",
|
|
76
|
+
info: "#60a5fa"
|
|
77
|
+
},
|
|
78
|
+
toneActive: {
|
|
79
|
+
brand: "#bae6fd",
|
|
80
|
+
accent: "#e9d5ff",
|
|
81
|
+
violet: "#ddd6fe",
|
|
82
|
+
ok: "#bbf7d0",
|
|
83
|
+
warn: "#fde68a",
|
|
84
|
+
err: "#fecaca",
|
|
85
|
+
info: "#bfdbfe"
|
|
86
|
+
},
|
|
87
|
+
surface: {
|
|
88
|
+
bg: "#0b1020",
|
|
89
|
+
bgInput: "#111827",
|
|
90
|
+
bgCode: "#080c16",
|
|
91
|
+
bgElev: "#151d2f"
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
var light = defineTheme({
|
|
95
|
+
fg: {
|
|
96
|
+
strong: "#111827",
|
|
97
|
+
body: "#1f2937",
|
|
98
|
+
sub: "#4b5563",
|
|
99
|
+
meta: "#6b7280",
|
|
100
|
+
faint: "#9ca3af"
|
|
101
|
+
},
|
|
102
|
+
tone: {
|
|
103
|
+
brand: "#2563eb",
|
|
104
|
+
accent: "#7c3aed",
|
|
105
|
+
violet: "#6d28d9",
|
|
106
|
+
ok: "#15803d",
|
|
107
|
+
warn: "#b45309",
|
|
108
|
+
err: "#dc2626",
|
|
109
|
+
info: "#0369a1"
|
|
110
|
+
},
|
|
111
|
+
toneActive: {
|
|
112
|
+
brand: "#1d4ed8",
|
|
113
|
+
accent: "#6d28d9",
|
|
114
|
+
violet: "#5b21b6",
|
|
115
|
+
ok: "#166534",
|
|
116
|
+
warn: "#92400e",
|
|
117
|
+
err: "#b91c1c",
|
|
118
|
+
info: "#075985"
|
|
119
|
+
},
|
|
120
|
+
surface: {
|
|
121
|
+
bg: "#ffffff",
|
|
122
|
+
bgInput: "#f8fafc",
|
|
123
|
+
bgCode: "#f3f4f6",
|
|
124
|
+
bgElev: "#eef2f7"
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
var tokyoNight = defineTheme({
|
|
128
|
+
fg: {
|
|
129
|
+
strong: "#c0caf5",
|
|
130
|
+
body: "#a9b1d6",
|
|
131
|
+
sub: "#9aa5ce",
|
|
132
|
+
meta: "#565f89",
|
|
133
|
+
faint: "#414868"
|
|
134
|
+
},
|
|
135
|
+
tone: {
|
|
136
|
+
brand: "#7aa2f7",
|
|
137
|
+
accent: "#bb9af7",
|
|
138
|
+
violet: "#9d7cd8",
|
|
139
|
+
ok: "#9ece6a",
|
|
140
|
+
warn: "#e0af68",
|
|
141
|
+
err: "#f7768e",
|
|
142
|
+
info: "#2ac3de"
|
|
143
|
+
},
|
|
144
|
+
toneActive: {
|
|
145
|
+
brand: "#a9c7ff",
|
|
146
|
+
accent: "#d7b9ff",
|
|
147
|
+
violet: "#c6a0f6",
|
|
148
|
+
ok: "#b9f27c",
|
|
149
|
+
warn: "#ffd089",
|
|
150
|
+
err: "#ff9cac",
|
|
151
|
+
info: "#7dcfff"
|
|
152
|
+
},
|
|
153
|
+
surface: {
|
|
154
|
+
bg: "#1a1b26",
|
|
155
|
+
bgInput: "#1f2335",
|
|
156
|
+
bgCode: "#16161e",
|
|
157
|
+
bgElev: "#24283b"
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
var githubLight = defineTheme({
|
|
161
|
+
fg: {
|
|
162
|
+
strong: "#1f2328",
|
|
163
|
+
body: "#24292f",
|
|
164
|
+
sub: "#57606a",
|
|
165
|
+
meta: "#6e7781",
|
|
166
|
+
faint: "#8c959f"
|
|
167
|
+
},
|
|
168
|
+
tone: {
|
|
169
|
+
brand: "#0969da",
|
|
170
|
+
accent: "#8250df",
|
|
171
|
+
violet: "#6639ba",
|
|
172
|
+
ok: "#1a7f37",
|
|
173
|
+
warn: "#9a6700",
|
|
174
|
+
err: "#cf222e",
|
|
175
|
+
info: "#0969da"
|
|
176
|
+
},
|
|
177
|
+
toneActive: {
|
|
178
|
+
brand: "#0550ae",
|
|
179
|
+
accent: "#6639ba",
|
|
180
|
+
violet: "#512a97",
|
|
181
|
+
ok: "#116329",
|
|
182
|
+
warn: "#7d4e00",
|
|
183
|
+
err: "#a40e26",
|
|
184
|
+
info: "#0550ae"
|
|
185
|
+
},
|
|
186
|
+
surface: {
|
|
187
|
+
bg: "#ffffff",
|
|
188
|
+
bgInput: "#f6f8fa",
|
|
189
|
+
bgCode: "#f6f8fa",
|
|
190
|
+
bgElev: "#eaeef2"
|
|
191
|
+
}
|
|
192
|
+
});
|
|
193
|
+
var highContrast = defineTheme({
|
|
194
|
+
fg: {
|
|
195
|
+
strong: "#ffffff",
|
|
196
|
+
body: "#f5f5f5",
|
|
197
|
+
sub: "#d4d4d4",
|
|
198
|
+
meta: "#bdbdbd",
|
|
199
|
+
faint: "#8a8a8a"
|
|
200
|
+
},
|
|
201
|
+
tone: {
|
|
202
|
+
brand: "#00e5ff",
|
|
203
|
+
accent: "#ff4dff",
|
|
204
|
+
violet: "#b388ff",
|
|
205
|
+
ok: "#00ff66",
|
|
206
|
+
warn: "#ffdd00",
|
|
207
|
+
err: "#ff4d4d",
|
|
208
|
+
info: "#4da3ff"
|
|
209
|
+
},
|
|
210
|
+
toneActive: {
|
|
211
|
+
brand: "#80f2ff",
|
|
212
|
+
accent: "#ff99ff",
|
|
213
|
+
violet: "#d0b3ff",
|
|
214
|
+
ok: "#80ffb3",
|
|
215
|
+
warn: "#ffee80",
|
|
216
|
+
err: "#ff9999",
|
|
217
|
+
info: "#99c9ff"
|
|
218
|
+
},
|
|
219
|
+
surface: {
|
|
220
|
+
bg: "#000000",
|
|
221
|
+
bgInput: "#0a0a0a",
|
|
222
|
+
bgCode: "#050505",
|
|
223
|
+
bgElev: "#141414"
|
|
224
|
+
}
|
|
225
|
+
});
|
|
226
|
+
var THEMES = {
|
|
227
|
+
default: githubDark,
|
|
228
|
+
dark,
|
|
229
|
+
light,
|
|
230
|
+
"tokyo-night": tokyoNight,
|
|
231
|
+
"github-dark": githubDark,
|
|
232
|
+
"github-light": githubLight,
|
|
233
|
+
"high-contrast": highContrast
|
|
234
|
+
};
|
|
235
|
+
var DEFAULT_THEME_NAME = "default";
|
|
236
|
+
function isThemeName(value) {
|
|
237
|
+
return Object.prototype.hasOwnProperty.call(THEMES, value);
|
|
238
|
+
}
|
|
239
|
+
function resolveThemeName(value) {
|
|
240
|
+
if (!value || value === "auto") return DEFAULT_THEME_NAME;
|
|
241
|
+
return isThemeName(value) ? value : DEFAULT_THEME_NAME;
|
|
242
|
+
}
|
|
243
|
+
function listThemeNames() {
|
|
244
|
+
return Object.keys(THEMES);
|
|
245
|
+
}
|
|
246
|
+
var DEFAULT_THEME = THEMES[DEFAULT_THEME_NAME];
|
|
247
|
+
var activeTheme = DEFAULT_THEME;
|
|
248
|
+
var activeThemeVersion = 0;
|
|
249
|
+
function setActiveTheme(theme) {
|
|
250
|
+
const previousTheme = activeTheme;
|
|
251
|
+
activeTheme = theme;
|
|
252
|
+
activeThemeVersion += 1;
|
|
253
|
+
const version = activeThemeVersion;
|
|
254
|
+
return () => {
|
|
255
|
+
if (activeThemeVersion !== version || activeTheme !== theme) return;
|
|
256
|
+
activeTheme = previousTheme;
|
|
257
|
+
activeThemeVersion += 1;
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
function proxyTokens(select) {
|
|
261
|
+
const target = select(DEFAULT_THEME);
|
|
262
|
+
return new Proxy(target, {
|
|
263
|
+
get(_target, prop) {
|
|
264
|
+
return select(activeTheme)[prop];
|
|
265
|
+
},
|
|
266
|
+
getOwnPropertyDescriptor(_target, prop) {
|
|
267
|
+
return Reflect.getOwnPropertyDescriptor(select(activeTheme), prop);
|
|
268
|
+
},
|
|
269
|
+
has(_target, prop) {
|
|
270
|
+
return prop in select(activeTheme);
|
|
271
|
+
},
|
|
272
|
+
ownKeys() {
|
|
273
|
+
return Reflect.ownKeys(select(activeTheme));
|
|
274
|
+
}
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
var FG = proxyTokens((theme) => theme.fg);
|
|
278
|
+
var TONE = proxyTokens((theme) => theme.tone);
|
|
279
|
+
var TONE_ACTIVE = proxyTokens((theme) => theme.toneActive);
|
|
280
|
+
var SURFACE = proxyTokens((theme) => theme.surface);
|
|
281
|
+
var CARD = proxyTokens((theme) => theme.card);
|
|
282
|
+
var USD_TO_CNY = 7.2;
|
|
283
|
+
var SYMBOL = { USD: "$", CNY: "\xA5" };
|
|
284
|
+
function formatBalance(amount, currency, opts) {
|
|
285
|
+
const cur = currency ?? "CNY";
|
|
286
|
+
const sym = SYMBOL[cur];
|
|
287
|
+
const digits = opts?.fractionDigits ?? 2;
|
|
288
|
+
const body = sym ? `${sym}${amount.toFixed(digits)}` : `${cur} ${amount.toFixed(digits)}`;
|
|
289
|
+
return opts?.label ? `w ${body}` : body;
|
|
290
|
+
}
|
|
291
|
+
function formatCost(costUsd, currency, fractionDigits = 4) {
|
|
292
|
+
const cur = currency ?? "CNY";
|
|
293
|
+
const amount = cur === "CNY" ? costUsd * USD_TO_CNY : costUsd;
|
|
294
|
+
return formatBalance(amount, cur, { fractionDigits });
|
|
295
|
+
}
|
|
296
|
+
function balanceColor(amount, currency) {
|
|
297
|
+
const cny = (currency ?? "CNY") === "USD" ? amount * USD_TO_CNY : amount;
|
|
298
|
+
if (cny < 5) return TONE.err;
|
|
299
|
+
if (cny < 20) return TONE.warn;
|
|
300
|
+
return TONE.brand;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
export {
|
|
304
|
+
THEMES,
|
|
305
|
+
DEFAULT_THEME_NAME,
|
|
306
|
+
isThemeName,
|
|
307
|
+
resolveThemeName,
|
|
308
|
+
listThemeNames,
|
|
309
|
+
setActiveTheme,
|
|
310
|
+
FG,
|
|
311
|
+
TONE,
|
|
312
|
+
TONE_ACTIVE,
|
|
313
|
+
SURFACE,
|
|
314
|
+
CARD,
|
|
315
|
+
formatBalance,
|
|
316
|
+
formatCost,
|
|
317
|
+
balanceColor
|
|
318
|
+
};
|
|
319
|
+
//# sourceMappingURL=chunk-WUI3P4RA.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/cli/ui/theme/tokens.ts"],"sourcesContent":["export type ThemeName =\n | \"default\"\n | \"dark\"\n | \"light\"\n | \"tokyo-night\"\n | \"github-dark\"\n | \"github-light\"\n | \"high-contrast\";\n\nexport interface ThemeTokens {\n fg: {\n strong: string;\n body: string;\n sub: string;\n meta: string;\n faint: string;\n };\n tone: {\n brand: string;\n accent: string;\n violet: string;\n ok: string;\n warn: string;\n err: string;\n info: string;\n };\n toneActive: ThemeTokens[\"tone\"];\n surface: {\n bg: string;\n bgInput: string;\n bgCode: string;\n bgElev: string;\n };\n card: Record<\n | \"user\"\n | \"reasoning\"\n | \"streaming\"\n | \"task\"\n | \"tool\"\n | \"plan\"\n | \"diff\"\n | \"error\"\n | \"warn\"\n | \"usage\"\n | \"subagent\"\n | \"approval\"\n | \"search\"\n | \"memory\"\n | \"ctx\"\n | \"doctor\"\n | \"branch\",\n { color: string; glyph: string }\n >;\n}\n\ntype ThemeBase = Omit<ThemeTokens, \"card\">;\n\nfunction card(fg: ThemeTokens[\"fg\"], tone: ThemeTokens[\"tone\"]): ThemeTokens[\"card\"] {\n return {\n user: { color: fg.meta, glyph: \"◇\" },\n reasoning: { color: tone.accent, glyph: \"◆\" },\n streaming: { color: tone.brand, glyph: \"◈\" },\n task: { color: tone.warn, glyph: \"▶\" },\n tool: { color: tone.info, glyph: \"▣\" },\n plan: { color: tone.accent, glyph: \"⊞\" },\n diff: { color: tone.ok, glyph: \"±\" },\n error: { color: tone.err, glyph: \"✖\" },\n warn: { color: tone.warn, glyph: \"⚠\" },\n usage: { color: fg.meta, glyph: \"Σ\" },\n subagent: { color: tone.violet, glyph: \"⌬\" },\n approval: { color: tone.warn, glyph: \"?\" },\n search: { color: tone.info, glyph: \"⊙\" },\n memory: { color: fg.meta, glyph: \"⌑\" },\n ctx: { color: tone.brand, glyph: \"◔\" },\n doctor: { color: fg.meta, glyph: \"⚕\" },\n branch: { color: tone.violet, glyph: \"⎇\" },\n };\n}\n\nfunction defineTheme(base: ThemeBase): ThemeTokens {\n return { ...base, card: card(base.fg, base.tone) };\n}\n\nconst githubDark = defineTheme({\n fg: {\n strong: \"#e6edf3\",\n body: \"#c9d1d9\",\n sub: \"#8b949e\",\n meta: \"#6e7681\",\n faint: \"#484f58\",\n },\n tone: {\n brand: \"#79c0ff\",\n accent: \"#d2a8ff\",\n violet: \"#b395f5\",\n ok: \"#7ee787\",\n warn: \"#f0b07d\",\n err: \"#ff8b81\",\n info: \"#79c0ff\",\n },\n toneActive: {\n brand: \"#a5d6ff\",\n accent: \"#e2c5ff\",\n violet: \"#c8aaff\",\n ok: \"#a8f5ad\",\n warn: \"#ffc99e\",\n err: \"#ffaba3\",\n info: \"#a5d6ff\",\n },\n surface: {\n bg: \"#0a0c10\",\n bgInput: \"#0d1015\",\n bgCode: \"#06080c\",\n bgElev: \"#11141a\",\n },\n});\n\nconst dark = defineTheme({\n fg: {\n strong: \"#f4f7fb\",\n body: \"#d8dee9\",\n sub: \"#a7b1c2\",\n meta: \"#778294\",\n faint: \"#4d5666\",\n },\n tone: {\n brand: \"#7dd3fc\",\n accent: \"#c084fc\",\n violet: \"#a78bfa\",\n ok: \"#86efac\",\n warn: \"#fbbf24\",\n err: \"#f87171\",\n info: \"#60a5fa\",\n },\n toneActive: {\n brand: \"#bae6fd\",\n accent: \"#e9d5ff\",\n violet: \"#ddd6fe\",\n ok: \"#bbf7d0\",\n warn: \"#fde68a\",\n err: \"#fecaca\",\n info: \"#bfdbfe\",\n },\n surface: {\n bg: \"#0b1020\",\n bgInput: \"#111827\",\n bgCode: \"#080c16\",\n bgElev: \"#151d2f\",\n },\n});\n\nconst light = defineTheme({\n fg: {\n strong: \"#111827\",\n body: \"#1f2937\",\n sub: \"#4b5563\",\n meta: \"#6b7280\",\n faint: \"#9ca3af\",\n },\n tone: {\n brand: \"#2563eb\",\n accent: \"#7c3aed\",\n violet: \"#6d28d9\",\n ok: \"#15803d\",\n warn: \"#b45309\",\n err: \"#dc2626\",\n info: \"#0369a1\",\n },\n toneActive: {\n brand: \"#1d4ed8\",\n accent: \"#6d28d9\",\n violet: \"#5b21b6\",\n ok: \"#166534\",\n warn: \"#92400e\",\n err: \"#b91c1c\",\n info: \"#075985\",\n },\n surface: {\n bg: \"#ffffff\",\n bgInput: \"#f8fafc\",\n bgCode: \"#f3f4f6\",\n bgElev: \"#eef2f7\",\n },\n});\n\nconst tokyoNight = defineTheme({\n fg: {\n strong: \"#c0caf5\",\n body: \"#a9b1d6\",\n sub: \"#9aa5ce\",\n meta: \"#565f89\",\n faint: \"#414868\",\n },\n tone: {\n brand: \"#7aa2f7\",\n accent: \"#bb9af7\",\n violet: \"#9d7cd8\",\n ok: \"#9ece6a\",\n warn: \"#e0af68\",\n err: \"#f7768e\",\n info: \"#2ac3de\",\n },\n toneActive: {\n brand: \"#a9c7ff\",\n accent: \"#d7b9ff\",\n violet: \"#c6a0f6\",\n ok: \"#b9f27c\",\n warn: \"#ffd089\",\n err: \"#ff9cac\",\n info: \"#7dcfff\",\n },\n surface: {\n bg: \"#1a1b26\",\n bgInput: \"#1f2335\",\n bgCode: \"#16161e\",\n bgElev: \"#24283b\",\n },\n});\n\nconst githubLight = defineTheme({\n fg: {\n strong: \"#1f2328\",\n body: \"#24292f\",\n sub: \"#57606a\",\n meta: \"#6e7781\",\n faint: \"#8c959f\",\n },\n tone: {\n brand: \"#0969da\",\n accent: \"#8250df\",\n violet: \"#6639ba\",\n ok: \"#1a7f37\",\n warn: \"#9a6700\",\n err: \"#cf222e\",\n info: \"#0969da\",\n },\n toneActive: {\n brand: \"#0550ae\",\n accent: \"#6639ba\",\n violet: \"#512a97\",\n ok: \"#116329\",\n warn: \"#7d4e00\",\n err: \"#a40e26\",\n info: \"#0550ae\",\n },\n surface: {\n bg: \"#ffffff\",\n bgInput: \"#f6f8fa\",\n bgCode: \"#f6f8fa\",\n bgElev: \"#eaeef2\",\n },\n});\n\nconst highContrast = defineTheme({\n fg: {\n strong: \"#ffffff\",\n body: \"#f5f5f5\",\n sub: \"#d4d4d4\",\n meta: \"#bdbdbd\",\n faint: \"#8a8a8a\",\n },\n tone: {\n brand: \"#00e5ff\",\n accent: \"#ff4dff\",\n violet: \"#b388ff\",\n ok: \"#00ff66\",\n warn: \"#ffdd00\",\n err: \"#ff4d4d\",\n info: \"#4da3ff\",\n },\n toneActive: {\n brand: \"#80f2ff\",\n accent: \"#ff99ff\",\n violet: \"#d0b3ff\",\n ok: \"#80ffb3\",\n warn: \"#ffee80\",\n err: \"#ff9999\",\n info: \"#99c9ff\",\n },\n surface: {\n bg: \"#000000\",\n bgInput: \"#0a0a0a\",\n bgCode: \"#050505\",\n bgElev: \"#141414\",\n },\n});\n\nexport const THEMES = {\n default: githubDark,\n dark,\n light,\n \"tokyo-night\": tokyoNight,\n \"github-dark\": githubDark,\n \"github-light\": githubLight,\n \"high-contrast\": highContrast,\n} as const satisfies Record<ThemeName, ThemeTokens>;\n\nexport const DEFAULT_THEME_NAME: ThemeName = \"default\";\n\nexport function isThemeName(value: string): value is ThemeName {\n return Object.prototype.hasOwnProperty.call(THEMES, value);\n}\n\nexport function resolveThemeName(value?: string | null): ThemeName {\n if (!value || value === \"auto\") return DEFAULT_THEME_NAME;\n return isThemeName(value) ? value : DEFAULT_THEME_NAME;\n}\n\nexport function listThemeNames(): ThemeName[] {\n return Object.keys(THEMES) as ThemeName[];\n}\n\nexport function themeTokens(name?: string | null): ThemeTokens {\n return THEMES[resolveThemeName(name)];\n}\n\nexport const DEFAULT_THEME = THEMES[DEFAULT_THEME_NAME];\n\nlet activeTheme: ThemeTokens = DEFAULT_THEME;\nlet activeThemeVersion = 0;\n\nexport function setActiveTheme(theme: ThemeTokens): () => void {\n const previousTheme = activeTheme;\n activeTheme = theme;\n activeThemeVersion += 1;\n const version = activeThemeVersion;\n return () => {\n if (activeThemeVersion !== version || activeTheme !== theme) return;\n activeTheme = previousTheme;\n activeThemeVersion += 1;\n };\n}\n\nfunction proxyTokens<T extends object>(select: (theme: ThemeTokens) => T): T {\n const target = select(DEFAULT_THEME);\n return new Proxy(target, {\n get(_target, prop: string | symbol) {\n return select(activeTheme)[prop as keyof T];\n },\n getOwnPropertyDescriptor(_target, prop: string | symbol) {\n return Reflect.getOwnPropertyDescriptor(select(activeTheme), prop);\n },\n has(_target, prop: string | symbol) {\n return prop in select(activeTheme);\n },\n ownKeys() {\n return Reflect.ownKeys(select(activeTheme));\n },\n });\n}\n\nexport const FG = proxyTokens((theme) => theme.fg);\nexport const TONE = proxyTokens((theme) => theme.tone);\nexport const TONE_ACTIVE = proxyTokens((theme) => theme.toneActive);\nexport const SURFACE = proxyTokens((theme) => theme.surface);\nexport const CARD = proxyTokens((theme) => theme.card);\n\nexport type CardTone = keyof ThemeTokens[\"card\"];\n\n/** DeepSeek prices in CNY; our internal table is USD divided by 7.2. Multiply back for display. */\nexport const USD_TO_CNY = 7.2;\n\nconst SYMBOL: Record<string, string> = { USD: \"$\", CNY: \"¥\" };\n\n/** Format an amount already in `currency`. Undefined currency → CNY (matches pre-fix behavior). */\nexport function formatBalance(\n amount: number,\n currency?: string,\n opts?: { fractionDigits?: number; label?: boolean },\n): string {\n const cur = currency ?? \"CNY\";\n const sym = SYMBOL[cur];\n const digits = opts?.fractionDigits ?? 2;\n const body = sym ? `${sym}${amount.toFixed(digits)}` : `${cur} ${amount.toFixed(digits)}`;\n return opts?.label ? `w ${body}` : body;\n}\n\n/** Format an internal USD cost in the wallet's display currency. Undefined currency → CNY. */\nexport function formatCost(costUsd: number, currency?: string, fractionDigits = 4): string {\n const cur = currency ?? \"CNY\";\n const amount = cur === \"CNY\" ? costUsd * USD_TO_CNY : costUsd;\n return formatBalance(amount, cur, { fractionDigits });\n}\n\n/** Threshold color for a wallet balance. USD is converted to CNY before the threshold check. */\nexport function balanceColor(amount: number, currency?: string): string {\n const cny = (currency ?? \"CNY\") === \"USD\" ? amount * USD_TO_CNY : amount;\n if (cny < 5) return TONE.err;\n if (cny < 20) return TONE.warn;\n return TONE.brand;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
bootstrapSemanticSearchInCodeMode
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-SW3CCXEV.js";
|
|
5
5
|
import {
|
|
6
6
|
chatCommand
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-5SAMVHA3.js";
|
|
8
8
|
import "./chunk-BQNUJJN7.js";
|
|
9
9
|
import "./chunk-RFX7TYVV.js";
|
|
10
|
-
import "./chunk-
|
|
10
|
+
import "./chunk-MRLXEMZ7.js";
|
|
11
11
|
import {
|
|
12
12
|
markPhase
|
|
13
13
|
} from "./chunk-CPOV2O73.js";
|
|
@@ -18,41 +18,42 @@ import {
|
|
|
18
18
|
registerMemoryTools,
|
|
19
19
|
registerPlanTool,
|
|
20
20
|
registerTodoTool
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-LNTORE5K.js";
|
|
22
22
|
import "./chunk-I6YIAK6C.js";
|
|
23
23
|
import "./chunk-XJLZ4HKU.js";
|
|
24
24
|
import "./chunk-XHQIK7B6.js";
|
|
25
25
|
import "./chunk-6TMHAK5D.js";
|
|
26
|
-
import "./chunk-
|
|
27
|
-
import "./chunk-
|
|
26
|
+
import "./chunk-KZHMKOJH.js";
|
|
27
|
+
import "./chunk-2EBODRRO.js";
|
|
28
28
|
import "./chunk-MHDNZXJJ.js";
|
|
29
|
-
import "./chunk-
|
|
29
|
+
import "./chunk-F3ILWP2L.js";
|
|
30
30
|
import "./chunk-DAEAAVDF.js";
|
|
31
31
|
import "./chunk-KMWKGPFZ.js";
|
|
32
32
|
import "./chunk-3Q3C4W66.js";
|
|
33
33
|
import "./chunk-4DCHFFEY.js";
|
|
34
|
-
import "./chunk-
|
|
34
|
+
import "./chunk-SA4UGZPG.js";
|
|
35
35
|
import "./chunk-G3XNWSFN.js";
|
|
36
36
|
import "./chunk-SOZE7V7V.js";
|
|
37
37
|
import {
|
|
38
38
|
JobRegistry,
|
|
39
39
|
registerShellTools
|
|
40
|
-
} from "./chunk-
|
|
40
|
+
} from "./chunk-SX6L4HZZ.js";
|
|
41
41
|
import "./chunk-U3V2ZQ5J.js";
|
|
42
42
|
import "./chunk-FM57FNPJ.js";
|
|
43
|
-
import "./chunk-
|
|
44
|
-
import "./chunk-
|
|
43
|
+
import "./chunk-RXGEGA7K.js";
|
|
44
|
+
import "./chunk-OERAGRJX.js";
|
|
45
45
|
import "./chunk-2AWTGJ2C.js";
|
|
46
46
|
import "./chunk-5X7LZJDE.js";
|
|
47
47
|
import {
|
|
48
48
|
sanitizeName
|
|
49
49
|
} from "./chunk-DFP4YSVM.js";
|
|
50
|
-
import "./chunk-
|
|
50
|
+
import "./chunk-Q36KBLSU.js";
|
|
51
51
|
import {
|
|
52
52
|
loadEditMode,
|
|
53
53
|
loadProjectShellAllowed,
|
|
54
54
|
readConfig
|
|
55
|
-
} from "./chunk-
|
|
55
|
+
} from "./chunk-5JXXEPDM.js";
|
|
56
|
+
import "./chunk-WUI3P4RA.js";
|
|
56
57
|
import "./chunk-ZTLZO42A.js";
|
|
57
58
|
import "./chunk-ORM6PK57.js";
|
|
58
59
|
|
|
@@ -149,4 +150,4 @@ async function codeCommand(opts = {}) {
|
|
|
149
150
|
export {
|
|
150
151
|
codeCommand
|
|
151
152
|
};
|
|
152
|
-
//# sourceMappingURL=code-
|
|
153
|
+
//# sourceMappingURL=code-V6F4BKMG.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/cli/commands/code.tsx"],"sourcesContent":["/**\n * `reasonix code [dir]` — opinionated wrapper around `reasonix chat` for\n * code-editing workflows.\n *\n * What it does differently from plain chat:\n * - Registers native filesystem tools rooted at the given directory\n * (CWD by default). No subprocess, no `npx install` step, R1-\n * friendly schemas. Replaced the old `@modelcontextprotocol/server-filesystem`\n * subprocess in 0.4.9 because its `edit_file` argv shape was the\n * biggest driver of R1 DSML hallucinations.\n * - Uses a coding-focused system prompt (src/code/prompt.ts) that\n * teaches the model to propose edits as SEARCH/REPLACE blocks.\n * - Defaults to the `smart` preset (reasoner + harvest) because\n * coding tasks pay back R1 thinking.\n * - Scopes its session to the directory so projects don't share\n * conversation history.\n * - Hooks `codeMode` into the TUI so assistant replies get parsed\n * for SEARCH/REPLACE blocks and applied on disk after each turn.\n */\n\nimport { readFileSync } from \"node:fs\";\nimport { basename, resolve } from \"node:path\";\nimport { loadEditMode, loadProjectShellAllowed, readConfig } from \"../../config.js\";\nimport { bootstrapSemanticSearchInCodeMode } from \"../../index/semantic/tool.js\";\nimport { sanitizeName } from \"../../memory/session.js\";\nimport { ToolRegistry } from \"../../tools.js\";\nimport { registerChoiceTool } from \"../../tools/choice.js\";\nimport { registerFilesystemTools } from \"../../tools/filesystem.js\";\nimport { JobRegistry } from \"../../tools/jobs.js\";\nimport { registerMemoryTools } from \"../../tools/memory.js\";\nimport { registerPlanTool } from \"../../tools/plan.js\";\nimport { registerShellTools } from \"../../tools/shell.js\";\nimport { registerTodoTool } from \"../../tools/todo.js\";\nimport { markPhase } from \"../startup-profile.js\";\nimport { chatCommand } from \"./chat.js\";\n\nexport interface CodeOptions {\n /** Directory to root the filesystem tools at. Defaults to process.cwd(). */\n dir?: string;\n /** Override the default `smart` model. */\n model?: string;\n /** Disable session persistence. */\n noSession?: boolean;\n /** Transcript file for replay/diff. */\n transcript?: string;\n /** Skip the session picker — always resume prior messages. */\n forceResume?: boolean;\n /** Skip the session picker — always wipe prior messages and start fresh. */\n forceNew?: boolean;\n /**\n * Soft USD spend cap. Off by default. Same semantics as `chat`:\n * warns at 80%, refuses next turn at 100%. Mid-session adjustable\n * via `/budget <usd>` slash command.\n */\n budgetUsd?: number;\n /** Suppress the auto-launched embedded web dashboard. */\n noDashboard?: boolean;\n /** Inline string appended to the code system prompt after the generated base prompt. */\n systemAppend?: string;\n /** Path to a UTF-8 text file whose contents are appended to the code system prompt. */\n systemAppendFile?: string;\n /** Default true. Pass false (CLI: `--no-alt-screen`) to keep chat output in shell scrollback. */\n altScreen?: boolean;\n}\n\nexport async function codeCommand(opts: CodeOptions = {}): Promise<void> {\n markPhase(\"code_command_enter\");\n const { codeSystemPrompt } = await import(\"../../code/prompt.js\");\n const rootDir = resolve(opts.dir ?? process.cwd());\n // Per-directory session so switching projects doesn't mix histories.\n // `code-<sanitized-basename>` fits the session name rules without\n // truncating most project names.\n const session = opts.noSession ? undefined : `code-${sanitizeName(basename(rootDir))}`;\n\n // Native filesystem tools. No subprocess, ~50-200 ms faster per call\n // than the MCP server was, and `edit_file` takes a flat SEARCH/REPLACE\n // shape instead of the `string=\"false\"` JSON-in-string array that\n // triggered R1's DSML hallucinations all through 0.4.x.\n const tools = new ToolRegistry();\n // Background-process registry shared between the shell tools and the\n // TUI's /jobs + /kill slashes + exit cleanup. One per `reasonix code`\n // run — orphan prevention on SIGINT / process exit kills everything\n // it owns, so dev servers don't outlive the Reasonix process.\n const jobs = new JobRegistry();\n // Bundled re-registration so `/cwd <path>` can swap every rootDir-\n // dependent tool atomically. ToolRegistry.register is keyed by name\n // and overwrites in-place, so re-calling these against the existing\n // registry replaces the closures cleanly without disturbing tool\n // specs (names/descriptions/params don't reference rootDir, so the\n // prefix cache survives).\n const registerRootedTools = (root: string): void => {\n registerFilesystemTools(tools, { rootDir: root });\n registerShellTools(tools, {\n rootDir: root,\n // Per-project \"always allow\" list persisted from prior ShellConfirm\n // choices; merged on top of the built-in allowlist in shell.ts.\n // GETTER form — re-read every dispatch so a prefix the user adds\n // via ShellConfirm mid-session takes effect on the next shell call\n // instead of waiting for `/new` or a relaunch.\n extraAllowed: () => loadProjectShellAllowed(root),\n // `yolo` edit-mode disables shell confirmations entirely. Re-read\n // from config on each dispatch so /mode yolo (or Shift+Tab cycling\n // through to it) flips the gate live without forcing a relaunch.\n allowAll: () => loadEditMode() === \"yolo\",\n jobs,\n });\n // `remember` / `forget` / `recall_memory` — cross-session user memory.\n // Project scope hashes off rootDir so switching projects gets a fresh\n // per-project memory store; the global scope is shared across runs.\n registerMemoryTools(tools, { projectRoot: root });\n };\n // Async tail to `registerRootedTools`. Kept separate because the FS /\n // shell / memory re-registration above is sync and must happen before\n // the next tool dispatch, while semantic-index probing reads disk and\n // can race ahead in the background. On `/cwd`, App.tsx fires this\n // after the sync swap and surfaces the result via postInfo.\n const reBootstrapSemantic = async (root: string): Promise<{ enabled: boolean }> => {\n const result = await bootstrapSemanticSearchInCodeMode(tools, root);\n if (!result.enabled) tools.unregister(\"semantic_search\");\n return result;\n };\n registerRootedTools(rootDir);\n // `submit_plan` is always in the spec list so the prefix cache stays\n // stable across plan-mode toggles (Pillar 1). The tool itself is a\n // no-op outside plan mode and throws `PlanProposedError` when the\n // user has `/plan`-enabled the session.\n registerPlanTool(tools);\n // `ask_choice` — branching primitive. Independent of plan mode: the\n // model uses it to put a 2–4 way choice in front of the user\n // (strategy, style, library pick) without trying to squeeze the\n // menu into a submit_plan body. Keeping it always-registered\n // preserves the prefix cache across plan-mode toggles.\n registerChoiceTool(tools);\n // `todo_write` — lightweight in-session task tracker, no approval gate.\n // Independent of plan mode (readOnly=true so it stays callable in /plan).\n registerTodoTool(tools);\n // `run_skill` is intentionally NOT registered here — App.tsx wires it\n // up with the subagent runner attached, so `runAs: subagent` skills\n // can spawn isolated child loops. Doing it here would mean the App's\n // re-registration would shadow the no-runner version, which works\n // (last write wins) but obscures the wiring.\n\n // Bootstrap semantic_search. Silent: registers the tool when an\n // on-disk index already exists, skips entirely otherwise. Setup\n // happens via the explicit `reasonix index` command — never\n // by surprise on launch.\n markPhase(\"semantic_bootstrap_start\");\n const semantic = await reBootstrapSemantic(rootDir);\n markPhase(\n semantic.enabled ? \"semantic_bootstrap_done_enabled\" : \"semantic_bootstrap_done_skipped\",\n );\n\n process.stderr.write(\n `▸ reasonix code: rooted at ${rootDir}, session \"${session ?? \"(ephemeral)\"}\" · ${tools.size} native tool(s)${\n semantic.enabled ? \" · semantic_search on\" : \"\"\n }\\n`,\n );\n\n // Belt-and-suspenders cleanup: even though spawn(detached:false)\n // should tie child processes to the parent's lifetime, Windows cmd.exe\n // wrappers occasionally leak. We DON'T install SIGINT/SIGTERM\n // handlers here — that overrode Node's default \"exit on Ctrl+C\" with\n // a silent no-op, which made Ctrl+C feel broken in the TUI. App.tsx\n // owns the SIGINT path now (it shows the quit-armed banner and calls\n // exit() on confirmation); this 'exit' hook just guarantees the job\n // registry is drained on the way out, regardless of which exit path\n // fired.\n process.once(\"exit\", () => {\n void jobs.shutdown();\n });\n\n let systemAppendFileContents: string | undefined;\n if (opts.systemAppend !== undefined && opts.systemAppend.trim().length === 0) {\n process.stderr.write(\"--system-append is empty — no prompt text will be appended\\n\");\n }\n if (opts.systemAppendFile) {\n const filePath = resolve(opts.systemAppendFile);\n try {\n systemAppendFileContents = readFileSync(filePath, \"utf8\");\n } catch (err) {\n const e = err as NodeJS.ErrnoException;\n process.stderr.write(\n `Error: cannot read --system-append-file \"${filePath}\": ${e.code ? `[${e.code}] ` : \"\"}${e.message}\\n`,\n );\n process.exit(1);\n }\n }\n\n await chatCommand({\n model: opts.model ?? \"deepseek-v4-flash\",\n budgetUsd: opts.budgetUsd,\n system: codeSystemPrompt(rootDir, {\n hasSemanticSearch: semantic.enabled,\n systemAppend: opts.systemAppend,\n systemAppendFile: systemAppendFileContents,\n }),\n transcript: opts.transcript,\n session,\n seedTools: tools,\n codeMode: {\n rootDir,\n jobs,\n reregisterTools: registerRootedTools,\n reBootstrapSemantic,\n },\n mcp: readConfig().mcp,\n forceResume: opts.forceResume,\n forceNew: opts.forceNew,\n noDashboard: opts.noDashboard,\n altScreen: opts.altScreen,\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoBA,SAAS,oBAAoB;AAC7B,SAAS,UAAU,eAAe;AA4ClC,eAAsB,YAAY,OAAoB,CAAC,GAAkB;AACvE,YAAU,oBAAoB;AAC9B,QAAM,EAAE,iBAAiB,IAAI,MAAM,OAAO,sBAAsB;AAChE,QAAM,UAAU,QAAQ,KAAK,OAAO,QAAQ,IAAI,CAAC;AAIjD,QAAM,UAAU,KAAK,YAAY,SAAY,QAAQ,aAAa,SAAS,OAAO,CAAC,CAAC;AAMpF,QAAM,QAAQ,IAAI,aAAa;AAK/B,QAAM,OAAO,IAAI,YAAY;AAO7B,QAAM,sBAAsB,CAAC,SAAuB;AAClD,4BAAwB,OAAO,EAAE,SAAS,KAAK,CAAC;AAChD,uBAAmB,OAAO;AAAA,MACxB,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAMT,cAAc,MAAM,wBAAwB,IAAI;AAAA;AAAA;AAAA;AAAA,MAIhD,UAAU,MAAM,aAAa,MAAM;AAAA,MACnC;AAAA,IACF,CAAC;AAID,wBAAoB,OAAO,EAAE,aAAa,KAAK,CAAC;AAAA,EAClD;AAMA,QAAM,sBAAsB,OAAO,SAAgD;AACjF,UAAM,SAAS,MAAM,kCAAkC,OAAO,IAAI;AAClE,QAAI,CAAC,OAAO,QAAS,OAAM,WAAW,iBAAiB;AACvD,WAAO;AAAA,EACT;AACA,sBAAoB,OAAO;AAK3B,mBAAiB,KAAK;AAMtB,qBAAmB,KAAK;AAGxB,mBAAiB,KAAK;AAWtB,YAAU,0BAA0B;AACpC,QAAM,WAAW,MAAM,oBAAoB,OAAO;AAClD;AAAA,IACE,SAAS,UAAU,oCAAoC;AAAA,EACzD;AAEA,UAAQ,OAAO;AAAA,IACb,mCAA8B,OAAO,cAAc,WAAW,aAAa,UAAO,MAAM,IAAI,kBAC1F,SAAS,UAAU,6BAA0B,EAC/C;AAAA;AAAA,EACF;AAWA,UAAQ,KAAK,QAAQ,MAAM;AACzB,SAAK,KAAK,SAAS;AAAA,EACrB,CAAC;AAED,MAAI;AACJ,MAAI,KAAK,iBAAiB,UAAa,KAAK,aAAa,KAAK,EAAE,WAAW,GAAG;AAC5E,YAAQ,OAAO,MAAM,mEAA8D;AAAA,EACrF;AACA,MAAI,KAAK,kBAAkB;AACzB,UAAM,WAAW,QAAQ,KAAK,gBAAgB;AAC9C,QAAI;AACF,iCAA2B,aAAa,UAAU,MAAM;AAAA,IAC1D,SAAS,KAAK;AACZ,YAAM,IAAI;AACV,cAAQ,OAAO;AAAA,QACb,4CAA4C,QAAQ,MAAM,EAAE,OAAO,IAAI,EAAE,IAAI,OAAO,EAAE,GAAG,EAAE,OAAO;AAAA;AAAA,MACpG;AACA,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF;AAEA,QAAM,YAAY;AAAA,IAChB,OAAO,KAAK,SAAS;AAAA,IACrB,WAAW,KAAK;AAAA,IAChB,QAAQ,iBAAiB,SAAS;AAAA,MAChC,mBAAmB,SAAS;AAAA,MAC5B,cAAc,KAAK;AAAA,MACnB,kBAAkB;AAAA,IACpB,CAAC;AAAA,IACD,YAAY,KAAK;AAAA,IACjB;AAAA,IACA,WAAW;AAAA,IACX,UAAU;AAAA,MACR;AAAA,MACA;AAAA,MACA,iBAAiB;AAAA,MACjB;AAAA,IACF;AAAA,IACA,KAAK,WAAW,EAAE;AAAA,IAClB,aAAa,KAAK;AAAA,IAClB,UAAU,KAAK;AAAA,IACf,aAAa,KAAK;AAAA,IAClB,WAAW,KAAK;AAAA,EAClB,CAAC;AACH;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/cli/commands/code.tsx"],"sourcesContent":["/**\n * `reasonix code [dir]` — opinionated wrapper around `reasonix chat` for\n * code-editing workflows.\n *\n * What it does differently from plain chat:\n * - Registers native filesystem tools rooted at the given directory\n * (CWD by default). No subprocess, no `npx install` step, R1-\n * friendly schemas. Replaced the old `@modelcontextprotocol/server-filesystem`\n * subprocess in 0.4.9 because its `edit_file` argv shape was the\n * biggest driver of R1 DSML hallucinations.\n * - Uses a coding-focused system prompt (src/code/prompt.ts) that\n * teaches the model to propose edits as SEARCH/REPLACE blocks.\n * - Defaults to the `smart` preset (reasoner + harvest) because\n * coding tasks pay back R1 thinking.\n * - Scopes its session to the directory so projects don't share\n * conversation history.\n * - Hooks `codeMode` into the TUI so assistant replies get parsed\n * for SEARCH/REPLACE blocks and applied on disk after each turn.\n */\n\nimport { readFileSync } from \"node:fs\";\nimport { basename, resolve } from \"node:path\";\nimport { loadEditMode, loadProjectShellAllowed, readConfig } from \"../../config.js\";\nimport { bootstrapSemanticSearchInCodeMode } from \"../../index/semantic/tool.js\";\nimport { sanitizeName } from \"../../memory/session.js\";\nimport { ToolRegistry } from \"../../tools.js\";\nimport { registerChoiceTool } from \"../../tools/choice.js\";\nimport { registerFilesystemTools } from \"../../tools/filesystem.js\";\nimport { JobRegistry } from \"../../tools/jobs.js\";\nimport { registerMemoryTools } from \"../../tools/memory.js\";\nimport { registerPlanTool } from \"../../tools/plan.js\";\nimport { registerShellTools } from \"../../tools/shell.js\";\nimport { registerTodoTool } from \"../../tools/todo.js\";\nimport { markPhase } from \"../startup-profile.js\";\nimport { chatCommand } from \"./chat.js\";\n\nexport interface CodeOptions {\n /** Directory to root the filesystem tools at. Defaults to process.cwd(). */\n dir?: string;\n /** Override the default `smart` model. */\n model?: string;\n /** Disable session persistence. */\n noSession?: boolean;\n /** Transcript file for replay/diff. */\n transcript?: string;\n /** Skip the session picker — always resume prior messages. */\n forceResume?: boolean;\n /** Skip the session picker — always wipe prior messages and start fresh. */\n forceNew?: boolean;\n /**\n * Soft USD spend cap. Off by default. Same semantics as `chat`:\n * warns at 80%, refuses next turn at 100%. Mid-session adjustable\n * via `/budget <usd>` slash command.\n */\n budgetUsd?: number;\n /** Suppress the auto-launched embedded web dashboard. */\n noDashboard?: boolean;\n /** Inline string appended to the code system prompt after the generated base prompt. */\n systemAppend?: string;\n /** Path to a UTF-8 text file whose contents are appended to the code system prompt. */\n systemAppendFile?: string;\n /** Default true. Pass false (CLI: `--no-alt-screen`) to keep chat output in shell scrollback. */\n altScreen?: boolean;\n}\n\nexport async function codeCommand(opts: CodeOptions = {}): Promise<void> {\n markPhase(\"code_command_enter\");\n const { codeSystemPrompt } = await import(\"../../code/prompt.js\");\n const rootDir = resolve(opts.dir ?? process.cwd());\n // Per-directory session so switching projects doesn't mix histories.\n // `code-<sanitized-basename>` fits the session name rules without\n // truncating most project names.\n const session = opts.noSession ? undefined : `code-${sanitizeName(basename(rootDir))}`;\n\n // Native filesystem tools. No subprocess, ~50-200 ms faster per call\n // than the MCP server was, and `edit_file` takes a flat SEARCH/REPLACE\n // shape instead of the `string=\"false\"` JSON-in-string array that\n // triggered R1's DSML hallucinations all through 0.4.x.\n const tools = new ToolRegistry();\n // Background-process registry shared between the shell tools and the\n // TUI's /jobs + /kill slashes + exit cleanup. One per `reasonix code`\n // run — orphan prevention on SIGINT / process exit kills everything\n // it owns, so dev servers don't outlive the Reasonix process.\n const jobs = new JobRegistry();\n // Bundled re-registration so `/cwd <path>` can swap every rootDir-\n // dependent tool atomically. ToolRegistry.register is keyed by name\n // and overwrites in-place, so re-calling these against the existing\n // registry replaces the closures cleanly without disturbing tool\n // specs (names/descriptions/params don't reference rootDir, so the\n // prefix cache survives).\n const registerRootedTools = (root: string): void => {\n registerFilesystemTools(tools, { rootDir: root });\n registerShellTools(tools, {\n rootDir: root,\n // Per-project \"always allow\" list persisted from prior ShellConfirm\n // choices; merged on top of the built-in allowlist in shell.ts.\n // GETTER form — re-read every dispatch so a prefix the user adds\n // via ShellConfirm mid-session takes effect on the next shell call\n // instead of waiting for `/new` or a relaunch.\n extraAllowed: () => loadProjectShellAllowed(root),\n // `yolo` edit-mode disables shell confirmations entirely. Re-read\n // from config on each dispatch so /mode yolo (or Shift+Tab cycling\n // through to it) flips the gate live without forcing a relaunch.\n allowAll: () => loadEditMode() === \"yolo\",\n jobs,\n });\n // `remember` / `forget` / `recall_memory` — cross-session user memory.\n // Project scope hashes off rootDir so switching projects gets a fresh\n // per-project memory store; the global scope is shared across runs.\n registerMemoryTools(tools, { projectRoot: root });\n };\n // Async tail to `registerRootedTools`. Kept separate because the FS /\n // shell / memory re-registration above is sync and must happen before\n // the next tool dispatch, while semantic-index probing reads disk and\n // can race ahead in the background. On `/cwd`, App.tsx fires this\n // after the sync swap and surfaces the result via postInfo.\n const reBootstrapSemantic = async (root: string): Promise<{ enabled: boolean }> => {\n const result = await bootstrapSemanticSearchInCodeMode(tools, root);\n if (!result.enabled) tools.unregister(\"semantic_search\");\n return result;\n };\n registerRootedTools(rootDir);\n // `submit_plan` is always in the spec list so the prefix cache stays\n // stable across plan-mode toggles (Pillar 1). The tool itself is a\n // no-op outside plan mode and throws `PlanProposedError` when the\n // user has `/plan`-enabled the session.\n registerPlanTool(tools);\n // `ask_choice` — branching primitive. Independent of plan mode: the\n // model uses it to put a 2–4 way choice in front of the user\n // (strategy, style, library pick) without trying to squeeze the\n // menu into a submit_plan body. Keeping it always-registered\n // preserves the prefix cache across plan-mode toggles.\n registerChoiceTool(tools);\n // `todo_write` — lightweight in-session task tracker, no approval gate.\n // Independent of plan mode (readOnly=true so it stays callable in /plan).\n registerTodoTool(tools);\n // `run_skill` is intentionally NOT registered here — App.tsx wires it\n // up with the subagent runner attached, so `runAs: subagent` skills\n // can spawn isolated child loops. Doing it here would mean the App's\n // re-registration would shadow the no-runner version, which works\n // (last write wins) but obscures the wiring.\n\n // Bootstrap semantic_search. Silent: registers the tool when an\n // on-disk index already exists, skips entirely otherwise. Setup\n // happens via the explicit `reasonix index` command — never\n // by surprise on launch.\n markPhase(\"semantic_bootstrap_start\");\n const semantic = await reBootstrapSemantic(rootDir);\n markPhase(\n semantic.enabled ? \"semantic_bootstrap_done_enabled\" : \"semantic_bootstrap_done_skipped\",\n );\n\n process.stderr.write(\n `▸ reasonix code: rooted at ${rootDir}, session \"${session ?? \"(ephemeral)\"}\" · ${tools.size} native tool(s)${\n semantic.enabled ? \" · semantic_search on\" : \"\"\n }\\n`,\n );\n\n // Belt-and-suspenders cleanup: even though spawn(detached:false)\n // should tie child processes to the parent's lifetime, Windows cmd.exe\n // wrappers occasionally leak. We DON'T install SIGINT/SIGTERM\n // handlers here — that overrode Node's default \"exit on Ctrl+C\" with\n // a silent no-op, which made Ctrl+C feel broken in the TUI. App.tsx\n // owns the SIGINT path now (it shows the quit-armed banner and calls\n // exit() on confirmation); this 'exit' hook just guarantees the job\n // registry is drained on the way out, regardless of which exit path\n // fired.\n process.once(\"exit\", () => {\n void jobs.shutdown();\n });\n\n let systemAppendFileContents: string | undefined;\n if (opts.systemAppend !== undefined && opts.systemAppend.trim().length === 0) {\n process.stderr.write(\"--system-append is empty — no prompt text will be appended\\n\");\n }\n if (opts.systemAppendFile) {\n const filePath = resolve(opts.systemAppendFile);\n try {\n systemAppendFileContents = readFileSync(filePath, \"utf8\");\n } catch (err) {\n const e = err as NodeJS.ErrnoException;\n process.stderr.write(\n `Error: cannot read --system-append-file \"${filePath}\": ${e.code ? `[${e.code}] ` : \"\"}${e.message}\\n`,\n );\n process.exit(1);\n }\n }\n\n await chatCommand({\n model: opts.model ?? \"deepseek-v4-flash\",\n budgetUsd: opts.budgetUsd,\n system: codeSystemPrompt(rootDir, {\n hasSemanticSearch: semantic.enabled,\n systemAppend: opts.systemAppend,\n systemAppendFile: systemAppendFileContents,\n }),\n transcript: opts.transcript,\n session,\n seedTools: tools,\n codeMode: {\n rootDir,\n jobs,\n reregisterTools: registerRootedTools,\n reBootstrapSemantic,\n },\n mcp: readConfig().mcp,\n forceResume: opts.forceResume,\n forceNew: opts.forceNew,\n noDashboard: opts.noDashboard,\n altScreen: opts.altScreen,\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoBA,SAAS,oBAAoB;AAC7B,SAAS,UAAU,eAAe;AA4ClC,eAAsB,YAAY,OAAoB,CAAC,GAAkB;AACvE,YAAU,oBAAoB;AAC9B,QAAM,EAAE,iBAAiB,IAAI,MAAM,OAAO,sBAAsB;AAChE,QAAM,UAAU,QAAQ,KAAK,OAAO,QAAQ,IAAI,CAAC;AAIjD,QAAM,UAAU,KAAK,YAAY,SAAY,QAAQ,aAAa,SAAS,OAAO,CAAC,CAAC;AAMpF,QAAM,QAAQ,IAAI,aAAa;AAK/B,QAAM,OAAO,IAAI,YAAY;AAO7B,QAAM,sBAAsB,CAAC,SAAuB;AAClD,4BAAwB,OAAO,EAAE,SAAS,KAAK,CAAC;AAChD,uBAAmB,OAAO;AAAA,MACxB,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAMT,cAAc,MAAM,wBAAwB,IAAI;AAAA;AAAA;AAAA;AAAA,MAIhD,UAAU,MAAM,aAAa,MAAM;AAAA,MACnC;AAAA,IACF,CAAC;AAID,wBAAoB,OAAO,EAAE,aAAa,KAAK,CAAC;AAAA,EAClD;AAMA,QAAM,sBAAsB,OAAO,SAAgD;AACjF,UAAM,SAAS,MAAM,kCAAkC,OAAO,IAAI;AAClE,QAAI,CAAC,OAAO,QAAS,OAAM,WAAW,iBAAiB;AACvD,WAAO;AAAA,EACT;AACA,sBAAoB,OAAO;AAK3B,mBAAiB,KAAK;AAMtB,qBAAmB,KAAK;AAGxB,mBAAiB,KAAK;AAWtB,YAAU,0BAA0B;AACpC,QAAM,WAAW,MAAM,oBAAoB,OAAO;AAClD;AAAA,IACE,SAAS,UAAU,oCAAoC;AAAA,EACzD;AAEA,UAAQ,OAAO;AAAA,IACb,mCAA8B,OAAO,cAAc,WAAW,aAAa,UAAO,MAAM,IAAI,kBAC1F,SAAS,UAAU,6BAA0B,EAC/C;AAAA;AAAA,EACF;AAWA,UAAQ,KAAK,QAAQ,MAAM;AACzB,SAAK,KAAK,SAAS;AAAA,EACrB,CAAC;AAED,MAAI;AACJ,MAAI,KAAK,iBAAiB,UAAa,KAAK,aAAa,KAAK,EAAE,WAAW,GAAG;AAC5E,YAAQ,OAAO,MAAM,mEAA8D;AAAA,EACrF;AACA,MAAI,KAAK,kBAAkB;AACzB,UAAM,WAAW,QAAQ,KAAK,gBAAgB;AAC9C,QAAI;AACF,iCAA2B,aAAa,UAAU,MAAM;AAAA,IAC1D,SAAS,KAAK;AACZ,YAAM,IAAI;AACV,cAAQ,OAAO;AAAA,QACb,4CAA4C,QAAQ,MAAM,EAAE,OAAO,IAAI,EAAE,IAAI,OAAO,EAAE,GAAG,EAAE,OAAO;AAAA;AAAA,MACpG;AACA,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF;AAEA,QAAM,YAAY;AAAA,IAChB,OAAO,KAAK,SAAS;AAAA,IACrB,WAAW,KAAK;AAAA,IAChB,QAAQ,iBAAiB,SAAS;AAAA,MAChC,mBAAmB,SAAS;AAAA,MAC5B,cAAc,KAAK;AAAA,MACnB,kBAAkB;AAAA,IACpB,CAAC;AAAA,IACD,YAAY,KAAK;AAAA,IACjB;AAAA,IACA,WAAW;AAAA,IACX,UAAU;AAAA,MACR;AAAA,MACA;AAAA,MACA,iBAAiB;AAAA,MACjB;AAAA,IACF;AAAA,IACA,KAAK,WAAW,EAAE;AAAA,IAClB,aAAa,KAAK;AAAA,IAClB,UAAU,KAAK;AAAA,IACf,aAAa,KAAK;AAAA,IAClB,WAAW,KAAK;AAAA,EAClB,CAAC;AACH;","names":[]}
|
|
@@ -4,12 +4,13 @@ import {
|
|
|
4
4
|
checkOllamaStatus,
|
|
5
5
|
pullOllamaModel,
|
|
6
6
|
startOllamaDaemon
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-RXGEGA7K.js";
|
|
8
8
|
import "./chunk-5X7LZJDE.js";
|
|
9
9
|
import {
|
|
10
10
|
loadIndexConfig,
|
|
11
11
|
resolveSemanticEmbeddingConfig
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-5JXXEPDM.js";
|
|
13
|
+
import "./chunk-WUI3P4RA.js";
|
|
13
14
|
|
|
14
15
|
// src/cli/commands/index.ts
|
|
15
16
|
import { resolve } from "path";
|
|
@@ -349,4 +350,4 @@ function makeTtyWriter() {
|
|
|
349
350
|
export {
|
|
350
351
|
indexCommand
|
|
351
352
|
};
|
|
352
|
-
//# sourceMappingURL=commands-
|
|
353
|
+
//# sourceMappingURL=commands-MEZPSEHV.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/cli/commands/index.ts","../../src/index/semantic/i18n.ts","../../src/index/semantic/preflight.ts"],"sourcesContent":["/** `reasonix index` — progress writes go to stderr so stdout stays pipeable. */\n\nimport { resolve } from \"node:path\";\nimport { loadIndexConfig, resolveSemanticEmbeddingConfig } from \"../../config.js\";\nimport { buildIndex } from \"../../index/semantic/builder.js\";\nimport type { BuildProgress, BuildResult, SkipBuckets } from \"../../index/semantic/builder.js\";\nimport { t } from \"../../index/semantic/i18n.js\";\nimport { semanticPreflight } from \"../../index/semantic/preflight.js\";\n\nexport interface IndexCommandOptions {\n rebuild?: boolean;\n model?: string;\n dir?: string;\n ollamaUrl?: string;\n yes?: boolean;\n}\n\nexport async function indexCommand(opts: IndexCommandOptions = {}): Promise<void> {\n const root = resolve(opts.dir ?? process.cwd());\n const tty = process.stderr.isTTY === true && process.stdin.isTTY === true;\n const resolved = resolveSemanticEmbeddingConfig();\n const embedding =\n resolved.provider === \"ollama\"\n ? {\n ...resolved,\n model: opts.model ?? resolved.model,\n baseUrl: opts.ollamaUrl ?? resolved.baseUrl,\n }\n : {\n ...resolved,\n model: opts.model ?? resolved.model,\n };\n\n const preflightOk = await semanticPreflight(embedding, {\n interactive: tty && !opts.yes,\n yesToAll: opts.yes ?? false,\n });\n if (!preflightOk) process.exit(1);\n\n const writer = makeProgressWriter(tty);\n\n const t0 = Date.now();\n let result: BuildResult;\n try {\n result = await buildIndex(root, {\n ...embedding,\n rebuild: opts.rebuild,\n indexConfig: loadIndexConfig(),\n onProgress: (p) => writer.update(p),\n });\n } catch (err) {\n writer.clear();\n const msg = err instanceof Error ? err.message : String(err);\n process.stderr.write(t(\"indexFailed\", { msg }));\n process.exit(1);\n }\n writer.clear();\n\n const seconds = ((Date.now() - t0) / 1000).toFixed(1);\n const successKey = result.chunksSkipped > 0 ? \"indexSuccessWithSkips\" : \"indexSuccess\";\n process.stderr.write(\n t(successKey, {\n scanned: result.filesScanned,\n changed: result.filesChanged,\n added: result.chunksAdded,\n removed: result.chunksRemoved,\n skipped: result.chunksSkipped,\n seconds,\n }),\n );\n const breakdown = renderSkipBreakdown(result.skipBuckets);\n if (breakdown) process.stderr.write(`${breakdown}\\n`);\n if (result.filesChanged === 0 && !opts.rebuild) {\n process.stderr.write(t(\"indexNothingToDo\"));\n }\n}\n\nfunction renderSkipBreakdown(buckets: SkipBuckets): string {\n const total = Object.values(buckets).reduce((a, b) => a + b, 0);\n if (total === 0) return \"\";\n const parts: string[] = [];\n if (buckets.gitignore) parts.push(`gitignore: ${buckets.gitignore}`);\n if (buckets.pattern) parts.push(`pattern: ${buckets.pattern}`);\n if (buckets.defaultDir) parts.push(`defaultDir: ${buckets.defaultDir}`);\n if (buckets.defaultFile) parts.push(`defaultFile: ${buckets.defaultFile}`);\n if (buckets.binaryExt) parts.push(`binaryExt: ${buckets.binaryExt}`);\n if (buckets.binaryContent) parts.push(`binaryContent: ${buckets.binaryContent}`);\n if (buckets.tooLarge) parts.push(`tooLarge: ${buckets.tooLarge}`);\n if (buckets.readError) parts.push(`readError: ${buckets.readError}`);\n return ` · skipped ${total} files (${parts.join(\", \")})`;\n}\n\ninterface ProgressWriter {\n update(p: BuildProgress): void;\n clear(): void;\n}\n\nconst SPINNER_FRAMES = [\"⠋\", \"⠙\", \"⠹\", \"⠸\", \"⠼\", \"⠴\", \"⠦\", \"⠧\", \"⠇\", \"⠏\"];\nconst SPINNER_INTERVAL_MS = 120;\n\nfunction makeProgressWriter(tty: boolean): ProgressWriter {\n if (!tty) return makeNonTtyWriter();\n return makeTtyWriter();\n}\n\nfunction makeNonTtyWriter(): ProgressWriter {\n let lastPhase: BuildProgress[\"phase\"] | null = null;\n let lastChunks = 0;\n return {\n update(p) {\n if (p.phase !== lastPhase) {\n lastPhase = p.phase;\n if (p.phase === \"scan\") {\n process.stderr.write(t(\"progressScanLine\"));\n } else if (p.phase === \"embed\") {\n process.stderr.write(\n t(\"progressEmbedLine\", {\n total: p.chunksTotal ?? 0,\n files: p.filesChanged ?? 0,\n }),\n );\n }\n }\n if (p.phase === \"embed\" && p.chunksDone !== undefined && p.chunksDone - lastChunks >= 50) {\n lastChunks = p.chunksDone;\n process.stderr.write(\n t(\"progressEmbedHeartbeat\", {\n done: p.chunksDone,\n total: p.chunksTotal ?? \"?\",\n }),\n );\n }\n },\n clear() {\n /* non-TTY keeps its accumulated lines */\n },\n };\n}\n\nfunction makeTtyWriter(): ProgressWriter {\n let status = t(\"progressStarting\");\n let lastLineLen = 0;\n let frameIdx = 0;\n const startTs = Date.now();\n\n const repaint = () => {\n const frame = SPINNER_FRAMES[frameIdx % SPINNER_FRAMES.length];\n frameIdx++;\n const elapsed = ((Date.now() - startTs) / 1000).toFixed(1);\n const line = `${frame} ${status} ${elapsed}s`;\n const padded = line + \" \".repeat(Math.max(0, lastLineLen - line.length));\n process.stderr.write(`\\r${padded}`);\n lastLineLen = line.length;\n };\n\n repaint();\n const interval = setInterval(repaint, SPINNER_INTERVAL_MS);\n\n return {\n update(p) {\n if (p.phase === \"scan\") {\n status = t(\"progressScan\", { files: p.filesScanned ?? 0 });\n } else if (p.phase === \"embed\") {\n const done = p.chunksDone ?? 0;\n const total = p.chunksTotal ?? 0;\n const pct = total > 0 ? ((done / total) * 100).toFixed(0) : \"0\";\n status = t(\"progressEmbed\", { done, total, pct });\n }\n repaint();\n },\n clear() {\n clearInterval(interval);\n if (lastLineLen > 0) {\n process.stderr.write(`\\r${\" \".repeat(lastLineLen)}\\r`);\n lastLineLen = 0;\n }\n },\n };\n}\n","/** EN+ZH for semantic-search prompts only; tool descriptions stay English to preserve prompt-cache. */\n\nexport type Locale = \"en\" | \"zh\";\n\nlet cachedLocale: Locale | null = null;\n\nexport function detectLocale(): Locale {\n if (cachedLocale) return cachedLocale;\n const override = (process.env.REASONIX_LANG ?? \"\").toLowerCase();\n if (override === \"zh\" || override === \"en\") {\n cachedLocale = override;\n return cachedLocale;\n }\n const env = process.env.LANG ?? process.env.LC_ALL ?? process.env.LC_MESSAGES ?? \"\";\n if (/^zh[-_]/i.test(env)) {\n cachedLocale = \"zh\";\n return \"zh\";\n }\n try {\n const sys = new Intl.DateTimeFormat().resolvedOptions().locale ?? \"\";\n if (/^zh[-_]/i.test(sys)) {\n cachedLocale = \"zh\";\n return \"zh\";\n }\n } catch {\n /* ignore — fall through to default */\n }\n cachedLocale = \"en\";\n return \"en\";\n}\n\n/** Reset the cached locale. Tests use this; production never needs it. */\nexport function resetLocaleCache(): void {\n cachedLocale = null;\n}\n\n/** Falls back to English so partial dictionary updates never show \"[missing]\". */\nexport function t(key: keyof typeof EN, vars: Record<string, string | number> = {}): string {\n const loc = detectLocale();\n const dict = loc === \"zh\" ? ZH : EN;\n const tpl = dict[key] ?? EN[key];\n return tpl.replace(/\\{(\\w+)\\}/g, (_m, name) => {\n const v = vars[name];\n return v === undefined ? `{${name}}` : String(v);\n });\n}\n\nconst EN = {\n // ── preflight ─────────────────────────────────────────────────────\n ollamaNotFound:\n \"✗ `ollama` not found on PATH.\\n Install from https://ollama.com (one-time, ~150 MB), then retry.\\n\",\n daemonNotReachableHint:\n \"✗ Ollama daemon not reachable. Run `ollama serve` and retry, or pass --yes to start it automatically.\\n\",\n daemonStartConfirm: \"Ollama daemon isn't running. Start `ollama serve` now?\",\n daemonAbortStart: \"✗ aborted — start `ollama serve` yourself and retry.\\n\",\n daemonStarting: \"▸ starting `ollama serve`…\\n\",\n daemonStartTimeout:\n \"✗ daemon didn't come up within 15s. Try `ollama serve` in a separate terminal and retry.\\n\",\n daemonReady: \"✓ daemon up{pid}\\n\",\n modelNotPulledHint:\n '✗ embedding model \"{model}\" not pulled. Run `ollama pull {model}` and retry, or pass --yes to pull it automatically.\\n',\n modelPullConfirm:\n 'Embedding model \"{model}\" isn\\'t pulled yet. Pull it now? (~274 MB for nomic-embed-text)',\n modelAbortPull: \"✗ aborted — pull the model yourself and retry.\\n\",\n modelPulling: \"▸ pulling {model}…\\n\",\n modelPullFailed: \"✗ `ollama pull {model}` failed (exit {code}).\\n\",\n modelPulled: \"✓ {model} pulled\\n\",\n\n // ── progress ─────────────────────────────────────────────────────\n // The TTY-mode progress writer paints `<spinner> <status> <elapsed>s`\n // every 120ms. The status itself comes from one of these keys based\n // on the current phase. {files}, {done}, {total}, {pct} are\n // substituted by the writer.\n progressStarting: \"starting…\",\n progressScan: \"scanning project · {files} files\",\n progressEmbed: \"embedding {done}/{total} chunks · {pct}%\",\n progressEmbedHeartbeat: \" {done}/{total}\\n\",\n progressScanLine: \"scanning files…\\n\",\n progressEmbedLine: \"embedding {total} chunks across {files} files…\\n\",\n // Final result line after a successful build.\n indexSuccess:\n \"✓ indexed {scanned} files ({changed} changed, {added} new chunks, {removed} stale removed) in {seconds}s\\n\",\n indexSuccessWithSkips:\n \"✓ indexed {scanned} files ({changed} changed, {added} new chunks, {removed} stale removed, {skipped} skipped due to embed errors) in {seconds}s\\n\",\n indexNothingToDo: \" (nothing to do — re-run with --rebuild to force a full rebuild)\\n\",\n indexFailed: \"✗ index failed: {msg}\\n\",\n\n // ── /semantic slash ──────────────────────────────────────────────\n slashHeader: \"semantic_search status\",\n slashEnabled: \"✓ enabled — index built, tool registered.\",\n slashEnabledDetail: \" index size: {chunks} chunks across {files} files\",\n slashEnabledHowto: \" the model will call semantic_search automatically when it fits.\",\n slashIndexMissing: \"✗ no index built yet for this project.\",\n slashHowToBuild: \" to enable, exit Reasonix and run in your shell:\\n reasonix index\",\n slashOllamaMissing: \" prerequisite: install Ollama from https://ollama.com\",\n slashDaemonDown:\n \" Ollama is installed but the daemon isn't running. start it with: ollama serve\",\n slashIndexInfo:\n \" what semantic_search does: cross-language code understanding via local embeddings.\\n better than grep when you describe WHAT something does, not WHICH token to find.\",\n} as const;\n\nconst ZH: Partial<Record<keyof typeof EN, string>> = {\n ollamaNotFound:\n \"✗ 未找到 `ollama`。\\n 请访问 https://ollama.com 安装(一次性,约 150 MB),然后重试。\\n\",\n daemonNotReachableHint:\n \"✗ Ollama 守护进程未启动。请运行 `ollama serve` 后重试,或加 --yes 让我自动启动。\\n\",\n daemonStartConfirm: \"Ollama 守护进程未运行。现在启动 `ollama serve` 吗?\",\n daemonAbortStart: \"✗ 已取消——请自行运行 `ollama serve` 后重试。\\n\",\n daemonStarting: \"▸ 正在启动 `ollama serve`…\\n\",\n daemonStartTimeout: \"✗ 15 秒内守护进程未就绪。请在另一个终端运行 `ollama serve` 后重试。\\n\",\n daemonReady: \"✓ 守护进程已启动{pid}\\n\",\n modelNotPulledHint:\n '✗ 嵌入模型 \"{model}\" 未下载。请运行 `ollama pull {model}` 后重试,或加 --yes 让我自动下载。\\n',\n modelPullConfirm: '嵌入模型 \"{model}\" 还未下载。现在下载吗?(nomic-embed-text 约 274 MB)',\n modelAbortPull: \"✗ 已取消——请自行下载模型后重试。\\n\",\n modelPulling: \"▸ 正在下载 {model}…\\n\",\n modelPullFailed: \"✗ `ollama pull {model}` 失败(退出码 {code})。\\n\",\n modelPulled: \"✓ {model} 下载完成\\n\",\n\n progressStarting: \"正在启动…\",\n progressScan: \"扫描项目 · 已扫描 {files} 个文件\",\n progressEmbed: \"正在向量化 {done}/{total} 个片段 · {pct}%\",\n progressEmbedHeartbeat: \" {done}/{total}\\n\",\n progressScanLine: \"正在扫描文件…\\n\",\n progressEmbedLine: \"正在向量化 {total} 个片段(涉及 {files} 个文件)…\\n\",\n indexSuccess:\n \"✓ 已建立索引:扫描 {scanned} 个文件({changed} 个有变化,新增 {added} 个片段,移除 {removed} 个过期);耗时 {seconds}s\\n\",\n indexSuccessWithSkips:\n \"✓ 已建立索引:扫描 {scanned} 个文件({changed} 个有变化,新增 {added} 个片段,移除 {removed} 个过期,跳过 {skipped} 个嵌入失败的片段);耗时 {seconds}s\\n\",\n indexNothingToDo: \" (没有变化——加 --rebuild 强制重建)\\n\",\n indexFailed: \"✗ 建立索引失败:{msg}\\n\",\n\n slashHeader: \"semantic_search 状态\",\n slashEnabled: \"✓ 已启用——索引已建好,工具已注册。\",\n slashEnabledDetail: \" 索引规模:{chunks} 个片段,{files} 个文件\",\n slashEnabledHowto: \" 模型在合适的时候会自动调用 semantic_search。\",\n slashIndexMissing: \"✗ 当前项目还没有索引。\",\n slashHowToBuild: \" 启用方式:退出 Reasonix,在终端运行:\\n reasonix index\",\n slashOllamaMissing: \" 前置依赖:从 https://ollama.com 安装 Ollama\",\n slashDaemonDown: \" 已装 Ollama 但守护进程未启动,请运行:ollama serve\",\n slashIndexInfo:\n ' semantic_search 用本地 embedding 做跨语言代码理解。\\n 当你描述\"做什么\"而不是具体 token 时,比 grep 更好。',\n};\n","import { stdin, stdout } from \"node:process\";\nimport { createInterface } from \"node:readline/promises\";\nimport type { ResolvedEmbeddingConfig } from \"../../config.js\";\nimport { t } from \"./i18n.js\";\nimport { checkOllamaStatus, pullOllamaModel, startOllamaDaemon } from \"./ollama-launcher.js\";\n\nexport interface PreflightOptions {\n model: string;\n baseUrl?: string | undefined;\n interactive: boolean;\n yesToAll: boolean;\n log?: (line: string) => void;\n}\n\nexport async function ollamaPreflight(opts: PreflightOptions): Promise<boolean> {\n const log = opts.log ?? ((line: string) => process.stderr.write(line));\n const status = await checkOllamaStatus(opts.model, opts.baseUrl);\n\n if (!status.binaryFound) {\n log(t(\"ollamaNotFound\"));\n return false;\n }\n\n if (!status.daemonRunning) {\n if (!opts.interactive && !opts.yesToAll) {\n log(t(\"daemonNotReachableHint\"));\n return false;\n }\n const ok = opts.yesToAll || (await confirm(t(\"daemonStartConfirm\"), true));\n if (!ok) {\n log(t(\"daemonAbortStart\"));\n return false;\n }\n log(t(\"daemonStarting\"));\n const started = await startOllamaDaemon({ baseUrl: opts.baseUrl, timeoutMs: 15_000 });\n if (!started.ready) {\n log(t(\"daemonStartTimeout\"));\n return false;\n }\n log(t(\"daemonReady\", { pid: started.pid ? ` (pid ${started.pid})` : \"\" }));\n }\n\n const after = status.daemonRunning ? status : await checkOllamaStatus(opts.model, opts.baseUrl);\n\n if (!after.modelPulled) {\n if (!opts.interactive && !opts.yesToAll) {\n log(t(\"modelNotPulledHint\", { model: opts.model }));\n return false;\n }\n const ok = opts.yesToAll || (await confirm(t(\"modelPullConfirm\", { model: opts.model }), true));\n if (!ok) {\n log(t(\"modelAbortPull\"));\n return false;\n }\n log(t(\"modelPulling\", { model: opts.model }));\n const ESC = String.fromCharCode(0x1b);\n const ANSI_CSI = new RegExp(`${ESC}\\\\[[0-9;]*[A-Za-z]`, \"g\");\n const code = await pullOllamaModel(opts.model, {\n onLine: (line) => {\n const cleaned = line.replace(ANSI_CSI, \"\").trim();\n if (cleaned.length === 0) return;\n log(` ${cleaned}\\n`);\n },\n });\n if (code !== 0) {\n log(t(\"modelPullFailed\", { model: opts.model, code }));\n return false;\n }\n log(t(\"modelPulled\", { model: opts.model }));\n }\n\n return true;\n}\n\nexport async function semanticPreflight(\n config: ResolvedEmbeddingConfig,\n opts: Omit<PreflightOptions, \"model\" | \"baseUrl\">,\n): Promise<boolean> {\n if (config.provider === \"openai-compat\") return true;\n return await ollamaPreflight({\n ...opts,\n model: config.model,\n baseUrl: config.baseUrl,\n });\n}\n\nexport async function confirm(question: string, defaultYes: boolean): Promise<boolean> {\n const suffix = defaultYes ? \"[Y/n]\" : \"[y/N]\";\n const rl = createInterface({ input: stdin, output: stdout });\n try {\n const raw = (await rl.question(`${question} ${suffix} `)).trim().toLowerCase();\n if (raw === \"\") return defaultYes;\n return raw === \"y\" || raw === \"yes\";\n } finally {\n rl.close();\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/cli/commands/index.ts","../../src/index/semantic/i18n.ts","../../src/index/semantic/preflight.ts"],"sourcesContent":["/** `reasonix index` — progress writes go to stderr so stdout stays pipeable. */\n\nimport { resolve } from \"node:path\";\nimport { loadIndexConfig, resolveSemanticEmbeddingConfig } from \"../../config.js\";\nimport { buildIndex } from \"../../index/semantic/builder.js\";\nimport type { BuildProgress, BuildResult, SkipBuckets } from \"../../index/semantic/builder.js\";\nimport { t } from \"../../index/semantic/i18n.js\";\nimport { semanticPreflight } from \"../../index/semantic/preflight.js\";\n\nexport interface IndexCommandOptions {\n rebuild?: boolean;\n model?: string;\n dir?: string;\n ollamaUrl?: string;\n yes?: boolean;\n}\n\nexport async function indexCommand(opts: IndexCommandOptions = {}): Promise<void> {\n const root = resolve(opts.dir ?? process.cwd());\n const tty = process.stderr.isTTY === true && process.stdin.isTTY === true;\n const resolved = resolveSemanticEmbeddingConfig();\n const embedding =\n resolved.provider === \"ollama\"\n ? {\n ...resolved,\n model: opts.model ?? resolved.model,\n baseUrl: opts.ollamaUrl ?? resolved.baseUrl,\n }\n : {\n ...resolved,\n model: opts.model ?? resolved.model,\n };\n\n const preflightOk = await semanticPreflight(embedding, {\n interactive: tty && !opts.yes,\n yesToAll: opts.yes ?? false,\n });\n if (!preflightOk) process.exit(1);\n\n const writer = makeProgressWriter(tty);\n\n const t0 = Date.now();\n let result: BuildResult;\n try {\n result = await buildIndex(root, {\n ...embedding,\n rebuild: opts.rebuild,\n indexConfig: loadIndexConfig(),\n onProgress: (p) => writer.update(p),\n });\n } catch (err) {\n writer.clear();\n const msg = err instanceof Error ? err.message : String(err);\n process.stderr.write(t(\"indexFailed\", { msg }));\n process.exit(1);\n }\n writer.clear();\n\n const seconds = ((Date.now() - t0) / 1000).toFixed(1);\n const successKey = result.chunksSkipped > 0 ? \"indexSuccessWithSkips\" : \"indexSuccess\";\n process.stderr.write(\n t(successKey, {\n scanned: result.filesScanned,\n changed: result.filesChanged,\n added: result.chunksAdded,\n removed: result.chunksRemoved,\n skipped: result.chunksSkipped,\n seconds,\n }),\n );\n const breakdown = renderSkipBreakdown(result.skipBuckets);\n if (breakdown) process.stderr.write(`${breakdown}\\n`);\n if (result.filesChanged === 0 && !opts.rebuild) {\n process.stderr.write(t(\"indexNothingToDo\"));\n }\n}\n\nfunction renderSkipBreakdown(buckets: SkipBuckets): string {\n const total = Object.values(buckets).reduce((a, b) => a + b, 0);\n if (total === 0) return \"\";\n const parts: string[] = [];\n if (buckets.gitignore) parts.push(`gitignore: ${buckets.gitignore}`);\n if (buckets.pattern) parts.push(`pattern: ${buckets.pattern}`);\n if (buckets.defaultDir) parts.push(`defaultDir: ${buckets.defaultDir}`);\n if (buckets.defaultFile) parts.push(`defaultFile: ${buckets.defaultFile}`);\n if (buckets.binaryExt) parts.push(`binaryExt: ${buckets.binaryExt}`);\n if (buckets.binaryContent) parts.push(`binaryContent: ${buckets.binaryContent}`);\n if (buckets.tooLarge) parts.push(`tooLarge: ${buckets.tooLarge}`);\n if (buckets.readError) parts.push(`readError: ${buckets.readError}`);\n return ` · skipped ${total} files (${parts.join(\", \")})`;\n}\n\ninterface ProgressWriter {\n update(p: BuildProgress): void;\n clear(): void;\n}\n\nconst SPINNER_FRAMES = [\"⠋\", \"⠙\", \"⠹\", \"⠸\", \"⠼\", \"⠴\", \"⠦\", \"⠧\", \"⠇\", \"⠏\"];\nconst SPINNER_INTERVAL_MS = 120;\n\nfunction makeProgressWriter(tty: boolean): ProgressWriter {\n if (!tty) return makeNonTtyWriter();\n return makeTtyWriter();\n}\n\nfunction makeNonTtyWriter(): ProgressWriter {\n let lastPhase: BuildProgress[\"phase\"] | null = null;\n let lastChunks = 0;\n return {\n update(p) {\n if (p.phase !== lastPhase) {\n lastPhase = p.phase;\n if (p.phase === \"scan\") {\n process.stderr.write(t(\"progressScanLine\"));\n } else if (p.phase === \"embed\") {\n process.stderr.write(\n t(\"progressEmbedLine\", {\n total: p.chunksTotal ?? 0,\n files: p.filesChanged ?? 0,\n }),\n );\n }\n }\n if (p.phase === \"embed\" && p.chunksDone !== undefined && p.chunksDone - lastChunks >= 50) {\n lastChunks = p.chunksDone;\n process.stderr.write(\n t(\"progressEmbedHeartbeat\", {\n done: p.chunksDone,\n total: p.chunksTotal ?? \"?\",\n }),\n );\n }\n },\n clear() {\n /* non-TTY keeps its accumulated lines */\n },\n };\n}\n\nfunction makeTtyWriter(): ProgressWriter {\n let status = t(\"progressStarting\");\n let lastLineLen = 0;\n let frameIdx = 0;\n const startTs = Date.now();\n\n const repaint = () => {\n const frame = SPINNER_FRAMES[frameIdx % SPINNER_FRAMES.length];\n frameIdx++;\n const elapsed = ((Date.now() - startTs) / 1000).toFixed(1);\n const line = `${frame} ${status} ${elapsed}s`;\n const padded = line + \" \".repeat(Math.max(0, lastLineLen - line.length));\n process.stderr.write(`\\r${padded}`);\n lastLineLen = line.length;\n };\n\n repaint();\n const interval = setInterval(repaint, SPINNER_INTERVAL_MS);\n\n return {\n update(p) {\n if (p.phase === \"scan\") {\n status = t(\"progressScan\", { files: p.filesScanned ?? 0 });\n } else if (p.phase === \"embed\") {\n const done = p.chunksDone ?? 0;\n const total = p.chunksTotal ?? 0;\n const pct = total > 0 ? ((done / total) * 100).toFixed(0) : \"0\";\n status = t(\"progressEmbed\", { done, total, pct });\n }\n repaint();\n },\n clear() {\n clearInterval(interval);\n if (lastLineLen > 0) {\n process.stderr.write(`\\r${\" \".repeat(lastLineLen)}\\r`);\n lastLineLen = 0;\n }\n },\n };\n}\n","/** EN+ZH for semantic-search prompts only; tool descriptions stay English to preserve prompt-cache. */\n\nexport type Locale = \"en\" | \"zh\";\n\nlet cachedLocale: Locale | null = null;\n\nexport function detectLocale(): Locale {\n if (cachedLocale) return cachedLocale;\n const override = (process.env.REASONIX_LANG ?? \"\").toLowerCase();\n if (override === \"zh\" || override === \"en\") {\n cachedLocale = override;\n return cachedLocale;\n }\n const env = process.env.LANG ?? process.env.LC_ALL ?? process.env.LC_MESSAGES ?? \"\";\n if (/^zh[-_]/i.test(env)) {\n cachedLocale = \"zh\";\n return \"zh\";\n }\n try {\n const sys = new Intl.DateTimeFormat().resolvedOptions().locale ?? \"\";\n if (/^zh[-_]/i.test(sys)) {\n cachedLocale = \"zh\";\n return \"zh\";\n }\n } catch {\n /* ignore — fall through to default */\n }\n cachedLocale = \"en\";\n return \"en\";\n}\n\n/** Reset the cached locale. Tests use this; production never needs it. */\nexport function resetLocaleCache(): void {\n cachedLocale = null;\n}\n\n/** Falls back to English so partial dictionary updates never show \"[missing]\". */\nexport function t(key: keyof typeof EN, vars: Record<string, string | number> = {}): string {\n const loc = detectLocale();\n const dict = loc === \"zh\" ? ZH : EN;\n const tpl = dict[key] ?? EN[key];\n return tpl.replace(/\\{(\\w+)\\}/g, (_m, name) => {\n const v = vars[name];\n return v === undefined ? `{${name}}` : String(v);\n });\n}\n\nconst EN = {\n // ── preflight ─────────────────────────────────────────────────────\n ollamaNotFound:\n \"✗ `ollama` not found on PATH.\\n Install from https://ollama.com (one-time, ~150 MB), then retry.\\n\",\n daemonNotReachableHint:\n \"✗ Ollama daemon not reachable. Run `ollama serve` and retry, or pass --yes to start it automatically.\\n\",\n daemonStartConfirm: \"Ollama daemon isn't running. Start `ollama serve` now?\",\n daemonAbortStart: \"✗ aborted — start `ollama serve` yourself and retry.\\n\",\n daemonStarting: \"▸ starting `ollama serve`…\\n\",\n daemonStartTimeout:\n \"✗ daemon didn't come up within 15s. Try `ollama serve` in a separate terminal and retry.\\n\",\n daemonReady: \"✓ daemon up{pid}\\n\",\n modelNotPulledHint:\n '✗ embedding model \"{model}\" not pulled. Run `ollama pull {model}` and retry, or pass --yes to pull it automatically.\\n',\n modelPullConfirm:\n 'Embedding model \"{model}\" isn\\'t pulled yet. Pull it now? (~274 MB for nomic-embed-text)',\n modelAbortPull: \"✗ aborted — pull the model yourself and retry.\\n\",\n modelPulling: \"▸ pulling {model}…\\n\",\n modelPullFailed: \"✗ `ollama pull {model}` failed (exit {code}).\\n\",\n modelPulled: \"✓ {model} pulled\\n\",\n\n // ── progress ─────────────────────────────────────────────────────\n // The TTY-mode progress writer paints `<spinner> <status> <elapsed>s`\n // every 120ms. The status itself comes from one of these keys based\n // on the current phase. {files}, {done}, {total}, {pct} are\n // substituted by the writer.\n progressStarting: \"starting…\",\n progressScan: \"scanning project · {files} files\",\n progressEmbed: \"embedding {done}/{total} chunks · {pct}%\",\n progressEmbedHeartbeat: \" {done}/{total}\\n\",\n progressScanLine: \"scanning files…\\n\",\n progressEmbedLine: \"embedding {total} chunks across {files} files…\\n\",\n // Final result line after a successful build.\n indexSuccess:\n \"✓ indexed {scanned} files ({changed} changed, {added} new chunks, {removed} stale removed) in {seconds}s\\n\",\n indexSuccessWithSkips:\n \"✓ indexed {scanned} files ({changed} changed, {added} new chunks, {removed} stale removed, {skipped} skipped due to embed errors) in {seconds}s\\n\",\n indexNothingToDo: \" (nothing to do — re-run with --rebuild to force a full rebuild)\\n\",\n indexFailed: \"✗ index failed: {msg}\\n\",\n\n // ── /semantic slash ──────────────────────────────────────────────\n slashHeader: \"semantic_search status\",\n slashEnabled: \"✓ enabled — index built, tool registered.\",\n slashEnabledDetail: \" index size: {chunks} chunks across {files} files\",\n slashEnabledHowto: \" the model will call semantic_search automatically when it fits.\",\n slashIndexMissing: \"✗ no index built yet for this project.\",\n slashHowToBuild: \" to enable, exit Reasonix and run in your shell:\\n reasonix index\",\n slashOllamaMissing: \" prerequisite: install Ollama from https://ollama.com\",\n slashDaemonDown:\n \" Ollama is installed but the daemon isn't running. start it with: ollama serve\",\n slashIndexInfo:\n \" what semantic_search does: cross-language code understanding via local embeddings.\\n better than grep when you describe WHAT something does, not WHICH token to find.\",\n} as const;\n\nconst ZH: Partial<Record<keyof typeof EN, string>> = {\n ollamaNotFound:\n \"✗ 未找到 `ollama`。\\n 请访问 https://ollama.com 安装(一次性,约 150 MB),然后重试。\\n\",\n daemonNotReachableHint:\n \"✗ Ollama 守护进程未启动。请运行 `ollama serve` 后重试,或加 --yes 让我自动启动。\\n\",\n daemonStartConfirm: \"Ollama 守护进程未运行。现在启动 `ollama serve` 吗?\",\n daemonAbortStart: \"✗ 已取消——请自行运行 `ollama serve` 后重试。\\n\",\n daemonStarting: \"▸ 正在启动 `ollama serve`…\\n\",\n daemonStartTimeout: \"✗ 15 秒内守护进程未就绪。请在另一个终端运行 `ollama serve` 后重试。\\n\",\n daemonReady: \"✓ 守护进程已启动{pid}\\n\",\n modelNotPulledHint:\n '✗ 嵌入模型 \"{model}\" 未下载。请运行 `ollama pull {model}` 后重试,或加 --yes 让我自动下载。\\n',\n modelPullConfirm: '嵌入模型 \"{model}\" 还未下载。现在下载吗?(nomic-embed-text 约 274 MB)',\n modelAbortPull: \"✗ 已取消——请自行下载模型后重试。\\n\",\n modelPulling: \"▸ 正在下载 {model}…\\n\",\n modelPullFailed: \"✗ `ollama pull {model}` 失败(退出码 {code})。\\n\",\n modelPulled: \"✓ {model} 下载完成\\n\",\n\n progressStarting: \"正在启动…\",\n progressScan: \"扫描项目 · 已扫描 {files} 个文件\",\n progressEmbed: \"正在向量化 {done}/{total} 个片段 · {pct}%\",\n progressEmbedHeartbeat: \" {done}/{total}\\n\",\n progressScanLine: \"正在扫描文件…\\n\",\n progressEmbedLine: \"正在向量化 {total} 个片段(涉及 {files} 个文件)…\\n\",\n indexSuccess:\n \"✓ 已建立索引:扫描 {scanned} 个文件({changed} 个有变化,新增 {added} 个片段,移除 {removed} 个过期);耗时 {seconds}s\\n\",\n indexSuccessWithSkips:\n \"✓ 已建立索引:扫描 {scanned} 个文件({changed} 个有变化,新增 {added} 个片段,移除 {removed} 个过期,跳过 {skipped} 个嵌入失败的片段);耗时 {seconds}s\\n\",\n indexNothingToDo: \" (没有变化——加 --rebuild 强制重建)\\n\",\n indexFailed: \"✗ 建立索引失败:{msg}\\n\",\n\n slashHeader: \"semantic_search 状态\",\n slashEnabled: \"✓ 已启用——索引已建好,工具已注册。\",\n slashEnabledDetail: \" 索引规模:{chunks} 个片段,{files} 个文件\",\n slashEnabledHowto: \" 模型在合适的时候会自动调用 semantic_search。\",\n slashIndexMissing: \"✗ 当前项目还没有索引。\",\n slashHowToBuild: \" 启用方式:退出 Reasonix,在终端运行:\\n reasonix index\",\n slashOllamaMissing: \" 前置依赖:从 https://ollama.com 安装 Ollama\",\n slashDaemonDown: \" 已装 Ollama 但守护进程未启动,请运行:ollama serve\",\n slashIndexInfo:\n ' semantic_search 用本地 embedding 做跨语言代码理解。\\n 当你描述\"做什么\"而不是具体 token 时,比 grep 更好。',\n};\n","import { stdin, stdout } from \"node:process\";\nimport { createInterface } from \"node:readline/promises\";\nimport type { ResolvedEmbeddingConfig } from \"../../config.js\";\nimport { t } from \"./i18n.js\";\nimport { checkOllamaStatus, pullOllamaModel, startOllamaDaemon } from \"./ollama-launcher.js\";\n\nexport interface PreflightOptions {\n model: string;\n baseUrl?: string | undefined;\n interactive: boolean;\n yesToAll: boolean;\n log?: (line: string) => void;\n}\n\nexport async function ollamaPreflight(opts: PreflightOptions): Promise<boolean> {\n const log = opts.log ?? ((line: string) => process.stderr.write(line));\n const status = await checkOllamaStatus(opts.model, opts.baseUrl);\n\n if (!status.binaryFound) {\n log(t(\"ollamaNotFound\"));\n return false;\n }\n\n if (!status.daemonRunning) {\n if (!opts.interactive && !opts.yesToAll) {\n log(t(\"daemonNotReachableHint\"));\n return false;\n }\n const ok = opts.yesToAll || (await confirm(t(\"daemonStartConfirm\"), true));\n if (!ok) {\n log(t(\"daemonAbortStart\"));\n return false;\n }\n log(t(\"daemonStarting\"));\n const started = await startOllamaDaemon({ baseUrl: opts.baseUrl, timeoutMs: 15_000 });\n if (!started.ready) {\n log(t(\"daemonStartTimeout\"));\n return false;\n }\n log(t(\"daemonReady\", { pid: started.pid ? ` (pid ${started.pid})` : \"\" }));\n }\n\n const after = status.daemonRunning ? status : await checkOllamaStatus(opts.model, opts.baseUrl);\n\n if (!after.modelPulled) {\n if (!opts.interactive && !opts.yesToAll) {\n log(t(\"modelNotPulledHint\", { model: opts.model }));\n return false;\n }\n const ok = opts.yesToAll || (await confirm(t(\"modelPullConfirm\", { model: opts.model }), true));\n if (!ok) {\n log(t(\"modelAbortPull\"));\n return false;\n }\n log(t(\"modelPulling\", { model: opts.model }));\n const ESC = String.fromCharCode(0x1b);\n const ANSI_CSI = new RegExp(`${ESC}\\\\[[0-9;]*[A-Za-z]`, \"g\");\n const code = await pullOllamaModel(opts.model, {\n onLine: (line) => {\n const cleaned = line.replace(ANSI_CSI, \"\").trim();\n if (cleaned.length === 0) return;\n log(` ${cleaned}\\n`);\n },\n });\n if (code !== 0) {\n log(t(\"modelPullFailed\", { model: opts.model, code }));\n return false;\n }\n log(t(\"modelPulled\", { model: opts.model }));\n }\n\n return true;\n}\n\nexport async function semanticPreflight(\n config: ResolvedEmbeddingConfig,\n opts: Omit<PreflightOptions, \"model\" | \"baseUrl\">,\n): Promise<boolean> {\n if (config.provider === \"openai-compat\") return true;\n return await ollamaPreflight({\n ...opts,\n model: config.model,\n baseUrl: config.baseUrl,\n });\n}\n\nexport async function confirm(question: string, defaultYes: boolean): Promise<boolean> {\n const suffix = defaultYes ? \"[Y/n]\" : \"[y/N]\";\n const rl = createInterface({ input: stdin, output: stdout });\n try {\n const raw = (await rl.question(`${question} ${suffix} `)).trim().toLowerCase();\n if (raw === \"\") return defaultYes;\n return raw === \"y\" || raw === \"yes\";\n } finally {\n rl.close();\n }\n}\n"],"mappings":"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","names":[]}
|