@wipcomputer/wip-ldm-os 0.4.59 → 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 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.59"
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
  }
@@ -2727,7 +2780,7 @@ async function main() {
2727
2780
 
2728
2781
  if (sub === '--help' || sub === '-h') {
2729
2782
  console.log(`
2730
- ldm worktree add <branch> Create worktree in _worktrees/ (auto-detects repo)
2783
+ ldm worktree add <branch> Create worktree in .worktrees/ (auto-detects repo)
2731
2784
  ldm worktree list List all worktrees across repos
2732
2785
  ldm worktree clean Prune worktrees for merged branches
2733
2786
  ldm worktree remove <path> Remove a specific worktree
@@ -2756,7 +2809,7 @@ async function main() {
2756
2809
 
2757
2810
  const repoName = basename(repoRoot);
2758
2811
  const branchSuffix = branchName.replace(/\//g, '--');
2759
- const worktreesDir = join(dirname(repoRoot), '_worktrees');
2812
+ const worktreesDir = join(dirname(repoRoot), '.worktrees');
2760
2813
  const worktreePath = join(worktreesDir, `${repoName}--${branchSuffix}`);
2761
2814
 
2762
2815
  mkdirSync(worktreesDir, { recursive: true });
@@ -2801,14 +2854,14 @@ async function main() {
2801
2854
  }
2802
2855
  } catch {}
2803
2856
 
2804
- // Also check _worktrees/ dir
2805
- const worktreesDir = join(dirname(process.cwd()), '_worktrees');
2857
+ // Also check .worktrees/ dir
2858
+ const worktreesDir = join(dirname(process.cwd()), '.worktrees');
2806
2859
  if (existsSync(worktreesDir)) {
2807
2860
  try {
2808
2861
  const entries = readdirSync(worktreesDir, { withFileTypes: true })
2809
2862
  .filter(d => d.isDirectory());
2810
2863
  if (entries.length > 0) {
2811
- console.log(` _worktrees/:`);
2864
+ console.log(` .worktrees/:`);
2812
2865
  for (const d of entries) {
2813
2866
  console.log(` ${d.name}`);
2814
2867
  }
package/catalog.json CHANGED
@@ -286,7 +286,7 @@
286
286
  "id": "tavily",
287
287
  "name": "Tavily",
288
288
  "description": "Web search and content extraction via Tavily API.",
289
- "npm": "tavily",
289
+ "npm": "@wipcomputer/openclaw-tavily",
290
290
  "repo": "wipcomputer/openclaw-tavily",
291
291
  "registryMatches": [
292
292
  "tavily"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wipcomputer/wip-ldm-os",
3
- "version": "0.4.59",
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": {