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 +184 -21
- package/dist/cli/index.js.map +1 -1
- package/dist/dashboard/static/app.js +93 -10
- package/dist/dashboard/static/style.css +150 -0
- package/dist/index.js +169 -21
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
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
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
|
2685
|
-
import { homedir as
|
|
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
|
|
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 =
|
|
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
|
-
|
|
2840
|
-
|
|
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 =
|
|
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:
|
|
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 =
|
|
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 =
|
|
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(
|
|
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";
|