crosspad-mcp-server 6.0.0 → 8.1.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 +109 -44
- package/dist/config.d.ts +2 -2
- package/dist/config.js +42 -8
- package/dist/config.js.map +1 -1
- package/dist/index.js +946 -308
- package/dist/index.js.map +1 -1
- package/dist/tools/app-manager.d.ts +13 -5
- package/dist/tools/app-manager.js +69 -46
- package/dist/tools/app-manager.js.map +1 -1
- package/dist/tools/architecture.js +13 -4
- package/dist/tools/architecture.js.map +1 -1
- package/dist/tools/build-check.d.ts +1 -1
- package/dist/tools/build-check.js +19 -9
- package/dist/tools/build-check.js.map +1 -1
- package/dist/tools/build.d.ts +43 -4
- package/dist/tools/build.js +147 -15
- package/dist/tools/build.js.map +1 -1
- package/dist/tools/diff-core.d.ts +5 -1
- package/dist/tools/diff-core.js +11 -6
- package/dist/tools/diff-core.js.map +1 -1
- package/dist/tools/idf-build.d.ts +1 -1
- package/dist/tools/idf-build.js +5 -5
- package/dist/tools/idf-build.js.map +1 -1
- package/dist/tools/idf-flash.d.ts +2 -2
- package/dist/tools/idf-flash.js +12 -11
- package/dist/tools/idf-flash.js.map +1 -1
- package/dist/tools/idf-monitor.d.ts +1 -1
- package/dist/tools/idf-monitor.js +57 -3
- package/dist/tools/idf-monitor.js.map +1 -1
- package/dist/tools/log.d.ts +2 -2
- package/dist/tools/log.js +6 -5
- package/dist/tools/log.js.map +1 -1
- package/dist/tools/repo-actions.js +88 -75
- package/dist/tools/repo-actions.js.map +1 -1
- package/dist/tools/repos.js +14 -10
- package/dist/tools/repos.js.map +1 -1
- package/dist/tools/screenshot.js +42 -7
- package/dist/tools/screenshot.js.map +1 -1
- package/dist/tools/settings.js +11 -1
- package/dist/tools/settings.js.map +1 -1
- package/dist/tools/symbols.js +13 -8
- package/dist/tools/symbols.js.map +1 -1
- package/dist/tools/test.d.ts +1 -9
- package/dist/tools/test.js +11 -92
- package/dist/tools/test.js.map +1 -1
- package/dist/utils/exec.d.ts +17 -5
- package/dist/utils/exec.js +73 -27
- package/dist/utils/exec.js.map +1 -1
- package/dist/utils/git.d.ts +9 -0
- package/dist/utils/git.js +61 -1
- package/dist/utils/git.js.map +1 -1
- package/dist/utils/remote-client.js +32 -14
- package/dist/utils/remote-client.js.map +1 -1
- package/package.json +4 -1
- package/dist/tools/scaffold.d.ts +0 -15
- package/dist/tools/scaffold.js +0 -192
- package/dist/tools/scaffold.js.map +0 -1
|
@@ -1 +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;
|
|
1
|
+
{"version":3,"file":"screenshot.js","sourceRoot":"","sources":["../../src/tools/screenshot.ts"],"names":[],"mappings":"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"}
|
package/dist/tools/settings.js
CHANGED
|
@@ -2,6 +2,12 @@
|
|
|
2
2
|
* MCP tool: read/write CrossPad settings via the running simulator.
|
|
3
3
|
*/
|
|
4
4
|
import { sendRemoteCommand, isSimulatorRunning } from "../utils/remote-client.js";
|
|
5
|
+
import { z } from "zod";
|
|
6
|
+
const SettingsSetResponseSchema = z.object({
|
|
7
|
+
ok: z.literal(true),
|
|
8
|
+
key: z.string(),
|
|
9
|
+
value: z.number(),
|
|
10
|
+
});
|
|
5
11
|
/**
|
|
6
12
|
* Read settings from the running simulator.
|
|
7
13
|
* @param category "all", "display", "keypad", "vibration", "wireless", "audio", "system"
|
|
@@ -39,7 +45,11 @@ export async function crosspadSettingsSet(key, value) {
|
|
|
39
45
|
if (!resp.ok) {
|
|
40
46
|
return { success: false, error: resp.error || "settings_set failed" };
|
|
41
47
|
}
|
|
42
|
-
|
|
48
|
+
const parsed = SettingsSetResponseSchema.safeParse(resp);
|
|
49
|
+
if (!parsed.success) {
|
|
50
|
+
return { success: false, error: `Simulator returned malformed settings_set response: ${parsed.error.message}` };
|
|
51
|
+
}
|
|
52
|
+
return { success: true, key: parsed.data.key, value: parsed.data.value };
|
|
43
53
|
}
|
|
44
54
|
catch (err) {
|
|
45
55
|
return { success: false, error: err.message };
|
|
@@ -1 +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;
|
|
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;AAClF,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,yBAAyB,GAAG,CAAC,CAAC,MAAM,CAAC;IACzC,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC;IACnB,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE;IACf,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;CAClB,CAAC,CAAC;AAeH;;;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,MAAM,MAAM,GAAG,yBAAyB,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QACzD,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,uDAAuD,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC;QAClH,CAAC;QACD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;IAC3E,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC;IAChD,CAAC;AACH,CAAC"}
|
package/dist/tools/symbols.js
CHANGED
|
@@ -9,24 +9,29 @@ import { runCommand } from "../utils/exec.js";
|
|
|
9
9
|
export function buildPattern(query, kind) {
|
|
10
10
|
const q = query; // Already escaped by caller
|
|
11
11
|
const patterns = [];
|
|
12
|
+
// Use explicit character classes — `\w` / `\s` inside `[...]` are not
|
|
13
|
+
// portable across POSIX ERE implementations.
|
|
14
|
+
const W = "[A-Za-z0-9_]"; // word char
|
|
15
|
+
const WS = "[ \\t]"; // whitespace (intra-line)
|
|
12
16
|
if (kind === "class" || kind === "all") {
|
|
13
17
|
// class/struct definition: class Foo { or class Foo : public Bar {
|
|
14
|
-
patterns.push(`(class|struct)
|
|
15
|
-
patterns.push(`(class|struct)
|
|
18
|
+
patterns.push(`(class|struct)${WS}+${W}*${q}${W}*${WS}*[:{]`);
|
|
19
|
+
patterns.push(`(class|struct)${WS}+${W}*${q}${W}*${WS}*$`); // multi-line def
|
|
16
20
|
}
|
|
17
21
|
if (kind === "macro" || kind === "all") {
|
|
18
|
-
patterns.push(`#define
|
|
22
|
+
patterns.push(`#define${WS}+${W}*${q}${W}*`);
|
|
19
23
|
}
|
|
20
24
|
if (kind === "enum" || kind === "all") {
|
|
21
|
-
patterns.push(`enum
|
|
25
|
+
patterns.push(`enum${WS}+(class${WS}+)?${W}*${q}${W}*`);
|
|
22
26
|
}
|
|
23
27
|
if (kind === "typedef" || kind === "all") {
|
|
24
|
-
patterns.push(`using
|
|
25
|
-
patterns.push(`typedef
|
|
28
|
+
patterns.push(`using${WS}+${W}*${q}${W}*${WS}*=`);
|
|
29
|
+
patterns.push(`typedef${WS}+.*${W}*${q}${W}*${WS}*;`);
|
|
26
30
|
}
|
|
27
31
|
if (kind === "function" || kind === "all") {
|
|
28
|
-
// Function definition:
|
|
29
|
-
|
|
32
|
+
// Function definition: starts with type qualifier (word char), then
|
|
33
|
+
// type tokens (word/colon/space/tab/star/amp/angle), then the name and `(`.
|
|
34
|
+
patterns.push(`^${W}[${W.slice(1, -1)}: \\t*&<>]+${W}*${q}${W}*${WS}*\\(`);
|
|
30
35
|
}
|
|
31
36
|
return patterns.join("|");
|
|
32
37
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"symbols.js","sourceRoot":"","sources":["../../src/tools/symbols.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAoB9C;;;GAGG;AACH,qCAAqC;AACrC,MAAM,UAAU,YAAY,CAAC,KAAa,EAAE,IAAY;IACtD,MAAM,CAAC,GAAG,KAAK,CAAC,CAAC,4BAA4B;IAC7C,MAAM,QAAQ,GAAa,EAAE,CAAC;IAE9B,IAAI,IAAI,KAAK,OAAO,IAAI,IAAI,KAAK,KAAK,EAAE,CAAC;QACvC,mEAAmE;QACnE,QAAQ,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"symbols.js","sourceRoot":"","sources":["../../src/tools/symbols.ts"],"names":[],"mappings":"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"}
|
package/dist/tools/test.d.ts
CHANGED
|
@@ -13,15 +13,7 @@ export interface TestResult {
|
|
|
13
13
|
* Build and run the crosspad test suite (Catch2).
|
|
14
14
|
* If tests/ dir doesn't exist, offers to scaffold it.
|
|
15
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
|
-
};
|
|
16
|
+
export declare function crosspadTest(filter?: string, listOnly?: boolean, onLine?: OnLine, signal?: AbortSignal): Promise<TestResult>;
|
|
25
17
|
/** @internal exported for testing */
|
|
26
18
|
export declare function parseCatch2Output(output: string): {
|
|
27
19
|
passed: number;
|
package/dist/tools/test.js
CHANGED
|
@@ -10,7 +10,7 @@ const TEST_EXE = path.join(BIN_DIR, `crosspad_tests${EXE_EXT}`);
|
|
|
10
10
|
* Build and run the crosspad test suite (Catch2).
|
|
11
11
|
* If tests/ dir doesn't exist, offers to scaffold it.
|
|
12
12
|
*/
|
|
13
|
-
export async function crosspadTest(filter = "", listOnly = false, onLine) {
|
|
13
|
+
export async function crosspadTest(filter = "", listOnly = false, onLine, signal) {
|
|
14
14
|
const startTime = Date.now();
|
|
15
15
|
// Check if test infrastructure exists
|
|
16
16
|
if (!fs.existsSync(TESTS_DIR)) {
|
|
@@ -18,7 +18,7 @@ export async function crosspadTest(filter = "", listOnly = false, onLine) {
|
|
|
18
18
|
success: false,
|
|
19
19
|
tests_found: false,
|
|
20
20
|
build_output: "",
|
|
21
|
-
test_output: `No tests/ directory found.
|
|
21
|
+
test_output: `No tests/ directory found. See docs for the Catch2 setup snippet.`,
|
|
22
22
|
passed: 0,
|
|
23
23
|
failed: 0,
|
|
24
24
|
errors: ["tests/ directory not found"],
|
|
@@ -30,7 +30,7 @@ export async function crosspadTest(filter = "", listOnly = false, onLine) {
|
|
|
30
30
|
const configCmd = `cmake -B build -G Ninja -DCMAKE_TOOLCHAIN_FILE=${VCPKG_TOOLCHAIN} -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTING=ON`;
|
|
31
31
|
let configResult;
|
|
32
32
|
if (onLine) {
|
|
33
|
-
configResult = await runBuildStream(configCmd, CROSSPAD_PC_ROOT, onLine, 120_000);
|
|
33
|
+
configResult = await runBuildStream(configCmd, CROSSPAD_PC_ROOT, onLine, 120_000, signal);
|
|
34
34
|
}
|
|
35
35
|
else {
|
|
36
36
|
configResult = runBuild(configCmd, CROSSPAD_PC_ROOT, 120_000);
|
|
@@ -52,7 +52,7 @@ export async function crosspadTest(filter = "", listOnly = false, onLine) {
|
|
|
52
52
|
const buildCmd = "cmake --build build --target crosspad_tests";
|
|
53
53
|
let buildResult;
|
|
54
54
|
if (onLine) {
|
|
55
|
-
buildResult = await runBuildStream(buildCmd, CROSSPAD_PC_ROOT, onLine, 300_000);
|
|
55
|
+
buildResult = await runBuildStream(buildCmd, CROSSPAD_PC_ROOT, onLine, 300_000, signal);
|
|
56
56
|
}
|
|
57
57
|
else {
|
|
58
58
|
buildResult = runBuild(buildCmd, CROSSPAD_PC_ROOT, 300_000);
|
|
@@ -82,20 +82,24 @@ export async function crosspadTest(filter = "", listOnly = false, onLine) {
|
|
|
82
82
|
};
|
|
83
83
|
}
|
|
84
84
|
// Run tests
|
|
85
|
+
// Escape double-quotes / backticks / dollars in the filter to prevent
|
|
86
|
+
// shell injection. Catch2 filters are simple tag/glob strings so this
|
|
87
|
+
// sanitization doesn't lose semantics.
|
|
88
|
+
const safeFilter = filter.replace(/[`"$\\]/g, "\\$&");
|
|
85
89
|
let testCmd = `"${TEST_EXE}"`;
|
|
86
90
|
if (listOnly) {
|
|
87
91
|
testCmd += " --list-tests";
|
|
88
92
|
}
|
|
89
93
|
else {
|
|
90
94
|
testCmd += " --reporter compact";
|
|
91
|
-
if (
|
|
92
|
-
testCmd += ` "${
|
|
95
|
+
if (safeFilter) {
|
|
96
|
+
testCmd += ` "${safeFilter}"`;
|
|
93
97
|
}
|
|
94
98
|
}
|
|
95
99
|
onLine?.("stdout", "[crosspad] Running tests...");
|
|
96
100
|
let testResult;
|
|
97
101
|
if (onLine) {
|
|
98
|
-
testResult = await runBuildStream(testCmd, CROSSPAD_PC_ROOT, onLine, 120_000);
|
|
102
|
+
testResult = await runBuildStream(testCmd, CROSSPAD_PC_ROOT, onLine, 120_000, signal);
|
|
99
103
|
}
|
|
100
104
|
else {
|
|
101
105
|
testResult = runBuild(testCmd, CROSSPAD_PC_ROOT, 120_000);
|
|
@@ -116,91 +120,6 @@ export async function crosspadTest(filter = "", listOnly = false, onLine) {
|
|
|
116
120
|
onLine?.("stdout", `[crosspad] Tests ${result.success ? "PASSED" : "FAILED"}: ${passed} passed, ${failed} failed (${result.duration_seconds.toFixed(1)}s)`);
|
|
117
121
|
return result;
|
|
118
122
|
}
|
|
119
|
-
/**
|
|
120
|
-
* Scaffold the test infrastructure: CMakeLists.txt additions + sample test file.
|
|
121
|
-
* Returns file contents — does NOT write to disk.
|
|
122
|
-
*/
|
|
123
|
-
export function crosspadTestScaffold() {
|
|
124
|
-
const files = {};
|
|
125
|
-
// tests/CMakeLists.txt
|
|
126
|
-
files["tests/CMakeLists.txt"] = `# CrossPad test suite — Catch2 v3
|
|
127
|
-
Include(FetchContent)
|
|
128
|
-
|
|
129
|
-
FetchContent_Declare(
|
|
130
|
-
Catch2
|
|
131
|
-
GIT_REPOSITORY https://github.com/catchorg/Catch2.git
|
|
132
|
-
GIT_TAG v3.5.2
|
|
133
|
-
)
|
|
134
|
-
FetchContent_MakeAvailable(Catch2)
|
|
135
|
-
|
|
136
|
-
# Collect test sources
|
|
137
|
-
file(GLOB_RECURSE TEST_SOURCES "\${CMAKE_CURRENT_SOURCE_DIR}/*.cpp")
|
|
138
|
-
|
|
139
|
-
add_executable(crosspad_tests \${TEST_SOURCES})
|
|
140
|
-
|
|
141
|
-
target_link_libraries(crosspad_tests PRIVATE
|
|
142
|
-
Catch2::Catch2WithMain
|
|
143
|
-
)
|
|
144
|
-
|
|
145
|
-
# Include crosspad-core headers (for testing core logic)
|
|
146
|
-
target_include_directories(crosspad_tests PRIVATE
|
|
147
|
-
\${CMAKE_SOURCE_DIR}/crosspad-core/include
|
|
148
|
-
\${CMAKE_SOURCE_DIR}/crosspad-gui/include
|
|
149
|
-
\${CMAKE_SOURCE_DIR}/src
|
|
150
|
-
)
|
|
151
|
-
|
|
152
|
-
# Same defines as main target
|
|
153
|
-
target_compile_definitions(crosspad_tests PRIVATE
|
|
154
|
-
PLATFORM_PC=1
|
|
155
|
-
CP_LCD_HOR_RES=320
|
|
156
|
-
CP_LCD_VER_RES=240
|
|
157
|
-
)
|
|
158
|
-
|
|
159
|
-
# Add crosspad-core sources we want to test (non-platform-specific)
|
|
160
|
-
# Add individual source files as needed:
|
|
161
|
-
# target_sources(crosspad_tests PRIVATE
|
|
162
|
-
# \${CMAKE_SOURCE_DIR}/crosspad-core/src/SomeFile.cpp
|
|
163
|
-
# )
|
|
164
|
-
|
|
165
|
-
include(CTest)
|
|
166
|
-
include(Catch)
|
|
167
|
-
catch_discover_tests(crosspad_tests)
|
|
168
|
-
`;
|
|
169
|
-
// tests/test_pad_manager.cpp — sample test
|
|
170
|
-
files["tests/test_pad_manager.cpp"] = `#include <catch2/catch_test_macros.hpp>
|
|
171
|
-
|
|
172
|
-
// Example: test crosspad-core types without full platform init
|
|
173
|
-
// #include <crosspad/pad/PadManager.hpp>
|
|
174
|
-
// #include <crosspad/platform/PlatformCapabilities.hpp>
|
|
175
|
-
|
|
176
|
-
TEST_CASE("Sanity check", "[core]") {
|
|
177
|
-
REQUIRE(1 + 1 == 2);
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
// TEST_CASE("PlatformCapabilities bitflags", "[core][capabilities]") {
|
|
181
|
-
// using crosspad::Capability;
|
|
182
|
-
// using crosspad::setPlatformCapabilities;
|
|
183
|
-
// using crosspad::hasCapability;
|
|
184
|
-
// using crosspad::hasAnyCapability;
|
|
185
|
-
//
|
|
186
|
-
// setPlatformCapabilities(Capability::Midi | Capability::Pads);
|
|
187
|
-
//
|
|
188
|
-
// REQUIRE(hasCapability(Capability::Midi));
|
|
189
|
-
// REQUIRE(hasCapability(Capability::Pads));
|
|
190
|
-
// REQUIRE_FALSE(hasCapability(Capability::AudioOut));
|
|
191
|
-
// REQUIRE(hasAnyCapability(Capability::Midi | Capability::AudioOut));
|
|
192
|
-
// }
|
|
193
|
-
`;
|
|
194
|
-
// Patch for root CMakeLists.txt
|
|
195
|
-
const cmakePatch = `
|
|
196
|
-
# Add this near the end of your CMakeLists.txt, before any final install/packaging:
|
|
197
|
-
# --- Test suite ---
|
|
198
|
-
if(EXISTS "\${CMAKE_SOURCE_DIR}/tests/CMakeLists.txt")
|
|
199
|
-
add_subdirectory(tests)
|
|
200
|
-
endif()
|
|
201
|
-
`;
|
|
202
|
-
return { files, cmake_patch: cmakePatch };
|
|
203
|
-
}
|
|
204
123
|
/** @internal exported for testing */
|
|
205
124
|
export function parseCatch2Output(output) {
|
|
206
125
|
// Catch2 compact reporter: "Passed X test(s)" / "Failed X test(s)"
|
package/dist/tools/test.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"test.js","sourceRoot":"","sources":["../../src/tools/test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC7E,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAU,MAAM,kBAAkB,CAAC;AAapE,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,OAAO,CAAC,CAAC;AACvD,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,KAAK,CAAC,CAAC;AACnD,MAAM,OAAO,GAAG,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;AACzC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,iBAAiB,OAAO,EAAE,CAAC,CAAC;AAEhE;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,SAAiB,EAAE,EACnB,WAAoB,KAAK,EACzB,MAAe;
|
|
1
|
+
{"version":3,"file":"test.js","sourceRoot":"","sources":["../../src/tools/test.ts"],"names":[],"mappings":"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"}
|
package/dist/utils/exec.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
/** Callback invoked for each line of stdout/stderr during streaming exec. */
|
|
2
2
|
export type OnLine = (stream: "stdout" | "stderr", line: string) => void;
|
|
3
|
+
/** @internal exported for testing — drop both env caches. */
|
|
4
|
+
export declare function _resetEnvCaches(): void;
|
|
3
5
|
/**
|
|
4
6
|
* Capture MSVC environment by running vcvarsall.bat and parsing `set` output.
|
|
5
7
|
* Cached for the lifetime of the server process. Windows-only.
|
|
@@ -20,14 +22,19 @@ export declare function runWithMsvc(cmd: string, cwd: string, timeoutMs?: number
|
|
|
20
22
|
* Run a command in the default shell, capturing output.
|
|
21
23
|
*/
|
|
22
24
|
export declare function runCommand(cmd: string, cwd: string, timeoutMs?: number): ExecResult;
|
|
25
|
+
/**
|
|
26
|
+
* Run an arbitrary executable with argv array (no shell). Use for inputs that
|
|
27
|
+
* may contain user-controlled strings — eliminates shell-injection risk.
|
|
28
|
+
*/
|
|
29
|
+
export declare function runArgvStream(cmd: string, args: string[], cwd: string, onLine: OnLine, timeoutMs?: number, signal?: AbortSignal, env?: Record<string, string>): Promise<ExecResult>;
|
|
23
30
|
/**
|
|
24
31
|
* Run a command with the MSVC environment, streaming output line-by-line.
|
|
25
32
|
*/
|
|
26
|
-
export declare function runWithMsvcStream(cmd: string, cwd: string, onLine: OnLine, timeoutMs?: number): Promise<ExecResult>;
|
|
33
|
+
export declare function runWithMsvcStream(cmd: string, cwd: string, onLine: OnLine, timeoutMs?: number, signal?: AbortSignal): Promise<ExecResult>;
|
|
27
34
|
/**
|
|
28
35
|
* Run a command in the default shell, streaming output line-by-line.
|
|
29
36
|
*/
|
|
30
|
-
export declare function runCommandStream(cmd: string, cwd: string, onLine: OnLine, timeoutMs?: number): Promise<ExecResult>;
|
|
37
|
+
export declare function runCommandStream(cmd: string, cwd: string, onLine: OnLine, timeoutMs?: number, signal?: AbortSignal): Promise<ExecResult>;
|
|
31
38
|
/**
|
|
32
39
|
* Capture ESP-IDF environment. Cached for the lifetime of the server process.
|
|
33
40
|
* - Windows: runs export.bat and parses `set` output
|
|
@@ -41,7 +48,12 @@ export declare function runWithIdf(cmd: string, cwd: string, timeoutMs?: number)
|
|
|
41
48
|
/**
|
|
42
49
|
* Run a command with the ESP-IDF environment, streaming output line-by-line.
|
|
43
50
|
*/
|
|
44
|
-
export declare function runWithIdfStream(cmd: string, cwd: string, onLine: OnLine, timeoutMs?: number): Promise<ExecResult>;
|
|
51
|
+
export declare function runWithIdfStream(cmd: string, cwd: string, onLine: OnLine, timeoutMs?: number, signal?: AbortSignal): Promise<ExecResult>;
|
|
52
|
+
/**
|
|
53
|
+
* Run with IDF env in argv mode (no shell) — use for commands taking
|
|
54
|
+
* user-controlled args (port path, firmware path).
|
|
55
|
+
*/
|
|
56
|
+
export declare function runIdfArgvStream(cmd: string, args: string[], cwd: string, onLine: OnLine, timeoutMs?: number, signal?: AbortSignal): Promise<ExecResult>;
|
|
45
57
|
/**
|
|
46
58
|
* Run a build command with the appropriate environment for the current platform.
|
|
47
59
|
* Windows: MSVC env + cmd.exe shell. Unix: default shell.
|
|
@@ -51,7 +63,7 @@ export declare function runBuild(cmd: string, cwd: string, timeoutMs?: number):
|
|
|
51
63
|
* Run a build command with streaming output, platform-aware.
|
|
52
64
|
* Windows: MSVC env + cmd.exe shell. Unix: default shell.
|
|
53
65
|
*/
|
|
54
|
-
export declare function runBuildStream(cmd: string, cwd: string, onLine: OnLine, timeoutMs?: number): Promise<ExecResult>;
|
|
66
|
+
export declare function runBuildStream(cmd: string, cwd: string, onLine: OnLine, timeoutMs?: number, signal?: AbortSignal): Promise<ExecResult>;
|
|
55
67
|
/**
|
|
56
68
|
* Run a command with the ESP-IDF environment, platform-aware.
|
|
57
69
|
*/
|
|
@@ -59,7 +71,7 @@ export declare function runIdf(cmd: string, cwd: string, timeoutMs?: number): Ex
|
|
|
59
71
|
/**
|
|
60
72
|
* Run a command with the ESP-IDF environment, streaming, platform-aware.
|
|
61
73
|
*/
|
|
62
|
-
export declare function runIdfStream(cmd: string, cwd: string, onLine: OnLine, timeoutMs?: number): Promise<ExecResult>;
|
|
74
|
+
export declare function runIdfStream(cmd: string, cwd: string, onLine: OnLine, timeoutMs?: number, signal?: AbortSignal): Promise<ExecResult>;
|
|
63
75
|
/**
|
|
64
76
|
* Spawn a detached process (for crosspad_run).
|
|
65
77
|
*/
|
package/dist/utils/exec.js
CHANGED
|
@@ -1,9 +1,20 @@
|
|
|
1
1
|
import { execSync, spawn } from "child_process";
|
|
2
|
+
import fs from "fs";
|
|
2
3
|
import { VCVARSALL, IS_WINDOWS, IDF_PATH } from "../config.js";
|
|
3
|
-
// ═══════════════════════════════════════════════════════════════════════
|
|
4
|
-
// MSVC ENVIRONMENT (Windows-only)
|
|
5
|
-
// ═══════════════════════════════════════════════════════════════════════
|
|
6
4
|
let cachedMsvcEnv = null;
|
|
5
|
+
function statMtime(p) {
|
|
6
|
+
try {
|
|
7
|
+
return fs.statSync(p).mtimeMs;
|
|
8
|
+
}
|
|
9
|
+
catch {
|
|
10
|
+
return 0;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
/** @internal exported for testing — drop both env caches. */
|
|
14
|
+
export function _resetEnvCaches() {
|
|
15
|
+
cachedMsvcEnv = null;
|
|
16
|
+
cachedIdfEnv = null;
|
|
17
|
+
}
|
|
7
18
|
/**
|
|
8
19
|
* Capture MSVC environment by running vcvarsall.bat and parsing `set` output.
|
|
9
20
|
* Cached for the lifetime of the server process. Windows-only.
|
|
@@ -12,8 +23,9 @@ export function getMsvcEnv() {
|
|
|
12
23
|
if (!IS_WINDOWS) {
|
|
13
24
|
return { ...process.env };
|
|
14
25
|
}
|
|
15
|
-
|
|
16
|
-
|
|
26
|
+
const mtime = statMtime(VCVARSALL);
|
|
27
|
+
if (cachedMsvcEnv && cachedMsvcEnv.mtimeMs === mtime)
|
|
28
|
+
return cachedMsvcEnv.data;
|
|
17
29
|
const cmd = `"${VCVARSALL}" x64 >nul 2>&1 && set`;
|
|
18
30
|
const output = execSync(cmd, {
|
|
19
31
|
shell: "cmd.exe",
|
|
@@ -27,7 +39,7 @@ export function getMsvcEnv() {
|
|
|
27
39
|
env[line.slice(0, eq)] = line.slice(eq + 1).trimEnd();
|
|
28
40
|
}
|
|
29
41
|
}
|
|
30
|
-
cachedMsvcEnv = env;
|
|
42
|
+
cachedMsvcEnv = { data: env, mtimeMs: mtime };
|
|
31
43
|
return env;
|
|
32
44
|
}
|
|
33
45
|
// ═══════════════════════════════════════════════════════════════════════
|
|
@@ -101,12 +113,12 @@ export function runCommand(cmd, cwd, timeoutMs = 60_000) {
|
|
|
101
113
|
// ═══════════════════════════════════════════════════════════════════════
|
|
102
114
|
/**
|
|
103
115
|
* Helper: spawn a process and stream stdout/stderr line-by-line via onLine.
|
|
104
|
-
*
|
|
116
|
+
* Supports argv mode (shell:false + args[]) and AbortSignal-driven cancellation.
|
|
105
117
|
*/
|
|
106
|
-
function spawnStreaming(cmd, cwd, env, shell, onLine, timeoutMs) {
|
|
118
|
+
function spawnStreaming(cmd, cwd, env, shell, onLine, timeoutMs, args = [], signal) {
|
|
107
119
|
return new Promise((resolve) => {
|
|
108
120
|
const start = Date.now();
|
|
109
|
-
const child = spawn(cmd,
|
|
121
|
+
const child = spawn(cmd, args, {
|
|
110
122
|
cwd,
|
|
111
123
|
env,
|
|
112
124
|
shell,
|
|
@@ -118,10 +130,23 @@ function spawnStreaming(cmd, cwd, env, shell, onLine, timeoutMs) {
|
|
|
118
130
|
let stdoutBuf = "";
|
|
119
131
|
let stderrBuf = "";
|
|
120
132
|
let killed = false;
|
|
133
|
+
let cancelled = false;
|
|
121
134
|
const timer = setTimeout(() => {
|
|
122
135
|
killed = true;
|
|
123
136
|
child.kill("SIGTERM");
|
|
124
137
|
}, timeoutMs);
|
|
138
|
+
const escalateKill = () => {
|
|
139
|
+
child.kill("SIGTERM");
|
|
140
|
+
setTimeout(() => { if (!child.killed)
|
|
141
|
+
child.kill("SIGKILL"); }, 2000);
|
|
142
|
+
};
|
|
143
|
+
const onAbort = () => { cancelled = true; killed = true; escalateKill(); };
|
|
144
|
+
if (signal) {
|
|
145
|
+
if (signal.aborted)
|
|
146
|
+
onAbort();
|
|
147
|
+
else
|
|
148
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
149
|
+
}
|
|
125
150
|
function flushLines(buf, stream) {
|
|
126
151
|
const parts = buf.split("\n");
|
|
127
152
|
for (let i = 0; i < parts.length - 1; i++) {
|
|
@@ -144,6 +169,8 @@ function spawnStreaming(cmd, cwd, env, shell, onLine, timeoutMs) {
|
|
|
144
169
|
});
|
|
145
170
|
child.on("close", (code) => {
|
|
146
171
|
clearTimeout(timer);
|
|
172
|
+
if (signal)
|
|
173
|
+
signal.removeEventListener("abort", onAbort);
|
|
147
174
|
if (stdoutBuf.length > 0)
|
|
148
175
|
onLine("stdout", stdoutBuf.replace(/\r$/, ""));
|
|
149
176
|
if (stderrBuf.length > 0)
|
|
@@ -151,13 +178,15 @@ function spawnStreaming(cmd, cwd, env, shell, onLine, timeoutMs) {
|
|
|
151
178
|
resolve({
|
|
152
179
|
success: killed ? false : code === 0,
|
|
153
180
|
stdout: normalizeLineEndings(stdout),
|
|
154
|
-
stderr: normalizeLineEndings(stderr),
|
|
181
|
+
stderr: normalizeLineEndings(cancelled ? stderr + "\n[cancelled]" : stderr),
|
|
155
182
|
exitCode: killed ? -1 : (code ?? 1),
|
|
156
183
|
durationMs: Date.now() - start,
|
|
157
184
|
});
|
|
158
185
|
});
|
|
159
186
|
child.on("error", (err) => {
|
|
160
187
|
clearTimeout(timer);
|
|
188
|
+
if (signal)
|
|
189
|
+
signal.removeEventListener("abort", onAbort);
|
|
161
190
|
resolve({
|
|
162
191
|
success: false,
|
|
163
192
|
stdout: normalizeLineEndings(stdout),
|
|
@@ -168,18 +197,25 @@ function spawnStreaming(cmd, cwd, env, shell, onLine, timeoutMs) {
|
|
|
168
197
|
});
|
|
169
198
|
});
|
|
170
199
|
}
|
|
200
|
+
/**
|
|
201
|
+
* Run an arbitrary executable with argv array (no shell). Use for inputs that
|
|
202
|
+
* may contain user-controlled strings — eliminates shell-injection risk.
|
|
203
|
+
*/
|
|
204
|
+
export function runArgvStream(cmd, args, cwd, onLine, timeoutMs = 60_000, signal, env) {
|
|
205
|
+
return spawnStreaming(cmd, cwd, env, false, onLine, timeoutMs, args, signal);
|
|
206
|
+
}
|
|
171
207
|
/**
|
|
172
208
|
* Run a command with the MSVC environment, streaming output line-by-line.
|
|
173
209
|
*/
|
|
174
|
-
export function runWithMsvcStream(cmd, cwd, onLine, timeoutMs = 300_000) {
|
|
210
|
+
export function runWithMsvcStream(cmd, cwd, onLine, timeoutMs = 300_000, signal) {
|
|
175
211
|
const env = getMsvcEnv();
|
|
176
|
-
return spawnStreaming(cmd, cwd, env, "cmd.exe", onLine, timeoutMs);
|
|
212
|
+
return spawnStreaming(cmd, cwd, env, "cmd.exe", onLine, timeoutMs, [], signal);
|
|
177
213
|
}
|
|
178
214
|
/**
|
|
179
215
|
* Run a command in the default shell, streaming output line-by-line.
|
|
180
216
|
*/
|
|
181
|
-
export function runCommandStream(cmd, cwd, onLine, timeoutMs = 60_000) {
|
|
182
|
-
return spawnStreaming(cmd, cwd, undefined, true, onLine, timeoutMs);
|
|
217
|
+
export function runCommandStream(cmd, cwd, onLine, timeoutMs = 60_000, signal) {
|
|
218
|
+
return spawnStreaming(cmd, cwd, undefined, true, onLine, timeoutMs, [], signal);
|
|
183
219
|
}
|
|
184
220
|
// ═══════════════════════════════════════════════════════════════════════
|
|
185
221
|
// ESP-IDF ENVIRONMENT
|
|
@@ -191,10 +227,12 @@ let cachedIdfEnv = null;
|
|
|
191
227
|
* - Linux/Mac: sources export.sh and captures env via null-delimited output
|
|
192
228
|
*/
|
|
193
229
|
export function getIdfEnv() {
|
|
194
|
-
|
|
195
|
-
|
|
230
|
+
const exportPath = IS_WINDOWS ? `${IDF_PATH}\\export.bat` : `${IDF_PATH}/export.sh`;
|
|
231
|
+
const mtime = statMtime(exportPath);
|
|
232
|
+
if (cachedIdfEnv && cachedIdfEnv.mtimeMs === mtime)
|
|
233
|
+
return cachedIdfEnv.data;
|
|
196
234
|
if (IS_WINDOWS) {
|
|
197
|
-
const exportBat =
|
|
235
|
+
const exportBat = exportPath;
|
|
198
236
|
const cmd = `set MSYSTEM=&& set PYTHONIOENCODING=utf-8&& call "${exportBat}" >nul 2>&1 && set`;
|
|
199
237
|
const output = execSync(cmd, {
|
|
200
238
|
shell: "cmd.exe",
|
|
@@ -208,11 +246,11 @@ export function getIdfEnv() {
|
|
|
208
246
|
env[line.slice(0, eq)] = line.slice(eq + 1).trimEnd();
|
|
209
247
|
}
|
|
210
248
|
}
|
|
211
|
-
cachedIdfEnv = env;
|
|
249
|
+
cachedIdfEnv = { data: env, mtimeMs: mtime };
|
|
212
250
|
return env;
|
|
213
251
|
}
|
|
214
252
|
// Linux/Mac: source export.sh and capture environment
|
|
215
|
-
const exportSh =
|
|
253
|
+
const exportSh = exportPath;
|
|
216
254
|
const cmd = `bash -c '. "${exportSh}" >/dev/null 2>&1 && env -0'`;
|
|
217
255
|
const output = execSync(cmd, {
|
|
218
256
|
encoding: "utf-8",
|
|
@@ -228,7 +266,7 @@ export function getIdfEnv() {
|
|
|
228
266
|
env[entry.slice(0, eq)] = entry.slice(eq + 1);
|
|
229
267
|
}
|
|
230
268
|
}
|
|
231
|
-
cachedIdfEnv = env;
|
|
269
|
+
cachedIdfEnv = { data: env, mtimeMs: mtime };
|
|
232
270
|
return env;
|
|
233
271
|
}
|
|
234
272
|
const IDF_SHELL = IS_WINDOWS ? "cmd.exe" : "/bin/bash";
|
|
@@ -268,9 +306,17 @@ export function runWithIdf(cmd, cwd, timeoutMs = 600_000) {
|
|
|
268
306
|
/**
|
|
269
307
|
* Run a command with the ESP-IDF environment, streaming output line-by-line.
|
|
270
308
|
*/
|
|
271
|
-
export function runWithIdfStream(cmd, cwd, onLine, timeoutMs = 600_000) {
|
|
309
|
+
export function runWithIdfStream(cmd, cwd, onLine, timeoutMs = 600_000, signal) {
|
|
310
|
+
const env = getIdfEnv();
|
|
311
|
+
return spawnStreaming(cmd, cwd, env, IDF_SHELL, onLine, timeoutMs, [], signal);
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* Run with IDF env in argv mode (no shell) — use for commands taking
|
|
315
|
+
* user-controlled args (port path, firmware path).
|
|
316
|
+
*/
|
|
317
|
+
export function runIdfArgvStream(cmd, args, cwd, onLine, timeoutMs = 600_000, signal) {
|
|
272
318
|
const env = getIdfEnv();
|
|
273
|
-
return spawnStreaming(cmd, cwd, env,
|
|
319
|
+
return spawnStreaming(cmd, cwd, env, false, onLine, timeoutMs, args, signal);
|
|
274
320
|
}
|
|
275
321
|
// ═══════════════════════════════════════════════════════════════════════
|
|
276
322
|
// PLATFORM-AGNOSTIC BUILD WRAPPERS
|
|
@@ -289,11 +335,11 @@ export function runBuild(cmd, cwd, timeoutMs = 300_000) {
|
|
|
289
335
|
* Run a build command with streaming output, platform-aware.
|
|
290
336
|
* Windows: MSVC env + cmd.exe shell. Unix: default shell.
|
|
291
337
|
*/
|
|
292
|
-
export function runBuildStream(cmd, cwd, onLine, timeoutMs = 300_000) {
|
|
338
|
+
export function runBuildStream(cmd, cwd, onLine, timeoutMs = 300_000, signal) {
|
|
293
339
|
if (IS_WINDOWS) {
|
|
294
|
-
return runWithMsvcStream(cmd, cwd, onLine, timeoutMs);
|
|
340
|
+
return runWithMsvcStream(cmd, cwd, onLine, timeoutMs, signal);
|
|
295
341
|
}
|
|
296
|
-
return runCommandStream(cmd, cwd, onLine, timeoutMs);
|
|
342
|
+
return runCommandStream(cmd, cwd, onLine, timeoutMs, signal);
|
|
297
343
|
}
|
|
298
344
|
/**
|
|
299
345
|
* Run a command with the ESP-IDF environment, platform-aware.
|
|
@@ -304,8 +350,8 @@ export function runIdf(cmd, cwd, timeoutMs = 600_000) {
|
|
|
304
350
|
/**
|
|
305
351
|
* Run a command with the ESP-IDF environment, streaming, platform-aware.
|
|
306
352
|
*/
|
|
307
|
-
export function runIdfStream(cmd, cwd, onLine, timeoutMs = 600_000) {
|
|
308
|
-
return runWithIdfStream(cmd, cwd, onLine, timeoutMs);
|
|
353
|
+
export function runIdfStream(cmd, cwd, onLine, timeoutMs = 600_000, signal) {
|
|
354
|
+
return runWithIdfStream(cmd, cwd, onLine, timeoutMs, signal);
|
|
309
355
|
}
|
|
310
356
|
/** Strip \r from Windows line endings */
|
|
311
357
|
function normalizeLineEndings(s) {
|