memorix 0.3.0 → 0.3.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/dist/cli/index.js CHANGED
@@ -532,11 +532,14 @@ async function getObservationsByIds(ids, projectId) {
532
532
  }
533
533
  async function getTimeline(anchorId, projectId, depthBefore = 3, depthAfter = 3) {
534
534
  const database = await getDb();
535
- const allResults = await search(database, {
535
+ const searchParams = {
536
536
  term: "",
537
- where: { projectId },
538
537
  limit: 1e3
539
- });
538
+ };
539
+ if (projectId) {
540
+ searchParams.where = { projectId };
541
+ }
542
+ const allResults = await search(database, searchParams);
540
543
  const docs = allResults.hits.map((h) => h.document).sort((a, b) => a.createdAt.localeCompare(b.createdAt));
541
544
  const anchorIndex = docs.findIndex((d) => d.observationId === anchorId);
542
545
  if (anchorIndex === -1) {
@@ -2311,8 +2314,8 @@ var init_engine2 = __esm({
2311
2314
  rulesCount = rules.length;
2312
2315
  } catch {
2313
2316
  }
2314
- const skills = this.scanSkills();
2315
- return { mcpConfigs, workflows, rulesCount, skills };
2317
+ const { skills, conflicts: skillConflicts } = this.scanSkills();
2318
+ return { mcpConfigs, workflows, rulesCount, skills, skillConflicts };
2316
2319
  }
2317
2320
  /**
2318
2321
  * Migrate workspace configs to a target agent format.
@@ -2323,7 +2326,7 @@ var init_engine2 = __esm({
2323
2326
  mcpServers: { scanned: [], generated: [] },
2324
2327
  workflows: { scanned: [], generated: [] },
2325
2328
  rules: { scanned: 0, generated: 0 },
2326
- skills: { scanned: [], copied: [] }
2329
+ skills: { scanned: [], conflicts: [], copied: [], skipped: [] }
2327
2330
  };
2328
2331
  const allServers = /* @__PURE__ */ new Map();
2329
2332
  for (const servers of Object.values(scan.mcpConfigs)) {
@@ -2361,6 +2364,7 @@ var init_engine2 = __esm({
2361
2364
  } catch {
2362
2365
  }
2363
2366
  result.skills.scanned = scan.skills;
2367
+ result.skills.conflicts = scan.skillConflicts;
2364
2368
  return result;
2365
2369
  }
2366
2370
  // ---- Private helpers ----
@@ -2381,7 +2385,8 @@ var init_engine2 = __esm({
2381
2385
  */
2382
2386
  scanSkills() {
2383
2387
  const skills = [];
2384
- const seen = /* @__PURE__ */ new Set();
2388
+ const conflicts = [];
2389
+ const seen = /* @__PURE__ */ new Map();
2385
2390
  const home = homedir5();
2386
2391
  for (const [agent, dirs] of Object.entries(_WorkspaceSyncEngine.SKILLS_DIRS)) {
2387
2392
  for (const dir of dirs) {
@@ -2395,7 +2400,6 @@ var init_engine2 = __esm({
2395
2400
  const entries = readdirSync(skillsRoot, { withFileTypes: true });
2396
2401
  for (const entry of entries) {
2397
2402
  if (!entry.isDirectory()) continue;
2398
- if (seen.has(entry.name)) continue;
2399
2403
  const skillMd = join6(skillsRoot, entry.name, "SKILL.md");
2400
2404
  if (!existsSync3(skillMd)) continue;
2401
2405
  let description = "";
@@ -2405,20 +2409,32 @@ var init_engine2 = __esm({
2405
2409
  if (match) description = match[1];
2406
2410
  } catch {
2407
2411
  }
2408
- seen.add(entry.name);
2409
- skills.push({
2412
+ const newEntry = {
2410
2413
  name: entry.name,
2411
2414
  description,
2412
2415
  sourcePath: join6(skillsRoot, entry.name),
2413
2416
  sourceAgent: agent
2414
- });
2417
+ };
2418
+ const existing = seen.get(entry.name);
2419
+ if (existing) {
2420
+ if (existing.sourceAgent !== agent) {
2421
+ conflicts.push({
2422
+ name: entry.name,
2423
+ kept: existing,
2424
+ skipped: newEntry
2425
+ });
2426
+ }
2427
+ continue;
2428
+ }
2429
+ seen.set(entry.name, newEntry);
2430
+ skills.push(newEntry);
2415
2431
  }
2416
2432
  } catch {
2417
2433
  }
2418
2434
  }
2419
2435
  }
2420
2436
  }
2421
- return skills;
2437
+ return { skills, conflicts };
2422
2438
  }
2423
2439
  /**
2424
2440
  * Copy skills to a target agent's skills directory.
@@ -2427,9 +2443,14 @@ var init_engine2 = __esm({
2427
2443
  copySkills(skills, target) {
2428
2444
  const targetDir = this.getTargetSkillsDir(target);
2429
2445
  const copied = [];
2446
+ const skipped = [];
2430
2447
  for (const skill of skills) {
2448
+ if (skill.sourceAgent === target) continue;
2431
2449
  const dest = join6(targetDir, skill.name);
2432
- if (existsSync3(dest)) continue;
2450
+ if (existsSync3(dest)) {
2451
+ skipped.push(`${skill.name} (already exists in ${target})`);
2452
+ continue;
2453
+ }
2433
2454
  try {
2434
2455
  mkdirSync2(targetDir, { recursive: true });
2435
2456
  cpSync(skill.sourcePath, dest, { recursive: true });
@@ -2437,7 +2458,7 @@ var init_engine2 = __esm({
2437
2458
  } catch {
2438
2459
  }
2439
2460
  }
2440
- return copied;
2461
+ return { copied, skipped };
2441
2462
  }
2442
2463
  scanWorkflows() {
2443
2464
  const workflows = [];
@@ -2473,9 +2494,9 @@ var init_engine2 = __esm({
2473
2494
  ...syncResult.workflows.generated
2474
2495
  ];
2475
2496
  const applyResult = await applier.apply(filesToWrite);
2476
- let copiedSkills = [];
2497
+ let skillResult = { copied: [], skipped: [] };
2477
2498
  if (syncResult.skills.scanned.length > 0) {
2478
- copiedSkills = this.copySkills(syncResult.skills.scanned, target);
2499
+ skillResult = this.copySkills(syncResult.skills.scanned, target);
2479
2500
  }
2480
2501
  const lines = [];
2481
2502
  if (applyResult.success) {
@@ -2483,13 +2504,27 @@ var init_engine2 = __esm({
2483
2504
  for (const f of applyResult.filesWritten) {
2484
2505
  lines.push(` \u2192 ${f}`);
2485
2506
  }
2486
- if (copiedSkills.length > 0) {
2507
+ if (skillResult.copied.length > 0) {
2487
2508
  lines.push(`
2488
- \u{1F9E9} Copied ${copiedSkills.length} skill(s):`);
2489
- for (const sk of copiedSkills) {
2509
+ \u{1F9E9} Copied ${skillResult.copied.length} skill(s):`);
2510
+ for (const sk of skillResult.copied) {
2490
2511
  lines.push(` \u2192 ${sk}`);
2491
2512
  }
2492
2513
  }
2514
+ if (skillResult.skipped.length > 0) {
2515
+ lines.push(`
2516
+ \u23ED\uFE0F Skipped ${skillResult.skipped.length} skill(s):`);
2517
+ for (const sk of skillResult.skipped) {
2518
+ lines.push(` \u2192 ${sk}`);
2519
+ }
2520
+ }
2521
+ if (syncResult.skills.conflicts.length > 0) {
2522
+ lines.push(`
2523
+ \u26A0\uFE0F Name conflicts (${syncResult.skills.conflicts.length}):`);
2524
+ for (const c of syncResult.skills.conflicts) {
2525
+ lines.push(` \u2192 "${c.name}": kept ${c.kept.sourceAgent}, skipped ${c.skipped.sourceAgent}`);
2526
+ }
2527
+ }
2493
2528
  if (applyResult.backups.length > 0) {
2494
2529
  lines.push(`
2495
2530
  \u{1F4E6} Backups created (${applyResult.backups.length}):`);
@@ -3505,6 +3540,12 @@ Entity: ${entityName} | Type: ${type} | Project: ${project.id}${enrichment}`
3505
3540
  } else {
3506
3541
  lines2.push("- No skills found");
3507
3542
  }
3543
+ if (scan.skillConflicts.length > 0) {
3544
+ lines2.push("", `### \u26A0\uFE0F Skill Name Conflicts`);
3545
+ for (const c of scan.skillConflicts) {
3546
+ lines2.push(`- **${c.name}**: kept from ${c.kept.sourceAgent}, duplicate in ${c.skipped.sourceAgent}`);
3547
+ }
3548
+ }
3508
3549
  return {
3509
3550
  content: [{ type: "text", text: lines2.join("\n") }]
3510
3551
  };