@dikolab/kbdb 0.6.3 → 0.6.5
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/cli.cjs +681 -249
- package/dist/cli.cjs.map +4 -4
- package/dist/cli.mjs +638 -206
- package/dist/cli.mjs.map +4 -4
- package/dist/kbdb-worker.cjs +49 -7
- package/dist/kbdb-worker.cjs.map +4 -4
- package/dist/mod.cjs +1 -1
- package/dist/mod.cjs.map +1 -1
- package/dist/mod.mjs +1 -1
- package/dist/mod.mjs.map +1 -1
- package/dist/src/shared/cli/constants/defaults.constant.d.ts +1 -1
- package/dist/src/shared/cli/functions/learn-markdown-document.function.d.ts +22 -0
- package/dist/src/shared/cli/functions/learn-structured-document.function.d.ts +10 -0
- package/dist/src/shared/cli/functions/learn-target-content.function.d.ts +12 -0
- package/dist/src/shared/cli/functions/map-add-section-result.function.d.ts +12 -0
- package/dist/src/shared/cli/functions/run-agent-list.function.d.ts +13 -9
- package/dist/src/shared/cli/functions/run-learn.function.d.ts +10 -59
- package/dist/src/shared/cli/functions/run-skill-list.function.d.ts +11 -7
- package/dist/src/shared/cli/functions/split-markdown-sections.function.d.ts +16 -0
- package/dist/src/shared/cli/typings/learn-client.interface.d.ts +16 -28
- package/dist/src/shared/cli/typings/learn-result.model.d.ts +2 -0
- package/dist/src/shared/cli/typings/markdown-section.interface.d.ts +23 -0
- package/dist/src/shared/content-splitter/classes/heading-parent-tracker.class.d.ts +20 -0
- package/dist/src/shared/content-splitter/constants/content-type-maps.constant.d.ts +5 -0
- package/dist/src/shared/content-splitter/constants/split-strategy-map.constant.d.ts +4 -0
- package/dist/src/shared/content-splitter/functions/detect-content-type.function.d.ts +13 -0
- package/dist/src/shared/content-splitter/functions/flush-markdown-draft.function.d.ts +14 -0
- package/dist/src/shared/content-splitter/functions/flush-toml-draft.function.d.ts +15 -0
- package/dist/src/shared/content-splitter/functions/push-content-section.function.d.ts +16 -0
- package/dist/src/shared/content-splitter/functions/resolve-parent-ids.function.d.ts +14 -0
- package/dist/src/shared/content-splitter/functions/split-content.function.d.ts +11 -0
- package/dist/src/shared/content-splitter/functions/split-html.function.d.ts +12 -0
- package/dist/src/shared/content-splitter/functions/split-markdown.function.d.ts +13 -0
- package/dist/src/shared/content-splitter/functions/split-plain-text.function.d.ts +8 -0
- package/dist/src/shared/content-splitter/functions/split-toml.function.d.ts +12 -0
- package/dist/src/shared/content-splitter/index.d.ts +11 -0
- package/dist/src/shared/content-splitter/typings/content-format.type.d.ts +2 -0
- package/dist/src/shared/content-splitter/typings/content-section.interface.d.ts +17 -0
- package/dist/src/shared/content-splitter/typings/markdown-draft.interface.d.ts +12 -0
- package/dist/src/shared/content-splitter/typings/split-result.interface.d.ts +8 -0
- package/dist/src/shared/content-splitter/typings/split-strategy.interface.d.ts +3 -0
- package/dist/src/shared/content-splitter/typings/toml-draft.interface.d.ts +15 -0
- package/dist/src/shared/mcp/functions/build-learn-payload.function.d.ts +24 -0
- package/dist/src/shared/mcp/functions/determine-learn-split.function.d.ts +18 -0
- package/dist/src/shared/mcp/functions/handle-agent-list.function.d.ts +11 -21
- package/dist/src/shared/mcp/functions/handle-tool-call.function.d.ts +1 -15
- package/dist/src/shared/mcp/functions/handle-tool-learn.function.d.ts +3 -1
- package/dist/src/shared/mcp/functions/handle-tool-skill-list.function.d.ts +13 -3
- package/dist/src/shared/mcp/functions/learn-with-splitting.function.d.ts +22 -0
- package/dist/src/shared/mcp/functions/parse-learn-args.function.d.ts +24 -0
- package/dist/src/shared/mcp/functions/store-split-learn-sections.function.d.ts +16 -0
- package/dist/src/shared/mcp/functions/unwrap-json-content.function.d.ts +9 -0
- package/dist/src/shared/mcp/typings/learn-section-params.interface.d.ts +20 -0
- package/dist/src/shared/mcp/typings/mcp-client.interface.d.ts +4 -0
- package/dist/src/shared/mcp/typings/mcp-worker-client.interface.d.ts +4 -0
- package/dist/src/shared/query-filter/functions/matches-query.function.d.ts +17 -0
- package/dist/src/shared/version/constants/version.constant.d.ts +1 -1
- package/dist/src/shared/wasm-codec/functions/decode-one-recall-result.function.d.ts +2 -1
- package/dist/src/shared/wasm-codec/functions/decode-recall-document.function.d.ts +2 -1
- package/dist/src/shared/wasm-codec/functions/decode-recall-result.function.d.ts +2 -0
- package/dist/src/shared/wasm-codec/functions/decode-recall-sibling.function.d.ts +2 -1
- package/dist/src/shared/wasm-codec/functions/decode-scored-results.function.d.ts +6 -0
- package/dist/src/shared/wasm-codec/functions/decode-section-match.function.d.ts +2 -1
- package/dist/src/shared/wasm-codec/functions/decode-section-records.function.d.ts +4 -0
- package/dist/src/shared/wasm-codec/functions/encode-add-section-params.function.d.ts +1 -0
- package/dist/src/shared/wasm-codec/typings/add-section-input.model.d.ts +2 -0
- package/dist/src/shared/wasm-codec/typings/section-match.model.d.ts +4 -0
- package/dist/src/shared/wasm-codec/typings/section-record-trailing.model.d.ts +2 -0
- package/dist/src/shared/wasm-codec/typings/section-record.model.d.ts +2 -0
- package/dist/src/shared/worker-client/typings/recall-result.model.d.ts +12 -0
- package/dist/src/shared/worker-client/typings/search-result.model.d.ts +4 -0
- package/dist/src/shared/worker-client/typings/section.model.d.ts +2 -0
- package/dist/wasm/default-embedding/kbdb_default_embedding_bg.wasm +0 -0
- package/dist/wasm/fs-database/kbdb_fs_database_bg.wasm +0 -0
- package/dist/wasm/kb-worker/kbdb_worker_bg.wasm +0 -0
- package/dist/wasm/query-parser/kbdb_query_parser_bg.wasm +0 -0
- package/dist/worker.mjs +49 -7
- package/dist/worker.mjs.map +4 -4
- package/package.json +1 -1
package/dist/cli.cjs
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
// src/cli.ts
|
|
5
5
|
var import_node_fs10 = require("node:fs");
|
|
6
|
-
var
|
|
6
|
+
var import_node_path15 = require("node:path");
|
|
7
7
|
|
|
8
8
|
// src/shared/runtime/functions/detect-runtime.ts
|
|
9
9
|
function detectRuntime() {
|
|
@@ -31,7 +31,10 @@ var SUPPORTED_EXTENSIONS = [
|
|
|
31
31
|
".md",
|
|
32
32
|
".txt",
|
|
33
33
|
".rst",
|
|
34
|
-
".adoc"
|
|
34
|
+
".adoc",
|
|
35
|
+
".html",
|
|
36
|
+
".htm",
|
|
37
|
+
".toml"
|
|
35
38
|
];
|
|
36
39
|
|
|
37
40
|
// src/shared/log/typings/log-level.type.ts
|
|
@@ -745,6 +748,319 @@ function computeDirectoryLevel(filePath, basePath) {
|
|
|
745
748
|
return Math.min(depth + 1, MAX_LEVEL);
|
|
746
749
|
}
|
|
747
750
|
|
|
751
|
+
// src/shared/content-splitter/constants/content-type-maps.constant.ts
|
|
752
|
+
var HINT_FORMAT_MAP = {
|
|
753
|
+
markdown: "markdown",
|
|
754
|
+
"text/markdown": "markdown",
|
|
755
|
+
md: "markdown",
|
|
756
|
+
html: "html",
|
|
757
|
+
"text/html": "html",
|
|
758
|
+
toml: "toml",
|
|
759
|
+
"application/toml": "toml",
|
|
760
|
+
"text/toml": "toml",
|
|
761
|
+
"text/x-toml": "toml"
|
|
762
|
+
};
|
|
763
|
+
var EXTENSION_FORMAT_MAP = {
|
|
764
|
+
md: "markdown",
|
|
765
|
+
markdown: "markdown",
|
|
766
|
+
html: "html",
|
|
767
|
+
htm: "html",
|
|
768
|
+
toml: "toml"
|
|
769
|
+
};
|
|
770
|
+
|
|
771
|
+
// src/shared/content-splitter/functions/detect-content-type.function.ts
|
|
772
|
+
function detectContentType(content, typeHint, filePath) {
|
|
773
|
+
const hinted = typeHint && HINT_FORMAT_MAP[typeHint.toLowerCase()];
|
|
774
|
+
if (hinted) return hinted;
|
|
775
|
+
const extension = filePath?.split(".").pop()?.toLowerCase();
|
|
776
|
+
const extMatch = extension && EXTENSION_FORMAT_MAP[extension];
|
|
777
|
+
if (extMatch) return extMatch;
|
|
778
|
+
return sniffContentType(content);
|
|
779
|
+
}
|
|
780
|
+
function sniffContentType(content) {
|
|
781
|
+
const trimmed = content.trimStart();
|
|
782
|
+
if (/^<!DOCTYPE/i.test(trimmed) || /^<html/i.test(trimmed)) {
|
|
783
|
+
return "html";
|
|
784
|
+
}
|
|
785
|
+
if (trimmed.startsWith("[") && trimmed.includes("=")) {
|
|
786
|
+
return "toml";
|
|
787
|
+
}
|
|
788
|
+
return "plain-text";
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
// src/shared/content-splitter/classes/heading-parent-tracker.class.ts
|
|
792
|
+
var HeadingParentTracker = class {
|
|
793
|
+
stack = [];
|
|
794
|
+
/**
|
|
795
|
+
* Resolves the parent index for a heading at `level`
|
|
796
|
+
* appearing at output position `index`, then records the
|
|
797
|
+
* heading so subsequent, deeper headings can nest under it.
|
|
798
|
+
*
|
|
799
|
+
* @param level - heading depth, shallower is smaller
|
|
800
|
+
* @param index - position of this heading in the output
|
|
801
|
+
* sections array
|
|
802
|
+
* @returns the parent's output index, or `null` when the
|
|
803
|
+
* heading is at the root
|
|
804
|
+
*/
|
|
805
|
+
resolve(level, index) {
|
|
806
|
+
while (this.stack.length > 0 && this.stack[this.stack.length - 1].level >= level) {
|
|
807
|
+
this.stack.pop();
|
|
808
|
+
}
|
|
809
|
+
const parentIndex = this.stack.length > 0 ? this.stack[this.stack.length - 1].index : null;
|
|
810
|
+
this.stack.push({ level, index });
|
|
811
|
+
return parentIndex;
|
|
812
|
+
}
|
|
813
|
+
};
|
|
814
|
+
|
|
815
|
+
// src/shared/content-splitter/functions/push-content-section.function.ts
|
|
816
|
+
function pushContentSection(sections, tracker, content, title, level) {
|
|
817
|
+
if (level === void 0) {
|
|
818
|
+
sections.push({ content, parentIndex: null });
|
|
819
|
+
return;
|
|
820
|
+
}
|
|
821
|
+
sections.push({
|
|
822
|
+
title,
|
|
823
|
+
level,
|
|
824
|
+
content,
|
|
825
|
+
parentIndex: tracker.resolve(level, sections.length)
|
|
826
|
+
});
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
// src/shared/content-splitter/functions/flush-markdown-draft.function.ts
|
|
830
|
+
function flushMarkdownDraft(draft, sections, tracker) {
|
|
831
|
+
const body = draft.lines.join("\n").trimEnd();
|
|
832
|
+
if (draft.title === void 0 && body.length === 0) return;
|
|
833
|
+
pushContentSection(
|
|
834
|
+
sections,
|
|
835
|
+
tracker,
|
|
836
|
+
body,
|
|
837
|
+
draft.title,
|
|
838
|
+
draft.level
|
|
839
|
+
);
|
|
840
|
+
}
|
|
841
|
+
|
|
842
|
+
// src/shared/content-splitter/functions/split-markdown.function.ts
|
|
843
|
+
var HEADING_PATTERN = /^(#{1,6})\s+(.+)$/;
|
|
844
|
+
function splitMarkdown(content) {
|
|
845
|
+
const sections = [];
|
|
846
|
+
const tracker = new HeadingParentTracker();
|
|
847
|
+
let draft = { lines: [] };
|
|
848
|
+
let inCodeBlock = false;
|
|
849
|
+
for (const line of content.split("\n")) {
|
|
850
|
+
if (line.startsWith("```") || line.startsWith("~~~")) {
|
|
851
|
+
inCodeBlock = !inCodeBlock;
|
|
852
|
+
draft.lines.push(line);
|
|
853
|
+
continue;
|
|
854
|
+
}
|
|
855
|
+
const heading = inCodeBlock ? null : HEADING_PATTERN.exec(line);
|
|
856
|
+
if (heading) {
|
|
857
|
+
flushMarkdownDraft(draft, sections, tracker);
|
|
858
|
+
draft = {
|
|
859
|
+
title: heading[2].trim(),
|
|
860
|
+
level: heading[1].length,
|
|
861
|
+
lines: []
|
|
862
|
+
};
|
|
863
|
+
continue;
|
|
864
|
+
}
|
|
865
|
+
draft.lines.push(line);
|
|
866
|
+
}
|
|
867
|
+
flushMarkdownDraft(draft, sections, tracker);
|
|
868
|
+
return sections.length > 0 ? sections : [{ content: content.trimEnd(), parentIndex: null }];
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
// src/shared/content-splitter/functions/split-html.function.ts
|
|
872
|
+
var HEADING_PATTERN2 = /<h([1-6])[^>]*>(.*?)<\/h\1>/gi;
|
|
873
|
+
function splitHtml(content) {
|
|
874
|
+
const matches = [...content.matchAll(HEADING_PATTERN2)];
|
|
875
|
+
if (matches.length === 0) {
|
|
876
|
+
return [{ content: content.trimEnd(), parentIndex: null }];
|
|
877
|
+
}
|
|
878
|
+
const sections = [];
|
|
879
|
+
const tracker = new HeadingParentTracker();
|
|
880
|
+
const firstIndex = matches[0].index;
|
|
881
|
+
const preamble = content.slice(0, firstIndex).trimEnd();
|
|
882
|
+
if (preamble.length > 0) {
|
|
883
|
+
pushContentSection(sections, tracker, preamble);
|
|
884
|
+
}
|
|
885
|
+
matches.forEach((match, i) => {
|
|
886
|
+
const start = match.index + match[0].length;
|
|
887
|
+
const end = matches[i + 1]?.index ?? content.length;
|
|
888
|
+
pushContentSection(
|
|
889
|
+
sections,
|
|
890
|
+
tracker,
|
|
891
|
+
content.slice(start, end).trimEnd(),
|
|
892
|
+
match[2].trim(),
|
|
893
|
+
Number(match[1])
|
|
894
|
+
);
|
|
895
|
+
});
|
|
896
|
+
return sections;
|
|
897
|
+
}
|
|
898
|
+
|
|
899
|
+
// src/shared/content-splitter/functions/flush-toml-draft.function.ts
|
|
900
|
+
function flushTomlDraft(draft, sections, pathIndex) {
|
|
901
|
+
const body = draft.lines.join("\n").trimEnd();
|
|
902
|
+
if (draft.title === void 0 && body.length === 0) return;
|
|
903
|
+
if (draft.title === void 0) {
|
|
904
|
+
sections.push({ content: body, parentIndex: null });
|
|
905
|
+
return;
|
|
906
|
+
}
|
|
907
|
+
const path = draft.path ?? draft.title;
|
|
908
|
+
sections.push({
|
|
909
|
+
title: draft.title,
|
|
910
|
+
content: body,
|
|
911
|
+
parentIndex: resolveParentIndex(path, pathIndex)
|
|
912
|
+
});
|
|
913
|
+
pathIndex.set(path, sections.length - 1);
|
|
914
|
+
}
|
|
915
|
+
function resolveParentIndex(path, pathIndex) {
|
|
916
|
+
if (/^["']/.test(path)) return null;
|
|
917
|
+
const segments = path.split(".");
|
|
918
|
+
segments.pop();
|
|
919
|
+
if (segments.length === 0) return null;
|
|
920
|
+
return pathIndex.get(segments.join(".")) ?? null;
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
// src/shared/content-splitter/functions/split-toml.function.ts
|
|
924
|
+
var HEADER_PATTERN = /^\[([^\]]+)\]\s*$/;
|
|
925
|
+
var QUOTED_PATTERN = /^(["'])(.*)\1$/;
|
|
926
|
+
function splitToml(content) {
|
|
927
|
+
const sections = [];
|
|
928
|
+
const pathIndex = /* @__PURE__ */ new Map();
|
|
929
|
+
let draft = { lines: [] };
|
|
930
|
+
for (const line of content.split("\n")) {
|
|
931
|
+
const header = HEADER_PATTERN.exec(line);
|
|
932
|
+
if (header) {
|
|
933
|
+
flushTomlDraft(draft, sections, pathIndex);
|
|
934
|
+
draft = { ...parseHeader(header[1]), lines: [] };
|
|
935
|
+
continue;
|
|
936
|
+
}
|
|
937
|
+
draft.lines.push(line);
|
|
938
|
+
}
|
|
939
|
+
flushTomlDraft(draft, sections, pathIndex);
|
|
940
|
+
return sections.length > 0 ? sections : [{ content: content.trimEnd(), parentIndex: null }];
|
|
941
|
+
}
|
|
942
|
+
function parseHeader(inner) {
|
|
943
|
+
const trimmed = inner.trim();
|
|
944
|
+
const quoted = QUOTED_PATTERN.exec(trimmed);
|
|
945
|
+
return quoted ? { title: quoted[2], path: trimmed } : { title: trimmed, path: trimmed };
|
|
946
|
+
}
|
|
947
|
+
|
|
948
|
+
// src/shared/content-splitter/functions/split-plain-text.function.ts
|
|
949
|
+
function splitPlainText(content) {
|
|
950
|
+
return [{ content, parentIndex: null }];
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
// src/shared/content-splitter/constants/split-strategy-map.constant.ts
|
|
954
|
+
var SPLIT_STRATEGY_MAP = {
|
|
955
|
+
markdown: splitMarkdown,
|
|
956
|
+
html: splitHtml,
|
|
957
|
+
toml: splitToml,
|
|
958
|
+
"plain-text": splitPlainText
|
|
959
|
+
};
|
|
960
|
+
|
|
961
|
+
// src/shared/content-splitter/functions/split-content.function.ts
|
|
962
|
+
function splitContent(content, typeHint, filePath) {
|
|
963
|
+
const format = detectContentType(content, typeHint, filePath);
|
|
964
|
+
return {
|
|
965
|
+
format,
|
|
966
|
+
sections: SPLIT_STRATEGY_MAP[format](content)
|
|
967
|
+
};
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
// src/shared/content-splitter/functions/resolve-parent-ids.function.ts
|
|
971
|
+
function resolveParentIds(sections, kbids) {
|
|
972
|
+
return sections.map(
|
|
973
|
+
(section) => section.parentIndex === null ? null : kbids[section.parentIndex]
|
|
974
|
+
);
|
|
975
|
+
}
|
|
976
|
+
|
|
977
|
+
// src/shared/cli/functions/map-add-section-result.function.ts
|
|
978
|
+
function mapAddSectionResult(result, path, size, sectionType) {
|
|
979
|
+
return {
|
|
980
|
+
kbid: result.items[0] ?? "",
|
|
981
|
+
indexed_terms_count: 0,
|
|
982
|
+
type: sectionType,
|
|
983
|
+
path,
|
|
984
|
+
size,
|
|
985
|
+
skipped: false,
|
|
986
|
+
superseded: result.superseded ?? null,
|
|
987
|
+
warnings: result.warnings ?? [],
|
|
988
|
+
near_duplicates: result.near_duplicates ?? []
|
|
989
|
+
};
|
|
990
|
+
}
|
|
991
|
+
|
|
992
|
+
// src/shared/cli/functions/learn-structured-document.function.ts
|
|
993
|
+
var import_node_path3 = require("node:path");
|
|
994
|
+
async function learnStructuredDocument(client, options, path, splitResult, sourcePath) {
|
|
995
|
+
const { sections } = splitResult;
|
|
996
|
+
const firstTitled = sections.find((s) => s.title !== void 0);
|
|
997
|
+
const docTitle = firstTitled?.title ?? (0, import_node_path3.basename)(path);
|
|
998
|
+
const kbids = [];
|
|
999
|
+
const results = [];
|
|
1000
|
+
for (const section of sections) {
|
|
1001
|
+
const [parent] = resolveParentIds([section], kbids);
|
|
1002
|
+
const added = await client.addSection({
|
|
1003
|
+
sectionType: "text",
|
|
1004
|
+
content: section.content,
|
|
1005
|
+
title: section.title,
|
|
1006
|
+
description: options.description,
|
|
1007
|
+
docid: path,
|
|
1008
|
+
tags: options.tags,
|
|
1009
|
+
replace: options.replace,
|
|
1010
|
+
sourcePath,
|
|
1011
|
+
level: section.level,
|
|
1012
|
+
parent: parent ?? void 0
|
|
1013
|
+
});
|
|
1014
|
+
kbids.push(added.items[0] ?? "");
|
|
1015
|
+
results.push(
|
|
1016
|
+
mapAddSectionResult(
|
|
1017
|
+
added,
|
|
1018
|
+
path,
|
|
1019
|
+
section.content.length,
|
|
1020
|
+
"text"
|
|
1021
|
+
)
|
|
1022
|
+
);
|
|
1023
|
+
}
|
|
1024
|
+
await client.groupSections(docTitle, kbids);
|
|
1025
|
+
return results;
|
|
1026
|
+
}
|
|
1027
|
+
|
|
1028
|
+
// src/shared/cli/functions/learn-target-content.function.ts
|
|
1029
|
+
async function learnTargetContent(client, options, path, content, sourcePath, level) {
|
|
1030
|
+
if (!options.title) {
|
|
1031
|
+
const isStdin = path === "-";
|
|
1032
|
+
const split = splitContent(
|
|
1033
|
+
content,
|
|
1034
|
+
isStdin ? "markdown" : void 0,
|
|
1035
|
+
isStdin ? void 0 : path
|
|
1036
|
+
);
|
|
1037
|
+
const hasTitled = split.sections.some(
|
|
1038
|
+
(s) => s.title !== void 0
|
|
1039
|
+
);
|
|
1040
|
+
if (split.sections.length >= 2 && hasTitled) {
|
|
1041
|
+
return learnStructuredDocument(
|
|
1042
|
+
client,
|
|
1043
|
+
options,
|
|
1044
|
+
path,
|
|
1045
|
+
split,
|
|
1046
|
+
sourcePath
|
|
1047
|
+
);
|
|
1048
|
+
}
|
|
1049
|
+
}
|
|
1050
|
+
const result = await client.addSection({
|
|
1051
|
+
sectionType: "text",
|
|
1052
|
+
content,
|
|
1053
|
+
title: options.title,
|
|
1054
|
+
description: options.description,
|
|
1055
|
+
docid: options.docid,
|
|
1056
|
+
tags: options.tags,
|
|
1057
|
+
replace: options.replace,
|
|
1058
|
+
sourcePath,
|
|
1059
|
+
level
|
|
1060
|
+
});
|
|
1061
|
+
return [mapAddSectionResult(result, path, content.length, "text")];
|
|
1062
|
+
}
|
|
1063
|
+
|
|
748
1064
|
// src/shared/cli/functions/run-learn.function.ts
|
|
749
1065
|
async function runLearn(client, options, io) {
|
|
750
1066
|
log(
|
|
@@ -759,37 +1075,30 @@ async function runLearn(client, options, io) {
|
|
|
759
1075
|
if (stdinConsumed) continue;
|
|
760
1076
|
stdinConsumed = true;
|
|
761
1077
|
const content = await readStdin();
|
|
762
|
-
const result = await client.addSection({
|
|
763
|
-
sectionType: "text",
|
|
764
|
-
content,
|
|
765
|
-
title: options.title,
|
|
766
|
-
description: options.description,
|
|
767
|
-
docid: options.docid,
|
|
768
|
-
tags: options.tags,
|
|
769
|
-
replace: options.replace,
|
|
770
|
-
level: options.level
|
|
771
|
-
});
|
|
772
1078
|
results.push(
|
|
773
|
-
|
|
1079
|
+
...await learnTargetContent(
|
|
1080
|
+
client,
|
|
1081
|
+
options,
|
|
1082
|
+
"-",
|
|
1083
|
+
content,
|
|
1084
|
+
void 0,
|
|
1085
|
+
options.level
|
|
1086
|
+
)
|
|
774
1087
|
);
|
|
775
1088
|
continue;
|
|
776
1089
|
}
|
|
777
1090
|
const files = collectFiles(target);
|
|
778
1091
|
for (const file of files) {
|
|
779
1092
|
const content = (0, import_node_fs2.readFileSync)(file, "utf-8");
|
|
780
|
-
const result = await client.addSection({
|
|
781
|
-
sectionType: "text",
|
|
782
|
-
content,
|
|
783
|
-
title: options.title,
|
|
784
|
-
description: options.description,
|
|
785
|
-
docid: options.docid,
|
|
786
|
-
tags: options.tags,
|
|
787
|
-
replace: options.replace,
|
|
788
|
-
sourcePath: file,
|
|
789
|
-
level: options.level ?? computeDirectoryLevel(file, target)
|
|
790
|
-
});
|
|
791
1093
|
results.push(
|
|
792
|
-
|
|
1094
|
+
...await learnTargetContent(
|
|
1095
|
+
client,
|
|
1096
|
+
options,
|
|
1097
|
+
file,
|
|
1098
|
+
content,
|
|
1099
|
+
file,
|
|
1100
|
+
options.level ?? computeDirectoryLevel(file, target)
|
|
1101
|
+
)
|
|
793
1102
|
);
|
|
794
1103
|
}
|
|
795
1104
|
}
|
|
@@ -799,19 +1108,6 @@ async function runLearn(client, options, io) {
|
|
|
799
1108
|
);
|
|
800
1109
|
return results;
|
|
801
1110
|
}
|
|
802
|
-
function mapAddSectionResult(result, path, size, sectionType) {
|
|
803
|
-
return {
|
|
804
|
-
kbid: result.items[0] ?? "",
|
|
805
|
-
indexed_terms_count: 0,
|
|
806
|
-
type: sectionType,
|
|
807
|
-
path,
|
|
808
|
-
size,
|
|
809
|
-
skipped: false,
|
|
810
|
-
superseded: result.superseded ?? null,
|
|
811
|
-
warnings: result.warnings ?? [],
|
|
812
|
-
near_duplicates: result.near_duplicates ?? []
|
|
813
|
-
};
|
|
814
|
-
}
|
|
815
1111
|
function readProcessStdin() {
|
|
816
1112
|
return new Promise((resolve7) => {
|
|
817
1113
|
const chunks = [];
|
|
@@ -906,32 +1202,32 @@ async function runRebuild(client, _options) {
|
|
|
906
1202
|
|
|
907
1203
|
// src/shared/cli/functions/find-db.function.ts
|
|
908
1204
|
var import_node_fs3 = require("node:fs");
|
|
909
|
-
var
|
|
1205
|
+
var import_node_path4 = require("node:path");
|
|
910
1206
|
function findDb(dbPath) {
|
|
911
1207
|
if (dbPath) {
|
|
912
|
-
const target = (0,
|
|
1208
|
+
const target = (0, import_node_path4.join)((0, import_node_path4.resolve)(dbPath), ".kbdb");
|
|
913
1209
|
return (0, import_node_fs3.existsSync)(target) ? target : null;
|
|
914
1210
|
}
|
|
915
1211
|
let current = process.cwd();
|
|
916
|
-
let parent = (0,
|
|
1212
|
+
let parent = (0, import_node_path4.dirname)(current);
|
|
917
1213
|
while (parent !== current) {
|
|
918
|
-
const candidate2 = (0,
|
|
1214
|
+
const candidate2 = (0, import_node_path4.join)(current, ".kbdb");
|
|
919
1215
|
if ((0, import_node_fs3.existsSync)(candidate2)) return candidate2;
|
|
920
1216
|
current = parent;
|
|
921
|
-
parent = (0,
|
|
1217
|
+
parent = (0, import_node_path4.dirname)(current);
|
|
922
1218
|
}
|
|
923
|
-
const candidate = (0,
|
|
1219
|
+
const candidate = (0, import_node_path4.join)(current, ".kbdb");
|
|
924
1220
|
return (0, import_node_fs3.existsSync)(candidate) ? candidate : null;
|
|
925
1221
|
}
|
|
926
1222
|
|
|
927
1223
|
// src/shared/cli/functions/run-init.function.ts
|
|
928
1224
|
var import_node_fs5 = require("node:fs");
|
|
929
|
-
var
|
|
1225
|
+
var import_node_path6 = require("node:path");
|
|
930
1226
|
|
|
931
1227
|
// src/shared/cli/functions/install-default-skills.function.ts
|
|
932
1228
|
var import_node_crypto = require("node:crypto");
|
|
933
1229
|
var import_node_fs4 = require("node:fs");
|
|
934
|
-
var
|
|
1230
|
+
var import_node_path5 = require("node:path");
|
|
935
1231
|
var BASE32_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
|
|
936
1232
|
function base32Encode(bytes) {
|
|
937
1233
|
let result = "";
|
|
@@ -992,8 +1288,8 @@ function installSkill(sectionsDir, skill) {
|
|
|
992
1288
|
});
|
|
993
1289
|
const kbid = computeSectionKbid("text/markdown", content);
|
|
994
1290
|
const prefix = kbid.slice(0, 2);
|
|
995
|
-
const shardDir = (0,
|
|
996
|
-
const filePath = (0,
|
|
1291
|
+
const shardDir = (0, import_node_path5.join)(sectionsDir, prefix);
|
|
1292
|
+
const filePath = (0, import_node_path5.join)(shardDir, `${kbid}.section`);
|
|
997
1293
|
if ((0, import_node_fs4.existsSync)(filePath)) {
|
|
998
1294
|
return;
|
|
999
1295
|
}
|
|
@@ -1021,7 +1317,7 @@ var DEFAULT_SKILLS = [
|
|
|
1021
1317
|
}
|
|
1022
1318
|
];
|
|
1023
1319
|
function installDefaultSkills(dbDir) {
|
|
1024
|
-
const sectionsDir = (0,
|
|
1320
|
+
const sectionsDir = (0, import_node_path5.join)(dbDir, "sections");
|
|
1025
1321
|
for (const skill of DEFAULT_SKILLS) {
|
|
1026
1322
|
installSkill(sectionsDir, skill);
|
|
1027
1323
|
}
|
|
@@ -1046,19 +1342,19 @@ var GITIGNORE = [
|
|
|
1046
1342
|
].join("\n");
|
|
1047
1343
|
function createScaffold(dbDir) {
|
|
1048
1344
|
(0, import_node_fs5.mkdirSync)(dbDir, { recursive: true });
|
|
1049
|
-
(0, import_node_fs5.mkdirSync)((0,
|
|
1050
|
-
(0, import_node_fs5.mkdirSync)((0,
|
|
1051
|
-
(0, import_node_fs5.writeFileSync)((0,
|
|
1052
|
-
(0, import_node_fs5.writeFileSync)((0,
|
|
1053
|
-
(0, import_node_fs5.writeFileSync)((0,
|
|
1054
|
-
(0, import_node_fs5.writeFileSync)((0,
|
|
1055
|
-
(0, import_node_fs5.writeFileSync)((0,
|
|
1056
|
-
(0, import_node_fs5.writeFileSync)((0,
|
|
1345
|
+
(0, import_node_fs5.mkdirSync)((0, import_node_path6.join)(dbDir, "sections"));
|
|
1346
|
+
(0, import_node_fs5.mkdirSync)((0, import_node_path6.join)(dbDir, "documents"));
|
|
1347
|
+
(0, import_node_fs5.writeFileSync)((0, import_node_path6.join)(dbDir, "catalog.toml"), CATALOG_TOML);
|
|
1348
|
+
(0, import_node_fs5.writeFileSync)((0, import_node_path6.join)(dbDir, "corpus.bin"), "");
|
|
1349
|
+
(0, import_node_fs5.writeFileSync)((0, import_node_path6.join)(dbDir, "inverted.idx"), "");
|
|
1350
|
+
(0, import_node_fs5.writeFileSync)((0, import_node_path6.join)(dbDir, "positional.idx"), "");
|
|
1351
|
+
(0, import_node_fs5.writeFileSync)((0, import_node_path6.join)(dbDir, "worker.toml"), WORKER_TOML);
|
|
1352
|
+
(0, import_node_fs5.writeFileSync)((0, import_node_path6.join)(dbDir, ".gitignore"), GITIGNORE);
|
|
1057
1353
|
}
|
|
1058
1354
|
function runInit(options) {
|
|
1059
1355
|
log("running init", 0 /* DEBUG */);
|
|
1060
|
-
const basePath = options.dbPath ? (0,
|
|
1061
|
-
const dbDir = (0,
|
|
1356
|
+
const basePath = options.dbPath ? (0, import_node_path6.resolve)(options.dbPath) : process.cwd();
|
|
1357
|
+
const dbDir = (0, import_node_path6.join)(basePath, ".kbdb");
|
|
1062
1358
|
try {
|
|
1063
1359
|
if ((0, import_node_fs5.existsSync)(dbDir)) {
|
|
1064
1360
|
return {
|
|
@@ -1199,28 +1495,27 @@ async function runSkillLearn(client, options) {
|
|
|
1199
1495
|
};
|
|
1200
1496
|
}
|
|
1201
1497
|
|
|
1498
|
+
// src/shared/query-filter/functions/matches-query.function.ts
|
|
1499
|
+
function matchesQuery(query, ...fields) {
|
|
1500
|
+
if (!query) return true;
|
|
1501
|
+
const needle = query.toLowerCase();
|
|
1502
|
+
return fields.some(
|
|
1503
|
+
(field) => typeof field === "string" && field.toLowerCase().includes(needle)
|
|
1504
|
+
);
|
|
1505
|
+
}
|
|
1506
|
+
|
|
1202
1507
|
// src/shared/cli/functions/run-skill-list.function.ts
|
|
1203
|
-
async function runSkillList(client,
|
|
1508
|
+
async function runSkillList(client, options) {
|
|
1204
1509
|
log("running skill-list", 0 /* DEBUG */);
|
|
1205
1510
|
const records = await client.listByType("skill");
|
|
1206
|
-
const
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
}
|
|
1213
|
-
} catch {
|
|
1214
|
-
}
|
|
1215
|
-
return {
|
|
1216
|
-
kbid: r.kbid,
|
|
1217
|
-
name: r.title,
|
|
1218
|
-
description: r.description,
|
|
1219
|
-
argumentCount
|
|
1220
|
-
};
|
|
1221
|
-
});
|
|
1511
|
+
const query = options.args.join(" ").toLowerCase();
|
|
1512
|
+
const filtered = records.filter(
|
|
1513
|
+
(r) => matchesQuery(query, r.title, r.description)
|
|
1514
|
+
);
|
|
1515
|
+
const names = filtered.map((r) => r.title);
|
|
1516
|
+
const data = { items: names, total: names.length, offset: 0 };
|
|
1222
1517
|
return {
|
|
1223
|
-
output: JSON.stringify(
|
|
1518
|
+
output: JSON.stringify(data, null, 2),
|
|
1224
1519
|
exitCode: 0
|
|
1225
1520
|
};
|
|
1226
1521
|
}
|
|
@@ -1349,16 +1644,15 @@ async function runAgentCreate(client, options) {
|
|
|
1349
1644
|
}
|
|
1350
1645
|
|
|
1351
1646
|
// src/shared/cli/functions/run-agent-list.function.ts
|
|
1352
|
-
async function runAgentList(client,
|
|
1647
|
+
async function runAgentList(client, options) {
|
|
1353
1648
|
log("running agent-list", 0 /* DEBUG */);
|
|
1354
1649
|
const docs = await client.listDocumentsByType("agent");
|
|
1355
|
-
const
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
}));
|
|
1650
|
+
const query = options.args.join(" ").toLowerCase();
|
|
1651
|
+
const filtered = docs.filter((d) => matchesQuery(query, d.title));
|
|
1652
|
+
const names = filtered.map((d) => d.title);
|
|
1653
|
+
const data = { items: names, total: names.length, offset: 0 };
|
|
1360
1654
|
return {
|
|
1361
|
-
output: JSON.stringify(
|
|
1655
|
+
output: JSON.stringify(data, null, 2),
|
|
1362
1656
|
exitCode: 0
|
|
1363
1657
|
};
|
|
1364
1658
|
}
|
|
@@ -1464,7 +1758,7 @@ async function runAgentSearch(client, options) {
|
|
|
1464
1758
|
}
|
|
1465
1759
|
|
|
1466
1760
|
// src/shared/cli/functions/run-import.function.ts
|
|
1467
|
-
var
|
|
1761
|
+
var import_node_path7 = require("node:path");
|
|
1468
1762
|
async function runImport(client, options) {
|
|
1469
1763
|
const from = options.from;
|
|
1470
1764
|
if (!from) {
|
|
@@ -1473,7 +1767,7 @@ async function runImport(client, options) {
|
|
|
1473
1767
|
throw new Error(msg);
|
|
1474
1768
|
}
|
|
1475
1769
|
return client.import({
|
|
1476
|
-
from: (0,
|
|
1770
|
+
from: (0, import_node_path7.resolve)(process.cwd(), from),
|
|
1477
1771
|
dryRun: options.dryRun === true
|
|
1478
1772
|
});
|
|
1479
1773
|
}
|
|
@@ -1826,7 +2120,7 @@ async function handleTypedSearch(client, options, type) {
|
|
|
1826
2120
|
}
|
|
1827
2121
|
|
|
1828
2122
|
// src/shared/version/constants/version.constant.ts
|
|
1829
|
-
var VERSION = "0.6.
|
|
2123
|
+
var VERSION = "0.6.5";
|
|
1830
2124
|
|
|
1831
2125
|
// src/shared/cli/functions/generate-help.function.ts
|
|
1832
2126
|
var KNOWN_COMMANDS = /* @__PURE__ */ new Set([
|
|
@@ -1854,13 +2148,13 @@ var GROUP_SUBCOMMANDS = {
|
|
|
1854
2148
|
],
|
|
1855
2149
|
skill: [
|
|
1856
2150
|
["learn", "Create a new skill definition"],
|
|
1857
|
-
["list", "List
|
|
2151
|
+
["list", "List skills (filter by keyword)"],
|
|
1858
2152
|
["get", "Retrieve a skill by name or kbid"],
|
|
1859
2153
|
["delete", "Remove a skill"]
|
|
1860
2154
|
],
|
|
1861
2155
|
agent: [
|
|
1862
2156
|
["create", "Create an agent with skill refs"],
|
|
1863
|
-
["list", "List
|
|
2157
|
+
["list", "List agents (filter by keyword)"],
|
|
1864
2158
|
["get", "Retrieve an agent by docid"],
|
|
1865
2159
|
["delete", "Remove an agent"]
|
|
1866
2160
|
],
|
|
@@ -1905,9 +2199,9 @@ Usage: kbdb [options]
|
|
|
1905
2199
|
kbdb <command> <subcommand> [options] ...[params]
|
|
1906
2200
|
|
|
1907
2201
|
Knowledge Base:
|
|
1908
|
-
learn Import content
|
|
2202
|
+
learn Import content (auto-splits structured formats)
|
|
1909
2203
|
unlearn Remove sections by kbid
|
|
1910
|
-
search Query the knowledge base
|
|
2204
|
+
search Query the knowledge base (sibling boost)
|
|
1911
2205
|
recall Retrieve section context by kbid
|
|
1912
2206
|
content Compose rendered content from ids
|
|
1913
2207
|
|
|
@@ -1926,28 +2220,34 @@ Maintenance:
|
|
|
1926
2220
|
|
|
1927
2221
|
Skills:
|
|
1928
2222
|
skill learn Create a new skill definition
|
|
1929
|
-
skill list List
|
|
2223
|
+
skill list List skills (filter by keyword)
|
|
1930
2224
|
skill get Retrieve a skill by name or kbid
|
|
1931
2225
|
skill delete Remove a skill
|
|
2226
|
+
skill search Search skills by keyword
|
|
1932
2227
|
|
|
1933
2228
|
Agents:
|
|
1934
2229
|
agent create Create an agent with skill refs
|
|
1935
|
-
agent list List
|
|
2230
|
+
agent list List agents (filter by keyword)
|
|
1936
2231
|
agent get Retrieve an agent by docid
|
|
1937
2232
|
agent delete Remove an agent
|
|
1938
|
-
|
|
1939
|
-
Worker:
|
|
1940
|
-
worker stop Stop the worker daemon
|
|
1941
|
-
worker restart Restart the worker daemon
|
|
2233
|
+
agent search Search agents by keyword
|
|
1942
2234
|
|
|
1943
2235
|
Server:
|
|
1944
2236
|
mcp Start MCP server mode (stdio)
|
|
1945
2237
|
|
|
1946
2238
|
Global Options:
|
|
1947
2239
|
-h, --help Show this help message
|
|
1948
|
-
|
|
2240
|
+
--version Show version information
|
|
2241
|
+
-v, --verbose Log warnings (-vv info, -vvv debug)
|
|
1949
2242
|
--db <path> Path to .kbdb directory
|
|
1950
|
-
--format <fmt> Output format (json|text|mcp)
|
|
2243
|
+
--format <fmt> Output format (rec|json|text|mcp)
|
|
2244
|
+
--timeout-ms <ms> Request timeout (default 30000)
|
|
2245
|
+
--retry <n> Retries on timeout (default 1)
|
|
2246
|
+
--non-interactive Suppress prompts
|
|
2247
|
+
|
|
2248
|
+
Worker:
|
|
2249
|
+
worker stop Stop background daemon
|
|
2250
|
+
worker restart Restart background daemon
|
|
1951
2251
|
|
|
1952
2252
|
Run "kbdb <command> --help" for detailed information.
|
|
1953
2253
|
`;
|
|
@@ -2004,9 +2304,22 @@ Options:
|
|
|
2004
2304
|
--replace Supersede existing section by source key
|
|
2005
2305
|
--db <path> Path to .kbdb directory
|
|
2006
2306
|
|
|
2307
|
+
Content splitting:
|
|
2308
|
+
Structured formats are automatically split
|
|
2309
|
+
into independent sections that share a docid.
|
|
2310
|
+
Each section carries a level (heading depth)
|
|
2311
|
+
and parent (kbid of enclosing section).
|
|
2312
|
+
Providing --title imports as a single section
|
|
2313
|
+
(skips splitting).
|
|
2314
|
+
|
|
2315
|
+
Supported formats:
|
|
2316
|
+
Markdown .md, text/markdown ATX headings
|
|
2317
|
+
HTML .html, text/html <h1>-<h6> tags
|
|
2318
|
+
TOML .toml, application/toml [section]
|
|
2319
|
+
Plain .txt, text/plain no splitting
|
|
2320
|
+
|
|
2007
2321
|
Output:
|
|
2008
|
-
|
|
2009
|
-
superseded, warnings, near_duplicates }
|
|
2322
|
+
{ items, total, offset } envelope
|
|
2010
2323
|
|
|
2011
2324
|
Examples:
|
|
2012
2325
|
kbdb learn README.md
|
|
@@ -2041,12 +2354,23 @@ Arguments:
|
|
|
2041
2354
|
Options:
|
|
2042
2355
|
--mode <mode> Result granularity (sections|documents|stats)
|
|
2043
2356
|
--limit <n> Max results (default: 20)
|
|
2044
|
-
--format <fmt> Output format (json|text|mcp)
|
|
2357
|
+
--format <fmt> Output format (rec|json|text|mcp)
|
|
2045
2358
|
--content, -c Hydrate results with section content
|
|
2046
2359
|
--db <path> Path to .kbdb directory
|
|
2047
2360
|
|
|
2361
|
+
Scoring:
|
|
2362
|
+
Results are ranked by BM25F. Sections from
|
|
2363
|
+
the same document (shared docid) receive a
|
|
2364
|
+
sibling score boost when multiple sections
|
|
2365
|
+
match the query.
|
|
2366
|
+
|
|
2367
|
+
Fields:
|
|
2368
|
+
Each result includes level (heading depth,
|
|
2369
|
+
1-6 or null) and parent (kbid of enclosing
|
|
2370
|
+
section or null).
|
|
2371
|
+
|
|
2048
2372
|
Output:
|
|
2049
|
-
|
|
2373
|
+
{ items, total, offset } envelope
|
|
2050
2374
|
|
|
2051
2375
|
Examples:
|
|
2052
2376
|
kbdb search "machine learning"
|
|
@@ -2066,7 +2390,8 @@ Options:
|
|
|
2066
2390
|
--db <path> Path to .kbdb directory
|
|
2067
2391
|
|
|
2068
2392
|
Output:
|
|
2069
|
-
JSON RecallResult or RecallResult[]
|
|
2393
|
+
JSON RecallResult or RecallResult[] with
|
|
2394
|
+
level, parent, siblings, and references
|
|
2070
2395
|
|
|
2071
2396
|
Examples:
|
|
2072
2397
|
kbdb recall abcdef1234567890abcdef1234
|
|
@@ -2075,11 +2400,14 @@ Examples:
|
|
|
2075
2400
|
content: `kbdb content - Compose rendered content from ids
|
|
2076
2401
|
|
|
2077
2402
|
Usage: kbdb content [options] <id>...
|
|
2403
|
+
kbdb content --search <query>...
|
|
2078
2404
|
|
|
2079
2405
|
Arguments:
|
|
2080
2406
|
<id> kbid or docid identifier
|
|
2407
|
+
<query> Search terms (with --search)
|
|
2081
2408
|
|
|
2082
2409
|
Options:
|
|
2410
|
+
--search, -s Search for ids by keyword
|
|
2083
2411
|
--db <path> Path to .kbdb directory
|
|
2084
2412
|
|
|
2085
2413
|
Output:
|
|
@@ -2088,6 +2416,7 @@ Output:
|
|
|
2088
2416
|
Examples:
|
|
2089
2417
|
kbdb content abcdef1234567890abcdef1234
|
|
2090
2418
|
kbdb content id1 id2
|
|
2419
|
+
kbdb content --search machine learning
|
|
2091
2420
|
`,
|
|
2092
2421
|
check: `kbdb check - Verify knowledge base integrity
|
|
2093
2422
|
|
|
@@ -2255,16 +2584,20 @@ Examples:
|
|
|
2255
2584
|
`,
|
|
2256
2585
|
"skill-list": `kbdb skill list - List all skills
|
|
2257
2586
|
|
|
2258
|
-
Usage: kbdb skill list [options]
|
|
2587
|
+
Usage: kbdb skill list [options] [keywords...]
|
|
2588
|
+
|
|
2589
|
+
Arguments:
|
|
2590
|
+
[keywords...] Case-insensitive substring filter on name or description
|
|
2259
2591
|
|
|
2260
2592
|
Options:
|
|
2261
2593
|
--db <path> Path to .kbdb directory
|
|
2262
2594
|
|
|
2263
2595
|
Output:
|
|
2264
|
-
JSON
|
|
2596
|
+
JSON { items, total, offset }
|
|
2265
2597
|
|
|
2266
2598
|
Examples:
|
|
2267
2599
|
kbdb skill list
|
|
2600
|
+
kbdb skill list summarize
|
|
2268
2601
|
kbdb skill list --db /path/to/project
|
|
2269
2602
|
`,
|
|
2270
2603
|
"skill-get": `kbdb skill get - Retrieve a skill by name or kbid
|
|
@@ -2320,16 +2653,20 @@ Examples:
|
|
|
2320
2653
|
`,
|
|
2321
2654
|
"agent-list": `kbdb agent list - List all agents
|
|
2322
2655
|
|
|
2323
|
-
Usage: kbdb agent list [options]
|
|
2656
|
+
Usage: kbdb agent list [options] [keywords...]
|
|
2657
|
+
|
|
2658
|
+
Arguments:
|
|
2659
|
+
[keywords...] Case-insensitive substring filter on agent name
|
|
2324
2660
|
|
|
2325
2661
|
Options:
|
|
2326
2662
|
--db <path> Path to .kbdb directory
|
|
2327
2663
|
|
|
2328
2664
|
Output:
|
|
2329
|
-
JSON
|
|
2665
|
+
JSON { items, total, offset }
|
|
2330
2666
|
|
|
2331
2667
|
Examples:
|
|
2332
2668
|
kbdb agent list
|
|
2669
|
+
kbdb agent list reviewer
|
|
2333
2670
|
kbdb agent list --db /path/to/project
|
|
2334
2671
|
`,
|
|
2335
2672
|
"agent-get": `kbdb agent get - Retrieve an agent by docid
|
|
@@ -2468,7 +2805,7 @@ var import_node_net = require("node:net");
|
|
|
2468
2805
|
|
|
2469
2806
|
// src/shared/worker-client/functions/discover-daemon.function.ts
|
|
2470
2807
|
var import_node_fs6 = require("node:fs");
|
|
2471
|
-
var
|
|
2808
|
+
var import_node_path8 = require("node:path");
|
|
2472
2809
|
var import_node_os = require("node:os");
|
|
2473
2810
|
|
|
2474
2811
|
// src/shared/platform/functions/is-process-alive.function.ts
|
|
@@ -2484,7 +2821,7 @@ function isProcessAlive(pid) {
|
|
|
2484
2821
|
// src/shared/worker-client/functions/discover-daemon.function.ts
|
|
2485
2822
|
function discoverDaemon(contextId) {
|
|
2486
2823
|
log("discovering daemon for context: " + contextId, 0 /* DEBUG */);
|
|
2487
|
-
const pidPath = (0,
|
|
2824
|
+
const pidPath = (0, import_node_path8.join)((0, import_node_os.tmpdir)(), `kbdb-${contextId}.pid`);
|
|
2488
2825
|
if (!(0, import_node_fs6.existsSync)(pidPath)) {
|
|
2489
2826
|
log(
|
|
2490
2827
|
"no daemon PID file found for context: " + contextId,
|
|
@@ -2506,8 +2843,8 @@ function discoverDaemon(contextId) {
|
|
|
2506
2843
|
return null;
|
|
2507
2844
|
}
|
|
2508
2845
|
log("daemon found: pid=" + pid.toString(), 0 /* DEBUG */);
|
|
2509
|
-
const socketPath = (0,
|
|
2510
|
-
const crashPath = (0,
|
|
2846
|
+
const socketPath = (0, import_node_path8.join)((0, import_node_os.tmpdir)(), `kbdb-${contextId}.sock`);
|
|
2847
|
+
const crashPath = (0, import_node_path8.join)((0, import_node_os.tmpdir)(), `kbdb-${contextId}.crash`);
|
|
2511
2848
|
try {
|
|
2512
2849
|
(0, import_node_fs6.unlinkSync)(crashPath);
|
|
2513
2850
|
} catch {
|
|
@@ -3028,10 +3365,10 @@ var WorkerClient = class {
|
|
|
3028
3365
|
|
|
3029
3366
|
// src/shared/worker-client/functions/resolve-db-path.function.ts
|
|
3030
3367
|
var import_node_fs7 = require("node:fs");
|
|
3031
|
-
var
|
|
3368
|
+
var import_node_path9 = require("node:path");
|
|
3032
3369
|
function resolveDbPath(targetDir) {
|
|
3033
|
-
const base = targetDir ? (0,
|
|
3034
|
-
const dbPath = (0,
|
|
3370
|
+
const base = targetDir ? (0, import_node_path9.resolve)(targetDir) : process.cwd();
|
|
3371
|
+
const dbPath = (0, import_node_path9.join)(base, ".kbdb");
|
|
3035
3372
|
if (!(0, import_node_fs7.existsSync)(dbPath)) {
|
|
3036
3373
|
const msg = `database not found: ${dbPath}`;
|
|
3037
3374
|
log(msg, 3 /* ERROR */);
|
|
@@ -3098,13 +3435,13 @@ function spawnDaemon(contextPath, runtime, workerScript) {
|
|
|
3098
3435
|
|
|
3099
3436
|
// src/shared/worker-client/functions/wait-for-daemon.function.ts
|
|
3100
3437
|
var import_node_fs8 = require("node:fs");
|
|
3101
|
-
var
|
|
3438
|
+
var import_node_path10 = require("node:path");
|
|
3102
3439
|
var import_node_os2 = require("node:os");
|
|
3103
3440
|
var DEFAULT_TIMEOUT_MS = 1e4;
|
|
3104
3441
|
var POLL_INTERVAL_MS = 100;
|
|
3105
3442
|
async function waitForDaemon(contextId, timeoutMs = DEFAULT_TIMEOUT_MS) {
|
|
3106
3443
|
log("waiting for daemon: contextId=" + contextId, 0 /* DEBUG */);
|
|
3107
|
-
const pidPath = (0,
|
|
3444
|
+
const pidPath = (0, import_node_path10.join)((0, import_node_os2.tmpdir)(), `kbdb-${contextId}.pid`);
|
|
3108
3445
|
const start = Date.now();
|
|
3109
3446
|
let iteration = 0;
|
|
3110
3447
|
while (Date.now() - start < timeoutMs) {
|
|
@@ -3132,10 +3469,10 @@ async function waitForDaemon(contextId, timeoutMs = DEFAULT_TIMEOUT_MS) {
|
|
|
3132
3469
|
|
|
3133
3470
|
// src/shared/worker-client/functions/read-crash-reason.function.ts
|
|
3134
3471
|
var import_node_fs9 = require("node:fs");
|
|
3135
|
-
var
|
|
3472
|
+
var import_node_path11 = require("node:path");
|
|
3136
3473
|
var import_node_os3 = require("node:os");
|
|
3137
3474
|
function readCrashReason(contextId) {
|
|
3138
|
-
const crashPath = (0,
|
|
3475
|
+
const crashPath = (0, import_node_path11.join)((0, import_node_os3.tmpdir)(), `kbdb-${contextId}.crash`);
|
|
3139
3476
|
if (!(0, import_node_fs9.existsSync)(crashPath)) {
|
|
3140
3477
|
return "daemon failed to start (no details available)";
|
|
3141
3478
|
}
|
|
@@ -3150,11 +3487,11 @@ function readCrashReason(contextId) {
|
|
|
3150
3487
|
}
|
|
3151
3488
|
|
|
3152
3489
|
// src/shared/worker-client/functions/resolve-spawn-script.function.ts
|
|
3153
|
-
var
|
|
3490
|
+
var import_node_path13 = require("node:path");
|
|
3154
3491
|
var import_node_url = require("node:url");
|
|
3155
3492
|
|
|
3156
3493
|
// src/shared/dir-resolver/functions/join-path.function.ts
|
|
3157
|
-
var
|
|
3494
|
+
var import_node_path12 = require("node:path");
|
|
3158
3495
|
function isRemoteUrl(path) {
|
|
3159
3496
|
return path.startsWith("http://") || path.startsWith("https://");
|
|
3160
3497
|
}
|
|
@@ -3163,7 +3500,7 @@ function joinPath(base, ...segments) {
|
|
|
3163
3500
|
const trailing = base.endsWith("/") ? "" : "/";
|
|
3164
3501
|
return base + trailing + segments.join("/");
|
|
3165
3502
|
}
|
|
3166
|
-
return (0,
|
|
3503
|
+
return (0, import_node_path12.join)(base, ...segments);
|
|
3167
3504
|
}
|
|
3168
3505
|
|
|
3169
3506
|
// src/shared/dir-resolver/functions/resolve-worker-script.function.ts
|
|
@@ -3181,15 +3518,15 @@ function resolveSpawnScript(runtime) {
|
|
|
3181
3518
|
}
|
|
3182
3519
|
function resolveScriptDir2(runtime) {
|
|
3183
3520
|
if (typeof __dirname !== "undefined") return __dirname;
|
|
3184
|
-
const thisDir = (0,
|
|
3521
|
+
const thisDir = (0, import_node_path13.dirname)((0, import_node_url.fileURLToPath)(import_meta.url));
|
|
3185
3522
|
if (runtime === "deno") {
|
|
3186
|
-
return (0,
|
|
3523
|
+
return (0, import_node_path13.resolve)(thisDir, "..", "..", "..");
|
|
3187
3524
|
}
|
|
3188
3525
|
return thisDir;
|
|
3189
3526
|
}
|
|
3190
3527
|
|
|
3191
3528
|
// src/shared/platform/functions/get-ipc-path.function.ts
|
|
3192
|
-
var
|
|
3529
|
+
var import_node_path14 = require("node:path");
|
|
3193
3530
|
|
|
3194
3531
|
// src/shared/platform/functions/get-tmpdir.function.ts
|
|
3195
3532
|
var import_node_os4 = require("node:os");
|
|
@@ -3202,7 +3539,7 @@ function getIpcPath(ctx) {
|
|
|
3202
3539
|
if (process.platform === "win32") {
|
|
3203
3540
|
return `\\\\.\\pipe\\kbdb-${ctx}`;
|
|
3204
3541
|
}
|
|
3205
|
-
return (0,
|
|
3542
|
+
return (0, import_node_path14.join)(getTmpdir(), `kbdb-${ctx}.sock`);
|
|
3206
3543
|
}
|
|
3207
3544
|
|
|
3208
3545
|
// src/shared/worker-client/functions/create-worker-client.function.ts
|
|
@@ -3670,7 +4007,7 @@ function createToolDefinitions() {
|
|
|
3670
4007
|
return [
|
|
3671
4008
|
{
|
|
3672
4009
|
name: "search",
|
|
3673
|
-
description: "Query the knowledge base by keywords. Returns ranked results with heading, snippet,
|
|
4010
|
+
description: "Query the knowledge base by keywords. Returns ranked results with heading, snippet, matched terms, level, and parent. Sections from the same document receive a sibling score boost when multiple sections match. Use multiple short keyword queries for best coverage. Use recall for full content.",
|
|
3674
4011
|
inputSchema: {
|
|
3675
4012
|
type: "object",
|
|
3676
4013
|
properties: {
|
|
@@ -3713,7 +4050,7 @@ function createToolDefinitions() {
|
|
|
3713
4050
|
},
|
|
3714
4051
|
{
|
|
3715
4052
|
name: "learn",
|
|
3716
|
-
description: "Import content into the knowledge base.
|
|
4053
|
+
description: "Import content into the knowledge base. Structured content (Markdown, HTML, TOML) is automatically split into sections that share a docid. Each section carries a level (heading depth) and parent reference. Providing title imports as a single section (skips splitting). Use replace when updating existing knowledge. Attach tags for scoping.",
|
|
3717
4054
|
inputSchema: {
|
|
3718
4055
|
type: "object",
|
|
3719
4056
|
properties: {
|
|
@@ -3723,11 +4060,11 @@ function createToolDefinitions() {
|
|
|
3723
4060
|
},
|
|
3724
4061
|
type: {
|
|
3725
4062
|
type: "string",
|
|
3726
|
-
description: "MIME type
|
|
4063
|
+
description: "MIME type or format hint. Supported: text/markdown, text/html, application/toml (also text/toml, text/x-toml), text/plain, image/*. Default: text/markdown."
|
|
3727
4064
|
},
|
|
3728
4065
|
title: {
|
|
3729
4066
|
type: "string",
|
|
3730
|
-
description: "Section title. Required for image/* types."
|
|
4067
|
+
description: "Section title. Skips content splitting when set. Required for image/* types."
|
|
3731
4068
|
},
|
|
3732
4069
|
description: {
|
|
3733
4070
|
type: "string",
|
|
@@ -3735,7 +4072,7 @@ function createToolDefinitions() {
|
|
|
3735
4072
|
},
|
|
3736
4073
|
docid: {
|
|
3737
4074
|
type: "string",
|
|
3738
|
-
description: "Document ID to group under"
|
|
4075
|
+
description: "Document ID to group sections under. Set automatically when content splitting is active."
|
|
3739
4076
|
},
|
|
3740
4077
|
tags: {
|
|
3741
4078
|
type: "array",
|
|
@@ -3804,7 +4141,7 @@ function createToolDefinitions() {
|
|
|
3804
4141
|
},
|
|
3805
4142
|
{
|
|
3806
4143
|
name: "recall",
|
|
3807
|
-
description: "Retrieve full content and context for sections by identifier. Use after search to read relevant results. Returns section text, metadata, references, and back-references.",
|
|
4144
|
+
description: "Retrieve full content and context for sections by identifier. Use after search to read relevant results. Returns section text, level, parent, metadata, references, and back-references.",
|
|
3808
4145
|
inputSchema: {
|
|
3809
4146
|
type: "object",
|
|
3810
4147
|
properties: {
|
|
@@ -3935,7 +4272,7 @@ function createToolDefinitions() {
|
|
|
3935
4272
|
},
|
|
3936
4273
|
{
|
|
3937
4274
|
name: "skill-learn",
|
|
3938
|
-
description: "Create or update a skill definition. Skills are reusable AI agent capabilities with template placeholders.",
|
|
4275
|
+
description: "Create or update a skill definition. Skills are reusable AI agent capabilities with template placeholders. Stored as atomic JSON (not split into sections).",
|
|
3939
4276
|
inputSchema: {
|
|
3940
4277
|
type: "object",
|
|
3941
4278
|
properties: {
|
|
@@ -3964,10 +4301,15 @@ function createToolDefinitions() {
|
|
|
3964
4301
|
},
|
|
3965
4302
|
{
|
|
3966
4303
|
name: "skill-list",
|
|
3967
|
-
description: "List
|
|
4304
|
+
description: "List skill definitions stored in the knowledge base, optionally filtered by a substring query.",
|
|
3968
4305
|
inputSchema: {
|
|
3969
4306
|
type: "object",
|
|
3970
|
-
properties: {
|
|
4307
|
+
properties: {
|
|
4308
|
+
query: {
|
|
4309
|
+
type: "string",
|
|
4310
|
+
description: "Case-insensitive substring filter on skill name or description."
|
|
4311
|
+
}
|
|
4312
|
+
}
|
|
3971
4313
|
},
|
|
3972
4314
|
annotations: {
|
|
3973
4315
|
title: "List Skills",
|
|
@@ -4024,7 +4366,7 @@ function createToolDefinitions() {
|
|
|
4024
4366
|
},
|
|
4025
4367
|
{
|
|
4026
4368
|
name: "agent-create",
|
|
4027
|
-
description: "Create an AI agent with a persona and optional skill references.",
|
|
4369
|
+
description: "Create an AI agent with a persona and optional skill references. Stored as atomic JSON (not split into sections).",
|
|
4028
4370
|
inputSchema: {
|
|
4029
4371
|
type: "object",
|
|
4030
4372
|
properties: {
|
|
@@ -4058,10 +4400,15 @@ function createToolDefinitions() {
|
|
|
4058
4400
|
},
|
|
4059
4401
|
{
|
|
4060
4402
|
name: "agent-list",
|
|
4061
|
-
description: "List
|
|
4403
|
+
description: "List agent documents in the knowledge base, optionally filtered by a substring query.",
|
|
4062
4404
|
inputSchema: {
|
|
4063
4405
|
type: "object",
|
|
4064
|
-
properties: {
|
|
4406
|
+
properties: {
|
|
4407
|
+
query: {
|
|
4408
|
+
type: "string",
|
|
4409
|
+
description: "Case-insensitive substring filter on agent name or description."
|
|
4410
|
+
}
|
|
4411
|
+
}
|
|
4065
4412
|
},
|
|
4066
4413
|
annotations: {
|
|
4067
4414
|
title: "List Agents",
|
|
@@ -4180,7 +4527,7 @@ function createToolDefinitions() {
|
|
|
4180
4527
|
title: "Auto-Capture Review",
|
|
4181
4528
|
readOnlyHint: false,
|
|
4182
4529
|
destructiveHint: false,
|
|
4183
|
-
idempotentHint:
|
|
4530
|
+
idempotentHint: false,
|
|
4184
4531
|
openWorldHint: false
|
|
4185
4532
|
}
|
|
4186
4533
|
}
|
|
@@ -4309,7 +4656,7 @@ async function readAgentDescription(client, sections) {
|
|
|
4309
4656
|
return "";
|
|
4310
4657
|
}
|
|
4311
4658
|
}
|
|
4312
|
-
async function handleAgentList(client) {
|
|
4659
|
+
async function handleAgentList(client, args = {}) {
|
|
4313
4660
|
const docs = await client.listDocumentsByType("agent");
|
|
4314
4661
|
const items = await Promise.all(
|
|
4315
4662
|
docs.map(async (d) => ({
|
|
@@ -4317,17 +4664,17 @@ async function handleAgentList(client) {
|
|
|
4317
4664
|
description: await readAgentDescription(client, d.sections)
|
|
4318
4665
|
}))
|
|
4319
4666
|
);
|
|
4320
|
-
const
|
|
4321
|
-
|
|
4322
|
-
|
|
4323
|
-
const text = [`${String(items.length)} agents:`, ...lines].join(
|
|
4324
|
-
"\n"
|
|
4667
|
+
const query = typeof args["query"] === "string" ? args["query"].toLowerCase() : "";
|
|
4668
|
+
const filtered = items.filter(
|
|
4669
|
+
(item) => matchesQuery(query, item.name, item.description)
|
|
4325
4670
|
);
|
|
4671
|
+
const names = filtered.map((item) => item.name);
|
|
4672
|
+
const data = { items: names, total: names.length, offset: 0 };
|
|
4326
4673
|
return {
|
|
4327
4674
|
content: [
|
|
4328
4675
|
{
|
|
4329
4676
|
type: "text",
|
|
4330
|
-
text
|
|
4677
|
+
text: JSON.stringify(data, null, 2)
|
|
4331
4678
|
}
|
|
4332
4679
|
]
|
|
4333
4680
|
};
|
|
@@ -4569,25 +4916,38 @@ async function handleAgentSearch(client, args) {
|
|
|
4569
4916
|
return { content: [{ type: "text", text }] };
|
|
4570
4917
|
}
|
|
4571
4918
|
|
|
4572
|
-
// src/shared/mcp/functions/
|
|
4919
|
+
// src/shared/mcp/functions/as-string.function.ts
|
|
4573
4920
|
function asString2(value, fallback) {
|
|
4574
4921
|
return typeof value === "string" ? value : fallback;
|
|
4575
4922
|
}
|
|
4576
|
-
|
|
4577
|
-
|
|
4578
|
-
}
|
|
4923
|
+
|
|
4924
|
+
// src/shared/mcp/functions/as-string-array-or-undefined.function.ts
|
|
4579
4925
|
function asStringArrayOrUndefined(value) {
|
|
4580
4926
|
if (Array.isArray(value) && value.every((item) => typeof item === "string")) {
|
|
4581
4927
|
return value;
|
|
4582
4928
|
}
|
|
4583
4929
|
return void 0;
|
|
4584
4930
|
}
|
|
4585
|
-
|
|
4586
|
-
|
|
4587
|
-
|
|
4588
|
-
|
|
4589
|
-
return [];
|
|
4931
|
+
|
|
4932
|
+
// src/shared/mcp/functions/as-boolean-or-undefined.function.ts
|
|
4933
|
+
function asBooleanOrUndefined(value) {
|
|
4934
|
+
return typeof value === "boolean" ? value : void 0;
|
|
4590
4935
|
}
|
|
4936
|
+
|
|
4937
|
+
// src/shared/mcp/functions/parse-learn-args.function.ts
|
|
4938
|
+
function parseLearnArgs(args) {
|
|
4939
|
+
return {
|
|
4940
|
+
sectionType: asString2(args["type"], "text/markdown"),
|
|
4941
|
+
title: typeof args["title"] === "string" ? args["title"] : void 0,
|
|
4942
|
+
description: typeof args["description"] === "string" ? args["description"] : void 0,
|
|
4943
|
+
docid: typeof args["docid"] === "string" ? args["docid"] : void 0,
|
|
4944
|
+
tags: asStringArrayOrUndefined(args["tags"]),
|
|
4945
|
+
replace: asBooleanOrUndefined(args["replace"]),
|
|
4946
|
+
level: typeof args["level"] === "number" ? args["level"] : void 0
|
|
4947
|
+
};
|
|
4948
|
+
}
|
|
4949
|
+
|
|
4950
|
+
// src/shared/mcp/functions/unwrap-json-content.function.ts
|
|
4591
4951
|
function unwrapJsonContent(raw) {
|
|
4592
4952
|
const trimmed = raw.trim();
|
|
4593
4953
|
if (!trimmed.startsWith("{")) return raw;
|
|
@@ -4600,6 +4960,158 @@ function unwrapJsonContent(raw) {
|
|
|
4600
4960
|
}
|
|
4601
4961
|
return raw;
|
|
4602
4962
|
}
|
|
4963
|
+
|
|
4964
|
+
// src/shared/mcp/functions/determine-learn-split.function.ts
|
|
4965
|
+
function determineLearnSplit(content, sectionType, title) {
|
|
4966
|
+
const splittable = sectionType.startsWith("text/") || sectionType === "markdown" || sectionType === "application/toml";
|
|
4967
|
+
if (title !== void 0 || !splittable) return void 0;
|
|
4968
|
+
const result = splitContent(content, sectionType);
|
|
4969
|
+
const hasTitledSection = result.sections.some(
|
|
4970
|
+
(section) => section.title !== void 0
|
|
4971
|
+
);
|
|
4972
|
+
return result.sections.length >= 2 && hasTitledSection ? result : void 0;
|
|
4973
|
+
}
|
|
4974
|
+
|
|
4975
|
+
// src/shared/mcp/functions/learn-with-splitting.function.ts
|
|
4976
|
+
async function learnWithSplitting(client, splitResult, params) {
|
|
4977
|
+
const { sections } = splitResult;
|
|
4978
|
+
const firstTitled = sections.find((s) => s.title !== void 0);
|
|
4979
|
+
const docTitle = firstTitled?.title ?? params.docid ?? "Untitled";
|
|
4980
|
+
const docid = params.docid ?? firstTitled?.title;
|
|
4981
|
+
const kbids = [];
|
|
4982
|
+
for (const section of sections) {
|
|
4983
|
+
const [parent] = resolveParentIds([section], kbids);
|
|
4984
|
+
const result = await client.addSection({
|
|
4985
|
+
sectionType: params.sectionType,
|
|
4986
|
+
content: section.content,
|
|
4987
|
+
title: section.title,
|
|
4988
|
+
description: params.description,
|
|
4989
|
+
docid,
|
|
4990
|
+
tags: params.tags,
|
|
4991
|
+
replace: params.replace,
|
|
4992
|
+
level: section.level,
|
|
4993
|
+
parent: parent ?? void 0
|
|
4994
|
+
});
|
|
4995
|
+
kbids.push(result.items[0] ?? "");
|
|
4996
|
+
}
|
|
4997
|
+
return { kbids, docTitle };
|
|
4998
|
+
}
|
|
4999
|
+
|
|
5000
|
+
// src/shared/mcp/functions/store-split-learn-sections.function.ts
|
|
5001
|
+
async function storeSplitLearnSections(client, splitResult, params) {
|
|
5002
|
+
const { kbids, docTitle } = await learnWithSplitting(
|
|
5003
|
+
client,
|
|
5004
|
+
splitResult,
|
|
5005
|
+
params
|
|
5006
|
+
);
|
|
5007
|
+
await client.groupSections(docTitle, kbids);
|
|
5008
|
+
return {
|
|
5009
|
+
items: kbids,
|
|
5010
|
+
total: kbids.length,
|
|
5011
|
+
offset: 0,
|
|
5012
|
+
superseded: null,
|
|
5013
|
+
warnings: [],
|
|
5014
|
+
near_duplicates: []
|
|
5015
|
+
};
|
|
5016
|
+
}
|
|
5017
|
+
|
|
5018
|
+
// src/shared/mcp/functions/build-learn-payload.function.ts
|
|
5019
|
+
function buildLearnPayload(result) {
|
|
5020
|
+
return {
|
|
5021
|
+
items: result.items,
|
|
5022
|
+
total: result.total,
|
|
5023
|
+
offset: result.offset,
|
|
5024
|
+
superseded: result.superseded ?? null,
|
|
5025
|
+
warnings: result.warnings ?? [],
|
|
5026
|
+
near_duplicates: result.near_duplicates ?? []
|
|
5027
|
+
};
|
|
5028
|
+
}
|
|
5029
|
+
|
|
5030
|
+
// src/shared/mcp/functions/handle-tool-learn.function.ts
|
|
5031
|
+
async function handleToolLearn(client, args) {
|
|
5032
|
+
const learnArgs = parseLearnArgs(args);
|
|
5033
|
+
const { sectionType, title, level, ...shared } = learnArgs;
|
|
5034
|
+
if (sectionType.startsWith("image/") && !title) {
|
|
5035
|
+
return {
|
|
5036
|
+
content: [
|
|
5037
|
+
{
|
|
5038
|
+
type: "text",
|
|
5039
|
+
text: "title is required for image/* types"
|
|
5040
|
+
}
|
|
5041
|
+
],
|
|
5042
|
+
isError: true
|
|
5043
|
+
};
|
|
5044
|
+
}
|
|
5045
|
+
const content = unwrapJsonContent(asString2(args["content"], ""));
|
|
5046
|
+
const splitResult = determineLearnSplit(content, sectionType, title);
|
|
5047
|
+
const result = splitResult ? await storeSplitLearnSections(client, splitResult, {
|
|
5048
|
+
sectionType,
|
|
5049
|
+
...shared
|
|
5050
|
+
}) : await client.addSection({
|
|
5051
|
+
sectionType,
|
|
5052
|
+
content,
|
|
5053
|
+
title,
|
|
5054
|
+
level,
|
|
5055
|
+
...shared
|
|
5056
|
+
});
|
|
5057
|
+
return {
|
|
5058
|
+
content: [
|
|
5059
|
+
{
|
|
5060
|
+
type: "text",
|
|
5061
|
+
text: JSON.stringify(buildLearnPayload(result))
|
|
5062
|
+
}
|
|
5063
|
+
]
|
|
5064
|
+
};
|
|
5065
|
+
}
|
|
5066
|
+
|
|
5067
|
+
// src/shared/mcp/functions/handle-tool-skill-learn.function.ts
|
|
5068
|
+
async function handleToolSkillLearn(client, args) {
|
|
5069
|
+
const name = asString2(args["name"], "");
|
|
5070
|
+
if (!name) {
|
|
5071
|
+
return {
|
|
5072
|
+
content: [{ type: "text", text: "name is required" }],
|
|
5073
|
+
isError: true
|
|
5074
|
+
};
|
|
5075
|
+
}
|
|
5076
|
+
const body = asString2(args["body"], "");
|
|
5077
|
+
if (!body) {
|
|
5078
|
+
return {
|
|
5079
|
+
content: [{ type: "text", text: "body is required" }],
|
|
5080
|
+
isError: true
|
|
5081
|
+
};
|
|
5082
|
+
}
|
|
5083
|
+
const description = typeof args["description"] === "string" ? args["description"] : void 0;
|
|
5084
|
+
const skillArgs = extractSkillArguments(body);
|
|
5085
|
+
const skill = {
|
|
5086
|
+
name,
|
|
5087
|
+
description,
|
|
5088
|
+
arguments: skillArgs.length > 0 ? skillArgs : void 0,
|
|
5089
|
+
body
|
|
5090
|
+
};
|
|
5091
|
+
const json = serializeSkillContent(skill);
|
|
5092
|
+
const result = await client.addSection({
|
|
5093
|
+
sectionType: "skill",
|
|
5094
|
+
content: json,
|
|
5095
|
+
title: name,
|
|
5096
|
+
description
|
|
5097
|
+
});
|
|
5098
|
+
return {
|
|
5099
|
+
content: [
|
|
5100
|
+
{
|
|
5101
|
+
type: "text",
|
|
5102
|
+
text: `Created skill "${name}" (kbid: ${result.items[0]})`
|
|
5103
|
+
}
|
|
5104
|
+
]
|
|
5105
|
+
};
|
|
5106
|
+
}
|
|
5107
|
+
|
|
5108
|
+
// src/shared/mcp/functions/handle-tool-call.function.ts
|
|
5109
|
+
function asStringArray2(value) {
|
|
5110
|
+
if (Array.isArray(value) && value.every((item) => typeof item === "string")) {
|
|
5111
|
+
return value;
|
|
5112
|
+
}
|
|
5113
|
+
return [];
|
|
5114
|
+
}
|
|
4603
5115
|
async function handleToolCall(client, name, args) {
|
|
4604
5116
|
log("tool call: " + name, 0 /* DEBUG */);
|
|
4605
5117
|
try {
|
|
@@ -4607,7 +5119,7 @@ async function handleToolCall(client, name, args) {
|
|
|
4607
5119
|
case "search":
|
|
4608
5120
|
return await handleSearch2(client, args);
|
|
4609
5121
|
case "learn":
|
|
4610
|
-
return await
|
|
5122
|
+
return await handleToolLearn(client, args);
|
|
4611
5123
|
case "unlearn":
|
|
4612
5124
|
return await handleUnlearn2(client, args);
|
|
4613
5125
|
case "retrieve":
|
|
@@ -4627,9 +5139,9 @@ async function handleToolCall(client, name, args) {
|
|
|
4627
5139
|
case "export":
|
|
4628
5140
|
return await handleExport2(client, args);
|
|
4629
5141
|
case "skill-learn":
|
|
4630
|
-
return await
|
|
5142
|
+
return await handleToolSkillLearn(client, args);
|
|
4631
5143
|
case "skill-list":
|
|
4632
|
-
return await handleSkillList(client);
|
|
5144
|
+
return await handleSkillList(client, args);
|
|
4633
5145
|
case "skill-get":
|
|
4634
5146
|
return await handleSkillGet(client, args);
|
|
4635
5147
|
case "skill-delete":
|
|
@@ -4637,7 +5149,7 @@ async function handleToolCall(client, name, args) {
|
|
|
4637
5149
|
case "agent-create":
|
|
4638
5150
|
return await handleAgentCreate(client, args);
|
|
4639
5151
|
case "agent-list":
|
|
4640
|
-
return await handleAgentList(client);
|
|
5152
|
+
return await handleAgentList(client, args);
|
|
4641
5153
|
case "agent-get":
|
|
4642
5154
|
return await handleAgentGet(client, args);
|
|
4643
5155
|
case "agent-delete":
|
|
@@ -4692,47 +5204,6 @@ async function handleSearch2(client, args) {
|
|
|
4692
5204
|
]
|
|
4693
5205
|
};
|
|
4694
5206
|
}
|
|
4695
|
-
async function handleLearn2(client, args) {
|
|
4696
|
-
const sectionType = asString2(args["type"], "text/markdown");
|
|
4697
|
-
const title = typeof args["title"] === "string" ? args["title"] : void 0;
|
|
4698
|
-
const description = typeof args["description"] === "string" ? args["description"] : void 0;
|
|
4699
|
-
const docid = typeof args["docid"] === "string" ? args["docid"] : void 0;
|
|
4700
|
-
const tags = asStringArrayOrUndefined(args["tags"]);
|
|
4701
|
-
const replace = asBooleanOrUndefined(args["replace"]);
|
|
4702
|
-
if (sectionType.startsWith("image/") && !title) {
|
|
4703
|
-
return {
|
|
4704
|
-
content: [
|
|
4705
|
-
{
|
|
4706
|
-
type: "text",
|
|
4707
|
-
text: "title is required for image/* types"
|
|
4708
|
-
}
|
|
4709
|
-
],
|
|
4710
|
-
isError: true
|
|
4711
|
-
};
|
|
4712
|
-
}
|
|
4713
|
-
const rawContent = asString2(args["content"], "");
|
|
4714
|
-
const content = unwrapJsonContent(rawContent);
|
|
4715
|
-
const result = await client.addSection({
|
|
4716
|
-
sectionType,
|
|
4717
|
-
content,
|
|
4718
|
-
title,
|
|
4719
|
-
description,
|
|
4720
|
-
docid,
|
|
4721
|
-
tags,
|
|
4722
|
-
replace
|
|
4723
|
-
});
|
|
4724
|
-
const payload = {
|
|
4725
|
-
items: result.items,
|
|
4726
|
-
total: result.total,
|
|
4727
|
-
offset: result.offset,
|
|
4728
|
-
superseded: result.superseded ?? null,
|
|
4729
|
-
warnings: result.warnings ?? [],
|
|
4730
|
-
near_duplicates: result.near_duplicates ?? []
|
|
4731
|
-
};
|
|
4732
|
-
return {
|
|
4733
|
-
content: [{ type: "text", text: JSON.stringify(payload) }]
|
|
4734
|
-
};
|
|
4735
|
-
}
|
|
4736
5207
|
async function handleUnlearn2(client, args) {
|
|
4737
5208
|
const kbid = asString2(args["kbid"], "");
|
|
4738
5209
|
await client.removeSection(kbid);
|
|
@@ -4839,56 +5310,17 @@ async function handleRebuild2(client) {
|
|
|
4839
5310
|
const text = `Rebuild complete: ${String(report.sections_reindexed)} sections reindexed, ${String(report.terms_indexed)} terms indexed.`;
|
|
4840
5311
|
return { content: [{ type: "text", text }] };
|
|
4841
5312
|
}
|
|
4842
|
-
async function
|
|
4843
|
-
const name = asString2(args["name"], "");
|
|
4844
|
-
if (!name) {
|
|
4845
|
-
return {
|
|
4846
|
-
content: [{ type: "text", text: "name is required" }],
|
|
4847
|
-
isError: true
|
|
4848
|
-
};
|
|
4849
|
-
}
|
|
4850
|
-
const body = asString2(args["body"], "");
|
|
4851
|
-
if (!body) {
|
|
4852
|
-
return {
|
|
4853
|
-
content: [{ type: "text", text: "body is required" }],
|
|
4854
|
-
isError: true
|
|
4855
|
-
};
|
|
4856
|
-
}
|
|
4857
|
-
const description = typeof args["description"] === "string" ? args["description"] : void 0;
|
|
4858
|
-
const skillArgs = extractSkillArguments(body);
|
|
4859
|
-
const skill = {
|
|
4860
|
-
name,
|
|
4861
|
-
description,
|
|
4862
|
-
arguments: skillArgs.length > 0 ? skillArgs : void 0,
|
|
4863
|
-
body
|
|
4864
|
-
};
|
|
4865
|
-
const json = serializeSkillContent(skill);
|
|
4866
|
-
const result = await client.addSection({
|
|
4867
|
-
sectionType: "skill",
|
|
4868
|
-
content: json,
|
|
4869
|
-
title: name,
|
|
4870
|
-
description
|
|
4871
|
-
});
|
|
4872
|
-
return {
|
|
4873
|
-
content: [
|
|
4874
|
-
{
|
|
4875
|
-
type: "text",
|
|
4876
|
-
text: `Created skill "${name}" (kbid: ${result.items[0]})`
|
|
4877
|
-
}
|
|
4878
|
-
]
|
|
4879
|
-
};
|
|
4880
|
-
}
|
|
4881
|
-
async function handleSkillList(client) {
|
|
5313
|
+
async function handleSkillList(client, args) {
|
|
4882
5314
|
const records = await client.listByType("skill");
|
|
4883
|
-
const
|
|
4884
|
-
|
|
4885
|
-
|
|
4886
|
-
return `${String(index + 1)}. ${label} (${r.kbid})${desc}`;
|
|
4887
|
-
});
|
|
4888
|
-
const text = [`${String(records.length)} skills:`, ...lines].join(
|
|
4889
|
-
"\n"
|
|
5315
|
+
const query = typeof args["query"] === "string" ? args["query"].toLowerCase() : "";
|
|
5316
|
+
const filtered = records.filter(
|
|
5317
|
+
(r) => matchesQuery(query, r.title, r.description)
|
|
4890
5318
|
);
|
|
4891
|
-
|
|
5319
|
+
const names = filtered.map((r) => r.title ?? "");
|
|
5320
|
+
const data = { items: names, total: names.length, offset: 0 };
|
|
5321
|
+
return {
|
|
5322
|
+
content: [{ type: "text", text: JSON.stringify(data, null, 2) }]
|
|
5323
|
+
};
|
|
4892
5324
|
}
|
|
4893
5325
|
async function handleSkillGet(client, args) {
|
|
4894
5326
|
const kbid = typeof args["kbid"] === "string" ? args["kbid"] : void 0;
|
|
@@ -5924,7 +6356,7 @@ var deps = {
|
|
|
5924
6356
|
log("starting MCP server", 1 /* INFO */);
|
|
5925
6357
|
const client = await createWorkerClient({ contextPath });
|
|
5926
6358
|
try {
|
|
5927
|
-
const tomlPath = (0,
|
|
6359
|
+
const tomlPath = (0, import_node_path15.join)(contextPath, "worker.toml");
|
|
5928
6360
|
let autoCaptureConfig;
|
|
5929
6361
|
try {
|
|
5930
6362
|
const tomlText = (0, import_node_fs10.readFileSync)(tomlPath, "utf-8");
|