memorix 0.3.9 → 0.4.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
@@ -1520,6 +1520,186 @@ var init_windsurf = __esm({
1520
1520
  }
1521
1521
  });
1522
1522
 
1523
+ // src/rules/adapters/antigravity.ts
1524
+ import matter5 from "gray-matter";
1525
+ var AntigravityAdapter;
1526
+ var init_antigravity = __esm({
1527
+ "src/rules/adapters/antigravity.ts"() {
1528
+ "use strict";
1529
+ init_esm_shims();
1530
+ init_utils();
1531
+ AntigravityAdapter = class {
1532
+ source = "antigravity";
1533
+ filePatterns = [
1534
+ "GEMINI.md",
1535
+ ".agent/rules/*.md",
1536
+ ".agent/skills/*/SKILL.md"
1537
+ ];
1538
+ parse(filePath, content) {
1539
+ if (filePath.includes("SKILL.md")) {
1540
+ return this.parseSkillMd(filePath, content);
1541
+ }
1542
+ if (filePath.includes(".agent/rules/")) {
1543
+ return this.parseAgentRule(filePath, content);
1544
+ }
1545
+ if (filePath === "GEMINI.md" || filePath.endsWith("/GEMINI.md")) {
1546
+ return this.parseGeminiMd(filePath, content);
1547
+ }
1548
+ return [];
1549
+ }
1550
+ generate(rules) {
1551
+ const projectRules = rules.filter((r) => r.scope !== "path-specific");
1552
+ const pathRules = rules.filter((r) => r.scope === "path-specific");
1553
+ const files = [];
1554
+ for (const rule of [...projectRules, ...pathRules]) {
1555
+ const fm = {};
1556
+ if (rule.description) fm.description = rule.description;
1557
+ const fileName = rule.id.replace(/^antigravity:/, "").replace(/[^a-zA-Z0-9-_]/g, "-") || "rule";
1558
+ const body = Object.keys(fm).length > 0 ? matter5.stringify(rule.content, fm) : rule.content;
1559
+ files.push({
1560
+ filePath: `.agent/rules/${fileName}.md`,
1561
+ content: body
1562
+ });
1563
+ }
1564
+ return files;
1565
+ }
1566
+ parseGeminiMd(filePath, content) {
1567
+ const trimmed = content.trim();
1568
+ if (!trimmed) return [];
1569
+ return [{
1570
+ id: generateRuleId("antigravity", filePath),
1571
+ content: trimmed,
1572
+ source: "antigravity",
1573
+ scope: "global",
1574
+ priority: 10,
1575
+ hash: hashContent(trimmed)
1576
+ }];
1577
+ }
1578
+ parseAgentRule(filePath, content) {
1579
+ const { data, content: body } = matter5(content);
1580
+ const trimmed = body.trim();
1581
+ if (!trimmed) return [];
1582
+ return [{
1583
+ id: generateRuleId("antigravity", filePath),
1584
+ content: trimmed,
1585
+ description: data.description,
1586
+ source: "antigravity",
1587
+ scope: "project",
1588
+ priority: 5,
1589
+ hash: hashContent(trimmed)
1590
+ }];
1591
+ }
1592
+ parseSkillMd(filePath, content) {
1593
+ const { data, content: body } = matter5(content);
1594
+ const trimmed = body.trim();
1595
+ if (!trimmed) return [];
1596
+ return [{
1597
+ id: generateRuleId("antigravity", filePath),
1598
+ content: trimmed,
1599
+ description: data.description || void 0,
1600
+ source: "antigravity",
1601
+ scope: "project",
1602
+ priority: 5,
1603
+ hash: hashContent(trimmed)
1604
+ }];
1605
+ }
1606
+ };
1607
+ }
1608
+ });
1609
+
1610
+ // src/rules/adapters/copilot.ts
1611
+ import matter6 from "gray-matter";
1612
+ var CopilotAdapter;
1613
+ var init_copilot = __esm({
1614
+ "src/rules/adapters/copilot.ts"() {
1615
+ "use strict";
1616
+ init_esm_shims();
1617
+ init_utils();
1618
+ CopilotAdapter = class {
1619
+ source = "copilot";
1620
+ filePatterns = [
1621
+ ".github/copilot-instructions.md",
1622
+ ".github/instructions/*.instructions.md"
1623
+ ];
1624
+ parse(filePath, content) {
1625
+ if (filePath.includes(".instructions.md") && filePath.includes(".github/instructions")) {
1626
+ return this.parsePathSpecific(filePath, content);
1627
+ }
1628
+ if (filePath.includes("copilot-instructions.md")) {
1629
+ return this.parseRepoWide(filePath, content);
1630
+ }
1631
+ return [];
1632
+ }
1633
+ generate(rules) {
1634
+ if (rules.length === 1 && (!rules[0].paths || rules[0].paths.length === 0)) {
1635
+ return [{
1636
+ filePath: ".github/copilot-instructions.md",
1637
+ content: rules[0].content
1638
+ }];
1639
+ }
1640
+ return rules.map((rule, i) => {
1641
+ const fm = {};
1642
+ if (rule.paths && rule.paths.length > 0) {
1643
+ fm.applyTo = rule.paths.join(",");
1644
+ }
1645
+ if (rule.description) {
1646
+ fm.description = rule.description;
1647
+ }
1648
+ const fileName = rule.id.replace(/^copilot:/, "").replace(/[^a-zA-Z0-9-_]/g, "-") || `instruction-${i}`;
1649
+ const body = Object.keys(fm).length > 0 ? matter6.stringify(rule.content, fm) : rule.content;
1650
+ return {
1651
+ filePath: `.github/instructions/${fileName}.instructions.md`,
1652
+ content: body
1653
+ };
1654
+ });
1655
+ }
1656
+ /**
1657
+ * Parse repository-wide .github/copilot-instructions.md
1658
+ * This is plain Markdown with no frontmatter.
1659
+ */
1660
+ parseRepoWide(filePath, content) {
1661
+ const trimmed = content.trim();
1662
+ if (!trimmed) return [];
1663
+ return [{
1664
+ id: generateRuleId("copilot", filePath),
1665
+ content: trimmed,
1666
+ description: "Repository-wide Copilot instructions",
1667
+ source: "copilot",
1668
+ scope: "project",
1669
+ priority: 3,
1670
+ hash: hashContent(trimmed)
1671
+ }];
1672
+ }
1673
+ /**
1674
+ * Parse path-specific .github/instructions/*.instructions.md
1675
+ * These have YAML frontmatter with `applyTo` glob pattern(s).
1676
+ */
1677
+ parsePathSpecific(filePath, content) {
1678
+ const { data, content: body } = matter6(content);
1679
+ const trimmed = body.trim();
1680
+ if (!trimmed) return [];
1681
+ const applyTo = data.applyTo;
1682
+ const hasApplyTo = !!applyTo;
1683
+ const rule = {
1684
+ id: generateRuleId("copilot", filePath),
1685
+ content: trimmed,
1686
+ source: "copilot",
1687
+ scope: hasApplyTo ? "path-specific" : "project",
1688
+ priority: 5,
1689
+ hash: hashContent(trimmed)
1690
+ };
1691
+ if (hasApplyTo) {
1692
+ rule.paths = applyTo.split(",").map((p3) => p3.trim());
1693
+ }
1694
+ if (data.description) {
1695
+ rule.description = data.description;
1696
+ }
1697
+ return [rule];
1698
+ }
1699
+ };
1700
+ }
1701
+ });
1702
+
1523
1703
  // src/rules/syncer.ts
1524
1704
  var syncer_exports = {};
1525
1705
  __export(syncer_exports, {
@@ -1536,6 +1716,8 @@ var init_syncer = __esm({
1536
1716
  init_claude_code();
1537
1717
  init_codex();
1538
1718
  init_windsurf();
1719
+ init_antigravity();
1720
+ init_copilot();
1539
1721
  RulesSyncer = class {
1540
1722
  projectRoot;
1541
1723
  adapters;
@@ -1546,7 +1728,9 @@ var init_syncer = __esm({
1546
1728
  new CursorAdapter(),
1547
1729
  new ClaudeCodeAdapter(),
1548
1730
  new CodexAdapter(),
1549
- new WindsurfAdapter()
1731
+ new WindsurfAdapter(),
1732
+ new AntigravityAdapter(),
1733
+ new CopilotAdapter()
1550
1734
  ];
1551
1735
  for (const a of all) {
1552
1736
  this.adapters.set(a.source, a);
@@ -2012,7 +2196,7 @@ import { homedir as homedir5 } from "os";
2012
2196
  import { join as join5 } from "path";
2013
2197
  import { existsSync as existsSync2, readFileSync } from "fs";
2014
2198
  var CopilotMCPAdapter;
2015
- var init_copilot = __esm({
2199
+ var init_copilot2 = __esm({
2016
2200
  "src/workspace/mcp-adapters/copilot.ts"() {
2017
2201
  "use strict";
2018
2202
  init_esm_shims();
@@ -2085,8 +2269,78 @@ var init_copilot = __esm({
2085
2269
  }
2086
2270
  });
2087
2271
 
2272
+ // src/workspace/mcp-adapters/antigravity.ts
2273
+ import { homedir as homedir6 } from "os";
2274
+ import { join as join6 } from "path";
2275
+ var AntigravityMCPAdapter;
2276
+ var init_antigravity2 = __esm({
2277
+ "src/workspace/mcp-adapters/antigravity.ts"() {
2278
+ "use strict";
2279
+ init_esm_shims();
2280
+ AntigravityMCPAdapter = class {
2281
+ source = "antigravity";
2282
+ parse(content) {
2283
+ try {
2284
+ const config = JSON.parse(content);
2285
+ const servers = config.mcpServers ?? config.mcp_servers ?? {};
2286
+ return Object.entries(servers).map(([name, entry]) => {
2287
+ const result = {
2288
+ name,
2289
+ command: entry.command ?? "",
2290
+ args: entry.args ?? []
2291
+ };
2292
+ if (entry.serverUrl) {
2293
+ result.url = entry.serverUrl;
2294
+ } else if (entry.url) {
2295
+ result.url = entry.url;
2296
+ }
2297
+ if (entry.headers && typeof entry.headers === "object" && Object.keys(entry.headers).length > 0) {
2298
+ result.headers = entry.headers;
2299
+ }
2300
+ if (entry.env && typeof entry.env === "object" && Object.keys(entry.env).length > 0) {
2301
+ result.env = entry.env;
2302
+ }
2303
+ if (entry.disabled === true) {
2304
+ result.disabled = true;
2305
+ }
2306
+ return result;
2307
+ });
2308
+ } catch {
2309
+ return [];
2310
+ }
2311
+ }
2312
+ generate(servers) {
2313
+ const mcpServers = {};
2314
+ for (const s of servers) {
2315
+ const entry = {};
2316
+ if (s.url) {
2317
+ entry.url = s.url;
2318
+ if (s.headers && Object.keys(s.headers).length > 0) {
2319
+ entry.headers = s.headers;
2320
+ }
2321
+ } else {
2322
+ entry.command = s.command;
2323
+ entry.args = s.args;
2324
+ }
2325
+ if (s.env && Object.keys(s.env).length > 0) {
2326
+ entry.env = s.env;
2327
+ }
2328
+ if (s.disabled === true) {
2329
+ entry.disabled = true;
2330
+ }
2331
+ mcpServers[s.name] = entry;
2332
+ }
2333
+ return JSON.stringify({ mcpServers }, null, 2);
2334
+ }
2335
+ getConfigPath(_projectRoot) {
2336
+ return join6(homedir6(), ".gemini", "antigravity", "mcp_config.json");
2337
+ }
2338
+ };
2339
+ }
2340
+ });
2341
+
2088
2342
  // src/workspace/workflow-sync.ts
2089
- import matter5 from "gray-matter";
2343
+ import matter7 from "gray-matter";
2090
2344
  var WorkflowSyncer;
2091
2345
  var init_workflow_sync = __esm({
2092
2346
  "src/workspace/workflow-sync.ts"() {
@@ -2101,7 +2355,7 @@ var init_workflow_sync = __esm({
2101
2355
  let description = "";
2102
2356
  let content = raw;
2103
2357
  try {
2104
- const parsed = matter5(raw);
2358
+ const parsed = matter7(raw);
2105
2359
  description = parsed.data?.description ?? "";
2106
2360
  content = parsed.content.trim();
2107
2361
  } catch {
@@ -2123,7 +2377,7 @@ var init_workflow_sync = __esm({
2123
2377
  if (wf.description) {
2124
2378
  fm.description = wf.description;
2125
2379
  }
2126
- const content = matter5.stringify(wf.content, fm);
2380
+ const content = matter7.stringify(wf.content, fm);
2127
2381
  return {
2128
2382
  filePath: `.agents/skills/${safeName}/SKILL.md`,
2129
2383
  content
@@ -2140,7 +2394,7 @@ var init_workflow_sync = __esm({
2140
2394
  }
2141
2395
  fm.globs = "";
2142
2396
  fm.alwaysApply = "false";
2143
- const content = matter5.stringify(wf.content, fm);
2397
+ const content = matter7.stringify(wf.content, fm);
2144
2398
  return {
2145
2399
  filePath: `.cursor/rules/${safeName}.mdc`,
2146
2400
  content
@@ -2328,8 +2582,8 @@ var init_applier = __esm({
2328
2582
 
2329
2583
  // src/workspace/engine.ts
2330
2584
  import { readFileSync as readFileSync2, readdirSync, existsSync as existsSync4, cpSync, mkdirSync as mkdirSync2 } from "fs";
2331
- import { join as join7 } from "path";
2332
- import { homedir as homedir6 } from "os";
2585
+ import { join as join8 } from "path";
2586
+ import { homedir as homedir7 } from "os";
2333
2587
  var WorkspaceSyncEngine;
2334
2588
  var init_engine2 = __esm({
2335
2589
  "src/workspace/engine.ts"() {
@@ -2339,7 +2593,8 @@ var init_engine2 = __esm({
2339
2593
  init_cursor2();
2340
2594
  init_codex2();
2341
2595
  init_claude_code2();
2342
- init_copilot();
2596
+ init_copilot2();
2597
+ init_antigravity2();
2343
2598
  init_workflow_sync();
2344
2599
  init_syncer();
2345
2600
  init_sanitizer();
@@ -2352,7 +2607,8 @@ var init_engine2 = __esm({
2352
2607
  ["cursor", new CursorMCPAdapter()],
2353
2608
  ["codex", new CodexMCPAdapter()],
2354
2609
  ["claude-code", new ClaudeCodeMCPAdapter()],
2355
- ["copilot", new CopilotMCPAdapter()]
2610
+ ["copilot", new CopilotMCPAdapter()],
2611
+ ["antigravity", new AntigravityMCPAdapter()]
2356
2612
  ]);
2357
2613
  this.workflowSyncer = new WorkflowSyncer();
2358
2614
  this.rulesSyncer = new RulesSyncer(projectRoot);
@@ -2369,7 +2625,8 @@ var init_engine2 = __esm({
2369
2625
  cursor: [],
2370
2626
  codex: [],
2371
2627
  "claude-code": [],
2372
- copilot: []
2628
+ copilot: [],
2629
+ antigravity: []
2373
2630
  };
2374
2631
  for (const [target, adapter] of this.adapters) {
2375
2632
  const configPath = adapter.getConfigPath(this.projectRoot);
@@ -2460,13 +2717,14 @@ var init_engine2 = __esm({
2460
2717
  cursor: [".cursor/skills", ".cursor/skills-cursor"],
2461
2718
  windsurf: [".windsurf/skills"],
2462
2719
  "claude-code": [".claude/skills"],
2463
- copilot: []
2720
+ copilot: [".github/skills", ".copilot/skills"],
2721
+ antigravity: [".agent/skills", ".gemini/skills", ".gemini/antigravity/skills"]
2464
2722
  };
2465
2723
  /** Get the target skills directory for an agent (null if agent has no skills support) */
2466
2724
  getTargetSkillsDir(target) {
2467
2725
  const dirs = _WorkspaceSyncEngine.SKILLS_DIRS[target];
2468
2726
  if (!dirs || dirs.length === 0) return null;
2469
- return join7(this.projectRoot, dirs[0]);
2727
+ return join8(this.projectRoot, dirs[0]);
2470
2728
  }
2471
2729
  /**
2472
2730
  * Scan all agent skills directories and collect unique skills.
@@ -2475,12 +2733,12 @@ var init_engine2 = __esm({
2475
2733
  const skills = [];
2476
2734
  const conflicts = [];
2477
2735
  const seen = /* @__PURE__ */ new Map();
2478
- const home = homedir6();
2736
+ const home = homedir7();
2479
2737
  for (const [agent, dirs] of Object.entries(_WorkspaceSyncEngine.SKILLS_DIRS)) {
2480
2738
  for (const dir of dirs) {
2481
2739
  const paths = [
2482
- join7(this.projectRoot, dir),
2483
- join7(home, dir)
2740
+ join8(this.projectRoot, dir),
2741
+ join8(home, dir)
2484
2742
  ];
2485
2743
  for (const skillsRoot of paths) {
2486
2744
  if (!existsSync4(skillsRoot)) continue;
@@ -2488,7 +2746,7 @@ var init_engine2 = __esm({
2488
2746
  const entries = readdirSync(skillsRoot, { withFileTypes: true });
2489
2747
  for (const entry of entries) {
2490
2748
  if (!entry.isDirectory()) continue;
2491
- const skillMd = join7(skillsRoot, entry.name, "SKILL.md");
2749
+ const skillMd = join8(skillsRoot, entry.name, "SKILL.md");
2492
2750
  if (!existsSync4(skillMd)) continue;
2493
2751
  let description = "";
2494
2752
  try {
@@ -2500,7 +2758,7 @@ var init_engine2 = __esm({
2500
2758
  const newEntry = {
2501
2759
  name: entry.name,
2502
2760
  description,
2503
- sourcePath: join7(skillsRoot, entry.name),
2761
+ sourcePath: join8(skillsRoot, entry.name),
2504
2762
  sourceAgent: agent
2505
2763
  };
2506
2764
  const existing = seen.get(entry.name);
@@ -2537,7 +2795,7 @@ var init_engine2 = __esm({
2537
2795
  }
2538
2796
  for (const skill of skills) {
2539
2797
  if (skill.sourceAgent === target) continue;
2540
- const dest = join7(targetDir, skill.name);
2798
+ const dest = join8(targetDir, skill.name);
2541
2799
  if (existsSync4(dest)) {
2542
2800
  skipped.push(`${skill.name} (already exists in ${target})`);
2543
2801
  continue;
@@ -2553,13 +2811,13 @@ var init_engine2 = __esm({
2553
2811
  }
2554
2812
  scanWorkflows() {
2555
2813
  const workflows = [];
2556
- const wfDir = join7(this.projectRoot, ".windsurf", "workflows");
2814
+ const wfDir = join8(this.projectRoot, ".windsurf", "workflows");
2557
2815
  if (!existsSync4(wfDir)) return workflows;
2558
2816
  try {
2559
2817
  const files = readdirSync(wfDir).filter((f) => f.endsWith(".md"));
2560
2818
  for (const file of files) {
2561
2819
  try {
2562
- const content = readFileSync2(join7(wfDir, file), "utf-8");
2820
+ const content = readFileSync2(join8(wfDir, file), "utf-8");
2563
2821
  workflows.push(this.workflowSyncer.parseWindsurfWorkflow(file, content));
2564
2822
  } catch {
2565
2823
  }
@@ -2646,7 +2904,8 @@ var init_engine2 = __esm({
2646
2904
  "claude-code": "claude-code",
2647
2905
  codex: "codex",
2648
2906
  windsurf: "windsurf",
2649
- copilot: "windsurf"
2907
+ copilot: "copilot",
2908
+ antigravity: "antigravity"
2650
2909
  };
2651
2910
  return map[target] ?? null;
2652
2911
  }
@@ -3583,12 +3842,12 @@ Entity: ${entityName} | Type: ${type} | Project: ${project.id}${enrichment}`
3583
3842
  };
3584
3843
  }
3585
3844
  );
3586
- const RULE_SOURCES = ["cursor", "claude-code", "codex", "windsurf"];
3845
+ const RULE_SOURCES = ["cursor", "claude-code", "codex", "windsurf", "antigravity", "copilot"];
3587
3846
  server.registerTool(
3588
3847
  "memorix_rules_sync",
3589
3848
  {
3590
3849
  title: "Rules Sync",
3591
- description: "Scan project for agent rule files (Cursor, Claude Code, Codex, Windsurf), deduplicate, detect conflicts, and optionally generate rules for a target agent format. Without target: returns sync status report. With target: generates converted rule files.",
3850
+ description: "Scan project for agent rule files (Cursor, Claude Code, Codex, Windsurf, Antigravity, Copilot), deduplicate, detect conflicts, and optionally generate rules for a target agent format. Without target: returns sync status report. With target: generates converted rule files.",
3592
3851
  inputSchema: {
3593
3852
  action: z.enum(["status", "generate"]).describe('Action: "status" for report, "generate" to produce target files'),
3594
3853
  target: z.enum(RULE_SOURCES).optional().describe("Target agent format for generation (required when action=generate)")
@@ -3638,7 +3897,7 @@ Entity: ${entityName} | Type: ${type} | Project: ${project.id}${enrichment}`
3638
3897
  };
3639
3898
  }
3640
3899
  );
3641
- const AGENT_TARGETS = ["windsurf", "cursor", "claude-code", "codex", "copilot"];
3900
+ const AGENT_TARGETS = ["windsurf", "cursor", "claude-code", "codex", "copilot", "antigravity"];
3642
3901
  server.registerTool(
3643
3902
  "memorix_workspace_sync",
3644
3903
  {
@@ -3882,7 +4141,8 @@ var init_sync = __esm({
3882
4141
  cursor: "Cursor (.cursor/rules/*.mdc, .cursorrules)",
3883
4142
  "claude-code": "Claude Code (CLAUDE.md, .claude/rules/*.md)",
3884
4143
  codex: "Codex (SKILL.md, AGENTS.md)",
3885
- windsurf: "Windsurf (.windsurfrules, .windsurf/rules/*.md)"
4144
+ windsurf: "Windsurf (.windsurfrules, .windsurf/rules/*.md)",
4145
+ antigravity: "Antigravity (.agent/rules/*.md, GEMINI.md)"
3886
4146
  };
3887
4147
  sync_default = defineCommand3({
3888
4148
  meta: {
@@ -3892,7 +4152,7 @@ var init_sync = __esm({
3892
4152
  args: {
3893
4153
  target: {
3894
4154
  type: "string",
3895
- description: "Target agent format (cursor, claude-code, codex, windsurf)",
4155
+ description: "Target agent format (cursor, claude-code, codex, windsurf, antigravity)",
3896
4156
  required: false
3897
4157
  },
3898
4158
  dry: {
@@ -3935,11 +4195,11 @@ var init_sync = __esm({
3935
4195
  }
3936
4196
  let target = args.target;
3937
4197
  if (!target) {
3938
- const available = ["cursor", "claude-code", "codex", "windsurf"].filter(
4198
+ const available = ["cursor", "claude-code", "codex", "windsurf", "antigravity"].filter(
3939
4199
  (t) => !sources.includes(t)
3940
4200
  );
3941
4201
  if (available.length === 0) {
3942
- available.push("cursor", "claude-code", "codex", "windsurf");
4202
+ available.push("cursor", "claude-code", "codex", "windsurf", "antigravity");
3943
4203
  }
3944
4204
  const selected = await p2.select({
3945
4205
  message: "Generate rules for which agent?",