kirograph 0.14.1 → 0.15.0

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.
Files changed (85) hide show
  1. package/README.md +128 -20
  2. package/dist/assets/logo.png +0 -0
  3. package/dist/bin/commands/help.js +3 -0
  4. package/dist/bin/commands/help.js.map +2 -2
  5. package/dist/bin/commands/uninit.js +10 -13
  6. package/dist/bin/commands/uninit.js.map +2 -2
  7. package/dist/bin/installer/config-prompt.js +37 -23
  8. package/dist/bin/installer/config-prompt.js.map +2 -2
  9. package/dist/bin/installer/hooks.js +20 -1
  10. package/dist/bin/installer/hooks.js.map +2 -2
  11. package/dist/bin/installer/index.js +9 -4
  12. package/dist/bin/installer/index.js.map +2 -2
  13. package/dist/bin/installer/prompts.js +37 -6
  14. package/dist/bin/installer/prompts.js.map +2 -2
  15. package/dist/bin/installer/steering.js +19 -0
  16. package/dist/bin/installer/steering.js.map +2 -2
  17. package/dist/bin/installer/targets/aider.js +72 -0
  18. package/dist/bin/installer/targets/aider.js.map +7 -0
  19. package/dist/bin/installer/targets/amp.js +91 -0
  20. package/dist/bin/installer/targets/amp.js.map +7 -0
  21. package/dist/bin/installer/targets/antigravity.js +109 -0
  22. package/dist/bin/installer/targets/antigravity.js.map +7 -0
  23. package/dist/bin/installer/targets/augment.js +81 -0
  24. package/dist/bin/installer/targets/augment.js.map +7 -0
  25. package/dist/bin/installer/targets/claude.js +1 -1
  26. package/dist/bin/installer/targets/claude.js.map +2 -2
  27. package/dist/bin/installer/targets/cline.js +91 -0
  28. package/dist/bin/installer/targets/cline.js.map +7 -0
  29. package/dist/bin/installer/targets/codex.js +1 -1
  30. package/dist/bin/installer/targets/codex.js.map +2 -2
  31. package/dist/bin/installer/targets/continue.js +107 -0
  32. package/dist/bin/installer/targets/continue.js.map +7 -0
  33. package/dist/bin/installer/targets/copilot.js +123 -0
  34. package/dist/bin/installer/targets/copilot.js.map +7 -0
  35. package/dist/bin/installer/targets/cursor.js +143 -0
  36. package/dist/bin/installer/targets/cursor.js.map +7 -0
  37. package/dist/bin/installer/targets/devin.js +148 -0
  38. package/dist/bin/installer/targets/devin.js.map +7 -0
  39. package/dist/bin/installer/targets/gemini-cli.js +126 -0
  40. package/dist/bin/installer/targets/gemini-cli.js.map +7 -0
  41. package/dist/bin/installer/targets/generic.js +120 -0
  42. package/dist/bin/installer/targets/generic.js.map +7 -0
  43. package/dist/bin/installer/targets/goose.js +72 -0
  44. package/dist/bin/installer/targets/goose.js.map +7 -0
  45. package/dist/bin/installer/targets/index.js.map +1 -1
  46. package/dist/bin/installer/targets/junie.js +105 -0
  47. package/dist/bin/installer/targets/junie.js.map +7 -0
  48. package/dist/bin/installer/targets/kilo.js +122 -0
  49. package/dist/bin/installer/targets/kilo.js.map +7 -0
  50. package/dist/bin/installer/targets/kiro.js +3 -3
  51. package/dist/bin/installer/targets/kiro.js.map +2 -2
  52. package/dist/bin/installer/targets/opencode.js +135 -0
  53. package/dist/bin/installer/targets/opencode.js.map +7 -0
  54. package/dist/bin/installer/targets/openhands.js +90 -0
  55. package/dist/bin/installer/targets/openhands.js.map +7 -0
  56. package/dist/bin/installer/targets/replit.js +72 -0
  57. package/dist/bin/installer/targets/replit.js.map +7 -0
  58. package/dist/bin/installer/targets/roo.js +96 -0
  59. package/dist/bin/installer/targets/roo.js.map +7 -0
  60. package/dist/bin/installer/targets/tabnine.js +82 -0
  61. package/dist/bin/installer/targets/tabnine.js.map +7 -0
  62. package/dist/bin/installer/targets/trae.js +84 -0
  63. package/dist/bin/installer/targets/trae.js.map +7 -0
  64. package/dist/bin/installer/targets/warp.js +97 -0
  65. package/dist/bin/installer/targets/warp.js.map +7 -0
  66. package/dist/bin/installer/targets/windsurf.js +141 -0
  67. package/dist/bin/installer/targets/windsurf.js.map +7 -0
  68. package/dist/bin/kirograph.js +3 -1
  69. package/dist/bin/kirograph.js.map +3 -3
  70. package/dist/compression/naive-cost.js +14 -0
  71. package/dist/compression/naive-cost.js.map +2 -2
  72. package/dist/compression/tracker.js +18 -4
  73. package/dist/compression/tracker.js.map +2 -2
  74. package/dist/compression/types.js.map +1 -1
  75. package/dist/config.js +33 -1
  76. package/dist/config.js.map +2 -2
  77. package/dist/db/database.js +17 -0
  78. package/dist/db/database.js.map +2 -2
  79. package/dist/index.js +3 -0
  80. package/dist/index.js.map +2 -2
  81. package/dist/mcp/tool-names.js +5 -1
  82. package/dist/mcp/tool-names.js.map +2 -2
  83. package/dist/mcp/tools.js +232 -3
  84. package/dist/mcp/tools.js.map +2 -2
  85. package/package.json +1 -1
package/dist/mcp/tools.js CHANGED
@@ -61,6 +61,19 @@ function writeSessionMarker(projectRoot) {
61
61
  } catch {
62
62
  }
63
63
  }
64
+ function formatAge(timestamp) {
65
+ const diff = Date.now() - timestamp;
66
+ const minutes = Math.floor(diff / 6e4);
67
+ if (minutes < 60) return `${minutes}m ago`;
68
+ const hours = Math.floor(minutes / 60);
69
+ if (hours < 24) return `${hours}h ago`;
70
+ const days = Math.floor(hours / 24);
71
+ if (days < 7) return `${days}d ago`;
72
+ const weeks = Math.floor(days / 7);
73
+ if (weeks < 5) return `${weeks}w ago`;
74
+ const months = Math.floor(days / 30);
75
+ return `${months}mo ago`;
76
+ }
64
77
  const tools = [
65
78
  {
66
79
  name: "kirograph_search",
@@ -343,6 +356,66 @@ const tools = [
343
356
  projectPath: { type: "string", description: "Project root path (optional)" }
344
357
  }
345
358
  }
359
+ },
360
+ // ── Memory tools (require enableMemory=true) ────────────────────────────────
361
+ {
362
+ name: "kirograph_mem_search",
363
+ description: "Search project memory for past decisions, errors, patterns, and context. Returns observations ranked by relevance.",
364
+ inputSchema: {
365
+ type: "object",
366
+ properties: {
367
+ query: { type: "string", description: "Natural language search query" },
368
+ kind: {
369
+ type: "string",
370
+ description: "Filter by observation kind",
371
+ enum: ["decision", "error", "pattern", "architecture", "summary", "note"]
372
+ },
373
+ limit: { type: "number", description: "Max results (default: 10)", default: 10 },
374
+ sessionId: { type: "string", description: "Filter to specific session" },
375
+ projectPath: { type: "string", description: "Project root path (optional)" }
376
+ },
377
+ required: ["query"]
378
+ }
379
+ },
380
+ {
381
+ name: "kirograph_mem_store",
382
+ description: "Store an observation in project memory. Content is automatically compressed (if caveman mode is on) and linked to relevant code symbols.",
383
+ inputSchema: {
384
+ type: "object",
385
+ properties: {
386
+ content: { type: "string", description: "Observation text" },
387
+ kind: {
388
+ type: "string",
389
+ description: "Observation kind",
390
+ enum: ["decision", "error", "pattern", "architecture", "summary", "note"],
391
+ default: "note"
392
+ },
393
+ projectPath: { type: "string", description: "Project root path (optional)" }
394
+ },
395
+ required: ["content"]
396
+ }
397
+ },
398
+ {
399
+ name: "kirograph_mem_timeline",
400
+ description: "List recent sessions and their observations chronologically.",
401
+ inputSchema: {
402
+ type: "object",
403
+ properties: {
404
+ limit: { type: "number", description: "Number of sessions to show (default: 5)", default: 5 },
405
+ sessionId: { type: "string", description: "Show observations for a specific session" },
406
+ projectPath: { type: "string", description: "Project root path (optional)" }
407
+ }
408
+ }
409
+ },
410
+ {
411
+ name: "kirograph_mem_status",
412
+ description: "Memory subsystem health: session count, observations, embedding coverage, storage size.",
413
+ inputSchema: {
414
+ type: "object",
415
+ properties: {
416
+ projectPath: { type: "string", description: "Project root path (optional)" }
417
+ }
418
+ }
346
419
  }
347
420
  ];
348
421
  class ToolHandler {
@@ -388,7 +461,11 @@ class ToolHandler {
388
461
  const naiveCost = estimateNaiveCost(toolName, outputTokens, args);
389
462
  if (naiveCost !== null && naiveCost > outputTokens) {
390
463
  const tracker = new import_tracker.TokenTracker(projectRoot);
391
- tracker.recordGraphSaving(toolName, outputTokens, naiveCost);
464
+ if (toolName.startsWith("kirograph_mem_")) {
465
+ tracker.recordMemorySaving(toolName, outputTokens, naiveCost);
466
+ } else {
467
+ tracker.recordGraphSaving(toolName, outputTokens, naiveCost);
468
+ }
392
469
  }
393
470
  } catch {
394
471
  }
@@ -455,7 +532,7 @@ class ToolHandler {
455
532
  ` Tokens with KiroGraph: ~${stats.totalCompressed.toLocaleString()}`,
456
533
  ` Saved: ${stats.totalSaved.toLocaleString()} tokens (${stats.savingsPercent}%)`
457
534
  ];
458
- if (stats.bySource.exec.count > 0 || stats.bySource.graph.count > 0) {
535
+ if (stats.bySource.exec.count > 0 || stats.bySource.graph.count > 0 || stats.bySource.memory.count > 0) {
459
536
  lines.push("", "By source:");
460
537
  if (stats.bySource.graph.count > 0) {
461
538
  lines.push(` Graph tools: ${stats.bySource.graph.count} calls, ~${stats.bySource.graph.saved.toLocaleString()} tokens saved (vs file reads/grep)`);
@@ -463,6 +540,9 @@ class ToolHandler {
463
540
  if (stats.bySource.exec.count > 0) {
464
541
  lines.push(` Compression: ${stats.bySource.exec.count} calls, ~${stats.bySource.exec.saved.toLocaleString()} tokens saved (vs raw output)`);
465
542
  }
543
+ if (stats.bySource.memory.count > 0) {
544
+ lines.push(` Memory: ${stats.bySource.memory.count} calls, ~${stats.bySource.memory.saved.toLocaleString()} tokens saved (vs re-discovering context)`);
545
+ }
466
546
  }
467
547
  if (Object.keys(stats.byFamily).length > 0) {
468
548
  lines.push("", "Top families:");
@@ -520,6 +600,36 @@ class ToolHandler {
520
600
  }
521
601
  }
522
602
  }
603
+ try {
604
+ const { loadConfig } = await Promise.resolve().then(() => require("../config.js"));
605
+ const projectRoot = cg.getProjectRoot();
606
+ const config = await loadConfig(projectRoot);
607
+ if (config.enableMemory) {
608
+ const { MemoryManager } = await Promise.resolve().then(() => require("../memory/index.js"));
609
+ const db = cg.getDatabase();
610
+ db.applyMemorySchema();
611
+ const mem = new MemoryManager(config, db.getRawDb());
612
+ mem.initialize();
613
+ const qualifiedNames = [
614
+ ...ctx.entryPoints.map((n) => n.qualifiedName),
615
+ ...ctx.relatedNodes.slice(0, 5).map((n) => n.qualifiedName)
616
+ ].filter(Boolean);
617
+ const contextLimit = config.memoryContextLimit ?? 3;
618
+ const contextThreshold = config.memoryContextThreshold ?? 0.3;
619
+ let memResults = mem.getLinkedObservations(qualifiedNames, contextLimit, contextThreshold);
620
+ if (memResults.length === 0) {
621
+ memResults = (await mem.search(args.task, { limit: contextLimit })).filter((r) => r.score >= contextThreshold);
622
+ }
623
+ if (memResults.length > 0) {
624
+ lines.push("", "## Related Memory");
625
+ for (const r of memResults.slice(0, contextLimit)) {
626
+ const age = formatAge(r.observation.createdAt);
627
+ lines.push(`- [${r.observation.kind}] ${r.observation.content} (${age})`);
628
+ }
629
+ }
630
+ }
631
+ } catch {
632
+ }
523
633
  return lines.join("\n");
524
634
  }
525
635
  case "kirograph_callers": {
@@ -552,8 +662,37 @@ class ToolHandler {
552
662
  const node = results[0].node;
553
663
  const affected = await cg.getImpactRadius(node.id, args.depth ?? 2);
554
664
  if (affected.length === 0) return `No dependents found for \`${node.name}\`.`;
555
- return `Changing \`${node.name}\` may affect ${affected.length} symbol(s):
665
+ let output = `Changing \`${node.name}\` may affect ${affected.length} symbol(s):
556
666
  ` + affected.map((n) => `- ${mapKind(n.kind)} \`${n.name}\` \u2014 ${n.filePath}:${n.startLine}`).join("\n");
667
+ try {
668
+ const { loadConfig } = await Promise.resolve().then(() => require("../config.js"));
669
+ const projectRoot = cg.getProjectRoot();
670
+ const config = await loadConfig(projectRoot);
671
+ if (config.enableMemory) {
672
+ const { MemoryManager } = await Promise.resolve().then(() => require("../memory/index.js"));
673
+ const db = cg.getDatabase();
674
+ db.applyMemorySchema();
675
+ const mem = new MemoryManager(config, db.getRawDb());
676
+ mem.initialize();
677
+ const contextLimit = config.memoryContextLimit ?? 3;
678
+ const contextThreshold = config.memoryContextThreshold ?? 0.3;
679
+ const memResults = mem.getLinkedObservations(
680
+ [node.qualifiedName],
681
+ contextLimit,
682
+ contextThreshold
683
+ );
684
+ if (memResults.length > 0) {
685
+ output += "\n\nRelated Memory:";
686
+ for (const r of memResults) {
687
+ const age = formatAge(r.observation.createdAt);
688
+ output += `
689
+ - [${r.observation.kind}] ${r.observation.content} (${age})`;
690
+ }
691
+ }
692
+ }
693
+ } catch {
694
+ }
695
+ return output;
557
696
  }
558
697
  case "kirograph_node": {
559
698
  const results = cg.searchNodes(args.symbol, void 0, 5);
@@ -934,6 +1073,96 @@ class ToolHandler {
934
1073
  }
935
1074
  return lines.join("\n");
936
1075
  }
1076
+ // ── Memory tools ────────────────────────────────────────────────────────
1077
+ case "kirograph_mem_search": {
1078
+ const { loadConfig } = await Promise.resolve().then(() => require("../config.js"));
1079
+ const projectRoot = cg.getProjectRoot();
1080
+ const config = await loadConfig(projectRoot);
1081
+ if (!config.enableMemory) return "Memory is not enabled. Set enableMemory: true in .kirograph/config.json";
1082
+ const { MemoryManager } = await Promise.resolve().then(() => require("../memory/index.js"));
1083
+ const db = cg.getDatabase();
1084
+ db.applyMemorySchema();
1085
+ const mem = new MemoryManager(config, db.getRawDb());
1086
+ mem.initialize();
1087
+ const results = await mem.search(args.query, {
1088
+ limit: args.limit ?? 10,
1089
+ kind: args.kind,
1090
+ sessionId: args.sessionId
1091
+ });
1092
+ if (results.length === 0) return `No memory observations found for "${args.query}".`;
1093
+ return results.map((r, i) => {
1094
+ const age = formatAge(r.observation.createdAt);
1095
+ return `${i + 1}. [${r.observation.kind}] ${r.observation.content} (${age})`;
1096
+ }).join("\n");
1097
+ }
1098
+ case "kirograph_mem_store": {
1099
+ const { loadConfig } = await Promise.resolve().then(() => require("../config.js"));
1100
+ const projectRoot = cg.getProjectRoot();
1101
+ const config = await loadConfig(projectRoot);
1102
+ if (!config.enableMemory) return "Memory is not enabled. Set enableMemory: true in .kirograph/config.json";
1103
+ const { MemoryManager } = await Promise.resolve().then(() => require("../memory/index.js"));
1104
+ const db = cg.getDatabase();
1105
+ db.applyMemorySchema();
1106
+ const mem = new MemoryManager(config, db.getRawDb());
1107
+ mem.initialize();
1108
+ const id = await mem.store({
1109
+ content: args.content,
1110
+ kind: args.kind ?? "note",
1111
+ source: "agent"
1112
+ });
1113
+ if (!id) return "Observation already exists (duplicate content).";
1114
+ return `Stored observation ${id} [${args.kind ?? "note"}]`;
1115
+ }
1116
+ case "kirograph_mem_timeline": {
1117
+ const { loadConfig } = await Promise.resolve().then(() => require("../config.js"));
1118
+ const projectRoot = cg.getProjectRoot();
1119
+ const config = await loadConfig(projectRoot);
1120
+ if (!config.enableMemory) return "Memory is not enabled. Set enableMemory: true in .kirograph/config.json";
1121
+ const { MemoryManager } = await Promise.resolve().then(() => require("../memory/index.js"));
1122
+ const db = cg.getDatabase();
1123
+ db.applyMemorySchema();
1124
+ const mem = new MemoryManager(config, db.getRawDb());
1125
+ mem.initialize();
1126
+ const { sessions, observations } = mem.timeline({
1127
+ limit: args.limit ?? 5,
1128
+ sessionId: args.sessionId
1129
+ });
1130
+ if (sessions.length === 0) return "No memory sessions found.";
1131
+ const lines = [];
1132
+ for (const session of sessions) {
1133
+ const start = new Date(session.startedAt).toISOString().slice(0, 16).replace("T", " ");
1134
+ const status = session.endedAt ? "ended" : "active";
1135
+ const obs = observations.get(session.id) ?? [];
1136
+ lines.push(`## ${start} [${session.ide ?? "unknown"}] (${status}, ${obs.length} observations)`);
1137
+ for (const o of obs.slice(0, 5)) {
1138
+ lines.push(` - [${o.kind}] ${o.content.slice(0, 120)}`);
1139
+ }
1140
+ if (obs.length > 5) lines.push(` \u2026and ${obs.length - 5} more`);
1141
+ }
1142
+ return lines.join("\n");
1143
+ }
1144
+ case "kirograph_mem_status": {
1145
+ const { loadConfig } = await Promise.resolve().then(() => require("../config.js"));
1146
+ const projectRoot = cg.getProjectRoot();
1147
+ const config = await loadConfig(projectRoot);
1148
+ if (!config.enableMemory) return "Memory is not enabled. Set enableMemory: true in .kirograph/config.json";
1149
+ const { MemoryManager } = await Promise.resolve().then(() => require("../memory/index.js"));
1150
+ const db = cg.getDatabase();
1151
+ db.applyMemorySchema();
1152
+ const mem = new MemoryManager(config, db.getRawDb());
1153
+ mem.initialize();
1154
+ const stats = mem.getStats();
1155
+ const lines = [
1156
+ "KiroGraph Memory Status",
1157
+ ` Sessions: ${stats.sessions} (${stats.activeSessions} active)`,
1158
+ ` Observations: ${stats.observations}`,
1159
+ ` Symbol links: ${stats.links}`,
1160
+ ` Embeddings: ${stats.vectors} / ${stats.embeddableCount}`,
1161
+ ` Model mismatch: ${stats.modelMismatch ? "\u26A0 yes \u2014 run kirograph mem reembed" : "no"}`,
1162
+ ` Caveman compression: ${config.cavemanMode !== "off" ? config.cavemanMode : "off (storing raw)"}`
1163
+ ];
1164
+ return lines.join("\n");
1165
+ }
937
1166
  default:
938
1167
  return `Unknown tool: ${toolName}`;
939
1168
  }