@hybridlabor-api/bdb-hardware-pcb 0.1.0 → 0.1.2
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/config/mcp/antigravity.json +1 -1
- package/config/mcp/claude.json +1 -1
- package/config/mcp/codex.toml +1 -1
- package/installer.js +62 -1
- package/package.json +1 -1
package/config/mcp/claude.json
CHANGED
package/config/mcp/codex.toml
CHANGED
|
@@ -14,7 +14,7 @@ args = []
|
|
|
14
14
|
enabled = true
|
|
15
15
|
|
|
16
16
|
[mcp_servers.kicad.env]
|
|
17
|
-
KICAD_CLI_PATH = "
|
|
17
|
+
KICAD_CLI_PATH = "__KICAD_CLI_PATH__"
|
|
18
18
|
|
|
19
19
|
[mcp_servers.openscad]
|
|
20
20
|
command = "__INSTALL_DIR__/scripts/run_openscad_mcp.sh"
|
package/installer.js
CHANGED
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
const os = require('os');
|
|
26
26
|
const path = require('path');
|
|
27
27
|
const fs = require('fs');
|
|
28
|
+
const crypto = require('crypto');
|
|
28
29
|
const { spawnSync } = require('child_process');
|
|
29
30
|
|
|
30
31
|
const AUTO = process.argv.includes('--auto');
|
|
@@ -71,12 +72,71 @@ function findPython() {
|
|
|
71
72
|
return null;
|
|
72
73
|
}
|
|
73
74
|
|
|
75
|
+
function findKicadCliPath() {
|
|
76
|
+
if (process.env.KICAD_CLI_PATH) return process.env.KICAD_CLI_PATH;
|
|
77
|
+
if (commandExists('kicad-cli')) return 'kicad-cli';
|
|
78
|
+
let candidates = [];
|
|
79
|
+
if (IS_WIN) {
|
|
80
|
+
const base = path.join(process.env.ProgramFiles || 'C:\\Program Files', 'KiCad');
|
|
81
|
+
if (fs.existsSync(base)) {
|
|
82
|
+
candidates = fs.readdirSync(base)
|
|
83
|
+
.map((v) => path.join(base, v, 'bin', 'kicad-cli.exe'))
|
|
84
|
+
.sort()
|
|
85
|
+
.reverse(); // prefer the highest version dir (e.g. 9.0 over 7.0)
|
|
86
|
+
}
|
|
87
|
+
} else if (process.platform === 'darwin') {
|
|
88
|
+
candidates = ['/Applications/KiCad/KiCad.app/Contents/MacOS/kicad-cli'];
|
|
89
|
+
} else {
|
|
90
|
+
candidates = ['/usr/bin/kicad-cli', '/usr/local/bin/kicad-cli'];
|
|
91
|
+
}
|
|
92
|
+
const found = candidates.find((p) => fs.existsSync(p));
|
|
93
|
+
if (found) return found;
|
|
94
|
+
log.warn('kicad-cli not found on PATH or in known install locations — set the KICAD_CLI_PATH env var manually once KiCad is installed.');
|
|
95
|
+
return 'kicad-cli';
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Hash of pyproject.toml, used as a cheap "did the dependency spec change"
|
|
99
|
+
// marker. AOS's swap-in-place upgrade preserves .venv across a version bump
|
|
100
|
+
// (that's the whole point of the PRESERVE list), so "the venv dir exists" is
|
|
101
|
+
// NOT enough on its own to prove it's still current for THIS version -- the
|
|
102
|
+
// hash comparison is what makes skipping safe across an upgrade that did
|
|
103
|
+
// change deps, not just across an unattended re-run that didn't.
|
|
104
|
+
function depsSpecHash(serverDir) {
|
|
105
|
+
const p = path.join(serverDir, 'pyproject.toml');
|
|
106
|
+
if (!fs.existsSync(p)) return null;
|
|
107
|
+
return crypto.createHash('sha256').update(fs.readFileSync(p)).digest('hex');
|
|
108
|
+
}
|
|
109
|
+
|
|
74
110
|
function setupServerEnv(server, uvBin, pythonBin) {
|
|
75
111
|
const venvDir = path.join(server.dir, '.venv');
|
|
112
|
+
const markerPath = path.join(venvDir, '.aos-deps-hash');
|
|
113
|
+
const currentHash = depsSpecHash(server.dir);
|
|
114
|
+
|
|
115
|
+
// Every Quick Update used to re-run `uv sync` / `pip install` here
|
|
116
|
+
// unconditionally, even when downloadOrUpdateModule() (in the main AOS
|
|
117
|
+
// installer) had already determined this module's version hadn't
|
|
118
|
+
// changed at all -- real network calls and, on the pip fallback path
|
|
119
|
+
// with no uv on PATH, a genuinely slow full dependency resolve, every
|
|
120
|
+
// single run, for nothing.
|
|
121
|
+
if (currentHash && fs.existsSync(venvDir) && fs.existsSync(markerPath)) {
|
|
122
|
+
try {
|
|
123
|
+
if (fs.readFileSync(markerPath, 'utf8').trim() === currentHash) {
|
|
124
|
+
log.ok(`${server.name}-mcp-server: dependencies already up to date, skipping sync`);
|
|
125
|
+
return true;
|
|
126
|
+
}
|
|
127
|
+
} catch (e) { /* fall through to a real sync if the marker is unreadable */ }
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const markDone = () => {
|
|
131
|
+
if (!currentHash) return;
|
|
132
|
+
try { fs.writeFileSync(markerPath, currentHash); } catch (e) { /* non-fatal: just means next run re-syncs once more */ }
|
|
133
|
+
};
|
|
134
|
+
|
|
76
135
|
if (uvBin) {
|
|
77
136
|
const res = spawnSync(uvBin, ['sync'], { cwd: server.dir, stdio: 'inherit' });
|
|
78
137
|
if (res.status === 0) {
|
|
79
138
|
log.ok(`${server.name}-mcp-server: dependencies synced via uv`);
|
|
139
|
+
markDone();
|
|
80
140
|
return true;
|
|
81
141
|
}
|
|
82
142
|
log.warn(`${server.name}-mcp-server: 'uv sync' failed (exit ${res.status}); falling back to venv+pip`);
|
|
@@ -99,6 +159,7 @@ function setupServerEnv(server, uvBin, pythonBin) {
|
|
|
99
159
|
return false;
|
|
100
160
|
}
|
|
101
161
|
log.ok(`${server.name}-mcp-server: dependencies installed via venv+pip`);
|
|
162
|
+
markDone();
|
|
102
163
|
return true;
|
|
103
164
|
}
|
|
104
165
|
|
|
@@ -166,7 +227,7 @@ function mcpServerEntries() {
|
|
|
166
227
|
kicad: {
|
|
167
228
|
command: kicad.command,
|
|
168
229
|
args: kicad.args,
|
|
169
|
-
env: { KICAD_CLI_PATH:
|
|
230
|
+
env: { KICAD_CLI_PATH: findKicadCliPath() },
|
|
170
231
|
},
|
|
171
232
|
openscad: {
|
|
172
233
|
command: openscad.command,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hybridlabor-api/bdb-hardware-pcb",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "BDB Hardware & PCB — KiCad + OpenSCAD MCP servers and AI-era skills for schematic capture, PCB layout/routing, DFM sign-off, and parametric 3D enclosure design",
|
|
5
5
|
"main": "installer.js",
|
|
6
6
|
"bin": {
|