@wipcomputer/wip-ldm-os 0.4.60 → 0.4.61
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/SKILL.md +1 -1
- package/bin/ldm.js +58 -5
- package/package.json +1 -1
package/SKILL.md
CHANGED
|
@@ -9,7 +9,7 @@ license: MIT
|
|
|
9
9
|
compatibility: Requires git, npm, node. Node.js 18+.
|
|
10
10
|
metadata:
|
|
11
11
|
display-name: "LDM OS"
|
|
12
|
-
version: "0.4.
|
|
12
|
+
version: "0.4.61"
|
|
13
13
|
homepage: "https://github.com/wipcomputer/wip-ldm-os"
|
|
14
14
|
author: "Parker Todd Brooks"
|
|
15
15
|
category: infrastructure
|
package/bin/ldm.js
CHANGED
|
@@ -229,22 +229,75 @@ function loadCatalog() {
|
|
|
229
229
|
|
|
230
230
|
function findInCatalog(id) {
|
|
231
231
|
const q = id.toLowerCase();
|
|
232
|
+
// Strip org/ prefix for matching (e.g. "wipcomputer/openclaw-tavily" -> "openclaw-tavily")
|
|
233
|
+
const qBase = q.includes('/') ? q.split('/').pop() : q;
|
|
232
234
|
const catalog = loadCatalog();
|
|
233
235
|
// Exact id match
|
|
234
|
-
const exact = catalog.find(c => c.id === id);
|
|
236
|
+
const exact = catalog.find(c => c.id === id || c.id === qBase);
|
|
235
237
|
if (exact) return exact;
|
|
238
|
+
// Exact repo match (e.g. "wipcomputer/openclaw-tavily" matches repo field directly)
|
|
239
|
+
const byRepo = catalog.find(c => c.repo && c.repo.toLowerCase() === q);
|
|
240
|
+
if (byRepo) return byRepo;
|
|
236
241
|
// Partial id match (e.g. "xai-grok" matches "wip-xai-grok")
|
|
237
|
-
|
|
242
|
+
// Check both directions but require word-boundary alignment (hyphen or start of string)
|
|
243
|
+
// to prevent "openclaw" matching "openclaw-tavily"
|
|
244
|
+
const partial = catalog.find(c => {
|
|
245
|
+
const cid = c.id.toLowerCase();
|
|
246
|
+
if (cid === qBase) return false;
|
|
247
|
+
// Query is suffix of catalog id: "xai-grok" matches "wip-xai-grok"
|
|
248
|
+
if (cid.endsWith(qBase) && (cid.length === qBase.length || cid[cid.length - qBase.length - 1] === '-')) return true;
|
|
249
|
+
// Catalog id is suffix of query: "wip-xai-grok" matches when query is "wip-xai-grok-private"
|
|
250
|
+
if (qBase.endsWith(cid) && (qBase.length === cid.length || qBase[qBase.length - cid.length - 1] === '-')) return true;
|
|
251
|
+
return false;
|
|
252
|
+
});
|
|
238
253
|
if (partial) return partial;
|
|
239
254
|
// Name match (case-insensitive, e.g. "xAI Grok")
|
|
240
255
|
const byName = catalog.find(c => c.name && c.name.toLowerCase() === q);
|
|
241
256
|
if (byName) return byName;
|
|
242
257
|
// registryMatches match
|
|
243
|
-
const byRegistry = catalog.find(c => (c.registryMatches || []).some(m => m.toLowerCase() === q));
|
|
258
|
+
const byRegistry = catalog.find(c => (c.registryMatches || []).some(m => m.toLowerCase() === q || m.toLowerCase() === qBase));
|
|
244
259
|
if (byRegistry) return byRegistry;
|
|
245
260
|
return null;
|
|
246
261
|
}
|
|
247
262
|
|
|
263
|
+
// Install a single catalog component directly (no subprocess).
|
|
264
|
+
// Replaces the old execSync('ldm install ${c.repo}') which spawned
|
|
265
|
+
// a full installer process for each component.
|
|
266
|
+
async function installCatalogComponent(c) {
|
|
267
|
+
const { installFromPath } = await import('../lib/deploy.mjs');
|
|
268
|
+
const repoTarget = c.repo;
|
|
269
|
+
const repoName = basename(repoTarget);
|
|
270
|
+
const repoPath = join(LDM_TMP, repoName);
|
|
271
|
+
const httpsUrl = `https://github.com/${repoTarget}.git`;
|
|
272
|
+
const sshUrl = `git@github.com:${repoTarget}.git`;
|
|
273
|
+
|
|
274
|
+
mkdirSync(LDM_TMP, { recursive: true });
|
|
275
|
+
console.log(` Cloning ${repoTarget}...`);
|
|
276
|
+
try {
|
|
277
|
+
if (existsSync(repoPath)) {
|
|
278
|
+
execSync(`rm -rf "${repoPath}"`, { stdio: 'pipe' });
|
|
279
|
+
}
|
|
280
|
+
try {
|
|
281
|
+
execSync(`git clone --depth 1 "${httpsUrl}" "${repoPath}"`, { stdio: 'pipe' });
|
|
282
|
+
} catch {
|
|
283
|
+
console.log(` HTTPS failed. Trying SSH...`);
|
|
284
|
+
if (existsSync(repoPath)) execSync(`rm -rf "${repoPath}"`, { stdio: 'pipe' });
|
|
285
|
+
execSync(`git clone --depth 1 "${sshUrl}" "${repoPath}"`, { stdio: 'pipe' });
|
|
286
|
+
}
|
|
287
|
+
} catch (e) {
|
|
288
|
+
console.error(` x Clone failed: ${e.message}`);
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
await installFromPath(repoPath);
|
|
293
|
+
|
|
294
|
+
// Clean up staging clone
|
|
295
|
+
if (repoPath.startsWith(LDM_TMP)) {
|
|
296
|
+
try { execSync(`rm -rf "${repoPath}"`, { stdio: 'pipe' }); } catch {}
|
|
297
|
+
}
|
|
298
|
+
console.log(` ✓ Installed ${c.name}`);
|
|
299
|
+
}
|
|
300
|
+
|
|
248
301
|
// ── ldm init ──
|
|
249
302
|
|
|
250
303
|
async function cmdInit() {
|
|
@@ -669,7 +722,7 @@ async function showCatalogPicker() {
|
|
|
669
722
|
for (const c of recommended) {
|
|
670
723
|
console.log(` Installing ${c.name}...`);
|
|
671
724
|
try {
|
|
672
|
-
|
|
725
|
+
await installCatalogComponent(c);
|
|
673
726
|
} catch (e) {
|
|
674
727
|
console.error(` x Failed to install ${c.name}: ${e.message}`);
|
|
675
728
|
}
|
|
@@ -705,7 +758,7 @@ async function showCatalogPicker() {
|
|
|
705
758
|
console.log('');
|
|
706
759
|
console.log(` Installing ${c.name}...`);
|
|
707
760
|
try {
|
|
708
|
-
|
|
761
|
+
await installCatalogComponent(c);
|
|
709
762
|
} catch (e) {
|
|
710
763
|
console.error(` x Failed to install ${c.name}: ${e.message}`);
|
|
711
764
|
}
|