reasonix 0.48.0 → 0.49.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/README.md +9 -0
- package/dashboard/dist/app.js +123 -16
- package/dashboard/dist/app.js.map +1 -1
- package/dist/cli/{acp-4ROCGYNH.js → acp-WFQIC6SO.js} +52 -135
- package/dist/cli/acp-WFQIC6SO.js.map +1 -0
- package/dist/cli/chat-D32JGNVH.js +51 -0
- package/dist/cli/{chunk-S2RMQULY.js → chunk-23ZPCIPR.js} +12 -9
- package/dist/cli/chunk-23ZPCIPR.js.map +1 -0
- package/dist/cli/{chunk-TKVXTQ3T.js → chunk-3ZZXQ3CZ.js} +27 -27
- package/dist/cli/chunk-3ZZXQ3CZ.js.map +1 -0
- package/dist/cli/{chunk-5OHHAQ4W.js → chunk-7AST3QQ3.js} +2 -2
- package/dist/cli/{chunk-MRZG4GBF.js → chunk-7JTKBJ2G.js} +3 -3
- package/dist/cli/{chunk-X53B3JIX.js → chunk-7X4JJOO7.js} +2 -61
- package/dist/cli/{chunk-X53B3JIX.js.map → chunk-7X4JJOO7.js.map} +1 -1
- package/dist/cli/{chunk-MOJYKO2A.js → chunk-ASOLXV67.js} +3 -3
- package/dist/cli/{chunk-7M4YYMKW.js → chunk-AWEULQG6.js} +49 -56
- package/dist/cli/{chunk-7M4YYMKW.js.map → chunk-AWEULQG6.js.map} +1 -1
- package/dist/cli/{chunk-HR5NBKEM.js → chunk-DFX5ZH5L.js} +2 -2
- package/dist/cli/{chunk-3WGTGXO4.js → chunk-GNS7BAT2.js} +4 -4
- package/dist/cli/chunk-GNS7BAT2.js.map +1 -0
- package/dist/cli/{chunk-TE5UIIFL.js → chunk-J2IHQGPQ.js} +12 -6
- package/dist/cli/chunk-J2IHQGPQ.js.map +1 -0
- package/dist/cli/{chunk-I4M5QJNL.js → chunk-JGTX4RRQ.js} +3 -3
- package/dist/cli/{chunk-FY4S7TJZ.js → chunk-JNTMOX7G.js} +10 -2
- package/dist/cli/chunk-JNTMOX7G.js.map +1 -0
- package/dist/cli/{chunk-OB4BUJBL.js → chunk-MGTBP7GG.js} +5 -2
- package/dist/cli/chunk-MGTBP7GG.js.map +1 -0
- package/dist/cli/{chunk-OPYALNTT.js → chunk-MQWO32ZD.js} +387 -184
- package/dist/cli/chunk-MQWO32ZD.js.map +1 -0
- package/dist/cli/{chunk-2QSTA2QV.js → chunk-O5LIHAMP.js} +8 -4
- package/dist/cli/chunk-O5LIHAMP.js.map +1 -0
- package/dist/cli/{chunk-NMQSUNLB.js → chunk-PB3MAFEI.js} +6 -3
- package/dist/cli/chunk-PB3MAFEI.js.map +1 -0
- package/dist/cli/{chunk-H4CCXMDD.js → chunk-PEMG6CUB.js} +2 -2
- package/dist/cli/{chunk-RUDBUHO4.js → chunk-PXBQ6IZ7.js} +3 -3
- package/dist/cli/{chunk-J2TQAWOM.js → chunk-Q46B3Z7H.js} +25 -10
- package/dist/cli/{chunk-J2TQAWOM.js.map → chunk-Q46B3Z7H.js.map} +1 -1
- package/dist/cli/{chunk-6MZTZO7A.js → chunk-QF32ROX2.js} +2152 -2613
- package/dist/cli/chunk-QF32ROX2.js.map +1 -0
- package/dist/cli/{chunk-OG5JANQ4.js → chunk-QX5TWXRZ.js} +2 -2
- package/dist/cli/{chunk-V4Y732RQ.js → chunk-TAIKVL35.js} +2 -2
- package/dist/cli/{chunk-B5CZL2SE.js → chunk-TEDWJKEI.js} +4 -9
- package/dist/cli/chunk-TEDWJKEI.js.map +1 -0
- package/dist/cli/{chunk-EMMENC4O.js → chunk-U5XQDCK7.js} +5 -5
- package/dist/cli/{chunk-DOWEOA6E.js → chunk-W46ZMNKO.js} +3 -3
- package/dist/cli/{chunk-CDVSFSAK.js → chunk-WMTMMSXU.js} +184 -8
- package/dist/cli/chunk-WMTMMSXU.js.map +1 -0
- package/dist/cli/{chunk-YW63N3ZR.js → chunk-YEF7C4XI.js} +270 -96
- package/dist/cli/chunk-YEF7C4XI.js.map +1 -0
- package/dist/cli/{chunk-JMDE6IO3.js → chunk-ZAEJWKXB.js} +2 -2
- package/dist/cli/chunk-ZWHSHFDP.js +6173 -0
- package/dist/cli/chunk-ZWHSHFDP.js.map +1 -0
- package/dist/cli/{code-PMPJWXEO.js → code-R4IHI7SR.js} +30 -30
- package/dist/cli/{commands-QS6TG4G3.js → commands-DRHFCYMO.js} +4 -4
- package/dist/cli/{commit-XPRSKUBF.js → commit-AG5KB4YP.js} +3 -3
- package/dist/cli/{desktop-562OPWIU.js → desktop-JGL6GORA.js} +60 -23
- package/dist/cli/desktop-JGL6GORA.js.map +1 -0
- package/dist/cli/{diff-I6W4AUWJ.js → diff-4Z7ETWZO.js} +9 -9
- package/dist/cli/{doctor-6XVZKT4U.js → doctor-VA3RHQLB.js} +9 -9
- package/dist/cli/index.js +37 -36
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/{mcp-7W7ANO2Y.js → mcp-LZO4HXFA.js} +34 -23
- package/dist/cli/mcp-LZO4HXFA.js.map +1 -0
- package/dist/cli/{mcp-browse-LA4I4YIZ.js → mcp-browse-C3GXVMYZ.js} +3 -3
- package/dist/cli/{mcp-inspect-LWXXU7BY.js → mcp-inspect-ZMYUNFDS.js} +2 -2
- package/dist/cli/{prompt-RKZD4X6Y.js → prompt-MC3U5KRP.js} +5 -4
- package/dist/cli/{prune-sessions-SEWX7GP6.js → prune-sessions-OEPFH4N6.js} +11 -7
- package/dist/cli/prune-sessions-OEPFH4N6.js.map +1 -0
- package/dist/cli/{replay-2X7MVXOI.js → replay-4TP7ZUMZ.js} +10 -10
- package/dist/cli/{run-TPKXIJ27.js → run-6MXQYBOE.js} +16 -15
- package/dist/cli/run-6MXQYBOE.js.map +1 -0
- package/dist/cli/{server-NHQ3QXOZ.js → server-Z3IMJNNI.js} +65 -12
- package/dist/cli/server-Z3IMJNNI.js.map +1 -0
- package/dist/cli/{sessions-2A4DGSHA.js → sessions-NXQ5SAV7.js} +18 -18
- package/dist/cli/sessions-NXQ5SAV7.js.map +1 -0
- package/dist/cli/{setup-GOLP7J4C.js → setup-LHZELI6I.js} +6 -6
- package/dist/cli/{stats-CGDAFDKI.js → stats-SUIJ3QWY.js} +6 -6
- package/dist/cli/{version-FIL4ZFOS.js → version-BIFONEUB.js} +13 -13
- package/dist/index.d.ts +71 -17
- package/dist/index.js +1040 -391
- package/dist/index.js.map +1 -1
- package/package.json +6 -2
- package/dist/cli/acp-4ROCGYNH.js.map +0 -1
- package/dist/cli/chat-GZNB5625.js +0 -51
- package/dist/cli/chunk-2QSTA2QV.js.map +0 -1
- package/dist/cli/chunk-3WGTGXO4.js.map +0 -1
- package/dist/cli/chunk-6MZTZO7A.js.map +0 -1
- package/dist/cli/chunk-B5CZL2SE.js.map +0 -1
- package/dist/cli/chunk-CDVSFSAK.js.map +0 -1
- package/dist/cli/chunk-FY4S7TJZ.js.map +0 -1
- package/dist/cli/chunk-NMQSUNLB.js.map +0 -1
- package/dist/cli/chunk-OB4BUJBL.js.map +0 -1
- package/dist/cli/chunk-OPYALNTT.js.map +0 -1
- package/dist/cli/chunk-S2RMQULY.js.map +0 -1
- package/dist/cli/chunk-TE5UIIFL.js.map +0 -1
- package/dist/cli/chunk-TKVXTQ3T.js.map +0 -1
- package/dist/cli/chunk-WZGNXR6E.js +0 -2020
- package/dist/cli/chunk-WZGNXR6E.js.map +0 -1
- package/dist/cli/chunk-YW63N3ZR.js.map +0 -1
- package/dist/cli/desktop-562OPWIU.js.map +0 -1
- package/dist/cli/mcp-7W7ANO2Y.js.map +0 -1
- package/dist/cli/prune-sessions-SEWX7GP6.js.map +0 -1
- package/dist/cli/run-TPKXIJ27.js.map +0 -1
- package/dist/cli/server-NHQ3QXOZ.js.map +0 -1
- package/dist/cli/sessions-2A4DGSHA.js.map +0 -1
- /package/dist/cli/{chat-GZNB5625.js.map → chat-D32JGNVH.js.map} +0 -0
- /package/dist/cli/{chunk-5OHHAQ4W.js.map → chunk-7AST3QQ3.js.map} +0 -0
- /package/dist/cli/{chunk-MRZG4GBF.js.map → chunk-7JTKBJ2G.js.map} +0 -0
- /package/dist/cli/{chunk-MOJYKO2A.js.map → chunk-ASOLXV67.js.map} +0 -0
- /package/dist/cli/{chunk-HR5NBKEM.js.map → chunk-DFX5ZH5L.js.map} +0 -0
- /package/dist/cli/{chunk-I4M5QJNL.js.map → chunk-JGTX4RRQ.js.map} +0 -0
- /package/dist/cli/{chunk-H4CCXMDD.js.map → chunk-PEMG6CUB.js.map} +0 -0
- /package/dist/cli/{chunk-RUDBUHO4.js.map → chunk-PXBQ6IZ7.js.map} +0 -0
- /package/dist/cli/{chunk-OG5JANQ4.js.map → chunk-QX5TWXRZ.js.map} +0 -0
- /package/dist/cli/{chunk-V4Y732RQ.js.map → chunk-TAIKVL35.js.map} +0 -0
- /package/dist/cli/{chunk-EMMENC4O.js.map → chunk-U5XQDCK7.js.map} +0 -0
- /package/dist/cli/{chunk-DOWEOA6E.js.map → chunk-W46ZMNKO.js.map} +0 -0
- /package/dist/cli/{chunk-JMDE6IO3.js.map → chunk-ZAEJWKXB.js.map} +0 -0
- /package/dist/cli/{code-PMPJWXEO.js.map → code-R4IHI7SR.js.map} +0 -0
- /package/dist/cli/{commands-QS6TG4G3.js.map → commands-DRHFCYMO.js.map} +0 -0
- /package/dist/cli/{commit-XPRSKUBF.js.map → commit-AG5KB4YP.js.map} +0 -0
- /package/dist/cli/{diff-I6W4AUWJ.js.map → diff-4Z7ETWZO.js.map} +0 -0
- /package/dist/cli/{doctor-6XVZKT4U.js.map → doctor-VA3RHQLB.js.map} +0 -0
- /package/dist/cli/{mcp-browse-LA4I4YIZ.js.map → mcp-browse-C3GXVMYZ.js.map} +0 -0
- /package/dist/cli/{mcp-inspect-LWXXU7BY.js.map → mcp-inspect-ZMYUNFDS.js.map} +0 -0
- /package/dist/cli/{prompt-RKZD4X6Y.js.map → prompt-MC3U5KRP.js.map} +0 -0
- /package/dist/cli/{replay-2X7MVXOI.js.map → replay-4TP7ZUMZ.js.map} +0 -0
- /package/dist/cli/{setup-GOLP7J4C.js.map → setup-LHZELI6I.js.map} +0 -0
- /package/dist/cli/{stats-CGDAFDKI.js.map → stats-SUIJ3QWY.js.map} +0 -0
- /package/dist/cli/{version-FIL4ZFOS.js.map → version-BIFONEUB.js.map} +0 -0
|
@@ -2,15 +2,15 @@
|
|
|
2
2
|
import { createRequire as __cr } from 'node:module'; if (typeof globalThis.require === 'undefined') { globalThis.require = __cr(import.meta.url); }
|
|
3
3
|
import {
|
|
4
4
|
buildCodeToolset
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-AWEULQG6.js";
|
|
6
6
|
import {
|
|
7
7
|
Eventizer,
|
|
8
8
|
autoResolveVerdict
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-MGTBP7GG.js";
|
|
10
10
|
import {
|
|
11
11
|
formatMcpLifecycleEvent,
|
|
12
12
|
formatMcpSlowToast
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-GNS7BAT2.js";
|
|
14
14
|
import {
|
|
15
15
|
buildTransportFromSpec,
|
|
16
16
|
preflightStdioSpec
|
|
@@ -19,19 +19,19 @@ import {
|
|
|
19
19
|
CacheFirstLoop,
|
|
20
20
|
ImmutablePrefix,
|
|
21
21
|
bridgeMcpTools
|
|
22
|
-
} from "./chunk-
|
|
23
|
-
import "./chunk-
|
|
22
|
+
} from "./chunk-MQWO32ZD.js";
|
|
23
|
+
import "./chunk-7AST3QQ3.js";
|
|
24
24
|
import {
|
|
25
25
|
openTranscriptFile,
|
|
26
26
|
recordFromLoopEvent,
|
|
27
27
|
writeRecord
|
|
28
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-7JTKBJ2G.js";
|
|
29
29
|
import {
|
|
30
30
|
McpClient
|
|
31
31
|
} from "./chunk-HIYTRCSW.js";
|
|
32
32
|
import {
|
|
33
33
|
codeSystemPrompt
|
|
34
|
-
} from "./chunk-
|
|
34
|
+
} from "./chunk-O5LIHAMP.js";
|
|
35
35
|
import {
|
|
36
36
|
canonicalPresetName,
|
|
37
37
|
resolvePreset
|
|
@@ -39,30 +39,31 @@ import {
|
|
|
39
39
|
import "./chunk-6OWJV3YW.js";
|
|
40
40
|
import {
|
|
41
41
|
DeepSeekClient
|
|
42
|
-
} from "./chunk-
|
|
42
|
+
} from "./chunk-J2IHQGPQ.js";
|
|
43
43
|
import "./chunk-25T6CVUP.js";
|
|
44
44
|
import {
|
|
45
45
|
loadDotenv
|
|
46
46
|
} from "./chunk-2UQP6H6T.js";
|
|
47
|
-
import "./chunk-
|
|
47
|
+
import "./chunk-TAIKVL35.js";
|
|
48
48
|
import {
|
|
49
|
-
derivePrefix,
|
|
50
49
|
pauseGate,
|
|
50
|
+
resolveApprovalPrompt,
|
|
51
|
+
toApprovalPrompt,
|
|
51
52
|
toolKindFor
|
|
52
|
-
} from "./chunk-
|
|
53
|
-
import "./chunk-
|
|
53
|
+
} from "./chunk-ZWHSHFDP.js";
|
|
54
|
+
import "./chunk-JNTMOX7G.js";
|
|
54
55
|
import "./chunk-PLHAZOLZ.js";
|
|
55
|
-
import "./chunk-
|
|
56
|
-
import "./chunk-
|
|
56
|
+
import "./chunk-DFX5ZH5L.js";
|
|
57
|
+
import "./chunk-PB3MAFEI.js";
|
|
57
58
|
import "./chunk-S4XVGLRW.js";
|
|
58
59
|
import {
|
|
59
60
|
timestampSuffix
|
|
60
61
|
} from "./chunk-RRXUIPWG.js";
|
|
61
|
-
import "./chunk-
|
|
62
|
-
import "./chunk-
|
|
62
|
+
import "./chunk-ZAEJWKXB.js";
|
|
63
|
+
import "./chunk-QX5TWXRZ.js";
|
|
63
64
|
import {
|
|
64
65
|
t
|
|
65
|
-
} from "./chunk-
|
|
66
|
+
} from "./chunk-YEF7C4XI.js";
|
|
66
67
|
import {
|
|
67
68
|
loadApiKey,
|
|
68
69
|
loadBaseUrl,
|
|
@@ -71,7 +72,7 @@ import {
|
|
|
71
72
|
loadReasoningEffort,
|
|
72
73
|
normalizeMcpConfig,
|
|
73
74
|
readConfig
|
|
74
|
-
} from "./chunk-
|
|
75
|
+
} from "./chunk-WMTMMSXU.js";
|
|
75
76
|
import {
|
|
76
77
|
VERSION
|
|
77
78
|
} from "./chunk-XXC2BYTV.js";
|
|
@@ -172,133 +173,46 @@ function emit(server, params) {
|
|
|
172
173
|
}
|
|
173
174
|
|
|
174
175
|
// src/acp/gates.ts
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
function permissionOptionsFor(req) {
|
|
184
|
-
switch (req.kind) {
|
|
185
|
-
case "run_command":
|
|
186
|
-
case "run_background":
|
|
187
|
-
case "path_access":
|
|
188
|
-
return [
|
|
189
|
-
{ optionId: ID_ALLOW_ONCE, name: "Allow once", kind: "allow_once" },
|
|
190
|
-
{ optionId: ID_ALLOW_ALWAYS, name: "Allow always", kind: "allow_always" },
|
|
191
|
-
{ optionId: ID_REJECT, name: "Reject", kind: "reject_once" }
|
|
192
|
-
];
|
|
193
|
-
case "plan_proposed":
|
|
194
|
-
return [
|
|
195
|
-
{ optionId: ID_ALLOW_ONCE, name: "Approve plan", kind: "allow_once" },
|
|
196
|
-
{ optionId: ID_REFINE, name: "Refine", kind: "allow_once" },
|
|
197
|
-
{ optionId: ID_CANCEL, name: "Cancel", kind: "reject_once" }
|
|
198
|
-
];
|
|
199
|
-
case "plan_checkpoint":
|
|
200
|
-
return [
|
|
201
|
-
{ optionId: ID_ALLOW_ONCE, name: "Continue", kind: "allow_once" },
|
|
202
|
-
{ optionId: ID_REVISE, name: "Revise", kind: "allow_once" },
|
|
203
|
-
{ optionId: ID_STOP, name: "Stop", kind: "reject_once" }
|
|
204
|
-
];
|
|
205
|
-
case "plan_revision":
|
|
206
|
-
return [
|
|
207
|
-
{ optionId: ID_ACCEPT, name: "Accept revision", kind: "allow_once" },
|
|
208
|
-
{ optionId: ID_REJECT, name: "Keep original plan", kind: "reject_once" }
|
|
209
|
-
];
|
|
210
|
-
case "choice": {
|
|
211
|
-
const payload = req.payload;
|
|
212
|
-
const opts = (payload.options ?? []).map((o) => ({
|
|
213
|
-
optionId: o.id,
|
|
214
|
-
name: o.title ?? o.id,
|
|
215
|
-
kind: "allow_once"
|
|
216
|
-
}));
|
|
217
|
-
opts.push({ optionId: ID_CANCEL, name: "Cancel", kind: "reject_once" });
|
|
218
|
-
return opts;
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
function pathPrefix(p) {
|
|
223
|
-
return p;
|
|
224
|
-
}
|
|
225
|
-
function verdictFor(req, result) {
|
|
226
|
-
const cancelled = result.outcome.outcome === "cancelled";
|
|
227
|
-
const optionId = result.outcome.outcome === "selected" ? result.outcome.optionId : null;
|
|
228
|
-
switch (req.kind) {
|
|
229
|
-
case "run_command":
|
|
230
|
-
case "run_background": {
|
|
231
|
-
if (cancelled || optionId === ID_REJECT) return { type: "deny" };
|
|
232
|
-
if (optionId === ID_ALLOW_ALWAYS) {
|
|
233
|
-
const payload = req.payload;
|
|
234
|
-
return { type: "always_allow", prefix: derivePrefix(payload.command ?? "") };
|
|
235
|
-
}
|
|
236
|
-
return { type: "run_once" };
|
|
237
|
-
}
|
|
238
|
-
case "path_access": {
|
|
239
|
-
if (cancelled || optionId === ID_REJECT) return { type: "deny" };
|
|
240
|
-
if (optionId === ID_ALLOW_ALWAYS) {
|
|
241
|
-
const payload = req.payload;
|
|
242
|
-
return { type: "always_allow", prefix: pathPrefix(payload.allowPrefix) };
|
|
243
|
-
}
|
|
244
|
-
return { type: "run_once" };
|
|
245
|
-
}
|
|
246
|
-
case "plan_proposed": {
|
|
247
|
-
if (cancelled || optionId === ID_CANCEL) return { type: "cancel" };
|
|
248
|
-
if (optionId === ID_REFINE) return { type: "refine" };
|
|
249
|
-
return { type: "approve" };
|
|
250
|
-
}
|
|
251
|
-
case "plan_checkpoint": {
|
|
252
|
-
if (cancelled || optionId === ID_STOP) return { type: "stop" };
|
|
253
|
-
if (optionId === ID_REVISE) return { type: "revise" };
|
|
254
|
-
return { type: "continue" };
|
|
255
|
-
}
|
|
256
|
-
case "plan_revision": {
|
|
257
|
-
if (cancelled) return { type: "cancelled" };
|
|
258
|
-
if (optionId === ID_ACCEPT) return { type: "accepted" };
|
|
259
|
-
return { type: "rejected" };
|
|
260
|
-
}
|
|
261
|
-
case "choice": {
|
|
262
|
-
if (cancelled || optionId === ID_CANCEL || !optionId) return { type: "cancel" };
|
|
263
|
-
return { type: "pick", optionId };
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
function permissionTitleFor(req) {
|
|
268
|
-
switch (req.kind) {
|
|
269
|
-
case "run_command":
|
|
270
|
-
case "run_background":
|
|
271
|
-
return `Run command \u2014 ${(req.payload.command ?? "").slice(0, 80)}`;
|
|
272
|
-
case "path_access":
|
|
273
|
-
return `Access path \u2014 ${req.payload.path}`;
|
|
274
|
-
case "plan_proposed":
|
|
275
|
-
return "Approve plan";
|
|
276
|
-
case "plan_checkpoint":
|
|
277
|
-
return `Checkpoint \u2014 ${req.payload.title ?? "step complete"}`;
|
|
278
|
-
case "plan_revision":
|
|
279
|
-
return "Approve plan revision";
|
|
280
|
-
case "choice":
|
|
281
|
-
return req.payload.question ?? "Choose an option";
|
|
176
|
+
function acpPermissionKindFor(prompt) {
|
|
177
|
+
switch (prompt.kind) {
|
|
178
|
+
case "shell":
|
|
179
|
+
return "execute";
|
|
180
|
+
case "path":
|
|
181
|
+
return prompt.data?.intent === "write" ? "edit" : "other";
|
|
182
|
+
default:
|
|
183
|
+
return "other";
|
|
282
184
|
}
|
|
283
185
|
}
|
|
284
|
-
function
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
186
|
+
function acpOptionKindFor(kind) {
|
|
187
|
+
switch (kind) {
|
|
188
|
+
case "allow_once":
|
|
189
|
+
return "allow_once";
|
|
190
|
+
case "allow_always":
|
|
191
|
+
return "allow_always";
|
|
192
|
+
case "reject":
|
|
193
|
+
return "reject_once";
|
|
194
|
+
case "custom":
|
|
195
|
+
return "allow_once";
|
|
288
196
|
}
|
|
289
|
-
return "other";
|
|
290
197
|
}
|
|
291
198
|
async function requestPermissionForGate(server, sessionId, req) {
|
|
199
|
+
const prompt = toApprovalPrompt(req);
|
|
292
200
|
const params = {
|
|
293
201
|
sessionId,
|
|
294
202
|
toolCall: {
|
|
295
203
|
toolCallId: `gate-${req.id}`,
|
|
296
|
-
title:
|
|
297
|
-
kind:
|
|
204
|
+
title: prompt.title,
|
|
205
|
+
kind: acpPermissionKindFor(prompt),
|
|
298
206
|
status: "pending",
|
|
299
207
|
rawInput: req.payload
|
|
300
208
|
},
|
|
301
|
-
options:
|
|
209
|
+
options: prompt.actions.map(
|
|
210
|
+
(a) => ({
|
|
211
|
+
optionId: a.id,
|
|
212
|
+
name: a.label,
|
|
213
|
+
kind: acpOptionKindFor(a.kind)
|
|
214
|
+
})
|
|
215
|
+
)
|
|
302
216
|
};
|
|
303
217
|
let result;
|
|
304
218
|
try {
|
|
@@ -309,7 +223,10 @@ async function requestPermissionForGate(server, sessionId, req) {
|
|
|
309
223
|
} catch {
|
|
310
224
|
result = { outcome: { outcome: "cancelled" } };
|
|
311
225
|
}
|
|
312
|
-
|
|
226
|
+
if (result.outcome.outcome === "cancelled") {
|
|
227
|
+
return resolveApprovalPrompt(prompt, "");
|
|
228
|
+
}
|
|
229
|
+
return resolveApprovalPrompt(prompt, result.outcome.optionId);
|
|
313
230
|
}
|
|
314
231
|
|
|
315
232
|
// src/acp/protocol.ts
|
|
@@ -680,4 +597,4 @@ export {
|
|
|
680
597
|
acpCommand,
|
|
681
598
|
loadMcpServers
|
|
682
599
|
};
|
|
683
|
-
//# sourceMappingURL=acp-
|
|
600
|
+
//# sourceMappingURL=acp-WFQIC6SO.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/cli/commands/acp.ts","../../src/acp/dispatch.ts","../../src/acp/gates.ts","../../src/acp/protocol.ts","../../src/acp/server.ts"],"sourcesContent":["/** ACP (Agent Client Protocol) agent — drives the cache-first loop over stdio NDJSON JSON-RPC. */\n\nimport { AsyncLocalStorage } from \"node:async_hooks\";\nimport { type WriteStream, existsSync, statSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { dispatchKernelEvent } from \"../../acp/dispatch.js\";\nimport { requestPermissionForGate } from \"../../acp/gates.js\";\nimport {\n ACP_PROTOCOL_VERSION,\n type ContentBlock,\n ERR_INVALID_PARAMS,\n type InitializeParams,\n type InitializeResult,\n type SessionCancelParams,\n type SessionNewParams,\n type SessionNewResult,\n type SessionPromptParams,\n type SessionPromptResult,\n type SessionUpdateParams,\n type StopReason,\n flattenPrompt,\n} from \"../../acp/protocol.js\";\nimport { AcpServer } from \"../../acp/server.js\";\nimport { codeSystemPrompt } from \"../../code/prompt.js\";\nimport { buildCodeToolset } from \"../../code/setup.js\";\nimport {\n loadApiKey,\n loadBaseUrl,\n loadPreset,\n loadReasoningEffort,\n normalizeMcpConfig,\n readConfig,\n} from \"../../config.js\";\nimport { loadEditMode } from \"../../config.js\";\nimport { Eventizer } from \"../../core/eventize.js\";\nimport { pauseGate } from \"../../core/pause-gate.js\";\nimport { autoResolveVerdict } from \"../../core/pause-policy.js\";\nimport { loadDotenv } from \"../../env.js\";\nimport { t } from \"../../i18n/index.js\";\nimport { CacheFirstLoop, DeepSeekClient, ImmutablePrefix } from \"../../index.js\";\nimport { McpClient } from \"../../mcp/client.js\";\nimport { preflightStdioSpec } from \"../../mcp/preflight.js\";\nimport { bridgeMcpTools } from \"../../mcp/registry.js\";\nimport { buildTransportFromSpec } from \"../../mcp/transport-from-spec.js\";\nimport { timestampSuffix } from \"../../memory/session.js\";\nimport { openTranscriptFile, recordFromLoopEvent, writeRecord } from \"../../transcript/log.js\";\nimport { VERSION } from \"../../version.js\";\nimport { formatMcpLifecycleEvent } from \"../ui/mcp-lifecycle.js\";\nimport { formatMcpSlowToast } from \"../ui/mcp-toast.js\";\nimport { canonicalPresetName, resolvePreset } from \"../ui/presets.js\";\n\nexport interface AcpOptions {\n model?: string;\n dir?: string;\n budgetUsd?: number;\n transcript?: string;\n yolo?: boolean;\n /** Zero or more MCP server specs. Each: `\"name=cmd args...\"` or `\"cmd args...\"`. */\n mcpSpecs?: string[];\n /** Global prefix — only honored when a single anonymous server is given. */\n mcpPrefix?: string;\n}\n\ninterface Session {\n id: string;\n rootDir: string;\n model: string;\n toolset: Awaited<ReturnType<typeof buildCodeToolset>>;\n mcpClients: McpClient[];\n loop: CacheFirstLoop;\n eventizer: Eventizer;\n ctx: { model: string; prefixHash: string; reasoningEffort: \"high\" | \"max\" };\n aborter: AbortController | null;\n}\n\nfunction resolveMcpPrefix(\n specName: string | null | undefined,\n specCount: number,\n globalPrefix: string | undefined,\n): string {\n if (specName) return `${specName}_`;\n if (specCount === 1 && globalPrefix) return globalPrefix;\n return \"\";\n}\n\n// Mirrors run.ts:81-142.\nexport async function loadMcpServers(\n tools: import(\"../../tools.js\").ToolRegistry,\n specs: string[],\n globalPrefix: string | undefined,\n): Promise<McpClient[]> {\n const clients: McpClient[] = [];\n if (specs.length === 0) return clients;\n const cfg = readConfig();\n const normalizedSpecs = normalizeMcpConfig(cfg, specs);\n for (const spec of normalizedSpecs) {\n let label = \"anon\";\n let mcp: McpClient | undefined;\n try {\n label = spec.name ?? \"anon\";\n if (spec.disabled) {\n process.stderr.write(`${formatMcpLifecycleEvent({ state: \"disabled\", name: label })}\\n`);\n continue;\n }\n process.stderr.write(`${formatMcpLifecycleEvent({ state: \"handshake\", name: label })}\\n`);\n const t0 = Date.now();\n const prefix = resolveMcpPrefix(spec.name, normalizedSpecs.length, globalPrefix);\n if (spec.transport === \"stdio\") preflightStdioSpec(spec);\n const transport = buildTransportFromSpec(spec);\n mcp = new McpClient({ transport });\n await mcp.initialize();\n const bridge = await bridgeMcpTools(mcp, {\n registry: tools,\n namePrefix: prefix,\n serverName: label,\n onSlow: (info) =>\n process.stderr.write(\n `${formatMcpSlowToast({ name: info.serverName, p95Ms: info.p95Ms, sampleSize: info.sampleSize })}\\n`,\n ),\n });\n process.stderr.write(\n `${formatMcpLifecycleEvent({\n state: \"connected\",\n name: label,\n tools: bridge.registeredNames.length,\n ms: Date.now() - t0,\n })}\\n`,\n );\n clients.push(mcp);\n } catch (err) {\n await mcp?.close().catch(() => undefined);\n process.stderr.write(\n `${formatMcpLifecycleEvent({ state: \"failed\", name: label, reason: (err as Error).message })}\\n → ${t(\"mcpLifecycle.failedSetupConfigHint\")}\\n`,\n );\n }\n }\n return clients;\n}\n\nfunction resolveDir(raw: string | undefined, fallback: string): string {\n if (!raw) return fallback;\n const abs = resolve(raw);\n if (!existsSync(abs) || !statSync(abs).isDirectory()) {\n throw new Error(`workspace directory not found: ${abs}`);\n }\n return abs;\n}\n\nasync function buildSession(opts: {\n rootDir: string;\n modelOverride?: string;\n budgetUsd?: number;\n mcpSpecs?: string[];\n mcpPrefix?: string;\n}): Promise<Session> {\n const preset = canonicalPresetName(loadPreset());\n const resolved = resolvePreset(preset);\n const model = opts.modelOverride || resolved.model;\n const toolset = await buildCodeToolset({ rootDir: opts.rootDir });\n // Bridge MCP tools BEFORE building the prefix so their specs make it into the cache key.\n const mcpClients = await loadMcpServers(toolset.tools, opts.mcpSpecs ?? [], opts.mcpPrefix);\n const system = codeSystemPrompt(opts.rootDir, {\n hasSemanticSearch: toolset.semantic.enabled,\n modelId: model,\n });\n const client = new DeepSeekClient({ baseUrl: loadBaseUrl() });\n const prefix = new ImmutablePrefix({ system, toolSpecs: toolset.tools.specs() });\n const loop = new CacheFirstLoop({\n client,\n prefix,\n tools: toolset.tools,\n model,\n budgetUsd: opts.budgetUsd,\n session: `acp-${timestampSuffix()}`,\n });\n return {\n id: `sess_${timestampSuffix()}-${Math.random().toString(36).slice(2, 8)}`,\n rootDir: opts.rootDir,\n model,\n toolset,\n mcpClients,\n loop,\n eventizer: new Eventizer(),\n ctx: {\n model,\n prefixHash: prefix.fingerprint,\n reasoningEffort: loadReasoningEffort(),\n },\n aborter: null,\n };\n}\n\nexport async function acpCommand(opts: AcpOptions): Promise<void> {\n loadDotenv();\n if (loadApiKey()) {\n process.env.DEEPSEEK_API_KEY = loadApiKey();\n }\n\n const defaultDir = resolveDir(opts.dir, process.cwd());\n const sessions = new Map<string, Session>();\n const sessionContext = new AsyncLocalStorage<string>();\n const server = new AcpServer();\n\n let transcriptStream: WriteStream | null = null;\n if (opts.transcript) {\n const defaultModel = opts.model || resolvePreset(canonicalPresetName(loadPreset())).model;\n transcriptStream = openTranscriptFile(opts.transcript, {\n version: 1,\n source: \"reasonix acp\",\n model: defaultModel,\n startedAt: new Date().toISOString(),\n });\n }\n\n pauseGate.on((req) => {\n const editMode = opts.yolo ? \"yolo\" : loadEditMode();\n const auto = autoResolveVerdict(req, editMode);\n if (auto !== null) {\n pauseGate.resolve(req.id, auto);\n return;\n }\n const activeSessionId = sessionContext.getStore();\n if (!activeSessionId || !sessions.has(activeSessionId)) {\n pauseGate.cancel(req.id);\n return;\n }\n void (async () => {\n const verdict = await requestPermissionForGate(server, activeSessionId, req);\n pauseGate.resolve(req.id, verdict);\n })();\n });\n\n server.onRequest<InitializeParams, InitializeResult>(\"initialize\", (params) => {\n if (!params || typeof params !== \"object\") {\n throw Object.assign(new Error(\"initialize: missing params\"), { code: ERR_INVALID_PARAMS });\n }\n return {\n protocolVersion: ACP_PROTOCOL_VERSION,\n agentCapabilities: {\n loadSession: false,\n promptCapabilities: { image: false, audio: false, embeddedContext: true },\n mcpCapabilities: { http: false, sse: false },\n },\n agentInfo: { name: \"reasonix\", title: \"Reasonix\", version: VERSION },\n authMethods: [],\n };\n });\n\n server.onRequest<SessionNewParams, SessionNewResult>(\"session/new\", async (params) => {\n const rootDir = resolveDir(params?.cwd, defaultDir);\n const session = await buildSession({\n rootDir,\n modelOverride: opts.model,\n budgetUsd: opts.budgetUsd,\n mcpSpecs: opts.mcpSpecs,\n mcpPrefix: opts.mcpPrefix,\n });\n sessions.set(session.id, session);\n return { sessionId: session.id };\n });\n\n server.onRequest<SessionPromptParams, SessionPromptResult>(\"session/prompt\", async (params) => {\n if (!params?.sessionId) {\n throw Object.assign(new Error(\"session/prompt: missing sessionId\"), {\n code: ERR_INVALID_PARAMS,\n });\n }\n const session = sessions.get(params.sessionId);\n if (!session) {\n throw Object.assign(new Error(`session/prompt: unknown session ${params.sessionId}`), {\n code: ERR_INVALID_PARAMS,\n });\n }\n const text = flattenPrompt(params.prompt as ContentBlock[]);\n if (!text) {\n throw Object.assign(new Error(\"session/prompt: empty prompt\"), { code: ERR_INVALID_PARAMS });\n }\n session.aborter = new AbortController();\n let stopReason: StopReason = \"end_turn\";\n try {\n await sessionContext.run(session.id, async () => {\n for await (const ev of session.loop.step(text)) {\n if (session.aborter?.signal.aborted) {\n stopReason = \"cancelled\";\n break;\n }\n // transcript needs raw LoopEvent (usage/cost/stats); kernel events lose those fields\n if (transcriptStream) {\n writeRecord(\n transcriptStream,\n recordFromLoopEvent(ev, {\n model: session.ctx.model,\n prefixHash: session.ctx.prefixHash,\n }),\n );\n }\n for (const kev of session.eventizer.consume(ev, session.ctx)) {\n dispatchKernelEvent(server, session.id, kev);\n if (kev.type === \"error\") stopReason = \"error\";\n }\n }\n });\n } catch (err) {\n const message = (err as Error).message;\n server.sendNotification(\"session/update\", {\n sessionId: session.id,\n update: {\n sessionUpdate: \"agent_message_chunk\",\n content: { type: \"text\", text: `\\n\\n[error] ${message}` },\n },\n } satisfies SessionUpdateParams);\n stopReason = \"error\";\n } finally {\n session.aborter = null;\n }\n return { stopReason };\n });\n\n server.onNotification<SessionCancelParams>(\"session/cancel\", (params) => {\n const session = params?.sessionId ? sessions.get(params.sessionId) : undefined;\n session?.aborter?.abort();\n });\n\n try {\n await server.done();\n } finally {\n transcriptStream?.end();\n // Tear down MCP children so spawned servers don't outlive the agent.\n const closes: Promise<unknown>[] = [];\n for (const session of sessions.values()) {\n for (const mcp of session.mcpClients) {\n closes.push(mcp.close().catch(() => undefined));\n }\n }\n await Promise.all(closes);\n }\n}\n","/** Map kernel events (model.delta / tool.preparing|intent|result) to ACP session/update notifications. */\n\nimport { toolKindFor } from \"@reasonix/core-utils\";\nimport type { Event as KernelEvent } from \"../core/events.js\";\nimport type { SessionUpdateParams } from \"./protocol.js\";\nimport type { AcpServer } from \"./server.js\";\nexport { toolKindFor } from \"@reasonix/core-utils\";\nexport type { AcpToolKind } from \"@reasonix/core-utils\";\n\nfunction tryParseJson(raw: string): unknown {\n if (!raw) return undefined;\n try {\n return JSON.parse(raw);\n } catch {\n return raw;\n }\n}\n\n/** Stateless mapping from one kernel event to (zero or more) ACP session/update notifications. */\nexport function dispatchKernelEvent(server: AcpServer, sessionId: string, ev: KernelEvent): void {\n switch (ev.type) {\n case \"model.delta\": {\n if (!ev.text) return;\n const variant = ev.channel === \"reasoning\" ? \"agent_thought_chunk\" : \"agent_message_chunk\";\n emit(server, {\n sessionId,\n update: { sessionUpdate: variant, content: { type: \"text\", text: ev.text } },\n });\n return;\n }\n case \"tool.preparing\": {\n emit(server, {\n sessionId,\n update: {\n sessionUpdate: \"tool_call\",\n toolCallId: ev.callId,\n title: ev.name,\n kind: toolKindFor(ev.name),\n status: \"pending\",\n },\n });\n return;\n }\n case \"tool.intent\": {\n emit(server, {\n sessionId,\n update: {\n sessionUpdate: \"tool_call_update\",\n toolCallId: ev.callId,\n status: \"in_progress\",\n },\n });\n const rawInput = tryParseJson(ev.args);\n if (rawInput !== undefined) {\n emit(server, {\n sessionId,\n update: {\n sessionUpdate: \"tool_call\",\n toolCallId: ev.callId,\n title: ev.name,\n kind: toolKindFor(ev.name),\n status: \"in_progress\",\n rawInput,\n },\n });\n }\n return;\n }\n case \"tool.result\": {\n emit(server, {\n sessionId,\n update: {\n sessionUpdate: \"tool_call_update\",\n toolCallId: ev.callId,\n status: ev.ok ? \"completed\" : \"failed\",\n content: [\n {\n type: \"content\",\n content: { type: \"text\", text: clip(ev.output) },\n },\n ],\n },\n });\n return;\n }\n default:\n return;\n }\n}\n\nconst MAX_RESULT_CHARS = 8000;\nfunction clip(text: string): string {\n if (text.length <= MAX_RESULT_CHARS) return text;\n return `${text.slice(0, MAX_RESULT_CHARS)}\\n…(${text.length - MAX_RESULT_CHARS} more chars truncated)`;\n}\n\nfunction emit(server: AcpServer, params: SessionUpdateParams): void {\n server.sendNotification(\"session/update\", params);\n}\n","/** Bridges Reasonix's internal `PauseGate` requests onto ACP `session/request_permission` round-trips. */\n\nimport { resolveApprovalPrompt, toApprovalPrompt } from \"@reasonix/core-utils\";\nimport type { PauseRequest } from \"../core/pause-gate.js\";\nimport type {\n PermissionOption,\n PermissionRequestParams,\n PermissionRequestResult,\n} from \"./protocol.js\";\nimport type { AcpServer } from \"./server.js\";\n\n/** Map an ApprovalPrompt kind to the ACP permission kind used by the host UI. */\nfunction acpPermissionKindFor(\n prompt: ReturnType<typeof toApprovalPrompt>,\n): \"execute\" | \"edit\" | \"other\" {\n switch (prompt.kind) {\n case \"shell\":\n return \"execute\";\n case \"path\":\n return prompt.data?.intent === \"write\" ? \"edit\" : \"other\";\n default:\n return \"other\";\n }\n}\n\n/** Map an ApprovalAction kind to the ACP PermissionOptionKind.\n * \"custom\" actions are treated as one-shot allows on the ACP wire. */\nfunction acpOptionKindFor(\n kind: ReturnType<typeof toApprovalPrompt>[\"actions\"][number][\"kind\"],\n): PermissionOption[\"kind\"] {\n switch (kind) {\n case \"allow_once\":\n return \"allow_once\";\n case \"allow_always\":\n return \"allow_always\";\n case \"reject\":\n return \"reject_once\";\n case \"custom\":\n return \"allow_once\";\n }\n}\n\n/** Forward a PauseGate request as an ACP `session/request_permission` call.\n * Uses `toApprovalPrompt()` as the single source of truth for UI metadata.\n */\nexport async function requestPermissionForGate(\n server: AcpServer,\n sessionId: string,\n req: PauseRequest,\n): Promise<\n | import(\"@reasonix/core-utils\").ConfirmationChoice\n | import(\"@reasonix/core-utils\").PlanVerdict\n | import(\"@reasonix/core-utils\").CheckpointVerdict\n | import(\"@reasonix/core-utils\").RevisionVerdict\n | import(\"@reasonix/core-utils\").ChoiceVerdict\n> {\n const prompt = toApprovalPrompt(req);\n\n const params: PermissionRequestParams = {\n sessionId,\n toolCall: {\n toolCallId: `gate-${req.id}`,\n title: prompt.title,\n kind: acpPermissionKindFor(prompt),\n status: \"pending\",\n rawInput: req.payload,\n },\n options: prompt.actions.map(\n (a): PermissionOption => ({\n optionId: a.id,\n name: a.label,\n kind: acpOptionKindFor(a.kind),\n }),\n ),\n };\n\n let result: PermissionRequestResult;\n try {\n result = await server.sendRequest<PermissionRequestResult>(\n \"session/request_permission\",\n params,\n );\n } catch {\n result = { outcome: { outcome: \"cancelled\" } };\n }\n\n if (result.outcome.outcome === \"cancelled\") {\n return resolveApprovalPrompt(prompt, \"\");\n }\n\n return resolveApprovalPrompt(prompt, result.outcome.optionId);\n}\n","/** Wire types for the Agent Client Protocol — https://agentclientprotocol.com */\n\nexport const ACP_PROTOCOL_VERSION = 1;\n\nexport type JsonRpcId = string | number;\n\nexport interface JsonRpcRequest<P = unknown> {\n jsonrpc: \"2.0\";\n id: JsonRpcId;\n method: string;\n params?: P;\n}\n\nexport interface JsonRpcNotification<P = unknown> {\n jsonrpc: \"2.0\";\n method: string;\n params?: P;\n}\n\nexport interface JsonRpcError {\n code: number;\n message: string;\n data?: unknown;\n}\n\nexport interface JsonRpcResponse<R = unknown> {\n jsonrpc: \"2.0\";\n id: JsonRpcId | null;\n result?: R;\n error?: JsonRpcError;\n}\n\nexport interface InitializeParams {\n protocolVersion: number;\n clientCapabilities?: {\n fs?: { readTextFile?: boolean; writeTextFile?: boolean };\n terminal?: boolean;\n };\n clientInfo?: { name: string; title?: string; version?: string };\n}\n\nexport interface InitializeResult {\n protocolVersion: number;\n agentCapabilities: {\n loadSession?: boolean;\n promptCapabilities?: { image?: boolean; audio?: boolean; embeddedContext?: boolean };\n mcpCapabilities?: { http?: boolean; sse?: boolean };\n };\n agentInfo: { name: string; title?: string; version: string };\n authMethods: never[];\n}\n\nexport interface SessionNewParams {\n cwd?: string;\n mcpServers?: Array<{\n name: string;\n command?: string;\n args?: string[];\n env?: Record<string, string>;\n }>;\n}\n\nexport interface SessionNewResult {\n sessionId: string;\n}\n\nexport type ContentBlock =\n | { type: \"text\"; text: string }\n | { type: \"resource\"; resource: { uri: string; mimeType?: string; text?: string } }\n | { type: \"image\"; mimeType: string; data: string }\n | { type: \"audio\"; mimeType: string; data: string };\n\nexport interface SessionPromptParams {\n sessionId: string;\n prompt: ContentBlock[];\n}\n\nexport type StopReason = \"end_turn\" | \"tool_use_complete\" | \"cancelled\" | \"error\";\n\nexport interface SessionPromptResult {\n stopReason: StopReason;\n}\n\nexport type SessionUpdate =\n | {\n sessionUpdate: \"agent_message_chunk\";\n content: { type: \"text\"; text: string };\n }\n | {\n sessionUpdate: \"agent_thought_chunk\";\n content: { type: \"text\"; text: string };\n }\n | {\n sessionUpdate: \"tool_call\";\n toolCallId: string;\n title?: string;\n kind?: \"read\" | \"edit\" | \"search\" | \"execute\" | \"other\";\n status?: \"pending\" | \"in_progress\" | \"completed\" | \"failed\";\n rawInput?: unknown;\n }\n | {\n sessionUpdate: \"tool_call_update\";\n toolCallId: string;\n status?: \"pending\" | \"in_progress\" | \"completed\" | \"failed\";\n content?: Array<{ type: \"content\"; content: { type: \"text\"; text: string } }>;\n }\n | {\n sessionUpdate: \"plan\";\n entries: Array<{\n content: string;\n priority: \"high\" | \"medium\" | \"low\";\n status: \"pending\" | \"in_progress\" | \"completed\";\n }>;\n };\n\nexport interface SessionUpdateParams {\n sessionId: string;\n update: SessionUpdate;\n}\n\nexport interface SessionCancelParams {\n sessionId: string;\n}\n\nexport type PermissionOptionKind = \"allow_once\" | \"allow_always\" | \"reject_once\" | \"reject_always\";\n\nexport interface PermissionOption {\n optionId: string;\n name: string;\n kind: PermissionOptionKind;\n}\n\nexport interface PermissionRequestParams {\n sessionId: string;\n toolCall: {\n toolCallId: string;\n title?: string;\n kind?: \"read\" | \"edit\" | \"search\" | \"execute\" | \"other\";\n status?: \"pending\";\n rawInput?: unknown;\n };\n options: PermissionOption[];\n}\n\nexport type PermissionOutcome =\n | { outcome: \"selected\"; optionId: string }\n | { outcome: \"cancelled\" };\n\nexport interface PermissionRequestResult {\n outcome: PermissionOutcome;\n}\n\nexport const ERR_PARSE = -32700;\nexport const ERR_INVALID_REQUEST = -32600;\nexport const ERR_METHOD_NOT_FOUND = -32601;\nexport const ERR_INVALID_PARAMS = -32602;\nexport const ERR_INTERNAL = -32603;\n\n/** Extract the user prompt text out of ACP content blocks. Resource blocks contribute their inline `text` if present. */\nexport function flattenPrompt(blocks: ContentBlock[]): string {\n const parts: string[] = [];\n for (const b of blocks) {\n if (b.type === \"text\") parts.push(b.text);\n else if (b.type === \"resource\" && b.resource.text) parts.push(b.resource.text);\n }\n return parts.join(\"\\n\\n\").trim();\n}\n","/** NDJSON JSON-RPC 2.0 server — per the ACP transport spec, one JSON object per line, no embedded newlines. */\n\nimport { type Interface, createInterface } from \"node:readline\";\nimport type { Readable, Writable } from \"node:stream\";\nimport {\n ERR_INTERNAL,\n ERR_METHOD_NOT_FOUND,\n ERR_PARSE,\n type JsonRpcId,\n type JsonRpcNotification,\n type JsonRpcRequest,\n type JsonRpcResponse,\n} from \"./protocol.js\";\n\nexport type RequestHandler<P = unknown, R = unknown> = (params: P) => Promise<R> | R;\nexport type NotificationHandler<P = unknown> = (params: P) => Promise<void> | void;\n\nexport interface AcpServerOptions {\n input?: Readable;\n output?: Writable;\n}\n\ninterface PendingOutbound {\n resolve: (value: unknown) => void;\n reject: (err: Error) => void;\n}\n\nexport class AcpServer {\n private requestHandlers = new Map<string, RequestHandler>();\n private notificationHandlers = new Map<string, NotificationHandler>();\n private pending = new Map<JsonRpcId, PendingOutbound>();\n private nextOutboundId = 1;\n private readonly output: Writable;\n private readonly rl: Interface;\n private closed = false;\n\n constructor(opts: AcpServerOptions = {}) {\n this.output = opts.output ?? process.stdout;\n const input = opts.input ?? process.stdin;\n this.rl = createInterface({ input });\n this.rl.on(\"line\", (line) => {\n void this.handleLine(line);\n });\n }\n\n onRequest<P, R>(method: string, handler: RequestHandler<P, R>): void {\n this.requestHandlers.set(method, handler as RequestHandler);\n }\n\n onNotification<P>(method: string, handler: NotificationHandler<P>): void {\n this.notificationHandlers.set(method, handler as NotificationHandler);\n }\n\n sendNotification(method: string, params: unknown): void {\n this.write({ jsonrpc: \"2.0\", method, params });\n }\n\n /** Send an outbound JSON-RPC request and resolve when the peer responds. */\n sendRequest<R = unknown>(method: string, params: unknown): Promise<R> {\n const id = this.nextOutboundId++;\n return new Promise<R>((resolve, reject) => {\n this.pending.set(id, {\n resolve: resolve as (v: unknown) => void,\n reject,\n });\n this.write({ jsonrpc: \"2.0\", id, method, params });\n });\n }\n\n close(): void {\n if (this.closed) return;\n this.closed = true;\n for (const p of this.pending.values()) p.reject(new Error(\"server closed\"));\n this.pending.clear();\n this.rl.close();\n }\n\n /** Wait for the input stream to end. */\n done(): Promise<void> {\n return new Promise((resolve) => this.rl.once(\"close\", () => resolve()));\n }\n\n private write(msg: JsonRpcRequest | JsonRpcNotification | JsonRpcResponse): void {\n this.output.write(`${JSON.stringify(msg)}\\n`);\n }\n\n private writeError(id: JsonRpcId | null, code: number, message: string): void {\n this.write({ jsonrpc: \"2.0\", id, error: { code, message } });\n }\n\n private async handleLine(raw: string): Promise<void> {\n const line = raw.trim();\n if (!line) return;\n let parsed: unknown;\n try {\n parsed = JSON.parse(line);\n } catch {\n this.writeError(null, ERR_PARSE, \"parse error\");\n return;\n }\n if (!parsed || typeof parsed !== \"object\") {\n this.writeError(null, ERR_PARSE, \"expected JSON object\");\n return;\n }\n const msg = parsed as Partial<JsonRpcRequest>;\n if (typeof msg.method === \"string\" && msg.id !== undefined) {\n const id = msg.id as JsonRpcId;\n const handler = this.requestHandlers.get(msg.method);\n if (!handler) {\n this.writeError(id, ERR_METHOD_NOT_FOUND, `method not found: ${msg.method}`);\n return;\n }\n try {\n const result = await handler(msg.params);\n this.write({ jsonrpc: \"2.0\", id, result });\n } catch (err) {\n this.writeError(id, ERR_INTERNAL, (err as Error).message);\n }\n return;\n }\n if (typeof msg.method === \"string\" && msg.id === undefined) {\n const handler = this.notificationHandlers.get(msg.method);\n if (!handler) return;\n try {\n await handler(msg.params);\n } catch {\n // notifications can't be replied to — log channel would help, but stderr would pollute the wire\n }\n return;\n }\n if (msg.id !== undefined && msg.method === undefined) {\n const response = parsed as JsonRpcResponse;\n const pending = this.pending.get(response.id as JsonRpcId);\n if (!pending) return;\n this.pending.delete(response.id as JsonRpcId);\n if (response.error) {\n pending.reject(new Error(response.error.message));\n } else {\n pending.resolve(response.result);\n }\n }\n }\n}\n"],"mappings":"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","names":["resolve"]}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createRequire as __cr } from 'node:module'; if (typeof globalThis.require === 'undefined') { globalThis.require = __cr(import.meta.url); }
|
|
3
|
+
import {
|
|
4
|
+
chatCommand
|
|
5
|
+
} from "./chunk-QF32ROX2.js";
|
|
6
|
+
import "./chunk-3ZZXQ3CZ.js";
|
|
7
|
+
import "./chunk-JMBMLOBP.js";
|
|
8
|
+
import "./chunk-U5XQDCK7.js";
|
|
9
|
+
import "./chunk-MGTBP7GG.js";
|
|
10
|
+
import "./chunk-GNS7BAT2.js";
|
|
11
|
+
import "./chunk-EQATK2L2.js";
|
|
12
|
+
import "./chunk-ZZM6QJ4W.js";
|
|
13
|
+
import "./chunk-MQWO32ZD.js";
|
|
14
|
+
import "./chunk-7AST3QQ3.js";
|
|
15
|
+
import "./chunk-7JTKBJ2G.js";
|
|
16
|
+
import "./chunk-HIYTRCSW.js";
|
|
17
|
+
import "./chunk-O5LIHAMP.js";
|
|
18
|
+
import "./chunk-FEZK652I.js";
|
|
19
|
+
import "./chunk-W46ZMNKO.js";
|
|
20
|
+
import "./chunk-PXBQ6IZ7.js";
|
|
21
|
+
import "./chunk-7X4JJOO7.js";
|
|
22
|
+
import "./chunk-LGEKVMMV.js";
|
|
23
|
+
import "./chunk-23ZPCIPR.js";
|
|
24
|
+
import "./chunk-Q46B3Z7H.js";
|
|
25
|
+
import "./chunk-6OWJV3YW.js";
|
|
26
|
+
import "./chunk-J2IHQGPQ.js";
|
|
27
|
+
import "./chunk-25T6CVUP.js";
|
|
28
|
+
import "./chunk-2UQP6H6T.js";
|
|
29
|
+
import "./chunk-ASOLXV67.js";
|
|
30
|
+
import "./chunk-SZ5XES2N.js";
|
|
31
|
+
import "./chunk-TEDWJKEI.js";
|
|
32
|
+
import "./chunk-E5WCLUIU.js";
|
|
33
|
+
import "./chunk-XJXDHAES.js";
|
|
34
|
+
import "./chunk-ZWHSHFDP.js";
|
|
35
|
+
import "./chunk-JNTMOX7G.js";
|
|
36
|
+
import "./chunk-PLHAZOLZ.js";
|
|
37
|
+
import "./chunk-PEMG6CUB.js";
|
|
38
|
+
import "./chunk-DFX5ZH5L.js";
|
|
39
|
+
import "./chunk-PB3MAFEI.js";
|
|
40
|
+
import "./chunk-S4XVGLRW.js";
|
|
41
|
+
import "./chunk-RRXUIPWG.js";
|
|
42
|
+
import "./chunk-ZAEJWKXB.js";
|
|
43
|
+
import "./chunk-QX5TWXRZ.js";
|
|
44
|
+
import "./chunk-YEF7C4XI.js";
|
|
45
|
+
import "./chunk-WMTMMSXU.js";
|
|
46
|
+
import "./chunk-XXC2BYTV.js";
|
|
47
|
+
import "./chunk-TUK7OWJA.js";
|
|
48
|
+
export {
|
|
49
|
+
chatCommand
|
|
50
|
+
};
|
|
51
|
+
//# sourceMappingURL=chat-D32JGNVH.js.map
|
|
@@ -4,39 +4,39 @@ import {
|
|
|
4
4
|
detectProxyUrl,
|
|
5
5
|
matchesNoProxy,
|
|
6
6
|
resolveNoProxy
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-Q46B3Z7H.js";
|
|
8
8
|
import {
|
|
9
9
|
resolveDataPath
|
|
10
10
|
} from "./chunk-6OWJV3YW.js";
|
|
11
11
|
import {
|
|
12
12
|
DeepSeekClient,
|
|
13
13
|
pickPrimaryBalance
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-J2IHQGPQ.js";
|
|
15
15
|
import {
|
|
16
16
|
loadDotenv
|
|
17
17
|
} from "./chunk-2UQP6H6T.js";
|
|
18
18
|
import {
|
|
19
19
|
checkOllamaStatus
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-PEMG6CUB.js";
|
|
21
21
|
import {
|
|
22
22
|
indexExists
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-DFX5ZH5L.js";
|
|
24
24
|
import {
|
|
25
25
|
loadHooks
|
|
26
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-PB3MAFEI.js";
|
|
27
27
|
import {
|
|
28
28
|
listSessions
|
|
29
29
|
} from "./chunk-RRXUIPWG.js";
|
|
30
30
|
import {
|
|
31
31
|
t
|
|
32
|
-
} from "./chunk-
|
|
32
|
+
} from "./chunk-YEF7C4XI.js";
|
|
33
33
|
import {
|
|
34
34
|
defaultConfigPath,
|
|
35
35
|
loadBaseUrl,
|
|
36
36
|
loadProxyConfig,
|
|
37
37
|
readConfig,
|
|
38
38
|
resolveSemanticEmbeddingConfig
|
|
39
|
-
} from "./chunk-
|
|
39
|
+
} from "./chunk-WMTMMSXU.js";
|
|
40
40
|
import {
|
|
41
41
|
VERSION
|
|
42
42
|
} from "./chunk-XXC2BYTV.js";
|
|
@@ -92,7 +92,10 @@ function checkProxy() {
|
|
|
92
92
|
}
|
|
93
93
|
];
|
|
94
94
|
}
|
|
95
|
-
const resolved = resolveNoProxy(process.env, {
|
|
95
|
+
const resolved = resolveNoProxy(process.env, {
|
|
96
|
+
extraNoProxy: cfg.noProxy,
|
|
97
|
+
bypassDeepSeekDirect: cfg.bypassDeepSeekDirect
|
|
98
|
+
});
|
|
96
99
|
const total = resolved.all.length;
|
|
97
100
|
const sourceSummary = [
|
|
98
101
|
`defaults ${resolved.defaults.length}`,
|
|
@@ -481,4 +484,4 @@ export {
|
|
|
481
484
|
formatDoctorJson,
|
|
482
485
|
doctorCommand
|
|
483
486
|
};
|
|
484
|
-
//# sourceMappingURL=chunk-
|
|
487
|
+
//# sourceMappingURL=chunk-23ZPCIPR.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/cli/commands/doctor.ts"],"sourcesContent":["/** Plain-text (not Ink) — must work when everything else is broken. fail → exit 1; warn → exit 0. */\n\nimport { existsSync, readFileSync, statSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join, resolve } from \"node:path\";\nimport { DeepSeekClient, pickPrimaryBalance } from \"../../client.js\";\nimport {\n defaultConfigPath,\n loadBaseUrl,\n loadProxyConfig,\n readConfig,\n resolveSemanticEmbeddingConfig,\n} from \"../../config.js\";\nimport { loadDotenv } from \"../../env.js\";\nimport { loadHooks } from \"../../hooks.js\";\nimport { t } from \"../../i18n/index.js\";\nimport { indexExists } from \"../../index/semantic/builder.js\";\nimport { checkOllamaStatus } from \"../../index/semantic/ollama-launcher.js\";\nimport { listSessions } from \"../../memory/session.js\";\nimport { detectProxyUrl, matchesNoProxy, resolveNoProxy } from \"../../net/proxy.js\";\nimport { resolveDataPath } from \"../../tokenizer.js\";\nimport { VERSION } from \"../../version.js\";\n\nexport type DoctorLevel = \"ok\" | \"warn\" | \"fail\";\n\nexport interface DoctorCheck {\n id: string;\n label: string;\n level: DoctorLevel;\n detail: string;\n}\n\nexport interface DoctorOptions {\n json?: boolean;\n}\n\ntype Level = DoctorLevel;\ntype Check = DoctorCheck;\n\nexport async function runDoctorChecks(projectRoot: string): Promise<DoctorCheck[]> {\n // No descriptive names for the destructured slots — CodeQL's clear-text-logging\n // heuristic taints any variable name matching `*key*`/`*auth*`/`*cred*`/etc and\n // would trip on `apiKeyCheck`. The slots map 1:1 to the Promise.all array below.\n const r = await Promise.all([\n checkApiKey(),\n checkConfig(),\n checkApiReach(),\n checkTokenizer(),\n checkSessions(),\n checkHooks(projectRoot),\n checkOllama(projectRoot),\n checkProject(projectRoot),\n ]);\n return [r[0], r[1], ...checkProxy(), r[2], r[3], r[4], r[5], r[6], r[7]];\n}\n\n/** Probe hosts used to show users what's going through the proxy vs. direct. Cheap (no I/O), purely a routing simulation against the same NO_PROXY patterns the dispatcher uses. */\nconst PROXY_PROBE_HOSTS = [\"api.deepseek.com\", \"github.com\", \"api.github.com\"] as const;\n\nfunction checkProxy(): Check[] {\n const url = detectProxyUrl();\n if (!url) {\n return [\n {\n id: \"proxy\",\n label: \"http proxy \",\n level: \"ok\",\n detail: \"no HTTPS_PROXY / HTTP_PROXY / ALL_PROXY set — direct connection\",\n },\n ];\n }\n let redacted = url;\n try {\n const u = new URL(url);\n if (u.username || u.password) {\n u.username = \"***\";\n u.password = \"\";\n redacted = u.toString();\n }\n } catch {\n /* not a URL — leave raw */\n }\n const cfg = loadProxyConfig();\n if (cfg.disabled) {\n return [\n {\n id: \"proxy\",\n label: \"http proxy \",\n level: \"ok\",\n detail: `HTTPS_PROXY=${redacted} is set but cfg.proxy.disabled — Reasonix routes direct`,\n },\n ];\n }\n const resolved = resolveNoProxy(process.env, {\n extraNoProxy: cfg.noProxy,\n bypassDeepSeekDirect: cfg.bypassDeepSeekDirect,\n });\n const total = resolved.all.length;\n const sourceSummary = [\n `defaults ${resolved.defaults.length}`,\n resolved.envSystem.length > 0 ? `env ${resolved.envSystem.length}` : null,\n resolved.envReasonix.length > 0 ? `REASONIX ${resolved.envReasonix.length}` : null,\n resolved.extra.length > 0 ? `config ${resolved.extra.length}` : null,\n ]\n .filter(Boolean)\n .join(\" + \");\n const proxyCheck: Check = {\n id: \"proxy\",\n label: \"http proxy \",\n level: \"ok\",\n detail: `routing fetch through ${redacted} (NO_PROXY: ${total} pattern${total === 1 ? \"\" : \"s\"} — ${sourceSummary})`,\n };\n const probes = PROXY_PROBE_HOSTS.map(\n (h) => `${h} → ${matchesNoProxy(h, resolved.all) ? \"direct\" : \"via proxy\"}`,\n );\n const routingCheck: Check = {\n id: \"proxy-routing\",\n label: \"proxy routing\",\n level: \"ok\",\n detail: probes.join(\", \"),\n };\n return [proxyCheck, routingCheck];\n}\n\nconst TTY = process.stdout.isTTY && process.env.TERM !== \"dumb\";\n\nfunction color(text: string, code: string): string {\n if (!TTY) return text;\n return `\\x1b[${code}m${text}\\x1b[0m`;\n}\n\nfunction badge(level: Level): string {\n if (level === \"ok\") return color(\"✓\", \"32\");\n if (level === \"warn\") return color(\"⚠\", \"33\");\n return color(\"✗\", \"31\");\n}\n\nfunction fmtBytes(n: number): string {\n if (n < 1024) return `${n} B`;\n if (n < 1024 * 1024) return `${(n / 1024).toFixed(1)} KB`;\n return `${(n / 1024 / 1024).toFixed(1)} MB`;\n}\n\nasync function checkApiKey(): Promise<Check> {\n const fromEnv = process.env.DEEPSEEK_API_KEY;\n if (fromEnv) {\n return {\n id: \"api-key\",\n label: \"api key \",\n level: \"ok\",\n detail: \"set via env DEEPSEEK_API_KEY\",\n };\n }\n try {\n const cfg = readConfig();\n if (cfg.apiKey) {\n return {\n id: \"api-key\",\n label: \"api key \",\n level: \"ok\",\n detail: `from ${defaultConfigPath()}`,\n };\n }\n } catch {\n /* fall through */\n }\n return {\n id: \"api-key\",\n label: \"api key \",\n level: \"fail\",\n detail:\n \"not set — `reasonix setup` to save one, or export DEEPSEEK_API_KEY. Get a key at https://platform.deepseek.com/api_keys\",\n };\n}\n\nasync function checkConfig(): Promise<Check> {\n const path = defaultConfigPath();\n if (!existsSync(path)) {\n return {\n id: \"config\",\n label: \"config \",\n level: \"warn\",\n detail: \"missing — running with library defaults. `reasonix setup` writes one.\",\n };\n }\n try {\n const cfg = readConfig(path);\n const parts: string[] = [];\n if (cfg.preset) parts.push(`preset=${cfg.preset}`);\n if (cfg.editMode) parts.push(`editMode=${cfg.editMode}`);\n if (cfg.mcp && cfg.mcp.length > 0) parts.push(`mcp=${cfg.mcp.length}`);\n return {\n id: \"config\",\n label: \"config \",\n level: \"ok\",\n detail: `${path}${parts.length ? ` (${parts.join(\", \")})` : \"\"}`,\n };\n } catch (err) {\n return {\n id: \"config\",\n label: \"config \",\n level: \"fail\",\n detail: t(\"doctorErrors.unreadable\", { path, message: (err as Error).message }),\n };\n }\n}\n\nasync function checkApiReach(): Promise<Check> {\n const key = process.env.DEEPSEEK_API_KEY ?? readConfig().apiKey;\n if (!key) {\n return {\n id: \"api-reach\",\n label: \"api reach \",\n level: \"warn\",\n detail: \"skipped — no api key to test with\",\n };\n }\n try {\n const client = new DeepSeekClient({ apiKey: key, baseUrl: loadBaseUrl() });\n const ctl = new AbortController();\n const timer = setTimeout(() => ctl.abort(), 8_000);\n let balance: Awaited<ReturnType<DeepSeekClient[\"getBalance\"]>>;\n try {\n balance = await client.getBalance({ signal: ctl.signal });\n } finally {\n clearTimeout(timer);\n }\n if (!balance) {\n return {\n id: \"api-reach\",\n label: \"api reach \",\n level: \"fail\",\n detail: \"/user/balance returned null — auth failed or network blocked\",\n };\n }\n const summary = summarizeBalances(balance.balance_infos);\n if (!balance.is_available) {\n return {\n id: \"api-reach\",\n label: \"api reach \",\n level: \"warn\",\n detail: `account flagged not-available${summary ? ` (${summary})` : \"\"} — top up or check your dashboard`,\n };\n }\n return {\n id: \"api-reach\",\n label: \"api reach \",\n level: \"ok\",\n detail: summary ? `/user/balance ok — ${summary}` : \"/user/balance ok\",\n };\n } catch (err) {\n return {\n id: \"api-reach\",\n label: \"api reach \",\n level: \"fail\",\n detail: `${(err as Error).message}`,\n };\n }\n}\n\nfunction summarizeBalances(\n infos: ReadonlyArray<{ currency: string; total_balance: string }>,\n): string {\n if (infos.length === 0) return \"\";\n const primary = pickPrimaryBalance(infos);\n if (infos.length === 1 || !primary)\n return primary ? `${primary.total_balance} ${primary.currency}` : \"\";\n const rest = infos.filter((i) => i !== primary).map((i) => `${i.total_balance} ${i.currency}`);\n return `${primary.total_balance} ${primary.currency} + ${rest.join(\" + \")}`;\n}\n\nasync function checkTokenizer(): Promise<Check> {\n // Reuse the runtime's resolver so the doctor never disagrees with what\n // the tokenizer actually loads — three candidates including a global\n // npm install probe via createRequire.\n const path = resolveDataPath();\n if (existsSync(path)) {\n try {\n const stat = statSync(path);\n return {\n id: \"tokenizer\",\n label: \"tokenizer \",\n level: \"ok\",\n detail: `${path} (${fmtBytes(stat.size)})`,\n };\n } catch {\n /* fall through to warn */\n }\n }\n return {\n id: \"tokenizer\",\n label: \"tokenizer \",\n level: \"warn\",\n detail:\n \"data/deepseek-tokenizer.json.gz not found — token counts will fall back to char heuristics\",\n };\n}\n\nasync function checkSessions(): Promise<Check> {\n try {\n const list = listSessions();\n if (list.length === 0) {\n return {\n id: \"sessions\",\n label: \"sessions \",\n level: \"ok\",\n detail: \"0 saved\",\n };\n }\n const totalBytes = list.reduce((s, e) => s + e.size, 0);\n const oldest = list[list.length - 1]!;\n const ageDays = Math.floor((Date.now() - oldest.mtime.getTime()) / (24 * 60 * 60 * 1000));\n const stale = list.filter(\n (e) => Date.now() - e.mtime.getTime() >= 90 * 24 * 60 * 60 * 1000,\n ).length;\n const detail = `${list.length} saved · ${fmtBytes(totalBytes)} · oldest ${ageDays}d`;\n if (stale > 0) {\n return {\n id: \"sessions\",\n label: \"sessions \",\n level: \"warn\",\n detail: `${detail} · ${stale} idle ≥90d (run \\`reasonix prune-sessions\\`)`,\n };\n }\n return { id: \"sessions\", label: \"sessions \", level: \"ok\", detail };\n } catch (err) {\n return {\n id: \"sessions\",\n label: \"sessions \",\n level: \"warn\",\n detail: t(\"doctorErrors.cannotList\", { message: (err as Error).message }),\n };\n }\n}\n\nasync function checkHooks(projectRoot: string): Promise<Check> {\n try {\n const all = loadHooks({ projectRoot });\n const global = all.filter((h) => h.scope === \"global\").length;\n const project = all.filter((h) => h.scope === \"project\").length;\n return {\n id: \"hooks\",\n label: \"hooks \",\n level: \"ok\",\n detail: `${global} global, ${project} project`,\n };\n } catch (err) {\n return {\n id: \"hooks\",\n label: \"hooks \",\n level: \"warn\",\n detail: t(\"doctorErrors.parseFailed\", { message: (err as Error).message }),\n };\n }\n}\n\nasync function checkOllama(projectRoot: string): Promise<Check> {\n let exists = false;\n try {\n exists = await indexExists(projectRoot);\n } catch {\n /* treat as no index */\n }\n if (!exists) {\n return {\n id: \"semantic\",\n label: \"semantic \",\n level: \"ok\",\n detail: \"not in use (no semantic index built; `reasonix index` to enable)\",\n };\n }\n const meta = readSemanticMeta(projectRoot);\n if (meta?.provider === \"openai-compat\") {\n const resolved = resolveSemanticEmbeddingConfig();\n if (resolved.provider !== \"openai-compat\") {\n return {\n id: \"semantic\",\n label: \"semantic \",\n level: \"warn\",\n detail: `index uses openai-compat/${meta.model} but current config resolves to ${resolved.provider}/${resolved.model} — rebuild before searching`,\n };\n }\n return {\n id: \"semantic\",\n label: \"semantic \",\n level: \"ok\",\n detail: `openai-compat · ${resolved.baseUrl} · model ${resolved.model} · api key configured`,\n };\n }\n try {\n const model = meta?.model || process.env.REASONIX_EMBED_MODEL || \"nomic-embed-text\";\n const status = await checkOllamaStatus(model);\n if (!status.binaryFound) {\n return {\n id: \"semantic\",\n label: \"semantic \",\n level: \"warn\",\n detail:\n \"ollama binary not on PATH — semantic_search will fail; install from https://ollama.com\",\n };\n }\n if (!status.daemonRunning) {\n return {\n id: \"semantic\",\n label: \"semantic \",\n level: \"warn\",\n detail:\n \"ollama daemon not running — `ollama serve` (or call /semantic in TUI to auto-start)\",\n };\n }\n if (!status.modelPulled) {\n return {\n id: \"semantic\",\n label: \"semantic \",\n level: \"warn\",\n detail: `model ${status.modelName} not pulled — \\`ollama pull ${status.modelName}\\``,\n };\n }\n return {\n id: \"semantic\",\n label: \"semantic \",\n level: \"ok\",\n detail: `ollama daemon up · model ${status.modelName} ready`,\n };\n } catch (err) {\n return {\n id: \"semantic\",\n label: \"semantic \",\n level: \"warn\",\n detail: t(\"doctorErrors.probeFailed\", { message: (err as Error).message }),\n };\n }\n}\n\nfunction readSemanticMeta(\n projectRoot: string,\n): { provider: \"ollama\" | \"openai-compat\"; model: string } | null {\n try {\n const raw = readFileSync(join(projectRoot, \".reasonix\", \"semantic\", \"index.meta.json\"), \"utf8\");\n const parsed = JSON.parse(raw) as { provider?: string; model?: string };\n return {\n provider: parsed.provider === \"openai-compat\" ? \"openai-compat\" : \"ollama\",\n model: typeof parsed.model === \"string\" ? parsed.model : \"\",\n };\n } catch {\n return null;\n }\n}\n\nasync function checkProject(projectRoot: string): Promise<Check> {\n // Heuristic: a \"real\" project has either .git, REASONIX.md, or\n // package.json. Lacking all three, `reasonix code` still works but\n // @-mentions and the project-memory pin won't surface much.\n const markers = [\".git\", \"REASONIX.md\", \"package.json\", \"pyproject.toml\", \"Cargo.toml\", \"go.mod\"];\n const found = markers.filter((m) => existsSync(join(projectRoot, m)));\n if (found.length === 0) {\n return {\n id: \"project\",\n label: \"project \",\n level: \"warn\",\n detail: `${projectRoot} has none of: ${markers.slice(0, 3).join(\", \")} … — \\`reasonix code\\` will still run, but @-mentions and project memory have nothing to anchor`,\n };\n }\n return {\n id: \"project\",\n label: \"project \",\n level: \"ok\",\n detail: `${projectRoot} (${found.join(\", \")})`,\n };\n}\n\nexport function formatDoctorJson(checks: DoctorCheck[], version: string): string {\n const ok = checks.filter((c) => c.level === \"ok\").length;\n const warn = checks.filter((c) => c.level === \"warn\").length;\n const fail = checks.filter((c) => c.level === \"fail\").length;\n return JSON.stringify({\n version,\n summary: { ok, warn, fail },\n checks: checks.map((c) => ({ id: c.id, status: c.level, message: c.detail })),\n });\n}\n\nexport async function doctorCommand(opts: DoctorOptions = {}): Promise<void> {\n loadDotenv();\n\n const projectRoot = resolve(process.cwd());\n const json = !!opts.json;\n\n if (!json) {\n console.log(`${color(`reasonix ${VERSION} · doctor`, \"1\")} (cwd: ${projectRoot})`);\n console.log(` home: ${homedir()}`);\n console.log(\"\");\n }\n\n // Run independent checks in parallel — saves ~5s when api-reach has\n // to time out. Each handler swallows its own throws into a `fail`\n // result so a thrown promise can't kill the whole report.\n const checks = await runDoctorChecks(projectRoot);\n\n const ok = checks.filter((c) => c.level === \"ok\").length;\n const warn = checks.filter((c) => c.level === \"warn\").length;\n const fail = checks.filter((c) => c.level === \"fail\").length;\n\n if (json) {\n console.log(formatDoctorJson(checks, VERSION));\n if (fail > 0) process.exit(1);\n return;\n }\n\n for (const c of checks) {\n console.log(` ${badge(c.level)} ${c.label} ${c.detail}`);\n }\n\n console.log(\"\");\n const summary = `${ok} ok · ${warn} warn · ${fail} fail`;\n if (fail > 0) {\n console.log(color(summary, \"31\"));\n process.exit(1);\n } else if (warn > 0) {\n console.log(color(summary, \"33\"));\n } else {\n console.log(color(summary, \"32\"));\n }\n}\n"],"mappings":"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","names":[]}
|