memorix 0.6.0 → 0.6.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
@@ -1799,6 +1799,89 @@ 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
+ if (rule.paths && rule.paths.length > 0) {
1830
+ fm.inclusion = "fileMatch";
1831
+ fm.fileMatchPattern = rule.paths.length === 1 ? rule.paths[0] : rule.paths;
1832
+ } else if (rule.alwaysApply) {
1833
+ fm.inclusion = "always";
1834
+ }
1835
+ const fileName = rule.id.replace(/^kiro:/, "").replace(/[^a-zA-Z0-9-_]/g, "-") || `rule-${i}`;
1836
+ const body = Object.keys(fm).length > 0 ? matter7.stringify(rule.content, fm) : rule.content;
1837
+ return {
1838
+ filePath: `.kiro/steering/${fileName}.md`,
1839
+ content: body
1840
+ };
1841
+ });
1842
+ }
1843
+ parseSteeringRule(filePath, content) {
1844
+ const { data, content: body } = matter7(content);
1845
+ const trimmed = body.trim();
1846
+ if (!trimmed) return [];
1847
+ const inclusion = data.inclusion ?? "always";
1848
+ const alwaysApply = inclusion === "always" || inclusion === "auto";
1849
+ let paths;
1850
+ if (inclusion === "fileMatch" && data.fileMatchPattern) {
1851
+ paths = Array.isArray(data.fileMatchPattern) ? data.fileMatchPattern : [data.fileMatchPattern];
1852
+ }
1853
+ let scope = "project";
1854
+ if (alwaysApply) scope = "global";
1855
+ else if (paths && paths.length > 0) scope = "path-specific";
1856
+ return [{
1857
+ id: generateRuleId("kiro", filePath),
1858
+ content: trimmed,
1859
+ description: data.description,
1860
+ source: "kiro",
1861
+ scope,
1862
+ paths,
1863
+ alwaysApply,
1864
+ priority: alwaysApply ? 10 : 5,
1865
+ hash: hashContent(trimmed)
1866
+ }];
1867
+ }
1868
+ parseAgentsMd(filePath, content) {
1869
+ const trimmed = content.trim();
1870
+ if (!trimmed) return [];
1871
+ return [{
1872
+ id: generateRuleId("kiro", filePath),
1873
+ content: trimmed,
1874
+ source: "kiro",
1875
+ scope: "project",
1876
+ alwaysApply: true,
1877
+ priority: 10,
1878
+ hash: hashContent(trimmed)
1879
+ }];
1880
+ }
1881
+ };
1882
+ }
1883
+ });
1884
+
1802
1885
  // src/rules/syncer.ts
1803
1886
  var syncer_exports = {};
1804
1887
  __export(syncer_exports, {
@@ -1817,6 +1900,7 @@ var init_syncer = __esm({
1817
1900
  init_windsurf();
1818
1901
  init_antigravity();
1819
1902
  init_copilot();
1903
+ init_kiro();
1820
1904
  RulesSyncer = class {
1821
1905
  projectRoot;
1822
1906
  adapters;
@@ -1829,7 +1913,8 @@ var init_syncer = __esm({
1829
1913
  new CodexAdapter(),
1830
1914
  new WindsurfAdapter(),
1831
1915
  new AntigravityAdapter(),
1832
- new CopilotAdapter()
1916
+ new CopilotAdapter(),
1917
+ new KiroAdapter()
1833
1918
  ];
1834
1919
  for (const a of all) {
1835
1920
  this.adapters.set(a.source, a);
@@ -2438,8 +2523,60 @@ var init_antigravity2 = __esm({
2438
2523
  }
2439
2524
  });
2440
2525
 
2526
+ // src/workspace/mcp-adapters/kiro.ts
2527
+ import { homedir as homedir7 } from "os";
2528
+ import { join as join7 } from "path";
2529
+ var KiroMCPAdapter;
2530
+ var init_kiro2 = __esm({
2531
+ "src/workspace/mcp-adapters/kiro.ts"() {
2532
+ "use strict";
2533
+ init_esm_shims();
2534
+ KiroMCPAdapter = class {
2535
+ source = "kiro";
2536
+ parse(content) {
2537
+ try {
2538
+ const config = JSON.parse(content);
2539
+ const servers = config.mcpServers ?? {};
2540
+ return Object.entries(servers).map(([name, entry]) => ({
2541
+ name,
2542
+ command: entry.command ?? "",
2543
+ args: entry.args ?? [],
2544
+ ...entry.env && Object.keys(entry.env).length > 0 ? { env: entry.env } : {},
2545
+ ...entry.url ? { url: entry.url } : {}
2546
+ }));
2547
+ } catch {
2548
+ return [];
2549
+ }
2550
+ }
2551
+ generate(servers) {
2552
+ const mcpServers = {};
2553
+ for (const s of servers) {
2554
+ const entry = {};
2555
+ if (s.url) {
2556
+ entry.url = s.url;
2557
+ } else {
2558
+ entry.command = s.command;
2559
+ entry.args = s.args;
2560
+ }
2561
+ if (s.env && Object.keys(s.env).length > 0) {
2562
+ entry.env = s.env;
2563
+ }
2564
+ mcpServers[s.name] = entry;
2565
+ }
2566
+ return JSON.stringify({ mcpServers }, null, 2);
2567
+ }
2568
+ getConfigPath(projectRoot) {
2569
+ if (projectRoot) {
2570
+ return join7(projectRoot, ".kiro", "settings", "mcp.json");
2571
+ }
2572
+ return join7(homedir7(), ".kiro", "settings", "mcp.json");
2573
+ }
2574
+ };
2575
+ }
2576
+ });
2577
+
2441
2578
  // src/workspace/workflow-sync.ts
2442
- import matter7 from "gray-matter";
2579
+ import matter8 from "gray-matter";
2443
2580
  var WorkflowSyncer;
2444
2581
  var init_workflow_sync = __esm({
2445
2582
  "src/workspace/workflow-sync.ts"() {
@@ -2454,7 +2591,7 @@ var init_workflow_sync = __esm({
2454
2591
  let description = "";
2455
2592
  let content = raw;
2456
2593
  try {
2457
- const parsed = matter7(raw);
2594
+ const parsed = matter8(raw);
2458
2595
  description = parsed.data?.description ?? "";
2459
2596
  content = parsed.content.trim();
2460
2597
  } catch {
@@ -2476,7 +2613,7 @@ var init_workflow_sync = __esm({
2476
2613
  if (wf.description) {
2477
2614
  fm.description = wf.description;
2478
2615
  }
2479
- const content = matter7.stringify(wf.content, fm);
2616
+ const content = matter8.stringify(wf.content, fm);
2480
2617
  return {
2481
2618
  filePath: `.agents/skills/${safeName}/SKILL.md`,
2482
2619
  content
@@ -2493,7 +2630,7 @@ var init_workflow_sync = __esm({
2493
2630
  }
2494
2631
  fm.globs = "";
2495
2632
  fm.alwaysApply = "false";
2496
- const content = matter7.stringify(wf.content, fm);
2633
+ const content = matter8.stringify(wf.content, fm);
2497
2634
  return {
2498
2635
  filePath: `.cursor/rules/${safeName}.mdc`,
2499
2636
  content
@@ -2681,8 +2818,8 @@ var init_applier = __esm({
2681
2818
 
2682
2819
  // src/workspace/engine.ts
2683
2820
  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";
2821
+ import { join as join9 } from "path";
2822
+ import { homedir as homedir8 } from "os";
2686
2823
  var WorkspaceSyncEngine;
2687
2824
  var init_engine2 = __esm({
2688
2825
  "src/workspace/engine.ts"() {
@@ -2694,6 +2831,7 @@ var init_engine2 = __esm({
2694
2831
  init_claude_code2();
2695
2832
  init_copilot2();
2696
2833
  init_antigravity2();
2834
+ init_kiro2();
2697
2835
  init_workflow_sync();
2698
2836
  init_syncer();
2699
2837
  init_sanitizer();
@@ -2707,7 +2845,8 @@ var init_engine2 = __esm({
2707
2845
  ["codex", new CodexMCPAdapter()],
2708
2846
  ["claude-code", new ClaudeCodeMCPAdapter()],
2709
2847
  ["copilot", new CopilotMCPAdapter()],
2710
- ["antigravity", new AntigravityMCPAdapter()]
2848
+ ["antigravity", new AntigravityMCPAdapter()],
2849
+ ["kiro", new KiroMCPAdapter()]
2711
2850
  ]);
2712
2851
  this.workflowSyncer = new WorkflowSyncer();
2713
2852
  this.rulesSyncer = new RulesSyncer(projectRoot);
@@ -2725,7 +2864,8 @@ var init_engine2 = __esm({
2725
2864
  codex: [],
2726
2865
  "claude-code": [],
2727
2866
  copilot: [],
2728
- antigravity: []
2867
+ antigravity: [],
2868
+ kiro: []
2729
2869
  };
2730
2870
  for (const [target, adapter] of this.adapters) {
2731
2871
  const configPath = adapter.getConfigPath(this.projectRoot);
@@ -2817,13 +2957,14 @@ var init_engine2 = __esm({
2817
2957
  windsurf: [".windsurf/skills"],
2818
2958
  "claude-code": [".claude/skills"],
2819
2959
  copilot: [".github/skills", ".copilot/skills"],
2820
- antigravity: [".agent/skills", ".gemini/skills", ".gemini/antigravity/skills"]
2960
+ antigravity: [".agent/skills", ".gemini/skills", ".gemini/antigravity/skills"],
2961
+ kiro: [".kiro/skills"]
2821
2962
  };
2822
2963
  /** Get the target skills directory for an agent (null if agent has no skills support) */
2823
2964
  getTargetSkillsDir(target) {
2824
2965
  const dirs = _WorkspaceSyncEngine.SKILLS_DIRS[target];
2825
2966
  if (!dirs || dirs.length === 0) return null;
2826
- return join8(this.projectRoot, dirs[0]);
2967
+ return join9(this.projectRoot, dirs[0]);
2827
2968
  }
2828
2969
  /**
2829
2970
  * Scan all agent skills directories and collect unique skills.
@@ -2832,12 +2973,12 @@ var init_engine2 = __esm({
2832
2973
  const skills = [];
2833
2974
  const conflicts = [];
2834
2975
  const seen = /* @__PURE__ */ new Map();
2835
- const home = homedir7();
2976
+ const home = homedir8();
2836
2977
  for (const [agent, dirs] of Object.entries(_WorkspaceSyncEngine.SKILLS_DIRS)) {
2837
2978
  for (const dir of dirs) {
2838
2979
  const paths = [
2839
- join8(this.projectRoot, dir),
2840
- join8(home, dir)
2980
+ join9(this.projectRoot, dir),
2981
+ join9(home, dir)
2841
2982
  ];
2842
2983
  for (const skillsRoot of paths) {
2843
2984
  if (!existsSync4(skillsRoot)) continue;
@@ -2845,7 +2986,7 @@ var init_engine2 = __esm({
2845
2986
  const entries = readdirSync(skillsRoot, { withFileTypes: true });
2846
2987
  for (const entry of entries) {
2847
2988
  if (!entry.isDirectory()) continue;
2848
- const skillMd = join8(skillsRoot, entry.name, "SKILL.md");
2989
+ const skillMd = join9(skillsRoot, entry.name, "SKILL.md");
2849
2990
  if (!existsSync4(skillMd)) continue;
2850
2991
  let description = "";
2851
2992
  try {
@@ -2857,7 +2998,7 @@ var init_engine2 = __esm({
2857
2998
  const newEntry = {
2858
2999
  name: entry.name,
2859
3000
  description,
2860
- sourcePath: join8(skillsRoot, entry.name),
3001
+ sourcePath: join9(skillsRoot, entry.name),
2861
3002
  sourceAgent: agent
2862
3003
  };
2863
3004
  const existing = seen.get(entry.name);
@@ -2894,7 +3035,7 @@ var init_engine2 = __esm({
2894
3035
  }
2895
3036
  for (const skill of skills) {
2896
3037
  if (skill.sourceAgent === target) continue;
2897
- const dest = join8(targetDir, skill.name);
3038
+ const dest = join9(targetDir, skill.name);
2898
3039
  if (existsSync4(dest)) {
2899
3040
  skipped.push(`${skill.name} (already exists in ${target})`);
2900
3041
  continue;
@@ -2910,13 +3051,13 @@ var init_engine2 = __esm({
2910
3051
  }
2911
3052
  scanWorkflows() {
2912
3053
  const workflows = [];
2913
- const wfDir = join8(this.projectRoot, ".windsurf", "workflows");
3054
+ const wfDir = join9(this.projectRoot, ".windsurf", "workflows");
2914
3055
  if (!existsSync4(wfDir)) return workflows;
2915
3056
  try {
2916
3057
  const files = readdirSync(wfDir).filter((f) => f.endsWith(".md"));
2917
3058
  for (const file of files) {
2918
3059
  try {
2919
- const content = readFileSync2(join8(wfDir, file), "utf-8");
3060
+ const content = readFileSync2(join9(wfDir, file), "utf-8");
2920
3061
  workflows.push(this.workflowSyncer.parseWindsurfWorkflow(file, content));
2921
3062
  } catch {
2922
3063
  }
@@ -3004,7 +3145,8 @@ var init_engine2 = __esm({
3004
3145
  codex: "codex",
3005
3146
  windsurf: "windsurf",
3006
3147
  copilot: "copilot",
3007
- antigravity: "antigravity"
3148
+ antigravity: "antigravity",
3149
+ kiro: "kiro"
3008
3150
  };
3009
3151
  return map[target] ?? null;
3010
3152
  }
@@ -3670,8 +3812,42 @@ async function handleApi(req, res, dataDir, projectId, projectName, baseDir) {
3670
3812
  });
3671
3813
  break;
3672
3814
  }
3673
- default:
3815
+ default: {
3816
+ const deleteMatch = apiPath.match(/^\/observations\/(\d+)$/);
3817
+ if (deleteMatch && req.method === "DELETE") {
3818
+ const obsId = parseInt(deleteMatch[1], 10);
3819
+ const allObs = await loadObservationsJson(effectiveDataDir);
3820
+ const idx = allObs.findIndex((o) => o.id === obsId);
3821
+ if (idx === -1) {
3822
+ sendError(res, "Observation not found", 404);
3823
+ } else {
3824
+ allObs.splice(idx, 1);
3825
+ await saveObservationsJson(effectiveDataDir, allObs);
3826
+ sendJson(res, { ok: true, deleted: obsId });
3827
+ }
3828
+ break;
3829
+ }
3830
+ if (apiPath === "/export") {
3831
+ const graph = await loadGraphJsonl(effectiveDataDir);
3832
+ const allObs = await loadObservationsJson(effectiveDataDir);
3833
+ const observations2 = filterByProject(allObs, effectiveProjectId);
3834
+ const nextId2 = await loadIdCounter(effectiveDataDir);
3835
+ const exportData = {
3836
+ project: { id: effectiveProjectId, name: effectiveProjectName },
3837
+ exportedAt: (/* @__PURE__ */ new Date()).toISOString(),
3838
+ graph,
3839
+ observations: observations2,
3840
+ nextId: nextId2
3841
+ };
3842
+ res.writeHead(200, {
3843
+ "Content-Type": "application/json",
3844
+ "Content-Disposition": `attachment; filename="memorix-${effectiveProjectId.replace(/\//g, "-")}-export.json"`
3845
+ });
3846
+ res.end(JSON.stringify(exportData, null, 2));
3847
+ break;
3848
+ }
3674
3849
  sendError(res, "Not found", 404);
3850
+ }
3675
3851
  }
3676
3852
  } catch (err) {
3677
3853
  const message = err instanceof Error ? err.message : "Unknown error";