memorix 0.6.0 → 0.6.1

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
@@ -1799,6 +1799,76 @@ var init_copilot = __esm({
1799
1799
  }
1800
1800
  });
1801
1801
 
1802
+ // src/rules/adapters/kiro.ts
1803
+ import matter7 from "gray-matter";
1804
+ var KiroAdapter;
1805
+ var init_kiro = __esm({
1806
+ "src/rules/adapters/kiro.ts"() {
1807
+ "use strict";
1808
+ init_esm_shims();
1809
+ init_utils();
1810
+ KiroAdapter = class {
1811
+ source = "kiro";
1812
+ filePatterns = [
1813
+ ".kiro/steering/*.md",
1814
+ "AGENTS.md"
1815
+ ];
1816
+ parse(filePath, content) {
1817
+ if (filePath.includes(".kiro/steering/")) {
1818
+ return this.parseSteeringRule(filePath, content);
1819
+ }
1820
+ if (filePath.endsWith("AGENTS.md")) {
1821
+ return this.parseAgentsMd(filePath, content);
1822
+ }
1823
+ return [];
1824
+ }
1825
+ generate(rules) {
1826
+ return rules.map((rule, i) => {
1827
+ const fm = {};
1828
+ if (rule.description) fm.description = rule.description;
1829
+ const fileName = rule.id.replace(/^kiro:/, "").replace(/[^a-zA-Z0-9-_]/g, "-") || `rule-${i}`;
1830
+ const body = Object.keys(fm).length > 0 ? matter7.stringify(rule.content, fm) : rule.content;
1831
+ return {
1832
+ filePath: `.kiro/steering/${fileName}.md`,
1833
+ content: body
1834
+ };
1835
+ });
1836
+ }
1837
+ parseSteeringRule(filePath, content) {
1838
+ const { data, content: body } = matter7(content);
1839
+ const trimmed = body.trim();
1840
+ if (!trimmed) return [];
1841
+ const trigger = data.trigger;
1842
+ const alwaysApply = !trigger || trigger === "always";
1843
+ return [{
1844
+ id: generateRuleId("kiro", filePath),
1845
+ content: trimmed,
1846
+ description: data.description,
1847
+ source: "kiro",
1848
+ scope: alwaysApply ? "global" : "path-specific",
1849
+ paths: data.globs,
1850
+ alwaysApply,
1851
+ priority: alwaysApply ? 10 : 5,
1852
+ hash: hashContent(trimmed)
1853
+ }];
1854
+ }
1855
+ parseAgentsMd(filePath, content) {
1856
+ const trimmed = content.trim();
1857
+ if (!trimmed) return [];
1858
+ return [{
1859
+ id: generateRuleId("kiro", filePath),
1860
+ content: trimmed,
1861
+ source: "kiro",
1862
+ scope: "project",
1863
+ alwaysApply: true,
1864
+ priority: 10,
1865
+ hash: hashContent(trimmed)
1866
+ }];
1867
+ }
1868
+ };
1869
+ }
1870
+ });
1871
+
1802
1872
  // src/rules/syncer.ts
1803
1873
  var syncer_exports = {};
1804
1874
  __export(syncer_exports, {
@@ -1817,6 +1887,7 @@ var init_syncer = __esm({
1817
1887
  init_windsurf();
1818
1888
  init_antigravity();
1819
1889
  init_copilot();
1890
+ init_kiro();
1820
1891
  RulesSyncer = class {
1821
1892
  projectRoot;
1822
1893
  adapters;
@@ -1829,7 +1900,8 @@ var init_syncer = __esm({
1829
1900
  new CodexAdapter(),
1830
1901
  new WindsurfAdapter(),
1831
1902
  new AntigravityAdapter(),
1832
- new CopilotAdapter()
1903
+ new CopilotAdapter(),
1904
+ new KiroAdapter()
1833
1905
  ];
1834
1906
  for (const a of all) {
1835
1907
  this.adapters.set(a.source, a);
@@ -2438,8 +2510,60 @@ var init_antigravity2 = __esm({
2438
2510
  }
2439
2511
  });
2440
2512
 
2513
+ // src/workspace/mcp-adapters/kiro.ts
2514
+ import { homedir as homedir7 } from "os";
2515
+ import { join as join7 } from "path";
2516
+ var KiroMCPAdapter;
2517
+ var init_kiro2 = __esm({
2518
+ "src/workspace/mcp-adapters/kiro.ts"() {
2519
+ "use strict";
2520
+ init_esm_shims();
2521
+ KiroMCPAdapter = class {
2522
+ source = "kiro";
2523
+ parse(content) {
2524
+ try {
2525
+ const config = JSON.parse(content);
2526
+ const servers = config.mcpServers ?? {};
2527
+ return Object.entries(servers).map(([name, entry]) => ({
2528
+ name,
2529
+ command: entry.command ?? "",
2530
+ args: entry.args ?? [],
2531
+ ...entry.env && Object.keys(entry.env).length > 0 ? { env: entry.env } : {},
2532
+ ...entry.url ? { url: entry.url } : {}
2533
+ }));
2534
+ } catch {
2535
+ return [];
2536
+ }
2537
+ }
2538
+ generate(servers) {
2539
+ const mcpServers = {};
2540
+ for (const s of servers) {
2541
+ const entry = {};
2542
+ if (s.url) {
2543
+ entry.url = s.url;
2544
+ } else {
2545
+ entry.command = s.command;
2546
+ entry.args = s.args;
2547
+ }
2548
+ if (s.env && Object.keys(s.env).length > 0) {
2549
+ entry.env = s.env;
2550
+ }
2551
+ mcpServers[s.name] = entry;
2552
+ }
2553
+ return JSON.stringify({ mcpServers }, null, 2);
2554
+ }
2555
+ getConfigPath(projectRoot) {
2556
+ if (projectRoot) {
2557
+ return join7(projectRoot, ".kiro", "settings", "mcp.json");
2558
+ }
2559
+ return join7(homedir7(), ".kiro", "settings", "mcp.json");
2560
+ }
2561
+ };
2562
+ }
2563
+ });
2564
+
2441
2565
  // src/workspace/workflow-sync.ts
2442
- import matter7 from "gray-matter";
2566
+ import matter8 from "gray-matter";
2443
2567
  var WorkflowSyncer;
2444
2568
  var init_workflow_sync = __esm({
2445
2569
  "src/workspace/workflow-sync.ts"() {
@@ -2454,7 +2578,7 @@ var init_workflow_sync = __esm({
2454
2578
  let description = "";
2455
2579
  let content = raw;
2456
2580
  try {
2457
- const parsed = matter7(raw);
2581
+ const parsed = matter8(raw);
2458
2582
  description = parsed.data?.description ?? "";
2459
2583
  content = parsed.content.trim();
2460
2584
  } catch {
@@ -2476,7 +2600,7 @@ var init_workflow_sync = __esm({
2476
2600
  if (wf.description) {
2477
2601
  fm.description = wf.description;
2478
2602
  }
2479
- const content = matter7.stringify(wf.content, fm);
2603
+ const content = matter8.stringify(wf.content, fm);
2480
2604
  return {
2481
2605
  filePath: `.agents/skills/${safeName}/SKILL.md`,
2482
2606
  content
@@ -2493,7 +2617,7 @@ var init_workflow_sync = __esm({
2493
2617
  }
2494
2618
  fm.globs = "";
2495
2619
  fm.alwaysApply = "false";
2496
- const content = matter7.stringify(wf.content, fm);
2620
+ const content = matter8.stringify(wf.content, fm);
2497
2621
  return {
2498
2622
  filePath: `.cursor/rules/${safeName}.mdc`,
2499
2623
  content
@@ -2681,8 +2805,8 @@ var init_applier = __esm({
2681
2805
 
2682
2806
  // src/workspace/engine.ts
2683
2807
  import { readFileSync as readFileSync2, readdirSync, existsSync as existsSync4, cpSync, mkdirSync as mkdirSync2 } from "fs";
2684
- import { join as join8 } from "path";
2685
- import { homedir as homedir7 } from "os";
2808
+ import { join as join9 } from "path";
2809
+ import { homedir as homedir8 } from "os";
2686
2810
  var WorkspaceSyncEngine;
2687
2811
  var init_engine2 = __esm({
2688
2812
  "src/workspace/engine.ts"() {
@@ -2694,6 +2818,7 @@ var init_engine2 = __esm({
2694
2818
  init_claude_code2();
2695
2819
  init_copilot2();
2696
2820
  init_antigravity2();
2821
+ init_kiro2();
2697
2822
  init_workflow_sync();
2698
2823
  init_syncer();
2699
2824
  init_sanitizer();
@@ -2707,7 +2832,8 @@ var init_engine2 = __esm({
2707
2832
  ["codex", new CodexMCPAdapter()],
2708
2833
  ["claude-code", new ClaudeCodeMCPAdapter()],
2709
2834
  ["copilot", new CopilotMCPAdapter()],
2710
- ["antigravity", new AntigravityMCPAdapter()]
2835
+ ["antigravity", new AntigravityMCPAdapter()],
2836
+ ["kiro", new KiroMCPAdapter()]
2711
2837
  ]);
2712
2838
  this.workflowSyncer = new WorkflowSyncer();
2713
2839
  this.rulesSyncer = new RulesSyncer(projectRoot);
@@ -2725,7 +2851,8 @@ var init_engine2 = __esm({
2725
2851
  codex: [],
2726
2852
  "claude-code": [],
2727
2853
  copilot: [],
2728
- antigravity: []
2854
+ antigravity: [],
2855
+ kiro: []
2729
2856
  };
2730
2857
  for (const [target, adapter] of this.adapters) {
2731
2858
  const configPath = adapter.getConfigPath(this.projectRoot);
@@ -2817,13 +2944,14 @@ var init_engine2 = __esm({
2817
2944
  windsurf: [".windsurf/skills"],
2818
2945
  "claude-code": [".claude/skills"],
2819
2946
  copilot: [".github/skills", ".copilot/skills"],
2820
- antigravity: [".agent/skills", ".gemini/skills", ".gemini/antigravity/skills"]
2947
+ antigravity: [".agent/skills", ".gemini/skills", ".gemini/antigravity/skills"],
2948
+ kiro: [".kiro/skills"]
2821
2949
  };
2822
2950
  /** Get the target skills directory for an agent (null if agent has no skills support) */
2823
2951
  getTargetSkillsDir(target) {
2824
2952
  const dirs = _WorkspaceSyncEngine.SKILLS_DIRS[target];
2825
2953
  if (!dirs || dirs.length === 0) return null;
2826
- return join8(this.projectRoot, dirs[0]);
2954
+ return join9(this.projectRoot, dirs[0]);
2827
2955
  }
2828
2956
  /**
2829
2957
  * Scan all agent skills directories and collect unique skills.
@@ -2832,12 +2960,12 @@ var init_engine2 = __esm({
2832
2960
  const skills = [];
2833
2961
  const conflicts = [];
2834
2962
  const seen = /* @__PURE__ */ new Map();
2835
- const home = homedir7();
2963
+ const home = homedir8();
2836
2964
  for (const [agent, dirs] of Object.entries(_WorkspaceSyncEngine.SKILLS_DIRS)) {
2837
2965
  for (const dir of dirs) {
2838
2966
  const paths = [
2839
- join8(this.projectRoot, dir),
2840
- join8(home, dir)
2967
+ join9(this.projectRoot, dir),
2968
+ join9(home, dir)
2841
2969
  ];
2842
2970
  for (const skillsRoot of paths) {
2843
2971
  if (!existsSync4(skillsRoot)) continue;
@@ -2845,7 +2973,7 @@ var init_engine2 = __esm({
2845
2973
  const entries = readdirSync(skillsRoot, { withFileTypes: true });
2846
2974
  for (const entry of entries) {
2847
2975
  if (!entry.isDirectory()) continue;
2848
- const skillMd = join8(skillsRoot, entry.name, "SKILL.md");
2976
+ const skillMd = join9(skillsRoot, entry.name, "SKILL.md");
2849
2977
  if (!existsSync4(skillMd)) continue;
2850
2978
  let description = "";
2851
2979
  try {
@@ -2857,7 +2985,7 @@ var init_engine2 = __esm({
2857
2985
  const newEntry = {
2858
2986
  name: entry.name,
2859
2987
  description,
2860
- sourcePath: join8(skillsRoot, entry.name),
2988
+ sourcePath: join9(skillsRoot, entry.name),
2861
2989
  sourceAgent: agent
2862
2990
  };
2863
2991
  const existing = seen.get(entry.name);
@@ -2894,7 +3022,7 @@ var init_engine2 = __esm({
2894
3022
  }
2895
3023
  for (const skill of skills) {
2896
3024
  if (skill.sourceAgent === target) continue;
2897
- const dest = join8(targetDir, skill.name);
3025
+ const dest = join9(targetDir, skill.name);
2898
3026
  if (existsSync4(dest)) {
2899
3027
  skipped.push(`${skill.name} (already exists in ${target})`);
2900
3028
  continue;
@@ -2910,13 +3038,13 @@ var init_engine2 = __esm({
2910
3038
  }
2911
3039
  scanWorkflows() {
2912
3040
  const workflows = [];
2913
- const wfDir = join8(this.projectRoot, ".windsurf", "workflows");
3041
+ const wfDir = join9(this.projectRoot, ".windsurf", "workflows");
2914
3042
  if (!existsSync4(wfDir)) return workflows;
2915
3043
  try {
2916
3044
  const files = readdirSync(wfDir).filter((f) => f.endsWith(".md"));
2917
3045
  for (const file of files) {
2918
3046
  try {
2919
- const content = readFileSync2(join8(wfDir, file), "utf-8");
3047
+ const content = readFileSync2(join9(wfDir, file), "utf-8");
2920
3048
  workflows.push(this.workflowSyncer.parseWindsurfWorkflow(file, content));
2921
3049
  } catch {
2922
3050
  }
@@ -3004,7 +3132,8 @@ var init_engine2 = __esm({
3004
3132
  codex: "codex",
3005
3133
  windsurf: "windsurf",
3006
3134
  copilot: "copilot",
3007
- antigravity: "antigravity"
3135
+ antigravity: "antigravity",
3136
+ kiro: "kiro"
3008
3137
  };
3009
3138
  return map[target] ?? null;
3010
3139
  }
@@ -3670,8 +3799,42 @@ async function handleApi(req, res, dataDir, projectId, projectName, baseDir) {
3670
3799
  });
3671
3800
  break;
3672
3801
  }
3673
- default:
3802
+ default: {
3803
+ const deleteMatch = apiPath.match(/^\/observations\/(\d+)$/);
3804
+ if (deleteMatch && req.method === "DELETE") {
3805
+ const obsId = parseInt(deleteMatch[1], 10);
3806
+ const allObs = await loadObservationsJson(effectiveDataDir);
3807
+ const idx = allObs.findIndex((o) => o.id === obsId);
3808
+ if (idx === -1) {
3809
+ sendError(res, "Observation not found", 404);
3810
+ } else {
3811
+ allObs.splice(idx, 1);
3812
+ await saveObservationsJson(effectiveDataDir, allObs);
3813
+ sendJson(res, { ok: true, deleted: obsId });
3814
+ }
3815
+ break;
3816
+ }
3817
+ if (apiPath === "/export") {
3818
+ const graph = await loadGraphJsonl(effectiveDataDir);
3819
+ const allObs = await loadObservationsJson(effectiveDataDir);
3820
+ const observations2 = filterByProject(allObs, effectiveProjectId);
3821
+ const nextId2 = await loadIdCounter(effectiveDataDir);
3822
+ const exportData = {
3823
+ project: { id: effectiveProjectId, name: effectiveProjectName },
3824
+ exportedAt: (/* @__PURE__ */ new Date()).toISOString(),
3825
+ graph,
3826
+ observations: observations2,
3827
+ nextId: nextId2
3828
+ };
3829
+ res.writeHead(200, {
3830
+ "Content-Type": "application/json",
3831
+ "Content-Disposition": `attachment; filename="memorix-${effectiveProjectId.replace(/\//g, "-")}-export.json"`
3832
+ });
3833
+ res.end(JSON.stringify(exportData, null, 2));
3834
+ break;
3835
+ }
3674
3836
  sendError(res, "Not found", 404);
3837
+ }
3675
3838
  }
3676
3839
  } catch (err) {
3677
3840
  const message = err instanceof Error ? err.message : "Unknown error";