kirograph 0.23.0 → 0.26.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 (62) hide show
  1. package/README.md +19 -5
  2. package/dist/bin/commands/configure-mcp.js +104 -0
  3. package/dist/bin/commands/configure-mcp.js.map +7 -0
  4. package/dist/bin/commands/memory.js +334 -2
  5. package/dist/bin/commands/memory.js.map +2 -2
  6. package/dist/bin/commands/wiki.js +307 -0
  7. package/dist/bin/commands/wiki.js.map +7 -0
  8. package/dist/bin/installer/common.js +9 -0
  9. package/dist/bin/installer/common.js.map +2 -2
  10. package/dist/bin/installer/config-prompt.js +96 -5
  11. package/dist/bin/installer/config-prompt.js.map +2 -2
  12. package/dist/bin/installer/hooks.js +40 -0
  13. package/dist/bin/installer/hooks.js.map +2 -2
  14. package/dist/bin/installer/index.js +22 -11
  15. package/dist/bin/installer/index.js.map +2 -2
  16. package/dist/bin/installer/instructions.js +27 -1
  17. package/dist/bin/installer/instructions.js.map +2 -2
  18. package/dist/bin/installer/mcp.js +37 -4
  19. package/dist/bin/installer/mcp.js.map +2 -2
  20. package/dist/bin/installer/prompts.js +3 -3
  21. package/dist/bin/installer/prompts.js.map +2 -2
  22. package/dist/bin/installer/steering.js +633 -291
  23. package/dist/bin/installer/steering.js.map +2 -2
  24. package/dist/bin/installer/targets/index.js.map +1 -1
  25. package/dist/bin/installer/targets/kiro.js +5 -4
  26. package/dist/bin/installer/targets/kiro.js.map +2 -2
  27. package/dist/bin/kirograph.js +3 -1
  28. package/dist/bin/kirograph.js.map +3 -3
  29. package/dist/config.js +52 -5
  30. package/dist/config.js.map +2 -2
  31. package/dist/db/database.js +11 -0
  32. package/dist/db/database.js.map +2 -2
  33. package/dist/db/memory-schema.sql +34 -1
  34. package/dist/db/wiki-schema.sql +40 -0
  35. package/dist/mcp/server.js +35 -11
  36. package/dist/mcp/server.js.map +2 -2
  37. package/dist/mcp/tool-names.js +112 -1
  38. package/dist/mcp/tool-names.js.map +2 -2
  39. package/dist/mcp/tools.js +458 -3
  40. package/dist/mcp/tools.js.map +2 -2
  41. package/dist/memory/database.js +131 -7
  42. package/dist/memory/database.js.map +2 -2
  43. package/dist/memory/index.js +130 -4
  44. package/dist/memory/index.js.map +3 -3
  45. package/dist/memory/types.js.map +1 -1
  46. package/dist/watchmen/synthesize.js +2 -0
  47. package/dist/watchmen/synthesize.js.map +2 -2
  48. package/dist/wiki/database.js +143 -0
  49. package/dist/wiki/database.js.map +7 -0
  50. package/dist/wiki/index.js +149 -0
  51. package/dist/wiki/index.js.map +7 -0
  52. package/dist/wiki/ingest.js +259 -0
  53. package/dist/wiki/ingest.js.map +7 -0
  54. package/dist/wiki/lint.js +93 -0
  55. package/dist/wiki/lint.js.map +7 -0
  56. package/dist/wiki/schema.js +148 -0
  57. package/dist/wiki/schema.js.map +7 -0
  58. package/dist/wiki/synthesize.js +104 -0
  59. package/dist/wiki/synthesize.js.map +7 -0
  60. package/dist/wiki/types.js +17 -0
  61. package/dist/wiki/types.js.map +7 -0
  62. package/package.json +5 -3
@@ -0,0 +1,307 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+ var wiki_exports = {};
30
+ __export(wiki_exports, {
31
+ register: () => register
32
+ });
33
+ module.exports = __toCommonJS(wiki_exports);
34
+ var fs = __toESM(require("fs"));
35
+ var import_ui = require("../ui");
36
+ const yellow = "\x1B[33m";
37
+ async function getWiki(cwd) {
38
+ const { KiroGraphWiki } = await Promise.resolve().then(() => require("../../wiki/index.js"));
39
+ const { loadConfig } = await Promise.resolve().then(() => require("../../config.js"));
40
+ const KiroGraph = (await Promise.resolve().then(() => require("../../index.js"))).default;
41
+ if (!KiroGraph.isInitialized(cwd)) {
42
+ console.error(" \u2716 KiroGraph is not initialized. Run `kirograph init` first.");
43
+ process.exit(1);
44
+ }
45
+ const config = await loadConfig(cwd);
46
+ if (!config.enableWiki) {
47
+ console.error(" \u2716 Wiki is not enabled. Set enableWiki: true in .kirograph/config.json");
48
+ process.exit(1);
49
+ }
50
+ const cg = await KiroGraph.open(cwd);
51
+ const db = cg.getDatabase();
52
+ db.applyWikiSchema();
53
+ const kirographDir = `${cwd}/.kirograph`;
54
+ const wiki = new KiroGraphWiki(db.getRawDb(), kirographDir, {
55
+ autoResolveConflicts: config.wikiAutoResolveConflicts
56
+ });
57
+ wiki.initialize();
58
+ return wiki;
59
+ }
60
+ function readStdinSync() {
61
+ return fs.readFileSync("/dev/stdin", "utf8");
62
+ }
63
+ function register(program) {
64
+ const wiki = program.command("wiki").description("LLM-maintained structured wiki (requires enableWiki: true)");
65
+ wiki.command("init").description("Initialize wiki: create SCHEMA.md and MANIFEST.md in .kirograph/wiki/").action(async () => {
66
+ const { KiroGraphWiki } = await Promise.resolve().then(() => require("../../wiki/index.js"));
67
+ const KiroGraph = (await Promise.resolve().then(() => require("../../index.js"))).default;
68
+ const cwd = process.cwd();
69
+ if (!KiroGraph.isInitialized(cwd)) {
70
+ console.error(" \u2716 KiroGraph is not initialized. Run `kirograph init` first.");
71
+ process.exit(1);
72
+ }
73
+ const { loadConfig } = await Promise.resolve().then(() => require("../../config.js"));
74
+ const config = await loadConfig(cwd);
75
+ const cg = await KiroGraph.open(cwd);
76
+ const db = cg.getDatabase();
77
+ db.applyWikiSchema();
78
+ const w = new KiroGraphWiki(db.getRawDb(), `${cwd}/.kirograph`, {
79
+ autoResolveConflicts: config.wikiAutoResolveConflicts
80
+ });
81
+ w.initWiki();
82
+ console.log(`
83
+ ${import_ui.green}\u2713${import_ui.reset} Wiki initialized in ${import_ui.dim}.kirograph/wiki/${import_ui.reset}`);
84
+ console.log(` ${import_ui.dim}Edit .kirograph/wiki/SCHEMA.md to customize naming and page structure.${import_ui.reset}
85
+ `);
86
+ });
87
+ wiki.command("ingest [source]").description("Print the ingest prompt for the LLM (reads file or stdin)").option("--name <name>", "Source name to include in the prompt").action(async (source, opts) => {
88
+ const cwd = process.cwd();
89
+ const w = await getWiki(cwd);
90
+ let content;
91
+ let sourceName = opts.name ?? source ?? "source";
92
+ if (source && fs.existsSync(source)) {
93
+ content = fs.readFileSync(source, "utf8");
94
+ sourceName = opts.name ?? source;
95
+ } else if (source) {
96
+ content = source;
97
+ } else {
98
+ content = readStdinSync();
99
+ }
100
+ const prompt = w.getIngestPrompt(content, sourceName);
101
+ console.log(`
102
+ ${(0, import_ui.section)("Wiki Ingest Prompt")} ${import_ui.dim}(pass to LLM, then run wiki apply-diff)${import_ui.reset}
103
+ `);
104
+ console.log(prompt);
105
+ console.log();
106
+ });
107
+ wiki.command("apply-diff [diff]").description("Apply a WIKI_DIFF string to the wiki (reads file or stdin)").action(async (diff) => {
108
+ const cwd = process.cwd();
109
+ const w = await getWiki(cwd);
110
+ let rawDiff;
111
+ if (diff && fs.existsSync(diff)) {
112
+ rawDiff = fs.readFileSync(diff, "utf8");
113
+ } else if (diff) {
114
+ rawDiff = diff;
115
+ } else {
116
+ rawDiff = readStdinSync();
117
+ }
118
+ const result = w.applyDiff(rawDiff);
119
+ console.log(`
120
+ ${import_ui.green}\u2713${import_ui.reset} Wiki diff applied
121
+ `);
122
+ if (result.created.length) {
123
+ console.log(` ${import_ui.violet}Created:${import_ui.reset} ${result.created.join(", ")}`);
124
+ }
125
+ if (result.updated.length) {
126
+ console.log(` ${import_ui.violet}Updated:${import_ui.reset} ${result.updated.join(", ")}`);
127
+ }
128
+ if (result.conflictsResolved.length) {
129
+ console.log(` ${import_ui.green}Conflicts resolved:${import_ui.reset} ${result.conflictsResolved.join(", ")}`);
130
+ }
131
+ if (result.conflictsPending.length) {
132
+ console.log(`
133
+ ${yellow}\u26A1 Conflicts pending (${result.conflictsPending.length}):${import_ui.reset}`);
134
+ for (const c of result.conflictsPending) {
135
+ console.log(` ${import_ui.dim} ${c.page} \xA7${c.section}${import_ui.reset}`);
136
+ console.log(` existing: "${c.existing}"`);
137
+ console.log(` incoming: "${c.incoming}" (source: ${c.source})`);
138
+ }
139
+ }
140
+ console.log();
141
+ });
142
+ wiki.command("search <query>").description("Full-text search over wiki pages").option("--limit <n>", "Max results", "5").option("--format <fmt>", "Output format: text, json", "text").action(async (query, opts) => {
143
+ const cwd = process.cwd();
144
+ const w = await getWiki(cwd);
145
+ const results = w.search(query, parseInt(opts.limit));
146
+ if (opts.format === "json") {
147
+ console.log(JSON.stringify(results.map((r) => ({
148
+ slug: r.page.slug,
149
+ title: r.page.title,
150
+ score: r.score,
151
+ updatedAt: r.page.updatedAt
152
+ })), null, 2));
153
+ return;
154
+ }
155
+ if (results.length === 0) {
156
+ console.log(`
157
+ ${import_ui.dim}No wiki pages found for "${query}"${import_ui.reset}
158
+ `);
159
+ return;
160
+ }
161
+ console.log(`
162
+ ${(0, import_ui.section)("Wiki Search:")} ${import_ui.violet}${import_ui.bold}${query}${import_ui.reset}
163
+ `);
164
+ for (const { page, score } of results) {
165
+ console.log(` ${import_ui.violet}[${page.slug}]${import_ui.reset} ${import_ui.bold}${page.title}${import_ui.reset} ${import_ui.dim}score: ${score.toFixed(3)}${import_ui.reset}`);
166
+ const preview = page.content.split("\n").find((l) => l.trim() && !l.startsWith("#"));
167
+ if (preview) console.log(` ${import_ui.dim}${preview.trim().slice(0, 120)}${import_ui.reset}`);
168
+ console.log();
169
+ }
170
+ });
171
+ wiki.command("page <slug>").description("Print the full content of a wiki page").action(async (slug) => {
172
+ const cwd = process.cwd();
173
+ const w = await getWiki(cwd);
174
+ const page = w.getPage(slug);
175
+ if (!page) {
176
+ console.error(` \u2716 Wiki page "${slug}" not found. Run \`kirograph wiki list\` to see available pages.`);
177
+ process.exit(1);
178
+ }
179
+ console.log();
180
+ console.log(page.content);
181
+ });
182
+ wiki.command("list").description("List all wiki pages").option("--format <fmt>", "Output format: text, json", "text").action(async (opts) => {
183
+ const cwd = process.cwd();
184
+ const w = await getWiki(cwd);
185
+ const pages = w.listPages();
186
+ if (opts.format === "json") {
187
+ console.log(JSON.stringify(pages.map((p) => ({
188
+ slug: p.slug,
189
+ title: p.title,
190
+ sourceCount: p.sourceCount,
191
+ updatedAt: p.updatedAt
192
+ })), null, 2));
193
+ return;
194
+ }
195
+ const stats = w.getStats();
196
+ console.log(`
197
+ ${(0, import_ui.section)("Wiki")} ${import_ui.dim}${stats.pageCount} page(s)${import_ui.reset}
198
+ `);
199
+ if (pages.length === 0) {
200
+ console.log(` ${import_ui.dim}No pages yet. Run \`kirograph wiki ingest\` to add pages.${import_ui.reset}
201
+ `);
202
+ return;
203
+ }
204
+ for (const p of pages) {
205
+ const date = new Date(p.updatedAt).toISOString().slice(0, 10);
206
+ console.log(` ${import_ui.violet}${p.slug.padEnd(32)}${import_ui.reset} ${p.title} ${import_ui.dim}(${p.sourceCount} src, ${date})${import_ui.reset}`);
207
+ }
208
+ console.log();
209
+ });
210
+ wiki.command("lint").description("Health check the wiki for issues").action(async () => {
211
+ const cwd = process.cwd();
212
+ const w = await getWiki(cwd);
213
+ const issues = w.lint();
214
+ if (issues.length === 0) {
215
+ console.log(`
216
+ ${import_ui.green}\u2713${import_ui.reset} Wiki lint passed \u2014 no issues found.
217
+ `);
218
+ return;
219
+ }
220
+ console.log(`
221
+ ${(0, import_ui.section)("Wiki Lint")} ${yellow}${issues.length} issue(s)${import_ui.reset}
222
+ `);
223
+ for (const issue of issues) {
224
+ const icon = issue.kind === "contradiction" ? "\u26A1" : issue.kind === "orphan" ? "\u25CB" : issue.kind === "broken_link" ? "\u{1F517}" : "\u26A0";
225
+ console.log(` ${icon} ${import_ui.dim}[${issue.kind}]${import_ui.reset} ${import_ui.violet}${issue.slug}${import_ui.reset}`);
226
+ console.log(` ${issue.detail}`);
227
+ console.log();
228
+ }
229
+ });
230
+ wiki.command("reindex").description("Rebuild SQLite index from .kirograph/wiki/*.md files").action(async () => {
231
+ const cwd = process.cwd();
232
+ const w = await getWiki(cwd);
233
+ const count = w.reindex();
234
+ console.log(`
235
+ ${import_ui.green}\u2713${import_ui.reset} Reindexed ${import_ui.bold}${count}${import_ui.reset} wiki page(s)
236
+ `);
237
+ });
238
+ wiki.command("status").description("Wiki subsystem stats").action(async () => {
239
+ const cwd = process.cwd();
240
+ const w = await getWiki(cwd);
241
+ const stats = w.getStats();
242
+ const oldest = stats.oldestPage ? new Date(stats.oldestPage).toISOString().slice(0, 10) : "n/a";
243
+ const newest = stats.newestPage ? new Date(stats.newestPage).toISOString().slice(0, 10) : "n/a";
244
+ console.log(`
245
+ ${(0, import_ui.section)("Wiki Status")}
246
+ `);
247
+ console.log(` Pages: ${import_ui.bold}${stats.pageCount}${import_ui.reset}`);
248
+ console.log(` Total sources: ${import_ui.bold}${stats.totalSources}${import_ui.reset}`);
249
+ console.log(` Oldest page: ${import_ui.dim}${oldest}${import_ui.reset}`);
250
+ console.log(` Newest page: ${import_ui.dim}${newest}${import_ui.reset}`);
251
+ console.log(` Wiki dir: ${import_ui.dim}.kirograph/wiki/${import_ui.reset}
252
+ `);
253
+ });
254
+ wiki.command("synthesize").description("Run local-model wiki synthesis: process the pending source queue (wikiSynthesisMode: local)").option("--quiet", "suppress progress output").action(async (opts) => {
255
+ const { KiroGraphWiki } = await Promise.resolve().then(() => require("../../wiki/index.js"));
256
+ const { loadConfig } = await Promise.resolve().then(() => require("../../config.js"));
257
+ const KiroGraph = (await Promise.resolve().then(() => require("../../index.js"))).default;
258
+ const cwd = process.cwd();
259
+ if (!KiroGraph.isInitialized(cwd)) {
260
+ console.error(" \u2716 KiroGraph is not initialized. Run `kirograph init` first.");
261
+ process.exit(1);
262
+ }
263
+ const config = await loadConfig(cwd);
264
+ if (!config.enableWiki) {
265
+ console.error(" \u2716 Wiki is not enabled.");
266
+ process.exit(1);
267
+ }
268
+ if (config.wikiSynthesisMode !== "local") {
269
+ console.error(' \u2716 wikiSynthesisMode is not "local". This command is for local-model synthesis only.');
270
+ process.exit(1);
271
+ }
272
+ const cg = await KiroGraph.open(cwd);
273
+ const db = cg.getDatabase();
274
+ db.applyWikiSchema();
275
+ const w = new KiroGraphWiki(db.getRawDb(), `${cwd}/.kirograph`, {
276
+ autoResolveConflicts: config.wikiAutoResolveConflicts
277
+ });
278
+ w.initialize();
279
+ const queueCount = w.getQueueCount();
280
+ if (queueCount === 0) {
281
+ if (!opts.quiet) console.log(`
282
+ ${import_ui.dim}Wiki queue is empty \u2014 nothing to synthesize.${import_ui.reset}
283
+ `);
284
+ process.exit(0);
285
+ }
286
+ if (!opts.quiet) console.log(`
287
+ ${yellow}\u27F3${import_ui.reset} Synthesizing ${import_ui.bold}${queueCount}${import_ui.reset} queued source(s) with local model...
288
+ `);
289
+ const result = await w.synthesize(config.wikiLocalModel, !!opts.quiet);
290
+ if (!opts.quiet) {
291
+ if (result.processed > 0) {
292
+ console.log(` ${import_ui.green}\u2713${import_ui.reset} Processed: ${import_ui.bold}${result.processed}${import_ui.reset} source(s)`);
293
+ if (result.created.length) console.log(` ${import_ui.green}\u2713${import_ui.reset} Created: ${result.created.join(", ")}`);
294
+ if (result.updated.length) console.log(` ${import_ui.green}\u2713${import_ui.reset} Updated: ${result.updated.join(", ")}`);
295
+ }
296
+ if (result.errors.length) {
297
+ for (const e of result.errors) console.error(` ${yellow}\u26A0${import_ui.reset} ${e}`);
298
+ }
299
+ console.log("");
300
+ }
301
+ });
302
+ }
303
+ // Annotate the CommonJS export names for ESM import in node:
304
+ 0 && (module.exports = {
305
+ register
306
+ });
307
+ //# sourceMappingURL=wiki.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/bin/commands/wiki.ts"],
4
+ "sourcesContent": ["/**\n * KiroGraph Wiki CLI\n *\n * kirograph wiki init\n * kirograph wiki ingest [source-file]\n * kirograph wiki apply-diff [diff-file]\n * kirograph wiki search <query>\n * kirograph wiki page <slug>\n * kirograph wiki list\n * kirograph wiki lint\n * kirograph wiki reindex\n * kirograph wiki status\n */\n\nimport { Command } from 'commander';\nimport * as fs from 'fs';\nimport { dim, reset, violet, bold, section, green } from '../ui';\n\nconst yellow = '\\x1b[33m';\n\nasync function getWiki(cwd: string) {\n const { KiroGraphWiki } = await Promise.resolve().then(() => require('../../wiki/index.js'));\n const { loadConfig } = await Promise.resolve().then(() => require('../../config.js'));\n const KiroGraph = (await Promise.resolve().then(() => require('../../index.js'))).default;\n\n if (!KiroGraph.isInitialized(cwd)) {\n console.error(' \u2716 KiroGraph is not initialized. Run `kirograph init` first.');\n process.exit(1);\n }\n const config = await loadConfig(cwd);\n if (!config.enableWiki) {\n console.error(' \u2716 Wiki is not enabled. Set enableWiki: true in .kirograph/config.json');\n process.exit(1);\n }\n\n const cg = await KiroGraph.open(cwd);\n const db = cg.getDatabase();\n db.applyWikiSchema();\n\n const kirographDir = `${cwd}/.kirograph`;\n const wiki = new KiroGraphWiki(db.getRawDb(), kirographDir, {\n autoResolveConflicts: config.wikiAutoResolveConflicts,\n });\n wiki.initialize();\n return wiki;\n}\n\nfunction readStdinSync(): string {\n return fs.readFileSync('/dev/stdin', 'utf8');\n}\n\nexport function register(program: Command): void {\n const wiki = program\n .command('wiki')\n .description('LLM-maintained structured wiki (requires enableWiki: true)');\n\n // \u2500\u2500 init \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n wiki\n .command('init')\n .description('Initialize wiki: create SCHEMA.md and MANIFEST.md in .kirograph/wiki/')\n .action(async () => {\n const { KiroGraphWiki } = await Promise.resolve().then(() => require('../../wiki/index.js'));\n const KiroGraph = (await Promise.resolve().then(() => require('../../index.js'))).default;\n const cwd = process.cwd();\n if (!KiroGraph.isInitialized(cwd)) {\n console.error(' \u2716 KiroGraph is not initialized. Run `kirograph init` first.');\n process.exit(1);\n }\n const { loadConfig } = await Promise.resolve().then(() => require('../../config.js'));\n const config = await loadConfig(cwd);\n const cg = await KiroGraph.open(cwd);\n const db = cg.getDatabase();\n db.applyWikiSchema();\n const w = new KiroGraphWiki(db.getRawDb(), `${cwd}/.kirograph`, {\n autoResolveConflicts: config.wikiAutoResolveConflicts,\n });\n w.initWiki();\n console.log(`\\n ${green}\u2713${reset} Wiki initialized in ${dim}.kirograph/wiki/${reset}`);\n console.log(` ${dim}Edit .kirograph/wiki/SCHEMA.md to customize naming and page structure.${reset}\\n`);\n });\n\n // \u2500\u2500 ingest \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n wiki\n .command('ingest [source]')\n .description('Print the ingest prompt for the LLM (reads file or stdin)')\n .option('--name <name>', 'Source name to include in the prompt')\n .action(async (source: string | undefined, opts: { name?: string }) => {\n const cwd = process.cwd();\n const w = await getWiki(cwd);\n\n let content: string;\n let sourceName = opts.name ?? source ?? 'source';\n\n if (source && fs.existsSync(source)) {\n content = fs.readFileSync(source, 'utf8');\n sourceName = opts.name ?? source;\n } else if (source) {\n content = source;\n } else {\n content = readStdinSync();\n }\n\n const prompt = w.getIngestPrompt(content, sourceName);\n console.log(`\\n ${section('Wiki Ingest Prompt')} ${dim}(pass to LLM, then run wiki apply-diff)${reset}\\n`);\n console.log(prompt);\n console.log();\n });\n\n // \u2500\u2500 apply-diff \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n wiki\n .command('apply-diff [diff]')\n .description('Apply a WIKI_DIFF string to the wiki (reads file or stdin)')\n .action(async (diff: string | undefined) => {\n const cwd = process.cwd();\n const w = await getWiki(cwd);\n\n let rawDiff: string;\n if (diff && fs.existsSync(diff)) {\n rawDiff = fs.readFileSync(diff, 'utf8');\n } else if (diff) {\n rawDiff = diff;\n } else {\n rawDiff = readStdinSync();\n }\n\n const result = w.applyDiff(rawDiff);\n\n console.log(`\\n ${green}\u2713${reset} Wiki diff applied\\n`);\n if (result.created.length) {\n console.log(` ${violet}Created:${reset} ${result.created.join(', ')}`);\n }\n if (result.updated.length) {\n console.log(` ${violet}Updated:${reset} ${result.updated.join(', ')}`);\n }\n if (result.conflictsResolved.length) {\n console.log(` ${green}Conflicts resolved:${reset} ${result.conflictsResolved.join(', ')}`);\n }\n if (result.conflictsPending.length) {\n console.log(`\\n ${yellow}\u26A1 Conflicts pending (${result.conflictsPending.length}):${reset}`);\n for (const c of result.conflictsPending) {\n console.log(` ${dim} ${c.page} \u00A7${c.section}${reset}`);\n console.log(` existing: \"${c.existing}\"`);\n console.log(` incoming: \"${c.incoming}\" (source: ${c.source})`);\n }\n }\n console.log();\n });\n\n // \u2500\u2500 search \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n wiki\n .command('search <query>')\n .description('Full-text search over wiki pages')\n .option('--limit <n>', 'Max results', '5')\n .option('--format <fmt>', 'Output format: text, json', 'text')\n .action(async (query: string, opts: { limit: string; format: string }) => {\n const cwd = process.cwd();\n const w = await getWiki(cwd);\n const results = w.search(query, parseInt(opts.limit));\n\n if (opts.format === 'json') {\n console.log(JSON.stringify(results.map(r => ({\n slug: r.page.slug,\n title: r.page.title,\n score: r.score,\n updatedAt: r.page.updatedAt,\n })), null, 2));\n return;\n }\n\n if (results.length === 0) {\n console.log(`\\n ${dim}No wiki pages found for \"${query}\"${reset}\\n`);\n return;\n }\n\n console.log(`\\n ${section('Wiki Search:')} ${violet}${bold}${query}${reset}\\n`);\n for (const { page, score } of results) {\n console.log(` ${violet}[${page.slug}]${reset} ${bold}${page.title}${reset} ${dim}score: ${score.toFixed(3)}${reset}`);\n const preview = page.content.split('\\n').find(l => l.trim() && !l.startsWith('#'));\n if (preview) console.log(` ${dim}${preview.trim().slice(0, 120)}${reset}`);\n console.log();\n }\n });\n\n // \u2500\u2500 page \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n wiki\n .command('page <slug>')\n .description('Print the full content of a wiki page')\n .action(async (slug: string) => {\n const cwd = process.cwd();\n const w = await getWiki(cwd);\n const page = w.getPage(slug);\n if (!page) {\n console.error(` \u2716 Wiki page \"${slug}\" not found. Run \\`kirograph wiki list\\` to see available pages.`);\n process.exit(1);\n }\n console.log();\n console.log(page.content);\n });\n\n // \u2500\u2500 list \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n wiki\n .command('list')\n .description('List all wiki pages')\n .option('--format <fmt>', 'Output format: text, json', 'text')\n .action(async (opts: { format: string }) => {\n const cwd = process.cwd();\n const w = await getWiki(cwd);\n const pages = w.listPages();\n\n if (opts.format === 'json') {\n console.log(JSON.stringify(pages.map(p => ({\n slug: p.slug,\n title: p.title,\n sourceCount: p.sourceCount,\n updatedAt: p.updatedAt,\n })), null, 2));\n return;\n }\n\n const stats = w.getStats();\n console.log(`\\n ${section('Wiki')} ${dim}${stats.pageCount} page(s)${reset}\\n`);\n if (pages.length === 0) {\n console.log(` ${dim}No pages yet. Run \\`kirograph wiki ingest\\` to add pages.${reset}\\n`);\n return;\n }\n for (const p of pages) {\n const date = new Date(p.updatedAt).toISOString().slice(0, 10);\n console.log(` ${violet}${p.slug.padEnd(32)}${reset} ${p.title} ${dim}(${p.sourceCount} src, ${date})${reset}`);\n }\n console.log();\n });\n\n // \u2500\u2500 lint \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n wiki\n .command('lint')\n .description('Health check the wiki for issues')\n .action(async () => {\n const cwd = process.cwd();\n const w = await getWiki(cwd);\n const issues = w.lint();\n\n if (issues.length === 0) {\n console.log(`\\n ${green}\u2713${reset} Wiki lint passed \u2014 no issues found.\\n`);\n return;\n }\n\n console.log(`\\n ${section('Wiki Lint')} ${yellow}${issues.length} issue(s)${reset}\\n`);\n for (const issue of issues) {\n const icon = issue.kind === 'contradiction' ? '\u26A1' : issue.kind === 'orphan' ? '\u25CB' : issue.kind === 'broken_link' ? '\uD83D\uDD17' : '\u26A0';\n console.log(` ${icon} ${dim}[${issue.kind}]${reset} ${violet}${issue.slug}${reset}`);\n console.log(` ${issue.detail}`);\n console.log();\n }\n });\n\n // \u2500\u2500 reindex \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n wiki\n .command('reindex')\n .description('Rebuild SQLite index from .kirograph/wiki/*.md files')\n .action(async () => {\n const cwd = process.cwd();\n const w = await getWiki(cwd);\n const count = w.reindex();\n console.log(`\\n ${green}\u2713${reset} Reindexed ${bold}${count}${reset} wiki page(s)\\n`);\n });\n\n // \u2500\u2500 status \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n wiki\n .command('status')\n .description('Wiki subsystem stats')\n .action(async () => {\n const cwd = process.cwd();\n const w = await getWiki(cwd);\n const stats = w.getStats();\n const oldest = stats.oldestPage ? new Date(stats.oldestPage).toISOString().slice(0, 10) : 'n/a';\n const newest = stats.newestPage ? new Date(stats.newestPage).toISOString().slice(0, 10) : 'n/a';\n console.log(`\\n ${section('Wiki Status')}\\n`);\n console.log(` Pages: ${bold}${stats.pageCount}${reset}`);\n console.log(` Total sources: ${bold}${stats.totalSources}${reset}`);\n console.log(` Oldest page: ${dim}${oldest}${reset}`);\n console.log(` Newest page: ${dim}${newest}${reset}`);\n console.log(` Wiki dir: ${dim}.kirograph/wiki/${reset}\\n`);\n });\n\n // \u2500\u2500 synthesize (local model) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n wiki\n .command('synthesize')\n .description('Run local-model wiki synthesis: process the pending source queue (wikiSynthesisMode: local)')\n .option('--quiet', 'suppress progress output')\n .action(async (opts) => {\n const { KiroGraphWiki } = await Promise.resolve().then(() => require('../../wiki/index.js'));\n const { loadConfig } = await Promise.resolve().then(() => require('../../config.js'));\n const KiroGraph = (await Promise.resolve().then(() => require('../../index.js'))).default;\n const cwd = process.cwd();\n\n if (!KiroGraph.isInitialized(cwd)) {\n console.error(' \u2716 KiroGraph is not initialized. Run `kirograph init` first.');\n process.exit(1);\n }\n const config = await loadConfig(cwd);\n if (!config.enableWiki) {\n console.error(' \u2716 Wiki is not enabled.');\n process.exit(1);\n }\n if (config.wikiSynthesisMode !== 'local') {\n console.error(' \u2716 wikiSynthesisMode is not \"local\". This command is for local-model synthesis only.');\n process.exit(1);\n }\n\n const cg = await KiroGraph.open(cwd);\n const db = cg.getDatabase();\n db.applyWikiSchema();\n const w = new KiroGraphWiki(db.getRawDb(), `${cwd}/.kirograph`, {\n autoResolveConflicts: config.wikiAutoResolveConflicts,\n });\n w.initialize();\n\n const queueCount = w.getQueueCount();\n if (queueCount === 0) {\n if (!opts.quiet) console.log(`\\n ${dim}Wiki queue is empty \u2014 nothing to synthesize.${reset}\\n`);\n process.exit(0);\n }\n\n if (!opts.quiet) console.log(`\\n ${yellow}\u27F3${reset} Synthesizing ${bold}${queueCount}${reset} queued source(s) with local model...\\n`);\n\n const result = await w.synthesize(config.wikiLocalModel, !!opts.quiet);\n\n if (!opts.quiet) {\n if (result.processed > 0) {\n console.log(` ${green}\u2713${reset} Processed: ${bold}${result.processed}${reset} source(s)`);\n if (result.created.length) console.log(` ${green}\u2713${reset} Created: ${result.created.join(', ')}`);\n if (result.updated.length) console.log(` ${green}\u2713${reset} Updated: ${result.updated.join(', ')}`);\n }\n if (result.errors.length) {\n for (const e of result.errors) console.error(` ${yellow}\u26A0${reset} ${e}`);\n }\n console.log('');\n }\n });\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -37,6 +37,7 @@ __export(common_exports, {
37
37
  appendImportLine: () => appendImportLine,
38
38
  buildInstructionOpts: () => buildInstructionOpts,
39
39
  ensureDir: () => ensureDir,
40
+ overwriteMcpServersConfig: () => overwriteMcpServersConfig,
40
41
  printMcpCommand: () => printMcpCommand,
41
42
  printMcpSetup: () => printMcpSetup,
42
43
  readJson: () => readJson,
@@ -81,6 +82,13 @@ function writeMcpServersConfig(configPath, serverConfig) {
81
82
  writeJson(configPath, existing);
82
83
  return true;
83
84
  }
85
+ function overwriteMcpServersConfig(configPath, serverConfig) {
86
+ ensureDir(path.dirname(configPath));
87
+ const existing = readJson(configPath);
88
+ existing.mcpServers = existing.mcpServers ?? {};
89
+ existing.mcpServers[KIROGRAPH_SERVER_NAME] = serverConfig;
90
+ writeJson(configPath, existing);
91
+ }
84
92
  function removeMcpServersConfig(configPath) {
85
93
  if (!fs.existsSync(configPath)) return false;
86
94
  const existing = readJson(configPath);
@@ -189,6 +197,7 @@ function printMcpCommand(command) {
189
197
  appendImportLine,
190
198
  buildInstructionOpts,
191
199
  ensureDir,
200
+ overwriteMcpServersConfig,
192
201
  printMcpCommand,
193
202
  printMcpSetup,
194
203
  readJson,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/bin/installer/common.ts"],
4
- "sourcesContent": ["import * as fs from 'fs';\nimport * as path from 'path';\nimport { KIROGRAPH_TOOL_NAMES } from '../../mcp/tool-names';\nimport type { InstructionOptions } from './instructions';\nimport type { CavemanMode } from './caveman';\n\nexport type InstallTarget = 'kiro' | 'claude' | 'codex' | 'cursor' | 'antigravity' | 'opencode' | 'windsurf' | 'cline' | 'copilot' | 'copilot-cli' | 'junie' | 'gemini-cli' | 'continue' | 'roo' | 'warp' | 'aider' | 'trae' | 'augment' | 'kilo' | 'amp' | 'devin' | 'replit' | 'goose' | 'openhands' | 'tabnine' | 'mistral-vibe' | 'ibm-bob' | 'crush' | 'droid-factory' | 'forgecode' | 'iflow' | 'qwen' | 'rovo' | 'qoder';\n\nexport const KIROGRAPH_SERVER_NAME = 'kirograph';\nexport const KIROGRAPH_COMMAND = 'kirograph';\nexport const KIROGRAPH_MCP_ARGS = ['serve', '--mcp'];\nexport const KIROGRAPH_SYNC_CMD = 'kirograph sync-if-dirty --quiet 2>/dev/null || true';\nexport const KIROGRAPH_TOOLS = KIROGRAPH_TOOL_NAMES;\nexport const KIROGRAPH_SCOPED_TOOLS = KIROGRAPH_TOOL_NAMES.map(name => `@kirograph/${name}`);\n\nexport function ensureDir(p: string): void {\n fs.mkdirSync(p, { recursive: true });\n}\n\nexport function readJson(p: string): any {\n try { return JSON.parse(fs.readFileSync(p, 'utf8')); } catch { return {}; }\n}\n\nexport function writeJson(p: string, data: unknown): void {\n fs.writeFileSync(p, JSON.stringify(data, null, 2) + '\\n');\n}\n\n/**\n * Write MCP server config to a JSON file under the mcpServers key.\n * Returns true if the config was written, false if already configured (idempotent).\n */\nexport function writeMcpServersConfig(configPath: string, serverConfig: object): boolean {\n ensureDir(path.dirname(configPath));\n const existing = readJson(configPath);\n existing.mcpServers = existing.mcpServers ?? {};\n if (existing.mcpServers[KIROGRAPH_SERVER_NAME]) {\n return false; // Already configured\n }\n existing.mcpServers[KIROGRAPH_SERVER_NAME] = serverConfig;\n writeJson(configPath, existing);\n return true;\n}\n\nexport function removeMcpServersConfig(configPath: string): boolean {\n if (!fs.existsSync(configPath)) return false;\n const existing = readJson(configPath);\n if (!existing.mcpServers?.[KIROGRAPH_SERVER_NAME]) return false;\n delete existing.mcpServers[KIROGRAPH_SERVER_NAME];\n writeJson(configPath, existing);\n return true;\n}\n\nexport function appendImportLine(filePath: string, line: string, heading: string): boolean {\n const existing = fs.existsSync(filePath) ? fs.readFileSync(filePath, 'utf8') : '';\n if (existing.includes(line)) return false;\n\n const prefix = existing.length > 0 && !existing.endsWith('\\n') ? '\\n' : '';\n const separator = existing.trim().length > 0 ? '\\n' : '';\n fs.writeFileSync(filePath, existing + prefix + separator + heading + '\\n' + line + '\\n');\n return true;\n}\n\nexport function removeImportLine(filePath: string, line: string): boolean {\n if (!fs.existsSync(filePath)) return false;\n const original = fs.readFileSync(filePath, 'utf8');\n const next = original\n .split('\\n')\n .filter(l => l.trim() !== line)\n .join('\\n')\n .replace(/\\n{3,}/g, '\\n\\n');\n if (next === original) return false;\n fs.writeFileSync(filePath, next.endsWith('\\n') ? next : next + '\\n');\n return true;\n}\n\nexport function upsertGeneratedBlock(filePath: string, blockId: string, heading: string, content: string): boolean {\n const start = `<!-- kirograph:${blockId}:start -->`;\n const end = `<!-- kirograph:${blockId}:end -->`;\n const block = `${start}\\n${heading}\\n\\n${content.trim()}\\n${end}`;\n const existing = fs.existsSync(filePath) ? fs.readFileSync(filePath, 'utf8') : '';\n const pattern = new RegExp(`${escapeRegExp(start)}[\\\\s\\\\S]*?${escapeRegExp(end)}`);\n\n if (pattern.test(existing)) {\n const next = existing.replace(pattern, block);\n if (next === existing) return false;\n fs.writeFileSync(filePath, next.endsWith('\\n') ? next : next + '\\n');\n return true;\n }\n\n const prefix = existing.length > 0 && !existing.endsWith('\\n') ? '\\n' : '';\n const separator = existing.trim().length > 0 ? '\\n' : '';\n fs.writeFileSync(filePath, existing + prefix + separator + block + '\\n');\n return true;\n}\n\nexport function removeGeneratedBlock(filePath: string, blockId: string): boolean {\n if (!fs.existsSync(filePath)) return false;\n const start = `<!-- kirograph:${blockId}:start -->`;\n const end = `<!-- kirograph:${blockId}:end -->`;\n const original = fs.readFileSync(filePath, 'utf8');\n const pattern = new RegExp(`\\\\n?${escapeRegExp(start)}[\\\\s\\\\S]*?${escapeRegExp(end)}\\\\n?`);\n const next = original.replace(pattern, '\\n').replace(/\\n{3,}/g, '\\n\\n');\n if (next === original) return false;\n fs.writeFileSync(filePath, next.endsWith('\\n') ? next : next + '\\n');\n return true;\n}\n\nfunction escapeRegExp(s: string): string {\n return s.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\n/**\n * Build InstructionOptions from the installLate parameters.\n * Used by all targets to pass full feature config to buildAgentInstructions.\n */\nexport function buildInstructionOpts(\n cavemanMode?: CavemanMode | 'off',\n shellCompressionLevel?: string,\n enableMemory?: boolean,\n hasHooks?: boolean,\n enableDocs?: boolean,\n enableData?: boolean,\n enableSecurity?: boolean,\n enableArchitecture?: boolean,\n enablePatterns?: boolean,\n): InstructionOptions {\n return {\n cavemanMode,\n shellCompressionLevel: (shellCompressionLevel as InstructionOptions['shellCompressionLevel']) ?? undefined,\n enableArchitecture: enableArchitecture ?? false,\n enableMemory: enableMemory ?? false,\n enableDocs: enableDocs ?? false,\n enableData: enableData ?? false,\n enableSecurity: enableSecurity ?? false,\n enablePatterns: enablePatterns ?? false,\n hasHooks: hasHooks ?? false,\n };\n}\n\nconst violet = '\\x1b[38;5;99m';\nconst resetAnsi = '\\x1b[0m';\nconst dimAnsi = '\\x1b[2m';\nconst boldAnsi = '\\x1b[1m';\n\n/**\n * Print a highlighted MCP config JSON block for targets that need user-scoped setup.\n */\nexport function printMcpSetup(configPath: string, projectRoot: string): void {\n const escapedPath = projectRoot.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"');\n console.log(`\\n ${dimAnsi}Add the MCP server manually:${resetAnsi}`);\n console.log(` ${dimAnsi}Edit${resetAnsi} ${violet}${boldAnsi}${configPath}${resetAnsi} ${dimAnsi}and add:${resetAnsi}`);\n console.log(` ${violet}{${resetAnsi}`);\n console.log(` ${violet} \"mcpServers\": {${resetAnsi}`);\n console.log(` ${violet} \"kirograph\": {${resetAnsi}`);\n console.log(` ${violet} \"command\": \"kirograph\",${resetAnsi}`);\n console.log(` ${violet} \"args\": [\"serve\", \"--mcp\", \"--path\", \"${escapedPath}\"]${resetAnsi}`);\n console.log(` ${violet} }${resetAnsi}`);\n console.log(` ${violet} }${resetAnsi}`);\n console.log(` ${violet}}${resetAnsi}\\n`);\n}\n\n/**\n * Print a highlighted CLI command for MCP registration.\n */\nexport function printMcpCommand(command: string): void {\n console.log(`\\n ${dimAnsi}Add the MCP server with:${resetAnsi}`);\n console.log(` ${violet}${boldAnsi}${command}${resetAnsi}\\n`);\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import * as fs from 'fs';\nimport * as path from 'path';\nimport { KIROGRAPH_TOOL_NAMES } from '../../mcp/tool-names';\nimport type { InstructionOptions } from './instructions';\nimport type { CavemanMode } from './caveman';\n\nexport type InstallTarget = 'kiro' | 'claude' | 'codex' | 'cursor' | 'antigravity' | 'opencode' | 'windsurf' | 'cline' | 'copilot' | 'copilot-cli' | 'junie' | 'gemini-cli' | 'continue' | 'roo' | 'warp' | 'aider' | 'trae' | 'augment' | 'kilo' | 'amp' | 'devin' | 'replit' | 'goose' | 'openhands' | 'tabnine' | 'mistral-vibe' | 'ibm-bob' | 'crush' | 'droid-factory' | 'forgecode' | 'iflow' | 'qwen' | 'rovo' | 'qoder';\n\nexport const KIROGRAPH_SERVER_NAME = 'kirograph';\nexport const KIROGRAPH_COMMAND = 'kirograph';\nexport const KIROGRAPH_MCP_ARGS = ['serve', '--mcp'];\nexport const KIROGRAPH_SYNC_CMD = 'kirograph sync-if-dirty --quiet 2>/dev/null || true';\nexport const KIROGRAPH_TOOLS = KIROGRAPH_TOOL_NAMES;\nexport const KIROGRAPH_SCOPED_TOOLS = KIROGRAPH_TOOL_NAMES.map(name => `@kirograph/${name}`);\n\nexport function ensureDir(p: string): void {\n fs.mkdirSync(p, { recursive: true });\n}\n\nexport function readJson(p: string): any {\n try { return JSON.parse(fs.readFileSync(p, 'utf8')); } catch { return {}; }\n}\n\nexport function writeJson(p: string, data: unknown): void {\n fs.writeFileSync(p, JSON.stringify(data, null, 2) + '\\n');\n}\n\n/**\n * Write MCP server config to a JSON file under the mcpServers key.\n * Returns true if the config was written, false if already configured (idempotent).\n */\nexport function writeMcpServersConfig(configPath: string, serverConfig: object): boolean {\n ensureDir(path.dirname(configPath));\n const existing = readJson(configPath);\n existing.mcpServers = existing.mcpServers ?? {};\n if (existing.mcpServers[KIROGRAPH_SERVER_NAME]) {\n return false; // Already configured\n }\n existing.mcpServers[KIROGRAPH_SERVER_NAME] = serverConfig;\n writeJson(configPath, existing);\n return true;\n}\n\n/**\n * Always write (overwrite) the MCP server config entry, regardless of whether it already exists.\n * Used when the final state is known upfront and idempotency would cause stale data.\n */\nexport function overwriteMcpServersConfig(configPath: string, serverConfig: object): void {\n ensureDir(path.dirname(configPath));\n const existing = readJson(configPath);\n existing.mcpServers = existing.mcpServers ?? {};\n existing.mcpServers[KIROGRAPH_SERVER_NAME] = serverConfig;\n writeJson(configPath, existing);\n}\n\nexport function removeMcpServersConfig(configPath: string): boolean {\n if (!fs.existsSync(configPath)) return false;\n const existing = readJson(configPath);\n if (!existing.mcpServers?.[KIROGRAPH_SERVER_NAME]) return false;\n delete existing.mcpServers[KIROGRAPH_SERVER_NAME];\n writeJson(configPath, existing);\n return true;\n}\n\nexport function appendImportLine(filePath: string, line: string, heading: string): boolean {\n const existing = fs.existsSync(filePath) ? fs.readFileSync(filePath, 'utf8') : '';\n if (existing.includes(line)) return false;\n\n const prefix = existing.length > 0 && !existing.endsWith('\\n') ? '\\n' : '';\n const separator = existing.trim().length > 0 ? '\\n' : '';\n fs.writeFileSync(filePath, existing + prefix + separator + heading + '\\n' + line + '\\n');\n return true;\n}\n\nexport function removeImportLine(filePath: string, line: string): boolean {\n if (!fs.existsSync(filePath)) return false;\n const original = fs.readFileSync(filePath, 'utf8');\n const next = original\n .split('\\n')\n .filter(l => l.trim() !== line)\n .join('\\n')\n .replace(/\\n{3,}/g, '\\n\\n');\n if (next === original) return false;\n fs.writeFileSync(filePath, next.endsWith('\\n') ? next : next + '\\n');\n return true;\n}\n\nexport function upsertGeneratedBlock(filePath: string, blockId: string, heading: string, content: string): boolean {\n const start = `<!-- kirograph:${blockId}:start -->`;\n const end = `<!-- kirograph:${blockId}:end -->`;\n const block = `${start}\\n${heading}\\n\\n${content.trim()}\\n${end}`;\n const existing = fs.existsSync(filePath) ? fs.readFileSync(filePath, 'utf8') : '';\n const pattern = new RegExp(`${escapeRegExp(start)}[\\\\s\\\\S]*?${escapeRegExp(end)}`);\n\n if (pattern.test(existing)) {\n const next = existing.replace(pattern, block);\n if (next === existing) return false;\n fs.writeFileSync(filePath, next.endsWith('\\n') ? next : next + '\\n');\n return true;\n }\n\n const prefix = existing.length > 0 && !existing.endsWith('\\n') ? '\\n' : '';\n const separator = existing.trim().length > 0 ? '\\n' : '';\n fs.writeFileSync(filePath, existing + prefix + separator + block + '\\n');\n return true;\n}\n\nexport function removeGeneratedBlock(filePath: string, blockId: string): boolean {\n if (!fs.existsSync(filePath)) return false;\n const start = `<!-- kirograph:${blockId}:start -->`;\n const end = `<!-- kirograph:${blockId}:end -->`;\n const original = fs.readFileSync(filePath, 'utf8');\n const pattern = new RegExp(`\\\\n?${escapeRegExp(start)}[\\\\s\\\\S]*?${escapeRegExp(end)}\\\\n?`);\n const next = original.replace(pattern, '\\n').replace(/\\n{3,}/g, '\\n\\n');\n if (next === original) return false;\n fs.writeFileSync(filePath, next.endsWith('\\n') ? next : next + '\\n');\n return true;\n}\n\nfunction escapeRegExp(s: string): string {\n return s.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\n/**\n * Build InstructionOptions from the installLate parameters.\n * Used by all targets to pass full feature config to buildAgentInstructions.\n */\nexport function buildInstructionOpts(\n cavemanMode?: CavemanMode | 'off',\n shellCompressionLevel?: string,\n enableMemory?: boolean,\n hasHooks?: boolean,\n enableDocs?: boolean,\n enableData?: boolean,\n enableSecurity?: boolean,\n enableArchitecture?: boolean,\n enablePatterns?: boolean,\n): InstructionOptions {\n return {\n cavemanMode,\n shellCompressionLevel: (shellCompressionLevel as InstructionOptions['shellCompressionLevel']) ?? undefined,\n enableArchitecture: enableArchitecture ?? false,\n enableMemory: enableMemory ?? false,\n enableDocs: enableDocs ?? false,\n enableData: enableData ?? false,\n enableSecurity: enableSecurity ?? false,\n enablePatterns: enablePatterns ?? false,\n hasHooks: hasHooks ?? false,\n };\n}\n\nconst violet = '\\x1b[38;5;99m';\nconst resetAnsi = '\\x1b[0m';\nconst dimAnsi = '\\x1b[2m';\nconst boldAnsi = '\\x1b[1m';\n\n/**\n * Print a highlighted MCP config JSON block for targets that need user-scoped setup.\n */\nexport function printMcpSetup(configPath: string, projectRoot: string): void {\n const escapedPath = projectRoot.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"');\n console.log(`\\n ${dimAnsi}Add the MCP server manually:${resetAnsi}`);\n console.log(` ${dimAnsi}Edit${resetAnsi} ${violet}${boldAnsi}${configPath}${resetAnsi} ${dimAnsi}and add:${resetAnsi}`);\n console.log(` ${violet}{${resetAnsi}`);\n console.log(` ${violet} \"mcpServers\": {${resetAnsi}`);\n console.log(` ${violet} \"kirograph\": {${resetAnsi}`);\n console.log(` ${violet} \"command\": \"kirograph\",${resetAnsi}`);\n console.log(` ${violet} \"args\": [\"serve\", \"--mcp\", \"--path\", \"${escapedPath}\"]${resetAnsi}`);\n console.log(` ${violet} }${resetAnsi}`);\n console.log(` ${violet} }${resetAnsi}`);\n console.log(` ${violet}}${resetAnsi}\\n`);\n}\n\n/**\n * Print a highlighted CLI command for MCP registration.\n */\nexport function printMcpCommand(command: string): void {\n console.log(`\\n ${dimAnsi}Add the MCP server with:${resetAnsi}`);\n console.log(` ${violet}${boldAnsi}${command}${resetAnsi}\\n`);\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -63,7 +63,7 @@ async function promptConfigOptions(rl) {
63
63
  "Semantic embeddings (similarity search):",
64
64
  "Enables natural-language code search via vector embeddings. A local model (~130MB) is downloaded on first use."
65
65
  );
66
- const patch = { enableEmbeddings, useVecIndex: false, semanticEngine: "cosine", turboquantMemDocs: false, turboquantBits: 3, turbovecMemDocs: false, turbovecBits: 4, typesenseDashboard: false, qdrantDashboard: false, extractDocstrings: true, trackCallSites: true, enableArchitecture: false, cavemanMode: "off", shellCompressionLevel: "normal", enableMemory: false, enableWatchmen: false, watchmenThreshold: 5, watchmenSynthesisMode: "local", watchmenLocalModel: "onnx-community/gemma-4-E4B-it-ONNX", enableDocs: false, docsContextLimit: 0, enableData: false, dataContextLimit: 0, enableSecurity: false, enablePatterns: false };
66
+ const patch = { enableEmbeddings, useVecIndex: false, semanticEngine: "cosine", turboquantMemDocs: false, turboquantBits: 3, turbovecMemDocs: false, turbovecBits: 4, typesenseDashboard: false, qdrantDashboard: false, extractDocstrings: false, trackCallSites: false, enableArchitecture: false, cavemanMode: "off", shellCompressionLevel: "normal", enableMemory: false, enableWatchmen: false, watchmenThreshold: 5, watchmenSynthesisMode: "local", watchmenLocalModel: "onnx-community/gemma-4-E4B-it-ONNX", enableDocs: false, docsContextLimit: 0, enableData: false, dataContextLimit: 0, enableSecurity: false, enablePatterns: false, enableWiki: false, wikiSynthesisMode: "agent", wikiLocalModel: "onnx-community/gemma-4-E4B-it-ONNX", enableCodeHealth: false, enableAdvancedAnalysis: false, enableAgentUtils: false };
67
67
  if (enableEmbeddings) {
68
68
  const modelChoice = await (0, import_prompts.arrowSelect)(
69
69
  rl,
@@ -156,12 +156,14 @@ async function promptConfigOptions(rl) {
156
156
  patch.extractDocstrings = await (0, import_prompts.askToggle)(
157
157
  rl,
158
158
  "Docstring extraction:",
159
- "Enriches symbol metadata and improves context quality. Slightly increases indexing time."
159
+ "Enriches symbol metadata and improves context quality. Slightly increases indexing time.",
160
+ false
160
161
  );
161
162
  patch.trackCallSites = await (0, import_prompts.askToggle)(
162
163
  rl,
163
164
  "Call site tracking (caller/callee graph):",
164
- "Enables kirograph_callers and kirograph_callees MCP tools. Increases index size."
165
+ "Enables kirograph_callers and kirograph_callees MCP tools. Increases index size.",
166
+ false
165
167
  );
166
168
  patch.enableArchitecture = await (0, import_prompts.askToggle)(
167
169
  rl,
@@ -169,6 +171,27 @@ async function promptConfigOptions(rl) {
169
171
  "Detects packages from manifests and architectural layers. Enables kirograph_architecture, kirograph_coupling, kirograph_package.",
170
172
  false
171
173
  );
174
+ if (patch.enableArchitecture) {
175
+ patch.enableAdvancedAnalysis = await (0, import_prompts.askToggle)(
176
+ rl,
177
+ "Advanced graph analysis (type hierarchies, flows, communities, refactor):",
178
+ "Enables kirograph_type_hierarchy, kirograph_flows, kirograph_communities, kirograph_refactor. Most useful alongside architecture analysis.",
179
+ false
180
+ );
181
+ }
182
+ (0, import_prompts.printSection)("\u{1F4CA}", "Graph Tools");
183
+ patch.enableCodeHealth = await (0, import_prompts.askToggle)(
184
+ rl,
185
+ "Code health tools (hotspots, dead code, change tracking):",
186
+ "Enables kirograph_hotspots, kirograph_surprising, kirograph_diff, kirograph_dead_code, kirograph_circular_deps.",
187
+ false
188
+ );
189
+ patch.enableAgentUtils = await (0, import_prompts.askToggle)(
190
+ rl,
191
+ "Agent utilities (file caching, budget tracking):",
192
+ "Enables kirograph_read, kirograph_gain, kirograph_budget.",
193
+ false
194
+ );
172
195
  (0, import_prompts.printSection)("\u{1F512}", "Security");
173
196
  patch.enableSecurity = await (0, import_prompts.askToggle)(
174
197
  rl,
@@ -244,13 +267,16 @@ async function promptConfigOptions(rl) {
244
267
  { value: "ultra", label: "ultra", description: "Max compression, abbreviations, \u2192 for causality" }
245
268
  ]);
246
269
  patch.cavemanMode = cavemanChoice;
247
- const compressionChoice = await (0, import_prompts.arrowSelect)(rl, "Shell compression (kirograph_exec default level):", [
248
- { value: "off", label: "off", description: "No compression hook or steering (tool still available)" },
270
+ const compressionChoice = await (0, import_prompts.arrowSelect)(rl, "Shell compression (kirograph_exec):", [
271
+ { value: "off", label: "off", description: "Disables kirograph_exec entirely" },
249
272
  { value: "normal", label: "normal", description: "Balanced: removes noise, keeps structure (recommended)" },
250
273
  { value: "aggressive", label: "aggressive", description: "More compact: groups by category, limits output" },
251
274
  { value: "ultra", label: "ultra", description: "Maximum compression: counts and summaries only" }
252
275
  ]);
253
276
  patch.shellCompressionLevel = compressionChoice;
277
+ if (compressionChoice === "off") {
278
+ console.log(" \u2139 kirograph_exec disabled (shell compression is off)");
279
+ }
254
280
  (0, import_prompts.printSection)("\u{1F9E0}", "Memory");
255
281
  patch.enableMemory = await (0, import_prompts.askToggle)(
256
282
  rl,
@@ -324,6 +350,71 @@ async function promptConfigOptions(rl) {
324
350
  }
325
351
  }
326
352
  }
353
+ (0, import_prompts.printSection)("\u{1F4D6}", "Wiki");
354
+ patch.enableWiki = await (0, import_prompts.askToggle)(
355
+ rl,
356
+ "LLM Wiki (Karpathy-style structured knowledge base):",
357
+ "Maintains a set of markdown pages that compound knowledge across sessions. Supports search, ingest (two-tool flow), conflict resolution, and health checks via kirograph_wiki_* tools.",
358
+ false
359
+ );
360
+ if (patch.enableWiki) {
361
+ const wikiMode = await (0, import_prompts.arrowSelect)(
362
+ rl,
363
+ "Wiki synthesis mode:",
364
+ [
365
+ {
366
+ value: "agent",
367
+ label: "Active agent (recommended)",
368
+ description: "Uses the active LLM agent to generate WIKI_DIFF blocks. Works with any AI tool. Consumes API tokens on ingest."
369
+ },
370
+ {
371
+ value: "local",
372
+ label: "Local model",
373
+ description: "Runs a local HuggingFace model to generate diffs. Zero API cost, no data leaves your machine. Same infra as Watchmen."
374
+ }
375
+ ]
376
+ );
377
+ patch.wikiSynthesisMode = wikiMode;
378
+ if (wikiMode === "local") {
379
+ const WIKI_LOCAL_MODELS = [
380
+ {
381
+ value: "onnx-community/gemma-4-E4B-it-ONNX",
382
+ label: "Gemma 4 E4B (recommended)",
383
+ description: "~3\u20134 GB \xB7 Google DeepMind Gemma 4 \xB7 4.5B params \xB7 128K context \xB7 Best quality \xB7 Apache 2.0"
384
+ },
385
+ {
386
+ value: "onnx-community/Qwen2.5-1.5B-Instruct",
387
+ label: "Qwen2.5-1.5B",
388
+ description: "~1.5 GB \xB7 Lighter option if RAM is limited \xB7 Acceptable quality"
389
+ },
390
+ {
391
+ value: "HuggingFaceTB/SmolLM2-1.7B-Instruct",
392
+ label: "SmolLM2-1.7B",
393
+ description: "~1.7 GB \xB7 HuggingFace compact model \xB7 Good at following structured formats"
394
+ },
395
+ {
396
+ value: "__other__",
397
+ label: "Other",
398
+ description: "Enter a custom HuggingFace model ID (must have ONNX weights on onnx-community)"
399
+ }
400
+ ];
401
+ const wikiModelChoice = await (0, import_prompts.arrowSelect)(rl, "Local wiki synthesis model:", WIKI_LOCAL_MODELS.map((m) => ({ value: m.value, label: m.label, description: m.description })));
402
+ if (wikiModelChoice === "__other__") {
403
+ console.log(`
404
+ ${import_prompts.dim}Enter a HuggingFace model ID (e.g. onnx-community/gemma-4-E4B-it-ONNX).${import_prompts.reset}`);
405
+ while (true) {
406
+ const raw = (await (0, import_prompts.ask)(rl, ` ${import_prompts.violet}Model identifier:${import_prompts.reset} `)).trim();
407
+ if (raw.includes("/")) {
408
+ patch.wikiLocalModel = raw;
409
+ break;
410
+ }
411
+ console.log(` Expected a HuggingFace model ID in the format org/model-name.`);
412
+ }
413
+ } else {
414
+ patch.wikiLocalModel = wikiModelChoice;
415
+ }
416
+ }
417
+ }
327
418
  return patch;
328
419
  }
329
420
  // Annotate the CommonJS export names for ESM import in node: