reasonix 0.50.1 → 0.51.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.css +1 -1
- package/dashboard/dist/app.js +24 -22
- package/dashboard/dist/app.js.map +1 -1
- package/dist/cli/{acp-6B25WIFF.js → acp-XEUHGG7X.js} +34 -31
- package/dist/cli/acp-XEUHGG7X.js.map +1 -0
- package/dist/cli/chat-NJ2Q5KHG.js +50 -0
- package/dist/cli/{chunk-OPGWCKKU.js → chunk-2HVTBFCI.js} +3 -3
- package/dist/cli/{chunk-AJIZ5KFK.js → chunk-2WUEAI2I.js} +3 -3
- package/dist/cli/{chunk-I4Q3QT4W.js → chunk-36BM7INR.js} +2 -2
- package/dist/cli/{chunk-3RNFYDDM.js → chunk-3BTK5BHI.js} +11 -7
- package/dist/cli/chunk-3BTK5BHI.js.map +1 -0
- package/dist/cli/{chunk-GMSAB2TC.js → chunk-3YRTIWFX.js} +2 -2
- package/dist/cli/{chunk-NLRC3DWQ.js → chunk-544J4PXD.js} +5 -5
- package/dist/cli/{chunk-7WITYWKN.js → chunk-5AIDYVH2.js} +2 -2
- package/dist/cli/{chunk-ALCOQP6R.js → chunk-5BBC6YMV.js} +5 -5
- package/dist/cli/{chunk-S4XVGLRW.js → chunk-6UNHNVJR.js} +72 -5
- package/dist/cli/chunk-6UNHNVJR.js.map +1 -0
- package/dist/cli/{chunk-IK6WWRIX.js → chunk-6XWXIVQ3.js} +38 -22
- package/dist/cli/chunk-6XWXIVQ3.js.map +1 -0
- package/dist/cli/{chunk-AAHB2PFX.js → chunk-7YB26OQO.js} +4 -4
- package/dist/cli/chunk-7YB26OQO.js.map +1 -0
- package/dist/cli/{chunk-MXWPAPZW.js → chunk-A5PBEIJ7.js} +53 -10
- package/dist/cli/chunk-A5PBEIJ7.js.map +1 -0
- package/dist/cli/{chunk-FQSQFCBI.js → chunk-BA5R6BAE.js} +2 -2
- package/dist/cli/{chunk-XWPZHWC2.js → chunk-BM6BBFAV.js} +2 -2
- package/dist/cli/{chunk-CAGKEGNE.js → chunk-BOWSNGQC.js} +52 -140
- package/dist/cli/chunk-BOWSNGQC.js.map +1 -0
- package/dist/cli/{chunk-EZ57UEZQ.js → chunk-C2MRSJTV.js} +2 -2
- package/dist/cli/{chunk-PYIZZAVQ.js → chunk-DVD67FXQ.js} +1716 -4
- package/dist/cli/chunk-DVD67FXQ.js.map +1 -0
- package/dist/cli/{chunk-ZAXMJANP.js → chunk-EAMXOWUW.js} +3 -3
- package/dist/cli/{chunk-TX652NBA.js → chunk-EWVFGYT6.js} +2 -2
- package/dist/cli/{chunk-IBRTU5WO.js → chunk-FP7IOWBQ.js} +18 -1182
- package/dist/cli/chunk-FP7IOWBQ.js.map +1 -0
- package/dist/cli/{chunk-I6FBSTTR.js → chunk-HGK57NBN.js} +9 -353
- package/dist/cli/chunk-HGK57NBN.js.map +1 -0
- package/dist/cli/chunk-JHWQDJZA.js +80 -0
- package/dist/cli/chunk-JHWQDJZA.js.map +1 -0
- package/dist/cli/{chunk-X2BQZQEE.js → chunk-K3QJ3GKI.js} +3 -3
- package/dist/cli/{chunk-GPUH2BNM.js → chunk-K4YQFULP.js} +612 -254
- package/dist/cli/chunk-K4YQFULP.js.map +1 -0
- package/dist/cli/chunk-L3VPEESB.js +31 -0
- package/dist/cli/chunk-L3VPEESB.js.map +1 -0
- package/dist/cli/{chunk-ENFBF6HI.js → chunk-N4SEBLU4.js} +383 -5
- package/dist/cli/chunk-N4SEBLU4.js.map +1 -0
- package/dist/cli/chunk-NRROJXXT.js +879 -0
- package/dist/cli/chunk-NRROJXXT.js.map +1 -0
- package/dist/cli/{chunk-3KRRTLC5.js → chunk-R6KIHEF3.js} +1619 -1036
- package/dist/cli/chunk-R6KIHEF3.js.map +1 -0
- package/dist/cli/{chunk-VVMY4M7J.js → chunk-SBHF5NWD.js} +27 -4
- package/dist/cli/chunk-SBHF5NWD.js.map +1 -0
- package/dist/cli/{chunk-OWA42BKS.js → chunk-SXSAWOB7.js} +14 -14
- package/dist/cli/{chunk-6IUMTRFP.js → chunk-UMZ6KHTS.js} +2 -2
- package/dist/cli/{chunk-7X4JJOO7.js → chunk-UO6E7FN3.js} +69 -5
- package/dist/cli/{chunk-7X4JJOO7.js.map → chunk-UO6E7FN3.js.map} +1 -1
- package/dist/cli/{chunk-3ZZXQ3CZ.js → chunk-UPW544V3.js} +2 -2
- package/dist/cli/{chunk-XJZWMU5P.js → chunk-WPOKBW5E.js} +2 -2
- package/dist/cli/{chunk-WSBFVOCO.js → chunk-Z3MKG7MQ.js} +2 -2
- package/dist/cli/{code-TBK2TASK.js → code-BMXLBC7D.js} +37 -36
- package/dist/cli/{code-TBK2TASK.js.map → code-BMXLBC7D.js.map} +1 -1
- package/dist/cli/{commands-NXTKSQTN.js → commands-E4RZXMF6.js} +5 -5
- package/dist/cli/{commit-IR5SPP7A.js → commit-KSRQ64IL.js} +3 -3
- package/dist/cli/{config-XK5WQGTS.js → config-QNDONOTU.js} +4 -2
- package/dist/cli/{desktop-5NTQBADL.js → desktop-H3ZHIMDA.js} +83 -37
- package/dist/cli/desktop-H3ZHIMDA.js.map +1 -0
- package/dist/cli/{diff-JNYX5BSZ.js → diff-I4PYI43W.js} +9 -9
- package/dist/cli/{doctor-IKYLUFXX.js → doctor-Y2E4MY2F.js} +12 -12
- package/dist/cli/{events-HSC57ONU.js → events-47HOT7ZA.js} +5 -5
- package/dist/cli/find-in-code-YLEIK5FK.js +145 -0
- package/dist/cli/find-in-code-YLEIK5FK.js.map +1 -0
- package/dist/cli/index.js +95 -44
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/{mcp-BDJJWOCD.js → mcp-76DK63ZB.js} +3 -3
- package/dist/cli/{mcp-browse-NJRZDI6V.js → mcp-browse-SDNUGO74.js} +3 -3
- package/dist/cli/{mcp-inspect-Y62NWZQL.js → mcp-inspect-BL5DEO5M.js} +3 -3
- package/dist/cli/{prompt-UTOIFUQC.js → prompt-JLATI3P7.js} +5 -5
- package/dist/cli/{prune-sessions-UCUD4XAP.js → prune-sessions-WHZDFUKD.js} +4 -4
- package/dist/cli/{replay-VVIN64MN.js → replay-MHXS7C7Z.js} +10 -10
- package/dist/cli/{run-76OBDZFB.js → run-SXNCPRJE.js} +22 -22
- package/dist/cli/{server-SZZDKTH2.js → server-GEHOE6CO.js} +61 -35
- package/dist/cli/server-GEHOE6CO.js.map +1 -0
- package/dist/cli/{sessions-FZTGRCM5.js → sessions-EPBFYISL.js} +18 -18
- package/dist/cli/{setup-4UNENGOE.js → setup-IW2XR5XI.js} +8 -7
- package/dist/cli/setup-IW2XR5XI.js.map +1 -0
- package/dist/cli/{stats-F4NDOD7D.js → stats-4WB4XHBP.js} +6 -6
- package/dist/cli/symbols-UQ274IOB.js +167 -0
- package/dist/cli/symbols-UQ274IOB.js.map +1 -0
- package/dist/cli/version-4SP3DLLH.js +33 -0
- package/dist/index.d.ts +25 -6
- package/dist/index.js +2700 -578
- package/dist/index.js.map +1 -1
- package/package.json +4 -2
- package/scripts/postinstall.mjs +3 -5
- package/dist/cli/acp-6B25WIFF.js.map +0 -1
- package/dist/cli/chat-7WASPB4O.js +0 -50
- package/dist/cli/chunk-3KRRTLC5.js.map +0 -1
- package/dist/cli/chunk-3RNFYDDM.js.map +0 -1
- package/dist/cli/chunk-AAHB2PFX.js.map +0 -1
- package/dist/cli/chunk-CAGKEGNE.js.map +0 -1
- package/dist/cli/chunk-ENFBF6HI.js.map +0 -1
- package/dist/cli/chunk-GPUH2BNM.js.map +0 -1
- package/dist/cli/chunk-I6FBSTTR.js.map +0 -1
- package/dist/cli/chunk-IBRTU5WO.js.map +0 -1
- package/dist/cli/chunk-IK6WWRIX.js.map +0 -1
- package/dist/cli/chunk-MXWPAPZW.js.map +0 -1
- package/dist/cli/chunk-PYIZZAVQ.js.map +0 -1
- package/dist/cli/chunk-S4XVGLRW.js.map +0 -1
- package/dist/cli/chunk-VVMY4M7J.js.map +0 -1
- package/dist/cli/desktop-5NTQBADL.js.map +0 -1
- package/dist/cli/server-SZZDKTH2.js.map +0 -1
- package/dist/cli/setup-4UNENGOE.js.map +0 -1
- package/dist/cli/version-LUVTWHLL.js +0 -33
- /package/dist/cli/{chat-7WASPB4O.js.map → chat-NJ2Q5KHG.js.map} +0 -0
- /package/dist/cli/{chunk-OPGWCKKU.js.map → chunk-2HVTBFCI.js.map} +0 -0
- /package/dist/cli/{chunk-AJIZ5KFK.js.map → chunk-2WUEAI2I.js.map} +0 -0
- /package/dist/cli/{chunk-I4Q3QT4W.js.map → chunk-36BM7INR.js.map} +0 -0
- /package/dist/cli/{chunk-GMSAB2TC.js.map → chunk-3YRTIWFX.js.map} +0 -0
- /package/dist/cli/{chunk-NLRC3DWQ.js.map → chunk-544J4PXD.js.map} +0 -0
- /package/dist/cli/{chunk-7WITYWKN.js.map → chunk-5AIDYVH2.js.map} +0 -0
- /package/dist/cli/{chunk-ALCOQP6R.js.map → chunk-5BBC6YMV.js.map} +0 -0
- /package/dist/cli/{chunk-FQSQFCBI.js.map → chunk-BA5R6BAE.js.map} +0 -0
- /package/dist/cli/{chunk-XWPZHWC2.js.map → chunk-BM6BBFAV.js.map} +0 -0
- /package/dist/cli/{chunk-EZ57UEZQ.js.map → chunk-C2MRSJTV.js.map} +0 -0
- /package/dist/cli/{chunk-ZAXMJANP.js.map → chunk-EAMXOWUW.js.map} +0 -0
- /package/dist/cli/{chunk-TX652NBA.js.map → chunk-EWVFGYT6.js.map} +0 -0
- /package/dist/cli/{chunk-X2BQZQEE.js.map → chunk-K3QJ3GKI.js.map} +0 -0
- /package/dist/cli/{chunk-OWA42BKS.js.map → chunk-SXSAWOB7.js.map} +0 -0
- /package/dist/cli/{chunk-6IUMTRFP.js.map → chunk-UMZ6KHTS.js.map} +0 -0
- /package/dist/cli/{chunk-3ZZXQ3CZ.js.map → chunk-UPW544V3.js.map} +0 -0
- /package/dist/cli/{chunk-XJZWMU5P.js.map → chunk-WPOKBW5E.js.map} +0 -0
- /package/dist/cli/{chunk-WSBFVOCO.js.map → chunk-Z3MKG7MQ.js.map} +0 -0
- /package/dist/cli/{commands-NXTKSQTN.js.map → commands-E4RZXMF6.js.map} +0 -0
- /package/dist/cli/{commit-IR5SPP7A.js.map → commit-KSRQ64IL.js.map} +0 -0
- /package/dist/cli/{config-XK5WQGTS.js.map → config-QNDONOTU.js.map} +0 -0
- /package/dist/cli/{diff-JNYX5BSZ.js.map → diff-I4PYI43W.js.map} +0 -0
- /package/dist/cli/{doctor-IKYLUFXX.js.map → doctor-Y2E4MY2F.js.map} +0 -0
- /package/dist/cli/{events-HSC57ONU.js.map → events-47HOT7ZA.js.map} +0 -0
- /package/dist/cli/{mcp-BDJJWOCD.js.map → mcp-76DK63ZB.js.map} +0 -0
- /package/dist/cli/{mcp-browse-NJRZDI6V.js.map → mcp-browse-SDNUGO74.js.map} +0 -0
- /package/dist/cli/{mcp-inspect-Y62NWZQL.js.map → mcp-inspect-BL5DEO5M.js.map} +0 -0
- /package/dist/cli/{prompt-UTOIFUQC.js.map → prompt-JLATI3P7.js.map} +0 -0
- /package/dist/cli/{prune-sessions-UCUD4XAP.js.map → prune-sessions-WHZDFUKD.js.map} +0 -0
- /package/dist/cli/{replay-VVIN64MN.js.map → replay-MHXS7C7Z.js.map} +0 -0
- /package/dist/cli/{run-76OBDZFB.js.map → run-SXNCPRJE.js.map} +0 -0
- /package/dist/cli/{sessions-FZTGRCM5.js.map → sessions-EPBFYISL.js.map} +0 -0
- /package/dist/cli/{stats-F4NDOD7D.js.map → stats-4WB4XHBP.js.map} +0 -0
- /package/dist/cli/{version-LUVTWHLL.js.map → version-4SP3DLLH.js.map} +0 -0
|
@@ -1,64 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire as __cr } from 'node:module'; if (typeof globalThis.require === 'undefined') { globalThis.require = __cr(import.meta.url); }
|
|
3
|
-
import {
|
|
4
|
-
bootstrapSemanticSearchInCodeMode
|
|
5
|
-
} from "./chunk-WSBFVOCO.js";
|
|
6
|
-
import {
|
|
7
|
-
registerSkillTools
|
|
8
|
-
} from "./chunk-XWPZHWC2.js";
|
|
9
|
-
import {
|
|
10
|
-
preflightStdioSpec
|
|
11
|
-
} from "./chunk-SVD4UPRQ.js";
|
|
12
|
-
import {
|
|
13
|
-
SHARED_SUBAGENT_SINK,
|
|
14
|
-
ToolRegistry,
|
|
15
|
-
formatSubagentResult,
|
|
16
|
-
registerChoiceTool,
|
|
17
|
-
registerFilesystemTools,
|
|
18
|
-
registerMemoryTools,
|
|
19
|
-
registerPlanTool,
|
|
20
|
-
registerTodoTool,
|
|
21
|
-
registerWebTools,
|
|
22
|
-
spawnSubagent
|
|
23
|
-
} from "./chunk-GPUH2BNM.js";
|
|
24
|
-
import {
|
|
25
|
-
JobRegistry,
|
|
26
|
-
registerShellTools
|
|
27
|
-
} from "./chunk-6IUMTRFP.js";
|
|
28
|
-
import {
|
|
29
|
-
SkillStore
|
|
30
|
-
} from "./chunk-ENFBF6HI.js";
|
|
31
|
-
import {
|
|
32
|
-
MCP_CATALOG
|
|
33
|
-
} from "./chunk-PLHAZOLZ.js";
|
|
34
|
-
import {
|
|
35
|
-
DeepSeekClient
|
|
36
|
-
} from "./chunk-EZ57UEZQ.js";
|
|
37
|
-
import {
|
|
38
|
-
defaultConfigPath,
|
|
39
|
-
loadEditMode,
|
|
40
|
-
loadEndpoint,
|
|
41
|
-
loadFilesystemOutlineThresholdBytes,
|
|
42
|
-
loadJavaSourceEnabled,
|
|
43
|
-
loadProjectShellAllowed,
|
|
44
|
-
loadResolvedSkillPaths,
|
|
45
|
-
loadSubagentModels,
|
|
46
|
-
loadToolRateLimit,
|
|
47
|
-
parseMcpSpec,
|
|
48
|
-
readConfig,
|
|
49
|
-
searchEnabled,
|
|
50
|
-
writeConfig
|
|
51
|
-
} from "./chunk-MXWPAPZW.js";
|
|
52
|
-
|
|
53
|
-
// src/tools/code-query.ts
|
|
54
|
-
import { readFile } from "fs/promises";
|
|
55
|
-
import { resolve as pathResolve } from "path";
|
|
56
|
-
|
|
57
|
-
// src/code-query/parser.ts
|
|
58
|
-
import { existsSync, readFileSync } from "fs";
|
|
59
|
-
import { createRequire } from "module";
|
|
60
|
-
import { dirname, resolve } from "path";
|
|
61
|
-
import { fileURLToPath } from "url";
|
|
62
3
|
|
|
63
4
|
// node_modules/web-tree-sitter/web-tree-sitter.js
|
|
64
5
|
var __defProp = Object.defineProperty;
|
|
@@ -1531,8 +1472,8 @@ var Language = class _Language {
|
|
|
1531
1472
|
if (input instanceof Uint8Array) {
|
|
1532
1473
|
binary2 = input;
|
|
1533
1474
|
} else if (globalThis.process?.versions.node) {
|
|
1534
|
-
const
|
|
1535
|
-
binary2 = await
|
|
1475
|
+
const fs2 = await import("fs/promises");
|
|
1476
|
+
binary2 = await fs2.readFile(input);
|
|
1536
1477
|
} else {
|
|
1537
1478
|
const response = await fetch(input);
|
|
1538
1479
|
if (!response.ok) {
|
|
@@ -1583,11 +1524,11 @@ async function Module2(moduleArg = {}) {
|
|
|
1583
1524
|
}, "quit_");
|
|
1584
1525
|
var _scriptName = import.meta.url;
|
|
1585
1526
|
var scriptDirectory = "";
|
|
1586
|
-
function locateFile(
|
|
1527
|
+
function locateFile(path) {
|
|
1587
1528
|
if (Module["locateFile"]) {
|
|
1588
|
-
return Module["locateFile"](
|
|
1529
|
+
return Module["locateFile"](path, scriptDirectory);
|
|
1589
1530
|
}
|
|
1590
|
-
return scriptDirectory +
|
|
1531
|
+
return scriptDirectory + path;
|
|
1591
1532
|
}
|
|
1592
1533
|
__name(locateFile, "locateFile");
|
|
1593
1534
|
var readAsync, readBinary;
|
|
@@ -1634,13 +1575,13 @@ async function Module2(moduleArg = {}) {
|
|
|
1634
1575
|
}
|
|
1635
1576
|
readAsync = /* @__PURE__ */ __name(async (url) => {
|
|
1636
1577
|
if (isFileURI(url)) {
|
|
1637
|
-
return new Promise((
|
|
1578
|
+
return new Promise((resolve2, reject) => {
|
|
1638
1579
|
var xhr = new XMLHttpRequest();
|
|
1639
1580
|
xhr.open("GET", url, true);
|
|
1640
1581
|
xhr.responseType = "arraybuffer";
|
|
1641
1582
|
xhr.onload = () => {
|
|
1642
1583
|
if (xhr.status == 200 || xhr.status == 0 && xhr.response) {
|
|
1643
|
-
|
|
1584
|
+
resolve2(xhr.response);
|
|
1644
1585
|
return;
|
|
1645
1586
|
}
|
|
1646
1587
|
reject(xhr.status);
|
|
@@ -1836,9 +1777,9 @@ async function Module2(moduleArg = {}) {
|
|
|
1836
1777
|
__name(receiveInstantiationResult, "receiveInstantiationResult");
|
|
1837
1778
|
var info2 = getWasmImports();
|
|
1838
1779
|
if (Module["instantiateWasm"]) {
|
|
1839
|
-
return new Promise((
|
|
1780
|
+
return new Promise((resolve2, reject) => {
|
|
1840
1781
|
Module["instantiateWasm"](info2, (mod, inst) => {
|
|
1841
|
-
|
|
1782
|
+
resolve2(receiveInstance(mod, inst));
|
|
1842
1783
|
});
|
|
1843
1784
|
});
|
|
1844
1785
|
}
|
|
@@ -3169,8 +3110,8 @@ async function Module2(moduleArg = {}) {
|
|
|
3169
3110
|
if (runtimeInitialized) {
|
|
3170
3111
|
moduleRtn = Module;
|
|
3171
3112
|
} else {
|
|
3172
|
-
moduleRtn = new Promise((
|
|
3173
|
-
readyPromiseResolve =
|
|
3113
|
+
moduleRtn = new Promise((resolve2, reject) => {
|
|
3114
|
+
readyPromiseResolve = resolve2;
|
|
3174
3115
|
readyPromiseReject = reject;
|
|
3175
3116
|
});
|
|
3176
3117
|
}
|
|
@@ -4032,32 +3973,14 @@ var Query = class {
|
|
|
4032
3973
|
};
|
|
4033
3974
|
|
|
4034
3975
|
// src/code-query/parser.ts
|
|
3976
|
+
import { existsSync, readFileSync } from "fs";
|
|
3977
|
+
import { createRequire } from "module";
|
|
3978
|
+
import { dirname, resolve } from "path";
|
|
3979
|
+
import { fileURLToPath } from "url";
|
|
4035
3980
|
var localRequire = createRequire(import.meta.url);
|
|
4036
|
-
var EXT_TO_GRAMMAR = {
|
|
4037
|
-
".ts": "typescript",
|
|
4038
|
-
".mts": "typescript",
|
|
4039
|
-
".cts": "typescript",
|
|
4040
|
-
".tsx": "tsx",
|
|
4041
|
-
".js": "javascript",
|
|
4042
|
-
".mjs": "javascript",
|
|
4043
|
-
".cjs": "javascript",
|
|
4044
|
-
".jsx": "javascript",
|
|
4045
|
-
".py": "python",
|
|
4046
|
-
".pyi": "python",
|
|
4047
|
-
".go": "go",
|
|
4048
|
-
".rs": "rust",
|
|
4049
|
-
".java": "java"
|
|
4050
|
-
};
|
|
4051
3981
|
var parserInitPromise = null;
|
|
4052
3982
|
var languageCache = /* @__PURE__ */ new Map();
|
|
4053
3983
|
var resolvedGrammarDir = null;
|
|
4054
|
-
function grammarForPath(filePath) {
|
|
4055
|
-
const lower = filePath.toLowerCase();
|
|
4056
|
-
for (const ext of Object.keys(EXT_TO_GRAMMAR)) {
|
|
4057
|
-
if (lower.endsWith(ext)) return EXT_TO_GRAMMAR[ext];
|
|
4058
|
-
}
|
|
4059
|
-
return null;
|
|
4060
|
-
}
|
|
4061
3984
|
async function getParser(grammar, opts = {}) {
|
|
4062
3985
|
if (!parserInitPromise) {
|
|
4063
3986
|
parserInitPromise = Parser.init({
|
|
@@ -4107,1095 +4030,8 @@ var DEV_PACKAGE_FOR_GRAMMAR = {
|
|
|
4107
4030
|
java: ["tree-sitter-java"]
|
|
4108
4031
|
};
|
|
4109
4032
|
|
|
4110
|
-
// src/code-query/find-in-code.ts
|
|
4111
|
-
var IDENTIFIER_TYPES = /* @__PURE__ */ new Set([
|
|
4112
|
-
"identifier",
|
|
4113
|
-
"property_identifier",
|
|
4114
|
-
"type_identifier",
|
|
4115
|
-
"shorthand_property_identifier",
|
|
4116
|
-
"shorthand_property_identifier_pattern",
|
|
4117
|
-
"field_identifier",
|
|
4118
|
-
"package_identifier"
|
|
4119
|
-
]);
|
|
4120
|
-
var DECLARATION_NAME_PARENTS = /* @__PURE__ */ new Set([
|
|
4121
|
-
"function_declaration",
|
|
4122
|
-
"function_signature",
|
|
4123
|
-
"class_declaration",
|
|
4124
|
-
"interface_declaration",
|
|
4125
|
-
"type_alias_declaration",
|
|
4126
|
-
"enum_declaration",
|
|
4127
|
-
"method_definition",
|
|
4128
|
-
"method_signature",
|
|
4129
|
-
"abstract_method_signature",
|
|
4130
|
-
"public_field_definition",
|
|
4131
|
-
"field_definition",
|
|
4132
|
-
"property_signature",
|
|
4133
|
-
"internal_module",
|
|
4134
|
-
"variable_declarator",
|
|
4135
|
-
"function_definition",
|
|
4136
|
-
"class_definition",
|
|
4137
|
-
"method_declaration",
|
|
4138
|
-
"type_spec",
|
|
4139
|
-
"function_item",
|
|
4140
|
-
"struct_item",
|
|
4141
|
-
"enum_item",
|
|
4142
|
-
"trait_item",
|
|
4143
|
-
"type_item",
|
|
4144
|
-
"mod_item",
|
|
4145
|
-
"const_item",
|
|
4146
|
-
"static_item",
|
|
4147
|
-
"constructor_declaration"
|
|
4148
|
-
]);
|
|
4149
|
-
var CALL_PARENT_TYPES = /* @__PURE__ */ new Set([
|
|
4150
|
-
"call_expression",
|
|
4151
|
-
"new_expression",
|
|
4152
|
-
"call",
|
|
4153
|
-
"method_invocation",
|
|
4154
|
-
"object_creation_expression"
|
|
4155
|
-
]);
|
|
4156
|
-
var MEMBER_PARENT_TYPES = /* @__PURE__ */ new Set([
|
|
4157
|
-
"member_expression",
|
|
4158
|
-
"attribute",
|
|
4159
|
-
"selector_expression",
|
|
4160
|
-
"field_expression"
|
|
4161
|
-
]);
|
|
4162
|
-
var CALLEE_FIELDS = ["function", "constructor", "name"];
|
|
4163
|
-
var MEMBER_NAME_FIELDS = ["property", "field", "attribute", "name"];
|
|
4164
|
-
async function findInCode(filePath, source, name2, opts = {}) {
|
|
4165
|
-
if (!name2) return [];
|
|
4166
|
-
const grammar = grammarForPath(filePath);
|
|
4167
|
-
if (!grammar) return [];
|
|
4168
|
-
const parser = await getParser(grammar);
|
|
4169
|
-
try {
|
|
4170
|
-
const tree = parser.parse(source);
|
|
4171
|
-
if (!tree) return [];
|
|
4172
|
-
try {
|
|
4173
|
-
const sourceLines = source.split(/\r?\n/);
|
|
4174
|
-
const matches = [];
|
|
4175
|
-
walk(tree.rootNode, (node) => {
|
|
4176
|
-
if (!IDENTIFIER_TYPES.has(node.type)) return;
|
|
4177
|
-
if (node.text !== name2) return;
|
|
4178
|
-
const kind = classify(node);
|
|
4179
|
-
const filter = opts.kind ?? "any";
|
|
4180
|
-
if (filter !== "any" && filter !== kind) return;
|
|
4181
|
-
const line = node.startPosition.row + 1;
|
|
4182
|
-
const column = node.startPosition.column + 1;
|
|
4183
|
-
matches.push({
|
|
4184
|
-
line,
|
|
4185
|
-
column,
|
|
4186
|
-
kind,
|
|
4187
|
-
snippet: sourceLines[node.startPosition.row] ?? ""
|
|
4188
|
-
});
|
|
4189
|
-
});
|
|
4190
|
-
return matches;
|
|
4191
|
-
} finally {
|
|
4192
|
-
tree.delete();
|
|
4193
|
-
}
|
|
4194
|
-
} finally {
|
|
4195
|
-
parser.delete();
|
|
4196
|
-
}
|
|
4197
|
-
}
|
|
4198
|
-
function classify(node) {
|
|
4199
|
-
const parent = node.parent;
|
|
4200
|
-
if (!parent) return "reference";
|
|
4201
|
-
if (DECLARATION_NAME_PARENTS.has(parent.type)) {
|
|
4202
|
-
const nameField = parent.childForFieldName("name");
|
|
4203
|
-
if (nameField && nameField.id === node.id) return "definition";
|
|
4204
|
-
}
|
|
4205
|
-
if (CALL_PARENT_TYPES.has(parent.type) && fieldMatches(parent, node, CALLEE_FIELDS)) {
|
|
4206
|
-
return "call";
|
|
4207
|
-
}
|
|
4208
|
-
if (MEMBER_PARENT_TYPES.has(parent.type) && fieldMatches(parent, node, MEMBER_NAME_FIELDS)) {
|
|
4209
|
-
const grandparent = parent.parent;
|
|
4210
|
-
if (grandparent && CALL_PARENT_TYPES.has(grandparent.type) && fieldMatches(grandparent, parent, CALLEE_FIELDS)) {
|
|
4211
|
-
return "call";
|
|
4212
|
-
}
|
|
4213
|
-
}
|
|
4214
|
-
return "reference";
|
|
4215
|
-
}
|
|
4216
|
-
function fieldMatches(parent, child, fields) {
|
|
4217
|
-
for (const field of fields) {
|
|
4218
|
-
const f = parent.childForFieldName(field);
|
|
4219
|
-
if (f && f.id === child.id) return true;
|
|
4220
|
-
}
|
|
4221
|
-
return false;
|
|
4222
|
-
}
|
|
4223
|
-
function walk(root, visit) {
|
|
4224
|
-
const cursor = root.walk();
|
|
4225
|
-
try {
|
|
4226
|
-
let visitedChildren = false;
|
|
4227
|
-
while (true) {
|
|
4228
|
-
if (!visitedChildren) visit(cursor.currentNode);
|
|
4229
|
-
if (!visitedChildren && cursor.gotoFirstChild()) continue;
|
|
4230
|
-
if (cursor.gotoNextSibling()) {
|
|
4231
|
-
visitedChildren = false;
|
|
4232
|
-
continue;
|
|
4233
|
-
}
|
|
4234
|
-
if (!cursor.gotoParent()) return;
|
|
4235
|
-
visitedChildren = true;
|
|
4236
|
-
}
|
|
4237
|
-
} finally {
|
|
4238
|
-
cursor.delete();
|
|
4239
|
-
}
|
|
4240
|
-
}
|
|
4241
|
-
|
|
4242
|
-
// src/code-query/symbols.ts
|
|
4243
|
-
var TS_QUERY = `
|
|
4244
|
-
(function_declaration name: (identifier) @name) @function
|
|
4245
|
-
(class_declaration name: (type_identifier) @name) @class
|
|
4246
|
-
(interface_declaration name: (type_identifier) @name) @interface
|
|
4247
|
-
(type_alias_declaration name: (type_identifier) @name) @type
|
|
4248
|
-
(enum_declaration name: (identifier) @name) @enum
|
|
4249
|
-
(method_definition name: (property_identifier) @name) @method
|
|
4250
|
-
(public_field_definition name: (property_identifier) @name) @property
|
|
4251
|
-
(variable_declarator name: (identifier) @name value: [(arrow_function) (function_expression)]) @function
|
|
4252
|
-
(internal_module name: (identifier) @name) @namespace
|
|
4253
|
-
`;
|
|
4254
|
-
var JS_QUERY = `
|
|
4255
|
-
(function_declaration name: (identifier) @name) @function
|
|
4256
|
-
(class_declaration name: (identifier) @name) @class
|
|
4257
|
-
(method_definition name: (property_identifier) @name) @method
|
|
4258
|
-
(field_definition property: (property_identifier) @name) @property
|
|
4259
|
-
(variable_declarator name: (identifier) @name value: [(arrow_function) (function_expression)]) @function
|
|
4260
|
-
`;
|
|
4261
|
-
var PYTHON_QUERY = `
|
|
4262
|
-
(function_definition name: (identifier) @name) @function
|
|
4263
|
-
(class_definition name: (identifier) @name) @class
|
|
4264
|
-
`;
|
|
4265
|
-
var GO_QUERY = `
|
|
4266
|
-
(function_declaration name: (identifier) @name) @function
|
|
4267
|
-
(method_declaration name: (field_identifier) @name) @method
|
|
4268
|
-
(type_spec name: (type_identifier) @name type: (struct_type)) @class
|
|
4269
|
-
(type_spec name: (type_identifier) @name type: (interface_type)) @interface
|
|
4270
|
-
(type_spec name: (type_identifier) @name) @type
|
|
4271
|
-
`;
|
|
4272
|
-
var RUST_QUERY = `
|
|
4273
|
-
(function_item name: (identifier) @name) @function
|
|
4274
|
-
(struct_item name: (type_identifier) @name) @class
|
|
4275
|
-
(enum_item name: (type_identifier) @name) @enum
|
|
4276
|
-
(trait_item name: (type_identifier) @name) @interface
|
|
4277
|
-
(type_item name: (type_identifier) @name) @type
|
|
4278
|
-
(mod_item name: (identifier) @name) @namespace
|
|
4279
|
-
(const_item name: (identifier) @name) @property
|
|
4280
|
-
(static_item name: (identifier) @name) @property
|
|
4281
|
-
`;
|
|
4282
|
-
var JAVA_QUERY = `
|
|
4283
|
-
(class_declaration name: (identifier) @name) @class
|
|
4284
|
-
(interface_declaration name: (identifier) @name) @interface
|
|
4285
|
-
(enum_declaration name: (identifier) @name) @enum
|
|
4286
|
-
(method_declaration name: (identifier) @name) @method
|
|
4287
|
-
(constructor_declaration name: (identifier) @name) @method
|
|
4288
|
-
(field_declaration declarator: (variable_declarator name: (identifier) @name)) @property
|
|
4289
|
-
`;
|
|
4290
|
-
var QUERIES = {
|
|
4291
|
-
typescript: TS_QUERY,
|
|
4292
|
-
tsx: TS_QUERY,
|
|
4293
|
-
javascript: JS_QUERY,
|
|
4294
|
-
python: PYTHON_QUERY,
|
|
4295
|
-
go: GO_QUERY,
|
|
4296
|
-
rust: RUST_QUERY,
|
|
4297
|
-
java: JAVA_QUERY
|
|
4298
|
-
};
|
|
4299
|
-
var KIND_CAPTURE_NAMES = /* @__PURE__ */ new Set([
|
|
4300
|
-
"function",
|
|
4301
|
-
"class",
|
|
4302
|
-
"interface",
|
|
4303
|
-
"type",
|
|
4304
|
-
"enum",
|
|
4305
|
-
"method",
|
|
4306
|
-
"property",
|
|
4307
|
-
"namespace"
|
|
4308
|
-
]);
|
|
4309
|
-
var PARENT_CONTAINER_TYPES = /* @__PURE__ */ new Set([
|
|
4310
|
-
"class_declaration",
|
|
4311
|
-
"interface_declaration",
|
|
4312
|
-
"internal_module",
|
|
4313
|
-
"class_definition",
|
|
4314
|
-
"impl_item",
|
|
4315
|
-
"trait_item",
|
|
4316
|
-
"mod_item"
|
|
4317
|
-
]);
|
|
4318
|
-
var METHOD_PROMOTING_CONTAINER_TYPES = /* @__PURE__ */ new Set([
|
|
4319
|
-
"class_declaration",
|
|
4320
|
-
"class_definition",
|
|
4321
|
-
"interface_declaration",
|
|
4322
|
-
"impl_item",
|
|
4323
|
-
"trait_item"
|
|
4324
|
-
]);
|
|
4325
|
-
async function extractSymbols(filePath, source) {
|
|
4326
|
-
const grammar = grammarForPath(filePath);
|
|
4327
|
-
if (!grammar) return [];
|
|
4328
|
-
const parser = await getParser(grammar);
|
|
4329
|
-
try {
|
|
4330
|
-
const tree = parser.parse(source);
|
|
4331
|
-
if (!tree) return [];
|
|
4332
|
-
const language = parser.language;
|
|
4333
|
-
if (!language) return [];
|
|
4334
|
-
const query = new Query(language, QUERIES[grammar]);
|
|
4335
|
-
try {
|
|
4336
|
-
const matches = query.matches(tree.rootNode);
|
|
4337
|
-
return matchesToSymbols(matches);
|
|
4338
|
-
} finally {
|
|
4339
|
-
query.delete();
|
|
4340
|
-
tree.delete();
|
|
4341
|
-
}
|
|
4342
|
-
} finally {
|
|
4343
|
-
parser.delete();
|
|
4344
|
-
}
|
|
4345
|
-
}
|
|
4346
|
-
function matchesToSymbols(matches) {
|
|
4347
|
-
const out2 = [];
|
|
4348
|
-
for (const match of matches) {
|
|
4349
|
-
let nameNode = null;
|
|
4350
|
-
let containerNode = null;
|
|
4351
|
-
let kind = null;
|
|
4352
|
-
for (const cap of match.captures) {
|
|
4353
|
-
if (cap.name === "name") {
|
|
4354
|
-
nameNode = cap.node;
|
|
4355
|
-
} else if (KIND_CAPTURE_NAMES.has(cap.name)) {
|
|
4356
|
-
containerNode = cap.node;
|
|
4357
|
-
kind = cap.name;
|
|
4358
|
-
}
|
|
4359
|
-
}
|
|
4360
|
-
if (!nameNode || !containerNode || !kind) continue;
|
|
4361
|
-
const enclosing = findEnclosingContainer(containerNode);
|
|
4362
|
-
if (kind === "function" && enclosing && METHOD_PROMOTING_CONTAINER_TYPES.has(enclosing.type)) {
|
|
4363
|
-
kind = "method";
|
|
4364
|
-
}
|
|
4365
|
-
out2.push({
|
|
4366
|
-
name: nameNode.text,
|
|
4367
|
-
kind,
|
|
4368
|
-
line: containerNode.startPosition.row + 1,
|
|
4369
|
-
column: containerNode.startPosition.column + 1,
|
|
4370
|
-
endLine: containerNode.endPosition.row + 1,
|
|
4371
|
-
endColumn: containerNode.endPosition.column + 1,
|
|
4372
|
-
parent: enclosing ? containerNameOf(enclosing) : void 0
|
|
4373
|
-
});
|
|
4374
|
-
}
|
|
4375
|
-
out2.sort((a, b) => a.line - b.line || a.column - b.column);
|
|
4376
|
-
return out2;
|
|
4377
|
-
}
|
|
4378
|
-
function findEnclosingContainer(node) {
|
|
4379
|
-
let current = node.parent;
|
|
4380
|
-
while (current) {
|
|
4381
|
-
if (PARENT_CONTAINER_TYPES.has(current.type)) return current;
|
|
4382
|
-
current = current.parent;
|
|
4383
|
-
}
|
|
4384
|
-
return null;
|
|
4385
|
-
}
|
|
4386
|
-
function containerNameOf(container) {
|
|
4387
|
-
if (container.type === "impl_item") {
|
|
4388
|
-
const typeField = container.childForFieldName("type");
|
|
4389
|
-
if (typeField) return typeField.text;
|
|
4390
|
-
}
|
|
4391
|
-
const nameField = container.childForFieldName("name");
|
|
4392
|
-
return nameField?.text;
|
|
4393
|
-
}
|
|
4394
|
-
|
|
4395
|
-
// src/tools/code-query.ts
|
|
4396
|
-
var UNSUPPORTED = "language not supported (TS/TSX/JS/JSX/Python/Go/Rust/Java); use search_content for grep-style matching";
|
|
4397
|
-
function registerCodeQueryTools(registry, opts) {
|
|
4398
|
-
const { rootDir } = opts;
|
|
4399
|
-
registry.register({
|
|
4400
|
-
name: "get_symbols",
|
|
4401
|
-
description: "Outline a single TS/TSX/JS/JSX/Python/Go/Rust/Java file via tree-sitter \u2014 returns its top-level + nested symbols (functions, classes, methods, interfaces, types, enums, namespaces) with 1-based line/column. Grammar-aware, ignores names inside comments/strings. Use for 'what's in this file' / 'where is X defined here'; for cross-file scans use search_content. Result: {path, symbols:[{name, kind, line, column, endLine, endColumn, parent?}]} or {path, error}.",
|
|
4402
|
-
readOnly: true,
|
|
4403
|
-
parallelSafe: true,
|
|
4404
|
-
stormExempt: true,
|
|
4405
|
-
parameters: {
|
|
4406
|
-
type: "object",
|
|
4407
|
-
properties: {
|
|
4408
|
-
path: {
|
|
4409
|
-
type: "string",
|
|
4410
|
-
description: "File path (relative to project root or absolute)."
|
|
4411
|
-
}
|
|
4412
|
-
},
|
|
4413
|
-
required: ["path"]
|
|
4414
|
-
},
|
|
4415
|
-
fn: async (args2) => {
|
|
4416
|
-
const filePath = resolveProjectPath(rootDir, args2.path);
|
|
4417
|
-
if (!grammarForPath(filePath)) {
|
|
4418
|
-
return JSON.stringify({ path: args2.path, error: UNSUPPORTED });
|
|
4419
|
-
}
|
|
4420
|
-
const source = await readFile(filePath, "utf8");
|
|
4421
|
-
const symbols = await extractSymbols(filePath, source);
|
|
4422
|
-
return JSON.stringify({ path: args2.path, symbols });
|
|
4423
|
-
}
|
|
4424
|
-
});
|
|
4425
|
-
registry.register({
|
|
4426
|
-
name: "find_in_code",
|
|
4427
|
-
description: "Find an identifier `name` in a single TS/TSX/JS/JSX/Python/Go/Rust/Java file, AST-filtered \u2014 skips matches inside comments and strings. Optional `kind` narrows by syntactic role: 'call' (function call site), 'definition' (declaration name), 'reference' (other uses), 'any' (default). Within-file only \u2014 does NOT resolve cross-file references; use search_content + reading for that. Result: {path, matches:[{line, column, kind, snippet}]} or {path, error}.",
|
|
4428
|
-
readOnly: true,
|
|
4429
|
-
parallelSafe: true,
|
|
4430
|
-
stormExempt: true,
|
|
4431
|
-
parameters: {
|
|
4432
|
-
type: "object",
|
|
4433
|
-
properties: {
|
|
4434
|
-
name: {
|
|
4435
|
-
type: "string",
|
|
4436
|
-
description: "Exact identifier text to find."
|
|
4437
|
-
},
|
|
4438
|
-
path: {
|
|
4439
|
-
type: "string",
|
|
4440
|
-
description: "File path (relative to project root or absolute)."
|
|
4441
|
-
},
|
|
4442
|
-
kind: {
|
|
4443
|
-
type: "string",
|
|
4444
|
-
enum: ["any", "call", "definition", "reference"],
|
|
4445
|
-
description: "Filter by syntactic role. Default 'any'."
|
|
4446
|
-
}
|
|
4447
|
-
},
|
|
4448
|
-
required: ["name", "path"]
|
|
4449
|
-
},
|
|
4450
|
-
fn: async (args2) => {
|
|
4451
|
-
const filePath = resolveProjectPath(rootDir, args2.path);
|
|
4452
|
-
if (!grammarForPath(filePath)) {
|
|
4453
|
-
return JSON.stringify({ path: args2.path, error: UNSUPPORTED });
|
|
4454
|
-
}
|
|
4455
|
-
const source = await readFile(filePath, "utf8");
|
|
4456
|
-
const kind = args2.kind ?? "any";
|
|
4457
|
-
const findOpts = kind === "any" ? {} : { kind };
|
|
4458
|
-
const matches = await findInCode(filePath, source, args2.name, findOpts);
|
|
4459
|
-
return JSON.stringify({ path: args2.path, matches });
|
|
4460
|
-
}
|
|
4461
|
-
});
|
|
4462
|
-
}
|
|
4463
|
-
function resolveProjectPath(rootDir, raw) {
|
|
4464
|
-
const stripped = raw.replace(/^[/\\]+/, "");
|
|
4465
|
-
return pathResolve(rootDir, stripped.length === 0 ? "." : stripped);
|
|
4466
|
-
}
|
|
4467
|
-
|
|
4468
|
-
// src/java/class-source-finder.ts
|
|
4469
|
-
import { execFile } from "child_process";
|
|
4470
|
-
import * as fs3 from "fs";
|
|
4471
|
-
import * as fsp from "fs/promises";
|
|
4472
|
-
import * as os from "os";
|
|
4473
|
-
import * as path from "path";
|
|
4474
|
-
|
|
4475
|
-
// src/java/zip-reader.ts
|
|
4476
|
-
import * as fs2 from "fs";
|
|
4477
|
-
import * as zlib from "zlib";
|
|
4478
|
-
var EOCD_SIGNATURE = 101010256;
|
|
4479
|
-
var CENTRAL_DIR_SIGNATURE = 33639248;
|
|
4480
|
-
var LOCAL_FILE_SIGNATURE = 67324752;
|
|
4481
|
-
var EOCD_MIN_SIZE = 22;
|
|
4482
|
-
var EOCD_MAX_COMMENT = 65535;
|
|
4483
|
-
var COMPRESSION_STORED = 0;
|
|
4484
|
-
var COMPRESSION_DEFLATED = 8;
|
|
4485
|
-
function readU32LE(buf, offset) {
|
|
4486
|
-
return buf.readUInt32LE(offset);
|
|
4487
|
-
}
|
|
4488
|
-
function readU16LE(buf, offset) {
|
|
4489
|
-
return buf.readUInt16LE(offset);
|
|
4490
|
-
}
|
|
4491
|
-
function findEOCD(fd, fileSize) {
|
|
4492
|
-
const searchStart = Math.max(0, fileSize - EOCD_MAX_COMMENT - EOCD_MIN_SIZE);
|
|
4493
|
-
let chunkOffset = fileSize;
|
|
4494
|
-
while (chunkOffset > searchStart) {
|
|
4495
|
-
const readSize = Math.min(1024, chunkOffset - searchStart);
|
|
4496
|
-
chunkOffset -= readSize;
|
|
4497
|
-
const buf = Buffer.alloc(readSize);
|
|
4498
|
-
fs2.readSync(fd, buf, 0, readSize, chunkOffset);
|
|
4499
|
-
for (let i2 = readSize - 4; i2 >= 0; i2--) {
|
|
4500
|
-
if (buf.readUInt32LE(i2) === EOCD_SIGNATURE) {
|
|
4501
|
-
const eocdOffset = chunkOffset + i2;
|
|
4502
|
-
const eocdSize = Math.min(EOCD_MIN_SIZE + EOCD_MAX_COMMENT, fileSize - eocdOffset);
|
|
4503
|
-
const eocdBuf = Buffer.alloc(eocdSize);
|
|
4504
|
-
fs2.readSync(fd, eocdBuf, 0, eocdSize, eocdOffset);
|
|
4505
|
-
return { offset: eocdOffset, buf: eocdBuf };
|
|
4506
|
-
}
|
|
4507
|
-
}
|
|
4508
|
-
}
|
|
4509
|
-
throw new Error("Not a valid ZIP file: EOCD signature not found");
|
|
4510
|
-
}
|
|
4511
|
-
function parseCentralDirectory(fd, eocdBuf) {
|
|
4512
|
-
const centralDirOffset = readU32LE(eocdBuf, 16);
|
|
4513
|
-
const totalEntries = readU16LE(eocdBuf, 10);
|
|
4514
|
-
const entries = [];
|
|
4515
|
-
let offset = centralDirOffset;
|
|
4516
|
-
for (let i2 = 0; i2 < totalEntries; i2++) {
|
|
4517
|
-
const headerBuf = Buffer.alloc(46);
|
|
4518
|
-
fs2.readSync(fd, headerBuf, 0, 46, offset);
|
|
4519
|
-
if (readU32LE(headerBuf, 0) !== CENTRAL_DIR_SIGNATURE) {
|
|
4520
|
-
throw new Error(`Corrupt central directory at offset ${offset}`);
|
|
4521
|
-
}
|
|
4522
|
-
const compressionMethod = readU16LE(headerBuf, 10);
|
|
4523
|
-
const compressedSize = readU32LE(headerBuf, 20);
|
|
4524
|
-
const uncompressedSize = readU32LE(headerBuf, 24);
|
|
4525
|
-
const fileNameLen = readU16LE(headerBuf, 28);
|
|
4526
|
-
const extraLen = readU16LE(headerBuf, 30);
|
|
4527
|
-
const commentLen = readU16LE(headerBuf, 32);
|
|
4528
|
-
const localHeaderOffset = readU32LE(headerBuf, 42);
|
|
4529
|
-
const nameBuf = Buffer.alloc(fileNameLen);
|
|
4530
|
-
fs2.readSync(fd, nameBuf, 0, fileNameLen, offset + 46);
|
|
4531
|
-
const fileName = nameBuf.toString("utf8");
|
|
4532
|
-
entries.push({
|
|
4533
|
-
fileName,
|
|
4534
|
-
compressionMethod,
|
|
4535
|
-
compressedSize,
|
|
4536
|
-
uncompressedSize,
|
|
4537
|
-
localHeaderOffset
|
|
4538
|
-
});
|
|
4539
|
-
offset += 46 + fileNameLen + extraLen + commentLen;
|
|
4540
|
-
}
|
|
4541
|
-
return entries;
|
|
4542
|
-
}
|
|
4543
|
-
function readJarEntry(jarPath, entryName) {
|
|
4544
|
-
const fd = fs2.openSync(jarPath, "r");
|
|
4545
|
-
try {
|
|
4546
|
-
const stat = fs2.fstatSync(fd);
|
|
4547
|
-
const fileSize = stat.size;
|
|
4548
|
-
const eocd = findEOCD(fd, fileSize);
|
|
4549
|
-
const entries = parseCentralDirectory(fd, eocd.buf);
|
|
4550
|
-
const target = entries.find((e) => e.fileName === entryName);
|
|
4551
|
-
if (!target) return null;
|
|
4552
|
-
const localHeaderBuf = Buffer.alloc(30);
|
|
4553
|
-
fs2.readSync(fd, localHeaderBuf, 0, 30, target.localHeaderOffset);
|
|
4554
|
-
if (readU32LE(localHeaderBuf, 0) !== LOCAL_FILE_SIGNATURE) {
|
|
4555
|
-
throw new Error(`Corrupt local file header at offset ${target.localHeaderOffset}`);
|
|
4556
|
-
}
|
|
4557
|
-
const localFileNameLen = readU16LE(localHeaderBuf, 26);
|
|
4558
|
-
const localExtraLen = readU16LE(localHeaderBuf, 28);
|
|
4559
|
-
const dataOffset = target.localHeaderOffset + 30 + localFileNameLen + localExtraLen;
|
|
4560
|
-
const compressedBuf = Buffer.alloc(target.compressedSize);
|
|
4561
|
-
fs2.readSync(fd, compressedBuf, 0, target.compressedSize, dataOffset);
|
|
4562
|
-
let data;
|
|
4563
|
-
if (target.compressionMethod === COMPRESSION_STORED) {
|
|
4564
|
-
data = compressedBuf;
|
|
4565
|
-
} else if (target.compressionMethod === COMPRESSION_DEFLATED) {
|
|
4566
|
-
data = zlib.inflateRawSync(compressedBuf);
|
|
4567
|
-
} else {
|
|
4568
|
-
throw new Error(
|
|
4569
|
-
`Unsupported compression method ${target.compressionMethod} for entry "${entryName}"`
|
|
4570
|
-
);
|
|
4571
|
-
}
|
|
4572
|
-
return { fileName: target.fileName, data };
|
|
4573
|
-
} finally {
|
|
4574
|
-
fs2.closeSync(fd);
|
|
4575
|
-
}
|
|
4576
|
-
}
|
|
4577
|
-
|
|
4578
|
-
// src/java/class-source-finder.ts
|
|
4579
|
-
var ClassSourceFinder = class _ClassSourceFinder {
|
|
4580
|
-
projectRoot;
|
|
4581
|
-
repoPaths;
|
|
4582
|
-
javapCommand;
|
|
4583
|
-
maxJarScan;
|
|
4584
|
-
signal;
|
|
4585
|
-
static defaultRepoPaths() {
|
|
4586
|
-
const home = os.homedir();
|
|
4587
|
-
const candidates = [path.join(home, ".m2", "repository"), path.join(home, ".gradle", "caches")];
|
|
4588
|
-
return candidates.filter((p) => fs3.existsSync(p));
|
|
4589
|
-
}
|
|
4590
|
-
constructor(options) {
|
|
4591
|
-
this.projectRoot = path.resolve(options.projectRoot);
|
|
4592
|
-
this.repoPaths = options.repoPaths && options.repoPaths.length > 0 ? options.repoPaths.map((p) => path.resolve(p)) : _ClassSourceFinder.defaultRepoPaths();
|
|
4593
|
-
this.javapCommand = options.javapCommand ?? "javap";
|
|
4594
|
-
this.maxJarScan = options.maxJarScan ?? 2e3;
|
|
4595
|
-
this.signal = options.signal;
|
|
4596
|
-
}
|
|
4597
|
-
async findSource(fullyQualifiedName, options) {
|
|
4598
|
-
this.throwIfAborted();
|
|
4599
|
-
const projectResult = await this.searchProject(fullyQualifiedName);
|
|
4600
|
-
if (projectResult) return projectResult;
|
|
4601
|
-
return this.searchRepositories(fullyQualifiedName, options?.jarKeyword);
|
|
4602
|
-
}
|
|
4603
|
-
async findSourceInJar(fullyQualifiedName, jarPath) {
|
|
4604
|
-
this.throwIfAborted();
|
|
4605
|
-
const resolvedJarPath = path.resolve(jarPath);
|
|
4606
|
-
if (!fs3.existsSync(resolvedJarPath)) {
|
|
4607
|
-
return { found: false, method: "not-found" };
|
|
4608
|
-
}
|
|
4609
|
-
const classEntry = `${fullyQualifiedName.replace(/\./g, "/")}.class`;
|
|
4610
|
-
try {
|
|
4611
|
-
const content = readJarEntry(resolvedJarPath, classEntry);
|
|
4612
|
-
if (!content) return { found: false, method: "not-found" };
|
|
4613
|
-
const source = await this.decompileFromJar(resolvedJarPath, content.data, fullyQualifiedName);
|
|
4614
|
-
return { found: true, source, method: "jar", sourcePath: resolvedJarPath };
|
|
4615
|
-
} catch (err2) {
|
|
4616
|
-
return { found: false, method: "not-found" };
|
|
4617
|
-
}
|
|
4618
|
-
}
|
|
4619
|
-
async searchProject(fqn) {
|
|
4620
|
-
const simpleName = this.simpleClassName(fqn);
|
|
4621
|
-
const suffixes = [`${simpleName}.java`, `${simpleName}.java.txt`];
|
|
4622
|
-
const queue = [this.projectRoot];
|
|
4623
|
-
while (queue.length > 0) {
|
|
4624
|
-
this.throwIfAborted();
|
|
4625
|
-
const dir = queue.shift();
|
|
4626
|
-
let entries;
|
|
4627
|
-
try {
|
|
4628
|
-
entries = await fsp.readdir(dir, { withFileTypes: true });
|
|
4629
|
-
} catch {
|
|
4630
|
-
continue;
|
|
4631
|
-
}
|
|
4632
|
-
for (const entry of entries) {
|
|
4633
|
-
const fullPath = path.join(dir, entry.name);
|
|
4634
|
-
if (entry.isDirectory()) {
|
|
4635
|
-
if (entry.name === "node_modules" || entry.name === ".git" || entry.name === "target" || entry.name === "build" || entry.name === "dist" || entry.name === ".idea" || entry.name === ".vscode" || entry.name === ".gradle") {
|
|
4636
|
-
continue;
|
|
4637
|
-
}
|
|
4638
|
-
queue.push(fullPath);
|
|
4639
|
-
} else if (entry.isFile()) {
|
|
4640
|
-
if (suffixes.includes(entry.name)) {
|
|
4641
|
-
const source = await fsp.readFile(fullPath, "utf-8");
|
|
4642
|
-
return { found: true, source, method: "project", sourcePath: fullPath };
|
|
4643
|
-
}
|
|
4644
|
-
}
|
|
4645
|
-
}
|
|
4646
|
-
}
|
|
4647
|
-
return null;
|
|
4648
|
-
}
|
|
4649
|
-
async searchRepositories(fqn, jarKeyword) {
|
|
4650
|
-
const javaEntry = `${fqn.replace(/\./g, "/")}.java`;
|
|
4651
|
-
const classEntry = `${fqn.replace(/\./g, "/")}.class`;
|
|
4652
|
-
const sourceJars = [];
|
|
4653
|
-
const regularJars = [];
|
|
4654
|
-
for (const repoDir of this.repoPaths) {
|
|
4655
|
-
await this.walkForJars(repoDir, sourceJars, regularJars, jarKeyword);
|
|
4656
|
-
}
|
|
4657
|
-
for (const jarPath of sourceJars) {
|
|
4658
|
-
this.throwIfAborted();
|
|
4659
|
-
try {
|
|
4660
|
-
const content = readJarEntry(jarPath, javaEntry);
|
|
4661
|
-
if (content) {
|
|
4662
|
-
return {
|
|
4663
|
-
found: true,
|
|
4664
|
-
source: content.data.toString("utf-8"),
|
|
4665
|
-
method: "m2-source-jar",
|
|
4666
|
-
sourcePath: jarPath
|
|
4667
|
-
};
|
|
4668
|
-
}
|
|
4669
|
-
} catch {
|
|
4670
|
-
}
|
|
4671
|
-
}
|
|
4672
|
-
let scanned = 0;
|
|
4673
|
-
for (const jarPath of regularJars) {
|
|
4674
|
-
this.throwIfAborted();
|
|
4675
|
-
if (scanned >= this.maxJarScan) break;
|
|
4676
|
-
scanned++;
|
|
4677
|
-
try {
|
|
4678
|
-
const content = readJarEntry(jarPath, classEntry);
|
|
4679
|
-
if (content) {
|
|
4680
|
-
const source = await this.decompileFromJar(jarPath, content.data, fqn);
|
|
4681
|
-
return { found: true, source, method: "m2-jar", sourcePath: jarPath };
|
|
4682
|
-
}
|
|
4683
|
-
} catch {
|
|
4684
|
-
}
|
|
4685
|
-
}
|
|
4686
|
-
return { found: false, method: "not-found" };
|
|
4687
|
-
}
|
|
4688
|
-
static MAX_WALK_DEPTH = 64;
|
|
4689
|
-
async walkForJars(dir, sourceJars, regularJars, keyword, depth = 0) {
|
|
4690
|
-
if (depth >= _ClassSourceFinder.MAX_WALK_DEPTH) return;
|
|
4691
|
-
let entries;
|
|
4692
|
-
try {
|
|
4693
|
-
entries = await fsp.readdir(dir, { withFileTypes: true });
|
|
4694
|
-
} catch {
|
|
4695
|
-
return;
|
|
4696
|
-
}
|
|
4697
|
-
for (const entry of entries) {
|
|
4698
|
-
this.throwIfAborted();
|
|
4699
|
-
if (sourceJars.length + regularJars.length >= this.maxJarScan) return;
|
|
4700
|
-
const fullPath = path.join(dir, entry.name);
|
|
4701
|
-
if (entry.isDirectory()) {
|
|
4702
|
-
await this.walkForJars(fullPath, sourceJars, regularJars, keyword, depth + 1);
|
|
4703
|
-
} else if (entry.isFile() && entry.name.endsWith(".jar")) {
|
|
4704
|
-
if (!keyword || fullPath.toLowerCase().includes(keyword.toLowerCase())) {
|
|
4705
|
-
if (entry.name.endsWith("-sources.jar") || entry.name.includes("-sources-")) {
|
|
4706
|
-
sourceJars.push(fullPath);
|
|
4707
|
-
} else {
|
|
4708
|
-
regularJars.push(fullPath);
|
|
4709
|
-
}
|
|
4710
|
-
}
|
|
4711
|
-
}
|
|
4712
|
-
}
|
|
4713
|
-
}
|
|
4714
|
-
async decompileFromJar(jarPath, classBytes, fqn) {
|
|
4715
|
-
const tmpDir = await fsp.mkdtemp(path.join(os.tmpdir(), "reasonix-java-src-"));
|
|
4716
|
-
try {
|
|
4717
|
-
const pkgPath = fqn.replace(/\./g, path.sep);
|
|
4718
|
-
const classDir = path.join(tmpDir, path.dirname(pkgPath));
|
|
4719
|
-
await fsp.mkdir(classDir, { recursive: true });
|
|
4720
|
-
const classFile = path.join(tmpDir, `${pkgPath}.class`);
|
|
4721
|
-
await fsp.writeFile(classFile, classBytes);
|
|
4722
|
-
const raw = await this.runJavap(fqn, tmpDir);
|
|
4723
|
-
return _ClassSourceFinder.compressJavapOutput(raw);
|
|
4724
|
-
} finally {
|
|
4725
|
-
await fsp.rm(tmpDir, { recursive: true, force: true }).catch(() => {
|
|
4726
|
-
});
|
|
4727
|
-
}
|
|
4728
|
-
}
|
|
4729
|
-
// Strip constant pool, debug tables (LineNumberTable / LocalVariableTable /
|
|
4730
|
-
// StackMapTable), and "Compiled from …" from javap output — cuts ~60-80% of
|
|
4731
|
-
// tokens for AI consumption while keeping method sigs + bytecode.
|
|
4732
|
-
static compressJavapOutput(raw) {
|
|
4733
|
-
const lines = raw.split("\n");
|
|
4734
|
-
const out2 = [];
|
|
4735
|
-
let skipUntilIndent = null;
|
|
4736
|
-
for (const line of lines) {
|
|
4737
|
-
if (/^\s+#\d+\s*=/.test(line)) continue;
|
|
4738
|
-
if (skipUntilIndent !== null) {
|
|
4739
|
-
const m = line.match(/^(\s*)/);
|
|
4740
|
-
const indent = m?.[1]?.length ?? 0;
|
|
4741
|
-
if (indent > skipUntilIndent) continue;
|
|
4742
|
-
skipUntilIndent = null;
|
|
4743
|
-
if (line.trim() === "") continue;
|
|
4744
|
-
}
|
|
4745
|
-
const debugMatch = line.match(/^(\s+)(LineNumberTable|LocalVariableTable|StackMapTable):/);
|
|
4746
|
-
if (debugMatch) {
|
|
4747
|
-
skipUntilIndent = debugMatch[1].length;
|
|
4748
|
-
continue;
|
|
4749
|
-
}
|
|
4750
|
-
if (line.startsWith("Compiled from ")) continue;
|
|
4751
|
-
out2.push(line);
|
|
4752
|
-
}
|
|
4753
|
-
return out2.join("\n").replace(/\n{3,}/g, "\n\n").trim();
|
|
4754
|
-
}
|
|
4755
|
-
runJavap(className, classPath) {
|
|
4756
|
-
return new Promise((resolve3, reject) => {
|
|
4757
|
-
execFile(
|
|
4758
|
-
this.javapCommand,
|
|
4759
|
-
["-c", "-p", "-cp", classPath, className],
|
|
4760
|
-
{
|
|
4761
|
-
maxBuffer: 15 * 1024 * 1024,
|
|
4762
|
-
timeout: 3e4,
|
|
4763
|
-
signal: this.signal
|
|
4764
|
-
},
|
|
4765
|
-
(err2, stdout, stderr) => {
|
|
4766
|
-
if (err2) {
|
|
4767
|
-
const msg = [stdout, stderr].filter(Boolean).join("\n") || err2.message;
|
|
4768
|
-
reject(new Error(`javap failed: ${msg}`));
|
|
4769
|
-
return;
|
|
4770
|
-
}
|
|
4771
|
-
resolve3(stdout);
|
|
4772
|
-
}
|
|
4773
|
-
);
|
|
4774
|
-
});
|
|
4775
|
-
}
|
|
4776
|
-
simpleClassName(fqn) {
|
|
4777
|
-
const lastDot = fqn.lastIndexOf(".");
|
|
4778
|
-
return lastDot === -1 ? fqn : fqn.slice(lastDot + 1);
|
|
4779
|
-
}
|
|
4780
|
-
throwIfAborted() {
|
|
4781
|
-
if (this.signal?.aborted) {
|
|
4782
|
-
throw new DOMException("Aborted", "AbortError");
|
|
4783
|
-
}
|
|
4784
|
-
}
|
|
4785
|
-
};
|
|
4786
|
-
|
|
4787
|
-
// src/tools/java-source.ts
|
|
4788
|
-
function registerJavaSourceTool(registry, opts = {}) {
|
|
4789
|
-
registry.register({
|
|
4790
|
-
name: "java_source",
|
|
4791
|
-
description: [
|
|
4792
|
-
"Find and return Java source code by fully-qualified class name.",
|
|
4793
|
-
"",
|
|
4794
|
-
"Search mode: walk the project tree for a `.java` file, then scan `~/.m2/repository` jars whose filename or path contains `jarKeyword`.",
|
|
4795
|
-
"",
|
|
4796
|
-
"Returns the source text (or decompiled bytecode) on success, or a clear 'not found' message.",
|
|
4797
|
-
"Only call this tool once per class name \u2014 it's I/O heavy."
|
|
4798
|
-
].join("\n"),
|
|
4799
|
-
readOnly: true,
|
|
4800
|
-
parameters: {
|
|
4801
|
-
type: "object",
|
|
4802
|
-
properties: {
|
|
4803
|
-
className: {
|
|
4804
|
-
type: "string",
|
|
4805
|
-
description: 'Fully qualified Java class name, e.g. "com.google.common.collect.Lists" or "org.springframework.web.servlet.DispatcherServlet".'
|
|
4806
|
-
},
|
|
4807
|
-
jarKeyword: {
|
|
4808
|
-
type: "string",
|
|
4809
|
-
description: 'Only search jars whose filename or path contains this keyword (case-insensitive). Keep it short \u2014 a narrow substring like "spring-core", "guava", or "mycompany-utils" scans faster and matches more precisely than a long fragment.'
|
|
4810
|
-
}
|
|
4811
|
-
},
|
|
4812
|
-
required: ["className", "jarKeyword"]
|
|
4813
|
-
},
|
|
4814
|
-
parallelSafe: true,
|
|
4815
|
-
fn: async (args2) => {
|
|
4816
|
-
const className = (args2?.className ?? "").trim();
|
|
4817
|
-
if (!className) {
|
|
4818
|
-
throw new Error("java_source: `className` is required");
|
|
4819
|
-
}
|
|
4820
|
-
if (!/^[a-zA-Z_$][\w$]*(\.[a-zA-Z_$][\w$]*)*$/.test(className)) {
|
|
4821
|
-
throw new Error(
|
|
4822
|
-
`java_source: "${className}" is not a valid fully qualified Java class name. Expected format: \`com.example.MyClass\``
|
|
4823
|
-
);
|
|
4824
|
-
}
|
|
4825
|
-
const jarKeyword = args2.jarKeyword.trim();
|
|
4826
|
-
if (!jarKeyword) {
|
|
4827
|
-
throw new Error("java_source: `jarKeyword` must not be empty");
|
|
4828
|
-
}
|
|
4829
|
-
const projectRoot = opts.projectRoot || process.cwd();
|
|
4830
|
-
const finder = new ClassSourceFinder({ projectRoot });
|
|
4831
|
-
const result = await finder.findSource(className, { jarKeyword });
|
|
4832
|
-
if (!result.found) {
|
|
4833
|
-
const keywordLine = ` \u2022 Maven .m2 / Gradle cache for jars containing keyword "${jarKeyword}"`;
|
|
4834
|
-
const tip = "Try a different keyword, or check if the class is in a different library.";
|
|
4835
|
-
return JSON.stringify({
|
|
4836
|
-
status: "not-found",
|
|
4837
|
-
className,
|
|
4838
|
-
message: `No source found for "${className}". Searched:
|
|
4839
|
-
\u2022 ${projectRoot}/ for matching .java files
|
|
4840
|
-
${keywordLine}
|
|
4841
|
-
|
|
4842
|
-
${tip}`
|
|
4843
|
-
});
|
|
4844
|
-
}
|
|
4845
|
-
return JSON.stringify({
|
|
4846
|
-
status: "found",
|
|
4847
|
-
className,
|
|
4848
|
-
method: result.method,
|
|
4849
|
-
sourcePath: result.sourcePath,
|
|
4850
|
-
source: result.source
|
|
4851
|
-
});
|
|
4852
|
-
}
|
|
4853
|
-
});
|
|
4854
|
-
return registry;
|
|
4855
|
-
}
|
|
4856
|
-
|
|
4857
|
-
// src/tools/scaffold.ts
|
|
4858
|
-
var VALID_SKILL_NAME = /^[a-zA-Z0-9][a-zA-Z0-9._-]{0,63}$/;
|
|
4859
|
-
var VALID_SERVER_NAME = /^[a-zA-Z_][a-zA-Z0-9_-]{0,63}$/;
|
|
4860
|
-
var VALID_TOOL_NAME = /^[a-zA-Z_][a-zA-Z0-9_-]*$/;
|
|
4861
|
-
function registerScaffoldTools(registry, opts = {}) {
|
|
4862
|
-
const configPath = opts.configPath ?? defaultConfigPath();
|
|
4863
|
-
registry.register({
|
|
4864
|
-
name: "create_skill",
|
|
4865
|
-
description: 'Scaffold a SKILL.md the user can later invoke via `/skill <name>`. Frontmatter (description / allowed_tools / run_as / model) is filled from structured args here. Use `run_as: "subagent"` for read-and-synthesize playbooks; default inline appends body to parent log. Refuses to overwrite existing skills.',
|
|
4866
|
-
parameters: {
|
|
4867
|
-
type: "object",
|
|
4868
|
-
properties: {
|
|
4869
|
-
name: {
|
|
4870
|
-
type: "string",
|
|
4871
|
-
description: "Identifier \u2014 letters/digits/`_`/`-`/`.`, 1\u201364 chars. Becomes filename + frontmatter `name`."
|
|
4872
|
-
},
|
|
4873
|
-
description: {
|
|
4874
|
-
type: "string",
|
|
4875
|
-
description: 'One-liner for the skills index. Lead with the verb ("Run X and \u2026").'
|
|
4876
|
-
},
|
|
4877
|
-
body: {
|
|
4878
|
-
type: "string",
|
|
4879
|
-
description: "Markdown playbook. Reference tools by name."
|
|
4880
|
-
},
|
|
4881
|
-
scope: {
|
|
4882
|
-
type: "string",
|
|
4883
|
-
enum: ["project", "global"],
|
|
4884
|
-
description: "`project` (default) = workspace .reasonix/skills/; `global` = ~/.reasonix/skills/."
|
|
4885
|
-
},
|
|
4886
|
-
allowed_tools: {
|
|
4887
|
-
type: "array",
|
|
4888
|
-
items: { type: "string" },
|
|
4889
|
-
description: "Optional tool allowlist for `run_as: subagent`. Omit for full inherited toolset."
|
|
4890
|
-
},
|
|
4891
|
-
run_as: {
|
|
4892
|
-
type: "string",
|
|
4893
|
-
enum: ["inline", "subagent"],
|
|
4894
|
-
description: "inline (default) appends body to parent log. subagent spawns isolated child; only final answer returns."
|
|
4895
|
-
},
|
|
4896
|
-
model: {
|
|
4897
|
-
type: "string",
|
|
4898
|
-
enum: ["deepseek-v4-flash", "deepseek-v4-pro"],
|
|
4899
|
-
description: "Subagent model override. Default flash; use pro only when the playbook needs it."
|
|
4900
|
-
}
|
|
4901
|
-
},
|
|
4902
|
-
required: ["name", "description", "body"]
|
|
4903
|
-
},
|
|
4904
|
-
fn: async (args2) => {
|
|
4905
|
-
const name2 = typeof args2.name === "string" ? args2.name.trim() : "";
|
|
4906
|
-
if (!VALID_SKILL_NAME.test(name2)) {
|
|
4907
|
-
return JSON.stringify({
|
|
4908
|
-
error: `invalid skill name: ${JSON.stringify(name2)} \u2014 use letters, digits, _, -, .`
|
|
4909
|
-
});
|
|
4910
|
-
}
|
|
4911
|
-
const description = typeof args2.description === "string" ? args2.description.trim().replace(/\n+/g, " ") : "";
|
|
4912
|
-
if (!description) {
|
|
4913
|
-
return JSON.stringify({
|
|
4914
|
-
error: "create_skill requires a non-empty 'description'"
|
|
4915
|
-
});
|
|
4916
|
-
}
|
|
4917
|
-
const body2 = typeof args2.body === "string" ? args2.body : "";
|
|
4918
|
-
if (!body2.trim()) {
|
|
4919
|
-
return JSON.stringify({ error: "create_skill requires a non-empty 'body'" });
|
|
4920
|
-
}
|
|
4921
|
-
const scope = args2.scope === "global" ? "global" : opts.projectRoot ? "project" : "global";
|
|
4922
|
-
const runAs = args2.run_as === "subagent" ? "subagent" : "inline";
|
|
4923
|
-
const allowedTools = parseAllowedTools(args2.allowed_tools);
|
|
4924
|
-
if (allowedTools && "error" in allowedTools) {
|
|
4925
|
-
return JSON.stringify({ error: allowedTools.error });
|
|
4926
|
-
}
|
|
4927
|
-
const model = typeof args2.model === "string" && args2.model.startsWith("deepseek-") ? args2.model : void 0;
|
|
4928
|
-
const content = serializeSkill({
|
|
4929
|
-
name: name2,
|
|
4930
|
-
description,
|
|
4931
|
-
runAs,
|
|
4932
|
-
allowedTools: allowedTools ?? void 0,
|
|
4933
|
-
model,
|
|
4934
|
-
body: body2
|
|
4935
|
-
});
|
|
4936
|
-
const store = new SkillStore({
|
|
4937
|
-
homeDir: opts.homeDir,
|
|
4938
|
-
projectRoot: opts.projectRoot,
|
|
4939
|
-
customSkillPaths: opts.projectRoot ? loadResolvedSkillPaths(opts.projectRoot, configPath) : []
|
|
4940
|
-
});
|
|
4941
|
-
const result = store.createWithContent(name2, scope, content);
|
|
4942
|
-
if ("error" in result) {
|
|
4943
|
-
return JSON.stringify({ error: result.error });
|
|
4944
|
-
}
|
|
4945
|
-
return JSON.stringify({
|
|
4946
|
-
success: true,
|
|
4947
|
-
path: result.path,
|
|
4948
|
-
scope,
|
|
4949
|
-
name: name2,
|
|
4950
|
-
run_as: runAs
|
|
4951
|
-
});
|
|
4952
|
-
}
|
|
4953
|
-
});
|
|
4954
|
-
registry.register({
|
|
4955
|
-
name: "add_mcp_server",
|
|
4956
|
-
description: 'Register a new MCP server in the user\'s config (`mcp` array). Takes effect next session. Use stdio for local commands, sse/streamable-http for remote. Pass `from_catalog` (e.g. "filesystem", "github") to auto-fill command+args from the bundled catalog. Refuses name collisions.',
|
|
4957
|
-
parameters: {
|
|
4958
|
-
type: "object",
|
|
4959
|
-
properties: {
|
|
4960
|
-
name: {
|
|
4961
|
-
type: "string",
|
|
4962
|
-
description: "Namespace prefix on every tool. Letters/digits/`_`/`-`, must start with letter or `_`."
|
|
4963
|
-
},
|
|
4964
|
-
transport: {
|
|
4965
|
-
type: "string",
|
|
4966
|
-
enum: ["stdio", "sse", "streamable-http"],
|
|
4967
|
-
description: "stdio = local command via stdin/stdout; sse / streamable-http = remote. Required unless `from_catalog` is set."
|
|
4968
|
-
},
|
|
4969
|
-
command: {
|
|
4970
|
-
type: "string",
|
|
4971
|
-
description: "Argv[0] for stdio \u2014 typically `npx` or a binary path."
|
|
4972
|
-
},
|
|
4973
|
-
args: {
|
|
4974
|
-
type: "array",
|
|
4975
|
-
items: { type: "string" },
|
|
4976
|
-
description: 'Remaining argv for stdio \u2014 e.g. `["-y", "@modelcontextprotocol/server-filesystem", "/path/to/dir"]`.'
|
|
4977
|
-
},
|
|
4978
|
-
url: {
|
|
4979
|
-
type: "string",
|
|
4980
|
-
description: "Endpoint URL for sse / streamable-http \u2014 must be http(s)://."
|
|
4981
|
-
},
|
|
4982
|
-
from_catalog: {
|
|
4983
|
-
type: "string",
|
|
4984
|
-
description: "Bundled catalog shortcut: filesystem / memory / github / puppeteer / everything. Fills command+args; user supplies user-args via `args`."
|
|
4985
|
-
}
|
|
4986
|
-
},
|
|
4987
|
-
required: ["name"]
|
|
4988
|
-
},
|
|
4989
|
-
fn: async (args2) => {
|
|
4990
|
-
const name2 = typeof args2.name === "string" ? args2.name.trim() : "";
|
|
4991
|
-
if (!VALID_SERVER_NAME.test(name2)) {
|
|
4992
|
-
return JSON.stringify({
|
|
4993
|
-
error: `invalid server name: ${JSON.stringify(name2)} \u2014 must match [a-zA-Z_][a-zA-Z0-9_-]*`
|
|
4994
|
-
});
|
|
4995
|
-
}
|
|
4996
|
-
const specStr = buildSpecString({
|
|
4997
|
-
name: name2,
|
|
4998
|
-
transport: typeof args2.transport === "string" ? args2.transport : void 0,
|
|
4999
|
-
command: typeof args2.command === "string" ? args2.command : void 0,
|
|
5000
|
-
argv: Array.isArray(args2.args) ? args2.args.filter((a) => typeof a === "string") : void 0,
|
|
5001
|
-
url: typeof args2.url === "string" ? args2.url : void 0,
|
|
5002
|
-
fromCatalog: typeof args2.from_catalog === "string" ? args2.from_catalog : void 0
|
|
5003
|
-
});
|
|
5004
|
-
if ("error" in specStr) {
|
|
5005
|
-
return JSON.stringify({ error: specStr.error });
|
|
5006
|
-
}
|
|
5007
|
-
let parsed;
|
|
5008
|
-
try {
|
|
5009
|
-
parsed = parseMcpSpec(specStr.spec);
|
|
5010
|
-
} catch (err2) {
|
|
5011
|
-
return JSON.stringify({ error: err2.message });
|
|
5012
|
-
}
|
|
5013
|
-
if (parsed.transport === "stdio") {
|
|
5014
|
-
try {
|
|
5015
|
-
preflightStdioSpec(parsed);
|
|
5016
|
-
} catch (err2) {
|
|
5017
|
-
return JSON.stringify({ error: err2.message });
|
|
5018
|
-
}
|
|
5019
|
-
}
|
|
5020
|
-
const cfg = readConfig(configPath);
|
|
5021
|
-
const existing = cfg.mcp ?? [];
|
|
5022
|
-
const collision = existing.find((s) => parseSpecName(s) === name2);
|
|
5023
|
-
if (collision) {
|
|
5024
|
-
return JSON.stringify({
|
|
5025
|
-
error: `MCP server ${JSON.stringify(name2)} already registered: ${collision}`
|
|
5026
|
-
});
|
|
5027
|
-
}
|
|
5028
|
-
cfg.mcp = [...existing, specStr.spec];
|
|
5029
|
-
writeConfig(cfg, configPath);
|
|
5030
|
-
return JSON.stringify({
|
|
5031
|
-
success: true,
|
|
5032
|
-
name: name2,
|
|
5033
|
-
transport: parsed.transport,
|
|
5034
|
-
spec: specStr.spec,
|
|
5035
|
-
config_path: configPath,
|
|
5036
|
-
active_on_next_launch: true
|
|
5037
|
-
});
|
|
5038
|
-
}
|
|
5039
|
-
});
|
|
5040
|
-
return registry;
|
|
5041
|
-
}
|
|
5042
|
-
function serializeSkill(args2) {
|
|
5043
|
-
const lines = ["---", `name: ${args2.name}`, `description: ${args2.description}`];
|
|
5044
|
-
if (args2.runAs === "subagent") {
|
|
5045
|
-
lines.push("runAs: subagent");
|
|
5046
|
-
}
|
|
5047
|
-
if (args2.allowedTools && args2.allowedTools.length > 0) {
|
|
5048
|
-
lines.push(`allowed-tools: ${args2.allowedTools.join(", ")}`);
|
|
5049
|
-
}
|
|
5050
|
-
if (args2.model) {
|
|
5051
|
-
lines.push(`model: ${args2.model}`);
|
|
5052
|
-
}
|
|
5053
|
-
lines.push("---", "");
|
|
5054
|
-
return `${lines.join("\n")}
|
|
5055
|
-
${args2.body.trim()}
|
|
5056
|
-
`;
|
|
5057
|
-
}
|
|
5058
|
-
function parseAllowedTools(raw) {
|
|
5059
|
-
if (raw === void 0 || raw === null) return void 0;
|
|
5060
|
-
if (!Array.isArray(raw)) {
|
|
5061
|
-
return { error: "'allowed_tools' must be an array of tool-name strings" };
|
|
5062
|
-
}
|
|
5063
|
-
const out2 = [];
|
|
5064
|
-
for (const v of raw) {
|
|
5065
|
-
if (typeof v !== "string") {
|
|
5066
|
-
return { error: "'allowed_tools' entries must be strings" };
|
|
5067
|
-
}
|
|
5068
|
-
const trimmed = v.trim();
|
|
5069
|
-
if (!trimmed) continue;
|
|
5070
|
-
if (!VALID_TOOL_NAME.test(trimmed)) {
|
|
5071
|
-
return { error: `invalid tool name in allowed_tools: ${JSON.stringify(trimmed)}` };
|
|
5072
|
-
}
|
|
5073
|
-
out2.push(trimmed);
|
|
5074
|
-
}
|
|
5075
|
-
return out2.length > 0 ? out2 : void 0;
|
|
5076
|
-
}
|
|
5077
|
-
function buildSpecString(input) {
|
|
5078
|
-
if (input.fromCatalog) {
|
|
5079
|
-
const entry = MCP_CATALOG.find((e) => e.name === input.fromCatalog);
|
|
5080
|
-
if (!entry) {
|
|
5081
|
-
const known = MCP_CATALOG.map((e) => e.name).join(", ");
|
|
5082
|
-
return {
|
|
5083
|
-
error: `unknown catalog entry: ${JSON.stringify(input.fromCatalog)} \u2014 known: ${known}`
|
|
5084
|
-
};
|
|
5085
|
-
}
|
|
5086
|
-
const userArgs = input.argv ?? [];
|
|
5087
|
-
if (entry.userArgs && userArgs.length === 0) {
|
|
5088
|
-
return {
|
|
5089
|
-
error: `catalog entry "${entry.name}" needs ${entry.userArgs} \u2014 pass it via the 'args' parameter`
|
|
5090
|
-
};
|
|
5091
|
-
}
|
|
5092
|
-
const tail = userArgs.map(quoteIfNeeded).join(" ");
|
|
5093
|
-
const body2 = `npx -y ${entry.package}${tail ? ` ${tail}` : ""}`;
|
|
5094
|
-
return { spec: `${input.name}=${body2}` };
|
|
5095
|
-
}
|
|
5096
|
-
const transport = input.transport;
|
|
5097
|
-
if (!transport) {
|
|
5098
|
-
return { error: "add_mcp_server requires 'transport' (or 'from_catalog')" };
|
|
5099
|
-
}
|
|
5100
|
-
if (transport === "stdio") {
|
|
5101
|
-
if (!input.command || !input.command.trim()) {
|
|
5102
|
-
return { error: "stdio transport requires 'command'" };
|
|
5103
|
-
}
|
|
5104
|
-
const tail = (input.argv ?? []).map(quoteIfNeeded).join(" ");
|
|
5105
|
-
const body2 = `${quoteIfNeeded(input.command.trim())}${tail ? ` ${tail}` : ""}`;
|
|
5106
|
-
return { spec: `${input.name}=${body2}` };
|
|
5107
|
-
}
|
|
5108
|
-
if (transport === "sse" || transport === "streamable-http") {
|
|
5109
|
-
if (!input.url || !/^https?:\/\//i.test(input.url)) {
|
|
5110
|
-
return { error: `${transport} transport requires an http(s):// 'url'` };
|
|
5111
|
-
}
|
|
5112
|
-
const prefix = transport === "streamable-http" ? "streamable+" : "";
|
|
5113
|
-
return { spec: `${input.name}=${prefix}${input.url.trim()}` };
|
|
5114
|
-
}
|
|
5115
|
-
return { error: `unknown transport: ${JSON.stringify(transport)}` };
|
|
5116
|
-
}
|
|
5117
|
-
function parseSpecName(spec) {
|
|
5118
|
-
const m = spec.trim().match(/^([a-zA-Z_][a-zA-Z0-9_-]*)=/);
|
|
5119
|
-
return m ? m[1] ?? null : null;
|
|
5120
|
-
}
|
|
5121
|
-
function quoteIfNeeded(s) {
|
|
5122
|
-
return /\s|"/.test(s) ? `"${s.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"` : s;
|
|
5123
|
-
}
|
|
5124
|
-
|
|
5125
|
-
// src/code/setup.ts
|
|
5126
|
-
function applyPlanMode(tools, editMode) {
|
|
5127
|
-
tools.setPlanMode(editMode === "plan");
|
|
5128
|
-
}
|
|
5129
|
-
async function buildCodeToolset(opts) {
|
|
5130
|
-
const tools = new ToolRegistry({ rateLimit: loadToolRateLimit() });
|
|
5131
|
-
applyPlanMode(tools, loadEditMode(opts.configPath));
|
|
5132
|
-
const jobs = new JobRegistry();
|
|
5133
|
-
const outlineThresholdBytes = loadFilesystemOutlineThresholdBytes();
|
|
5134
|
-
const registerRooted = (root) => {
|
|
5135
|
-
registerFilesystemTools(tools, { rootDir: root, outlineThresholdBytes });
|
|
5136
|
-
const cfg = readConfig();
|
|
5137
|
-
registerShellTools(tools, {
|
|
5138
|
-
rootDir: root,
|
|
5139
|
-
extraAllowed: () => loadProjectShellAllowed(root),
|
|
5140
|
-
allowAll: () => loadEditMode() === "yolo",
|
|
5141
|
-
jobs,
|
|
5142
|
-
onJobsChanged: opts.onJobsChanged,
|
|
5143
|
-
sensitivePaths: cfg.sensitivePaths
|
|
5144
|
-
});
|
|
5145
|
-
registerMemoryTools(tools, { projectRoot: root });
|
|
5146
|
-
registerCodeQueryTools(tools, { rootDir: root });
|
|
5147
|
-
};
|
|
5148
|
-
const reBootstrapSemantic = async (root) => {
|
|
5149
|
-
const result = await bootstrapSemanticSearchInCodeMode(tools, root);
|
|
5150
|
-
if (!result.enabled) tools.unregister("semantic_search");
|
|
5151
|
-
return result;
|
|
5152
|
-
};
|
|
5153
|
-
registerRooted(opts.rootDir);
|
|
5154
|
-
registerPlanTool(tools);
|
|
5155
|
-
registerChoiceTool(tools);
|
|
5156
|
-
registerTodoTool(tools);
|
|
5157
|
-
registerScaffoldTools(tools, { projectRoot: opts.rootDir });
|
|
5158
|
-
if (searchEnabled()) {
|
|
5159
|
-
registerWebTools(tools);
|
|
5160
|
-
}
|
|
5161
|
-
if (loadJavaSourceEnabled()) {
|
|
5162
|
-
registerJavaSourceTool(tools, { projectRoot: opts.rootDir });
|
|
5163
|
-
}
|
|
5164
|
-
let subagentClient = null;
|
|
5165
|
-
registerSkillTools(tools, {
|
|
5166
|
-
projectRoot: opts.rootDir,
|
|
5167
|
-
customSkillPaths: loadResolvedSkillPaths(opts.rootDir),
|
|
5168
|
-
subagentModels: loadSubagentModels(),
|
|
5169
|
-
onSkillInstalled: opts.onSkillInstalled,
|
|
5170
|
-
subagentRunner: async (skill, task, signal) => {
|
|
5171
|
-
if (!subagentClient) {
|
|
5172
|
-
const ep = loadEndpoint();
|
|
5173
|
-
subagentClient = new DeepSeekClient({ apiKey: ep.apiKey, baseUrl: ep.baseUrl });
|
|
5174
|
-
}
|
|
5175
|
-
const result = await spawnSubagent({
|
|
5176
|
-
client: subagentClient,
|
|
5177
|
-
parentRegistry: tools,
|
|
5178
|
-
parentSignal: signal,
|
|
5179
|
-
system: skill.body,
|
|
5180
|
-
task,
|
|
5181
|
-
model: skill.model,
|
|
5182
|
-
allowedTools: skill.allowedTools,
|
|
5183
|
-
skillName: skill.name,
|
|
5184
|
-
// Late-bound: the TUI's `useSubagent` writes the live callback into
|
|
5185
|
-
// SHARED_SUBAGENT_SINK after mount. Until then `.current` is null
|
|
5186
|
-
// and the events are silently dropped — that's fine for non-TUI
|
|
5187
|
-
// callers (`reasonix chat --transcript`, library use).
|
|
5188
|
-
sink: opts.subagentSink ?? SHARED_SUBAGENT_SINK
|
|
5189
|
-
});
|
|
5190
|
-
return formatSubagentResult(result);
|
|
5191
|
-
}
|
|
5192
|
-
});
|
|
5193
|
-
const semantic = await reBootstrapSemantic(opts.rootDir);
|
|
5194
|
-
return { tools, jobs, registerRooted, reBootstrapSemantic, semantic };
|
|
5195
|
-
}
|
|
5196
|
-
|
|
5197
4033
|
export {
|
|
5198
|
-
|
|
5199
|
-
|
|
4034
|
+
Query,
|
|
4035
|
+
getParser
|
|
5200
4036
|
};
|
|
5201
|
-
//# sourceMappingURL=chunk-
|
|
4037
|
+
//# sourceMappingURL=chunk-FP7IOWBQ.js.map
|