@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,66 @@
|
|
|
1
|
+
import type { CliOptions } from '../typings/cli-options.interface.ts';
|
|
2
|
+
import type { RecallResult } from '../../worker-client/typings/recall-result.model.ts';
|
|
3
|
+
|
|
4
|
+
/** Maximum allowed expansion depth for recall operations. */
|
|
5
|
+
const MAX_RECALL_DEPTH = 3;
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Minimal client interface required by `runRecall`.
|
|
9
|
+
*
|
|
10
|
+
* Decouples the CLI function from the concrete `WorkerClient`
|
|
11
|
+
* implementation, making it straightforward to test with mocks.
|
|
12
|
+
*/
|
|
13
|
+
export interface RecallClient {
|
|
14
|
+
/**
|
|
15
|
+
* Retrieves full content and context for one or more sections
|
|
16
|
+
* by their knowledge-base identifiers.
|
|
17
|
+
*
|
|
18
|
+
* @param params - section identifier(s) and optional expansion
|
|
19
|
+
* depth (0--3)
|
|
20
|
+
* @returns a single `RecallResult` when `kbid` is supplied, or
|
|
21
|
+
* a `RecallResult[]` when `kbids` is supplied
|
|
22
|
+
*/
|
|
23
|
+
recall(params: {
|
|
24
|
+
kbid?: string;
|
|
25
|
+
kbids?: string[];
|
|
26
|
+
depth?: number;
|
|
27
|
+
}): Promise<RecallResult | RecallResult[]>;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Retrieves full content and progressive context for one or more
|
|
32
|
+
* sections by kbid via the provided client.
|
|
33
|
+
*
|
|
34
|
+
* Returns an error result when no kbids are provided in
|
|
35
|
+
* `options.args`. For a single kbid, calls `client.recall` with the
|
|
36
|
+
* `kbid` parameter and returns the single `RecallResult`. For
|
|
37
|
+
* multiple kbids, calls `client.recall` with the `kbids` array.
|
|
38
|
+
*
|
|
39
|
+
* The `depth` option is read from `options.depth`, defaulting to 0
|
|
40
|
+
* and clamped to the range 0--3.
|
|
41
|
+
*
|
|
42
|
+
* @param client - recall client to delegate to
|
|
43
|
+
* @param options - parsed CLI options supplying kbids in `args` and
|
|
44
|
+
* expansion depth in `depth`
|
|
45
|
+
* @returns the `RecallResult` or `RecallResult[]` from the client,
|
|
46
|
+
* or an error object when no kbids are provided
|
|
47
|
+
*/
|
|
48
|
+
export async function runRecall(
|
|
49
|
+
client: RecallClient,
|
|
50
|
+
options: CliOptions,
|
|
51
|
+
): Promise<RecallResult | RecallResult[] | { error: string }> {
|
|
52
|
+
if (options.args.length === 0) {
|
|
53
|
+
return { error: 'no kbid provided' };
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const depth = Math.min(
|
|
57
|
+
MAX_RECALL_DEPTH,
|
|
58
|
+
Math.max(0, options.depth ?? 0),
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
if (options.args.length === 1) {
|
|
62
|
+
return client.recall({ kbid: options.args[0], depth });
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return client.recall({ kbids: options.args, depth });
|
|
66
|
+
}
|
|
@@ -1,6 +1,58 @@
|
|
|
1
1
|
import type { CliOptions } from '../typings/cli-options.interface.ts';
|
|
2
2
|
import type { PagedSearchDisplay } from '../typings/search-display.model.ts';
|
|
3
3
|
|
|
4
|
+
/** A single raw search result item returned by the daemon. */
|
|
5
|
+
interface RawSearchItem {
|
|
6
|
+
/** Knowledge-base identifier of the matched section. */
|
|
7
|
+
readonly kbid: string;
|
|
8
|
+
/** Section heading, or null when untitled. */
|
|
9
|
+
readonly heading: string | null;
|
|
10
|
+
/** MIME type of the section content. */
|
|
11
|
+
readonly type: string;
|
|
12
|
+
/** Document IDs this section belongs to. */
|
|
13
|
+
readonly docids: readonly string[];
|
|
14
|
+
/** Relevance score from the ranking engine. */
|
|
15
|
+
readonly score: number;
|
|
16
|
+
/** KWIC excerpt centered on the highest-scoring matched term. */
|
|
17
|
+
readonly snippet: string;
|
|
18
|
+
/** Query terms that matched within this section. */
|
|
19
|
+
readonly matched_terms: readonly string[];
|
|
20
|
+
/**
|
|
21
|
+
* Fields that contained at least one match.
|
|
22
|
+
* May be absent from older daemon versions.
|
|
23
|
+
*/
|
|
24
|
+
readonly matched_fields?: readonly string[];
|
|
25
|
+
/**
|
|
26
|
+
* Normalised confidence score (0.0-1.0) relative to the top result.
|
|
27
|
+
* May be absent from older daemon versions.
|
|
28
|
+
*/
|
|
29
|
+
readonly confidence?: number;
|
|
30
|
+
/**
|
|
31
|
+
* ISO 8601 creation timestamp of the section.
|
|
32
|
+
* May be absent from older daemon versions.
|
|
33
|
+
*/
|
|
34
|
+
readonly created_at?: string;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** Raw paginated search response from the daemon. */
|
|
38
|
+
interface RawSearchResponse {
|
|
39
|
+
/** Result items for the current page. */
|
|
40
|
+
readonly items: readonly RawSearchItem[];
|
|
41
|
+
/** Total number of matches across all pages. */
|
|
42
|
+
readonly total: number;
|
|
43
|
+
/** Number of results skipped. */
|
|
44
|
+
readonly offset: number;
|
|
45
|
+
/** Maximum results per page. */
|
|
46
|
+
readonly limit: number;
|
|
47
|
+
/** Whether more results exist beyond this page. */
|
|
48
|
+
readonly has_more: boolean;
|
|
49
|
+
/**
|
|
50
|
+
* When `true`, the engine relaxed the query to produce results.
|
|
51
|
+
* May be absent from older daemon versions.
|
|
52
|
+
*/
|
|
53
|
+
readonly relaxed?: boolean;
|
|
54
|
+
}
|
|
55
|
+
|
|
4
56
|
/**
|
|
5
57
|
* Minimal client interface required by `runSearch`.
|
|
6
58
|
*
|
|
@@ -18,21 +70,7 @@ export interface SearchClient {
|
|
|
18
70
|
mode?: string;
|
|
19
71
|
limit?: number;
|
|
20
72
|
offset?: number;
|
|
21
|
-
}): Promise<
|
|
22
|
-
readonly items: readonly {
|
|
23
|
-
readonly kbid: string;
|
|
24
|
-
readonly heading: string | null;
|
|
25
|
-
readonly type: string;
|
|
26
|
-
readonly docids: readonly string[];
|
|
27
|
-
readonly score: number;
|
|
28
|
-
readonly snippet: string;
|
|
29
|
-
readonly matched_terms: readonly string[];
|
|
30
|
-
}[];
|
|
31
|
-
readonly total: number;
|
|
32
|
-
readonly offset: number;
|
|
33
|
-
readonly limit: number;
|
|
34
|
-
readonly has_more: boolean;
|
|
35
|
-
}>;
|
|
73
|
+
}): Promise<RawSearchResponse>;
|
|
36
74
|
}
|
|
37
75
|
|
|
38
76
|
/**
|
|
@@ -59,6 +97,7 @@ export async function runSearch(
|
|
|
59
97
|
offset: 0,
|
|
60
98
|
limit: options.limit,
|
|
61
99
|
has_more: false,
|
|
100
|
+
relaxed: false,
|
|
62
101
|
};
|
|
63
102
|
}
|
|
64
103
|
|
|
@@ -76,13 +115,17 @@ export async function runSearch(
|
|
|
76
115
|
type: r.type,
|
|
77
116
|
docids: r.docids,
|
|
78
117
|
score: r.score,
|
|
118
|
+
confidence: r.confidence ?? 0,
|
|
79
119
|
snippet: r.snippet,
|
|
80
120
|
matched_terms: r.matched_terms,
|
|
121
|
+
matched_fields: r.matched_fields ?? [],
|
|
122
|
+
created_at: r.created_at ?? '',
|
|
81
123
|
preview: '',
|
|
82
124
|
})),
|
|
83
125
|
total: results.total,
|
|
84
126
|
offset: results.offset,
|
|
85
127
|
limit: results.limit,
|
|
86
128
|
has_more: results.has_more,
|
|
129
|
+
relaxed: results.relaxed ?? false,
|
|
87
130
|
};
|
|
88
131
|
}
|
package/src/shared/cli/index.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export { parseArgs } from './functions/parse-args.function.ts';
|
|
2
2
|
export { formatOutput } from './functions/format-output.function.ts';
|
|
3
3
|
export { runSearch } from './functions/run-search.function.ts';
|
|
4
|
+
export { runRecall } from './functions/run-recall.function.ts';
|
|
5
|
+
export { runExport } from './functions/run-export.function.ts';
|
|
4
6
|
export { runLearn } from './functions/run-learn.function.ts';
|
|
5
7
|
export { runUnlearn } from './functions/run-unlearn.function.ts';
|
|
6
8
|
export { runContent } from './functions/run-content.function.ts';
|
|
@@ -28,6 +30,8 @@ export type {
|
|
|
28
30
|
PagedSearchDisplay,
|
|
29
31
|
} from './typings/search-display.model.ts';
|
|
30
32
|
export type { SearchClient } from './functions/run-search.function.ts';
|
|
33
|
+
export type { RecallClient } from './functions/run-recall.function.ts';
|
|
34
|
+
export type { ExportClient } from './functions/run-export.function.ts';
|
|
31
35
|
export type { LearnClient } from './functions/run-learn.function.ts';
|
|
32
36
|
export type {
|
|
33
37
|
UnlearnClient,
|
|
@@ -52,6 +52,19 @@ export interface CliOptions {
|
|
|
52
52
|
body?: string;
|
|
53
53
|
/** Comma-separated skill kbids for agent create. */
|
|
54
54
|
skills?: string[];
|
|
55
|
+
/**
|
|
56
|
+
* Recall expansion depth (0-3). Clamped to 3.
|
|
57
|
+
* Defaults to 0.
|
|
58
|
+
*/
|
|
59
|
+
depth?: number;
|
|
60
|
+
/** Comma-separated tags for scoping (learn, recall). */
|
|
61
|
+
tags?: string[];
|
|
62
|
+
/**
|
|
63
|
+
* When `true`, enables supersession by source key (learn).
|
|
64
|
+
* Re-learning edited content replaces the original section
|
|
65
|
+
* instead of creating a sibling.
|
|
66
|
+
*/
|
|
67
|
+
replace?: boolean;
|
|
55
68
|
/** Positional arguments following the sub-command. */
|
|
56
69
|
args: string[];
|
|
57
70
|
}
|
|
@@ -8,4 +8,20 @@ export interface LearnResult {
|
|
|
8
8
|
size: number;
|
|
9
9
|
/** `true` when the file was skipped without being ingested. */
|
|
10
10
|
skipped: boolean;
|
|
11
|
+
/**
|
|
12
|
+
* Kbid of the section that was superseded via `--replace`,
|
|
13
|
+
* or `null` when no supersession occurred.
|
|
14
|
+
*/
|
|
15
|
+
superseded: string | null;
|
|
16
|
+
/**
|
|
17
|
+
* Advisory warning strings returned by the engine
|
|
18
|
+
* (e.g. `"heading_missing"` when no title is provided).
|
|
19
|
+
*/
|
|
20
|
+
warnings: string[];
|
|
21
|
+
/**
|
|
22
|
+
* Sections with content similarity >= 0.85 to this section.
|
|
23
|
+
* Each entry identifies a near-duplicate section and its
|
|
24
|
+
* similarity score.
|
|
25
|
+
*/
|
|
26
|
+
near_duplicates: { kbid: string; similarity: number }[];
|
|
11
27
|
}
|
|
@@ -10,10 +10,22 @@ export interface SearchDisplay {
|
|
|
10
10
|
docids: readonly string[];
|
|
11
11
|
/** Relevance score assigned by the ranking engine. */
|
|
12
12
|
score: number;
|
|
13
|
+
/**
|
|
14
|
+
* Normalised confidence score (0.0-1.0) relative to the
|
|
15
|
+
* top result in this result set.
|
|
16
|
+
*/
|
|
17
|
+
confidence: number;
|
|
13
18
|
/** KWIC snippet from the WASM engine (~150 chars). */
|
|
14
19
|
snippet: string;
|
|
15
20
|
/** Query terms that matched within this section. */
|
|
16
21
|
matched_terms: readonly string[];
|
|
22
|
+
/**
|
|
23
|
+
* Fields that contained at least one match:
|
|
24
|
+
* subset of `["heading", "body", "code"]`.
|
|
25
|
+
*/
|
|
26
|
+
matched_fields: readonly string[];
|
|
27
|
+
/** ISO 8601 creation timestamp of the section. */
|
|
28
|
+
created_at: string;
|
|
17
29
|
/**
|
|
18
30
|
* CLI-side truncated content preview for terminal display.
|
|
19
31
|
* Populated when `--content` / `-c` is used.
|
|
@@ -33,4 +45,10 @@ export interface PagedSearchDisplay {
|
|
|
33
45
|
limit: number;
|
|
34
46
|
/** Whether more results exist beyond this page. */
|
|
35
47
|
has_more: boolean;
|
|
48
|
+
/**
|
|
49
|
+
* When `true`, the engine relaxed the query (e.g. dropped
|
|
50
|
+
* rare terms) to return results that would otherwise be
|
|
51
|
+
* empty.
|
|
52
|
+
*/
|
|
53
|
+
relaxed: boolean;
|
|
36
54
|
}
|
|
@@ -207,8 +207,12 @@ export class McpServer {
|
|
|
207
207
|
request.method === 'notifications/initialized' ||
|
|
208
208
|
request.method === 'notifications/cancelled'
|
|
209
209
|
) {
|
|
210
|
-
if (
|
|
210
|
+
if (
|
|
211
|
+
request.method === 'notifications/initialized' &&
|
|
212
|
+
!this.initialized
|
|
213
|
+
) {
|
|
211
214
|
this.initialized = true;
|
|
215
|
+
void this.runStartupHealthCheck();
|
|
212
216
|
}
|
|
213
217
|
}
|
|
214
218
|
return null;
|
|
@@ -445,4 +449,29 @@ export class McpServer {
|
|
|
445
449
|
const json = JSON.stringify(response);
|
|
446
450
|
process.stdout.write(json + '\n');
|
|
447
451
|
}
|
|
452
|
+
|
|
453
|
+
/**
|
|
454
|
+
* Runs an integrity check immediately after the MCP handshake
|
|
455
|
+
* completes. Emits a `notifications/message` warning when the
|
|
456
|
+
* check detects issues so the connected agent is aware before
|
|
457
|
+
* making requests. The server continues operating regardless of
|
|
458
|
+
* the result.
|
|
459
|
+
*/
|
|
460
|
+
private async runStartupHealthCheck(): Promise<void> {
|
|
461
|
+
try {
|
|
462
|
+
const report = await this.client.integrityCheck();
|
|
463
|
+
if (!report.ok) {
|
|
464
|
+
const summary = report.errors
|
|
465
|
+
.map((e) => `${e.type}: ${e.entity} -- ${e.detail}`)
|
|
466
|
+
.join('; ');
|
|
467
|
+
this.notify('notifications/message', {
|
|
468
|
+
level: 'warning',
|
|
469
|
+
logger: 'kbdb',
|
|
470
|
+
data: `Database integrity issues detected: ${summary}`,
|
|
471
|
+
});
|
|
472
|
+
}
|
|
473
|
+
} catch {
|
|
474
|
+
// Health check failure is non-fatal -- server continues
|
|
475
|
+
}
|
|
476
|
+
}
|
|
448
477
|
}
|
|
@@ -10,10 +10,11 @@ export function createToolDefinitions(): McpToolDefinition[] {
|
|
|
10
10
|
{
|
|
11
11
|
name: 'search',
|
|
12
12
|
description:
|
|
13
|
-
'
|
|
14
|
-
' results with
|
|
15
|
-
'
|
|
16
|
-
'
|
|
13
|
+
'Query the knowledge base by keywords.' +
|
|
14
|
+
' Returns ranked results with heading,' +
|
|
15
|
+
' snippet, and matched terms. Use multiple' +
|
|
16
|
+
' short keyword queries for best coverage.' +
|
|
17
|
+
' Use recall to get full content.',
|
|
17
18
|
inputSchema: {
|
|
18
19
|
type: 'object',
|
|
19
20
|
properties: {
|
|
@@ -49,7 +50,11 @@ export function createToolDefinitions(): McpToolDefinition[] {
|
|
|
49
50
|
},
|
|
50
51
|
{
|
|
51
52
|
name: 'learn',
|
|
52
|
-
description:
|
|
53
|
+
description:
|
|
54
|
+
'Import content into the knowledge base.' +
|
|
55
|
+
' Use for durable facts, decisions, and' +
|
|
56
|
+
' corrections. Use replace when updating' +
|
|
57
|
+
' existing knowledge. Attach tags for scoping.',
|
|
53
58
|
inputSchema: {
|
|
54
59
|
type: 'object',
|
|
55
60
|
properties: {
|
|
@@ -76,6 +81,17 @@ export function createToolDefinitions(): McpToolDefinition[] {
|
|
|
76
81
|
type: 'string',
|
|
77
82
|
description: 'Document ID to group under',
|
|
78
83
|
},
|
|
84
|
+
tags: {
|
|
85
|
+
type: 'array',
|
|
86
|
+
items: { type: 'string' },
|
|
87
|
+
description: 'Tags for scoping and filtering',
|
|
88
|
+
},
|
|
89
|
+
replace: {
|
|
90
|
+
type: 'boolean',
|
|
91
|
+
description:
|
|
92
|
+
'Replace existing section with same' +
|
|
93
|
+
' source key (supersession)',
|
|
94
|
+
},
|
|
79
95
|
},
|
|
80
96
|
required: ['content'],
|
|
81
97
|
},
|
|
@@ -268,6 +284,31 @@ export function createToolDefinitions(): McpToolDefinition[] {
|
|
|
268
284
|
openWorldHint: false,
|
|
269
285
|
},
|
|
270
286
|
},
|
|
287
|
+
{
|
|
288
|
+
name: 'export',
|
|
289
|
+
description:
|
|
290
|
+
'Export the database as a self-contained' +
|
|
291
|
+
' directory snapshot (sections, documents,' +
|
|
292
|
+
' catalog -- no indexes).',
|
|
293
|
+
inputSchema: {
|
|
294
|
+
type: 'object',
|
|
295
|
+
properties: {
|
|
296
|
+
path: {
|
|
297
|
+
type: 'string',
|
|
298
|
+
description:
|
|
299
|
+
'Export destination path' +
|
|
300
|
+
' (default: ./kbdb-export/)',
|
|
301
|
+
},
|
|
302
|
+
},
|
|
303
|
+
},
|
|
304
|
+
annotations: {
|
|
305
|
+
title: 'Export Snapshot',
|
|
306
|
+
readOnlyHint: false,
|
|
307
|
+
destructiveHint: false,
|
|
308
|
+
idempotentHint: true,
|
|
309
|
+
openWorldHint: false,
|
|
310
|
+
},
|
|
311
|
+
},
|
|
271
312
|
{
|
|
272
313
|
name: 'skill-learn',
|
|
273
314
|
description:
|
|
@@ -32,6 +32,30 @@ function asString(value: unknown, fallback: string): string {
|
|
|
32
32
|
return typeof value === 'string' ? value : fallback;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
+
/**
|
|
36
|
+
* Narrows an `unknown` value to a boolean, returning `undefined`
|
|
37
|
+
* when the value is not a boolean.
|
|
38
|
+
*/
|
|
39
|
+
function asBooleanOrUndefined(value: unknown): boolean | undefined {
|
|
40
|
+
return typeof value === 'boolean' ? value : undefined;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Narrows an `unknown` value to a `string[]`, returning `undefined`
|
|
45
|
+
* when the value is not an array of strings.
|
|
46
|
+
*/
|
|
47
|
+
function asStringArrayOrUndefined(
|
|
48
|
+
value: unknown,
|
|
49
|
+
): string[] | undefined {
|
|
50
|
+
if (
|
|
51
|
+
Array.isArray(value) &&
|
|
52
|
+
value.every((item) => typeof item === 'string')
|
|
53
|
+
) {
|
|
54
|
+
return value;
|
|
55
|
+
}
|
|
56
|
+
return undefined;
|
|
57
|
+
}
|
|
58
|
+
|
|
35
59
|
/**
|
|
36
60
|
* Narrows an `unknown` value to a `string[]`, returning an empty
|
|
37
61
|
* array when the value is not an array of strings.
|
|
@@ -82,6 +106,8 @@ export async function handleToolCall(
|
|
|
82
106
|
return await handleGc(client);
|
|
83
107
|
case 'rebuild':
|
|
84
108
|
return await handleRebuild(client);
|
|
109
|
+
case 'export':
|
|
110
|
+
return await handleExport(client, args);
|
|
85
111
|
case 'skill-learn':
|
|
86
112
|
return await handleSkillLearn(client, args);
|
|
87
113
|
case 'skill-list':
|
|
@@ -135,7 +161,15 @@ async function handleSearch(
|
|
|
135
161
|
|
|
136
162
|
const stripped = {
|
|
137
163
|
...results,
|
|
138
|
-
items: results.items.map(
|
|
164
|
+
items: results.items.map(
|
|
165
|
+
({
|
|
166
|
+
score: _score,
|
|
167
|
+
confidence: _confidence,
|
|
168
|
+
...rest
|
|
169
|
+
}: (typeof results.items)[number] & {
|
|
170
|
+
confidence?: number;
|
|
171
|
+
}) => rest,
|
|
172
|
+
),
|
|
139
173
|
};
|
|
140
174
|
|
|
141
175
|
return {
|
|
@@ -161,6 +195,8 @@ async function handleLearn(
|
|
|
161
195
|
: undefined;
|
|
162
196
|
const docid =
|
|
163
197
|
typeof args['docid'] === 'string' ? args['docid'] : undefined;
|
|
198
|
+
const tags = asStringArrayOrUndefined(args['tags']);
|
|
199
|
+
const replace = asBooleanOrUndefined(args['replace']);
|
|
164
200
|
if (sectionType.startsWith('image/') && !title) {
|
|
165
201
|
return {
|
|
166
202
|
content: [
|
|
@@ -178,12 +214,25 @@ async function handleLearn(
|
|
|
178
214
|
title,
|
|
179
215
|
description,
|
|
180
216
|
docid,
|
|
217
|
+
tags,
|
|
218
|
+
replace,
|
|
181
219
|
});
|
|
220
|
+
const normalized = {
|
|
221
|
+
kbid: result.kbid,
|
|
222
|
+
indexed_terms_count: result.indexed_terms_count ?? 0,
|
|
223
|
+
elapsed_ms: result.elapsed_ms ?? 0,
|
|
224
|
+
superseded: result.superseded ?? null,
|
|
225
|
+
warnings: result.warnings ?? [],
|
|
226
|
+
near_duplicates: (result.near_duplicates ?? []).map((d) => ({
|
|
227
|
+
kbid: d.kbid,
|
|
228
|
+
similarity: d.similarity,
|
|
229
|
+
})),
|
|
230
|
+
};
|
|
182
231
|
return {
|
|
183
232
|
content: [
|
|
184
233
|
{
|
|
185
234
|
type: 'text',
|
|
186
|
-
text: JSON.stringify(
|
|
235
|
+
text: JSON.stringify(normalized),
|
|
187
236
|
},
|
|
188
237
|
],
|
|
189
238
|
};
|
|
@@ -472,3 +521,22 @@ async function handleSkillDelete(
|
|
|
472
521
|
],
|
|
473
522
|
};
|
|
474
523
|
}
|
|
524
|
+
|
|
525
|
+
async function handleExport(
|
|
526
|
+
client: McpWorkerClient,
|
|
527
|
+
args: Record<string, unknown>,
|
|
528
|
+
): Promise<ToolCallResult> {
|
|
529
|
+
const path =
|
|
530
|
+
typeof args['path'] === 'string' ? args['path'] : undefined;
|
|
531
|
+
const result = await client.export(
|
|
532
|
+
path !== undefined ? { path } : {},
|
|
533
|
+
);
|
|
534
|
+
return {
|
|
535
|
+
content: [
|
|
536
|
+
{
|
|
537
|
+
type: 'text',
|
|
538
|
+
text: JSON.stringify(result),
|
|
539
|
+
},
|
|
540
|
+
],
|
|
541
|
+
};
|
|
542
|
+
}
|
|
@@ -45,6 +45,18 @@ export interface McpIntegrityCheckResult {
|
|
|
45
45
|
readonly elapsed_ms: number;
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
+
/** Export report returned by the daemon. */
|
|
49
|
+
export interface McpExportResult {
|
|
50
|
+
/** Absolute path to the directory where files were written. */
|
|
51
|
+
readonly path: string;
|
|
52
|
+
/** Number of section files copied to the export directory. */
|
|
53
|
+
readonly sections_exported: number;
|
|
54
|
+
/** Number of document manifest files copied. */
|
|
55
|
+
readonly documents_exported: number;
|
|
56
|
+
/** Time taken to complete the export, in milliseconds. */
|
|
57
|
+
readonly elapsed_ms: number;
|
|
58
|
+
}
|
|
59
|
+
|
|
48
60
|
/** Garbage collection report returned by the daemon. */
|
|
49
61
|
export interface McpGcResult {
|
|
50
62
|
/** Number of unreferenced sections removed. */
|
|
@@ -53,6 +65,12 @@ export interface McpGcResult {
|
|
|
53
65
|
readonly removed_bytes: number;
|
|
54
66
|
/** Time taken to complete garbage collection, in milliseconds. */
|
|
55
67
|
readonly elapsed_ms: number;
|
|
68
|
+
/**
|
|
69
|
+
* Number of sections whose source_path file no longer contains
|
|
70
|
+
* their heading text. Advisory; not auto-removed by gc.
|
|
71
|
+
* Absent on older daemon versions.
|
|
72
|
+
*/
|
|
73
|
+
readonly stale_sources?: number;
|
|
56
74
|
}
|
|
57
75
|
|
|
58
76
|
/** Index rebuild report returned by the daemon. */
|
|
@@ -96,11 +114,20 @@ export interface McpWorkerClient {
|
|
|
96
114
|
readonly score: number;
|
|
97
115
|
readonly snippet: string;
|
|
98
116
|
readonly matched_terms: readonly string[];
|
|
117
|
+
/** Fields that contained matches (heading, body, code). */
|
|
118
|
+
readonly matched_fields?: readonly string[];
|
|
119
|
+
/** ISO 8601 creation timestamp of the section. */
|
|
120
|
+
readonly created_at?: string;
|
|
99
121
|
}[];
|
|
100
122
|
readonly total: number;
|
|
101
123
|
readonly offset: number;
|
|
102
124
|
readonly limit: number;
|
|
103
125
|
readonly has_more: boolean;
|
|
126
|
+
/**
|
|
127
|
+
* `true` when results came from an automatic AND-to-OR
|
|
128
|
+
* fallback query relaxation.
|
|
129
|
+
*/
|
|
130
|
+
readonly relaxed?: boolean;
|
|
104
131
|
}>;
|
|
105
132
|
|
|
106
133
|
/**
|
|
@@ -120,6 +147,13 @@ export interface McpWorkerClient {
|
|
|
120
147
|
readonly description?: string;
|
|
121
148
|
/** Optional document ID to group this section under. */
|
|
122
149
|
readonly docid?: string;
|
|
150
|
+
/** Optional tags for scoping and filtering. */
|
|
151
|
+
readonly tags?: string[];
|
|
152
|
+
/**
|
|
153
|
+
* When `true`, replaces an existing section that has the same
|
|
154
|
+
* source key (supersession).
|
|
155
|
+
*/
|
|
156
|
+
readonly replace?: boolean;
|
|
123
157
|
}): Promise<AddSectionResult>;
|
|
124
158
|
|
|
125
159
|
/**
|
|
@@ -263,6 +297,17 @@ export interface McpWorkerClient {
|
|
|
263
297
|
readonly depth?: number;
|
|
264
298
|
}): Promise<unknown>;
|
|
265
299
|
|
|
300
|
+
/**
|
|
301
|
+
* Exports the database to a target directory as a self-contained
|
|
302
|
+
* snapshot (sections, documents, catalog -- no indexes).
|
|
303
|
+
*
|
|
304
|
+
* @param params - optional export parameters
|
|
305
|
+
* @returns export report with the resolved path and file counts
|
|
306
|
+
*/
|
|
307
|
+
export(params?: {
|
|
308
|
+
readonly path?: string;
|
|
309
|
+
}): Promise<McpExportResult>;
|
|
310
|
+
|
|
266
311
|
/** Destroys the IPC socket and clears the connection state. */
|
|
267
312
|
disconnect(): void;
|
|
268
313
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/** Current package version, kept in sync with package.json. */
|
|
2
|
-
export const VERSION = '0.2.
|
|
2
|
+
export const VERSION = '0.2.2';
|