kirograph 0.23.0 → 0.27.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.
- package/README.md +19 -5
- package/dist/bin/commands/configure-mcp.js +104 -0
- package/dist/bin/commands/configure-mcp.js.map +7 -0
- package/dist/bin/commands/memory.js +334 -2
- package/dist/bin/commands/memory.js.map +2 -2
- package/dist/bin/commands/uninit.js +12 -5
- package/dist/bin/commands/uninit.js.map +2 -2
- package/dist/bin/commands/wiki.js +307 -0
- package/dist/bin/commands/wiki.js.map +7 -0
- package/dist/bin/installer/common.js +9 -0
- package/dist/bin/installer/common.js.map +2 -2
- package/dist/bin/installer/config-prompt.js +96 -5
- package/dist/bin/installer/config-prompt.js.map +2 -2
- package/dist/bin/installer/hooks.js +182 -88
- package/dist/bin/installer/hooks.js.map +2 -2
- package/dist/bin/installer/index.js +30 -12
- package/dist/bin/installer/index.js.map +2 -2
- package/dist/bin/installer/instructions.js +27 -1
- package/dist/bin/installer/instructions.js.map +2 -2
- package/dist/bin/installer/mcp.js +37 -4
- package/dist/bin/installer/mcp.js.map +2 -2
- package/dist/bin/installer/prompts.js +3 -3
- package/dist/bin/installer/prompts.js.map +2 -2
- package/dist/bin/installer/steering.js +633 -291
- package/dist/bin/installer/steering.js.map +2 -2
- package/dist/bin/installer/targets/index.js.map +1 -1
- package/dist/bin/installer/targets/kiro.js +7 -6
- package/dist/bin/installer/targets/kiro.js.map +2 -2
- package/dist/bin/kirograph.js +3 -1
- package/dist/bin/kirograph.js.map +3 -3
- package/dist/config.js +52 -5
- package/dist/config.js.map +2 -2
- package/dist/db/database.js +11 -0
- package/dist/db/database.js.map +2 -2
- package/dist/db/memory-schema.sql +34 -1
- package/dist/db/wiki-schema.sql +40 -0
- package/dist/mcp/server.js +35 -11
- package/dist/mcp/server.js.map +2 -2
- package/dist/mcp/tool-names.js +112 -1
- package/dist/mcp/tool-names.js.map +2 -2
- package/dist/mcp/tools.js +458 -3
- package/dist/mcp/tools.js.map +2 -2
- package/dist/memory/database.js +131 -7
- package/dist/memory/database.js.map +2 -2
- package/dist/memory/index.js +130 -4
- package/dist/memory/index.js.map +3 -3
- package/dist/memory/types.js.map +1 -1
- package/dist/watchmen/synthesize.js +2 -0
- package/dist/watchmen/synthesize.js.map +2 -2
- package/dist/wiki/database.js +143 -0
- package/dist/wiki/database.js.map +7 -0
- package/dist/wiki/index.js +149 -0
- package/dist/wiki/index.js.map +7 -0
- package/dist/wiki/ingest.js +259 -0
- package/dist/wiki/ingest.js.map +7 -0
- package/dist/wiki/lint.js +93 -0
- package/dist/wiki/lint.js.map +7 -0
- package/dist/wiki/schema.js +148 -0
- package/dist/wiki/schema.js.map +7 -0
- package/dist/wiki/synthesize.js +104 -0
- package/dist/wiki/synthesize.js.map +7 -0
- package/dist/wiki/types.js +17 -0
- package/dist/wiki/types.js.map +7 -0
- package/package.json +6 -4
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var schema_exports = {};
|
|
20
|
+
__export(schema_exports, {
|
|
21
|
+
DEFAULT_SCHEMA: () => DEFAULT_SCHEMA,
|
|
22
|
+
parseWikiDiff: () => parseWikiDiff
|
|
23
|
+
});
|
|
24
|
+
module.exports = __toCommonJS(schema_exports);
|
|
25
|
+
const DEFAULT_SCHEMA = `# Wiki Schema
|
|
26
|
+
|
|
27
|
+
This file tells KiroGraph's LLM how to structure and maintain the project wiki.
|
|
28
|
+
Edit it to match your project's conventions.
|
|
29
|
+
|
|
30
|
+
## Naming convention
|
|
31
|
+
|
|
32
|
+
- Entities (classes, services, modules): \`<ClassName>.md\` or \`<module-name>.md\`
|
|
33
|
+
- Architecture decisions: \`arch/<slug>.md\`
|
|
34
|
+
- Recurring patterns: \`pattern/<slug>.md\`
|
|
35
|
+
- External integrations: \`ext/<service>.md\`
|
|
36
|
+
|
|
37
|
+
## Page structure
|
|
38
|
+
|
|
39
|
+
Every page should follow this template:
|
|
40
|
+
|
|
41
|
+
\`\`\`markdown
|
|
42
|
+
## Summary
|
|
43
|
+
One to three sentences describing what this entity is and why it exists.
|
|
44
|
+
|
|
45
|
+
## Decisions
|
|
46
|
+
- YYYY-MM-DD \u2014 Decision text (one line per decision, newest first)
|
|
47
|
+
|
|
48
|
+
## Known Issues / Gotchas
|
|
49
|
+
- Bullet points of non-obvious constraints, bugs, or workarounds
|
|
50
|
+
|
|
51
|
+
## Related
|
|
52
|
+
- [[other-page-slug]] \u2014 one line description of the relationship
|
|
53
|
+
|
|
54
|
+
## Sources
|
|
55
|
+
- source-name (YYYY-MM-DD)
|
|
56
|
+
\`\`\`
|
|
57
|
+
|
|
58
|
+
## Ingest workflow
|
|
59
|
+
|
|
60
|
+
When given a source document to ingest:
|
|
61
|
+
|
|
62
|
+
1. Read the source and identify entities, decisions, and patterns mentioned
|
|
63
|
+
2. Check MANIFEST.md to find existing pages for those entities
|
|
64
|
+
3. For each existing page: integrate new information into the appropriate sections
|
|
65
|
+
4. For each new entity: create a page following the structure above
|
|
66
|
+
5. Always update ## Sources with the source name and today's date
|
|
67
|
+
6. Update ## Related cross-references in all touched pages
|
|
68
|
+
7. If new information contradicts an existing claim, emit a WIKI_DIFF_CONFLICTS block
|
|
69
|
+
|
|
70
|
+
## WIKI_DIFF format
|
|
71
|
+
|
|
72
|
+
Produce output using this exact format \u2014 one block per page operation:
|
|
73
|
+
|
|
74
|
+
\`\`\`
|
|
75
|
+
WIKI_DIFF_START
|
|
76
|
+
{"action":"upsert","page":"PageSlug","section":"Decisions","mode":"append"}
|
|
77
|
+
- YYYY-MM-DD \u2014 New decision text
|
|
78
|
+
WIKI_DIFF_END
|
|
79
|
+
\`\`\`
|
|
80
|
+
|
|
81
|
+
Actions:
|
|
82
|
+
- \`create\` \u2014 new page (requires \`title\` field, content is full markdown)
|
|
83
|
+
- \`upsert\` \u2014 update a section in an existing page (mode: \`append\` or \`replace\`)
|
|
84
|
+
- \`append\` \u2014 append to the end of an existing page
|
|
85
|
+
|
|
86
|
+
For conflicts:
|
|
87
|
+
\`\`\`
|
|
88
|
+
WIKI_DIFF_CONFLICTS
|
|
89
|
+
{"page":"PageSlug","section":"SectionName","existing":"old claim","incoming":"new claim","source":"ADR-001.md","existingDate":"2025-01-01","incomingDate":"2025-06-15"}
|
|
90
|
+
WIKI_DIFF_CONFLICTS_END
|
|
91
|
+
\`\`\`
|
|
92
|
+
`;
|
|
93
|
+
function parseWikiDiff(raw) {
|
|
94
|
+
const entries = [];
|
|
95
|
+
const conflicts = [];
|
|
96
|
+
const diffRegex = /WIKI_DIFF_START\n([\s\S]*?)\nWIKI_DIFF_END/g;
|
|
97
|
+
let match;
|
|
98
|
+
while ((match = diffRegex.exec(raw)) !== null) {
|
|
99
|
+
const block = match[1].trim();
|
|
100
|
+
const firstNewline = block.indexOf("\n");
|
|
101
|
+
if (firstNewline === -1) continue;
|
|
102
|
+
const headerStr = block.slice(0, firstNewline).trim();
|
|
103
|
+
const content = block.slice(firstNewline + 1);
|
|
104
|
+
let header;
|
|
105
|
+
try {
|
|
106
|
+
header = JSON.parse(headerStr);
|
|
107
|
+
} catch {
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
entries.push({
|
|
111
|
+
action: header.action ?? "upsert",
|
|
112
|
+
page: header.page ?? "",
|
|
113
|
+
title: header.title,
|
|
114
|
+
section: header.section,
|
|
115
|
+
mode: header.mode ?? "append",
|
|
116
|
+
content
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
const conflictRegex = /WIKI_DIFF_CONFLICTS\n([\s\S]*?)\nWIKI_DIFF_CONFLICTS_END/g;
|
|
120
|
+
while ((match = conflictRegex.exec(raw)) !== null) {
|
|
121
|
+
const block = match[1].trim();
|
|
122
|
+
for (const line of block.split("\n")) {
|
|
123
|
+
const trimmed = line.trim();
|
|
124
|
+
if (!trimmed) continue;
|
|
125
|
+
try {
|
|
126
|
+
const c = JSON.parse(trimmed);
|
|
127
|
+
conflicts.push({
|
|
128
|
+
page: c.page ?? "",
|
|
129
|
+
section: c.section ?? "",
|
|
130
|
+
existing: c.existing ?? "",
|
|
131
|
+
incoming: c.incoming ?? "",
|
|
132
|
+
source: c.source ?? "",
|
|
133
|
+
existingDate: c.existingDate,
|
|
134
|
+
incomingDate: c.incomingDate
|
|
135
|
+
});
|
|
136
|
+
} catch {
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return { entries, conflicts, rawDiff: raw };
|
|
142
|
+
}
|
|
143
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
144
|
+
0 && (module.exports = {
|
|
145
|
+
DEFAULT_SCHEMA,
|
|
146
|
+
parseWikiDiff
|
|
147
|
+
});
|
|
148
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/wiki/schema.ts"],
|
|
4
|
+
"sourcesContent": ["// Default SCHEMA.md content written by `kirograph wiki init`\n\nexport const DEFAULT_SCHEMA = `# Wiki Schema\n\nThis file tells KiroGraph's LLM how to structure and maintain the project wiki.\nEdit it to match your project's conventions.\n\n## Naming convention\n\n- Entities (classes, services, modules): \\`<ClassName>.md\\` or \\`<module-name>.md\\`\n- Architecture decisions: \\`arch/<slug>.md\\`\n- Recurring patterns: \\`pattern/<slug>.md\\`\n- External integrations: \\`ext/<service>.md\\`\n\n## Page structure\n\nEvery page should follow this template:\n\n\\`\\`\\`markdown\n## Summary\nOne to three sentences describing what this entity is and why it exists.\n\n## Decisions\n- YYYY-MM-DD \u2014 Decision text (one line per decision, newest first)\n\n## Known Issues / Gotchas\n- Bullet points of non-obvious constraints, bugs, or workarounds\n\n## Related\n- [[other-page-slug]] \u2014 one line description of the relationship\n\n## Sources\n- source-name (YYYY-MM-DD)\n\\`\\`\\`\n\n## Ingest workflow\n\nWhen given a source document to ingest:\n\n1. Read the source and identify entities, decisions, and patterns mentioned\n2. Check MANIFEST.md to find existing pages for those entities\n3. For each existing page: integrate new information into the appropriate sections\n4. For each new entity: create a page following the structure above\n5. Always update ## Sources with the source name and today's date\n6. Update ## Related cross-references in all touched pages\n7. If new information contradicts an existing claim, emit a WIKI_DIFF_CONFLICTS block\n\n## WIKI_DIFF format\n\nProduce output using this exact format \u2014 one block per page operation:\n\n\\`\\`\\`\nWIKI_DIFF_START\n{\"action\":\"upsert\",\"page\":\"PageSlug\",\"section\":\"Decisions\",\"mode\":\"append\"}\n- YYYY-MM-DD \u2014 New decision text\nWIKI_DIFF_END\n\\`\\`\\`\n\nActions:\n- \\`create\\` \u2014 new page (requires \\`title\\` field, content is full markdown)\n- \\`upsert\\` \u2014 update a section in an existing page (mode: \\`append\\` or \\`replace\\`)\n- \\`append\\` \u2014 append to the end of an existing page\n\nFor conflicts:\n\\`\\`\\`\nWIKI_DIFF_CONFLICTS\n{\"page\":\"PageSlug\",\"section\":\"SectionName\",\"existing\":\"old claim\",\"incoming\":\"new claim\",\"source\":\"ADR-001.md\",\"existingDate\":\"2025-01-01\",\"incomingDate\":\"2025-06-15\"}\nWIKI_DIFF_CONFLICTS_END\n\\`\\`\\`\n`;\n\n// \u2500\u2500 WIKI_DIFF parser \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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\nimport type { WikiDiff, WikiDiffEntry, WikiDiffConflict } from './types';\n\nexport function parseWikiDiff(raw: string): WikiDiff {\n const entries: WikiDiffEntry[] = [];\n const conflicts: WikiDiffConflict[] = [];\n\n // Parse WIKI_DIFF_START...WIKI_DIFF_END blocks\n const diffRegex = /WIKI_DIFF_START\\n([\\s\\S]*?)\\nWIKI_DIFF_END/g;\n let match: RegExpExecArray | null;\n\n while ((match = diffRegex.exec(raw)) !== null) {\n const block = match[1].trim();\n const firstNewline = block.indexOf('\\n');\n if (firstNewline === -1) continue;\n\n const headerStr = block.slice(0, firstNewline).trim();\n const content = block.slice(firstNewline + 1);\n\n let header: Record<string, any>;\n try {\n header = JSON.parse(headerStr);\n } catch {\n continue;\n }\n\n entries.push({\n action: header.action ?? 'upsert',\n page: header.page ?? '',\n title: header.title,\n section: header.section,\n mode: header.mode ?? 'append',\n content,\n });\n }\n\n // Parse WIKI_DIFF_CONFLICTS...WIKI_DIFF_CONFLICTS_END blocks\n const conflictRegex = /WIKI_DIFF_CONFLICTS\\n([\\s\\S]*?)\\nWIKI_DIFF_CONFLICTS_END/g;\n\n while ((match = conflictRegex.exec(raw)) !== null) {\n const block = match[1].trim();\n for (const line of block.split('\\n')) {\n const trimmed = line.trim();\n if (!trimmed) continue;\n try {\n const c = JSON.parse(trimmed);\n conflicts.push({\n page: c.page ?? '',\n section: c.section ?? '',\n existing: c.existing ?? '',\n incoming: c.incoming ?? '',\n source: c.source ?? '',\n existingDate: c.existingDate,\n incomingDate: c.incomingDate,\n });\n } catch {\n continue;\n }\n }\n }\n\n return { entries, conflicts, rawDiff: raw };\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAEO,MAAM,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAyEvB,SAAS,cAAc,KAAuB;AACnD,QAAM,UAA2B,CAAC;AAClC,QAAM,YAAgC,CAAC;AAGvC,QAAM,YAAY;AAClB,MAAI;AAEJ,UAAQ,QAAQ,UAAU,KAAK,GAAG,OAAO,MAAM;AAC7C,UAAM,QAAQ,MAAM,CAAC,EAAE,KAAK;AAC5B,UAAM,eAAe,MAAM,QAAQ,IAAI;AACvC,QAAI,iBAAiB,GAAI;AAEzB,UAAM,YAAY,MAAM,MAAM,GAAG,YAAY,EAAE,KAAK;AACpD,UAAM,UAAU,MAAM,MAAM,eAAe,CAAC;AAE5C,QAAI;AACJ,QAAI;AACF,eAAS,KAAK,MAAM,SAAS;AAAA,IAC/B,QAAQ;AACN;AAAA,IACF;AAEA,YAAQ,KAAK;AAAA,MACX,QAAQ,OAAO,UAAU;AAAA,MACzB,MAAM,OAAO,QAAQ;AAAA,MACrB,OAAO,OAAO;AAAA,MACd,SAAS,OAAO;AAAA,MAChB,MAAM,OAAO,QAAQ;AAAA,MACrB;AAAA,IACF,CAAC;AAAA,EACH;AAGA,QAAM,gBAAgB;AAEtB,UAAQ,QAAQ,cAAc,KAAK,GAAG,OAAO,MAAM;AACjD,UAAM,QAAQ,MAAM,CAAC,EAAE,KAAK;AAC5B,eAAW,QAAQ,MAAM,MAAM,IAAI,GAAG;AACpC,YAAM,UAAU,KAAK,KAAK;AAC1B,UAAI,CAAC,QAAS;AACd,UAAI;AACF,cAAM,IAAI,KAAK,MAAM,OAAO;AAC5B,kBAAU,KAAK;AAAA,UACb,MAAM,EAAE,QAAQ;AAAA,UAChB,SAAS,EAAE,WAAW;AAAA,UACtB,UAAU,EAAE,YAAY;AAAA,UACxB,UAAU,EAAE,YAAY;AAAA,UACxB,QAAQ,EAAE,UAAU;AAAA,UACpB,cAAc,EAAE;AAAA,UAChB,cAAc,EAAE;AAAA,QAClB,CAAC;AAAA,MACH,QAAQ;AACN;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO,EAAE,SAAS,WAAW,SAAS,IAAI;AAC5C;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var synthesize_exports = {};
|
|
20
|
+
__export(synthesize_exports, {
|
|
21
|
+
runWikiLocalSynthesis: () => runWikiLocalSynthesis
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(synthesize_exports);
|
|
24
|
+
var import_synthesize = require("../watchmen/synthesize");
|
|
25
|
+
const SYSTEM_PROMPT = `You are a project wiki assistant. You receive a source text and a wiki schema, and you produce structured WIKI_DIFF blocks.
|
|
26
|
+
|
|
27
|
+
Rules:
|
|
28
|
+
- Output ONLY WIKI_DIFF_START / WIKI_DIFF_END blocks. No explanations, no prose.
|
|
29
|
+
- Follow the schema exactly \u2014 use the JSON header format shown.
|
|
30
|
+
- Use "page" field (not "slug") in the JSON header.
|
|
31
|
+
- Keep page slugs lowercase-kebab-case.
|
|
32
|
+
- Copy technical terms, function names, and identifiers exactly as they appear in the source.
|
|
33
|
+
- If the source contradicts an existing page, add a WIKI_DIFF_CONFLICTS block.`;
|
|
34
|
+
function isGemma4(modelName) {
|
|
35
|
+
return modelName.includes("gemma-4");
|
|
36
|
+
}
|
|
37
|
+
async function generate(pipe, userPrompt, modelName, quiet) {
|
|
38
|
+
const messages = [
|
|
39
|
+
{ role: "system", content: SYSTEM_PROMPT },
|
|
40
|
+
{ role: "user", content: userPrompt }
|
|
41
|
+
];
|
|
42
|
+
const genOpts = {
|
|
43
|
+
max_new_tokens: 600,
|
|
44
|
+
return_full_text: false
|
|
45
|
+
};
|
|
46
|
+
if (isGemma4(modelName)) {
|
|
47
|
+
genOpts.temperature = 1;
|
|
48
|
+
genOpts.top_p = 0.95;
|
|
49
|
+
genOpts.top_k = 64;
|
|
50
|
+
genOpts.do_sample = true;
|
|
51
|
+
} else {
|
|
52
|
+
genOpts.do_sample = false;
|
|
53
|
+
genOpts.repetition_penalty = 1.3;
|
|
54
|
+
}
|
|
55
|
+
const output = await pipe(messages, genOpts);
|
|
56
|
+
let text;
|
|
57
|
+
if (Array.isArray(output) && output[0]?.generated_text) {
|
|
58
|
+
const gt = output[0].generated_text;
|
|
59
|
+
text = Array.isArray(gt) ? gt[gt.length - 1]?.content ?? "" : String(gt);
|
|
60
|
+
} else {
|
|
61
|
+
text = String(output);
|
|
62
|
+
}
|
|
63
|
+
return (0, import_synthesize.removeHallucinatedContent)((0, import_synthesize.truncateAtRepetitionLoop)((0, import_synthesize.stripCodeFences)(text)));
|
|
64
|
+
}
|
|
65
|
+
async function runWikiLocalSynthesis(wiki, modelName, quiet = false) {
|
|
66
|
+
const result = {
|
|
67
|
+
processed: 0,
|
|
68
|
+
created: [],
|
|
69
|
+
updated: [],
|
|
70
|
+
errors: []
|
|
71
|
+
};
|
|
72
|
+
const queue = wiki.getPendingQueue();
|
|
73
|
+
if (queue.length === 0) return result;
|
|
74
|
+
if (!quiet) process.stderr.write(`[wiki] Loading model ${modelName}...
|
|
75
|
+
`);
|
|
76
|
+
const pipe = await (0, import_synthesize.getGenPipeline)(modelName, quiet);
|
|
77
|
+
for (const entry of queue) {
|
|
78
|
+
if (!quiet) process.stderr.write(`[wiki] Synthesizing source "${entry.sourceName}"...
|
|
79
|
+
`);
|
|
80
|
+
try {
|
|
81
|
+
const prompt = wiki.getIngestPrompt(entry.sourceText, entry.sourceName);
|
|
82
|
+
const raw = await generate(pipe, prompt, modelName, quiet);
|
|
83
|
+
if (!raw.includes("WIKI_DIFF_START")) {
|
|
84
|
+
if (!quiet) process.stderr.write(`[wiki] No WIKI_DIFF found for "${entry.sourceName}" \u2014 skipping
|
|
85
|
+
`);
|
|
86
|
+
result.errors.push(`No WIKI_DIFF produced for source "${entry.sourceName}"`);
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
const applyResult = wiki.applyDiff(raw);
|
|
90
|
+
result.created.push(...applyResult.created);
|
|
91
|
+
result.updated.push(...applyResult.updated);
|
|
92
|
+
result.processed++;
|
|
93
|
+
} catch (e) {
|
|
94
|
+
result.errors.push(`Error processing "${entry.sourceName}": ${e?.message ?? e}`);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
wiki.clearQueue();
|
|
98
|
+
return result;
|
|
99
|
+
}
|
|
100
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
101
|
+
0 && (module.exports = {
|
|
102
|
+
runWikiLocalSynthesis
|
|
103
|
+
});
|
|
104
|
+
//# sourceMappingURL=synthesize.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/wiki/synthesize.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * KiroGraph Wiki \u2014 Local model synthesis\n *\n * Reads the pending wiki_queue, runs a local HuggingFace model to produce\n * WIKI_DIFF blocks for each queued source, then applies them.\n * Mirrors the watchmen local synthesis pattern.\n */\n\nimport {\n getGenPipeline,\n stripCodeFences,\n removeHallucinatedContent,\n truncateAtRepetitionLoop,\n} from '../watchmen/synthesize';\nimport type { KiroGraphWiki } from './index';\n\nexport interface WikiSynthesisResult {\n processed: number;\n created: string[];\n updated: string[];\n errors: string[];\n}\n\nconst SYSTEM_PROMPT = `You are a project wiki assistant. You receive a source text and a wiki schema, and you produce structured WIKI_DIFF blocks.\n\nRules:\n- Output ONLY WIKI_DIFF_START / WIKI_DIFF_END blocks. No explanations, no prose.\n- Follow the schema exactly \u2014 use the JSON header format shown.\n- Use \"page\" field (not \"slug\") in the JSON header.\n- Keep page slugs lowercase-kebab-case.\n- Copy technical terms, function names, and identifiers exactly as they appear in the source.\n- If the source contradicts an existing page, add a WIKI_DIFF_CONFLICTS block.`;\n\nfunction isGemma4(modelName: string): boolean {\n return modelName.includes('gemma-4');\n}\n\nasync function generate(\n pipe: any,\n userPrompt: string,\n modelName: string,\n quiet: boolean,\n): Promise<string> {\n const messages = [\n { role: 'system', content: SYSTEM_PROMPT },\n { role: 'user', content: userPrompt },\n ];\n\n const genOpts: any = {\n max_new_tokens: 600,\n return_full_text: false,\n };\n\n if (isGemma4(modelName)) {\n genOpts.temperature = 1.0;\n genOpts.top_p = 0.95;\n genOpts.top_k = 64;\n genOpts.do_sample = true;\n } else {\n genOpts.do_sample = false;\n genOpts.repetition_penalty = 1.3;\n }\n\n const output = await pipe(messages, genOpts);\n\n let text: string;\n if (Array.isArray(output) && output[0]?.generated_text) {\n const gt = output[0].generated_text;\n text = Array.isArray(gt) ? gt[gt.length - 1]?.content ?? '' : String(gt);\n } else {\n text = String(output);\n }\n\n return removeHallucinatedContent(truncateAtRepetitionLoop(stripCodeFences(text)));\n}\n\nexport async function runWikiLocalSynthesis(\n wiki: KiroGraphWiki,\n modelName: string,\n quiet = false,\n): Promise<WikiSynthesisResult> {\n const result: WikiSynthesisResult = {\n processed: 0,\n created: [],\n updated: [],\n errors: [],\n };\n\n const queue = wiki.getPendingQueue();\n if (queue.length === 0) return result;\n\n if (!quiet) process.stderr.write(`[wiki] Loading model ${modelName}...\\n`);\n const pipe = await getGenPipeline(modelName, quiet);\n\n for (const entry of queue) {\n if (!quiet) process.stderr.write(`[wiki] Synthesizing source \"${entry.sourceName}\"...\\n`);\n try {\n const prompt = wiki.getIngestPrompt(entry.sourceText, entry.sourceName);\n const raw = await generate(pipe, prompt, modelName, quiet);\n\n if (!raw.includes('WIKI_DIFF_START')) {\n if (!quiet) process.stderr.write(`[wiki] No WIKI_DIFF found for \"${entry.sourceName}\" \u2014 skipping\\n`);\n result.errors.push(`No WIKI_DIFF produced for source \"${entry.sourceName}\"`);\n continue;\n }\n\n const applyResult = wiki.applyDiff(raw);\n result.created.push(...applyResult.created);\n result.updated.push(...applyResult.updated);\n result.processed++;\n } catch (e: any) {\n result.errors.push(`Error processing \"${entry.sourceName}\": ${e?.message ?? e}`);\n }\n }\n\n wiki.clearQueue();\n return result;\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAQA,wBAKO;AAUP,MAAM,gBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAUtB,SAAS,SAAS,WAA4B;AAC5C,SAAO,UAAU,SAAS,SAAS;AACrC;AAEA,eAAe,SACb,MACA,YACA,WACA,OACiB;AACjB,QAAM,WAAW;AAAA,IACf,EAAE,MAAM,UAAU,SAAS,cAAc;AAAA,IACzC,EAAE,MAAM,QAAQ,SAAS,WAAW;AAAA,EACtC;AAEA,QAAM,UAAe;AAAA,IACnB,gBAAgB;AAAA,IAChB,kBAAkB;AAAA,EACpB;AAEA,MAAI,SAAS,SAAS,GAAG;AACvB,YAAQ,cAAc;AACtB,YAAQ,QAAQ;AAChB,YAAQ,QAAQ;AAChB,YAAQ,YAAY;AAAA,EACtB,OAAO;AACL,YAAQ,YAAY;AACpB,YAAQ,qBAAqB;AAAA,EAC/B;AAEA,QAAM,SAAS,MAAM,KAAK,UAAU,OAAO;AAE3C,MAAI;AACJ,MAAI,MAAM,QAAQ,MAAM,KAAK,OAAO,CAAC,GAAG,gBAAgB;AACtD,UAAM,KAAK,OAAO,CAAC,EAAE;AACrB,WAAO,MAAM,QAAQ,EAAE,IAAI,GAAG,GAAG,SAAS,CAAC,GAAG,WAAW,KAAK,OAAO,EAAE;AAAA,EACzE,OAAO;AACL,WAAO,OAAO,MAAM;AAAA,EACtB;AAEA,aAAO,iDAA0B,gDAAyB,mCAAgB,IAAI,CAAC,CAAC;AAClF;AAEA,eAAsB,sBACpB,MACA,WACA,QAAQ,OACsB;AAC9B,QAAM,SAA8B;AAAA,IAClC,WAAW;AAAA,IACX,SAAS,CAAC;AAAA,IACV,SAAS,CAAC;AAAA,IACV,QAAQ,CAAC;AAAA,EACX;AAEA,QAAM,QAAQ,KAAK,gBAAgB;AACnC,MAAI,MAAM,WAAW,EAAG,QAAO;AAE/B,MAAI,CAAC,MAAO,SAAQ,OAAO,MAAM,wBAAwB,SAAS;AAAA,CAAO;AACzE,QAAM,OAAO,UAAM,kCAAe,WAAW,KAAK;AAElD,aAAW,SAAS,OAAO;AACzB,QAAI,CAAC,MAAO,SAAQ,OAAO,MAAM,+BAA+B,MAAM,UAAU;AAAA,CAAQ;AACxF,QAAI;AACF,YAAM,SAAS,KAAK,gBAAgB,MAAM,YAAY,MAAM,UAAU;AACtE,YAAM,MAAM,MAAM,SAAS,MAAM,QAAQ,WAAW,KAAK;AAEzD,UAAI,CAAC,IAAI,SAAS,iBAAiB,GAAG;AACpC,YAAI,CAAC,MAAO,SAAQ,OAAO,MAAM,kCAAkC,MAAM,UAAU;AAAA,CAAgB;AACnG,eAAO,OAAO,KAAK,qCAAqC,MAAM,UAAU,GAAG;AAC3E;AAAA,MACF;AAEA,YAAM,cAAc,KAAK,UAAU,GAAG;AACtC,aAAO,QAAQ,KAAK,GAAG,YAAY,OAAO;AAC1C,aAAO,QAAQ,KAAK,GAAG,YAAY,OAAO;AAC1C,aAAO;AAAA,IACT,SAAS,GAAQ;AACf,aAAO,OAAO,KAAK,qBAAqB,MAAM,UAAU,MAAM,GAAG,WAAW,CAAC,EAAE;AAAA,IACjF;AAAA,EACF;AAEA,OAAK,WAAW;AAChB,SAAO;AACT;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __copyProps = (to, from, except, desc) => {
|
|
7
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
8
|
+
for (let key of __getOwnPropNames(from))
|
|
9
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
10
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
11
|
+
}
|
|
12
|
+
return to;
|
|
13
|
+
};
|
|
14
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
15
|
+
var types_exports = {};
|
|
16
|
+
module.exports = __toCommonJS(types_exports);
|
|
17
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/wiki/types.ts"],
|
|
4
|
+
"sourcesContent": ["// \u2500\u2500 WikiPage \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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\nexport interface WikiPage {\n slug: string;\n title: string;\n content: string;\n filePath: string;\n updatedAt: number;\n sourceCount: number;\n}\n\nexport interface ScoredWikiPage {\n page: WikiPage;\n score: number;\n}\n\n// \u2500\u2500 WIKI_DIFF types \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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\nexport type DiffAction = 'upsert' | 'create' | 'append';\nexport type DiffMode = 'replace' | 'append';\n\nexport interface WikiDiffEntry {\n action: DiffAction;\n page: string; // slug\n title?: string; // required for action=create\n section?: string; // target section heading (e.g. \"Decisions\")\n mode?: DiffMode; // for action=upsert: replace section or append to it\n content: string; // markdown content to write\n}\n\nexport interface WikiDiffConflict {\n page: string;\n section: string;\n existing: string;\n incoming: string;\n source: string;\n existingDate?: string; // ISO date string\n incomingDate?: string; // ISO date string\n}\n\nexport interface WikiDiff {\n entries: WikiDiffEntry[];\n conflicts: WikiDiffConflict[];\n rawDiff: string;\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\u2500\u2500\n\nexport type LintIssueKind = 'contradiction' | 'orphan' | 'stale' | 'broken_link';\n\nexport interface WikiLintIssue {\n kind: LintIssueKind;\n slug: string;\n detail: string;\n relatedSlug?: string;\n}\n\n// \u2500\u2500 Stats \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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\nexport interface WikiStats {\n pageCount: number;\n totalSources: number;\n oldestPage: number | null;\n newestPage: number | null;\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;AAAA;AAAA;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kirograph",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.27.0",
|
|
4
4
|
"description": "Semantic code knowledge graph for Kiro: fewer tool calls, instant symbol lookups, 100% local.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -24,6 +24,8 @@
|
|
|
24
24
|
"test:turboquant": "bash scripts/turboquant/test.sh",
|
|
25
25
|
"test:turbovec": "bash scripts/turbovec/test.sh",
|
|
26
26
|
"test:data": "bash scripts/data/test.sh",
|
|
27
|
+
"test:wiki": "bash scripts/wiki/test.sh",
|
|
28
|
+
"test:mem": "bash scripts/mem/test.sh",
|
|
27
29
|
"clean": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\"",
|
|
28
30
|
"release": "./scripts/release.sh",
|
|
29
31
|
"docs": "npx serve docs"
|
|
@@ -44,8 +46,7 @@
|
|
|
44
46
|
"parquetjs-lite": "^0.8.7",
|
|
45
47
|
"picomatch": "^4.0.3",
|
|
46
48
|
"tree-sitter-wasms": "^0.1.11",
|
|
47
|
-
"web-tree-sitter": "^0.25.3"
|
|
48
|
-
"xlsx": "^0.18.5"
|
|
49
|
+
"web-tree-sitter": "^0.25.3"
|
|
49
50
|
},
|
|
50
51
|
"optionalDependencies": {
|
|
51
52
|
"@ast-grep/lang-bash": "^0.0.8",
|
|
@@ -77,7 +78,8 @@
|
|
|
77
78
|
"sqlite-vec": "^0.1.9",
|
|
78
79
|
"turboquant-js": "^0.2.0",
|
|
79
80
|
"turbovec-node": "file:native/turbovec-node",
|
|
80
|
-
"typesense": "^3.0.6"
|
|
81
|
+
"typesense": "^3.0.6",
|
|
82
|
+
"xlsx": "^0.18.5"
|
|
81
83
|
},
|
|
82
84
|
"devDependencies": {
|
|
83
85
|
"@types/figlet": "^1.7.0",
|