@devflow-tools/knowledge-engine 0.2.3 → 0.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/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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bm25.js","sourceRoot":"","sources":["../src/bm25.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function fetchHtml(url: string): Promise<string>;
2
+ //# sourceMappingURL=fetcher.d.ts.map
@@ -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"}
@@ -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
@@ -1,2 +1,5 @@
1
1
  export { KnowledgeEngine } from "./knowledge-engine.js";
2
+ export { fetchHtml } from "./fetcher.js";
3
+ export { htmlToMarkdown, sliceByHeadings } from "./markdown-converter.js";
4
+ export { bm25Search } from "./bm25.js";
2
5
  //# sourceMappingURL=index.d.ts.map
@@ -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
@@ -1,2 +1,5 @@
1
1
  export { KnowledgeEngine } from "./knowledge-engine.js";
2
+ export { fetchHtml } from "./fetcher.js";
3
+ export { htmlToMarkdown, sliceByHeadings } from "./markdown-converter.js";
4
+ export { bm25Search } from "./bm25.js";
2
5
  //# sourceMappingURL=index.js.map
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 { IKnowledgeEngine, KnowledgeEntry, KnowledgeSource, SearchOptions, SyncResult, KnowledgeSourceStatus, IDataProvider } from "@devflow-tools/sdk";
2
- export declare class KnowledgeEngine implements IKnowledgeEngine {
3
- private provider;
4
- private sourcesKey;
5
- constructor(provider: IDataProvider);
6
- private loadSourceRegistry;
7
- private saveSourceRegistry;
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(_pluginName?: string): Promise<SyncResult[]>;
10
+ syncDocs(pluginName?: string): Promise<SyncResult[]>;
10
11
  search(query: string, options?: SearchOptions): Promise<KnowledgeEntry[]>;
11
- lookup(symbol: string, _scope?: string): Promise<KnowledgeEntry | null>;
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,EACV,gBAAgB,EAAE,cAAc,EAAE,eAAe,EACjD,aAAa,EAAE,UAAU,EAAE,qBAAqB,EAAE,aAAa,EAChE,MAAM,oBAAoB,CAAC;AAE5B,qBAAa,eAAgB,YAAW,gBAAgB;IACtD,OAAO,CAAC,QAAQ,CAAgB;IAChC,OAAO,CAAC,UAAU,CAAuB;gBAE7B,QAAQ,EAAE,aAAa;YAIrB,kBAAkB;YAoBlB,kBAAkB;IAW1B,cAAc,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAMtD,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAIrD,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IAiBzE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IASvE,UAAU,IAAI,OAAO,CAAC,qBAAqB,EAAE,CAAC;CAIrD"}
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"}
@@ -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
- provider;
3
- sourcesKey = "knowledge:sources";
4
- constructor(provider) {
5
- this.provider = provider;
7
+ projectRoot;
8
+ constructor(opts) {
9
+ this.projectRoot = opts.projectRoot;
6
10
  }
7
- async loadSourceRegistry() {
8
- const sources = new Map();
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
- async saveSourceRegistry(sources) {
24
- const data = Array.from(sources.entries()).map(([name, status]) => ({
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 sources = await this.loadSourceRegistry();
35
- sources.set(source.name, { source, status: "idle" });
36
- await this.saveSourceRegistry(sources);
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(_pluginName) {
39
- return [];
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 rows = await this.provider.sqlQuery("SELECT id, source, title, content FROM devflow_knowledge_entries WHERE content LIKE ? OR title LIKE ? LIMIT ?", [`%${query}%`, `%${query}%`, limit]);
44
- return rows.map((r) => ({
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.source,
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, _scope) {
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((r) => r.title.toLowerCase().includes(symbol.toLowerCase()));
144
+ const exact = results.find(r => r.title.toLowerCase().includes(symbol.toLowerCase()));
57
145
  return exact ?? null;
58
146
  }
59
147
  async getSources() {
60
- const sources = await this.loadSourceRegistry();
61
- return Array.from(sources.values());
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":"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"}
1
+ {"version":3,"file":"knowledge-engine.js","sourceRoot":"","sources":["../src/knowledge-engine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export declare function htmlToMarkdown(html: string): string;
2
+ export interface Chunk {
3
+ title: string;
4
+ content: string;
5
+ }
6
+ export declare function sliceByHeadings(markdown: string): Chunk[];
7
+ //# sourceMappingURL=markdown-converter.d.ts.map
@@ -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.2.3",
3
+ "version": "0.3.0",
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.2.3"
20
+ "@devflow-tools/sdk": "^0.2.3",
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": "9951e2306d1a742cdecc0868154fd3f74d6d2684"
31
+ "gitHead": "2d52bb1401b6501a527cac7de0f664c18bf60dcf"
30
32
  }