@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.
Files changed (3) hide show
  1. package/SKILL.md +1 -1
  2. package/bin/ldm.js +58 -5
  3. 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.60"
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
- const partial = catalog.find(c => c.id.toLowerCase().includes(q) || q.includes(c.id.toLowerCase()));
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
- execSync(`ldm install ${c.repo}`, { stdio: 'inherit' });
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
- execSync(`ldm install ${c.repo}`, { stdio: 'inherit' });
761
+ await installCatalogComponent(c);
709
762
  } catch (e) {
710
763
  console.error(` x Failed to install ${c.name}: ${e.message}`);
711
764
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wipcomputer/wip-ldm-os",
3
- "version": "0.4.60",
3
+ "version": "0.4.61",
4
4
  "type": "module",
5
5
  "description": "LDM OS: identity, memory, and sovereignty infrastructure for AI agents",
6
6
  "engines": {