@dikolab/kbdb 0.2.1 → 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/README.md +59 -24
- package/dist/cli.cjs +462 -73
- package/dist/cli.cjs.map +4 -4
- package/dist/cli.mjs +454 -65
- package/dist/cli.mjs.map +4 -4
- package/dist/kbdb-worker.cjs +395 -60
- package/dist/kbdb-worker.cjs.map +4 -4
- package/dist/mod.cjs +18 -1
- package/dist/mod.cjs.map +2 -2
- package/dist/mod.mjs +18 -1
- package/dist/mod.mjs.map +2 -2
- package/dist/src/shared/cli/functions/dispatch-command.function.d.ts +3 -1
- package/dist/src/shared/cli/functions/install-default-skills.function.d.ts +12 -0
- package/dist/src/shared/cli/functions/run-check.function.d.ts +47 -5
- package/dist/src/shared/cli/functions/run-export.function.d.ts +34 -0
- package/dist/src/shared/cli/functions/run-gc.function.d.ts +6 -0
- package/dist/src/shared/cli/functions/run-learn.function.d.ts +35 -6
- package/dist/src/shared/cli/functions/run-recall.function.d.ts +45 -0
- package/dist/src/shared/cli/functions/run-search.function.d.ts +52 -15
- package/dist/src/shared/cli/index.d.ts +4 -0
- package/dist/src/shared/cli/typings/cli-options.interface.d.ts +13 -0
- package/dist/src/shared/cli/typings/learn-result.model.d.ts +19 -0
- package/dist/src/shared/cli/typings/search-display.model.d.ts +18 -0
- package/dist/src/shared/mcp/classes/mcp-server.class.d.ts +8 -0
- package/dist/src/shared/mcp/typings/mcp-client.interface.d.ts +43 -0
- package/dist/src/shared/version/constants/version.constant.d.ts +1 -1
- package/dist/src/shared/wasm-codec/functions/decode-add-section-result.function.d.ts +48 -0
- package/dist/src/shared/wasm-codec/functions/decode-scored-results.function.d.ts +58 -0
- package/dist/src/shared/wasm-codec/functions/decode-section-records.function.d.ts +33 -0
- package/dist/src/shared/wasm-codec/functions/encode-add-section-params.function.d.ts +52 -0
- package/dist/src/shared/wasm-codec/index.d.ts +2 -0
- package/dist/src/shared/worker-client/classes/worker-client.class.d.ts +16 -0
- package/dist/src/shared/worker-client/index.d.ts +1 -1
- package/dist/src/shared/worker-client/typings/add-section-result.model.d.ts +29 -15
- package/dist/src/shared/worker-client/typings/export-result.model.d.ts +14 -0
- package/dist/src/shared/worker-client/typings/gc-result.model.d.ts +6 -0
- package/dist/src/shared/worker-client/typings/search-result.model.d.ts +12 -0
- package/dist/src/shared/worker-client/typings/section.model.d.ts +16 -0
- package/dist/src/shared/worker-daemon/classes/worker-daemon.class.d.ts +35 -0
- package/dist/wasm/fs-database/kbdb_fs_database.d.ts +22 -1
- package/dist/wasm/fs-database/kbdb_fs_database.js +28 -1
- package/dist/wasm/fs-database/kbdb_fs_database_bg.wasm +0 -0
- package/dist/wasm/fs-database/kbdb_fs_database_bg.wasm.d.ts +1 -0
- package/dist/wasm/kb-worker/kbdb_worker.d.ts +48 -1
- package/dist/wasm/kb-worker/kbdb_worker.js +60 -1
- package/dist/wasm/kb-worker/kbdb_worker_bg.wasm +0 -0
- package/dist/wasm/kb-worker/kbdb_worker_bg.wasm.d.ts +2 -0
- package/dist/wasm/query-parser/kbdb_query_parser_bg.wasm +0 -0
- package/dist/worker.mjs +396 -60
- package/dist/worker.mjs.map +4 -4
- package/docs/details/cli.md +102 -15
- package/docs/details/library-api.md +55 -6
- package/docs/details/mcp-server.md +8 -4
- package/docs/details/search-and-ranking.md +63 -5
- package/docs/details/storage.md +2 -0
- package/docs/goals/cli.md +255 -14
- package/docs/goals/database.md +244 -17
- package/docs/goals/document.md +1 -1
- package/docs/goals/mcp.md +83 -14
- package/docs/goals/query-parser.md +98 -4
- package/docs/goals/query-result.md +177 -10
- package/docs/goals/skills.md +72 -0
- package/docs/goals/worker-daemon.md +54 -7
- package/docs/modules/rust/fs-database/functions/integrity.md +11 -0
- package/docs/modules/rust/fs-database/functions/section.md +23 -6
- package/docs/modules/rust/fs-database/module.md +1 -0
- package/docs/modules/rust/fs-database/types/section.md +27 -1
- package/docs/modules/rust/overview.md +2 -1
- package/docs/modules/rust/query-parser/functions/module.md +2 -2
- package/docs/modules/rust/query-parser/functions/pipeline.md +44 -6
- package/docs/modules/rust/query-parser/module.md +5 -4
- package/docs/modules/rust/query-parser/types/keyphrase.md +11 -0
- package/docs/modules/rust/query-parser/types/module.md +3 -3
- package/docs/modules/typescript/shared/cli/functions.md +68 -3
- package/package.json +1 -1
- package/src/shared/cli/functions/dispatch-command.function.ts +53 -1
- package/src/shared/cli/functions/format-output.function.ts +36 -12
- package/src/shared/cli/functions/generate-help.function.ts +56 -1
- package/src/shared/cli/functions/install-default-skills.function.ts +296 -0
- package/src/shared/cli/functions/parse-args.function.ts +13 -0
- package/src/shared/cli/functions/run-check.function.ts +87 -6
- package/src/shared/cli/functions/run-export.function.ts +40 -0
- package/src/shared/cli/functions/run-gc.function.ts +6 -0
- package/src/shared/cli/functions/run-init.function.ts +2 -0
- package/src/shared/cli/functions/run-learn.function.ts +68 -16
- package/src/shared/cli/functions/run-recall.function.ts +66 -0
- package/src/shared/cli/functions/run-search.function.ts +58 -15
- package/src/shared/cli/index.ts +4 -0
- package/src/shared/cli/typings/cli-options.interface.ts +13 -0
- package/src/shared/cli/typings/learn-result.model.ts +16 -0
- package/src/shared/cli/typings/search-display.model.ts +18 -0
- package/src/shared/mcp/classes/mcp-server.class.ts +30 -1
- package/src/shared/mcp/functions/create-tool-definitions.function.ts +46 -5
- package/src/shared/mcp/functions/handle-tool-call.function.ts +70 -2
- package/src/shared/mcp/typings/mcp-client.interface.ts +45 -0
- package/src/shared/version/constants/version.constant.ts +1 -1
- package/src/shared/wasm-codec/functions/decode-add-section-result.function.ts +112 -0
- package/src/shared/wasm-codec/functions/decode-scored-results.function.ts +86 -0
- package/src/shared/wasm-codec/functions/decode-section-records.function.ts +87 -0
- package/src/shared/wasm-codec/functions/encode-add-section-params.function.ts +68 -0
- package/src/shared/wasm-codec/index.ts +5 -0
- package/src/shared/worker-client/classes/worker-client.class.ts +19 -0
- package/src/shared/worker-client/index.ts +4 -1
- package/src/shared/worker-client/typings/add-section-result.model.ts +30 -15
- package/src/shared/worker-client/typings/export-result.model.ts +14 -0
- package/src/shared/worker-client/typings/gc-result.model.ts +6 -0
- package/src/shared/worker-client/typings/search-result.model.ts +12 -0
- package/src/shared/worker-client/typings/section.model.ts +16 -0
- package/src/shared/worker-daemon/classes/worker-daemon.class.ts +315 -46
- package/src/shared/worker-daemon/functions/create-host-imports.function.ts +19 -4
- package/src/shared/worker-daemon/functions/create-ipc-server.function.ts +5 -1
- package/src/wasm/fs-database/kbdb_fs_database.d.ts +22 -1
- package/src/wasm/fs-database/kbdb_fs_database.js +28 -1
- package/src/wasm/fs-database/kbdb_fs_database_bg.wasm +0 -0
- package/src/wasm/fs-database/kbdb_fs_database_bg.wasm.d.ts +1 -0
- package/src/wasm/kb-worker/kbdb_worker.d.ts +48 -1
- package/src/wasm/kb-worker/kbdb_worker.js +60 -1
- package/src/wasm/kb-worker/kbdb_worker_bg.wasm +0 -0
- package/src/wasm/kb-worker/kbdb_worker_bg.wasm.d.ts +2 -0
- package/src/wasm/query-parser/kbdb_query_parser_bg.wasm +0 -0
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { decodeString } from './decode-string.function.ts';
|
|
2
|
+
import { decodeU32 } from './decode-u32.function.ts';
|
|
3
|
+
import { decodeU64 } from './decode-u64.function.ts';
|
|
4
|
+
import { decodeF32 } from './decode-f32.function.ts';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* A near-duplicate section identified during add-section indexing.
|
|
8
|
+
*/
|
|
9
|
+
export interface NearDuplicate {
|
|
10
|
+
/** Knowledge-base identifier of the near-duplicate section. */
|
|
11
|
+
readonly kbid: string;
|
|
12
|
+
/** Jaccard similarity score (0.0–1.0). */
|
|
13
|
+
readonly similarity: number;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Decoded result of a `worker_add_section` WASM call.
|
|
18
|
+
*
|
|
19
|
+
* Mirrors the Rust `AddSectionResult` struct encoded via the
|
|
20
|
+
* `Encode` trait wire format.
|
|
21
|
+
*/
|
|
22
|
+
export interface AddSectionResult {
|
|
23
|
+
/** Knowledge-base identifier assigned to the new section. */
|
|
24
|
+
readonly kbid: string;
|
|
25
|
+
/** Number of unique terms indexed for the section. */
|
|
26
|
+
readonly indexedTermsCount: number;
|
|
27
|
+
/** Wall-clock time the add operation took, in milliseconds. */
|
|
28
|
+
readonly elapsedMs: number;
|
|
29
|
+
/**
|
|
30
|
+
* Knowledge-base identifier of the section that was superseded,
|
|
31
|
+
* or `null` if no supersession occurred.
|
|
32
|
+
*/
|
|
33
|
+
readonly superseded: string | null;
|
|
34
|
+
/** Advisory warnings emitted during indexing. */
|
|
35
|
+
readonly warnings: string[];
|
|
36
|
+
/**
|
|
37
|
+
* Near-duplicate sections detected above the similarity threshold
|
|
38
|
+
* (Jaccard ≥ 0.85).
|
|
39
|
+
*/
|
|
40
|
+
readonly nearDuplicates: NearDuplicate[];
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Decodes the binary `AddSectionResult` returned by the
|
|
45
|
+
* `worker_add_section` WASM export.
|
|
46
|
+
*
|
|
47
|
+
* Wire format (little-endian):
|
|
48
|
+
* - `kbid`: `u32` length + UTF-8 bytes
|
|
49
|
+
* - `indexed_terms_count`: `u32`
|
|
50
|
+
* - `elapsed_ms`: `u64`
|
|
51
|
+
* - `superseded`: `u8` flag (0=None, 1=Some) + optional `String`
|
|
52
|
+
* - `warnings`: `u32` count + each `String`
|
|
53
|
+
* - `near_duplicates`: `u32` count + each (`String` + `f32`)
|
|
54
|
+
*/
|
|
55
|
+
export function decodeAddSectionResult(
|
|
56
|
+
bytes: Uint8Array,
|
|
57
|
+
): AddSectionResult {
|
|
58
|
+
let offset = 0;
|
|
59
|
+
|
|
60
|
+
const kbid = decodeString(bytes, offset);
|
|
61
|
+
offset += kbid.bytesRead;
|
|
62
|
+
|
|
63
|
+
const indexedTermsCount = decodeU32(bytes, offset);
|
|
64
|
+
offset += indexedTermsCount.bytesRead;
|
|
65
|
+
|
|
66
|
+
const elapsedMsBig = decodeU64(bytes, offset);
|
|
67
|
+
offset += elapsedMsBig.bytesRead;
|
|
68
|
+
|
|
69
|
+
// Decode Option<String> for superseded
|
|
70
|
+
const supersededTag = bytes[offset];
|
|
71
|
+
offset += 1;
|
|
72
|
+
let superseded: string | null = null;
|
|
73
|
+
if (supersededTag === 0x01) {
|
|
74
|
+
const supersededStr = decodeString(bytes, offset);
|
|
75
|
+
offset += supersededStr.bytesRead;
|
|
76
|
+
superseded = supersededStr.value;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Decode Vec<String> for warnings
|
|
80
|
+
const warningCount = decodeU32(bytes, offset);
|
|
81
|
+
offset += warningCount.bytesRead;
|
|
82
|
+
const warnings: string[] = [];
|
|
83
|
+
for (let i = 0; i < warningCount.value; i++) {
|
|
84
|
+
const warning = decodeString(bytes, offset);
|
|
85
|
+
offset += warning.bytesRead;
|
|
86
|
+
warnings.push(warning.value);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Decode Vec<(String, f32)> for near_duplicates
|
|
90
|
+
const dupCount = decodeU32(bytes, offset);
|
|
91
|
+
offset += dupCount.bytesRead;
|
|
92
|
+
const nearDuplicates: NearDuplicate[] = [];
|
|
93
|
+
for (let i = 0; i < dupCount.value; i++) {
|
|
94
|
+
const dupKbid = decodeString(bytes, offset);
|
|
95
|
+
offset += dupKbid.bytesRead;
|
|
96
|
+
const similarity = decodeF32(bytes, offset);
|
|
97
|
+
offset += similarity.bytesRead;
|
|
98
|
+
nearDuplicates.push({
|
|
99
|
+
kbid: dupKbid.value,
|
|
100
|
+
similarity: similarity.value,
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return {
|
|
105
|
+
kbid: kbid.value,
|
|
106
|
+
indexedTermsCount: indexedTermsCount.value,
|
|
107
|
+
elapsedMs: Number(elapsedMsBig.value),
|
|
108
|
+
superseded,
|
|
109
|
+
warnings,
|
|
110
|
+
nearDuplicates,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
@@ -2,22 +2,57 @@ import { decodeString } from './decode-string.function.ts';
|
|
|
2
2
|
import { decodeU32 } from './decode-u32.function.ts';
|
|
3
3
|
import { decodeF32 } from './decode-f32.function.ts';
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* A single ranked result item from a paged search response.
|
|
7
|
+
*/
|
|
5
8
|
export interface SectionMatch {
|
|
9
|
+
/** Knowledge-base identifier for the matched section. */
|
|
6
10
|
kbid: string;
|
|
11
|
+
/** Section heading, or `null` when untitled. */
|
|
7
12
|
heading: string | null;
|
|
13
|
+
/** MIME type of the section content. */
|
|
8
14
|
type: string;
|
|
15
|
+
/** Document IDs this section belongs to. */
|
|
9
16
|
docids: string[];
|
|
17
|
+
/** Relevance score from the ranking engine. */
|
|
10
18
|
score: number;
|
|
19
|
+
/**
|
|
20
|
+
* Confidence modifier (0.0–1.0) applied after relaxed search.
|
|
21
|
+
* Always 1.0 for strict-mode results.
|
|
22
|
+
*/
|
|
23
|
+
confidence: number;
|
|
24
|
+
/** KWIC snippet (~150 chars around the best match). */
|
|
11
25
|
snippet: string;
|
|
26
|
+
/** Query terms that matched within this section. */
|
|
12
27
|
matched_terms: string[];
|
|
28
|
+
/**
|
|
29
|
+
* Document fields that contained at least one matched term
|
|
30
|
+
* (e.g. `'title'`, `'body'`).
|
|
31
|
+
*/
|
|
32
|
+
matched_fields: string[];
|
|
33
|
+
/** ISO 8601 creation timestamp of the section. */
|
|
34
|
+
created_at: string;
|
|
13
35
|
}
|
|
14
36
|
|
|
37
|
+
/**
|
|
38
|
+
* Paginated search response envelope returned by the WASM engine.
|
|
39
|
+
*/
|
|
15
40
|
export interface PagedSearchResult {
|
|
41
|
+
/** Matching sections for the current page. */
|
|
16
42
|
items: SectionMatch[];
|
|
43
|
+
/** Total number of matches across all pages. */
|
|
17
44
|
total: number;
|
|
45
|
+
/** Number of results skipped (pagination offset). */
|
|
18
46
|
offset: number;
|
|
47
|
+
/** Maximum results per page. */
|
|
19
48
|
limit: number;
|
|
49
|
+
/** Whether more results exist beyond this page. */
|
|
20
50
|
has_more: boolean;
|
|
51
|
+
/**
|
|
52
|
+
* Whether the engine fell back to relaxed (OR-mode) search
|
|
53
|
+
* after strict (AND-mode) returned no results.
|
|
54
|
+
*/
|
|
55
|
+
relaxed: boolean;
|
|
21
56
|
}
|
|
22
57
|
|
|
23
58
|
function decodeOptionString(
|
|
@@ -32,6 +67,29 @@ function decodeOptionString(
|
|
|
32
67
|
return { value: str.value, bytesRead: 1 + str.bytesRead };
|
|
33
68
|
}
|
|
34
69
|
|
|
70
|
+
/**
|
|
71
|
+
* Decodes the binary `PagedSearchResult` returned by the
|
|
72
|
+
* `worker_get_result` WASM export after a `worker_search` call.
|
|
73
|
+
*
|
|
74
|
+
* Wire format (little-endian):
|
|
75
|
+
* - `total`: `u32`
|
|
76
|
+
* - `offset`: `u32`
|
|
77
|
+
* - `limit`: `u32`
|
|
78
|
+
* - `has_more`: `u8` (0/1)
|
|
79
|
+
* - `relaxed`: `u8` (0/1)
|
|
80
|
+
* - `item_count`: `u32`
|
|
81
|
+
* - Per item:
|
|
82
|
+
* - `kbid`: `String`
|
|
83
|
+
* - `heading`: `Option<String>`
|
|
84
|
+
* - `section_type`: `String`
|
|
85
|
+
* - `docids`: `u32` count + `String[]`
|
|
86
|
+
* - `score`: `f32`
|
|
87
|
+
* - `confidence`: `f32`
|
|
88
|
+
* - `snippet`: `String`
|
|
89
|
+
* - `matched_terms`: `u32` count + `String[]`
|
|
90
|
+
* - `matched_fields`: `u32` count + `String[]`
|
|
91
|
+
* - `created_at`: `String`
|
|
92
|
+
*/
|
|
35
93
|
export function decodePagedSearchResult(
|
|
36
94
|
bytes: Uint8Array,
|
|
37
95
|
): PagedSearchResult {
|
|
@@ -49,6 +107,12 @@ export function decodePagedSearchResult(
|
|
|
49
107
|
const hasMore = bytes[offset] === 1;
|
|
50
108
|
offset += 1;
|
|
51
109
|
|
|
110
|
+
// relaxed flag added after has_more
|
|
111
|
+
const relaxed = offset < bytes.length && bytes[offset] === 1;
|
|
112
|
+
if (offset < bytes.length) {
|
|
113
|
+
offset += 1;
|
|
114
|
+
}
|
|
115
|
+
|
|
52
116
|
const itemCount = decodeU32(bytes, offset);
|
|
53
117
|
offset += itemCount.bytesRead;
|
|
54
118
|
|
|
@@ -75,6 +139,10 @@ export function decodePagedSearchResult(
|
|
|
75
139
|
const score = decodeF32(bytes, offset);
|
|
76
140
|
offset += score.bytesRead;
|
|
77
141
|
|
|
142
|
+
// confidence added after score
|
|
143
|
+
const confidence = decodeF32(bytes, offset);
|
|
144
|
+
offset += confidence.bytesRead;
|
|
145
|
+
|
|
78
146
|
const snippet = decodeString(bytes, offset);
|
|
79
147
|
offset += snippet.bytesRead;
|
|
80
148
|
|
|
@@ -87,14 +155,31 @@ export function decodePagedSearchResult(
|
|
|
87
155
|
matched_terms.push(term.value);
|
|
88
156
|
}
|
|
89
157
|
|
|
158
|
+
// matched_fields added after matched_terms
|
|
159
|
+
const fieldCount = decodeU32(bytes, offset);
|
|
160
|
+
offset += fieldCount.bytesRead;
|
|
161
|
+
const matched_fields: string[] = [];
|
|
162
|
+
for (let j = 0; j < fieldCount.value; j++) {
|
|
163
|
+
const field = decodeString(bytes, offset);
|
|
164
|
+
offset += field.bytesRead;
|
|
165
|
+
matched_fields.push(field.value);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// created_at added after matched_fields
|
|
169
|
+
const createdAt = decodeString(bytes, offset);
|
|
170
|
+
offset += createdAt.bytesRead;
|
|
171
|
+
|
|
90
172
|
items.push({
|
|
91
173
|
kbid: kbid.value,
|
|
92
174
|
heading: heading.value,
|
|
93
175
|
type: sectionType.value,
|
|
94
176
|
docids,
|
|
95
177
|
score: score.value,
|
|
178
|
+
confidence: confidence.value,
|
|
96
179
|
snippet: snippet.value,
|
|
97
180
|
matched_terms,
|
|
181
|
+
matched_fields,
|
|
182
|
+
created_at: createdAt.value,
|
|
98
183
|
});
|
|
99
184
|
}
|
|
100
185
|
|
|
@@ -104,5 +189,6 @@ export function decodePagedSearchResult(
|
|
|
104
189
|
offset: resultOffset.value,
|
|
105
190
|
limit: limit.value,
|
|
106
191
|
has_more: hasMore,
|
|
192
|
+
relaxed,
|
|
107
193
|
};
|
|
108
194
|
}
|
|
@@ -40,6 +40,33 @@ export interface SectionRecord {
|
|
|
40
40
|
codeTokenCount: number;
|
|
41
41
|
/** Application-level type name assigned to this section. */
|
|
42
42
|
typeName: string;
|
|
43
|
+
/**
|
|
44
|
+
* Stable logical identity derived from source path and heading.
|
|
45
|
+
* `null` for stdin input or sections without a source path.
|
|
46
|
+
*/
|
|
47
|
+
sourceKey: string | null;
|
|
48
|
+
/**
|
|
49
|
+
* Absolute path of the source file that was learned.
|
|
50
|
+
* `null` for stdin input or programmatic API calls.
|
|
51
|
+
*/
|
|
52
|
+
sourcePath: string | null;
|
|
53
|
+
/**
|
|
54
|
+
* ISO 8601 modified time of the source file at learn time.
|
|
55
|
+
* `null` when no source file exists.
|
|
56
|
+
*/
|
|
57
|
+
sourceMtime: string | null;
|
|
58
|
+
/**
|
|
59
|
+
* ISO 8601 timestamp of the last supersession.
|
|
60
|
+
* `null` on first creation.
|
|
61
|
+
*/
|
|
62
|
+
updatedAt: string | null;
|
|
63
|
+
/** User-supplied tags for scoping and filtering. */
|
|
64
|
+
tags: string[];
|
|
65
|
+
/**
|
|
66
|
+
* The kbid of the section this one replaced via supersession.
|
|
67
|
+
* `null` on first creation or non-superseding additions.
|
|
68
|
+
*/
|
|
69
|
+
supersedes: string | null;
|
|
43
70
|
}
|
|
44
71
|
|
|
45
72
|
function decodeOptionString(
|
|
@@ -82,6 +109,12 @@ function decodeSectionType(
|
|
|
82
109
|
* Each record is decoded in field order as produced by the Rust
|
|
83
110
|
* `SectionRecord::encode` implementation.
|
|
84
111
|
*
|
|
112
|
+
* Trailing fields (`sourceKey`, `sourcePath`, `sourceMtime`,
|
|
113
|
+
* `updatedAt`, `tags`, `supersedes`) were added after the initial
|
|
114
|
+
* format. When decoding legacy bytes that stop after `typeName`,
|
|
115
|
+
* those fields default to `null` / `[]`. This matches the Rust
|
|
116
|
+
* decoder's backward-compatibility guards.
|
|
117
|
+
*
|
|
85
118
|
* @param bytes - raw bytes returned by a WASM section-list export
|
|
86
119
|
* @returns decoded array of section records, empty when count is zero
|
|
87
120
|
*/
|
|
@@ -136,6 +169,54 @@ export function decodeSectionRecords(
|
|
|
136
169
|
const typeName = decodeString(bytes, offset);
|
|
137
170
|
offset += typeName.bytesRead;
|
|
138
171
|
|
|
172
|
+
// New trailing fields -- use length guards for backward compat.
|
|
173
|
+
let sourceKey: string | null = null;
|
|
174
|
+
if (offset < bytes.length) {
|
|
175
|
+
const v = decodeOptionString(bytes, offset);
|
|
176
|
+
offset += v.bytesRead;
|
|
177
|
+
sourceKey = v.value;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
let sourcePath: string | null = null;
|
|
181
|
+
if (offset < bytes.length) {
|
|
182
|
+
const v = decodeOptionString(bytes, offset);
|
|
183
|
+
offset += v.bytesRead;
|
|
184
|
+
sourcePath = v.value;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
let sourceMtime: string | null = null;
|
|
188
|
+
if (offset < bytes.length) {
|
|
189
|
+
const v = decodeOptionString(bytes, offset);
|
|
190
|
+
offset += v.bytesRead;
|
|
191
|
+
sourceMtime = v.value;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
let updatedAt: string | null = null;
|
|
195
|
+
if (offset < bytes.length) {
|
|
196
|
+
const v = decodeOptionString(bytes, offset);
|
|
197
|
+
offset += v.bytesRead;
|
|
198
|
+
updatedAt = v.value;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
let tags: string[] = [];
|
|
202
|
+
if (offset < bytes.length) {
|
|
203
|
+
const tagCount = decodeU32(bytes, offset);
|
|
204
|
+
offset += tagCount.bytesRead;
|
|
205
|
+
tags = [];
|
|
206
|
+
for (let j = 0; j < tagCount.value; j++) {
|
|
207
|
+
const tag = decodeString(bytes, offset);
|
|
208
|
+
offset += tag.bytesRead;
|
|
209
|
+
tags.push(tag.value);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
let supersedes: string | null = null;
|
|
214
|
+
if (offset < bytes.length) {
|
|
215
|
+
const v = decodeOptionString(bytes, offset);
|
|
216
|
+
offset += v.bytesRead;
|
|
217
|
+
supersedes = v.value;
|
|
218
|
+
}
|
|
219
|
+
|
|
139
220
|
const record: SectionRecord = {
|
|
140
221
|
kbid: kbid.value,
|
|
141
222
|
docid: docid.value,
|
|
@@ -151,6 +232,12 @@ export function decodeSectionRecords(
|
|
|
151
232
|
bodyTokenCount: bodyTokenCount.value,
|
|
152
233
|
codeTokenCount: codeTokenCount.value,
|
|
153
234
|
typeName: typeName.value,
|
|
235
|
+
sourceKey,
|
|
236
|
+
sourcePath,
|
|
237
|
+
sourceMtime,
|
|
238
|
+
updatedAt,
|
|
239
|
+
tags,
|
|
240
|
+
supersedes,
|
|
154
241
|
};
|
|
155
242
|
if (st.mimeType !== undefined) {
|
|
156
243
|
record.mimeType = st.mimeType;
|
|
@@ -1,20 +1,83 @@
|
|
|
1
1
|
import { encodeSectionType } from './encode-section-type.function.ts';
|
|
2
2
|
import { encodeString } from './encode-string.function.ts';
|
|
3
3
|
import { encodeOptionString } from './encode-option-string.function.ts';
|
|
4
|
+
import { encodeU32 } from './encode-u32.function.ts';
|
|
4
5
|
|
|
6
|
+
/**
|
|
7
|
+
* Parameters for adding a new section to the knowledge base.
|
|
8
|
+
*
|
|
9
|
+
* Maps to the Rust `AddSectionParams` struct encoded for the
|
|
10
|
+
* `worker_add_section` WASM export.
|
|
11
|
+
*/
|
|
5
12
|
export interface AddSectionInput {
|
|
13
|
+
/** Semantic content category. */
|
|
6
14
|
sectionType: 'text' | 'code' | 'image';
|
|
15
|
+
/** MIME type; required for `code` and `image` section types. */
|
|
7
16
|
mimeType?: string;
|
|
17
|
+
/** Raw section content. */
|
|
8
18
|
content: string;
|
|
19
|
+
/** Optional section heading. */
|
|
9
20
|
title?: string | null;
|
|
21
|
+
/** Optional description summary. */
|
|
10
22
|
description?: string | null;
|
|
23
|
+
/** Optional document identifier to attach the section to. */
|
|
11
24
|
docid?: string | null;
|
|
25
|
+
/**
|
|
26
|
+
* Application-level type name for the section (e.g. `'skill'`,
|
|
27
|
+
* `'fact'`). `null` means no custom type.
|
|
28
|
+
*/
|
|
12
29
|
typeName?: string | null;
|
|
30
|
+
/**
|
|
31
|
+
* Absolute path of the source file being learned. `undefined`
|
|
32
|
+
* means stdin input or programmatic API call.
|
|
33
|
+
*/
|
|
34
|
+
sourcePath?: string;
|
|
35
|
+
/**
|
|
36
|
+
* ISO 8601 modified time of the source file. `undefined` means
|
|
37
|
+
* no source file exists.
|
|
38
|
+
*/
|
|
39
|
+
sourceMtime?: string;
|
|
40
|
+
/**
|
|
41
|
+
* User-supplied tags for scoping and filtering. Defaults to
|
|
42
|
+
* an empty list when not provided.
|
|
43
|
+
*/
|
|
44
|
+
tags?: string[];
|
|
45
|
+
/**
|
|
46
|
+
* When `true`, supersede any existing section with the same
|
|
47
|
+
* source key. Defaults to `false`.
|
|
48
|
+
*/
|
|
49
|
+
replace?: boolean;
|
|
13
50
|
}
|
|
14
51
|
|
|
52
|
+
/**
|
|
53
|
+
* Encodes `AddSectionInput` as the binary format expected by the
|
|
54
|
+
* `worker_add_section` WASM export.
|
|
55
|
+
*
|
|
56
|
+
* Wire format (little-endian):
|
|
57
|
+
* - `SectionType` tag byte (+ optional MIME string for code/image)
|
|
58
|
+
* - `content`: `u32` length + UTF-8 bytes
|
|
59
|
+
* - `title`: `u8` flag + optional `String`
|
|
60
|
+
* - `description`: `u8` flag + optional `String`
|
|
61
|
+
* - `docid`: `u8` flag + optional `String`
|
|
62
|
+
* - `typeName`: `u8` flag + optional `String`
|
|
63
|
+
* - `sourcePath`: `u8` flag + optional `String`
|
|
64
|
+
* - `sourceMtime`: `u8` flag + optional `String`
|
|
65
|
+
* - `tags`: `u32` count + each `String`
|
|
66
|
+
* - `replace`: `u8` (0 or 1)
|
|
67
|
+
*/
|
|
15
68
|
export function encodeAddSectionParams(
|
|
16
69
|
params: AddSectionInput,
|
|
17
70
|
): Uint8Array {
|
|
71
|
+
const tags = params.tags ?? [];
|
|
72
|
+
const tagParts: Uint8Array[] = [];
|
|
73
|
+
for (const tag of tags) {
|
|
74
|
+
tagParts.push(encodeString(tag));
|
|
75
|
+
}
|
|
76
|
+
const tagsCountBytes = encodeU32(tags.length);
|
|
77
|
+
const replaceByte = new Uint8Array([
|
|
78
|
+
params.replace === true ? 1 : 0,
|
|
79
|
+
]);
|
|
80
|
+
|
|
18
81
|
const parts = [
|
|
19
82
|
encodeSectionType(params.sectionType, params.mimeType),
|
|
20
83
|
encodeString(params.content),
|
|
@@ -22,6 +85,11 @@ export function encodeAddSectionParams(
|
|
|
22
85
|
encodeOptionString(params.description),
|
|
23
86
|
encodeOptionString(params.docid),
|
|
24
87
|
encodeOptionString(params.typeName),
|
|
88
|
+
encodeOptionString(params.sourcePath),
|
|
89
|
+
encodeOptionString(params.sourceMtime),
|
|
90
|
+
tagsCountBytes,
|
|
91
|
+
...tagParts,
|
|
92
|
+
replaceByte,
|
|
25
93
|
];
|
|
26
94
|
const totalLen = parts.reduce((sum, p) => sum + p.length, 0);
|
|
27
95
|
const result = new Uint8Array(totalLen);
|
|
@@ -23,9 +23,14 @@ export { decodeKeyValueText } from './functions/decode-key-value-text.function.t
|
|
|
23
23
|
export { decodeRemoveFlag } from './functions/decode-remove-flag.function.ts';
|
|
24
24
|
export { encodeRecallParams } from './functions/encode-recall-params.function.ts';
|
|
25
25
|
export { decodeRecallResult } from './functions/decode-recall-result.function.ts';
|
|
26
|
+
export { decodeAddSectionResult } from './functions/decode-add-section-result.function.ts';
|
|
26
27
|
|
|
27
28
|
export type { DecodeResult } from './functions/decode-string.function.ts';
|
|
28
29
|
export type { AddSectionInput } from './functions/encode-add-section-params.function.ts';
|
|
30
|
+
export type {
|
|
31
|
+
AddSectionResult,
|
|
32
|
+
NearDuplicate,
|
|
33
|
+
} from './functions/decode-add-section-result.function.ts';
|
|
29
34
|
export type {
|
|
30
35
|
SectionMatch,
|
|
31
36
|
PagedSearchResult,
|
|
@@ -21,6 +21,7 @@ import type {
|
|
|
21
21
|
RecallParams,
|
|
22
22
|
RecallResult,
|
|
23
23
|
} from '../typings/recall-result.model.ts';
|
|
24
|
+
import type { ExportResult } from '../typings/export-result.model.ts';
|
|
24
25
|
|
|
25
26
|
/** Pending JSON-RPC call awaiting a response from the daemon. */
|
|
26
27
|
interface PendingCall {
|
|
@@ -381,6 +382,24 @@ export class WorkerClient {
|
|
|
381
382
|
}) as Promise<DocumentManifest[]>;
|
|
382
383
|
}
|
|
383
384
|
|
|
385
|
+
/**
|
|
386
|
+
* Exports the database to a target directory on disk.
|
|
387
|
+
*
|
|
388
|
+
* Copies section files, document manifests, and `catalog.toml`
|
|
389
|
+
* to `params.path`. Index files are not exported because they
|
|
390
|
+
* are derivable from the section and document data.
|
|
391
|
+
*
|
|
392
|
+
* @param params - optional export parameters
|
|
393
|
+
* @param params.path - target directory path; defaults to
|
|
394
|
+
* `./kbdb-export/` when not provided
|
|
395
|
+
* @returns export report with the resolved path and file counts
|
|
396
|
+
*/
|
|
397
|
+
async export(params?: { path?: string }): Promise<ExportResult> {
|
|
398
|
+
return this.call('export', {
|
|
399
|
+
targetPath: params?.path || undefined,
|
|
400
|
+
}) as Promise<ExportResult>;
|
|
401
|
+
}
|
|
402
|
+
|
|
384
403
|
/**
|
|
385
404
|
* Sends a JSON-RPC 2.0 request and awaits the response.
|
|
386
405
|
*
|
|
@@ -18,7 +18,10 @@ export type {
|
|
|
18
18
|
export type { StatusResult } from './typings/status-result.model.ts';
|
|
19
19
|
export type { WorkerClientError } from './typings/worker-client-error.interface.ts';
|
|
20
20
|
export type { DaemonInfo } from './typings/daemon-info.model.ts';
|
|
21
|
-
export type {
|
|
21
|
+
export type {
|
|
22
|
+
AddSectionResult,
|
|
23
|
+
NearDuplicateEntry,
|
|
24
|
+
} from './typings/add-section-result.model.ts';
|
|
22
25
|
export type { RemoveSectionResult } from './typings/remove-section-result.model.ts';
|
|
23
26
|
export type { ContentResult } from './typings/content-result.model.ts';
|
|
24
27
|
export type {
|
|
@@ -1,22 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A near-duplicate section reported after adding a new section.
|
|
3
|
+
*/
|
|
4
|
+
export interface NearDuplicateEntry {
|
|
5
|
+
/** Knowledge-base identifier of the near-duplicate section. */
|
|
6
|
+
readonly kbid: string;
|
|
7
|
+
/** Jaccard similarity score (0.0--1.0). */
|
|
8
|
+
readonly similarity: number;
|
|
9
|
+
}
|
|
10
|
+
|
|
1
11
|
/** Result returned by the daemon after adding a new section. */
|
|
2
12
|
export interface AddSectionResult {
|
|
3
13
|
/** Knowledge-base identifier assigned to the section. */
|
|
4
14
|
readonly kbid: string;
|
|
5
|
-
/** MIME type of the stored section. */
|
|
6
|
-
readonly type: string;
|
|
7
|
-
/** Section title, if provided. */
|
|
8
|
-
readonly title?: string;
|
|
9
|
-
/** Section description, if provided. */
|
|
10
|
-
readonly description?: string;
|
|
11
|
-
/** Total token count for the section. */
|
|
12
|
-
readonly token_count: number;
|
|
13
|
-
/** Number of unique terms indexed for this section. */
|
|
14
|
-
readonly indexed_terms_count: number;
|
|
15
|
-
/** Time taken to process and store the section, in milliseconds. */
|
|
16
|
-
readonly elapsed_ms: number;
|
|
17
15
|
/**
|
|
18
|
-
*
|
|
19
|
-
*
|
|
16
|
+
* Number of unique terms indexed for the section.
|
|
17
|
+
* Present in the current binary-decoded response format.
|
|
18
|
+
*/
|
|
19
|
+
readonly indexed_terms_count?: number;
|
|
20
|
+
/**
|
|
21
|
+
* Wall-clock time the add operation took, in milliseconds.
|
|
22
|
+
* Present in the current binary-decoded response format.
|
|
23
|
+
*/
|
|
24
|
+
readonly elapsed_ms?: number;
|
|
25
|
+
/**
|
|
26
|
+
* Knowledge-base identifier of the section that was superseded,
|
|
27
|
+
* or `null` if no supersession occurred.
|
|
28
|
+
*/
|
|
29
|
+
readonly superseded?: string | null;
|
|
30
|
+
/** Advisory warnings emitted during indexing. */
|
|
31
|
+
readonly warnings?: string[];
|
|
32
|
+
/**
|
|
33
|
+
* Near-duplicate sections detected above the similarity threshold
|
|
34
|
+
* (Jaccard >= 0.85).
|
|
20
35
|
*/
|
|
21
|
-
readonly
|
|
36
|
+
readonly near_duplicates?: NearDuplicateEntry[];
|
|
22
37
|
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Report returned by the daemon after exporting the database to a
|
|
3
|
+
* target directory.
|
|
4
|
+
*/
|
|
5
|
+
export interface ExportResult {
|
|
6
|
+
/** Absolute path to the directory where files were written. */
|
|
7
|
+
readonly path: string;
|
|
8
|
+
/** Number of section files copied to the export directory. */
|
|
9
|
+
readonly sections_exported: number;
|
|
10
|
+
/** Number of document manifest files copied. */
|
|
11
|
+
readonly documents_exported: number;
|
|
12
|
+
/** Wall-clock time the export operation took, in milliseconds. */
|
|
13
|
+
readonly elapsed_ms: number;
|
|
14
|
+
}
|
|
@@ -9,4 +9,10 @@ export interface GcResult {
|
|
|
9
9
|
readonly removed_bytes: number;
|
|
10
10
|
/** Time taken to complete garbage collection, in milliseconds. */
|
|
11
11
|
readonly elapsed_ms: number;
|
|
12
|
+
/**
|
|
13
|
+
* Number of sections whose source_path file no longer contains
|
|
14
|
+
* their heading text. Advisory; not auto-removed by gc.
|
|
15
|
+
* Absent on older daemon versions.
|
|
16
|
+
*/
|
|
17
|
+
readonly stale_sources?: number;
|
|
12
18
|
}
|
|
@@ -14,6 +14,18 @@ export interface SearchResult {
|
|
|
14
14
|
readonly snippet: string;
|
|
15
15
|
/** Query terms that matched within this section. */
|
|
16
16
|
readonly matched_terms: readonly string[];
|
|
17
|
+
/**
|
|
18
|
+
* Fields that contained at least one match
|
|
19
|
+
* (e.g. `'heading'`, `'body'`).
|
|
20
|
+
*/
|
|
21
|
+
readonly matched_fields?: readonly string[];
|
|
22
|
+
/**
|
|
23
|
+
* Normalised confidence score (0.0-1.0) relative to the top result.
|
|
24
|
+
* May be absent from older daemon versions.
|
|
25
|
+
*/
|
|
26
|
+
readonly confidence?: number;
|
|
27
|
+
/** ISO 8601 creation timestamp of the section. */
|
|
28
|
+
readonly created_at?: string;
|
|
17
29
|
}
|
|
18
30
|
|
|
19
31
|
/** Paginated search result envelope. */
|
|
@@ -24,4 +24,20 @@ export interface AddSectionParams {
|
|
|
24
24
|
readonly content: string;
|
|
25
25
|
/** Parent document identifier to associate the section with. */
|
|
26
26
|
readonly docid?: string;
|
|
27
|
+
/** Human-readable heading for the section. */
|
|
28
|
+
readonly title?: string;
|
|
29
|
+
/** Short summary or description of the section. */
|
|
30
|
+
readonly description?: string;
|
|
31
|
+
/** Application-defined tags for scoping and filtering. */
|
|
32
|
+
readonly tags?: string[];
|
|
33
|
+
/**
|
|
34
|
+
* When `true`, supersedes an existing section with the same
|
|
35
|
+
* source key (derived from `sourcePath` and `title`).
|
|
36
|
+
*/
|
|
37
|
+
readonly replace?: boolean;
|
|
38
|
+
/**
|
|
39
|
+
* Absolute path to the source file. Required for supersession
|
|
40
|
+
* via source key when `replace` is `true`.
|
|
41
|
+
*/
|
|
42
|
+
readonly sourcePath?: string;
|
|
27
43
|
}
|