crosspad-mcp-server 4.0.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 +187 -0
- package/dist/config.d.ts +10 -0
- package/dist/config.js +33 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +360 -0
- package/dist/index.js.map +1 -0
- package/dist/tools/architecture.d.ts +16 -0
- package/dist/tools/architecture.js +198 -0
- package/dist/tools/architecture.js.map +1 -0
- package/dist/tools/build-check.d.ts +23 -0
- package/dist/tools/build-check.js +162 -0
- package/dist/tools/build-check.js.map +1 -0
- package/dist/tools/build.d.ts +14 -0
- package/dist/tools/build.js +101 -0
- package/dist/tools/build.js.map +1 -0
- package/dist/tools/diff-core.d.ts +24 -0
- package/dist/tools/diff-core.js +88 -0
- package/dist/tools/diff-core.js.map +1 -0
- package/dist/tools/idf-build.d.ts +10 -0
- package/dist/tools/idf-build.js +155 -0
- package/dist/tools/idf-build.js.map +1 -0
- package/dist/tools/input.d.ts +36 -0
- package/dist/tools/input.js +61 -0
- package/dist/tools/input.js.map +1 -0
- package/dist/tools/log.d.ts +16 -0
- package/dist/tools/log.js +49 -0
- package/dist/tools/log.js.map +1 -0
- package/dist/tools/repos.d.ts +12 -0
- package/dist/tools/repos.js +63 -0
- package/dist/tools/repos.js.map +1 -0
- package/dist/tools/scaffold.d.ts +15 -0
- package/dist/tools/scaffold.js +192 -0
- package/dist/tools/scaffold.js.map +1 -0
- package/dist/tools/screenshot.d.ts +24 -0
- package/dist/tools/screenshot.js +80 -0
- package/dist/tools/screenshot.js.map +1 -0
- package/dist/tools/settings.d.ts +25 -0
- package/dist/tools/settings.js +48 -0
- package/dist/tools/settings.js.map +1 -0
- package/dist/tools/stats.d.ts +18 -0
- package/dist/tools/stats.js +31 -0
- package/dist/tools/stats.js.map +1 -0
- package/dist/tools/symbols.d.ts +20 -0
- package/dist/tools/symbols.js +157 -0
- package/dist/tools/symbols.js.map +1 -0
- package/dist/tools/test.d.ts +24 -0
- package/dist/tools/test.js +227 -0
- package/dist/tools/test.js.map +1 -0
- package/dist/utils/exec.d.ts +58 -0
- package/dist/utils/exec.js +292 -0
- package/dist/utils/exec.js.map +1 -0
- package/dist/utils/git.d.ts +10 -0
- package/dist/utils/git.js +29 -0
- package/dist/utils/git.js.map +1 -0
- package/dist/utils/remote-client.d.ts +17 -0
- package/dist/utils/remote-client.js +94 -0
- package/dist/utils/remote-client.js.map +1 -0
- package/package.json +21 -0
- package/server.json +23 -0
- package/src/config.ts +45 -0
- package/src/index.ts +484 -0
- package/src/tools/architecture.ts +260 -0
- package/src/tools/build-check.ts +178 -0
- package/src/tools/build.ts +130 -0
- package/src/tools/diff-core.ts +130 -0
- package/src/tools/idf-build.ts +182 -0
- package/src/tools/input.ts +80 -0
- package/src/tools/log.ts +75 -0
- package/src/tools/repos.ts +75 -0
- package/src/tools/scaffold.ts +229 -0
- package/src/tools/screenshot.ts +100 -0
- package/src/tools/settings.ts +68 -0
- package/src/tools/stats.ts +38 -0
- package/src/tools/symbols.ts +185 -0
- package/src/tools/test.ts +264 -0
- package/src/utils/exec.ts +376 -0
- package/src/utils/git.ts +45 -0
- package/src/utils/remote-client.ts +107 -0
- package/tsconfig.json +16 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP tool: capture a screenshot from the running CrossPad simulator.
|
|
3
|
+
* The simulator encodes PNG natively via stb_image_write.
|
|
4
|
+
*
|
|
5
|
+
* When saving to file, the simulator writes the PNG directly to disk
|
|
6
|
+
* (no base64 round-trip over TCP). Otherwise returns inline base64.
|
|
7
|
+
*/
|
|
8
|
+
export interface ScreenshotResult {
|
|
9
|
+
success: boolean;
|
|
10
|
+
width?: number;
|
|
11
|
+
height?: number;
|
|
12
|
+
format?: string;
|
|
13
|
+
file_path?: string;
|
|
14
|
+
data_base64?: string;
|
|
15
|
+
size?: number;
|
|
16
|
+
error?: string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Take a screenshot of the simulator window.
|
|
20
|
+
* @param save_to_file If true, simulator writes PNG directly to disk (fast path).
|
|
21
|
+
* @param filename Custom filename (default: screenshot_<timestamp>.png)
|
|
22
|
+
* @param region "full" for entire window (490x680), "lcd" for LCD only (320x240)
|
|
23
|
+
*/
|
|
24
|
+
export declare function crosspadScreenshot(saveToFile?: boolean, filename?: string, region?: "full" | "lcd"): Promise<ScreenshotResult>;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP tool: capture a screenshot from the running CrossPad simulator.
|
|
3
|
+
* The simulator encodes PNG natively via stb_image_write.
|
|
4
|
+
*
|
|
5
|
+
* When saving to file, the simulator writes the PNG directly to disk
|
|
6
|
+
* (no base64 round-trip over TCP). Otherwise returns inline base64.
|
|
7
|
+
*/
|
|
8
|
+
import { sendRemoteCommand, isSimulatorRunning } from "../utils/remote-client.js";
|
|
9
|
+
import fs from "fs";
|
|
10
|
+
import path from "path";
|
|
11
|
+
import { CROSSPAD_PC_ROOT } from "../config.js";
|
|
12
|
+
/**
|
|
13
|
+
* Take a screenshot of the simulator window.
|
|
14
|
+
* @param save_to_file If true, simulator writes PNG directly to disk (fast path).
|
|
15
|
+
* @param filename Custom filename (default: screenshot_<timestamp>.png)
|
|
16
|
+
* @param region "full" for entire window (490x680), "lcd" for LCD only (320x240)
|
|
17
|
+
*/
|
|
18
|
+
export async function crosspadScreenshot(saveToFile = true, filename, region = "full") {
|
|
19
|
+
const running = await isSimulatorRunning();
|
|
20
|
+
if (!running) {
|
|
21
|
+
return {
|
|
22
|
+
success: false,
|
|
23
|
+
error: "Simulator is not running. Use crosspad_run to start it.",
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
try {
|
|
27
|
+
if (saveToFile) {
|
|
28
|
+
// Fast path: simulator writes PNG directly to disk
|
|
29
|
+
const fname = filename || `screenshot_${Date.now()}.png`;
|
|
30
|
+
const screenshotsDir = path.join(CROSSPAD_PC_ROOT, "screenshots");
|
|
31
|
+
if (!fs.existsSync(screenshotsDir)) {
|
|
32
|
+
fs.mkdirSync(screenshotsDir, { recursive: true });
|
|
33
|
+
}
|
|
34
|
+
const filePath = path.join(screenshotsDir, fname).replace(/\\/g, "/");
|
|
35
|
+
const cmd = { cmd: "screenshot", file: filePath };
|
|
36
|
+
if (region === "lcd")
|
|
37
|
+
cmd.region = "lcd";
|
|
38
|
+
const resp = await sendRemoteCommand(cmd);
|
|
39
|
+
if (!resp.ok) {
|
|
40
|
+
return {
|
|
41
|
+
success: false,
|
|
42
|
+
error: resp.error || "Screenshot failed",
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
return {
|
|
46
|
+
success: true,
|
|
47
|
+
width: resp.width,
|
|
48
|
+
height: resp.height,
|
|
49
|
+
format: "png",
|
|
50
|
+
file_path: filePath,
|
|
51
|
+
size: resp.size,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
// Inline path: returns base64-encoded PNG
|
|
55
|
+
const inlineCmd = { cmd: "screenshot" };
|
|
56
|
+
if (region === "lcd")
|
|
57
|
+
inlineCmd.region = "lcd";
|
|
58
|
+
const resp = await sendRemoteCommand(inlineCmd);
|
|
59
|
+
if (!resp.ok) {
|
|
60
|
+
return {
|
|
61
|
+
success: false,
|
|
62
|
+
error: resp.error || "Screenshot failed",
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
return {
|
|
66
|
+
success: true,
|
|
67
|
+
width: resp.width,
|
|
68
|
+
height: resp.height,
|
|
69
|
+
format: "png",
|
|
70
|
+
data_base64: resp.data,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
catch (err) {
|
|
74
|
+
return {
|
|
75
|
+
success: false,
|
|
76
|
+
error: err.message,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=screenshot.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"screenshot.js","sourceRoot":"","sources":["../../src/tools/screenshot.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAClF,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAahD;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,aAAsB,IAAI,EAC1B,QAAiB,EACjB,SAAyB,MAAM;IAE/B,MAAM,OAAO,GAAG,MAAM,kBAAkB,EAAE,CAAC;IAC3C,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO;YACL,OAAO,EAAE,KAAK;YACd,KAAK,EAAE,yDAAyD;SACjE,CAAC;IACJ,CAAC;IAED,IAAI,CAAC;QACH,IAAI,UAAU,EAAE,CAAC;YACf,mDAAmD;YACnD,MAAM,KAAK,GAAG,QAAQ,IAAI,cAAc,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC;YACzD,MAAM,cAAc,GAAG,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,aAAa,CAAC,CAAC;YAClE,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,cAAc,CAAC,EAAE,CAAC;gBACnC,EAAE,CAAC,SAAS,CAAC,cAAc,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YACpD,CAAC;YACD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;YAEtE,MAAM,GAAG,GAA4B,EAAE,GAAG,EAAE,YAAY,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;YAC3E,IAAI,MAAM,KAAK,KAAK;gBAAE,GAAG,CAAC,MAAM,GAAG,KAAK,CAAC;YACzC,MAAM,IAAI,GAAG,MAAM,iBAAiB,CAAC,GAAG,CAAC,CAAC;YAE1C,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;gBACb,OAAO;oBACL,OAAO,EAAE,KAAK;oBACd,KAAK,EAAG,IAAI,CAAC,KAAgB,IAAI,mBAAmB;iBACrD,CAAC;YACJ,CAAC;YAED,OAAO;gBACL,OAAO,EAAE,IAAI;gBACb,KAAK,EAAE,IAAI,CAAC,KAAe;gBAC3B,MAAM,EAAE,IAAI,CAAC,MAAgB;gBAC7B,MAAM,EAAE,KAAK;gBACb,SAAS,EAAE,QAAQ;gBACnB,IAAI,EAAE,IAAI,CAAC,IAAc;aAC1B,CAAC;QACJ,CAAC;QAED,0CAA0C;QAC1C,MAAM,SAAS,GAA4B,EAAE,GAAG,EAAE,YAAY,EAAE,CAAC;QACjE,IAAI,MAAM,KAAK,KAAK;YAAE,SAAS,CAAC,MAAM,GAAG,KAAK,CAAC;QAC/C,MAAM,IAAI,GAAG,MAAM,iBAAiB,CAAC,SAAS,CAAC,CAAC;QAEhD,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;YACb,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,KAAK,EAAG,IAAI,CAAC,KAAgB,IAAI,mBAAmB;aACrD,CAAC;QACJ,CAAC;QAED,OAAO;YACL,OAAO,EAAE,IAAI;YACb,KAAK,EAAE,IAAI,CAAC,KAAe;YAC3B,MAAM,EAAE,IAAI,CAAC,MAAgB;YAC7B,MAAM,EAAE,KAAK;YACb,WAAW,EAAE,IAAI,CAAC,IAAc;SACjC,CAAC;IACJ,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,OAAO;YACL,OAAO,EAAE,KAAK;YACd,KAAK,EAAE,GAAG,CAAC,OAAO;SACnB,CAAC;IACJ,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP tool: read/write CrossPad settings via the running simulator.
|
|
3
|
+
*/
|
|
4
|
+
export interface SettingsGetResult {
|
|
5
|
+
success: boolean;
|
|
6
|
+
settings?: Record<string, unknown>;
|
|
7
|
+
error?: string;
|
|
8
|
+
}
|
|
9
|
+
export interface SettingsSetResult {
|
|
10
|
+
success: boolean;
|
|
11
|
+
key?: string;
|
|
12
|
+
value?: number;
|
|
13
|
+
error?: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Read settings from the running simulator.
|
|
17
|
+
* @param category "all", "display", "keypad", "vibration", "wireless", "audio", "system"
|
|
18
|
+
*/
|
|
19
|
+
export declare function crosspadSettingsGet(category?: string): Promise<SettingsGetResult>;
|
|
20
|
+
/**
|
|
21
|
+
* Write a single setting on the running simulator.
|
|
22
|
+
* @param key Dotted key name (e.g. "lcd_brightness", "keypad.eco_mode", "vibration.enable")
|
|
23
|
+
* @param value Numeric value (booleans: 0=false, 1=true)
|
|
24
|
+
*/
|
|
25
|
+
export declare function crosspadSettingsSet(key: string, value: number): Promise<SettingsSetResult>;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP tool: read/write CrossPad settings via the running simulator.
|
|
3
|
+
*/
|
|
4
|
+
import { sendRemoteCommand, isSimulatorRunning } from "../utils/remote-client.js";
|
|
5
|
+
/**
|
|
6
|
+
* Read settings from the running simulator.
|
|
7
|
+
* @param category "all", "display", "keypad", "vibration", "wireless", "audio", "system"
|
|
8
|
+
*/
|
|
9
|
+
export async function crosspadSettingsGet(category = "all") {
|
|
10
|
+
const running = await isSimulatorRunning();
|
|
11
|
+
if (!running) {
|
|
12
|
+
return { success: false, error: "Simulator is not running. Use crosspad_run to start it." };
|
|
13
|
+
}
|
|
14
|
+
try {
|
|
15
|
+
const resp = await sendRemoteCommand({ cmd: "settings_get", category });
|
|
16
|
+
if (!resp.ok) {
|
|
17
|
+
return { success: false, error: resp.error || "settings_get failed" };
|
|
18
|
+
}
|
|
19
|
+
// Remove 'ok' field, pass the rest as settings
|
|
20
|
+
const { ok, ...settings } = resp;
|
|
21
|
+
return { success: true, settings };
|
|
22
|
+
}
|
|
23
|
+
catch (err) {
|
|
24
|
+
return { success: false, error: err.message };
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Write a single setting on the running simulator.
|
|
29
|
+
* @param key Dotted key name (e.g. "lcd_brightness", "keypad.eco_mode", "vibration.enable")
|
|
30
|
+
* @param value Numeric value (booleans: 0=false, 1=true)
|
|
31
|
+
*/
|
|
32
|
+
export async function crosspadSettingsSet(key, value) {
|
|
33
|
+
const running = await isSimulatorRunning();
|
|
34
|
+
if (!running) {
|
|
35
|
+
return { success: false, error: "Simulator is not running. Use crosspad_run to start it." };
|
|
36
|
+
}
|
|
37
|
+
try {
|
|
38
|
+
const resp = await sendRemoteCommand({ cmd: "settings_set", key, value });
|
|
39
|
+
if (!resp.ok) {
|
|
40
|
+
return { success: false, error: resp.error || "settings_set failed" };
|
|
41
|
+
}
|
|
42
|
+
return { success: true, key: resp.key, value: resp.value };
|
|
43
|
+
}
|
|
44
|
+
catch (err) {
|
|
45
|
+
return { success: false, error: err.message };
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=settings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"settings.js","sourceRoot":"","sources":["../../src/tools/settings.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAelF;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,WAAmB,KAAK;IAExB,MAAM,OAAO,GAAG,MAAM,kBAAkB,EAAE,CAAC;IAC3C,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,yDAAyD,EAAE,CAAC;IAC9F,CAAC;IAED,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,iBAAiB,CAAC,EAAE,GAAG,EAAE,cAAc,EAAE,QAAQ,EAAE,CAAC,CAAC;QACxE,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;YACb,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAG,IAAI,CAAC,KAAgB,IAAI,qBAAqB,EAAE,CAAC;QACpF,CAAC;QACD,+CAA+C;QAC/C,MAAM,EAAE,EAAE,EAAE,GAAG,QAAQ,EAAE,GAAG,IAAI,CAAC;QACjC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;IACrC,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC;IAChD,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,GAAW,EACX,KAAa;IAEb,MAAM,OAAO,GAAG,MAAM,kBAAkB,EAAE,CAAC;IAC3C,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,yDAAyD,EAAE,CAAC;IAC9F,CAAC;IAED,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,iBAAiB,CAAC,EAAE,GAAG,EAAE,cAAc,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC;QAC1E,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;YACb,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAG,IAAI,CAAC,KAAgB,IAAI,qBAAqB,EAAE,CAAC;QACpF,CAAC;QACD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,CAAC,GAAa,EAAE,KAAK,EAAE,IAAI,CAAC,KAAe,EAAE,CAAC;IACjF,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC;IAChD,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP tool: read runtime statistics from the running CrossPad simulator.
|
|
3
|
+
*/
|
|
4
|
+
export interface StatsResult {
|
|
5
|
+
success: boolean;
|
|
6
|
+
stats?: Record<string, unknown>;
|
|
7
|
+
error?: string;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Query runtime statistics from the simulator:
|
|
11
|
+
* - Platform capabilities (active flags)
|
|
12
|
+
* - Pad state (16 pads: pressed, playing, note, channel, RGB color)
|
|
13
|
+
* - Active pad logic handler + registered handlers
|
|
14
|
+
* - Registered apps
|
|
15
|
+
* - Heap stats (SRAM/PSRAM)
|
|
16
|
+
* - Settings summary (brightness, theme, kit, audio engine)
|
|
17
|
+
*/
|
|
18
|
+
export declare function crosspadStats(): Promise<StatsResult>;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP tool: read runtime statistics from the running CrossPad simulator.
|
|
3
|
+
*/
|
|
4
|
+
import { sendRemoteCommand, isSimulatorRunning } from "../utils/remote-client.js";
|
|
5
|
+
/**
|
|
6
|
+
* Query runtime statistics from the simulator:
|
|
7
|
+
* - Platform capabilities (active flags)
|
|
8
|
+
* - Pad state (16 pads: pressed, playing, note, channel, RGB color)
|
|
9
|
+
* - Active pad logic handler + registered handlers
|
|
10
|
+
* - Registered apps
|
|
11
|
+
* - Heap stats (SRAM/PSRAM)
|
|
12
|
+
* - Settings summary (brightness, theme, kit, audio engine)
|
|
13
|
+
*/
|
|
14
|
+
export async function crosspadStats() {
|
|
15
|
+
const running = await isSimulatorRunning();
|
|
16
|
+
if (!running) {
|
|
17
|
+
return { success: false, error: "Simulator is not running. Use crosspad_run to start it." };
|
|
18
|
+
}
|
|
19
|
+
try {
|
|
20
|
+
const resp = await sendRemoteCommand({ cmd: "stats" });
|
|
21
|
+
if (!resp.ok) {
|
|
22
|
+
return { success: false, error: resp.error || "stats failed" };
|
|
23
|
+
}
|
|
24
|
+
const { ok, ...stats } = resp;
|
|
25
|
+
return { success: true, stats };
|
|
26
|
+
}
|
|
27
|
+
catch (err) {
|
|
28
|
+
return { success: false, error: err.message };
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=stats.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stats.js","sourceRoot":"","sources":["../../src/tools/stats.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAQlF;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,MAAM,OAAO,GAAG,MAAM,kBAAkB,EAAE,CAAC;IAC3C,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,yDAAyD,EAAE,CAAC;IAC9F,CAAC;IAED,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,iBAAiB,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC;QACvD,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;YACb,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAG,IAAI,CAAC,KAAgB,IAAI,cAAc,EAAE,CAAC;QAC7E,CAAC;QACD,MAAM,EAAE,EAAE,EAAE,GAAG,KAAK,EAAE,GAAG,IAAI,CAAC;QAC9B,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;IAClC,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC;IAChD,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export interface SymbolResult {
|
|
2
|
+
symbol: string;
|
|
3
|
+
kind: "class" | "function" | "macro" | "enum" | "typedef";
|
|
4
|
+
file: string;
|
|
5
|
+
line: number;
|
|
6
|
+
context: string;
|
|
7
|
+
repo: string;
|
|
8
|
+
}
|
|
9
|
+
export interface SymbolSearchResult {
|
|
10
|
+
query: string;
|
|
11
|
+
kind_filter: string;
|
|
12
|
+
results: SymbolResult[];
|
|
13
|
+
total_matches: number;
|
|
14
|
+
truncated: boolean;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Search for symbol definitions (classes, functions, macros, enums) across CrossPad repos.
|
|
18
|
+
* Only matches definition lines, not usages.
|
|
19
|
+
*/
|
|
20
|
+
export declare function crosspadSearchSymbols(query: string, kind?: string, repos?: string[], maxResults?: number): SymbolSearchResult;
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import { REPOS } from "../config.js";
|
|
3
|
+
import { runCommand } from "../utils/exec.js";
|
|
4
|
+
/**
|
|
5
|
+
* Build a regex pattern that matches definition lines containing the query.
|
|
6
|
+
* Each kind has a specific pattern that only matches declarations/definitions.
|
|
7
|
+
*/
|
|
8
|
+
function buildPattern(query, kind) {
|
|
9
|
+
const q = query; // Already escaped by caller
|
|
10
|
+
const patterns = [];
|
|
11
|
+
if (kind === "class" || kind === "all") {
|
|
12
|
+
// class/struct definition: class Foo { or class Foo : public Bar {
|
|
13
|
+
patterns.push(`(class|struct)\\s+\\w*${q}\\w*\\s*[:{]`);
|
|
14
|
+
patterns.push(`(class|struct)\\s+\\w*${q}\\w*\\s*$`); // multi-line def
|
|
15
|
+
}
|
|
16
|
+
if (kind === "macro" || kind === "all") {
|
|
17
|
+
patterns.push(`#define\\s+\\w*${q}\\w*`);
|
|
18
|
+
}
|
|
19
|
+
if (kind === "enum" || kind === "all") {
|
|
20
|
+
patterns.push(`enum\\s+(class\\s+)?\\w*${q}\\w*`);
|
|
21
|
+
}
|
|
22
|
+
if (kind === "typedef" || kind === "all") {
|
|
23
|
+
patterns.push(`using\\s+\\w*${q}\\w*\\s*=`);
|
|
24
|
+
patterns.push(`typedef\\s+.*\\b\\w*${q}\\w*\\s*;`);
|
|
25
|
+
}
|
|
26
|
+
if (kind === "function" || kind === "all") {
|
|
27
|
+
// Function definition: type name( or void name( — exclude calls by requiring return type or line start
|
|
28
|
+
patterns.push(`^\\w[\\w:\\s*&<>]+\\b\\w*${q}\\w*\\s*\\(`);
|
|
29
|
+
}
|
|
30
|
+
return patterns.join("|");
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Search for symbol definitions (classes, functions, macros, enums) across CrossPad repos.
|
|
34
|
+
* Only matches definition lines, not usages.
|
|
35
|
+
*/
|
|
36
|
+
export function crosspadSearchSymbols(query, kind = "all", repos = ["all"], maxResults = 50) {
|
|
37
|
+
const results = [];
|
|
38
|
+
const targetRepos = repos.includes("all")
|
|
39
|
+
? Object.entries(REPOS)
|
|
40
|
+
: Object.entries(REPOS).filter(([name]) => repos.includes(name));
|
|
41
|
+
const pattern = buildPattern(escapeForRegex(query), kind);
|
|
42
|
+
if (!pattern) {
|
|
43
|
+
return { query, kind_filter: kind, results: [], total_matches: 0, truncated: false };
|
|
44
|
+
}
|
|
45
|
+
for (const [repoName, repoPath] of targetRepos) {
|
|
46
|
+
if (!fs.existsSync(repoPath))
|
|
47
|
+
continue;
|
|
48
|
+
const grepCmd = `git grep -n -E "${escapeForShell(pattern)}" -- "*.hpp" "*.h" "*.cpp" "*.c"`;
|
|
49
|
+
const result = runCommand(grepCmd, repoPath, 30_000);
|
|
50
|
+
if (!result.success && result.stdout.length === 0)
|
|
51
|
+
continue;
|
|
52
|
+
for (const line of result.stdout.split("\n")) {
|
|
53
|
+
if (!line.trim())
|
|
54
|
+
continue;
|
|
55
|
+
const match = line.match(/^([^:]+):(\d+):(.*)$/);
|
|
56
|
+
if (!match)
|
|
57
|
+
continue;
|
|
58
|
+
const [, file, lineStr, content] = match;
|
|
59
|
+
const lineNum = parseInt(lineStr, 10);
|
|
60
|
+
const trimmedContent = content.trim();
|
|
61
|
+
// Skip forward declarations (class Foo;)
|
|
62
|
+
if (/^\s*(class|struct)\s+\w+\s*;/.test(trimmedContent))
|
|
63
|
+
continue;
|
|
64
|
+
// Skip includes
|
|
65
|
+
if (/^\s*#include/.test(trimmedContent))
|
|
66
|
+
continue;
|
|
67
|
+
// Skip comments
|
|
68
|
+
if (/^\s*(\/\/|\/\*|\*)/.test(trimmedContent))
|
|
69
|
+
continue;
|
|
70
|
+
const detectedKind = classifyDefinition(trimmedContent);
|
|
71
|
+
if (!detectedKind)
|
|
72
|
+
continue;
|
|
73
|
+
if (kind !== "all" && detectedKind !== kind)
|
|
74
|
+
continue;
|
|
75
|
+
const symbolName = extractSymbolName(trimmedContent, detectedKind);
|
|
76
|
+
if (!symbolName)
|
|
77
|
+
continue;
|
|
78
|
+
// Symbol name must contain query
|
|
79
|
+
if (!symbolName.toLowerCase().includes(query.toLowerCase()))
|
|
80
|
+
continue;
|
|
81
|
+
// Deduplicate by symbol+file
|
|
82
|
+
const key = `${symbolName}:${file}`;
|
|
83
|
+
if (results.some((r) => `${r.symbol}:${r.file.split("/").pop()}` === key))
|
|
84
|
+
continue;
|
|
85
|
+
results.push({
|
|
86
|
+
symbol: symbolName,
|
|
87
|
+
kind: detectedKind,
|
|
88
|
+
file: `${repoPath}/${file}`.replace(/\\/g, "/"),
|
|
89
|
+
line: lineNum,
|
|
90
|
+
context: trimmedContent.slice(0, 150),
|
|
91
|
+
repo: repoName,
|
|
92
|
+
});
|
|
93
|
+
if (results.length >= maxResults)
|
|
94
|
+
break;
|
|
95
|
+
}
|
|
96
|
+
if (results.length >= maxResults)
|
|
97
|
+
break;
|
|
98
|
+
}
|
|
99
|
+
return {
|
|
100
|
+
query,
|
|
101
|
+
kind_filter: kind,
|
|
102
|
+
results: results.slice(0, maxResults),
|
|
103
|
+
total_matches: results.length,
|
|
104
|
+
truncated: results.length >= maxResults,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
function escapeForShell(s) {
|
|
108
|
+
// Only escape shell metacharacters, NOT backslashes (needed for regex \s \w etc.)
|
|
109
|
+
return s.replace(/["`$]/g, "\\$&");
|
|
110
|
+
}
|
|
111
|
+
function escapeForRegex(s) {
|
|
112
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
113
|
+
}
|
|
114
|
+
function classifyDefinition(line) {
|
|
115
|
+
if (/^\s*#define\s+/.test(line))
|
|
116
|
+
return "macro";
|
|
117
|
+
if (/^\s*enum\s+/.test(line))
|
|
118
|
+
return "enum";
|
|
119
|
+
if (/^\s*(typedef|using)\s+/.test(line))
|
|
120
|
+
return "typedef";
|
|
121
|
+
if (/^\s*(class|struct)\s+\w+/.test(line))
|
|
122
|
+
return "class";
|
|
123
|
+
// Function: starts with type qualifier, has word( pattern
|
|
124
|
+
if (/^[\w:][\w:\s*&<>,]*\b\w+\s*\(/.test(line) &&
|
|
125
|
+
!/^\s*(if|while|for|switch|return|delete|new|throw|sizeof)\b/.test(line)) {
|
|
126
|
+
return "function";
|
|
127
|
+
}
|
|
128
|
+
return null;
|
|
129
|
+
}
|
|
130
|
+
function extractSymbolName(line, kind) {
|
|
131
|
+
switch (kind) {
|
|
132
|
+
case "class": {
|
|
133
|
+
const m = line.match(/(?:class|struct)\s+(\w+)/);
|
|
134
|
+
return m ? m[1] : null;
|
|
135
|
+
}
|
|
136
|
+
case "macro": {
|
|
137
|
+
const m = line.match(/#define\s+(\w+)/);
|
|
138
|
+
return m ? m[1] : null;
|
|
139
|
+
}
|
|
140
|
+
case "enum": {
|
|
141
|
+
const m = line.match(/enum\s+(?:class\s+)?(\w+)/);
|
|
142
|
+
return m ? m[1] : null;
|
|
143
|
+
}
|
|
144
|
+
case "typedef": {
|
|
145
|
+
const m = line.match(/using\s+(\w+)\s*=/) || line.match(/typedef\s+.*\b(\w+)\s*;/);
|
|
146
|
+
return m ? m[1] : null;
|
|
147
|
+
}
|
|
148
|
+
case "function": {
|
|
149
|
+
// Last word before opening paren: returnType funcName(
|
|
150
|
+
const m = line.match(/\b(\w+)\s*\(/);
|
|
151
|
+
return m ? m[1] : null;
|
|
152
|
+
}
|
|
153
|
+
default:
|
|
154
|
+
return null;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
//# sourceMappingURL=symbols.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"symbols.js","sourceRoot":"","sources":["../../src/tools/symbols.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { OnLine } from "../utils/exec.js";
|
|
2
|
+
export interface TestResult {
|
|
3
|
+
success: boolean;
|
|
4
|
+
tests_found: boolean;
|
|
5
|
+
build_output: string;
|
|
6
|
+
test_output: string;
|
|
7
|
+
passed: number;
|
|
8
|
+
failed: number;
|
|
9
|
+
errors: string[];
|
|
10
|
+
duration_seconds: number;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Build and run the crosspad test suite (Catch2).
|
|
14
|
+
* If tests/ dir doesn't exist, offers to scaffold it.
|
|
15
|
+
*/
|
|
16
|
+
export declare function crosspadTest(filter?: string, listOnly?: boolean, onLine?: OnLine): Promise<TestResult>;
|
|
17
|
+
/**
|
|
18
|
+
* Scaffold the test infrastructure: CMakeLists.txt additions + sample test file.
|
|
19
|
+
* Returns file contents — does NOT write to disk.
|
|
20
|
+
*/
|
|
21
|
+
export declare function crosspadTestScaffold(): {
|
|
22
|
+
files: Record<string, string>;
|
|
23
|
+
cmake_patch: string;
|
|
24
|
+
};
|