@devflow-tools/knowledge-engine 0.2.3 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bm25.d.ts +14 -0
- package/dist/bm25.d.ts.map +1 -0
- package/dist/bm25.js +58 -0
- package/dist/bm25.js.map +1 -0
- package/dist/fetcher.d.ts +2 -0
- package/dist/fetcher.d.ts.map +1 -0
- package/dist/fetcher.js +25 -0
- package/dist/fetcher.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/knowledge-engine.d.ts +10 -9
- package/dist/knowledge-engine.d.ts.map +1 -1
- package/dist/knowledge-engine.js +155 -41
- package/dist/knowledge-engine.js.map +1 -1
- package/dist/markdown-converter.d.ts +7 -0
- package/dist/markdown-converter.d.ts.map +1 -0
- package/dist/markdown-converter.js +61 -0
- package/dist/markdown-converter.js.map +1 -0
- package/package.json +5 -3
package/dist/bm25.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
interface ChunkDoc {
|
|
2
|
+
id: string;
|
|
3
|
+
title: string;
|
|
4
|
+
content: string;
|
|
5
|
+
}
|
|
6
|
+
interface SearchResult {
|
|
7
|
+
id: string;
|
|
8
|
+
title: string;
|
|
9
|
+
content: string;
|
|
10
|
+
score: number;
|
|
11
|
+
}
|
|
12
|
+
export declare function bm25Search(query: string, chunks: ChunkDoc[], limit: number): SearchResult[];
|
|
13
|
+
export {};
|
|
14
|
+
//# sourceMappingURL=bm25.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bm25.d.ts","sourceRoot":"","sources":["../src/bm25.ts"],"names":[],"mappings":"AAGA,UAAU,QAAQ;IAChB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,UAAU,YAAY;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACf;AAsBD,wBAAgB,UAAU,CACxB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,QAAQ,EAAE,EAClB,KAAK,EAAE,MAAM,GACZ,YAAY,EAAE,CAsChB"}
|
package/dist/bm25.js
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
const k1 = 1.2;
|
|
2
|
+
const b = 0.75;
|
|
3
|
+
function tokenize(text) {
|
|
4
|
+
return text
|
|
5
|
+
.toLowerCase()
|
|
6
|
+
.replace(/[^a-z0-9一-鿿\s]/g, " ")
|
|
7
|
+
.split(/\s+/)
|
|
8
|
+
.filter(t => t.length > 0);
|
|
9
|
+
}
|
|
10
|
+
function computeIdf(term, docs) {
|
|
11
|
+
const docCount = docs.length;
|
|
12
|
+
const termDocs = docs.filter(doc => doc.includes(term)).length;
|
|
13
|
+
if (termDocs === 0)
|
|
14
|
+
return 0;
|
|
15
|
+
return Math.log((docCount - termDocs + 0.5) / (termDocs + 0.5) + 1);
|
|
16
|
+
}
|
|
17
|
+
function avgDocLength(docs) {
|
|
18
|
+
if (docs.length === 0)
|
|
19
|
+
return 1;
|
|
20
|
+
return docs.reduce((sum, d) => sum + d.length, 0) / docs.length;
|
|
21
|
+
}
|
|
22
|
+
export function bm25Search(query, chunks, limit) {
|
|
23
|
+
if (chunks.length === 0 || query.trim().length === 0)
|
|
24
|
+
return [];
|
|
25
|
+
const docs = chunks.map(c => tokenize(c.content + " " + c.title));
|
|
26
|
+
const avgdl = avgDocLength(docs);
|
|
27
|
+
const queryTerms = tokenize(query);
|
|
28
|
+
const results = chunks
|
|
29
|
+
.map((chunk, i) => {
|
|
30
|
+
const doc = docs[i];
|
|
31
|
+
const docLen = doc.length;
|
|
32
|
+
const score = queryTerms.reduce((sum, term) => {
|
|
33
|
+
const idf = computeIdf(term, docs);
|
|
34
|
+
let tf = 0;
|
|
35
|
+
for (const t of doc) {
|
|
36
|
+
if (t === term)
|
|
37
|
+
tf++;
|
|
38
|
+
}
|
|
39
|
+
const numerator = tf * (k1 + 1);
|
|
40
|
+
const denominator = tf + k1 * (1 - b + b * (docLen / avgdl));
|
|
41
|
+
return sum + idf * (numerator / denominator);
|
|
42
|
+
}, 0);
|
|
43
|
+
// Boost exact title match
|
|
44
|
+
const titleTokens = tokenize(chunk.title);
|
|
45
|
+
const titleBoost = titleTokens.some(t => queryTerms.includes(t)) ? 1.5 : 1.0;
|
|
46
|
+
return {
|
|
47
|
+
id: chunk.id,
|
|
48
|
+
title: chunk.title,
|
|
49
|
+
content: chunk.content.slice(0, 500),
|
|
50
|
+
score: score * titleBoost,
|
|
51
|
+
};
|
|
52
|
+
})
|
|
53
|
+
.filter(r => r.score > 0)
|
|
54
|
+
.sort((a, b) => b.score - a.score)
|
|
55
|
+
.slice(0, limit);
|
|
56
|
+
return results;
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=bm25.js.map
|
package/dist/bm25.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bm25.js","sourceRoot":"","sources":["../src/bm25.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fetcher.d.ts","sourceRoot":"","sources":["../src/fetcher.ts"],"names":[],"mappings":"AAGA,wBAAsB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAqB5D"}
|
package/dist/fetcher.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
const USER_AGENT = "DevFlow-KnowledgeSync/0.1 (Node.js)";
|
|
2
|
+
const MAX_RETRIES = 1;
|
|
3
|
+
export async function fetchHtml(url) {
|
|
4
|
+
let lastError = null;
|
|
5
|
+
for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
|
|
6
|
+
try {
|
|
7
|
+
const res = await fetch(url, {
|
|
8
|
+
headers: { "User-Agent": USER_AGENT },
|
|
9
|
+
signal: AbortSignal.timeout(30_000),
|
|
10
|
+
});
|
|
11
|
+
if (!res.ok) {
|
|
12
|
+
throw new Error(`Failed to fetch "${url}": ${res.status} ${res.statusText}`);
|
|
13
|
+
}
|
|
14
|
+
return await res.text();
|
|
15
|
+
}
|
|
16
|
+
catch (err) {
|
|
17
|
+
lastError = err;
|
|
18
|
+
if (attempt < MAX_RETRIES) {
|
|
19
|
+
await new Promise(r => setTimeout(r, 1000));
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
throw lastError ?? new Error(`Failed to fetch "${url}": unknown error`);
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=fetcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fetcher.js","sourceRoot":"","sources":["../src/fetcher.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,GAAG,qCAAqC,CAAC;AACzD,MAAM,WAAW,GAAG,CAAC,CAAC;AAEtB,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,GAAW;IACzC,IAAI,SAAS,GAAiB,IAAI,CAAC;IAEnC,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,WAAW,EAAE,OAAO,EAAE,EAAE,CAAC;QACxD,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;gBAC3B,OAAO,EAAE,EAAE,YAAY,EAAE,UAAU,EAAE;gBACrC,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC;aACpC,CAAC,CAAC;YACH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;gBACZ,MAAM,IAAI,KAAK,CAAC,oBAAoB,GAAG,MAAM,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC;YAC/E,CAAC;YACD,OAAO,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;QAC1B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,SAAS,GAAG,GAAY,CAAC;YACzB,IAAI,OAAO,GAAG,WAAW,EAAE,CAAC;gBAC1B,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;YAC9C,CAAC;QACH,CAAC;IACH,CAAC;IACD,MAAM,SAAS,IAAI,IAAI,KAAK,CAAC,oBAAoB,GAAG,kBAAkB,CAAC,CAAC;AAC1E,CAAC"}
|
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1E,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC"}
|
package/dist/index.js
CHANGED
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1E,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC"}
|
|
@@ -1,14 +1,15 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
export declare class KnowledgeEngine
|
|
3
|
-
private
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
private
|
|
1
|
+
import type { KnowledgeEntry, KnowledgeSource, SearchOptions, SyncResult, KnowledgeSourceStatus } from "@devflow-tools/sdk";
|
|
2
|
+
export declare class KnowledgeEngine {
|
|
3
|
+
private projectRoot;
|
|
4
|
+
constructor(opts: {
|
|
5
|
+
projectRoot: string;
|
|
6
|
+
});
|
|
7
|
+
private get knowledgeDir();
|
|
8
|
+
private pluginDir;
|
|
8
9
|
registerSource(source: KnowledgeSource): Promise<void>;
|
|
9
|
-
syncDocs(
|
|
10
|
+
syncDocs(pluginName?: string): Promise<SyncResult[]>;
|
|
10
11
|
search(query: string, options?: SearchOptions): Promise<KnowledgeEntry[]>;
|
|
11
|
-
lookup(symbol: string,
|
|
12
|
+
lookup(symbol: string, scope?: string): Promise<KnowledgeEntry | null>;
|
|
12
13
|
getSources(): Promise<KnowledgeSourceStatus[]>;
|
|
13
14
|
}
|
|
14
15
|
//# sourceMappingURL=knowledge-engine.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"knowledge-engine.d.ts","sourceRoot":"","sources":["../src/knowledge-engine.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"knowledge-engine.d.ts","sourceRoot":"","sources":["../src/knowledge-engine.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,aAAa,EAAE,UAAU,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAyB5H,qBAAa,eAAe;IAC1B,OAAO,CAAC,WAAW,CAAS;gBAEhB,IAAI,EAAE;QAAE,WAAW,EAAE,MAAM,CAAA;KAAE;IAIzC,OAAO,KAAK,YAAY,GAEvB;IAED,OAAO,CAAC,SAAS;IAIX,cAAc,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAetD,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IA2DpD,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IAsEzE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IAOtE,UAAU,IAAI,OAAO,CAAC,qBAAqB,EAAE,CAAC;CAiCrD"}
|
package/dist/knowledge-engine.js
CHANGED
|
@@ -1,64 +1,178 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from "fs";
|
|
2
|
+
import { join } from "path";
|
|
3
|
+
import { fetchHtml } from "./fetcher.js";
|
|
4
|
+
import { htmlToMarkdown, sliceByHeadings } from "./markdown-converter.js";
|
|
5
|
+
import { bm25Search } from "./bm25.js";
|
|
1
6
|
export class KnowledgeEngine {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
this.provider = provider;
|
|
7
|
+
projectRoot;
|
|
8
|
+
constructor(opts) {
|
|
9
|
+
this.projectRoot = opts.projectRoot;
|
|
6
10
|
}
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const raw = await this.provider.kvGet(this.sourcesKey);
|
|
10
|
-
if (raw) {
|
|
11
|
-
const data = raw;
|
|
12
|
-
for (const item of data) {
|
|
13
|
-
sources.set(item.name, {
|
|
14
|
-
source: item.source,
|
|
15
|
-
status: item.status,
|
|
16
|
-
lastSyncTime: item.lastSyncTime,
|
|
17
|
-
entryCount: item.entryCount,
|
|
18
|
-
});
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
return sources;
|
|
11
|
+
get knowledgeDir() {
|
|
12
|
+
return join(this.projectRoot, ".devflow", "knowledge");
|
|
22
13
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
name,
|
|
26
|
-
source: status.source,
|
|
27
|
-
status: status.status,
|
|
28
|
-
lastSyncTime: status.lastSyncTime,
|
|
29
|
-
entryCount: status.entryCount,
|
|
30
|
-
}));
|
|
31
|
-
await this.provider.kvSet(this.sourcesKey, data);
|
|
14
|
+
pluginDir(pluginName) {
|
|
15
|
+
return join(this.knowledgeDir, pluginName);
|
|
32
16
|
}
|
|
33
17
|
async registerSource(source) {
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
|
|
18
|
+
const dir = this.pluginDir(source.name);
|
|
19
|
+
mkdirSync(dir, { recursive: true });
|
|
20
|
+
const manifestPath = join(dir, "manifest.json");
|
|
21
|
+
if (!existsSync(manifestPath)) {
|
|
22
|
+
writeFileSync(manifestPath, JSON.stringify({
|
|
23
|
+
urls: source.urls,
|
|
24
|
+
fetchedAt: 0,
|
|
25
|
+
chunkCount: 0,
|
|
26
|
+
pluginName: source.pluginName,
|
|
27
|
+
version: source.version,
|
|
28
|
+
}, null, 2), "utf-8");
|
|
29
|
+
}
|
|
37
30
|
}
|
|
38
|
-
async syncDocs(
|
|
39
|
-
|
|
31
|
+
async syncDocs(pluginName) {
|
|
32
|
+
const name = pluginName ?? "";
|
|
33
|
+
if (!name)
|
|
34
|
+
return [];
|
|
35
|
+
const results = [];
|
|
36
|
+
const dir = this.pluginDir(name);
|
|
37
|
+
mkdirSync(dir, { recursive: true });
|
|
38
|
+
const manifestPath = join(dir, "manifest.json");
|
|
39
|
+
if (!existsSync(manifestPath))
|
|
40
|
+
return [];
|
|
41
|
+
const manifest = JSON.parse(readFileSync(manifestPath, "utf-8"));
|
|
42
|
+
const urls = manifest.urls ?? [];
|
|
43
|
+
for (const url of urls) {
|
|
44
|
+
const errors = [];
|
|
45
|
+
let added = 0;
|
|
46
|
+
try {
|
|
47
|
+
const html = await fetchHtml(url);
|
|
48
|
+
const markdown = htmlToMarkdown(html);
|
|
49
|
+
const chunks = sliceByHeadings(markdown);
|
|
50
|
+
const chunkFiles = chunks.map((chunk, i) => ({
|
|
51
|
+
id: `chunk-${String(i + 1).padStart(3, "0")}`,
|
|
52
|
+
title: chunk.title,
|
|
53
|
+
section: new URL(url).pathname,
|
|
54
|
+
content: chunk.content,
|
|
55
|
+
sourceUrl: url,
|
|
56
|
+
fetchedAt: Date.now(),
|
|
57
|
+
}));
|
|
58
|
+
for (const cf of chunkFiles) {
|
|
59
|
+
writeFileSync(join(dir, `${cf.id}.json`), JSON.stringify(cf, null, 2), "utf-8");
|
|
60
|
+
}
|
|
61
|
+
added = chunkFiles.length;
|
|
62
|
+
writeFileSync(manifestPath, JSON.stringify({
|
|
63
|
+
urls: manifest.urls,
|
|
64
|
+
fetchedAt: Date.now(),
|
|
65
|
+
chunkCount: chunkFiles.length,
|
|
66
|
+
pluginName: manifest.pluginName,
|
|
67
|
+
version: manifest.version,
|
|
68
|
+
sourceUrl: url,
|
|
69
|
+
}, null, 2), "utf-8");
|
|
70
|
+
}
|
|
71
|
+
catch (err) {
|
|
72
|
+
errors.push(err.message);
|
|
73
|
+
}
|
|
74
|
+
results.push({ source: url, added, updated: 0, errors });
|
|
75
|
+
}
|
|
76
|
+
return results;
|
|
40
77
|
}
|
|
41
78
|
async search(query, options) {
|
|
42
79
|
const limit = options?.limit ?? 10;
|
|
43
|
-
const
|
|
44
|
-
|
|
80
|
+
const sources = options?.sources;
|
|
81
|
+
if (!existsSync(this.knowledgeDir))
|
|
82
|
+
return [];
|
|
83
|
+
const allChunks = [];
|
|
84
|
+
const pluginDirs = sources ?? readdirSync(this.knowledgeDir, { withFileTypes: true })
|
|
85
|
+
.filter(d => d.isDirectory())
|
|
86
|
+
.map(d => d.name);
|
|
87
|
+
for (const pluginName of pluginDirs) {
|
|
88
|
+
const dir = this.pluginDir(pluginName);
|
|
89
|
+
if (!existsSync(dir))
|
|
90
|
+
continue;
|
|
91
|
+
// Read version from manifest
|
|
92
|
+
let version;
|
|
93
|
+
const manifestPath = join(dir, "manifest.json");
|
|
94
|
+
if (existsSync(manifestPath)) {
|
|
95
|
+
try {
|
|
96
|
+
const m = JSON.parse(readFileSync(manifestPath, "utf-8"));
|
|
97
|
+
version = m.version;
|
|
98
|
+
}
|
|
99
|
+
catch { /* ignore */ }
|
|
100
|
+
}
|
|
101
|
+
const files = readdirSync(dir).filter(f => f.startsWith("chunk-") && f.endsWith(".json"));
|
|
102
|
+
for (const file of files) {
|
|
103
|
+
try {
|
|
104
|
+
const chunk = JSON.parse(readFileSync(join(dir, file), "utf-8"));
|
|
105
|
+
allChunks.push({
|
|
106
|
+
id: `${pluginName}:${chunk.id}`,
|
|
107
|
+
title: chunk.title,
|
|
108
|
+
content: chunk.content,
|
|
109
|
+
sourceUrl: chunk.sourceUrl,
|
|
110
|
+
pluginName,
|
|
111
|
+
version,
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
catch {
|
|
115
|
+
// Skip corrupted files
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
if (query.trim().length === 0) {
|
|
120
|
+
return allChunks.slice(0, limit).map(c => ({
|
|
121
|
+
id: c.id,
|
|
122
|
+
source: c.pluginName,
|
|
123
|
+
title: c.title,
|
|
124
|
+
content: c.content.slice(0, 500),
|
|
125
|
+
url: c.sourceUrl,
|
|
126
|
+
version: c.version,
|
|
127
|
+
embedding: [],
|
|
128
|
+
}));
|
|
129
|
+
}
|
|
130
|
+
return bm25Search(query, allChunks, limit).map(r => ({
|
|
45
131
|
id: r.id,
|
|
46
|
-
source: r.
|
|
132
|
+
source: allChunks.find(c => c.id === r.id)?.pluginName ?? "",
|
|
47
133
|
title: r.title,
|
|
48
134
|
content: r.content,
|
|
135
|
+
url: allChunks.find(c => c.id === r.id)?.sourceUrl,
|
|
136
|
+
version: allChunks.find(c => c.id === r.id)?.version,
|
|
49
137
|
embedding: [],
|
|
50
138
|
}));
|
|
51
139
|
}
|
|
52
|
-
async lookup(symbol,
|
|
53
|
-
const results = await this.search(symbol, { limit: 5 });
|
|
140
|
+
async lookup(symbol, scope) {
|
|
141
|
+
const results = await this.search(symbol, { limit: 5, sources: scope ? [scope] : undefined });
|
|
54
142
|
if (results.length === 0)
|
|
55
143
|
return null;
|
|
56
|
-
const exact = results.find(
|
|
144
|
+
const exact = results.find(r => r.title.toLowerCase().includes(symbol.toLowerCase()));
|
|
57
145
|
return exact ?? null;
|
|
58
146
|
}
|
|
59
147
|
async getSources() {
|
|
60
|
-
|
|
61
|
-
|
|
148
|
+
if (!existsSync(this.knowledgeDir))
|
|
149
|
+
return [];
|
|
150
|
+
const pluginDirs = readdirSync(this.knowledgeDir, { withFileTypes: true })
|
|
151
|
+
.filter(d => d.isDirectory())
|
|
152
|
+
.map(d => d.name);
|
|
153
|
+
return pluginDirs.map(name => {
|
|
154
|
+
const manifestPath = join(this.pluginDir(name), "manifest.json");
|
|
155
|
+
const hasManifest = existsSync(manifestPath);
|
|
156
|
+
let chunkCount = 0;
|
|
157
|
+
let lastSync = 0;
|
|
158
|
+
let urls = [];
|
|
159
|
+
let pluginName = "";
|
|
160
|
+
let version = "";
|
|
161
|
+
if (hasManifest) {
|
|
162
|
+
const manifest = JSON.parse(readFileSync(manifestPath, "utf-8"));
|
|
163
|
+
chunkCount = manifest.chunkCount ?? 0;
|
|
164
|
+
lastSync = manifest.fetchedAt ?? 0;
|
|
165
|
+
urls = manifest.urls ?? [];
|
|
166
|
+
pluginName = manifest.pluginName ?? "";
|
|
167
|
+
version = manifest.version ?? "";
|
|
168
|
+
}
|
|
169
|
+
return {
|
|
170
|
+
source: { name, urls, pluginName, version },
|
|
171
|
+
status: chunkCount > 0 ? "synced" : "idle",
|
|
172
|
+
lastSyncTime: lastSync || undefined,
|
|
173
|
+
entryCount: chunkCount || undefined,
|
|
174
|
+
};
|
|
175
|
+
});
|
|
62
176
|
}
|
|
63
177
|
}
|
|
64
178
|
//# sourceMappingURL=knowledge-engine.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"knowledge-engine.js","sourceRoot":"","sources":["../src/knowledge-engine.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"knowledge-engine.js","sourceRoot":"","sources":["../src/knowledge-engine.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdown-converter.d.ts","sourceRoot":"","sources":["../src/markdown-converter.ts"],"names":[],"mappings":"AAUA,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED,MAAM,WAAW,KAAK;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,KAAK,EAAE,CAmDzD"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import TurndownService from "turndown";
|
|
2
|
+
const turndown = new TurndownService({
|
|
3
|
+
headingStyle: "atx",
|
|
4
|
+
codeBlockStyle: "fenced",
|
|
5
|
+
});
|
|
6
|
+
// Remove script/style tags before conversion
|
|
7
|
+
turndown.remove(["script", "style"]);
|
|
8
|
+
export function htmlToMarkdown(html) {
|
|
9
|
+
return turndown.turndown(html);
|
|
10
|
+
}
|
|
11
|
+
export function sliceByHeadings(markdown) {
|
|
12
|
+
const trimmed = markdown.trim();
|
|
13
|
+
if (trimmed.length === 0)
|
|
14
|
+
return [];
|
|
15
|
+
const lines = trimmed.split("\n");
|
|
16
|
+
const chunks = [];
|
|
17
|
+
let currentTitle = "";
|
|
18
|
+
let currentContent = [];
|
|
19
|
+
let preambleContent = [];
|
|
20
|
+
let foundFirstH2 = false;
|
|
21
|
+
for (const line of lines) {
|
|
22
|
+
if (line.startsWith("## ")) {
|
|
23
|
+
if (foundFirstH2) {
|
|
24
|
+
// Push previous H2 section
|
|
25
|
+
if (currentContent.length > 0) {
|
|
26
|
+
chunks.push({ title: currentTitle, content: currentContent.join("\n").trim() });
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
// This is the first H2 encountered
|
|
31
|
+
foundFirstH2 = true;
|
|
32
|
+
}
|
|
33
|
+
currentTitle = line.slice(3).trim();
|
|
34
|
+
// Prepend preamble content to the first H2 section
|
|
35
|
+
currentContent = preambleContent.length > 0 ? [...preambleContent] : [];
|
|
36
|
+
preambleContent = [];
|
|
37
|
+
}
|
|
38
|
+
else if (!foundFirstH2) {
|
|
39
|
+
preambleContent.push(line);
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
currentContent.push(line);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
// Push final H2 section
|
|
46
|
+
if (currentContent.some(l => l.trim().length > 0)) {
|
|
47
|
+
chunks.push({ title: currentTitle, content: currentContent.join("\n").trim() });
|
|
48
|
+
}
|
|
49
|
+
// If no H2 headings at all, create one chunk from entire markdown
|
|
50
|
+
if (!foundFirstH2) {
|
|
51
|
+
const h1Match = trimmed.match(/^# (.+)$/m);
|
|
52
|
+
return [{ title: h1Match?.[1] ?? "Untitled", content: trimmed }];
|
|
53
|
+
}
|
|
54
|
+
// If preamble exists but no H2 sections were created (empty H2 sections)
|
|
55
|
+
if (chunks.length === 0 && preambleContent.length > 0) {
|
|
56
|
+
const h1Match = trimmed.match(/^# (.+)$/m);
|
|
57
|
+
return [{ title: h1Match?.[1] ?? "Untitled", content: trimmed }];
|
|
58
|
+
}
|
|
59
|
+
return chunks;
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=markdown-converter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdown-converter.js","sourceRoot":"","sources":["../src/markdown-converter.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@devflow-tools/knowledge-engine",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -17,14 +17,16 @@
|
|
|
17
17
|
"clean": "rm -rf dist"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@devflow-tools/sdk": "^0.
|
|
20
|
+
"@devflow-tools/sdk": "^0.3.0",
|
|
21
|
+
"turndown": "^7.2.4"
|
|
21
22
|
},
|
|
22
23
|
"devDependencies": {
|
|
24
|
+
"@types/turndown": "^5.0.6",
|
|
23
25
|
"typescript": "^5.5.0",
|
|
24
26
|
"vitest": "^2.0.0"
|
|
25
27
|
},
|
|
26
28
|
"files": [
|
|
27
29
|
"dist"
|
|
28
30
|
],
|
|
29
|
-
"gitHead": "
|
|
31
|
+
"gitHead": "2d52bb1401b6501a527cac7de0f664c18bf60dcf"
|
|
30
32
|
}
|