@tangle-network/agent-knowledge 1.2.0 → 1.3.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/AGENTS.md +36 -0
- package/README.md +95 -0
- package/dist/{chunk-TXNYP4WI.js → chunk-4PNXQ2NT.js} +1 -1
- package/dist/chunk-4PNXQ2NT.js.map +1 -0
- package/dist/{chunk-JLCQ6O7W.js → chunk-HKYD765Q.js} +574 -441
- package/dist/chunk-HKYD765Q.js.map +1 -0
- package/dist/chunk-WCYW2GDA.js +551 -0
- package/dist/chunk-WCYW2GDA.js.map +1 -0
- package/dist/chunk-YMKHCTS2.js +19 -0
- package/dist/chunk-YMKHCTS2.js.map +1 -0
- package/dist/cli.js +77 -34
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +686 -406
- package/dist/index.js +591 -168
- package/dist/index.js.map +1 -1
- package/dist/sources/index.d.ts +386 -0
- package/dist/sources/index.js +34 -0
- package/dist/sources/index.js.map +1 -0
- package/dist/{types-DTUp66Gr.d.ts → types-CAeh7Lwb.d.ts} +1 -1
- package/dist/viz/index.d.ts +1 -1
- package/dist/viz/index.js +1 -1
- package/package.json +18 -12
- package/dist/chunk-JLCQ6O7W.js.map +0 -1
- package/dist/chunk-TXNYP4WI.js.map +0 -1
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// src/ids.ts
|
|
2
|
+
import { createHash } from "crypto";
|
|
3
|
+
function sha256(text) {
|
|
4
|
+
return createHash("sha256").update(text).digest("hex");
|
|
5
|
+
}
|
|
6
|
+
function slugify(input) {
|
|
7
|
+
const out = input.trim().toLowerCase().normalize("NFKD").replace(/[\u0300-\u036f]/g, "").replace(/[^a-z0-9\u4e00-\u9fff]+/g, "-").replace(/^-+|-+$/g, "");
|
|
8
|
+
return out || "untitled";
|
|
9
|
+
}
|
|
10
|
+
function stableId(prefix, content) {
|
|
11
|
+
return `${prefix}_${sha256(content).slice(0, 16)}`;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export {
|
|
15
|
+
sha256,
|
|
16
|
+
slugify,
|
|
17
|
+
stableId
|
|
18
|
+
};
|
|
19
|
+
//# sourceMappingURL=chunk-YMKHCTS2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/ids.ts"],"sourcesContent":["import { createHash } from 'node:crypto'\n\nexport function sha256(text: string): string {\n return createHash('sha256').update(text).digest('hex')\n}\n\nexport function slugify(input: string): string {\n const out = input\n .trim()\n .toLowerCase()\n .normalize('NFKD')\n .replace(/[\\u0300-\\u036f]/g, '')\n .replace(/[^a-z0-9\\u4e00-\\u9fff]+/g, '-')\n .replace(/^-+|-+$/g, '')\n return out || 'untitled'\n}\n\nexport function stableId(prefix: string, content: string): string {\n return `${prefix}_${sha256(content).slice(0, 16)}`\n}\n"],"mappings":";AAAA,SAAS,kBAAkB;AAEpB,SAAS,OAAO,MAAsB;AAC3C,SAAO,WAAW,QAAQ,EAAE,OAAO,IAAI,EAAE,OAAO,KAAK;AACvD;AAEO,SAAS,QAAQ,OAAuB;AAC7C,QAAM,MAAM,MACT,KAAK,EACL,YAAY,EACZ,UAAU,MAAM,EAChB,QAAQ,oBAAoB,EAAE,EAC9B,QAAQ,4BAA4B,GAAG,EACvC,QAAQ,YAAY,EAAE;AACzB,SAAO,OAAO;AAChB;AAEO,SAAS,SAAS,QAAgB,SAAyB;AAChE,SAAO,GAAG,MAAM,IAAI,OAAO,OAAO,EAAE,MAAM,GAAG,EAAE,CAAC;AAClD;","names":[]}
|
package/dist/cli.js
CHANGED
|
@@ -11,12 +11,13 @@ import {
|
|
|
11
11
|
searchKnowledge,
|
|
12
12
|
validateKnowledgeIndex,
|
|
13
13
|
writeKnowledgeIndex
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-HKYD765Q.js";
|
|
15
15
|
import {
|
|
16
16
|
detectKnowledgeGaps,
|
|
17
17
|
findSurprisingConnections,
|
|
18
18
|
toKnowledgeVizGraph
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-4PNXQ2NT.js";
|
|
20
|
+
import "./chunk-YMKHCTS2.js";
|
|
20
21
|
|
|
21
22
|
// src/cli.ts
|
|
22
23
|
import { existsSync, readFileSync } from "fs";
|
|
@@ -86,9 +87,13 @@ async function main() {
|
|
|
86
87
|
}
|
|
87
88
|
case "index": {
|
|
88
89
|
const index = await writeKnowledgeIndex(root);
|
|
89
|
-
if (args.flags.json === "true") process.stdout.write(JSON.stringify(index, null, 2)
|
|
90
|
-
else process.stdout.write(`indexed ${index.pages.length} pages, ${index.graph.edges.length} edges
|
|
90
|
+
if (args.flags.json === "true") process.stdout.write(`${JSON.stringify(index, null, 2)}
|
|
91
91
|
`);
|
|
92
|
+
else
|
|
93
|
+
process.stdout.write(
|
|
94
|
+
`indexed ${index.pages.length} pages, ${index.graph.edges.length} edges
|
|
95
|
+
`
|
|
96
|
+
);
|
|
92
97
|
return 0;
|
|
93
98
|
}
|
|
94
99
|
case "source-add": {
|
|
@@ -99,16 +104,20 @@ async function main() {
|
|
|
99
104
|
}
|
|
100
105
|
await initKnowledgeBase(root);
|
|
101
106
|
const sources = await addSourcePath(root, resolve(path));
|
|
102
|
-
if (args.flags.json === "true") process.stdout.write(JSON.stringify(sources, null, 2)
|
|
107
|
+
if (args.flags.json === "true") process.stdout.write(`${JSON.stringify(sources, null, 2)}
|
|
108
|
+
`);
|
|
103
109
|
else for (const source of sources) process.stdout.write(`${source.id} ${source.uri}
|
|
104
110
|
`);
|
|
105
111
|
return 0;
|
|
106
112
|
}
|
|
107
113
|
case "sources": {
|
|
108
114
|
const registry = await loadSourceRegistry(root);
|
|
109
|
-
if (args.flags.json === "true")
|
|
115
|
+
if (args.flags.json === "true")
|
|
116
|
+
process.stdout.write(`${JSON.stringify(registry.sources, null, 2)}
|
|
117
|
+
`);
|
|
110
118
|
else {
|
|
111
|
-
for (const source of registry.sources)
|
|
119
|
+
for (const source of registry.sources)
|
|
120
|
+
process.stdout.write(`${source.id} ${source.title ?? source.uri} ${source.uri}
|
|
112
121
|
`);
|
|
113
122
|
}
|
|
114
123
|
return 0;
|
|
@@ -122,7 +131,8 @@ async function main() {
|
|
|
122
131
|
await initKnowledgeBase(root);
|
|
123
132
|
const result = await applyKnowledgeWriteBlocksFile(root, resolve(proposalPath));
|
|
124
133
|
await writeKnowledgeIndex(root);
|
|
125
|
-
if (args.flags.json === "true") process.stdout.write(JSON.stringify(result, null, 2)
|
|
134
|
+
if (args.flags.json === "true") process.stdout.write(`${JSON.stringify(result, null, 2)}
|
|
135
|
+
`);
|
|
126
136
|
else {
|
|
127
137
|
for (const path of result.written) process.stdout.write(`wrote ${path}
|
|
128
138
|
`);
|
|
@@ -134,11 +144,16 @@ async function main() {
|
|
|
134
144
|
case "inspect": {
|
|
135
145
|
const index = await loadOrBuildIndex(root);
|
|
136
146
|
const inspection = inspectKnowledgeIndex(index);
|
|
137
|
-
if (args.flags.json === "true")
|
|
138
|
-
|
|
139
|
-
process.stdout.write(`pages=${inspection.pageCount} sources=${inspection.sourceCount} edges=${inspection.edgeCount} findings=${inspection.findingCount} blocking=${inspection.blockingFindingCount}
|
|
147
|
+
if (args.flags.json === "true")
|
|
148
|
+
process.stdout.write(`${JSON.stringify(inspection, null, 2)}
|
|
140
149
|
`);
|
|
141
|
-
|
|
150
|
+
else {
|
|
151
|
+
process.stdout.write(
|
|
152
|
+
`pages=${inspection.pageCount} sources=${inspection.sourceCount} edges=${inspection.edgeCount} findings=${inspection.findingCount} blocking=${inspection.blockingFindingCount}
|
|
153
|
+
`
|
|
154
|
+
);
|
|
155
|
+
for (const page of inspection.topPages.slice(0, 5))
|
|
156
|
+
process.stdout.write(`${page.degree} ${page.path} sources=${page.sources}
|
|
142
157
|
`);
|
|
143
158
|
}
|
|
144
159
|
return inspection.blockingFindingCount > 0 ? 2 : 0;
|
|
@@ -150,17 +165,21 @@ async function main() {
|
|
|
150
165
|
return 1;
|
|
151
166
|
}
|
|
152
167
|
const explanation = explainKnowledgeTarget(await loadOrBuildIndex(root), target);
|
|
153
|
-
if (args.flags.json === "true")
|
|
168
|
+
if (args.flags.json === "true")
|
|
169
|
+
process.stdout.write(`${JSON.stringify(explanation, null, 2)}
|
|
170
|
+
`);
|
|
154
171
|
else {
|
|
155
172
|
process.stdout.write(`${explanation.page ? explanation.page.title : target}
|
|
156
173
|
`);
|
|
157
|
-
for (const source of explanation.sources)
|
|
174
|
+
for (const source of explanation.sources)
|
|
175
|
+
process.stdout.write(`source ${source.id} ${source.title ?? source.uri}
|
|
158
176
|
`);
|
|
159
177
|
for (const link of explanation.links) process.stdout.write(`out ${link}
|
|
160
178
|
`);
|
|
161
179
|
for (const inbound of explanation.inbound) process.stdout.write(`in ${inbound}
|
|
162
180
|
`);
|
|
163
|
-
for (const related of explanation.related.slice(0, 5))
|
|
181
|
+
for (const related of explanation.related.slice(0, 5))
|
|
182
|
+
process.stdout.write(`related ${related.path} score=${related.score.toFixed(5)}
|
|
164
183
|
`);
|
|
165
184
|
}
|
|
166
185
|
return 0;
|
|
@@ -174,11 +193,14 @@ async function main() {
|
|
|
174
193
|
const index = await loadOrBuildIndex(root);
|
|
175
194
|
const results = searchKnowledge(index, query, Number(args.flags.limit ?? 10));
|
|
176
195
|
if (args.flags.json === "true") {
|
|
177
|
-
process.stdout.write(JSON.stringify(results, null, 2)
|
|
196
|
+
process.stdout.write(`${JSON.stringify(results, null, 2)}
|
|
197
|
+
`);
|
|
178
198
|
} else {
|
|
179
199
|
for (const result of results) {
|
|
180
|
-
process.stdout.write(
|
|
181
|
-
|
|
200
|
+
process.stdout.write(
|
|
201
|
+
`${result.rank}. ${result.page.title} (${result.page.path}) score=${result.score.toFixed(5)}
|
|
202
|
+
`
|
|
203
|
+
);
|
|
182
204
|
if (result.snippet) process.stdout.write(` ${result.snippet}
|
|
183
205
|
`);
|
|
184
206
|
}
|
|
@@ -187,31 +209,45 @@ async function main() {
|
|
|
187
209
|
}
|
|
188
210
|
case "graph": {
|
|
189
211
|
const index = await loadOrBuildIndex(root);
|
|
190
|
-
if ((args.flags.format ?? "summary") === "json")
|
|
191
|
-
|
|
212
|
+
if ((args.flags.format ?? "summary") === "json")
|
|
213
|
+
process.stdout.write(`${JSON.stringify(index.graph, null, 2)}
|
|
192
214
|
`);
|
|
215
|
+
else
|
|
216
|
+
process.stdout.write(
|
|
217
|
+
`nodes=${index.graph.nodes.length} edges=${index.graph.edges.length}
|
|
218
|
+
`
|
|
219
|
+
);
|
|
193
220
|
return 0;
|
|
194
221
|
}
|
|
195
222
|
case "lint": {
|
|
196
223
|
const index = await loadOrBuildIndex(root);
|
|
197
224
|
const findings = lintKnowledgeIndex(index);
|
|
198
|
-
if (args.flags.json === "true") process.stdout.write(JSON.stringify(findings, null, 2)
|
|
225
|
+
if (args.flags.json === "true") process.stdout.write(`${JSON.stringify(findings, null, 2)}
|
|
226
|
+
`);
|
|
199
227
|
else {
|
|
200
228
|
if (findings.length === 0) process.stdout.write("no findings\n");
|
|
201
229
|
for (const finding of findings) {
|
|
202
|
-
process.stdout.write(
|
|
203
|
-
`
|
|
230
|
+
process.stdout.write(
|
|
231
|
+
`${finding.severity.toUpperCase()} ${finding.type}${finding.page ? ` ${finding.page}` : ""}: ${finding.message}
|
|
232
|
+
`
|
|
233
|
+
);
|
|
204
234
|
}
|
|
205
235
|
}
|
|
206
236
|
return findings.some((finding) => finding.severity === "error") ? 2 : 0;
|
|
207
237
|
}
|
|
208
238
|
case "validate": {
|
|
209
|
-
const result = validateKnowledgeIndex(await loadOrBuildIndex(root), {
|
|
210
|
-
|
|
239
|
+
const result = validateKnowledgeIndex(await loadOrBuildIndex(root), {
|
|
240
|
+
strict: args.flags.strict === "true"
|
|
241
|
+
});
|
|
242
|
+
if (args.flags.json === "true") process.stdout.write(`${JSON.stringify(result, null, 2)}
|
|
243
|
+
`);
|
|
211
244
|
else {
|
|
212
245
|
process.stdout.write(result.ok ? "valid\n" : "invalid\n");
|
|
213
|
-
for (const finding of result.findings)
|
|
214
|
-
|
|
246
|
+
for (const finding of result.findings)
|
|
247
|
+
process.stdout.write(
|
|
248
|
+
`${finding.severity.toUpperCase()} ${finding.type}${finding.page ? ` ${finding.page}` : ""}: ${finding.message}
|
|
249
|
+
`
|
|
250
|
+
);
|
|
215
251
|
}
|
|
216
252
|
return result.ok ? 0 : 2;
|
|
217
253
|
}
|
|
@@ -222,7 +258,8 @@ async function main() {
|
|
|
222
258
|
process.stderr.write("export currently supports --format json\n");
|
|
223
259
|
return 1;
|
|
224
260
|
}
|
|
225
|
-
process.stdout.write(JSON.stringify(index, null, 2)
|
|
261
|
+
process.stdout.write(`${JSON.stringify(index, null, 2)}
|
|
262
|
+
`);
|
|
226
263
|
return 0;
|
|
227
264
|
}
|
|
228
265
|
case "viz": {
|
|
@@ -233,10 +270,13 @@ async function main() {
|
|
|
233
270
|
gaps: detectKnowledgeGaps(viz),
|
|
234
271
|
surprisingConnections: findSurprisingConnections(viz)
|
|
235
272
|
};
|
|
236
|
-
if (args.flags.json === "true") process.stdout.write(JSON.stringify(payload, null, 2)
|
|
237
|
-
else {
|
|
238
|
-
process.stdout.write(`communities=${viz.communities.length} gaps=${payload.gaps.length} surprising=${payload.surprisingConnections.length}
|
|
273
|
+
if (args.flags.json === "true") process.stdout.write(`${JSON.stringify(payload, null, 2)}
|
|
239
274
|
`);
|
|
275
|
+
else {
|
|
276
|
+
process.stdout.write(
|
|
277
|
+
`communities=${viz.communities.length} gaps=${payload.gaps.length} surprising=${payload.surprisingConnections.length}
|
|
278
|
+
`
|
|
279
|
+
);
|
|
240
280
|
}
|
|
241
281
|
return 0;
|
|
242
282
|
}
|
|
@@ -259,12 +299,15 @@ ${HELP}`);
|
|
|
259
299
|
}
|
|
260
300
|
async function loadOrBuildIndex(root) {
|
|
261
301
|
const path = join(layoutFor(root).cacheDir, "index.json");
|
|
262
|
-
if (existsSync(path))
|
|
302
|
+
if (existsSync(path))
|
|
303
|
+
return JSON.parse(readFileSync(path, "utf8"));
|
|
263
304
|
return await writeKnowledgeIndex(root);
|
|
264
305
|
}
|
|
265
306
|
main().then((code) => process.exit(code)).catch((err) => {
|
|
266
|
-
process.stderr.write(
|
|
267
|
-
`)
|
|
307
|
+
process.stderr.write(
|
|
308
|
+
`agent-knowledge error: ${err instanceof Error ? err.stack ?? err.message : String(err)}
|
|
309
|
+
`
|
|
310
|
+
);
|
|
268
311
|
process.exit(1);
|
|
269
312
|
});
|
|
270
313
|
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { existsSync, readFileSync } from 'node:fs'\nimport { join, resolve } from 'node:path'\n\nimport { buildKnowledgeIndex, writeKnowledgeIndex } from './indexer'\nimport { explainKnowledgeTarget, inspectKnowledgeIndex } from './inspect'\nimport { lintKnowledgeIndex } from './lint'\nimport { applyKnowledgeWriteBlocksFile } from './proposals'\nimport { searchKnowledge } from './search'\nimport { addSourcePath, loadSourceRegistry } from './sources'\nimport { initKnowledgeBase, layoutFor } from './store'\nimport { validateKnowledgeIndex } from './validate'\nimport { detectKnowledgeGaps, findSurprisingConnections, toKnowledgeVizGraph } from './viz/index'\n\ninterface Args {\n command: string\n positional: string[]\n flags: Record<string, string>\n}\n\nfunction parseArgs(argv: string[]): Args {\n const [command, ...rest] = argv\n const positional: string[] = []\n const flags: Record<string, string> = {}\n for (let i = 0; i < rest.length; i++) {\n const token = rest[i]!\n if (token.startsWith('--')) {\n const key = token.slice(2)\n const next = rest[i + 1]\n if (next && !next.startsWith('--')) {\n flags[key] = next\n i++\n } else {\n flags[key] = 'true'\n }\n } else {\n positional.push(token)\n }\n }\n return { command: command ?? 'help', positional, flags }\n}\n\nconst HELP = `agent-knowledge — source-grounded knowledge graph CLI.\n\nCommands:\n init [--root .]\n Create raw/sources, knowledge, and cache directories.\n index [--root .] [--json]\n Build .agent-knowledge/index.json from knowledge/**/*.md.\n source-add <path> [--root .] [--json]\n Copy a file or directory into raw/sources and register immutable source records.\n sources [--root .] [--json]\n List registered sources.\n apply-write-blocks <proposal-file> [--root .] [--json]\n Apply safe ---FILE: knowledge/...--- blocks emitted by an agent.\n inspect [--root .] [--json]\n Summarize page/source/edge counts, top pages, and lint state.\n explain <page|id|query> [--root .] [--json]\n Explain sources, links, inbound links, and related pages.\n search <query> [--root .] [--limit 10] [--json]\n Fast local token+graph search over the generated knowledge index.\n graph [--root .] [--format summary|json]\n Emit graph summary or JSON.\n lint [--root .] [--json]\n Run deterministic structural lint.\n validate [--root .] [--strict] [--json]\n Run schema + lint validation. Exits non-zero on blocking findings.\n export [--root .] [--format json]\n Export the current index.\n viz [--root .] [--json]\n Emit graph gaps and surprising connections.\n version\n Print package version.\n`\n\nasync function main(): Promise<number> {\n const args = parseArgs(process.argv.slice(2))\n const root = resolve(args.flags.root ?? '.')\n switch (args.command) {\n case 'init': {\n const layout = await initKnowledgeBase(root)\n process.stdout.write(`initialized knowledge base at ${layout.root}\\n`)\n return 0\n }\n case 'index': {\n const index = await writeKnowledgeIndex(root)\n if (args.flags.json === 'true') process.stdout.write(JSON.stringify(index, null, 2) + '\\n')\n else process.stdout.write(`indexed ${index.pages.length} pages, ${index.graph.edges.length} edges\\n`)\n return 0\n }\n case 'source-add': {\n const [path] = args.positional\n if (!path) {\n process.stderr.write('source-add requires a file or directory path\\n')\n return 1\n }\n await initKnowledgeBase(root)\n const sources = await addSourcePath(root, resolve(path))\n if (args.flags.json === 'true') process.stdout.write(JSON.stringify(sources, null, 2) + '\\n')\n else for (const source of sources) process.stdout.write(`${source.id} ${source.uri}\\n`)\n return 0\n }\n case 'sources': {\n const registry = await loadSourceRegistry(root)\n if (args.flags.json === 'true') process.stdout.write(JSON.stringify(registry.sources, null, 2) + '\\n')\n else {\n for (const source of registry.sources) process.stdout.write(`${source.id} ${source.title ?? source.uri} ${source.uri}\\n`)\n }\n return 0\n }\n case 'apply-write-blocks': {\n const [proposalPath] = args.positional\n if (!proposalPath) {\n process.stderr.write('apply-write-blocks requires a proposal file\\n')\n return 1\n }\n await initKnowledgeBase(root)\n const result = await applyKnowledgeWriteBlocksFile(root, resolve(proposalPath))\n await writeKnowledgeIndex(root)\n if (args.flags.json === 'true') process.stdout.write(JSON.stringify(result, null, 2) + '\\n')\n else {\n for (const path of result.written) process.stdout.write(`wrote ${path}\\n`)\n for (const warning of result.warnings) process.stderr.write(`warning: ${warning}\\n`)\n }\n return result.warnings.length > 0 ? 2 : 0\n }\n case 'inspect': {\n const index = await loadOrBuildIndex(root)\n const inspection = inspectKnowledgeIndex(index)\n if (args.flags.json === 'true') process.stdout.write(JSON.stringify(inspection, null, 2) + '\\n')\n else {\n process.stdout.write(`pages=${inspection.pageCount} sources=${inspection.sourceCount} edges=${inspection.edgeCount} findings=${inspection.findingCount} blocking=${inspection.blockingFindingCount}\\n`)\n for (const page of inspection.topPages.slice(0, 5)) process.stdout.write(`${page.degree} ${page.path} sources=${page.sources}\\n`)\n }\n return inspection.blockingFindingCount > 0 ? 2 : 0\n }\n case 'explain': {\n const target = args.positional.join(' ')\n if (!target) {\n process.stderr.write('explain requires a page path, id, title, or query\\n')\n return 1\n }\n const explanation = explainKnowledgeTarget(await loadOrBuildIndex(root), target)\n if (args.flags.json === 'true') process.stdout.write(JSON.stringify(explanation, null, 2) + '\\n')\n else {\n process.stdout.write(`${explanation.page ? explanation.page.title : target}\\n`)\n for (const source of explanation.sources) process.stdout.write(`source ${source.id} ${source.title ?? source.uri}\\n`)\n for (const link of explanation.links) process.stdout.write(`out ${link}\\n`)\n for (const inbound of explanation.inbound) process.stdout.write(`in ${inbound}\\n`)\n for (const related of explanation.related.slice(0, 5)) process.stdout.write(`related ${related.path} score=${related.score.toFixed(5)}\\n`)\n }\n return 0\n }\n case 'search': {\n const query = args.positional.join(' ')\n if (!query) {\n process.stderr.write('search requires a query\\n')\n return 1\n }\n const index = await loadOrBuildIndex(root)\n const results = searchKnowledge(index, query, Number(args.flags.limit ?? 10))\n if (args.flags.json === 'true') {\n process.stdout.write(JSON.stringify(results, null, 2) + '\\n')\n } else {\n for (const result of results) {\n process.stdout.write(`${result.rank}. ${result.page.title} (${result.page.path}) score=${result.score.toFixed(5)}\\n`)\n if (result.snippet) process.stdout.write(` ${result.snippet}\\n`)\n }\n }\n return 0\n }\n case 'graph': {\n const index = await loadOrBuildIndex(root)\n if ((args.flags.format ?? 'summary') === 'json') process.stdout.write(JSON.stringify(index.graph, null, 2) + '\\n')\n else process.stdout.write(`nodes=${index.graph.nodes.length} edges=${index.graph.edges.length}\\n`)\n return 0\n }\n case 'lint': {\n const index = await loadOrBuildIndex(root)\n const findings = lintKnowledgeIndex(index)\n if (args.flags.json === 'true') process.stdout.write(JSON.stringify(findings, null, 2) + '\\n')\n else {\n if (findings.length === 0) process.stdout.write('no findings\\n')\n for (const finding of findings) {\n process.stdout.write(`${finding.severity.toUpperCase()} ${finding.type}${finding.page ? ` ${finding.page}` : ''}: ${finding.message}\\n`)\n }\n }\n return findings.some((finding) => finding.severity === 'error') ? 2 : 0\n }\n case 'validate': {\n const result = validateKnowledgeIndex(await loadOrBuildIndex(root), { strict: args.flags.strict === 'true' })\n if (args.flags.json === 'true') process.stdout.write(JSON.stringify(result, null, 2) + '\\n')\n else {\n process.stdout.write(result.ok ? 'valid\\n' : 'invalid\\n')\n for (const finding of result.findings) process.stdout.write(`${finding.severity.toUpperCase()} ${finding.type}${finding.page ? ` ${finding.page}` : ''}: ${finding.message}\\n`)\n }\n return result.ok ? 0 : 2\n }\n case 'export': {\n const index = await loadOrBuildIndex(root)\n const format = args.flags.format ?? 'json'\n if (format !== 'json') {\n process.stderr.write('export currently supports --format json\\n')\n return 1\n }\n process.stdout.write(JSON.stringify(index, null, 2) + '\\n')\n return 0\n }\n case 'viz': {\n const index = await loadOrBuildIndex(root)\n const viz = toKnowledgeVizGraph(index.graph)\n const payload = {\n graph: viz,\n gaps: detectKnowledgeGaps(viz),\n surprisingConnections: findSurprisingConnections(viz),\n }\n if (args.flags.json === 'true') process.stdout.write(JSON.stringify(payload, null, 2) + '\\n')\n else {\n process.stdout.write(`communities=${viz.communities.length} gaps=${payload.gaps.length} surprising=${payload.surprisingConnections.length}\\n`)\n }\n return 0\n }\n case 'version': {\n const pkg = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8')) as { version: string }\n process.stdout.write(`${pkg.version}\\n`)\n return 0\n }\n case 'help':\n case '--help':\n case '-h':\n process.stdout.write(HELP)\n return 0\n default:\n process.stderr.write(`unknown command: ${args.command}\\n${HELP}`)\n return 1\n }\n}\n\nasync function loadOrBuildIndex(root: string) {\n const path = join(layoutFor(root).cacheDir, 'index.json')\n if (existsSync(path)) return JSON.parse(readFileSync(path, 'utf8')) as Awaited<ReturnType<typeof buildKnowledgeIndex>>\n return await writeKnowledgeIndex(root)\n}\n\nmain()\n .then((code) => process.exit(code))\n .catch((err) => {\n process.stderr.write(`agent-knowledge error: ${err instanceof Error ? err.stack ?? err.message : String(err)}\\n`)\n process.exit(1)\n })\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { existsSync, readFileSync } from 'node:fs'\nimport { join, resolve } from 'node:path'\n\nimport { type buildKnowledgeIndex, writeKnowledgeIndex } from './indexer'\nimport { explainKnowledgeTarget, inspectKnowledgeIndex } from './inspect'\nimport { lintKnowledgeIndex } from './lint'\nimport { applyKnowledgeWriteBlocksFile } from './proposals'\nimport { searchKnowledge } from './search'\nimport { addSourcePath, loadSourceRegistry } from './sources'\nimport { initKnowledgeBase, layoutFor } from './store'\nimport { validateKnowledgeIndex } from './validate'\nimport { detectKnowledgeGaps, findSurprisingConnections, toKnowledgeVizGraph } from './viz/index'\n\ninterface Args {\n command: string\n positional: string[]\n flags: Record<string, string>\n}\n\nfunction parseArgs(argv: string[]): Args {\n const [command, ...rest] = argv\n const positional: string[] = []\n const flags: Record<string, string> = {}\n for (let i = 0; i < rest.length; i++) {\n const token = rest[i]!\n if (token.startsWith('--')) {\n const key = token.slice(2)\n const next = rest[i + 1]\n if (next && !next.startsWith('--')) {\n flags[key] = next\n i++\n } else {\n flags[key] = 'true'\n }\n } else {\n positional.push(token)\n }\n }\n return { command: command ?? 'help', positional, flags }\n}\n\nconst HELP = `agent-knowledge — source-grounded knowledge graph CLI.\n\nCommands:\n init [--root .]\n Create raw/sources, knowledge, and cache directories.\n index [--root .] [--json]\n Build .agent-knowledge/index.json from knowledge/**/*.md.\n source-add <path> [--root .] [--json]\n Copy a file or directory into raw/sources and register immutable source records.\n sources [--root .] [--json]\n List registered sources.\n apply-write-blocks <proposal-file> [--root .] [--json]\n Apply safe ---FILE: knowledge/...--- blocks emitted by an agent.\n inspect [--root .] [--json]\n Summarize page/source/edge counts, top pages, and lint state.\n explain <page|id|query> [--root .] [--json]\n Explain sources, links, inbound links, and related pages.\n search <query> [--root .] [--limit 10] [--json]\n Fast local token+graph search over the generated knowledge index.\n graph [--root .] [--format summary|json]\n Emit graph summary or JSON.\n lint [--root .] [--json]\n Run deterministic structural lint.\n validate [--root .] [--strict] [--json]\n Run schema + lint validation. Exits non-zero on blocking findings.\n export [--root .] [--format json]\n Export the current index.\n viz [--root .] [--json]\n Emit graph gaps and surprising connections.\n version\n Print package version.\n`\n\nasync function main(): Promise<number> {\n const args = parseArgs(process.argv.slice(2))\n const root = resolve(args.flags.root ?? '.')\n switch (args.command) {\n case 'init': {\n const layout = await initKnowledgeBase(root)\n process.stdout.write(`initialized knowledge base at ${layout.root}\\n`)\n return 0\n }\n case 'index': {\n const index = await writeKnowledgeIndex(root)\n if (args.flags.json === 'true') process.stdout.write(`${JSON.stringify(index, null, 2)}\\n`)\n else\n process.stdout.write(\n `indexed ${index.pages.length} pages, ${index.graph.edges.length} edges\\n`,\n )\n return 0\n }\n case 'source-add': {\n const [path] = args.positional\n if (!path) {\n process.stderr.write('source-add requires a file or directory path\\n')\n return 1\n }\n await initKnowledgeBase(root)\n const sources = await addSourcePath(root, resolve(path))\n if (args.flags.json === 'true') process.stdout.write(`${JSON.stringify(sources, null, 2)}\\n`)\n else for (const source of sources) process.stdout.write(`${source.id} ${source.uri}\\n`)\n return 0\n }\n case 'sources': {\n const registry = await loadSourceRegistry(root)\n if (args.flags.json === 'true')\n process.stdout.write(`${JSON.stringify(registry.sources, null, 2)}\\n`)\n else {\n for (const source of registry.sources)\n process.stdout.write(`${source.id} ${source.title ?? source.uri} ${source.uri}\\n`)\n }\n return 0\n }\n case 'apply-write-blocks': {\n const [proposalPath] = args.positional\n if (!proposalPath) {\n process.stderr.write('apply-write-blocks requires a proposal file\\n')\n return 1\n }\n await initKnowledgeBase(root)\n const result = await applyKnowledgeWriteBlocksFile(root, resolve(proposalPath))\n await writeKnowledgeIndex(root)\n if (args.flags.json === 'true') process.stdout.write(`${JSON.stringify(result, null, 2)}\\n`)\n else {\n for (const path of result.written) process.stdout.write(`wrote ${path}\\n`)\n for (const warning of result.warnings) process.stderr.write(`warning: ${warning}\\n`)\n }\n return result.warnings.length > 0 ? 2 : 0\n }\n case 'inspect': {\n const index = await loadOrBuildIndex(root)\n const inspection = inspectKnowledgeIndex(index)\n if (args.flags.json === 'true')\n process.stdout.write(`${JSON.stringify(inspection, null, 2)}\\n`)\n else {\n process.stdout.write(\n `pages=${inspection.pageCount} sources=${inspection.sourceCount} edges=${inspection.edgeCount} findings=${inspection.findingCount} blocking=${inspection.blockingFindingCount}\\n`,\n )\n for (const page of inspection.topPages.slice(0, 5))\n process.stdout.write(`${page.degree} ${page.path} sources=${page.sources}\\n`)\n }\n return inspection.blockingFindingCount > 0 ? 2 : 0\n }\n case 'explain': {\n const target = args.positional.join(' ')\n if (!target) {\n process.stderr.write('explain requires a page path, id, title, or query\\n')\n return 1\n }\n const explanation = explainKnowledgeTarget(await loadOrBuildIndex(root), target)\n if (args.flags.json === 'true')\n process.stdout.write(`${JSON.stringify(explanation, null, 2)}\\n`)\n else {\n process.stdout.write(`${explanation.page ? explanation.page.title : target}\\n`)\n for (const source of explanation.sources)\n process.stdout.write(`source ${source.id} ${source.title ?? source.uri}\\n`)\n for (const link of explanation.links) process.stdout.write(`out ${link}\\n`)\n for (const inbound of explanation.inbound) process.stdout.write(`in ${inbound}\\n`)\n for (const related of explanation.related.slice(0, 5))\n process.stdout.write(`related ${related.path} score=${related.score.toFixed(5)}\\n`)\n }\n return 0\n }\n case 'search': {\n const query = args.positional.join(' ')\n if (!query) {\n process.stderr.write('search requires a query\\n')\n return 1\n }\n const index = await loadOrBuildIndex(root)\n const results = searchKnowledge(index, query, Number(args.flags.limit ?? 10))\n if (args.flags.json === 'true') {\n process.stdout.write(`${JSON.stringify(results, null, 2)}\\n`)\n } else {\n for (const result of results) {\n process.stdout.write(\n `${result.rank}. ${result.page.title} (${result.page.path}) score=${result.score.toFixed(5)}\\n`,\n )\n if (result.snippet) process.stdout.write(` ${result.snippet}\\n`)\n }\n }\n return 0\n }\n case 'graph': {\n const index = await loadOrBuildIndex(root)\n if ((args.flags.format ?? 'summary') === 'json')\n process.stdout.write(`${JSON.stringify(index.graph, null, 2)}\\n`)\n else\n process.stdout.write(\n `nodes=${index.graph.nodes.length} edges=${index.graph.edges.length}\\n`,\n )\n return 0\n }\n case 'lint': {\n const index = await loadOrBuildIndex(root)\n const findings = lintKnowledgeIndex(index)\n if (args.flags.json === 'true') process.stdout.write(`${JSON.stringify(findings, null, 2)}\\n`)\n else {\n if (findings.length === 0) process.stdout.write('no findings\\n')\n for (const finding of findings) {\n process.stdout.write(\n `${finding.severity.toUpperCase()} ${finding.type}${finding.page ? ` ${finding.page}` : ''}: ${finding.message}\\n`,\n )\n }\n }\n return findings.some((finding) => finding.severity === 'error') ? 2 : 0\n }\n case 'validate': {\n const result = validateKnowledgeIndex(await loadOrBuildIndex(root), {\n strict: args.flags.strict === 'true',\n })\n if (args.flags.json === 'true') process.stdout.write(`${JSON.stringify(result, null, 2)}\\n`)\n else {\n process.stdout.write(result.ok ? 'valid\\n' : 'invalid\\n')\n for (const finding of result.findings)\n process.stdout.write(\n `${finding.severity.toUpperCase()} ${finding.type}${finding.page ? ` ${finding.page}` : ''}: ${finding.message}\\n`,\n )\n }\n return result.ok ? 0 : 2\n }\n case 'export': {\n const index = await loadOrBuildIndex(root)\n const format = args.flags.format ?? 'json'\n if (format !== 'json') {\n process.stderr.write('export currently supports --format json\\n')\n return 1\n }\n process.stdout.write(`${JSON.stringify(index, null, 2)}\\n`)\n return 0\n }\n case 'viz': {\n const index = await loadOrBuildIndex(root)\n const viz = toKnowledgeVizGraph(index.graph)\n const payload = {\n graph: viz,\n gaps: detectKnowledgeGaps(viz),\n surprisingConnections: findSurprisingConnections(viz),\n }\n if (args.flags.json === 'true') process.stdout.write(`${JSON.stringify(payload, null, 2)}\\n`)\n else {\n process.stdout.write(\n `communities=${viz.communities.length} gaps=${payload.gaps.length} surprising=${payload.surprisingConnections.length}\\n`,\n )\n }\n return 0\n }\n case 'version': {\n const pkg = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8')) as {\n version: string\n }\n process.stdout.write(`${pkg.version}\\n`)\n return 0\n }\n case 'help':\n case '--help':\n case '-h':\n process.stdout.write(HELP)\n return 0\n default:\n process.stderr.write(`unknown command: ${args.command}\\n${HELP}`)\n return 1\n }\n}\n\nasync function loadOrBuildIndex(root: string) {\n const path = join(layoutFor(root).cacheDir, 'index.json')\n if (existsSync(path))\n return JSON.parse(readFileSync(path, 'utf8')) as Awaited<ReturnType<typeof buildKnowledgeIndex>>\n return await writeKnowledgeIndex(root)\n}\n\nmain()\n .then((code) => process.exit(code))\n .catch((err) => {\n process.stderr.write(\n `agent-knowledge error: ${err instanceof Error ? (err.stack ?? err.message) : String(err)}\\n`,\n )\n process.exit(1)\n })\n"],"mappings":"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","names":[]}
|